Index: /webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c =================================================================== --- /webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c (revision 44) +++ /webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c (revision 56) @@ -8,8 +8,26 @@ #include "task.h" #include "serial.h" +#include "MetersIncludes.h" + + +static void advanceHistoryArray(void); #define solarSTACK_SIZE configMINIMAL_STACK_SIZE+200 #define SOLAR_READ_DELAY 500 + +/* after what inactivity time (ms) do we determine the solar FSM as stuck? */ +#define SOLAR_FSM_STUCK_TIMEOUT 2000 + +/* means "unknown value", converted to "U" on rrdtool script side */ +#define SOLAR_FSM_INVALID_VALUE 0x4000 /* 16384 */ + + + +int SolarHistory[SOLAR_WATT_HISTORYSIZE][3]; /* three watt values: P1, P2, P3 */ +int historyRemainTime = SOLAR_WATT_HISTORY_STEPSIZE; /* how many ticks have we left until the next history entry must be written? */ + + + // Pin I/O LED Control Maskbit @@ -106,4 +124,8 @@ portTickType xLastSolarStateChangeTime; + /* time when the elements of the history array were last moved on one step */ +portTickType xLastSolarHistoryAdvance; + + int solarReadErrors = 0; @@ -141,5 +163,7 @@ void initSolarFSM(void) { + int i; xLastSolarStateChangeTime = xTaskGetTickCount(); + xLastSolarHistoryAdvance = xTaskGetTickCount(); xLastReadTime = xTaskGetTickCount(); solarState = SOL_NO_INIT; @@ -147,4 +171,18 @@ rxBuf3NextFreeRxPos = 0; currentChannel = 0; + + /* set data to invalid value */ + chanWatt[0] = SOLAR_FSM_INVALID_VALUE; + chanWatt[1] = SOLAR_FSM_INVALID_VALUE; + chanWatt[2] = SOLAR_FSM_INVALID_VALUE; + + /* invalidate history */ + for (i = 0; i < SOLAR_WATT_HISTORYSIZE; i++) + { + SolarHistory[i][0] = SOLAR_FSM_INVALID_VALUE; + SolarHistory[i][1] = SOLAR_FSM_INVALID_VALUE; + SolarHistory[i][2] = SOLAR_FSM_INVALID_VALUE; + } + } /* initSolarFSM */ @@ -326,5 +364,5 @@ /* did the SolarFSM get stuck during reading? */ - if (xTaskGetTickCount() > xLastSolarStateChangeTime + 5000) + if (xTaskGetTickCount() > xLastSolarStateChangeTime + SOLAR_FSM_STUCK_TIMEOUT) { /* something has gone wrong (possible Rx Timeout). restart, state SOL_NO_INIT */ @@ -332,4 +370,20 @@ initSolarFSM(); solarReadErrors++; + } + else if (xTaskGetTickCount() < xLastSolarStateChangeTime) + { + /* overflow of timer, just recover. delay will be wrong. */ + xLastSolarStateChangeTime = xTaskGetTickCount(); + } + + + if (xTaskGetTickCount() > (xLastSolarHistoryAdvance + SOLAR_WATT_HISTORY_STEPSIZE)) + { + advanceHistoryArray(); + } + else if (xTaskGetTickCount() < xLastSolarHistoryAdvance) + { + /* overflow of timer, just recover. delay will be wrong. */ + xLastSolarHistoryAdvance = xTaskGetTickCount(); } @@ -454,6 +508,8 @@ if ((currentChannel >= 0) && (currentChannel < 6)) { + portENTER_CRITICAL(); chanVolt[currentChannel] = rxUART3[11]; chanWatt[currentChannel] = (int)(rxUART3[7]) | (((int)(rxUART3[8])) << 8) /* index 7: LSB, index 8: MSB */; + portEXIT_CRITICAL(); } /* if */ @@ -495,4 +551,30 @@ +/* + * Check if we have to save the current data to the next history array set, and do it + * if necessary. + * + */ +static void advanceHistoryArray(void) +{ + int i; + + /* advance entries by 1. we do not care about data locking here. */ + for (i = 0; i < (SOLAR_WATT_HISTORYSIZE-1); i++) + { + portENTER_CRITICAL(); + SolarHistory[i+1][0] = SolarHistory[i][0]; + SolarHistory[i+1][1] = SolarHistory[i][1]; + SolarHistory[i+1][2] = SolarHistory[i][2]; + portEXIT_CRITICAL(); + } /* for */ + /* get the most recent values to index 0 */ + portENTER_CRITICAL(); + SolarHistory[0][0] = chanWatt[0]; + SolarHistory[0][1] = chanWatt[1]; + SolarHistory[0][2] = chanWatt[2]; + portEXIT_CRITICAL(); + +} /* advanceHistoryArray() */ Index: /webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h =================================================================== --- /webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h (revision 50) +++ /webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h (revision 56) @@ -28,2 +28,11 @@ meterItem meterItems[NUMBER_OF_METERS]; /* the data for all the meters */ +/* the history spans (SOLAR_WATT_HISTORYSIZE * SOLAR_WATT_HISTORY_STEPSIZE) / 1000 seconds */ + +/* how many old values of the three wattages do we keep? */ +#define SOLAR_WATT_HISTORYSIZE 10 +/* how far are the values apart? in milliseconds */ +#define SOLAR_WATT_HISTORY_STEPSIZE 3000 +extern int SolarHistory[SOLAR_WATT_HISTORYSIZE][3]; /* three watt values: P1, P2, P3 */ +extern int historyRemainTime; /* how many ticks have we left until the next history entry must be written? */ + Index: /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c =================================================================== --- /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c (revision 55) +++ /webserver/example/EnergyMeters/EnergyMeters/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c (revision 56) @@ -218,9 +218,10 @@ extern void vTaskList( signed char *pcWriteBuffer ); -static char cCountBuf[ 800 ]; +static char cCountBuf[ 1000 ]; long lRefreshCount = 0; static unsigned short generate_rtos_stats(void *arg) { + int i; unsigned long long currentTime = getEpochTimeWithMs(); @@ -323,4 +324,23 @@ ); strcat( uip_appdata, cCountBuf ); + + + sprintf( cCountBuf, "HIST %u %u\r\n", + SOLAR_WATT_HISTORY_STEPSIZE, + SOLAR_WATT_HISTORYSIZE ); + strcat( uip_appdata, cCountBuf ); + + for (i = 0; i < SOLAR_WATT_HISTORYSIZE; i++) + { + sprintf( + cCountBuf, "SH %u %u %u %u\r\n", + SOLAR_WATT_HISTORYSIZE, + + SolarHistory[i][0], + SolarHistory[i][1], + SolarHistory[i][2] + ); + strcat( uip_appdata, cCountBuf ); + } /* for */ //strcat( ( char * ) uip_appdata, ( char * ) "1234test" );