From 91653e197f5dd5de874bd13a1a82205b2fa57df6 Mon Sep 17 00:00:00 2001 From: Dirk Jahnke Date: Sat, 1 Dec 2018 13:12:33 +0100 Subject: [PATCH] Improved failure handling, especially in radio. --- src/display.cpp | 3 +- src/display.h | 2 +- src/main.cpp | 21 ++++++-- src/radio.cpp | 136 +++++++++++++++++++++++++++++------------------- src/radio.h | 7 ++- 5 files changed, 107 insertions(+), 62 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index 501e8bb..d8bc0eb 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -62,7 +62,7 @@ void Display::begin(void) { setLargeTextSize(); u8g2.drawStr(0,16,"Booting FastClock"); u8g2.sendBuffer(); - delay(200); + delay(400); //addLogMessage("Display initialized"); } @@ -141,7 +141,6 @@ void Display::showDashboard(void) { lastBlinkChange_ms = lastDisplayUpdate_ms; blinkOnCycle = !blinkOnCycle; } - u8g2.clearBuffer(); u8g2.setDrawColor(1); diff --git a/src/display.h b/src/display.h index 1cc9eb9..70e8d0a 100644 --- a/src/display.h +++ b/src/display.h @@ -4,7 +4,7 @@ #include "config.h" // 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 diff --git a/src/main.cpp b/src/main.cpp index dc665e2..3beae8a 100644 --- a/src/main.cpp +++ b/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_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; //flag for saving data @@ -230,6 +230,7 @@ void checkForPowerOffRequest() { } if (millis() - powerOffButtonPressed_ts > 2000) { // pressed for longer than 2 seconds, now turn off + Serial.println(F("OFF")); ESP.deepSleep(ESP.deepSleepMax()); delay(200); } @@ -266,8 +267,20 @@ void loop(void) #endif #endif - fastclock.loop(); - radio.loop(); - display.showDashboard(); + // we do not want to call every task on every cycle: + switch (millis() & 0x03) { + case 0: + fastclock.loop(); + break; + case 1: + break; + case 2: + display.showDashboard(); + break; + case 3: + break; + } + yield(); + radio.loop(); // called always } diff --git a/src/radio.cpp b/src/radio.cpp index bfe2483..74c7d55 100644 --- a/src/radio.cpp +++ b/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 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]; #define MAX_CLIENTS_MANAGED 20 static uint8_t numberOfKnownClients = 0; static struct { uint8_t clientNetworkAddress; - char clientName[MAX_CLIENT_NAME_LEN]; + char clientName[MAX_CLIENT_NAME_LEN+1]; } client[MAX_CLIENTS_MANAGED]; static uint8_t nextClientNetworkAddress = 1; -void Radio::switchToSenderRole(void) -{ - Serial.println("*** changing to Tx role"); - rf24.openWritingPipe(addresses[1]); - rf24.openReadingPipe(1,addresses[0]); - rf24.stopListening(); - role = inTX; // Become the primary transmitter (ping out) +void Radio::checkRadioFailure(void) { + if (rf24.failureDetected) { + Serial.println(F("Radio failure detected!")); + rf24.failureDetected = 0; + radioInit(); + } } -void Radio::switchToReceiverRole(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) { +void Radio::radioInit(void) { display->addLogMessage("Start RF24 radio"); pinMode(PIN_NRF24_CSN, OUTPUT); pinMode(PIN_NRF24_CE, OUTPUT); rf24.begin(); - if (rf24.isChipConnected()) { display->addLogMessage("*** RF chip found"); } - else { display->addLogMessage("*** ERROR: RF chip not found!"); } + if (rf24.isChipConnected()) { + 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.setPALevel(RF24_PA_MAX); rf24.setDataRate(RF24_2MBPS); @@ -55,69 +51,103 @@ void Radio::begin(void) { rf24.openWritingPipe(addresses[0]); rf24.openReadingPipe(1, addresses[1]); rf24.startListening(); - Serial.println("*** Check"); - //rf24.printDetails(); rf24.powerUp(); // @TODO: real random seed! //randomSeed(analogRead(0)); //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(); } 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); broadcastMessage(msg, len); - Serial.print("# set channel "); Serial.println(clockChannel); + Serial.print(F("# set channel ")); Serial.println(clockChannel); rf24.setChannel(clockChannel); // switch back - Serial.println("# done"); + Serial.println(F("# done")); } void Radio::broadcastMessage(void *msg, int len) { uint8_t *m = (uint8_t *) msg; - Serial.print("*** Tx: ts="); Serial.print(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); + Serial.print(F("ts=")); Serial.println(millis()); switchToSenderRole(); - Serial.print("#1"); + if (!rf24.writeFast(msg, len, true /*multicast*/)) { sendFailedCounter++; - Serial.print("*** ERROR: failed to send msg type="); - Serial.print(*((char *) msg)); - Serial.print(" for to=0x"); - Serial.println(m[1], HEX); + Serial.println(F("*** ERROR: failed to send msg")); } - 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 if (millis() - pauseTime > 3) { 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 //delayMicroseconds(130); // This gives the PLL time to sync back up } - stopTime = millis(); - Serial.print("stopTime="); Serial.println(stopTime); + //stopTime = millis(); + //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 //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 - Serial.print("*** send finished, failed="); Serial.println(sendFailedCounter); 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) { diff --git a/src/radio.h b/src/radio.h index 4334c40..a393407 100644 --- a/src/radio.h +++ b/src/radio.h @@ -75,7 +75,7 @@ public: clockChannel = DEFAULT_CLOCK_CHANNEL; strncpy(clockName, "defclk", MAX_CLOCK_NAME_LEN); }; - + void setClockName(const char *_clockName) { strncpy(clockName, _clockName, MAX_CLOCK_NAME_LEN); }; @@ -94,13 +94,16 @@ public: void avoidChannelSwitchesFor_ms(unsigned int duration_ms); void listenOnlyFor_ms(unsigned int duration_ms); bool allowedToSendNow(void); + void checkRadioFailure(void); + void powerDown(void); private: Display *display; bool isMaster; + void radioInit(void); void switchToSenderRole(void); void switchToReceiverRole(void); bool inTX, inRX, role; - char clockName[MAX_CLOCK_NAME_LEN]; + char clockName[MAX_CLOCK_NAME_LEN+1]; void broadcastMessage(void *msg, int len); void broadcastMessageOnChannel(void *msg, int len, uint8_t channel); void broadcastClockAdvertisement(const char *clockName, uint8_t channel);