Advertisement
Guest User

Untitled

a guest
Feb 4th, 2014
357
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 13.13 KB | None | 0 0
  1. #define F_CPU 14745600
  2. #define BAUD_PRESCALE 23
  3.  
  4. #define DAY_IN_SECONDS 86400L
  5. #define I_LAYER_COUNT 17
  6. #define J_LAYER_COUNT 16
  7. #define WEIGHT_RESOLUTION 32.0F
  8. #define BASE_ETA 0.01 * WEIGHT_RESOLUTION
  9. #define FORECAST_PERIOD 1800
  10. #define TRAINING_PERIODS 3
  11.  
  12. #include <stdio.h>
  13. #include <stdbool.h>
  14. #include <stdlib.h>
  15. #include <math.h>
  16. #include <avr/io.h>
  17. #include <avr/interrupt.h>
  18. #include <avr/wdt.h>
  19. #include <util/delay.h>
  20. #include "wti_serial.h"
  21. #include "wti_ringbuffer.h"
  22. #include "wti_switch.h"
  23.  
  24. typedef enum {SUCCESS, CRC_MISMATCH} network_restore_status;
  25.  
  26. void initializeHardware();
  27. void initializeNeuralNetwork();
  28. int8_t randInt8();
  29. float sig(float);
  30. void calculateSensorValues(float *sensors, int32_t theTime, int32_t lastCoffeeTime);
  31. void calculateHiddenLayerValues(float *hiddenNodes, float *sensors);
  32. void calculateOutput(float *output, float *hiddenNodes);
  33. float forecast(int32_t theTime, int32_t lastCoffeeTime);
  34. void train(float target, int32_t theTime, int32_t lastCoffeeTime, float eta);
  35. void randAdd(int8_t *integer, float flt);
  36. void lightLights(float forecast);
  37. void eeWrite(uint16_t*, uint8_t);
  38. uint8_t eeRead(uint16_t*);
  39. void backupNetwork();
  40. network_restore_status restoreNetwork();
  41.  
  42. static FILE serialStdout = FDEV_SETUP_STREAM(serialWrite, NULL, _FDEV_SETUP_WRITE);
  43.  
  44. volatile int32_t timerCounter;
  45. volatile int16_t forecastTimer = 10;
  46. volatile int16_t trainingTimer = 60;
  47. volatile int16_t backupTimer = 7237;
  48.  
  49. // Network Data
  50. int8_t ijMatrix[I_LAYER_COUNT][J_LAYER_COUNT];
  51. int8_t jkMatrix[J_LAYER_COUNT];
  52. int8_t jBias[J_LAYER_COUNT];
  53. int8_t kBias;
  54.  
  55. int main(void) {  
  56.   // Training Data
  57.   int32_t tLastCoffeeTimes[TRAINING_PERIODS] = {0};
  58.   int32_t tTheTimes[TRAINING_PERIODS] = {0};
  59.   int32_t lastCoffeeTime = 0;
  60.   float tTargets[TRAINING_PERIODS] = {0.1};
  61.   float eta;  
  62.  
  63.   initializeHardware();    
  64.  
  65.   _delay_ms(1000);
  66.   printf("7");  
  67.   _delay_ms(1000);
  68.   printf("6");  
  69.   _delay_ms(1000);
  70.   printf("5");  
  71.   _delay_ms(1000);
  72.   printf("4");  
  73.   _delay_ms(1000);
  74.   printf("3");  
  75.   _delay_ms(1000);
  76.   printf("2");  
  77.   _delay_ms(1000);
  78.   printf("1");  
  79.   _delay_ms(1000);
  80.   printf("0\n");
  81.   if (restoreNetwork() != SUCCESS) {
  82.     _delay_ms(3000);
  83.     initializeNeuralNetwork();
  84.     backupNetwork();
  85.   }
  86.  
  87.   while(1) {    
  88.     wdt_reset();
  89.     if ((PINC & (1<<PINC0)) == 0) {
  90.       for (uint8_t k = 0; k < TRAINING_PERIODS; k++) {
  91.         tTargets[k] = 0.9;
  92.       }
  93.      
  94.       lastCoffeeTime = timerCounter;
  95.       printf("Button Press.\n");
  96.     }
  97.    
  98.     if (trainingTimer == 0) {
  99.       trainingTimer = FORECAST_PERIOD / TRAINING_PERIODS;
  100.  
  101.       eta = BASE_ETA + 0.4 * WEIGHT_RESOLUTION * exp(-(double)timerCounter/(DAY_IN_SECONDS * 2));      
  102.       train(tTargets[0], tTheTimes[0], tLastCoffeeTimes[0], eta);
  103.      
  104.       for (uint8_t k = 1; k < TRAINING_PERIODS; k++) {        
  105.         tTargets[k - 1] = tTargets[k];
  106.         tTheTimes[k - 1] = tTheTimes[k];
  107.         tLastCoffeeTimes[k - 1] = tLastCoffeeTimes[k];
  108.       }
  109.      
  110.       tTargets[TRAINING_PERIODS - 1] = 0.1;
  111.       tTheTimes[TRAINING_PERIODS - 1] = timerCounter;
  112.       tLastCoffeeTimes[TRAINING_PERIODS - 1] = lastCoffeeTime;  
  113.      
  114.       printf("\nijMatrix:\n");
  115.       for (uint8_t i = 0; i < I_LAYER_COUNT; i++) {
  116.         for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  117.           printf("%i, ", ijMatrix[i][j]);
  118.         }
  119.         printf("\n");
  120.       }  
  121.      
  122.       printf("\njBiases:\n");
  123.       for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  124.         printf("%i, ", jBias[j]);
  125.       }
  126.       printf("\n");
  127.      
  128.       printf("\njkMatrix:\n");      
  129.       for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  130.         printf("%i, ", jkMatrix[j]);
  131.       }
  132.       printf("\n\nkBias: %i\n\n", kBias);      
  133.     }
  134.    
  135.     if (forecastTimer == 0) {
  136.       float currentForecast = forecast(timerCounter, lastCoffeeTime);            
  137.       forecastTimer = 30;
  138.       printf("Current forecast: %f at %li, %li\n", currentForecast, (timerCounter % 86400), (lastCoffeeTime % 86400));
  139.       lightLights(currentForecast);
  140.     }
  141.  
  142.     if (backupTimer == 0) {
  143.       backupTimer = 7200;
  144.       backupNetwork();
  145.     }
  146.    
  147.     _delay_ms(100);
  148.   }          
  149. }
  150.  
  151. void initializeHardware() {
  152.   cli();
  153.   stdout = &serialStdout;
  154.  
  155.   //Initialize USART, its buffer and TWI
  156.   usartInit(BAUD_PRESCALE);
  157.   rbInit(&serialTxBuffer);
  158.  
  159.   // turn off Timer/Counter2, Timer/Counter0, Serial Peripheral Interface, ADC
  160.   PRR = (1<<PRTIM2) | (1<<PRTIM0) | (1<<PRSPI) | (1<<PRADC);
  161.  
  162.   MCUSR &= ~(1<<WDRF); //Disable System Reset Flag in MCU Status Register
  163.   wdt_reset(); //C.f. doc note on page 53.
  164.   //"The Watchdog Timer should be reset before any change of the WDP bits"
  165.   WDTCSR = (1<<WDCE) | (1<<WDE); //Write logic one to WDCE and WDE bits of WDTCSR simultaneously
  166.   //to begin wd config procedure
  167.   WDTCSR = (1<<WDP3) | (1<<WDP0);  //  Set WD prescaler for 8.0 seconds
  168.  
  169.   OCR1A  = 0x3840; // Compare match at 1.00 seconds
  170.   TCCR1B = (1<<CS12) | (1<<CS10);
  171.   TIMSK1 = (1<<OCIE1A) | (1<<TOIE1);
  172.  
  173.   PORTC = (1<<PORTC0) | (1<<PORTC1) | (1<<PORTC2) | (1<<PORTC3);
  174.   DDRC = (1<<PORTC1) | (1<<PORTC2) | (1<<PORTC3);
  175.  
  176.   // Set up EEPROM
  177.   EECR = 0x00; // Mode = atomic, Interrupt = disabled
  178.   sei();
  179. }
  180.  
  181. void initializeNeuralNetwork() {
  182.   srandom(252);  
  183.    
  184.   for (int j = 0; j < J_LAYER_COUNT; j++) {
  185.     for (int i = 0; i < I_LAYER_COUNT; i++) {
  186.       ijMatrix[i][j] = randInt8() / 4;
  187.     }
  188.   }
  189.  
  190.   for (int j = 0; j < J_LAYER_COUNT; j++) {
  191.     jkMatrix[j] = randInt8() / 4;
  192.     jBias[j] = randInt8() / 4;
  193.  
  194.     if(jkMatrix[j] == 0) {
  195.       jkMatrix[j] = 4;
  196.     }
  197.   }
  198.  
  199.   kBias = randInt8() / 4;
  200.  
  201.   for (int32_t tTime = 0; tTime < 86400 * 6; tTime += 60 * 5) {
  202.     train(0.3, tTime, tTime - 3600, 0.1 * WEIGHT_RESOLUTION);
  203.   }
  204. }
  205.  
  206. int8_t randInt8() {
  207.   return (rand() % 128) - 64;
  208. }
  209.  
  210. float readClockSensorSin(int32_t theTime, int32_t period) {
  211.   return sin(2 * M_PI * (double)(theTime % period) / period);
  212. }
  213.  
  214. float readClockSensorCos(int32_t theTime, int32_t period) {
  215.   return cos(2 * M_PI * (double)(theTime % period) / period);
  216. }
  217.  
  218. float sig(float x) {
  219.   return 1 / (1 + exp(-x));
  220. }
  221.  
  222. void calculateSensorValues(float *sensors, int32_t theTime, int32_t lastCoffeeTime) {
  223.   sensors[0] = readClockSensorSin(theTime, DAY_IN_SECONDS);
  224.   sensors[1] = readClockSensorCos(theTime, DAY_IN_SECONDS);
  225.  
  226.   sensors[2] = readClockSensorSin(theTime, DAY_IN_SECONDS/2);
  227.   sensors[3] = readClockSensorCos(theTime, DAY_IN_SECONDS/2);
  228.  
  229.   sensors[4] = readClockSensorSin(theTime, DAY_IN_SECONDS/3);
  230.   sensors[5] = readClockSensorCos(theTime, DAY_IN_SECONDS/3);
  231.  
  232.   sensors[6] = readClockSensorSin(theTime, DAY_IN_SECONDS/4);
  233.   sensors[7] = readClockSensorCos(theTime, DAY_IN_SECONDS/4);
  234.  
  235.   sensors[8] = readClockSensorSin(theTime, DAY_IN_SECONDS/6);
  236.   sensors[9] = readClockSensorCos(theTime, DAY_IN_SECONDS/6);
  237.  
  238.   sensors[10] = readClockSensorSin(theTime, DAY_IN_SECONDS/8);
  239.   sensors[11] = readClockSensorCos(theTime, DAY_IN_SECONDS/8);
  240.  
  241.   sensors[12] = readClockSensorSin(theTime, DAY_IN_SECONDS/12);
  242.   sensors[13] = readClockSensorCos(theTime, DAY_IN_SECONDS/12);
  243.  
  244.   sensors[14] = exp(-(double)(theTime - lastCoffeeTime) / ((double)60L * 60 * 2));
  245.   sensors[15] = exp(-(double)(theTime - lastCoffeeTime) / ((double)60L * 60 * 8));
  246.   sensors[16] = exp(-(double)(theTime - lastCoffeeTime) / ((double)60L * 60 * 24));
  247. }
  248.  
  249. void calculateHiddenLayerValues(float *hiddenNodes, float *sensors) {
  250.   for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  251.     hiddenNodes[j] = (float)jBias[j] / WEIGHT_RESOLUTION;
  252.    
  253.     for (uint8_t i = 0; i < I_LAYER_COUNT; i++) {
  254.       hiddenNodes[j] += sensors[i] * (float)ijMatrix[i][j] / WEIGHT_RESOLUTION;
  255.     }
  256.    
  257.     hiddenNodes[j] = sig(hiddenNodes[j]);
  258.   }
  259. }
  260.  
  261. void calculateOutput(float *output, float *hiddenNodes) {
  262.   *output = (float)kBias / WEIGHT_RESOLUTION;
  263.   for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  264.     *output += hiddenNodes[j] * (float)jkMatrix[j] / WEIGHT_RESOLUTION;
  265.   }
  266.   *output = sig(*output);
  267. }
  268.  
  269. float forecast(int32_t theTime, int32_t lastCoffeeTime) {
  270.   float sensors[I_LAYER_COUNT];
  271.   float hiddenNodes[J_LAYER_COUNT];
  272.   float output;
  273.  
  274.   calculateSensorValues(sensors, theTime, lastCoffeeTime);
  275.   calculateHiddenLayerValues(hiddenNodes, sensors);
  276.   calculateOutput(&output, hiddenNodes);  
  277.  
  278.   return output;  
  279. }
  280.  
  281. void train (float target, int32_t theTime, int32_t lastCoffeeTime, float eta) {
  282.   float sensors[I_LAYER_COUNT];
  283.   float hiddenNodes[J_LAYER_COUNT];
  284.   float deltaJs[J_LAYER_COUNT];
  285.   float output, deltaK;
  286.    
  287.   calculateSensorValues(sensors, theTime, lastCoffeeTime);
  288.   calculateHiddenLayerValues(hiddenNodes, sensors);
  289.   calculateOutput(&output, hiddenNodes);
  290.  
  291.   printf("\nTraining:\n");
  292.   printf("Target: %f, Output: %f\n", target, output);
  293.  
  294.   deltaK = output * (1 - output) * (output - target);
  295.  
  296.   for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  297.     deltaJs[j] = hiddenNodes[j] * (1 - hiddenNodes[j]) * deltaK * jkMatrix[j];
  298.   }
  299.  
  300.   for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  301.     for (uint8_t i = 0; i < I_LAYER_COUNT; i++) {
  302.       randAdd(&ijMatrix[i][j], -eta * deltaJs[j] * sensors[i]);
  303.     }
  304.   }
  305.  
  306.   for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  307.     randAdd(&jBias[j], -eta * deltaJs[j]);
  308.   }
  309.  
  310.   for (uint8_t j = 0; j < J_LAYER_COUNT; j++) {
  311.     randAdd(&jkMatrix[j], -eta * deltaK * hiddenNodes[j]);
  312.   }
  313.  
  314.   randAdd(&kBias, -eta * deltaK);
  315.  
  316.   calculateSensorValues(sensors, theTime, lastCoffeeTime);
  317.   calculateHiddenLayerValues(hiddenNodes, sensors);
  318.   calculateOutput(&output, hiddenNodes);
  319.   printf("\nUpdated Output: %f\n", output);
  320. }
  321.  
  322. void randAdd(int8_t *integer, float flt) {
  323.   int8_t sign;
  324.   int16_t result = *integer;
  325.  
  326.   if (flt < 0) {
  327.     flt = -flt;
  328.     sign = -1;
  329.   } else {
  330.     sign = 1;    
  331.   }
  332.  
  333.   while (flt > 1) {
  334.     flt--;
  335.     result += sign;
  336.     printf("|");
  337.   }
  338.    
  339.   if (flt * 1000 >= rand() % 1000) {
  340.     printf(".");
  341.     result += sign;
  342.   }
  343.  
  344.   if (result > 127) {
  345.     result = 127;  
  346.   } else if (result < -128) {
  347.     result = -128;
  348.   }
  349.  
  350.   *integer = (int8_t)result;
  351. }
  352.  
  353. void lightLights(float forecast) {
  354.   PORTC &= ~((1<<PORTC1) | (1<<PORTC2) | (1<<PORTC3));
  355.  
  356.   if (forecast >= 0.05 && 0.15 > forecast) {
  357.     PORTC |= (1 << PORTC1);
  358.   }
  359.  
  360.   if (forecast >= 0.15 && 0.25 > forecast) {
  361.     PORTC |= (1 << PORTC2);
  362.   }
  363.  
  364.   if (forecast >= 0.25) {
  365.     PORTC |= (1 << PORTC3);
  366.   }
  367. }
  368.  
  369. ISR(TIMER1_COMPA_vect) {
  370.   TCNT1 = 0x0000;
  371.   timerCounter++;
  372.  
  373.   if (trainingTimer > 0) {
  374.     trainingTimer--;
  375.   }
  376.  
  377.   if (forecastTimer > 0) {
  378.     forecastTimer--;
  379.   }
  380.  
  381.   if (backupTimer > 0) {
  382.     backupTimer--;
  383.   }
  384. }
  385.  
  386. void eeWrite(uint16_t *uiAddress, uint8_t ucData) {
  387.   cli();
  388.   /* Wait for completion of previous write */
  389.   while(EECR & (1<<EEPE)) ;
  390.  
  391.   /* Set up address and Data Registers */
  392.   EEAR = *uiAddress;
  393.   EEDR = ucData;
  394.   /* Write logical one to EEMPE */
  395.   EECR |= (1<<EEMPE);
  396.   /* Start eeprom write by setting EEPE */
  397.   EECR |= (1<<EEPE);
  398.   (*uiAddress)++;
  399.   sei();
  400. }
  401.  
  402. uint8_t eeRead(uint16_t *uiAddress) {
  403.   /* Wait for completion of previous write */
  404.   while(EECR & (1<<EEPE)) ;
  405.   /* Set up address register */
  406.   EEAR = *uiAddress;
  407.   /* Start eeprom read by writing EERE */
  408.   EECR |= (1<<EERE);
  409.   (*uiAddress)++;
  410.   /* Return data from Data Register */
  411.   return EEDR;
  412. }
  413.  
  414. uint16_t crc16(uint16_t crc, uint8_t data) {
  415.   crc = crc ^ (uint16_t)data;
  416.  
  417.   for (uint8_t i = 8; i > 0; i--) {
  418.     if (crc & 0x0001) {
  419.       crc = (crc >> 1)^0x8408;
  420.     } else {
  421.       crc >>= 1;
  422.     }
  423.   }
  424.  
  425.   return crc;  
  426. }
  427.  
  428. void backupNetwork() {
  429.   uint16_t eeAddress = 0;
  430.   uint16_t crc = 0xFFFF;
  431.  
  432.   for (int j = 0; j < J_LAYER_COUNT; j++) {
  433.     for (int i = 0; i < I_LAYER_COUNT; i++) {
  434.       eeWrite(&eeAddress, ijMatrix[i][j]);
  435.       crc = crc16(crc, ijMatrix[i][j]);
  436.     }
  437.   }
  438.  
  439.   for (int j = 0; j < J_LAYER_COUNT; j++) {
  440.     eeWrite(&eeAddress, jkMatrix[j]);
  441.     crc = crc16(crc, jkMatrix[j]);
  442.   }
  443.  
  444.   for (int j = 0; j < J_LAYER_COUNT; j++) {
  445.     eeWrite(&eeAddress, jBias[j]);
  446.     crc = crc16(crc, jBias[j]);
  447.   }
  448.  
  449.   eeWrite(&eeAddress, kBias);
  450.   crc = crc16(crc, kBias);
  451.  
  452.   printf("New CRC: %x\n", crc);
  453.   eeWrite(&eeAddress, (crc>>8));
  454.   eeWrite(&eeAddress, crc);
  455. }
  456.  
  457. network_restore_status restoreNetwork() {
  458.   uint16_t eeAddress = 0;
  459.   uint16_t crc = 0xFFFF;
  460.   uint16_t storedCrc = 0;
  461.  
  462.   for (int j = 0; j < J_LAYER_COUNT; j++) {
  463.     for (int i = 0; i < I_LAYER_COUNT; i++) {
  464.       ijMatrix[i][j] = eeRead(&eeAddress);
  465.       crc = crc16(crc, ijMatrix[i][j]);
  466.     }
  467.   }  
  468.  
  469.   for (int j = 0; j < J_LAYER_COUNT; j++) {
  470.     jkMatrix[j] = eeRead(&eeAddress);
  471.     crc = crc16(crc, jkMatrix[j]);
  472.   }
  473.  
  474.   for (int j = 0; j < J_LAYER_COUNT; j++) {
  475.     jBias[j] = eeRead(&eeAddress);
  476.     crc = crc16(crc, jBias[j]);
  477.   }
  478.  
  479.   kBias = eeRead(&eeAddress);
  480.   crc = crc16(crc, kBias);
  481.  
  482.   storedCrc |= (uint16_t)eeRead(&eeAddress);
  483.   storedCrc <<= 8;
  484.   storedCrc |= (uint16_t)eeRead(&eeAddress);
  485.   if (crc != storedCrc) {
  486.     printf("Restore Failed. %x != %x\n", crc, storedCrc);
  487.     return CRC_MISMATCH;
  488.   } else {
  489.     printf("Network restored successfully.\n");
  490.     return SUCCESS;
  491.   }
  492. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement