Click here to Skip to main content
15,884,177 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
I have repo code that I am working on as part of an internship that they have me trying to get to work with a sensor. When I load the code and upload it it doesn't seem to want to update the shadow onto AWS. The timestamp appears but the sensor readings don't show up (temp, humidity, etc). Can anyone look at the code that is familiar with AWS and help me figure out why this wont update? Please be aware that this is public repo that I am just working with and I didnt write this code. I am simply trying to make it work as part of my assignment for work.
C++
  1  #include <eeprom.h>
  2  #include <time.h>
  3  #include "adp5350.h"
  4  #include "certs.h"
  5  #include <wificlientsecure.h>
  6  #include <mqttclient.h>
  7  #include "ESPAsyncWebServer.h"
  8  #include <espmdns.h>
  9  
 10  #include <adafruit_bme280.h>
 11  
 12  // This include is for the AWS IOT library that we installed
 13  // This include is for Wifi functionality
 14  #include <wifi.h>
 15  
 16  // Wifi credentials
 17  char WIFI_SSID[]="Your WiFi SSID Here";
 18  char WIFI_PASSWORD[]="Your WiFi Password Here";
 19  
 20  // Connection status
 21  int status = WL_IDLE_STATUS;
 22  
 23  // Payload array to store thing shadow JSON document
 24  char payload[512];
 25  
 26  // Counter for iteration
 27  int counter = 0;
 28  
 29  // Definitions for BME280
 30  #define BME_SCL 4
 31  #define BME_SDA 19
 32  TwoWire I2CBME = TwoWire(0);
 33  Adafruit_BME280 bme;
 34  
 35  // Definition for ADP5350 PMIC
 36  ADP5350 adp;
 37  
 38  // Definitions for how long the process will sleep
 39  #define uS_TO_S_FACTOR 1000000ULL  /* Conversion factor for micro seconds to seconds */
 40  #define TIME_TO_SLEEP  30 * 60        /* Time ESP32 will go to sleep (in seconds) */
 41  
 42  #define WAKEUP_PIN 35
 43  
 44  // Definition for the ready pin and its interrupt routine
 45  struct READY_PIN {
 46    const uint8_t PIN;
 47    bool pressed;
 48  };
 49  
 50  READY_PIN ready_pin = { 16, false };
 51  
 52  void IRAM_ATTR isr() {
 53    ready_pin.pressed = true;
 54  }
 55  
 56  void IRAM_ATTR wakeup_isr() {
 57    Serial.println("wakeup pin pressed");
 58  }
 59  
 60  int startTimeMicros;
 61  int endTimeMicros;
 62  
 63  // The name of the device. This MUST match up with the name defined in the AWS console
 64  #define DEVICE_NAME "co2-sensor"
 65  
 66  // The MQTTT endpoint for the device (unique for each AWS account but shared amongst devices within the account)
 67  #define AWS_IOT_ENDPOINT "a1qphq4dovfqf6-ats.iot.us-east-2.amazonaws.com"
 68  
 69  // The MQTT topic that this device should publish to
 70  #define AWS_IOT_TOPIC "$aws/things/co2-sensor/shadow/update"
 71  //#define AWS_IOT_TOPIC "my/topic"
 72  
 73  // How many times we should attempt to connect to AWS
 74  #define AWS_MAX_RECONNECT_TRIES 50
 75  
 76  WiFiClientSecure net = WiFiClientSecure();
 77  MQTTClient client = MQTTClient(512);
 78  
 79  hw_timer_t * timer = NULL;
 80  portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
 81  AsyncWebServer server(80);
 82  bool sleepFlag = false;
 83  
 84  void IRAM_ATTR timerExpired() {
 85    //portENTER_CRITICAL_ISR(&timerMux);
 86    Serial.println("Timer Expired");
 87    detachInterrupt(digitalPinToInterrupt(35));
 88    sleepFlag = true;
 89    //portEXIT_CRITICAL_ISR(&timerMux);
 90  }
 91  
 92  // Getting CO2 from Blink
 93  int getco2() {
 94    ready_pin.pressed = false;
 95    adp.enableLDO(2, 1);
 96    int timeout = 0;
 97    while (ready_pin.pressed == false) {
 98      delay(1);
 99      timeout++;
100      if (timeout > 5000) {
101        Serial.println("nready timed out at 5 sec");
102        adp.enableLDO(2, 0);
103        return 0;
104      }
105    }
106  
107    Serial2.flush();
108    Serial2.print('Z', 1);
109    timeout = 0;
110    while (Serial2.available() <= 0) {
111      delay(1);
112      timeout++;
113      if (timeout > 3000) {
114        Serial.println("timed out");
115        adp.enableLDO(2, 0);
116        return 0;
117      }
118    }
119    byte co2array[Serial2.available()];
120    int i = 0;
121    while (Serial2.peek() != -1) {
122      co2array[i] = Serial2.read();
123      i++;
124    }
125    if (sizeof(co2array) < 3) {
126      Serial.println("response is incomplete");
127      adp.enableLDO(2, 0);
128      return 0;
129    }
130    if (co2array[2] != 0x55) {
131      Serial.println("response is not reliable");
132      adp.enableLDO(2, 0);
133      return 0;
134    }
135    int co2 = (co2array[0] << 8) | co2array[1];
136    
137    digitalWrite(15, HIGH);
138    ready_pin.pressed = false;
139    adp.enableLDO(2, 0);
140    
141    return co2;
142  }
143  
144  void connectToAWS()
145  {
146    // Configure WiFiClientSecure to use the AWS certificates we generated
147    net.setCACert(AWS_CERT_CA);
148    net.setCertificate(AWS_CERT_CRT);
149    net.setPrivateKey(AWS_CERT_PRIVATE);
150  
151    // Connect to the MQTT broker on the AWS endpoint we defined earlier
152    client.begin(AWS_IOT_ENDPOINT, 8883, net);
153  
154    // Try to connect to AWS and count how many times we retried.
155    int retries = 0;
156    Serial.print("Connecting to AWS IOT");
157  
158    while (!client.connect(DEVICE_NAME) && retries < AWS_MAX_RECONNECT_TRIES) {
159      Serial.print(".");
160      delay(100);
161      retries++;
162    }
163  
164    // Make sure that we did indeed successfully connect to the MQTT broker
165    // If not we just end the function and wait for the next loop.
166    if(!client.connected()){
167      Serial.println(" Timeout!");
168      return;
169    }
170  
171    // If we land here, we have successfully connected to AWS!
172    // And we can subscribe to topics and send messages.
173    Serial.println("Connected!");
174  }
175  
176  
177  // Go to sleep routine
178  void goToSleep() {
179    //Deep Sleep
180    WiFi.disconnect(true);
181    
182    Serial.println("Going to sleep now");
183    Serial.flush(); 
184  
185    //Get the processing time and subtract it from the sleep time so we can try and data log at more exact intervals
186    endTimeMicros = micros();
187    esp_sleep_enable_timer_wakeup(TIME_TO_SLEEP * uS_TO_S_FACTOR - (endTimeMicros - startTimeMicros));
188    esp_sleep_enable_ext0_wakeup(GPIO_NUM_35, 0);
189    esp_deep_sleep_start();
190  }
191  
192  
193  void updateShadow() {
194    // Connecting to AWS
195    connectToAWS();
196    
197    Serial.println("Sending data...");
198    // Turning on the LED
199    digitalWrite(18, HIGH);
200  
201    // Getting values
202    float temperature = bme.readTemperature();
203    float humidity = bme.readHumidity();
204    float pressure = bme.readPressure();
205    int co2 = getco2();
206    uint16_t battery = adp.batteryVoltage();
207  
208    // We want to make sure we're getting a CO2 Value
209    if (co2 == 0) {
210      adp.enableLDO(2,0);
211      delay(3000);
212      
213      return;
214    }
215    
216    char rule_payload[512];
217    time_t now = time(nullptr);
218    time_t delete_time = now + (5 * 24 * 60 * 60);
219    sprintf(rule_payload, "{\"state\":{\"reported\":{\"co2\":\" %d \", \"temperature\":\" %f \", \"humidity\":\" %f \", \"pressure\":\" %f \", \"battery\":\" %d \", \"name\":\" co2-sensor \", \"timestamp\":\" %d \", \"ttl\": \" %d \" }}}",co2,temperature,humidity,pressure,battery,now,delete_time);
220    Serial.println(rule_payload);
221    int err = client.publish(AWS_IOT_TOPIC, rule_payload);
222    if (err == 0) {
223      Serial.println("publish success");
224    } else {
225      Serial.println("publish fail");
226      Serial.print(err);
227      Serial.println("");
228    }
229    
230  
231    digitalWrite(18, LOW);
232    goToSleep();
233  }
234  
235  void enableSleepTimer() {
236    Serial.println("Enabling Timer");
237    timer = timerBegin(0,80,true);
238    timerAttachInterrupt(timer, &timerExpired, true);
239  
240    timerAlarmWrite(timer, 30000000, true);
241    timerAlarmEnable(timer);
242  }
243  
244  void disableSleepTimer() {
245    Serial.println("Disabling Timer");
246    timerAlarmDisable(timer);
247    timerDetachInterrupt(timer);
248    timerEnd(timer);
249  }
250  
251  void enterServerMode() {
252    Serial.println("Entering Server Mode for Measurements and Calibration");
253    
254    if (!MDNS.begin("esp32")) {
255      Serial.println("Error setting up MDNS responder!");
256      goToSleep();
257    }
258  
259    enableSleepTimer();
260    disableCore0WDT();
261    disableCore1WDT();
262    disableLoopWDT();
263  
264    server.on("/values/co2", HTTP_GET, [](AsyncWebServerRequest *request) {
265      Serial.println("Getting CO2");
266      disableSleepTimer();
267      enableSleepTimer();
268      digitalWrite(18, HIGH);
269      adp.enableLDO(2,0);
270      int co2 = getco2();
271      adp.enableLDO(2,0);
272      char payload[512];
273      time_t now = time(nullptr);
274      sprintf(payload, "{\"co2\":\" %d \", \"timestamp\":\" %d \" }",co2,now);
275      Serial.println(payload);
276      request->send(200, "text/plain", payload);
277      digitalWrite(18, LOW);
278    });
279  
280    server.on("/values/temperature", HTTP_GET   , [](AsyncWebServerRequest *request){
281      Serial.println("Getting Temperature");
282      disableSleepTimer();
283      enableSleepTimer();
284      digitalWrite(18, HIGH);
285      float temperature = bme.readTemperature();
286      char payload[512];
287      time_t now = time(nullptr);
288      sprintf(payload, "{\"temperature\":\" %f \", \"timestamp\":\" %d \" }",temperature,now);
289      Serial.println(payload);
290      request->send(200, "text/plain", payload);
291      digitalWrite(18, LOW);
292    });
293    
294     server.on("/values/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
295      Serial.println("Getting Humidity");
296      disableSleepTimer();
297      enableSleepTimer();
298      digitalWrite(18, HIGH);
299      float humidity = bme.readHumidity();
300      char payload[512];
301      time_t now = time(nullptr);
302      sprintf(payload, "{\"humidity\":\" %f \", \"timestamp\":\" %d \" }",humidity,now);
303      Serial.println(payload);
304      request->send(200, "text/plain", payload);
305      digitalWrite(18, LOW);
306    });
307    
308    server.on("/values/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
309      Serial.println("Getting Pressure");
310      disableSleepTimer();
311      enableSleepTimer();
312      digitalWrite(18, HIGH);
313      float pressure = bme.readPressure();
314      char payload[512];
315      time_t now = time(nullptr);
316      sprintf(payload, "{\"pressure\":\" %f \", \"timestamp\":\" %d \" }",pressure,now);
317      Serial.println(payload);
318      request->send(200, "text/plain", payload);
319      digitalWrite(18, LOW);
320    });
321  
322    server.on("/values/battery", HTTP_GET, [](AsyncWebServerRequest *request){
323      Serial.println("Getting Battery");
324      disableSleepTimer();
325      enableSleepTimer();
326      digitalWrite(18, HIGH);
327      uint16_t battery = adp.batteryVoltage();
328      char payload[512];
329      time_t now = time(nullptr);
330      sprintf(payload, "{\"battery\":\" %d \", \"timestamp\":\" %d \" }",battery,now);
331      Serial.println(payload);
332      request->send(200, "text/plain", payload);
333      digitalWrite(18, LOW);
334    });
335    
336    server.on("/values/all", HTTP_GET, [](AsyncWebServerRequest *request){
337      Serial.println("Getting All");
338      disableSleepTimer();
339      enableSleepTimer();
340      digitalWrite(18, HIGH);
341      int co2 = getco2();
342      float temperature = bme.readTemperature();
343      float humidity = bme.readHumidity();
344      float pressure = bme.readPressure();
345      uint16_t battery = adp.batteryVoltage();
346      char payload[512];
347      time_t now = time(nullptr);
348      sprintf(payload, "{\"co2\":\" %d \", \"temperature\":\" %f \", \"humidity\":\" %f \", \"pressure\":\" %f \", \"timestamp\":\" %d \", \"battery\":\" %d \"  }",co2,temperature,humidity,pressure,now,battery);
349      Serial.println(payload);
350      request->send(200, "text/plain", payload);
351      digitalWrite(18, LOW);
352    });
353  
354    server.on("/values/calibrate", HTTP_GET, [](AsyncWebServerRequest *request) {
355      Serial.println("Calibrating to Target");
356      disableSleepTimer();
357      enableSleepTimer();
358      digitalWrite(18, HIGH);
359      const char * calibrationPoint = request->getParam("cal")->value().c_str();
360      adp.enableLDO(2,1);
361      int timeout = 0;
362      while (ready_pin.pressed == false) {
363        delay(1);
364        timeout++;
365        if (timeout > 5000) {
366          Serial.println("nready timed out at 5 sec");
367          adp.enableLDO(2, 0);
368          return 0;
369        }
370      }
371      Serial2.print('Z',1);
372      delay(100);
373      if (Serial2.available() > 0) {
374        byte co2[Serial2.available()];
375        Serial2.readBytes(co2, Serial2.available());
376      }
377      delay(100);
378      char * cal_command = (char *)malloc(16);
379      sprintf(cal_command, "X %s\r\n", calibrationPoint);
380      Serial.print(cal_command);
381      Serial2.print(cal_command);
382      delay(100);
383      if (Serial2.available() > 0) {
384        byte cal_ret[Serial2.available()];
385        Serial2.readBytes(cal_ret, Serial2.available());
386      }
387      adp.enableLDO(2,0);
388      digitalWrite(18, LOW);
389    });
390  
391    server.on("/values/zero", HTTP_GET, [](AsyncWebServerRequest *request) {
392      Serial.println("Zero Calibrating");
393      disableSleepTimer();
394      enableSleepTimer();
395      digitalWrite(18, HIGH);
396      adp.enableLDO(2,1);
397      int timeout = 0;
398      while (ready_pin.pressed == false) {
399        delay(1);
400        timeout++;
401        if (timeout > 5000) {
402          Serial.println("nready timed out at 5 sec");
403          adp.enableLDO(2, 0);
404          return 0;
405        }
406      }
407      Serial2.print('Z',1);
408      delay(100);
409      if (Serial2.available() > 0) {
410        byte co2[Serial2.available()];
411        Serial2.readBytes(co2, Serial2.available());
412      }
413      delay(100);
414      Serial2.print("U\r\n");
415      delay(100);
416      if (Serial2.available() > 0) {
417        byte cal_ret[Serial2.available()];
418        Serial2.readBytes(cal_ret, Serial2.available());
419      }
420      adp.enableLDO(2,0);
421      digitalWrite(18, LOW);
422    });
423  
424    server.on("/values/ambient", HTTP_GET, [](AsyncWebServerRequest *request) {
425      Serial.println("Ambient Calibrating");
426      disableSleepTimer();
427      enableSleepTimer();
428      digitalWrite(18, HIGH);
429      adp.enableLDO(2,1);
430      int timeout = 0;
431      while (ready_pin.pressed == false) {
432        delay(1);
433        timeout++;
434        if (timeout > 5000) {
435          Serial.println("nready timed out at 5 sec");
436          adp.enableLDO(2, 0);
437          return 0;
438        }
439      }
440      Serial2.print('Z',1);
441      delay(100);
442      if (Serial2.available() > 0) {
443        byte co2[Serial2.available()];
444        Serial2.readBytes(co2, Serial2.available());
445      }
446      delay(100);
447      Serial2.print("G\r\n");
448      delay(100);
449      if (Serial2.available() > 0) {
450        byte cal_ret[Serial2.available()];
451        Serial2.readBytes(cal_ret, Serial2.available());
452      }
453      adp.enableLDO(2,0);
454      digitalWrite(18, LOW);
455    });
456    
457    server.begin();
458    MDNS.addService("co2sensor", "_tcp", 80);
459  }
460  
461  
462  void setup() {
463    // put your setup code here, to run once:
464    // Since we're using WiFi, we need to turn on the second LDO for extra current
465    adp.enableLDO(3, 1);
466    adp.setCharger(1);
467    adp.enableFuelGauge(1);
468    startTimeMicros = micros();
469    delay(1000);
470    // Reducing the CPU Frequency is better for power consumption, helping to extend battery life
471    setCpuFrequencyMhz(80);
472  
473    // Serial for debugging
474    Serial.begin(115200);
475    Serial.println("starting aws iot application");
476  
477    // Weird bug with Arduino Library, need to disconnect from WiFi before attempting to connect
478    WiFi.disconnect(true);
479    // initialise WiFi connection
480    int attempts = 0;
481    while (status != WL_CONNECTED) {
482      // After 5 failed attempts of trying to connect to the WiFI just go to sleep to conserve battery
483      if (attempts > 5) {
484        goToSleep();
485      }
486      Serial.print("Attempting to connect to Wifi network: ");
487      status = WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
488      delay(5000);
489    }
490    Serial.println("Connected to Wifi!");
491  
492    Serial.print("IP address: ");
493    Serial.println(WiFi.localIP());
494  
495    // Getting the current time in GMT
496    configTime(3 * 3600, 0, "pool.ntp.org", "time.nist.gov");
497    while (!time(nullptr)) {
498      delay(1000);
499    }
500  
501    // Setting up the LED
502    pinMode(18, OUTPUT);
503    digitalWrite(18, LOW);
504  
505    // Enable Charging and Fuel Gauge so we can see how much battery is left
506    adp.setCharger(1);
507    adp.enableFuelGauge(1);
508  
509    // Turn off the LDO to the sensor as a precautionary measure to make sure we are able to read
510    adp.enableLDO(2, 0);
511  
512    // Setting up the READY pin
513    delay(10);
514    pinMode(ready_pin.PIN, INPUT);
515    attachInterrupt(ready_pin.PIN, isr, RISING);
516    pinMode(WAKEUP_PIN, INPUT);
517    attachInterrupt(WAKEUP_PIN, wakeup_isr, FALLING);
518  
519    // Setting up the UART for the Sensor
520    Serial2.begin(38400, SERIAL_8N1, 14, 13);
521    delay(120);
522  
523    // Setting up the BME280
524    I2CBME.begin(BME_SDA,BME_SCL,100000);
525    unsigned status;
526    status = bme.begin(0x77,&I2CBME);
527    if (!status) {
528      Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
529      Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16);
530      Serial.print("        ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
531      Serial.print("   ID of 0x56-0x58 represents a BMP 280,\n");
532      Serial.print("        ID of 0x60 represents a BME 280.\n");
533      Serial.print("        ID of 0x61 represents a BME 680.\n");
534      
535      goToSleep();
536    }
537  
538    esp_sleep_wakeup_cause_t wakeup_reason;
539  
540    wakeup_reason = esp_sleep_get_wakeup_cause();
541  
542    switch(wakeup_reason)
543    {
544      case ESP_SLEEP_WAKEUP_EXT0 : enterServerMode(); break;
545      case ESP_SLEEP_WAKEUP_EXT1 : enterServerMode(); break;
546      case ESP_SLEEP_WAKEUP_TIMER : updateShadow(); break;
547      case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
548      case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
549      default : updateShadow(); break;
550    }
551  }
552  
553  void loop() {
554    // put your main code here, to run repeatedly:
555    if (sleepFlag) {
556      sleepFlag = false;
557      goToSleep();
558    }
559  }


What I have tried:

I tried online articles but I am not familiar with AWS. There are various ways to "fix" the issue but every time I try something it doesn't seem to work.
Posted
Updated 8-Feb-23 3:44am
v2
Comments
Andre Oosthuizen 8-Feb-23 10:03am    
Not sure if this will help - https://aws.amazon.com/blogs/compute/building-an-aws-iot-core-device-using-aws-serverless-and-an-esp32/

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900