Index: webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c =================================================================== --- webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c (revision 67) +++ webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c (revision 68) @@ -23,4 +23,8 @@ #define SOLAR_FSM_STUCK_TIMEOUT 2000 +/* how often (in ms) do we query the timer? */ +#define SOLAR_TIME_CHECK_INTERVAL (60 * 1000) + + /* means "unknown value", converted to "U" on rrdtool script side */ #define SOLAR_FSM_INVALID_VALUE 0x4000 /* 16384 */ @@ -34,5 +38,5 @@ unsigned long correctVoltWattRx = 0; /* counter of correctly received wattage/voltage packets */ unsigned long failedVoltWattRx = 0; /* counter of incorrectly received wattage/voltage packets */ - +unsigned long queryTimeCounter = 0; /* counter attempted queries for the time */ static unsigned short staticCRC; @@ -81,5 +85,5 @@ unsigned char currentChannel; /* the SolarCount channel we currently query (here: 0 to 3) */ -static int solarState = SOL_NO_INIT; /* state of the SolarCount communication state machine */ +static int solarState = SOL_QUERY_TIME; /* state of the SolarCount communication state machine */ @@ -140,4 +144,7 @@ portTickType xLastSolarStateChangeTime; +portTickType xLastTimeCheckTime; + + /* time when the elements of the history array were last moved on one step */ portTickType xLastSolarHistoryAdvance; @@ -148,4 +155,8 @@ int solarReadCounter = 0; + + +int solarStateWhenFail = 0xFF; +int currentChannelWhenFail = 0xFF; /* pototype section */ @@ -181,6 +192,7 @@ int i; xLastSolarStateChangeTime = xTaskGetTickCount(); + xLastTimeCheckTime = xTaskGetTickCount(); xLastReadTime = xTaskGetTickCount(); - solarState = SOL_NO_INIT; + solarState = SOL_QUERY_TIME; uart3TxRunning = 0; /* reset flag to tell if we are currently sending a datagram */ rxBuf3NextFreeRxPos = 0; @@ -374,10 +386,16 @@ /* did the SolarFSM get stuck during reading? */ - if (xTaskGetTickCount() > xLastSolarStateChangeTime + SOLAR_FSM_STUCK_TIMEOUT) - { - /* something has gone wrong (possible Rx Timeout). restart, state SOL_NO_INIT */ + if (xTaskGetTickCount() > (xLastSolarStateChangeTime + SOLAR_FSM_STUCK_TIMEOUT)) + { + /* something has gone wrong (possible Rx Timeout). restart, state SOL_QUERY_TIME */ xLastSolarStateChangeTime = xTaskGetTickCount(); + + /* save error info */ + solarStateWhenFail = solarState; + currentChannelWhenFail = currentChannel; + initSolarFSM(); solarReadErrors++; + } else if (xTaskGetTickCount() < xLastSolarStateChangeTime) @@ -429,5 +447,5 @@ /* now ready to query channel 0 data in next state */ xLastSolarStateChangeTime = xTaskGetTickCount(); - solarState = SOL_QUERY_TIME; + solarState = SOL_CHAN; } else @@ -441,9 +459,9 @@ resetUart3RxBuf(); /* init */ - currentChannel = 0; /* the channel we query first */ /* send query_sc_time */ send_uart3((unsigned char *)query_sc_time, sizeof(query_sc_time)); xLastSolarStateChangeTime = xTaskGetTickCount(); + queryTimeCounter++; solarState = SOL_WAIT_FOR_TIME_RSP; /* query sent wait for response */ break; @@ -456,5 +474,5 @@ if (cmpResult == 0) { - /* we have got a match! */ + /* we have got a match! */ if (checkRxTwoByteCheckSum(1, 10, 11) == 1) /* checksum in bytes 11 and 12, check bytes 1 to 10 */ @@ -472,5 +490,5 @@ else { - ; + /* time rx checksum error */ ; } @@ -478,6 +496,6 @@ resetUart3RxBuf(); - - solarState = SOL_CHAN; /* change state: time response received, now query the channels */ + xLastSolarStateChangeTime = xTaskGetTickCount(); + solarState = SOL_NO_INIT; /* change state: time response received, now init and query the channels */ } else @@ -517,11 +535,39 @@ xLastSolarStateChangeTime = xTaskGetTickCount(); solarState = SOL_FINISHED; + currentChannel = 0; + + /* new duplicated code: */ + + resetUart3RxBuf(); + + + if (xTaskGetTickCount() > (xLastTimeCheckTime + SOLAR_TIME_CHECK_INTERVAL)) + { + /* time to get the time info again! */ + xLastTimeCheckTime = xTaskGetTickCount(); + solarState = SOL_QUERY_TIME; /* restart the measurement cycle (with time check at first) */ + } + else if (xTaskGetTickCount() < xLastTimeCheckTime) + { + /* overflow of timer, just recover. delay will be wrong. */ + xLastTimeCheckTime = xTaskGetTickCount(); + solarState = SOL_NO_INIT; /* restart the measurement cycle (without time check at first) */ + } + else + { + /* not time to get the time info. leave state at SOL_FINISHED. */ + } + + + break; default: - ; /* do nothing */ + currentChannel = 0; /* current channel not 0 to 6, reset it. */ + /* nothing else to do */ + } /* switch */ - if (solarState != SOL_FINISHED) + if ((solarState != SOL_FINISHED) && (solarState != SOL_QUERY_TIME)) { - xLastSolarStateChangeTime = xTaskGetTickCount(); + xLastSolarStateChangeTime = xTaskGetTickCount(); solarState = SOL_CHAN_WAIT_REPLY; /* wait for reply if not finished */ } /* if */ @@ -552,5 +598,5 @@ case 6: /* wait for the response to the finishing init */ - cmpResult = checkUart3Received(init_after_all_chan_rsp, init_after_all_chan_r_m, sizeof(init_after_all_chan_rsp)-1); + // cmpResult = checkUart3Received(init_after_all_chan_rsp, init_after_all_chan_r_m, sizeof(init_after_all_chan_rsp)-1); break; default: @@ -601,4 +647,8 @@ /* switch to next channel */ currentChannel++; + + /* finally, discard data from buffer */ + resetUart3RxBuf(); + /* now ready to query channel data for next channel */ xLastSolarStateChangeTime = xTaskGetTickCount(); @@ -607,10 +657,31 @@ else { + + /* I think we never go here ... */ + /* we received the finishing sequence */ xLastSolarStateChangeTime = xTaskGetTickCount(); - solarState = SOL_NO_INIT; /* restart the measurement cycle */ - } - - resetUart3RxBuf(); + + resetUart3RxBuf(); + + // may be duplicated + if (xTaskGetTickCount() > (xLastTimeCheckTime + SOLAR_TIME_CHECK_INTERVAL)) + { + /* time to get the time info again! */ + xLastTimeCheckTime = xTaskGetTickCount(); + solarState = SOL_QUERY_TIME; /* restart the measurement cycle (with time check at first) */ + } + else if (xTaskGetTickCount() < xLastTimeCheckTime) + { + /* overflow of timer, just recover. delay will be wrong. */ + xLastTimeCheckTime = xTaskGetTickCount(); + solarState = SOL_NO_INIT; /* restart the measurement cycle (without time check at first) */ + } + else + { + /* not time to get the time info. do a regular reading cycle without time */ + solarState = SOL_NO_INIT; /* restart the measurement cycle (without time check at first) */ + } + } /* else */ }