Improved failure handling, especially in radio.
This commit is contained in:
		| @@ -62,7 +62,7 @@ void Display::begin(void) { | |||||||
|   setLargeTextSize(); |   setLargeTextSize(); | ||||||
|   u8g2.drawStr(0,16,"Booting FastClock"); |   u8g2.drawStr(0,16,"Booting FastClock"); | ||||||
|   u8g2.sendBuffer(); |   u8g2.sendBuffer(); | ||||||
|   delay(200); |   delay(400); | ||||||
|   //addLogMessage("Display initialized"); |   //addLogMessage("Display initialized"); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -141,7 +141,6 @@ void Display::showDashboard(void) { | |||||||
|     lastBlinkChange_ms = lastDisplayUpdate_ms; |     lastBlinkChange_ms = lastDisplayUpdate_ms; | ||||||
|     blinkOnCycle = !blinkOnCycle; |     blinkOnCycle = !blinkOnCycle; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   u8g2.clearBuffer(); |   u8g2.clearBuffer(); | ||||||
|   u8g2.setDrawColor(1); |   u8g2.setDrawColor(1); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| #include "config.h" | #include "config.h" | ||||||
|  |  | ||||||
| // avoid flickering of the display: | // avoid flickering of the display: | ||||||
| #define TIME_BETWEEN_DISPLAY_UPDATES_ms 200 | #define TIME_BETWEEN_DISPLAY_UPDATES_ms 300 | ||||||
| #define BLINK_ON_OFF_TIME_ms 1000 | #define BLINK_ON_OFF_TIME_ms 1000 | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/main.cpp
									
									
									
									
									
								
							| @@ -28,7 +28,7 @@ char static_ip[16] = "10.0.1.56"; | |||||||
| char static_gw[16] = "10.0.1.1"; | char static_gw[16] = "10.0.1.1"; | ||||||
| char static_sn[16] = "255.255.255.0"; | char static_sn[16] = "255.255.255.0"; | ||||||
|  |  | ||||||
| char clockName[MAX_CLOCK_NAME_LEN] = "fastclk"; | char clockName[MAX_CLOCK_NAME_LEN+1] = "fastclk"; | ||||||
| uint8_t clockChannel = DEFAULT_CLOCK_CHANNEL; | uint8_t clockChannel = DEFAULT_CLOCK_CHANNEL; | ||||||
|  |  | ||||||
| //flag for saving data | //flag for saving data | ||||||
| @@ -230,6 +230,7 @@ void checkForPowerOffRequest() { | |||||||
|     } |     } | ||||||
|     if (millis() - powerOffButtonPressed_ts > 2000) { |     if (millis() - powerOffButtonPressed_ts > 2000) { | ||||||
|       // pressed for longer than 2 seconds, now turn off |       // pressed for longer than 2 seconds, now turn off | ||||||
|  |       Serial.println(F("OFF")); | ||||||
|       ESP.deepSleep(ESP.deepSleepMax()); |       ESP.deepSleep(ESP.deepSleepMax()); | ||||||
|       delay(200); |       delay(200); | ||||||
|     } |     } | ||||||
| @@ -266,8 +267,20 @@ void loop(void) | |||||||
|     #endif |     #endif | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|   fastclock.loop(); |   // we do not want to call every task on every cycle: | ||||||
|   radio.loop(); |   switch (millis() & 0x03) { | ||||||
|   display.showDashboard(); |     case 0: | ||||||
|  |       fastclock.loop(); | ||||||
|  |       break; | ||||||
|  |     case 1: | ||||||
|  |       break; | ||||||
|  |     case 2: | ||||||
|  |       display.showDashboard(); | ||||||
|  |       break; | ||||||
|  |     case 3: | ||||||
|  |       break; | ||||||
|  |   } | ||||||
|  |   yield(); | ||||||
|  |   radio.loop(); // called always | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										136
									
								
								src/radio.cpp
									
									
									
									
									
								
							
							
						
						
									
										136
									
								
								src/radio.cpp
									
									
									
									
									
								
							| @@ -9,43 +9,39 @@ static RF24 rf24(PIN_NRF24_CE, PIN_NRF24_CSN); // 10, 8 | |||||||
| static byte addresses[][6] = {NETWORK_ADDRESS_MASTER_SEND, NETWORK_ADDRESS_MASTER_RECEIVE}; | static byte addresses[][6] = {NETWORK_ADDRESS_MASTER_SEND, NETWORK_ADDRESS_MASTER_RECEIVE}; | ||||||
|  |  | ||||||
| static int sendFailedCounter = 0; | static int sendFailedCounter = 0; | ||||||
| static unsigned long stopTime = 0, pauseTime = 0; | //static unsigned long stopTime = 0; | ||||||
|  | static unsigned long pauseTime = 0; | ||||||
| static char thisClockName[MAX_CLOCK_NAME_LEN]; | static char thisClockName[MAX_CLOCK_NAME_LEN]; | ||||||
|  |  | ||||||
| #define MAX_CLIENTS_MANAGED 20 | #define MAX_CLIENTS_MANAGED 20 | ||||||
| static uint8_t numberOfKnownClients = 0; | static uint8_t numberOfKnownClients = 0; | ||||||
| static struct { | static struct { | ||||||
|   uint8_t clientNetworkAddress; |   uint8_t clientNetworkAddress; | ||||||
|   char clientName[MAX_CLIENT_NAME_LEN]; |   char clientName[MAX_CLIENT_NAME_LEN+1]; | ||||||
| } client[MAX_CLIENTS_MANAGED]; | } client[MAX_CLIENTS_MANAGED]; | ||||||
| static uint8_t nextClientNetworkAddress = 1; | static uint8_t nextClientNetworkAddress = 1; | ||||||
|  |  | ||||||
| void Radio::switchToSenderRole(void) | void Radio::checkRadioFailure(void) { | ||||||
| { |   if (rf24.failureDetected) { | ||||||
|   Serial.println("*** changing to Tx role"); |     Serial.println(F("Radio failure detected!")); | ||||||
|   rf24.openWritingPipe(addresses[1]); |     rf24.failureDetected = 0; | ||||||
|   rf24.openReadingPipe(1,addresses[0]); |     radioInit(); | ||||||
|   rf24.stopListening(); |   } | ||||||
|   role = inTX;                  // Become the primary transmitter (ping out) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| void Radio::switchToReceiverRole(void) | void Radio::radioInit(void) { | ||||||
| { |  | ||||||
|   Serial.println("*** changing to Rx role"); |  | ||||||
|   rf24.openWritingPipe(addresses[0]); |  | ||||||
|   rf24.openReadingPipe(1,addresses[1]); |  | ||||||
|   rf24.startListening(); |  | ||||||
|   role = inRX;                // Become the primary receiver (pong back) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void Radio::begin(void) { |  | ||||||
|   display->addLogMessage("Start RF24 radio"); |   display->addLogMessage("Start RF24 radio"); | ||||||
|   pinMode(PIN_NRF24_CSN, OUTPUT); |   pinMode(PIN_NRF24_CSN, OUTPUT); | ||||||
|   pinMode(PIN_NRF24_CE, OUTPUT); |   pinMode(PIN_NRF24_CE, OUTPUT); | ||||||
|  |  | ||||||
|   rf24.begin(); |   rf24.begin(); | ||||||
|   if (rf24.isChipConnected()) { display->addLogMessage("*** RF chip found"); } |   if (rf24.isChipConnected()) { | ||||||
|   else { display->addLogMessage("*** ERROR: RF chip not found!"); } |     display->addLogMessage("*** RF chip found"); | ||||||
|  |     Serial.println(F("*** RF chip found")); | ||||||
|  |   } else { | ||||||
|  |     display->addLogMessage("*** ERROR: RF chip not found!"); | ||||||
|  |     Serial.println(F("*** ERROR: RF chip not found!")); | ||||||
|  |   } | ||||||
|   rf24.setChannel(clockChannel); |   rf24.setChannel(clockChannel); | ||||||
|   rf24.setPALevel(RF24_PA_MAX); |   rf24.setPALevel(RF24_PA_MAX); | ||||||
|   rf24.setDataRate(RF24_2MBPS); |   rf24.setDataRate(RF24_2MBPS); | ||||||
| @@ -55,69 +51,103 @@ void Radio::begin(void) { | |||||||
|   rf24.openWritingPipe(addresses[0]); |   rf24.openWritingPipe(addresses[0]); | ||||||
|   rf24.openReadingPipe(1, addresses[1]); |   rf24.openReadingPipe(1, addresses[1]); | ||||||
|   rf24.startListening(); |   rf24.startListening(); | ||||||
|   Serial.println("*** Check"); |  | ||||||
|   //rf24.printDetails(); |  | ||||||
|   rf24.powerUp(); |   rf24.powerUp(); | ||||||
|   // @TODO: real random seed! |   // @TODO: real random seed! | ||||||
|   //randomSeed(analogRead(0)); |   //randomSeed(analogRead(0)); | ||||||
|   //randomSeed(22); |   //randomSeed(22); | ||||||
|   Serial.print("*** RF payload size="); Serial.print(rf24.getPayloadSize()); Serial.println(" bytes"); | } | ||||||
|   if (rf24.testCarrier() || rf24.testRPD()) { display->addLogMessage("*** Carrier/RPD seen on radio"); } |  | ||||||
|   if (rf24.failureDetected) { display->addLogMessage("*** Radio error detected!"); } | void Radio::powerDown(void) { | ||||||
|  |   rf24.powerDown(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Radio::switchToSenderRole(void) | ||||||
|  | { | ||||||
|  |   Serial.println(F("# Tx")); | ||||||
|  |   rf24.openWritingPipe(addresses[1]); | ||||||
|  |   rf24.openReadingPipe(1,addresses[0]); | ||||||
|  |   rf24.stopListening(); | ||||||
|  |   role = inTX;                  // Become the primary transmitter (ping out) | ||||||
|  |   pauseTime = millis(); | ||||||
|  |   checkRadioFailure(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Radio::switchToReceiverRole(void) | ||||||
|  | { | ||||||
|  |   Serial.println(F("# Rx")); | ||||||
|  |   rf24.openWritingPipe(addresses[0]); | ||||||
|  |   rf24.openReadingPipe(1,addresses[1]); | ||||||
|  |   rf24.startListening(); | ||||||
|  |   role = inRX;                // Become the primary receiver (pong back) | ||||||
|  |   checkRadioFailure(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void Radio::begin(void) { | ||||||
|  |   display->addLogMessage("Start RF24 radio"); | ||||||
|  |   pinMode(PIN_NRF24_CSN, OUTPUT); | ||||||
|  |   pinMode(PIN_NRF24_CE, OUTPUT); | ||||||
|  |  | ||||||
|  |   radioInit(); | ||||||
|  |   Serial.print(F("*** RF payload size=")); Serial.print(rf24.getPayloadSize()); Serial.println(F(" bytes")); | ||||||
|  |   if (rf24.testCarrier() || rf24.testRPD()) { | ||||||
|  |     display->addLogMessage("*** Carrier/RPD seen on radio"); | ||||||
|  |     Serial.println(F("*** Carrier/RPD seen on radio")); | ||||||
|  |   } | ||||||
|  |   if (rf24.failureDetected) { | ||||||
|  |     display->addLogMessage("*** Radio error detected!"); | ||||||
|  |     Serial.println(F("*** ERROR: Radio error detected!")); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   // Start the radio listening for data |  | ||||||
|   //rf24.startListening(); |  | ||||||
|   switchToReceiverRole(); |   switchToReceiverRole(); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Radio::broadcastMessageOnChannel(void *msg, int len, uint8_t channel) { | void Radio::broadcastMessageOnChannel(void *msg, int len, uint8_t channel) { | ||||||
|   Serial.print("# set channel "); Serial.println(channel); |   Serial.print(F("# set channel ")); Serial.println(channel); | ||||||
|   rf24.setChannel(channel); |   rf24.setChannel(channel); | ||||||
|   broadcastMessage(msg, len); |   broadcastMessage(msg, len); | ||||||
|   Serial.print("# set channel "); Serial.println(clockChannel); |   Serial.print(F("# set channel ")); Serial.println(clockChannel); | ||||||
|   rf24.setChannel(clockChannel); // switch back |   rf24.setChannel(clockChannel); // switch back | ||||||
|   Serial.println("# done"); |   Serial.println(F("# done")); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Radio::broadcastMessage(void *msg, int len) { | void Radio::broadcastMessage(void *msg, int len) { | ||||||
|   uint8_t *m = (uint8_t *) msg; |   uint8_t *m = (uint8_t *) msg; | ||||||
|   Serial.print("*** Tx: ts="); Serial.print(millis()); |   Serial.print(F("ts=")); Serial.println(millis()); | ||||||
|   Serial.print(", len="); Serial.print(len); |  | ||||||
|   Serial.print(", typ="); |  | ||||||
|   Serial.print((uint8_t) m[0], HEX); Serial.print(" ("); Serial.print((char) m[0]); |  | ||||||
|   Serial.print("), to="); Serial.print((uint8_t) m[1], HEX); |  | ||||||
|   Serial.print(", from="); Serial.print((uint8_t) m[2], HEX); |  | ||||||
|   Serial.print(", msg="); Serial.print((uint8_t) m[3], HEX); |  | ||||||
|   Serial.print(", "); Serial.print((uint8_t) m[4], HEX); |  | ||||||
|   Serial.print(", "); Serial.print((uint8_t) m[5], HEX); |  | ||||||
|   Serial.print(", "); Serial.print((uint8_t) m[6], HEX); |  | ||||||
|   Serial.print(", "); Serial.print((uint8_t) m[7], HEX); |  | ||||||
|   Serial.print(", "); Serial.println((uint8_t) m[8], HEX); |  | ||||||
|   switchToSenderRole(); |   switchToSenderRole(); | ||||||
|   Serial.print("#1"); |  | ||||||
|   if (!rf24.writeFast(msg, len, true /*multicast*/)) { |   if (!rf24.writeFast(msg, len, true /*multicast*/)) { | ||||||
|       sendFailedCounter++; |       sendFailedCounter++; | ||||||
|       Serial.print("*** ERROR: failed to send msg type="); |       Serial.println(F("*** ERROR: failed to send msg")); | ||||||
|       Serial.print(*((char *) msg)); |  | ||||||
|       Serial.print(" for to=0x"); |  | ||||||
|       Serial.println(m[1], HEX); |  | ||||||
|   } |   } | ||||||
|   Serial.print("ts="); Serial.println(millis()); |   Serial.print(F("ts=")); Serial.println(millis()); | ||||||
|   //This is only required when NO ACK ( enableAutoAck(0) ) payloads are used |   //This is only required when NO ACK ( enableAutoAck(0) ) payloads are used | ||||||
|   if (millis() - pauseTime > 3) { |   if (millis() - pauseTime > 3) { | ||||||
|     pauseTime = millis(); |     pauseTime = millis(); | ||||||
|     Serial.print("pauseTime="); Serial.println(pauseTime); |     Serial.println(F("@TODO: tx-pause")); | ||||||
|     //rf24.txStandBy();          // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data |     //rf24.txStandBy();          // Need to drop out of TX mode every 4ms if sending a steady stream of multicast data | ||||||
|     //delayMicroseconds(130);     // This gives the PLL time to sync back up |     //delayMicroseconds(130);     // This gives the PLL time to sync back up | ||||||
|   } |   } | ||||||
|   stopTime = millis(); |   //stopTime = millis(); | ||||||
|   Serial.print("stopTime="); Serial.println(stopTime); |   //Serial.print(F("stopTime=")); Serial.println(stopTime); | ||||||
|                                       //This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success |                                       //This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success | ||||||
|   //if (!rf24.txStandBy()) { sendFailedCounter += 3; } //Standby, block only until FIFO empty or auto-retry timeout. Flush TX FIFO if failed |   //if (!rf24.txStandBy()) { sendFailedCounter += 3; } //Standby, block only until FIFO empty or auto-retry timeout. Flush TX FIFO if failed | ||||||
|   //radio.txStandBy(1000);              //Standby, using extended timeout period of 1 second |   //radio.txStandBy(1000);              //Standby, using extended timeout period of 1 second | ||||||
|  |  | ||||||
|   Serial.print("*** send finished, failed="); Serial.println(sendFailedCounter); |  | ||||||
|   listenOnlyFor_ms(MIN_TIME_BETWEEN_TRANSMISSIONS_ms); |   listenOnlyFor_ms(MIN_TIME_BETWEEN_TRANSMISSIONS_ms); | ||||||
|  |   switchToReceiverRole(); | ||||||
|  |  | ||||||
|  |   Serial.print(F("*** sent: len=")); Serial.print(len); | ||||||
|  |   Serial.print(F(", typ=")); | ||||||
|  |   Serial.print((uint8_t) m[0], HEX); Serial.print(" ("); Serial.print((char) m[0]); | ||||||
|  |   Serial.print(F("), to=")); Serial.print((uint8_t) m[1], HEX); | ||||||
|  |   Serial.print(F(", from=")); Serial.print((uint8_t) m[2], HEX); | ||||||
|  |   Serial.print(F(", msg=")); Serial.print((uint8_t) m[3], HEX); | ||||||
|  |   Serial.print(' '); Serial.print((uint8_t) m[4], HEX); | ||||||
|  |   Serial.print(' '); Serial.print((uint8_t) m[5], HEX); | ||||||
|  |   Serial.print(' '); Serial.print((uint8_t) m[6], HEX); | ||||||
|  |   Serial.print(' '); Serial.print((uint8_t) m[7], HEX); | ||||||
|  |   Serial.print(' '); Serial.println((uint8_t) m[8], HEX); | ||||||
|  |   Serial.print(F("*** send failed=")); Serial.println(sendFailedCounter); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Radio::broadcastClockAdvertisement(const char *clockName, uint8_t channel) { | void Radio::broadcastClockAdvertisement(const char *clockName, uint8_t channel) { | ||||||
|   | |||||||
| @@ -94,13 +94,16 @@ public: | |||||||
|   void avoidChannelSwitchesFor_ms(unsigned int duration_ms); |   void avoidChannelSwitchesFor_ms(unsigned int duration_ms); | ||||||
|   void listenOnlyFor_ms(unsigned int duration_ms); |   void listenOnlyFor_ms(unsigned int duration_ms); | ||||||
|   bool allowedToSendNow(void); |   bool allowedToSendNow(void); | ||||||
|  |   void checkRadioFailure(void); | ||||||
|  |   void powerDown(void); | ||||||
| private: | private: | ||||||
|   Display *display; |   Display *display; | ||||||
|   bool isMaster; |   bool isMaster; | ||||||
|  |   void radioInit(void); | ||||||
|   void switchToSenderRole(void); |   void switchToSenderRole(void); | ||||||
|   void switchToReceiverRole(void); |   void switchToReceiverRole(void); | ||||||
|   bool inTX, inRX, role; |   bool inTX, inRX, role; | ||||||
|   char clockName[MAX_CLOCK_NAME_LEN]; |   char clockName[MAX_CLOCK_NAME_LEN+1]; | ||||||
|   void broadcastMessage(void *msg, int len); |   void broadcastMessage(void *msg, int len); | ||||||
|   void broadcastMessageOnChannel(void *msg, int len, uint8_t channel); |   void broadcastMessageOnChannel(void *msg, int len, uint8_t channel); | ||||||
|   void broadcastClockAdvertisement(const char *clockName, uint8_t channel); |   void broadcastClockAdvertisement(const char *clockName, uint8_t channel); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user