Looking for a bulletproof/fully tested 433Mhz receiver/transmitter code?

PeterVF
Posts: 2
Joined: Sun Jan 12, 2020 10:01 am

Looking for a bulletproof/fully tested 433Mhz receiver/transmitter code?

Postby PeterVF » Sun Jan 12, 2020 10:30 am

Hi Guys,

My system reads sensor data over simple 433Mhz ASK routine and updates a web page on ESPAsyncWebServer. There is also a routine to read the time from NTP server.

I used two different libraries RFReceive: https://github.com/zeitgeist87/RFReceiver or RadioHead https://github.com/PaulStoffregen/RadioHead.

In both cases after a planned failure of Wifi (just switch it off on the access point) the system crashes with Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed)

If I don't initialize 433Mhz radio objects, failure of the WiFi does not influence the system. If WiFi will be available again the system recovers the WiFI connection and works as design.

Decoding of the crash dump does not provide any valuable information.

I read viewtopic.php?t=7684 and https://github.com/espressif/arduino-esp32/issues/855 that a part of the code within interrupt routine must always be in the ESP32's IRAM - is that correct? I tried to add IRAM_ATTR to few function handling radio parts without any success.

Question 1:
Can you share or recommend a bulletproof code that will receive data from "arduino micro simple ask 433Mhz transmitter"?

Question 2:
Can you recommend a patch/fix to my solution? For example, how can I identify a function, which requires to stay in IRAM (if it is the solution of my problem)?

Question 3:
Can i somehow disable (taking into consideration a slowdown of the performance) the caching? Is there something similar in Arduino / Platformio config to disable SPI_MASTER_ISR_IN_IRAM in ESP32 config settings?

I do appreciate all kind of your feedback!

... and the respective codes (I use VSC and with platformio add on, not a native arduino ide):
  1. #include <Arduino.h>
  2. #include "main.h"
  3. #include "index.h"
  4. #include "credentials.h"
  5. #include <NTPClient.h>
  6. #include <WiFiUdp.h>
  7. #include <TimeLib.h>
  8. #include <Timezone.h>
  9. #include "WiFi.h"
  10. #include <ESPmDNS.h>
  11. #include "ESPAsyncWebServer.h"
  12. #include <PinChangeInterruptHandler.h>
  13. #include <RFReceiver.h>
  14.  
  15. void updateJson();
  16. void blink();
  17. void printData(Tdata&);
  18. void printDateTime(Timezone, time_t, const char *);
  19.  
  20. // Central European Time (Frankfurt, Paris)
  21. WiFiUDP ntpUDP;
  22. NTPClient timeClient(ntpUDP, "europe.pool.ntp.org", 0);     /// get UTC
  23. TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};     // Central European Summer Time
  24. TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};       // Central European Standard Time
  25. Timezone CE(CEST, CET);
  26. TimeChangeRule *tcr;
  27.  
  28. time_t syncNTP();
  29. getExternalTime NtpTime = &syncNTP;
  30.  
  31. AsyncWebServer server(80);
  32. AsyncEventSource events("/events");
  33.  
  34. Tdata sensorsData[sensorNumber];
  35. char jsonData[370];
  36.  
  37. RFReceiver receiver(4);
  38.  
  39. void setup()
  40. {
  41.   for (int i=0; i<sensorNumber; i++) {
  42.     sensorsData[0].timeStamp = 0;
  43.     sensorsData[0].temperature = 0.0;
  44.     sensorsData[0].humidity = 0.0;
  45.     sensorsData[0].pressure = 0.0;
  46.     sensorsData[0].battery = 0.0;
  47. }
  48.  
  49.   pinMode(LED_BUILTIN, OUTPUT);
  50.   Serial.begin(115200);
  51.   delay(1000);
  52.    
  53.   WiFi.begin(ssid, password);
  54.   Serial.setDebugOutput(true);
  55.   PRINTS("Connecting to WiFi ");
  56.   while (WiFi.status() != WL_CONNECTED) {
  57.     PRINTS(".");
  58.     blink();
  59.    }
  60.   PRINTS(" connected\n");
  61.   PRINTS(WiFi.localIP());
  62.  
  63.   if (!MDNS.begin(localDomain)) {
  64.       PRINTS("Error setting up MDNS responder! Program Stoped\n");
  65.       while(1) {
  66.           blink();
  67.       }
  68.   }
  69.   PRINTS("mDNS responder started\n");
  70.  
  71.   timeClient.begin();
  72.   if (!timeClient.update()) {
  73.     PRINTS("1st NTP Update Failed. Program Stoped\n");
  74.       while(1) {
  75.           blink();
  76.       }    
  77.   };
  78.  
  79.   setSyncInterval(_setSyncInterval);
  80.   setSyncProvider(NtpTime);
  81.  
  82.  
  83.   server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
  84.     request->send(200, "text/html", index_html);
  85.   });
  86.  
  87.   server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request) {
  88.       request->send(404);
  89.     });
  90.  
  91.   events.onConnect([](AsyncEventSourceClient *client){
  92.     syncNTP();
  93.     updateJson();
  94.     client->send(jsonData,"data",millis());
  95.   });
  96.  
  97.   server.addHandler(&events);
  98.   server.begin();
  99.   MDNS.addService("http", "tcp", 80);
  100.  
  101.   receiver.begin();
  102.   PRINT("Max Buf: ", MAX_PACKAGE_SIZE);
  103.  
  104. }
  105. time_t last_utc=0;
  106.  
  107. void loop()
  108. {
  109.    uint8_t buf[MAX_PACKAGE_SIZE];
  110.    uint8_t buflen = sizeof(buf);
  111.    uint8_t sensorID;
  112.    byte senderId = 0;
  113.    byte packageId = 0;
  114.  
  115. //PP2
  116.     if (receiver.ready())
  117.     { // (driver.recv(buf, &buflen)) // Non-blocking
  118.       buflen = receiver.recvPackage(buf, &senderId, &packageId);
  119.       // Message with a good checksum received, dump it.
  120.         #if  DEBUG_ON
  121.          //driver.printBuffer("Got:", buf, buflen);
  122.          PRINT("Buf Len:", buflen); PRINTLN;
  123.          PRINT("Size of TData:", sizeof(Tdata)); PRINTLN;
  124.       #endif
  125.       if (buflen==dataSize) {
  126.         //data = *(Tdata *) buf;
  127.         sensorID=(*reinterpret_cast<Tdata *> (buf)).sensorID;
  128.         memcpy(&sensorsData[sensorID],&buf, sizeof(Tdata));
  129.         PRINT("Sensor ID: ", sensorID); PRINTLN;
  130.         sensorsData[sensorID].timeStamp = now();
  131.         updateJson();
  132.         events.send(jsonData,"data",millis());
  133.         printData(sensorsData[sensorID]);
  134.       }
  135.     }
  136.     if (now()-last_utc >= 1) {
  137.      last_utc = now();
  138.      updateJson();
  139.      events.send(jsonData,"data",millis());
  140.      //printDateTime(CE, last_utc,(timeStatus()==timeSet)? " OK":(timeStatus()==timeNeedsSync)? " Need Sync":" Not Set");
  141.  
  142.     }
  143. }
  144.  
  145. void updateJson() {
  146.   time_t  t = CE.toLocal(now(), &tcr);
  147.   time_t t0 = CE.toLocal(sensorsData[0].timeStamp, &tcr);
  148.   time_t t1 = CE.toLocal(sensorsData[1].timeStamp, &tcr);
  149.   time_t t2 = CE.toLocal(sensorsData[2].timeStamp, &tcr);
  150.   sprintf(jsonData,jsonStruc,
  151.       (timeStatus()==timeSet)? "white":(timeStatus()==timeNeedsSync)? "red":"yellow",
  152.       hour(t), minute(t), second(t), day(t), month(t), year(t),
  153.       hour(t0), minute(t0), second(t0), day(t0), month(t0), year(t0)%100U,
  154.       sensorsData[0].temperature,
  155.       sensorsData[0].humidity,
  156.       sensorsData[0].pressure,
  157.       sensorsData[0].battery,
  158.       hour(t1), minute(t1), second(t1), day(t1), month(t1), year(t1)%100U,  
  159.       sensorsData[1].temperature,
  160.       sensorsData[1].humidity,
  161.       sensorsData[1].pressure,
  162.       sensorsData[1].battery,
  163.       hour(t2), minute(t2), second(t2), day(t2), month(t2), year(t2)%100U,  
  164.       sensorsData[2].temperature,
  165.       sensorsData[2].humidity,
  166.       (float)sensorsData[0].counter);
  167. }
  168.  
  169. time_t syncNTP() {
  170.   bool NTPSyncOK=true;
  171.   PRINTS("\nNTP Syncing ... ");
  172.   // WiFi.printDiag(Serial);  
  173.   if (WiFi.isConnected()) {
  174.     NTPSyncOK = timeClient.forceUpdate();
  175.   } else {
  176.       PRINTS("\nRecovering WiFi connection\n");
  177.       //WiFi.mode(WIFI_STA);
  178.       WiFi.begin();
  179.       if (WiFi.isConnected()) {
  180.         NTPSyncOK = timeClient.forceUpdate();
  181.         //WiFi.mode(WIFI_OFF);
  182.       } else {
  183.         PRINTS("\nWIFI failed ...\n");
  184.         NTPSyncOK = false;
  185.       }
  186.   }
  187.   if (NTPSyncOK) {
  188.     PRINTS("NTP Sync OK\n");
  189.     return timeClient.getEpochTime();
  190.   }
  191.   else {
  192.     PRINTS("NTP Sync Failed\n");
  193.     return 0;
  194.   }
  195. }
  196.  
  197. void blink() {
  198.   digitalWrite(LED_BUILTIN, HIGH);
  199.   delay(500);
  200.   digitalWrite(LED_BUILTIN, LOW);
  201.   delay(500);
  202. }
  203.  
  204. // --------------------------------
  205. void printData(Tdata& data)
  206. {
  207.     PRINT ("Sensor      = ", data.sensorID);    PRINTLN;
  208.     PRINT ("Temperature = ", data.temperature); PRINTS(" *C\n");
  209.     PRINT ("Pressure    = ", data.pressure);    PRINTS(" hPa\n");
  210.     PRINT ("Humidity    = ", data.humidity);    PRINTS(" %\n");
  211.     PRINT ("Battery     = ", data.battery);     PRINTS(" V\n");
  212.     PRINTS("Time        = "); printDateTime(CE, data.timeStamp,(timeStatus()==timeSet)? " OK":(timeStatus()==timeNeedsSync)? " Need Sync":" Not Set");
  213.     PRINT ("Counter     = ", data.counter);     PRINTLN;
  214. }
  215.  
  216. void printDateTime(Timezone tz, time_t utc, const char *descr)
  217. {
  218.     char buf[40];
  219.     char m[4];    // temporary storage for month string (DateStrings.cpp uses shared buffer)
  220.     TimeChangeRule *tcr;        // pointer to the time change rule, use to get the TZ abbrev
  221.  
  222.     time_t t = tz.toLocal(utc, &tcr);
  223.     strcpy(m, monthShortStr(month(t)));
  224.     sprintf(buf, "%.2d:%.2d:%.2d %s %.2d %s %d %s",
  225.         hour(t), minute(t), second(t), dayShortStr(weekday(t)), day(t), m, year(t), tcr -> abbrev);
  226.     PRINTS(buf); PRINTS(descr); PRINTLN;
  227. }
[
  1. #include <Arduino.h>
  2. #define  DEBUG_ON 1
  3.  
  4. #define localDomain "pogoda"
  5. #define _setSyncInterval 15
  6.  
  7.  
  8. typedef struct
  9. {
  10.   float temperature;
  11.   float humidity;
  12.   float pressure;
  13.   float battery;
  14.   long  counter;
  15.   uint8_t  sensorID;
  16.   long  dummy;
  17.   time_t timeStamp;
  18. } Tdata;
  19.  
  20. const char jsonStruc[] PROGMEM = R"rawliteral(
  21. {"XC1":"%s",
  22. "clock":"%02d:%02d:%02d &nbsp; %02d:%02d:%02d",
  23. "time0":"%02d:%02d:%02d &nbsp; %02d:%02d:%02d",
  24. "temp0":"%.2f",
  25. "hum0" :"%.0f",
  26. "pres0":"%.0f",
  27. "bat0" :"%.2f",
  28. "time1":"%02d:%02d:%02d &nbsp; %02d:%02d:%02d",
  29. "temp1":"%.2f",
  30. "hum1" :"%.0f",
  31. "pres1":"%.0f",
  32. "bat1" :"%.2f",
  33. "time2":"%02d:%02d:%02d &nbsp; %02d:%02d:%02d",
  34. "temp2":"%.2f",
  35. "hum2" :"%.0f",
  36. "pres2":"%.0f"}
  37. )rawliteral";
  38.  
  39. const uint8_t sensorNumber = 3;
  40. const uint8_t dataSize = 21; // data frame size
  41.  
  42. #if  DEBUG_ON
  43. #define PRINT(s, v) { Serial.print(s); Serial.print(v); }    
  44. #define PRINTX(s, v) { Serial.print(s); Serial.print(v, HEX); }  
  45. #define PRINTS(s) Serial.print(s)  
  46. #define PRINTLN Serial.println()
  47. #else
  48. #define PRINT(s, v)  
  49. #define PRINTX(s, v)  
  50. #define PRINTS(s)    
  51. #define PRINTLN
  52. #endif
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html>
<html lang=pl>
<head>
....
</body>
</html>
)rawliteral";
  1.  

PeterVF
Posts: 2
Joined: Sun Jan 12, 2020 10:01 am

Re: Looking for a bulletproof/fully tested 433Mhz receiver/transmitter code?

Postby PeterVF » Mon Jan 13, 2020 9:33 am

I developed the solution to the "question 2": => https://github.com/adafruit/RadioHead/issues/39
Any comments and answers to 1 & 2 are still highly appreciated.
Best
PF

Who is online

Users browsing this forum: No registered users and 69 guests