Cannot get real sensor values from Thingspeak

Lauri Matikainen 2021-10-25
最新活动Lauri Matikainen 回复于 2021-10-27

Hi,

I am experiencing trouble in sending the actual sensor values to Thingspeak. I use a code template that I downloaded from a github repository https://github.com/mathworks/thingspeak-arduino/tree/master/examples/ESP32/WriteMultipleFields. The main issue is that I don't know how to fill out the source code to get real sensor values instead of random values.

I am using a DHT sensor, from which I want to measure both the temperature and the humidity. Here is what it looks like in the serial monitor after uploading the code to the ESP32 dev board.

Here is my code that I amended from the source template, and uploaded to the ESP32 board.

#include "DHT.h"
#include <WiFi.h>
#include "ThingSpeak.h"
// The wire is in pin 14 as required by the DHT-sensor, so it is written here:
#define DHTPIN 14    
// We use a DHT11-sensor
#define DHTTYPE DHT110
const char* ssid = "Koti_9BE9";   // your network SSID (name) 
const char* password = "XXXXXXX";   // your network password
WiFiClient  client;
// We write one (1) as the channel number. Assumably in that order in which they are in the MyChannels-page. 
unsigned long myChannelNumber = 1;
const char * myWriteAPIKey = "NW34MMOB5J1NGRL2";
// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 10000; // This specifies what kind of delay we want between measurements. DHT11
// The fastest measurement interval of DHT sensors is 2000 ms (2 seconds).
// An object from where values are brought from the DHT library
DHT dht(DHTPIN, DHTTYPE);
// Initialize our values. Writing down the values that need to be measured from DHT-sensors: 
// humidity h, temperature t, and temperature in fahrenheit-scale f
float h = dht.readHumidity();
float t = dht.readTemperature();
float f = dht.readTemperature(true);
String myStatus = "";
void setup() {
  Serial.begin(115200);
  Serial.println(F("DHT11 test!"));
    dht.begin();
    WiFi.mode(WIFI_STA);   
   ThingSpeak.begin(client);
  }
void loop() {
    delay(20000);
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    float f = dht.readTemperature(true);
    if (isnan(h) || isnan(t) || isnan(f)) {
      Serial.println(F("Failed to read from DHT sensor!"));
      return;
    }
    if(WiFi.status() != WL_CONNECTED){      
      Serial.print("Attempting to connect");
      while(WiFi.status() != WL_CONNECTED){
        WiFi.begin(ssid, password); 
        delay(5000);     
      } 
      Serial.println("\nConnected.");
    }
    float hif = dht.computeHeatIndex(f, h);
    float hic = dht.computeHeatIndex(t, h, false);
    Serial.print(F("Humidity: "));
    Serial.print(h);
    Serial.print(F("%  Temperature: "));
    Serial.print(t);
    Serial.print(F("°C "));
    Serial.print(f);
    Serial.print(F("°F  Heat index: "));
    Serial.print(hic);
    Serial.print(F("°C "));
    Serial.print(hif);
    Serial.println(F("°F"));
int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
if(x == 200){
  Serial.println("Channel update successful.");
}
else{
  Serial.println("Problem updating channel. HTTP error code " + String(x));
}
}

Many thanks for any advice.

Lauri

Lauri Matikainen
Lauri Matikainen 2021-10-26

Thank you for your reply!

How should I name my sensor variables? Can I figure it out by looking at the library of the sensor in question? In this DHT sensor case I should probably check them from DHT_U.h (DHT Unified Sensor) library, at home/(name)/.arduino/libraries. I looked for a proper variable declaration from the file, and after trial and error I found dht.temperature().getEvent(&event); and dht.humidity().getEvent(&event); to be valid, i.e. not unknown nor erroneous according to the Arduino IDE compiler. However, with these variables I seem to get only number ones (1) as sensor values to my Thingspeak channel (check the image). So I am still trying to find sensor variables that give me the real, measured sensor values.

Below is my edited WriteMultipleFields (added the DHT11-sensor, my ssid, password, write api key, channel number, and edited the sensor variables from random(0,100) to dht.temperature().getEvent(&event); and dht.humidity().getEvent(&event);.

#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>
#include <WiFi.h>
#include "secrets.h"
#include "ThingSpeak.h" // always include thingspeak header file after other header files and custom macros
/* Pin number for DHT11 data pin */
#define DHTPIN 14
//type of sensor in use:
#define DHTTYPE    DHT11   
DHT_Unified dht(DHTPIN, DHTTYPE);
uint32_t delayMS;
char ssid[] = "mokkula";   // your network SSID (name) 
char pass[] = "XXXXXXXX";   // your network password
int keyIndex = 0;            // your network key Index number (needed only for WEP)
WiFiClient  client;
unsigned long myChannelNumber = '123456';
const char * myWriteAPIKey = "letters";
// Initialize our values
//sensor_t sensor;
sensors_event_t event;
float number1 = dht.temperature().getEvent(&event);
float number2 = dht.humidity().getEvent(&event);
//int number3 = random(0,100);
//int number4 = random(0,100);
String myStatus = "";
void setup() {
  Serial.begin(115200);  //Initialize serial
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo native USB port only
  }
    WiFi.mode(WIFI_STA);   
    ThingSpeak.begin(client);  // Initialize ThingSpeak
  }
void loop() {
    // Connect or reconnect to WiFi
    if(WiFi.status() != WL_CONNECTED){
      Serial.print("Attempting to connect to SSID: ");
      Serial.println(SECRET_SSID);
      while(WiFi.status() != WL_CONNECTED){
        WiFi.begin(ssid, pass);  // Connect to WPA/WPA2 network. Change this line if using open or WEP network
        Serial.print(".");
        delay(5000);     
      } 
      Serial.println("\nConnected.");
    }
    // set the fields with the values
    ThingSpeak.setField(1, number1);
    ThingSpeak.setField(2, number2);
    //ThingSpeak.setField(3, number3);
    //ThingSpeak.setField(4, number4);
    // figure out the status message
    if(number1 > number2){
      myStatus = String("field1 is greater than field2"); 
    }
    else if(number1 < number2){
      myStatus = String("field1 is less than field2");
    }
    else{
      myStatus = String("field1 equals field2");
    }
    // set the status
    ThingSpeak.setStatus(myStatus);
    // write to the ThingSpeak channel
    int x = ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
    if(x == 200){
      Serial.println("Channel update successful.");
    }
    else{
      Serial.println("Problem updating channel. HTTP error code " + String(x));
    }
    // change the values
    number1++;
    if(number1 > 99){
      number1 = 0;
    }
    number2 = random(0,100);
    //number3 = random(0,100);
    //number4 = random(0,100);
    delay(20000); // Wait 20 seconds to update the channel again
  }
Christopher Stapels
Christopher Stapels 2021-10-27 (编辑时间: 2021-10-27)

I'm not clear what you mean by naming your sensor variables, but I would say to find an example and copy what they do. In you code, move this into your loop().

number1 = dht.temperature().getEvent(&event);
number2 = dht.humidity().getEvent(&event);

keep this in your variables declaration

    float number1;
    float number2;

I'm not 100% sure of the dht syntax there, but if its correct, that says to read the present temperature. You want to read the temperature in each loop, not just at initialization. However, I bet the sensor isn't even warmed up then, which is perhaps why you get the value of 1. I'm not sure why the value isn't increasing in each loop, but it could be because it is a float type and not an integer. ++ operator isn't defined for float types.

Lauri Matikainen
Lauri Matikainen 2021-10-27

I'm neither sure about the dht syntax. Previously I had it as

float number1 = dht.temperature().getSensor(&sensor);
float number1 = dht.humidity().getSensor(&sensor);

but the compiler would always return an apparently insurmountable error message as follows: "void value not ignored as it ought to be." For some reason, I got it through when I changed the "sensors" to "events". However, the "events" appear to give me only the value of 1. And they seem to do so irrespective of whether the commands are inside the loop or not.

I have two DHT libraries in my .arduino15/libraries -folder. I suspect that either one of them contains the syntax of the DHT11 sensor for temperature and humidity. I have tried the following:

  • dht.readTemperature() and dht.readHumidity(): "class 'DHT_Unified' has no member named 'readTemperature'; did you mean 'Temperature'?
  • dht.temperature() and dht.humidity(): "cannot convert 'DHT_Unified::Temperature' to 'int' in initialization (or float if I use float)
  • dht.temperature().getSensor(&sensor) and dht.humidity().getSensor(&sensor): "void value not ignored as it ought to be",
  • dht.temperature().getEvent(&event) and dht.temperature().getEvent(&event): ran okay but resulted in the values of 1 at Thingspeak.

I think the secret for the correct syntax for getting the sensor measurements must lie somewhere in these libraries:

DHT.h: #ifndef DHT_H #define DHT_H

#include "Arduino.h"
/* Uncomment to enable printing out nice debug messages. */
//#define DHT_DEBUG
#define DEBUG_PRINTER                                                          \
  Serial /**< Define where debug output will be printed.                       \
          */
/* Setup debug printing macros. */
#ifdef DHT_DEBUG
#define DEBUG_PRINT(...)                                                       \
  { DEBUG_PRINTER.print(__VA_ARGS__); }
#define DEBUG_PRINTLN(...)                                                     \
  { DEBUG_PRINTER.println(__VA_ARGS__); }
#else
#define DEBUG_PRINT(...)                                                       \
  {} /**< Debug Print Placeholder if Debug is disabled */
#define DEBUG_PRINTLN(...)                                                     \
  {} /**< Debug Print Line Placeholder if Debug is disabled */
#endif
/* Define types of sensors. */
static const uint8_t DHT11{11};  /**< DHT TYPE 11 */
static const uint8_t DHT12{12};  /**< DHY TYPE 12 */
static const uint8_t DHT21{21};  /**< DHT TYPE 21 */
static const uint8_t DHT22{22};  /**< DHT TYPE 22 */
static const uint8_t AM2301{21}; /**< AM2301 */
#if defined(TARGET_NAME) && (TARGET_NAME == ARDUINO_NANO33BLE)
#ifndef microsecondsToClockCycles
/*!
 * As of 7 Sep 2020 the Arduino Nano 33 BLE boards do not have
 * microsecondsToClockCycles defined.
 */
#define microsecondsToClockCycles(a) ((a) * (SystemCoreClock / 1000000L))
#endif
#endif
/*!
 *  @brief  Class that stores state and functions for DHT
 */
class DHT {
public:
  DHT(uint8_t pin, uint8_t type, uint8_t count = 6);
  void begin(uint8_t usec = 55);
  float readTemperature(bool S = false, bool force = false);
  float convertCtoF(float);
  float convertFtoC(float);
  float computeHeatIndex(bool isFahrenheit = true);
  float computeHeatIndex(float temperature, float percentHumidity,
                         bool isFahrenheit = true);
  float readHumidity(bool force = false);
  bool read(bool force = false);
private:
  uint8_t data[5];
  uint8_t _pin, _type;
#ifdef __AVR
  // Use direct GPIO access on an 8-bit AVR so keep track of the port and
  // bitmask for the digital pin connected to the DHT.  Other platforms will use
  // digitalRead.
  uint8_t _bit, _port;
#endif
  uint32_t _lastreadtime, _maxcycles;
  bool _lastresult;
  uint8_t pullTime; // Time (in usec) to pull up data line before reading
    uint32_t expectPulse(bool level);
  };
/*!
 *  @brief  Class that defines Interrupt Lock Avaiability
 */
class InterruptLock {
public:
  InterruptLock() {
#if !defined(ARDUINO_ARCH_NRF52)
    noInterrupts();
#endif
  }
  ~InterruptLock() {
#if !defined(ARDUINO_ARCH_NRF52)
    interrupts();
#endif
  }
};
#endif

DHT_U.h:

#ifndef DHT_U_H
#define DHT_U_H
#include <Adafruit_Sensor.h>
#include <DHT.h>
#define DHT_SENSOR_VERSION 1 /**< Sensor Version */
/*!
 *  @brief  Class that stores state and functions for interacting with
 * DHT_Unified.
 */
class DHT_Unified {
public:
  DHT_Unified(uint8_t pin, uint8_t type, uint8_t count = 6,
              int32_t tempSensorId = -1, int32_t humiditySensorId = -1);
  void begin();
    /*!
     *  @brief  Class that stores state and functions about Temperature
     */
    class Temperature : public Adafruit_Sensor {
    public:
      Temperature(DHT_Unified *parent, int32_t id);
      bool getEvent(sensors_event_t *event);
      void getSensor(sensor_t *sensor);
    private:
      DHT_Unified *_parent;
      int32_t _id;
    };
    /*!
     *  @brief  Class that stores state and functions about Humidity
     */
    class Humidity : public Adafruit_Sensor {
    public:
      Humidity(DHT_Unified *parent, int32_t id);
      bool getEvent(sensors_event_t *event);
      void getSensor(sensor_t *sensor);
    private:
      DHT_Unified *_parent;
      int32_t _id;
    };
    /*!
     *  @brief  Returns temperature stored in _temp
     *  @return Temperature value
     */
    Temperature temperature() { return _temp; }
    /*!
     *  @brief  Returns humidity stored in _humidity
     *  @return Humidity value
     */
    Humidity humidity() { return _humidity; }
private:
  DHT _dht;
  uint8_t _type;
  Temperature _temp;
  Humidity _humidity;
    void setName(sensor_t *sensor);
    void setMinDelay(sensor_t *sensor);
  };
#endif
Christopher Stapels
Christopher Stapels 2021-10-26

You need to use setField(filednum,value) first. In the ThingSpeak library, look at the write multiple fields example in the thingspeak examples under esp32 for the correct syntax.

标签

尚未输入任何标签。