Advertisement
Guest User

Ultra Low Power ESP32C3 datalogger

a guest
Nov 17th, 2024
31
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "esp_wifi.h"
  2. #include "driver/adc.h"
  3.  
  4.  
  5. #include <WiFi.h>
  6. #include "nvs_flash.h"
  7. #include <SimplePgSQL.h>
  8. #include "time.h"
  9. //#include <ESP32Time.h>
  10. #include "SPI.h"
  11.  
  12.  
  13. #include <Adafruit_BMP280.h>
  14. #include <Adafruit_AHTX0.h>
  15.  
  16. #include <Adafruit_GFX.h>
  17. #include <Adafruit_PCD8544.h>
  18. #include <ADS1115_WE.h>
  19. #include <Wire.h>
  20. bool isSetNtp = false;                                 // flag to indicate if we had a successful NTP call
  21.             // test variable in RTC memory
  22.  
  23. // callback to check if NTP was called
  24. #include "esp_sntp.h"
  25. void cbSyncTime(struct timeval *tv) { // callback function to show when NTP was synchronized
  26.   Serial.println("NTP time synched");
  27.   isSetNtp = true;
  28. }
  29.  
  30. #define I2C_ADDRESS 0x48
  31.  
  32. ADS1115_WE adc = ADS1115_WE(I2C_ADDRESS);
  33.  
  34.  Adafruit_PCD8544 display = Adafruit_PCD8544(0, 1, 2);
  35.  
  36.  
  37. Adafruit_AHTX0 aht;
  38. Adafruit_BMP280 bmp;
  39.  
  40. //ESP32Time rtc(0);  // offset in seconds
  41.  
  42. int16_t adc0, adc1, adc2, adc3;
  43. float volts0, volts1, volts2, volts3;
  44. float abshum;
  45.  
  46.  
  47.  
  48. #include <Preferences.h>
  49. Preferences prefs;
  50.   struct tm timeinfo;
  51.  
  52. RTC_DATA_ATTR int readingCnt = -1;
  53. RTC_DATA_ATTR int arrayCnt = 0;
  54.  
  55. int i;
  56.  
  57. typedef struct {
  58.   float temp1;
  59.   float temp2;
  60.   unsigned long   time;
  61.   float volts;
  62.   float pres;
  63. } sensorReadings;
  64.  
  65. #define maximumReadings 360 // The maximum number of readings that can be stored in the available space
  66. #define sleeptimeSecs   30
  67. #define WIFI_TIMEOUT 20000
  68. #define TIME_TIMEOUT 20000
  69.  
  70. RTC_DATA_ATTR sensorReadings Readings[maximumReadings];
  71.  
  72. const char* ntpServer = "pool.ntp.org";
  73. const long gmtOffset_sec = -18000;  //Replace with your GMT offset (secs)
  74. const int daylightOffset_sec = 3600;   //Replace with your daylight offset (secs)
  75. int hours, mins, secs;
  76. float tempC;
  77. bool sent = false;
  78.  
  79.  
  80. IPAddress PGIP(x,x,x,x);
  81.  
  82. const char ssid[] = "xxxx";      //  your network SSID (name)
  83. const char pass[] = "xxxx";      // your network password
  84.  
  85. const char user[] = "xxxx";       // your database user
  86. const char password[] = "xxxx";   // your database password
  87. const char dbname[] = "xxxx";         // your database name
  88.  
  89.  
  90. int WiFiStatus;
  91. WiFiClient client;
  92.  
  93.  
  94.  
  95.  
  96.  
  97. /////////////////////////
  98. //POSTGRESQL CODE BEGIN//
  99. /////////////////////////
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106. char buffer[1024];
  107. PGconnection conn(&client, 0, 1024, buffer);
  108.  
  109. char tosend[192];
  110. String tosendstr;
  111.  
  112.  
  113. #ifndef USE_ARDUINO_ETHERNET
  114. void checkConnection()
  115. {
  116.     int status = WiFi.status();
  117.     if (status != WL_CONNECTED) {
  118.         if (WiFiStatus == WL_CONNECTED) {
  119.             Serial.println("Connection lost");
  120.             WiFiStatus = status;
  121.         }
  122.     }
  123.     else {
  124.         if (WiFiStatus != WL_CONNECTED) {
  125.             Serial.println("Connected");
  126.             WiFiStatus = status;
  127.         }
  128.     }
  129. }
  130.  
  131. #endif
  132.  
  133. static PROGMEM const char query_rel[] = "\
  134. SELECT a.attname \"Column\",\
  135.  pg_catalog.format_type(a.atttypid, a.atttypmod) \"Type\",\
  136.  case when a.attnotnull then 'not null ' else 'null' end as \"null\",\
  137.  (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)\
  138.   FROM pg_catalog.pg_attrdef d\
  139.   WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) \"Extras\"\
  140. FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c\
  141. WHERE a.attrelid = c.oid AND c.relkind = 'r' AND\
  142. c.relname = %s AND\
  143. pg_catalog.pg_table_is_visible(c.oid)\
  144. AND a.attnum > 0 AND NOT a.attisdropped\
  145.    ORDER BY a.attnum";
  146.  
  147. static PROGMEM const char query_tables[] = "\
  148. SELECT n.nspname as \"Schema\",\
  149.  c.relname as \"Name\",\
  150.  CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' THEN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' END as \"Type\",\
  151.  pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\"\
  152. FROM pg_catalog.pg_class c\
  153.     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\
  154. WHERE c.relkind IN ('r','v','m','S','f','')\
  155.      AND n.nspname <> 'pg_catalog'\
  156.      AND n.nspname <> 'information_schema'\
  157.      AND n.nspname !~ '^pg_toast'\
  158.  AND pg_catalog.pg_table_is_visible(c.oid)\
  159. ORDER BY 1,2";
  160.  
  161. int pg_status = 0;
  162.  
  163. void doPg(void)
  164. {
  165.     char *msg;
  166.     int rc;
  167.     if (!pg_status) {
  168.         conn.setDbLogin(PGIP,
  169.             user,
  170.             password,
  171.             dbname,
  172.             "utf8");
  173.         pg_status = 1;
  174.         return;
  175.     }
  176.  
  177.     if (pg_status == 1) {
  178.         rc = conn.status();
  179.         if (rc == CONNECTION_BAD || rc == CONNECTION_NEEDED) {
  180.             char *c=conn.getMessage();
  181.             if (c) Serial.println(c);
  182.             pg_status = -1;
  183.         }
  184.         else if (rc == CONNECTION_OK) {
  185.             pg_status = 2;
  186.             Serial.println("Enter query");
  187.         }
  188.         return;
  189.     }
  190.     if (pg_status == 2) {
  191.         if (!Serial.available()) return;
  192.         char inbuf[192];
  193.         int n = Serial.readBytesUntil('\n',inbuf,191);
  194.         while (n > 0) {
  195.             if (isspace(inbuf[n-1])) n--;
  196.             else break;
  197.         }
  198.         inbuf[n] = 0;
  199.  
  200.         if (!strcmp(inbuf,"\\d")) {
  201.             if (conn.execute(query_tables, true)) goto error;
  202.             Serial.println("Working...");
  203.             pg_status = 3;
  204.             return;
  205.         }
  206.         if (!strncmp(inbuf,"\\d",2) && isspace(inbuf[2])) {
  207.             char *c=inbuf+3;
  208.             while (*c && isspace(*c)) c++;
  209.             if (!*c) {
  210.                 if (conn.execute(query_tables, true)) goto error;
  211.                 Serial.println("Working...");
  212.                 pg_status = 3;
  213.                 return;
  214.             }
  215.             if (conn.executeFormat(true, query_rel, c)) goto error;
  216.             Serial.println("Working...");
  217.             pg_status = 3;
  218.             return;
  219.         }
  220.  
  221.         if (!strncmp(inbuf,"exit",4)) {
  222.             conn.close();
  223.             Serial.println("Thank you");
  224.             pg_status = -1;
  225.             return;
  226.         }
  227.         if (conn.execute(inbuf)) goto error;
  228.         Serial.println("Working...");
  229.         pg_status = 3;
  230.     }
  231.     if (pg_status == 3) {
  232.         rc=conn.getData();
  233.         if (rc < 0) goto error;
  234.         if (!rc) return;
  235.         if (rc & PG_RSTAT_HAVE_COLUMNS) {
  236.             for (i=0; i < conn.nfields(); i++) {
  237.                 if (i) Serial.print(" | ");
  238.                 Serial.print(conn.getColumn(i));
  239.             }
  240.             Serial.println("\n==========");
  241.         }
  242.         else if (rc & PG_RSTAT_HAVE_ROW) {
  243.             for (i=0; i < conn.nfields(); i++) {
  244.                 if (i) Serial.print(" | ");
  245.                 msg = conn.getValue(i);
  246.                 if (!msg) msg=(char *)"NULL";
  247.                 Serial.print(msg);
  248.             }
  249.             Serial.println();
  250.         }
  251.         else if (rc & PG_RSTAT_HAVE_SUMMARY) {
  252.             Serial.print("Rows affected: ");
  253.             Serial.println(conn.ntuples());
  254.         }
  255.         else if (rc & PG_RSTAT_HAVE_MESSAGE) {
  256.             msg = conn.getMessage();
  257.             if (msg) Serial.println(msg);
  258.         }
  259.         if (rc & PG_RSTAT_READY) {
  260.             pg_status = 2;
  261.             Serial.println("Enter query");
  262.         }
  263.     }
  264.     return;
  265. error:
  266.     msg = conn.getMessage();
  267.     if (msg) Serial.println(msg);
  268.     else Serial.println("UNKNOWN ERROR");
  269.     if (conn.status() == CONNECTION_BAD) {
  270.         Serial.println("Connection is bad");
  271.         pg_status = -1;
  272.     }
  273. }
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281.  
  282. /////////////////////////
  283. //POSTGRESQL CODE END  //
  284. /////////////////////////
  285.  
  286.  
  287.  
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294. void gotosleep() {
  295.       //WiFi.disconnect();
  296.       delay(1);
  297.       esp_sleep_enable_timer_wakeup(sleeptimeSecs * 1000000ULL);
  298.       delay(1);
  299.       esp_deep_sleep_start();
  300.       delay(1000);
  301. }
  302.  
  303.  
  304. void killwifi() {
  305.             WiFi.disconnect();
  306. }
  307.  
  308. void transmitReadings() {
  309.   i=0;
  310.           while (i<maximumReadings) {
  311.             doPg();
  312.             display.clearDisplay();   // clears the screen and buffer
  313.             display.setCursor(0,0);
  314.             display.print("TXing #");
  315.             display.print(i);
  316.             display.print(",");
  317.             display.println(arrayCnt);
  318.             display.display();
  319.  
  320.             if ((pg_status == 2) && (i<maximumReadings)){
  321.               tosendstr = "insert into burst values (42,1," + String(Readings[i].time) + "," + String(Readings[i].temp1,3) + "), (42,2," + String(Readings[i].time) + "," + String(Readings[i].volts,4) + "), (42,3," + String(Readings[i].time) + "," + String(Readings[i].temp2,3) + "), (42,4," + String(Readings[i].time) + "," + String(Readings[i].pres,3) + ")";
  322.               conn.execute(tosendstr.c_str());
  323.               pg_status = 3;
  324.               delay(10);
  325.               i++;
  326.             }
  327.             delay(10);
  328.            
  329.           }
  330.          
  331. }
  332.  
  333.  
  334. float readChannel(ADS1115_MUX channel) {
  335.   float voltage = 0.0;
  336.   adc.setCompareChannels(channel);
  337.   adc.startSingleMeasurement();
  338.   while(adc.isBusy()){}
  339.   voltage = adc.getResult_V(); // alternative: getResult_mV for Millivolt
  340.   return voltage;
  341. }
  342.  
  343.  
  344.  
  345. void initTime(String timezone){
  346.   configTzTime(timezone.c_str(), "time.cloudflare.com", "pool.ntp.org", "time.nist.gov");
  347.  
  348.   while ((!isSetNtp) && (millis() < TIME_TIMEOUT)) {
  349.         delay(250);
  350.         display.print(".");
  351.         display.display();
  352.         }
  353.  
  354. }
  355.  
  356.  
  357. void setup(void)
  358. {
  359.   sntp_set_time_sync_notification_cb(cbSyncTime);
  360.   display.begin(20, 7);
  361.  
  362.  
  363.   display.display(); // show splashscreen
  364.   display.clearDisplay();   // clears the screen and buffer
  365.   display.setTextSize(1);
  366.   display.setTextColor(BLACK);
  367.   display.setCursor(0,0);
  368.   display.setTextWrap(true);
  369.   if ((readingCnt == -1)) {
  370.  
  371.       WiFi.mode(WIFI_STA);
  372.       WiFi.begin((char *)ssid, pass);
  373.       display.print("Connecting to get time...");
  374.       display.display();
  375.       while ((WiFi.status() != WL_CONNECTED) && (millis() < WIFI_TIMEOUT)) {
  376.         delay(250);
  377.         display.print(".");
  378.         display.display();
  379.       }
  380.           display.clearDisplay();   // clears the screen and buffer
  381.           display.setCursor(0,0);
  382.           if (WiFi.status() == WL_CONNECTED) {
  383.             display.print("Connected. Getting time...");
  384.           }
  385.           else
  386.           {
  387.             display.print("Connection timed out. :(");
  388.           }
  389.           display.display();
  390.           initTime("EST5EDT,M3.2.0,M11.1.0");
  391.           //rtc.setTimeStruct(timeinfo);
  392.           killwifi();
  393.           readingCnt = 0;
  394.           delay(1);
  395.           readingCnt = 0;
  396.           delay(1);
  397.  
  398.           esp_sleep_enable_timer_wakeup(1 * 1000000);
  399.           esp_deep_sleep_start();
  400.           delay(1000);
  401.   }
  402.  
  403.   Wire.begin();
  404.   adc.init();
  405.   adc.setVoltageRange_mV(ADS1115_RANGE_4096);
  406.  
  407.   float volts0 = 2.0 * readChannel(ADS1115_COMP_3_GND);
  408.  
  409.  
  410.   bmp.begin();
  411.   bmp.setSampling(Adafruit_BMP280::MODE_FORCED,     /* Operating Mode. */
  412.                   Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
  413.                   Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
  414.                   Adafruit_BMP280::FILTER_X16,      /* Filtering. */
  415.                   Adafruit_BMP280::STANDBY_MS_500);
  416.   bmp.takeForcedMeasurement();
  417.   float presread = bmp.readPressure() / 100.0;
  418.   aht.begin();
  419.   sensors_event_t humidity, temp;
  420.   aht.getEvent(&humidity, &temp);
  421.   abshum = (6.112 * pow(2.71828, ((17.67 * temp.temperature)/(temp.temperature + 243.5))) * humidity.relative_humidity * 2.1674)/(273.15 + temp.temperature); //calculate absolute humidity
  422.   display.print("Time: ");
  423.   setenv("TZ","EST5EDT,M3.2.0,M11.1.0",1);  //  Now adjust the TZ.  Clock settings are adjusted to show the new local time
  424.   tzset();
  425.   getLocalTime(&timeinfo);
  426.   int hr12 = timeinfo.tm_hour;
  427.   String AMPM;
  428.   if (hr12 > 12) {
  429.     hr12 -= 12;
  430.     AMPM = "PM";
  431.   }
  432.   else {AMPM = "AM";}
  433.  
  434.   display.print(hr12);
  435.   if (timeinfo.tm_min < 10) {display.print(":0");}
  436.   else {display.print(":");}
  437.  
  438.   display.print(timeinfo.tm_min);
  439.   display.println(AMPM);
  440.  
  441.   display.print(temp.temperature, 2);
  442.   display.print("C ");
  443.   display.print(humidity.relative_humidity, 1);
  444.   display.println("%");
  445.  
  446.   display.print("Abs: ");
  447.   display.print(abshum, 2);
  448.   display.println("g");
  449.  
  450.   display.print("Batt: ");
  451.   display.print(volts0, 4);
  452.   display.println("v");
  453.  
  454.   display.print("Pres: ");
  455.   display.print(presread, 2);
  456.   display.println("m");
  457.  
  458.   display.print("R");
  459.   display.print(readingCnt);
  460.   display.print("/");
  461.   display.print(maximumReadings);
  462.   display.print(" A");
  463.   display.print(arrayCnt);
  464.   display.display();
  465.  
  466.   //Store the sensor readings in the struct we declared earlier, using the RTC-ram integer "readingCnt" to increment the array index by one each reading
  467.   Readings[readingCnt].temp1 = temp.temperature;    // Units °C
  468.   Readings[readingCnt].temp2 = abshum; //humidity is temp2
  469.   Readings[readingCnt].time = mktime(&timeinfo);
  470.   Readings[readingCnt].volts = volts0;
  471.   Readings[readingCnt].pres = presread;
  472.  
  473.  
  474.  
  475.   ++readingCnt;
  476.   delay(1);
  477.  
  478.   if (readingCnt >= maximumReadings) {
  479.  
  480.       prefs.begin("stuff", false, "nvs2"); //open up a prefs on the custom NVS2 partition
  481.       WiFi.mode(WIFI_STA);
  482.       WiFi.begin((char *)ssid, pass);
  483.       display.clearDisplay();   // clears the screen and buffer
  484.       display.setCursor(0,0);
  485.       display.print("Connecting to transmit...");
  486.       display.display();
  487.       while ((WiFi.status() != WL_CONNECTED) && (millis() < WIFI_TIMEOUT)) {
  488.         delay(250);
  489.         display.print(".");
  490.         display.display();
  491.       }
  492.  
  493.       if ((WiFi.status() != WL_CONNECTED) && (millis() >= WIFI_TIMEOUT)) {
  494.  
  495.         delay(1);
  496.         ++arrayCnt;
  497.         delay(1);
  498.         prefs.putBytes(String(arrayCnt).c_str(), &Readings, sizeof(Readings));
  499.         readingCnt = 0;
  500.         killwifi();
  501.         esp_sleep_enable_timer_wakeup(1 * 1000000);
  502.         esp_deep_sleep_start();
  503.         delay(1000);
  504.       }
  505.       display.clearDisplay();   // clears the screen and buffer
  506.       display.setCursor(0,0);
  507.       display.print("Connected. Transmitting #0");
  508.       display.display();
  509.       transmitReadings();
  510.       while (arrayCnt > 0) {
  511.         display.clearDisplay();   // clears the screen and buffer
  512.         display.setCursor(0,0);
  513.         display.print("Transmitting #");
  514.         display.print(arrayCnt);
  515.         display.display();
  516.         delay(50);
  517.         prefs.getBytes(String(arrayCnt).c_str(), &Readings, sizeof(Readings));
  518.         arrayCnt--;
  519.         transmitReadings();
  520.       }
  521.       arrayCnt = 0;
  522.       readingCnt = -1;
  523.       delay(1);
  524.       arrayCnt = 0;
  525.       readingCnt = -1;
  526.       delay(1);
  527.       display.clearDisplay();   // clears the screen and buffer
  528.       display.setCursor(0,0);
  529.       display.print("Done.  Closing connection...");
  530.       display.display();
  531.       conn.close();
  532.  
  533.       killwifi();
  534.  
  535.       ESP.restart();
  536.   }
  537.  
  538.  
  539.         gotosleep();
  540.  
  541. }
  542.  
  543.  
  544. void loop()
  545. {
  546. gotosleep();
  547. }
  548.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement