Index: webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c =================================================================== --- webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c (revision 69) +++ webserver/example/EnergyMeters/Source/EnergyMeters/SolarCountUART.c (revision 70) @@ -103,4 +103,7 @@ +int dayRxYield[NUMBER_OF_SOLAR_CHANNELS]; /* daily yield data */ + + const unsigned char query_sc_time[] = "\x02\xB0\xF0\x03\x00\x04\xAB\xB9\x03"; // Zeit abfragen const unsigned char query_sc_time_rsp[] = "\x02\xF0\xB0\x08\x00\x84\x00\x00\x00\x00\x00\x00\x00\x03"; // Zeit abfragen @@ -120,6 +123,26 @@ //specification: unsigned char req_month_yield[] = "\x02\x31\x3c\x4d\x30\x31\x30\x30\x03"; // Frame for querying the yield. Will be filled in by solQueryYield() -// 02 31 3c 4d 30 30 30 30 30 31 fd 03 -unsigned char req_month_yield[] = "\x02\x31\x3c\x4d\x30\x30\x30\x30\x30\x31\xfd\x03"; // Frame for querying the yield. Will be filled in by solQueryYield() +// +unsigned char req_month_yield[] = "\x02\x31\x3C\x6d\x30\x32\x30\x30\x30\x32\xff\x03"; // Frame for querying the monthly yield. Will be filled in by solQueryYield() + + +unsigned char req_minute_yield[] = "\x02\x31\x3C\x6D\x30\x32\x30\x30\x30\x32\x00\x03"; // Frame for querying the minutely yield. Will be filled in by solQueryYield() +const unsigned char yield_minute_rsp[] = "\x02\x31\x6D\x30\x31\x30\x30\x30\x32\x30\x30\x30\x30\x30\x32\x41\x44\xC8\x03\x03"; +const unsigned char yield_minute_r_m[] = "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"; + + +unsigned char req_day_yield[] = "\x02\x31\x3c\x44\x30\x32\x30\x30\x30\x32\x00\x03"; // Frame for querying the minutely yield. Will be filled in by solQueryYield() +const unsigned char yield_day_rsp[] = "\x02\x31\x44\x30\x31\x30\x30\x30\x32\x30\x30\x30\x30\x30\x32\x41\x44\xC8\x03\x03"; +const unsigned char yield_day_r_m[] = "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"; + + +unsigned char req_hour_yield[] = "\x02\x31\x3c\x68\x30\x32\x30\x30\x30\x32\x00\x03"; // Frame for querying the minutely yield. Will be filled in by solQueryYield() +const unsigned char yield_hour_rsp[] = "\x02\x31\x68\x30\x31\x30\x30\x30\x32\x30\x30\x30\x30\x30\x30\x30\x30\x30\x03\x03"; +const unsigned char yield_hour_r_m[] = "\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF"; + + + + + // tt (time) values: m=minute , h = hour, D = day, M = month (\x31), Y = year @@ -129,12 +152,10 @@ // ad: unit address // r1 to r7: result binary coded hex -// ad tt cc m1 m2 r1 r2 r3 r4 r5 r6 r7 ck -//specification: unsigned char yield_month_rsp[] = "\x02\x31\x4d\x30\x00\x00\x09\x0c\x04\x0a\x26\x86\xcd\x00\x03"; /* exp. query yield response. Will be filled in by solQueryYield() */ -//specification: unsigned char yield_month_r_m[] = "\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff"; /* exp. query yield seq response mask. Will be filled in by solQueryYield() */ - -// 02 31 4d 30 30 30 30 30 31 30 30 30 30 31 35 44 43 9a 03 03 -// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 -unsigned char yield_month_rsp[] = "\x02\x31\x4d\x30\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"; /* exp. query yield response. Will be filled in by solQueryYield() */ -unsigned char yield_month_r_m[] = "\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff"; /* exp. query yield seq response mask. Will be filled in by solQueryYield() */ + + +// 02 31 4d 30 30 30 30 30 31 30 30 30 30 31 35 44 43 +// 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 +unsigned char yield_month_rsp[] = "\x02\x31\x4d\x33\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03"; /* exp. query yield response. Will be filled in by solQueryYield() */ +unsigned char yield_month_r_m[] = "\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff"; /* exp. query yield seq response mask. Will be filled in by solQueryYield() */ @@ -229,4 +250,6 @@ { int i; + int k; + xLastSolarStateChangeTime = xTaskGetTickCount(); xLastTimeCheckTime = xTaskGetTickCount(); @@ -243,4 +266,10 @@ /* do not invalidate history here so we do not lose all data */ + + /* init daily rx yield array with 0 */ + for (i = 0; i < NUMBER_OF_SOLAR_CHANNELS; i++) + { + dayRxYield[i] = 0; + } /* for */ @@ -417,5 +446,8 @@ void solarFSM(void) { + unsigned char i; int cmpResult; + unsigned char power; /* variable for conversions */ + unsigned char checkDate; /* temp variable for day of month */ @@ -537,5 +569,5 @@ currentChannel = 0; /* start yield scan on channel 0 */ - solarState = SOL_QUERY_YIELD; /* change state: time response received, now init and query the channels */ + solarState = SOL_QUERY_YIELD; //xxxxxxx SOL_NO_INIT; //SOL_QUERY_YIELD; /* change state: time response received, now init and query the channels */ } else @@ -552,22 +584,62 @@ /* first, fill in data for tx */ // TODO - - -// req_month_yield[4] = 0x30 + 1; // channel -// req_month_yield[8] = 0x30 + 0; // month MSB (binary coded hex) -// req_month_yield[9] = 0x30 + 4; // month LSB (binary coded hex) - - /* then, calculate the CRC for tx */ - (void)checkRxOneByteCheckSum(&(req_month_yield[0]), 1, 7, 8); - /* checksum now in calculatedCrc1Byte */ - - - // crc - //req_month_yield[7] = calculatedCrc1Byte; /* fill in checksum */ - - resetUart3RxBuf(); - send_uart3((unsigned char *)req_month_yield, sizeof(req_month_yield)); - - solarState = SOL_QUERY_YIELD_WAIT_REPLY; /* change state: now wait for response */ + + + if (currentChannel >= 6) + { + currentChannel = 0; + solarState = SOL_NO_INIT; /* we are done with all the channels. go ahead */ + } + else + { + /* query the next channel */ + + checkDate = scDate[2]-1; /* we query the previous day */ + + if (checkDate == 0) + { + /* first day of month */ + + /* check new month */ + if (scDate[1] == 3) + { + /* looking for end of february? handle leap years */ + if ((scDate[0] % 4) == 0) + { + checkDate = 29; /* leap year */ + } + else + { + checkDate = 28; /* not a leap year */ + } + } + else if + ((scDate[1] == 1) || + (scDate[1] == 5) || + (scDate[1] == 7) || + (scDate[1] == 8) || + (scDate[1] == 10) || + (scDate[1] == 12)) + { + checkDate = 31; + } + else + { + checkDate = 30; + } + } + + send_yield_query_day(/* channel: */ currentChannel, /* day: (yesterday) */ checkDate ); + xLastSolarStateChangeTime = xTaskGetTickCount(); + solarState = SOL_QUERY_YIELD_WAIT_REPLY; /* query next channel. change state: now wait for response */ + + } + + //send_yield_query_minute(/* channel: */ 1, /* minute: */ 40 ); + + // hour is broken... ?! + //send_yield_query_hour(/* channel: */ 1, /* hour: */ 11 ); + + break; /* end of case SOL_QUERY_YIELD */ @@ -576,6 +648,11 @@ - - cmpResult = checkUart3Received(yield_month_rsp, yield_month_r_m, sizeof(yield_month_rsp)-1); + // cmpResult = checkUart3Received(yield_minute_rsp, yield_minute_r_m, sizeof(yield_minute_rsp)-1); + + // the query for hour is broken... ?! + //cmpResult = checkUart3Received(yield_hour_rsp, yield_hour_r_m, sizeof(yield_hour_rsp)-1); + + cmpResult = checkUart3Received(yield_day_rsp, yield_day_r_m, sizeof(yield_day_rsp)-1); + @@ -584,28 +661,23 @@ { /* we have got a match! */ - - - resultValueRaw = extractBinaryHexDigitString( &(rxUART3[0]), - 9, /* first byte of binary hex string */ - 16 /* last byte of binary hex string */ - ); - - - - solarState = SOL_NO_INIT; /* go ahead */ - + + if (currentChannel <= 5) + { + + + dayRxYield[currentChannel] = + extractBinaryHexDigitString( &(rxUART3[0]), 13, 16 ); + + } /* if */ + else + { + /* all channels done. nothing to do, we leave via SOL_QUERY_YIELD */ + } + + + currentChannel++; /* increment channel counter so we query the next channel in the next round */ + xLastSolarStateChangeTime = xTaskGetTickCount(); + solarState = SOL_QUERY_YIELD; /* go ahead */ } -#if 0 - currentChannel++; /* next channel */ - - if (currentChannel >= 6) - { - solarState = SOL_NO_INIT; /* change state: last channel done */ - } /* if */ - else - { - solarState = SOL_QUERY_YIELD; /* scan next channel */ - } /* else */ -#endif break; /* end of case SOL_QUERY_YIELD_WAIT_REPLY */ @@ -1012,5 +1084,5 @@ -portCHAR checkRxOneByteCheckSum(unsigned char* dataStart, unsigned char firstByte, unsigned char lastByte, unsigned charCheckSumStartByte) +portCHAR checkRxOneByteCheckSum(unsigned char* dataStart, unsigned char firstByte, unsigned char lastByte, unsigned char CheckSumStartByte) { portCHAR retVal; /* return value */ @@ -1020,8 +1092,14 @@ int x; - unsigned long crcLONG = 0; + unsigned long crcLONG; unsigned char crcCHAR; unsigned char crcCHARinv; - unsigned char carry = 0; + unsigned char carry; + + crcLONG = 0; + crcCHAR = 0; + crcCHARinv = 0; + carry = 0; + /* use bytes 1 to 13 for the checksum */ @@ -1029,10 +1107,4 @@ { - /* overflow? */ - // if (((portSHORT)crc + (portSHORT)(dataStart[x])) > 0xFF) - // { - // carry++; - // } - crcLONG = (crcLONG + dataStart[x]); /* add and truncate to 8 bit */ } @@ -1040,7 +1112,5 @@ carry = (unsigned char)(((crcLONG & 0xFF00) >> 8)); - crcCHAR = (unsigned char)(crcLONG & 0xFF); - - crcCHAR = (unsigned char)(crcCHAR + carry); + crcCHAR = ((unsigned char)crcLONG) + carry; crcCHARinv = (unsigned char)(~crcCHAR); @@ -1048,5 +1118,5 @@ calculatedCrc1Byte = crcCHARinv; /* save calculated CRC (for use in case of checksum generation) */ - if (crcCHARinv == dataStart[charCheckSumStartByte]) + if (crcCHARinv == dataStart[CheckSumStartByte]) { retVal = 1; /* checksum OK, data is valid */ @@ -1060,5 +1130,5 @@ -portCHAR checkRxTwoByteCheckSum(unsigned char* dataStart, unsigned char firstByte, unsigned char lastByte, unsigned charCheckSumStartByte ) +portCHAR checkRxTwoByteCheckSum(unsigned char* dataStart, unsigned char firstByte, unsigned char lastByte, unsigned char CheckSumStartByte ) { unsigned short cmpValue; @@ -1077,5 +1147,5 @@ - cmpValue = ((((unsigned short)dataStart[charCheckSumStartByte+1])<<8) | dataStart[charCheckSumStartByte]); + cmpValue = ((((unsigned short)dataStart[CheckSumStartByte+1])<<8) | dataStart[CheckSumStartByte]); calculatedCrc2Byte = staticCRC; /* save calculated CRC (for use in case of checksum generation) */ @@ -1132,2 +1202,125 @@ } /* extractBinaryHexDigitString() */ + + +static unsigned char calculate_crc8(unsigned char * d_serdata_tuc, unsigned char nbytes) +{ + unsigned char i; + unsigned char j; + unsigned char d_currbyte_tuc; + unsigned char d_crc_tuc; + + /* start with BISISTX and repeat the checksum calculation for all bytes until CHKS8 (excl.) */ + d_crc_tuc = 0; // init the checksum + + for( j = 1; j < (nbytes-2); j ++ ) + { + + d_currbyte_tuc = d_serdata_tuc[ j ]; + + for( i = 8; i > 0; i -- ) + { + /* if current bit != 0 */ + if (( (d_crc_tuc ^ d_currbyte_tuc) & BIT0 ) != 0) + { + d_crc_tuc ^= 0x18; + d_crc_tuc >>= 1; + d_crc_tuc |= BIT7; + } + else + { + d_crc_tuc >>= 1; + } + d_currbyte_tuc >>= 1; // prepare for next databit + } /* for */ + } // this byte is finished + + /* checksum is complete now - result always ORed with 0x80 and then compare */ + /* calculated and received checksum */ + d_crc_tuc |= BIT7; + return d_crc_tuc; +} + + +void send_yield_query_day(unsigned char channel /* 0 to 5 */, unsigned char day /* 1 to 31 */) +{ + unsigned char newChkSum; + + req_day_yield[5] = 0x30 + channel; // channel + + + /* convert day to binary coded hex */ + if (day > 15) + { + req_day_yield[8] = 0x31; /* hex MSB day is 1 */ + day = day - 16; /* decrease day (is now remainder */ + } + else + { + req_day_yield[8] = 0x30; /* hex MSB day is 0 */ + } + req_day_yield[9] = 0x30 + day; /* hex LSB day */ + + newChkSum = calculate_crc8( (&(req_day_yield[0])), (sizeof(req_day_yield)-1)); + req_day_yield[10] = newChkSum; /* fill in checksum */ + + resetUart3RxBuf(); + send_uart3((unsigned char *)req_day_yield, sizeof(req_day_yield)); + +} /* prepare_yield_query_day() */ + + +void send_yield_query_hour(unsigned char channel /* 0 to 5 */, unsigned char hour /* 0 to 23 */) +{ + + unsigned char newChkSum; + unsigned char hourMSB; + unsigned char hourLSB; + + req_hour_yield[5] = 0x30 + channel; // channel + + + hourMSB = hour % 16; + hourLSB = hour - hourMSB; + + req_hour_yield[8] = 0x30 + hourMSB; // minute MSB (binary coded hex) + req_hour_yield[9] = 0x30 + hourLSB; // minute LSB (binary coded hex) + + newChkSum = calculate_crc8( (&(req_hour_yield[0])), (sizeof(req_hour_yield)-1)); + + // crc + req_hour_yield[10] = newChkSum; /* fill in checksum */ + + resetUart3RxBuf(); + send_uart3((unsigned char *)req_hour_yield, sizeof(req_hour_yield)); + + + +} /* prepare_yield_query_hour() */ + + +void send_yield_query_minute(unsigned char channel /* 0 to 5 */, unsigned char minute /* 0 to 59 */) +{ + unsigned char newChkSum; + unsigned char minuteMSB; + unsigned char minuteLSB; + + req_minute_yield[5] = 0x30 + channel; // channel + + + minuteMSB = minute % 16; + minuteLSB = minute - minuteMSB; + + req_minute_yield[6] = 0x30 + minuteMSB; // minute MSB (binary coded hex) + req_minute_yield[7] = 0x30 + minuteLSB; // minute LSB (binary coded hex) + + newChkSum = calculate_crc8( (&(req_minute_yield[0])), (sizeof(req_minute_yield)-1)); + + // crc + req_minute_yield[10] = newChkSum; /* fill in checksum */ + + resetUart3RxBuf(); + send_uart3((unsigned char *)req_minute_yield, sizeof(req_minute_yield)); + + +} /* prepare_yield_query_minute() */ Index: webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h =================================================================== --- webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h (revision 69) +++ webserver/example/EnergyMeters/Source/EnergyMeters/MetersIncludes.h (revision 70) @@ -2,6 +2,9 @@ void initMeterItems(void); -portCHAR checkRxOneByteCheckSum(unsigned char* dataStart, unsigned char firstByte, unsigned char lastByte, unsigned charCheckSumStartByte); -portCHAR checkRxTwoByteCheckSum(unsigned char* dataStart, unsigned char firstByte, unsigned char lastByte, unsigned charCheckSumStartByte ); +portCHAR checkRxOneByteCheckSum(unsigned char* dataStart, unsigned char firstByte, unsigned char lastByte, unsigned char CheckSumStartByte); +portCHAR checkRxTwoByteCheckSum(unsigned char* dataStart, unsigned char firstByte, unsigned char lastByte, unsigned char CheckSumStartByte ); + + +static unsigned char calculate_crc8(unsigned char * d_serdata_tuc, unsigned char nbytes); int extractBinaryHexDigitString(unsigned char* srcDataStart, @@ -12,4 +15,9 @@ unsigned long long getEpochTimeWithMs(void); + + +void send_yield_query_day(unsigned char channel /* 0 to 5 */, unsigned char day /* 1 to 31 */); +void send_yield_query_hour(unsigned char channel /* 0 to 5 */, unsigned char hour /* 0 to 23 */); +void send_yield_query_minute(unsigned char channel /* 0 to 5 */, unsigned char minute /* 0 to 59 */); #define NUMBER_OF_METERS 6 /* the number of meters we use */ @@ -24,4 +32,9 @@ #define METERS_INT_CHECK_INTERVAL_MS 100 /* how often (in ms) do we check if one of the I/O lines has triggered */ + + +#define NUMBER_OF_SOLAR_CHANNELS 6 /* number of solar channels */ +#define DAILY_RX_YIELD_LENGTH 9 /* length of the rx data */ + @@ -50,2 +63,14 @@ extern int historyRemainTime; /* how many ticks have we left until the next history entry must be written? */ +/* bit values for calculate_crc8() */ + +#define BIT0 (1U << 0) +#define BIT1 (1U << 1) +#define BIT2 (1U << 2) +#define BIT3 (1U << 3) +#define BIT4 (1U << 4) +#define BIT5 (1U << 5) +#define BIT6 (1U << 6) +#define BIT7 (1U << 7) + +