Community
OpenEnergyMonitor

Community

EmonESP as a TH node


(Dave) #1

After getting my IoTaWatt and with how easy it was to set up, I got to thinking about the idea of using an ESP8266 based device to create a WiFi enabled T/H node. I got to thinking about adapting the IoTaWatt firmware to work on a different ‘shield’ for use as a T/H node (I’ll post about that over in IoTaWatt later). After thinking about it, it occurred to me that while having local SD logging, graphing, setup and such as nice and easy as the IoTaWatt would be really nice, in most cases, it’s really overkill. I have one node that has two DS18B20 sensors and one DHT22 and is taking readings of my garage temp, outside temp and garage humidity where it would be great, and another one possibly down the road where I’d have two AM2305’s on the return and supply of my HVAC system, and perhaps an AM2305 outside for an outside humidity reading, but for most nodes, where just a DHT22 (or similar) sensor is needed, the sketch I found in the ‘guide/esp_dht22_emoncms’ folder of the EmonESP-master git repository really would be perfect (Not sure why it’s in the ‘guide’ folder)… If it worked right.

I’m guessing it’s an incomplete work? One problem I had, that I’ve had with every simple script I’ve played with, is it wouldn’t connect up to my secured wireless. I’m guessing it needs some other library to be able to connect to WPA/WPA2 SSIDs. But I was able to get it to connect to my open wireless. I also got it to post to my EmonCMS - but it wasn’t right. It created a ‘Node NoGroup’ Input, and each time it pushed data, it added a new line for each index, so I’ve got like 45 ‘1’ entries for Humidity and the same number of ‘2’ entries for temp.

Any thoughts on finishing this? While it would most likley need to run on mains power, unless one of the smaller variants of the ESP8266 were used along with the newer T/H sensor used int he EmonTH V2, but just my opinion, this would be a nice addition to the nodes available for use with EmonCMS.

I messed with it a little in Arduino IDE, and PlatformIO was mentioned to me, but I must be doing something wrong with PlatformIO, as it seems flaky to me. FOr example, when I clicked ‘Build’, it didn’t just build it and say ‘done’ or ‘error’, it kept building it over and over again. Same thing when I went to upload a sketch to the ESP. Arduino, while writing to the ESP is a bit flaky (I found it’ll fail, and if I keep clicking ‘upload’ after each fail, usually after the second or third fail, it’ll upload and off it goes), its overall behavior seems to make sense. Probably something I’m missing or doing wrong.


(Dave) #2

Can anyone help me with this? Through trial and error posting to my EmonCMS server, I got the following URL posting ‘Temperature’ and ‘Humidity’ data for node ‘ESP8266Test’ properly - so if I re-post, it doesn’t create another key, it updates the existing keys

http://myemoncms/input/post.json?node=ESP8266Test&fulljson={%22Temperature%22:70.3,%22Humidity%22:20.5}&apikey=MylongAPIKey

But I can’t, for the life of me, get it to compile right in the IDE.

The original string, ("/input/post.json?csv="+String(h)+","+String(t)+"&apikey=XXXXXXXXXXXXXXXXXXXXX":wink: compiles, but when it posts, it doesn’t post a node name or anything other than a key (1 or 2), and each time it posts, it adds another line for each, rather than updating the existing keys.

If I change the string URL to (/input/post.json?node=ESP8266Test&fulljson={“Humidity”:"+String(h)+",“Temperature”:"+String(t)+"}&apikey=), which in theory, looks like it should send the right data, the compiler spits out ‘expected ‘,’ or ‘;’ before ‘Humidity’’. If I put a “,” or “;” before ‘Humidity’, I get the same exact message.

If I change it to (/input/post.json?csv={"+String(h)+","+String(t)+"}&apikey=) it compiles and tries to post data, but then after the first post attempt, I get an ‘Invalid or too deeply nested’ error.

And this is with the ArduinoIDE - I tried using PlatformIO, but that wouldn’t build at all. Got the following mess:

platformio run --target upload
Compiling .pioenvs\emonesp\FrameworkArduino\cont.o

Compiling .pioenvs\emonesp\FrameworkArduino\cont_util.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_eboot_command.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_flash_utils.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_i2s.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_main.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_noniso.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_phy.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_postmortem.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_si2c.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_timer.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_wiring.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_wiring_analog.o
Compiling .pioenvs\emonesp\FrameworkArduino\core_esp8266_wiring_digital.o
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino:11:17: error: 'DHT22' was not declared in this scope
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
^
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino:14:17: note: in expansion of macro 'DHTTYPE'
DHT dht(DHTPIN, DHTTYPE);
^
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino: In function 'void setup()':
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino:47:7: error: 'class DHT' has no member named 'begin'
dht.begin();
^
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino: In function 'void loop()':
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino:65:17: error: 'class DHT' has no member named 'readHumidity'
float h = dht.readHumidity();
^
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino:67:17: error: 'class DHT' has no member named 'readTemperature'
float t = dht.readTemperature();
^
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino:69:17: error: 'class DHT' has no member named 'readTemperature'
float f = dht.readTemperature(true);
^
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino:88:19: error: 'class DHT' has no member named 'computeHeatIndex'
float hif = dht.computeHeatIndex(f, h);
^
C:/Users/Dave/Desktop/Arduino/EmonESP-master/guide/esp_dht22_emoncms/esp_dht22_emoncms.ino:90:19: error: 'class DHT' has no member named 'computeHeatIndex'
float hic = dht.computeHeatIndex(t, h, false);
^
*** [.pioenvs\emonesp\src\esp_dht22_emoncms.ino.o] Error 1
 [ERROR] Took 4.69 seconds

(Robert Wall) #3

I’ve got to go out now, but can you post the few lines of code up to where you build the string?
What you’re seeing has all the hallmarks of missing quotes or unbalanced parentheses, but as you’ve given only snippets it’s hard to untangle.
I haven’t got an ESP, but if it compiles and builds the correct string, it should work anywhere. (I might try it with a Nanode - I have one of those.) :open_mouth:

I’n not surprised you had trouble with platformio - my experience is well documented.


(Dave) #4

It’s just the 'esp_dht22_emoncms.ino that’s in the ‘guide’ folder which works except for how it’s posting the data to EmonCMS, just trying to figure out how to get the string right so it posts the data right.

//simple sketch reading from DHT22 and posting up to emoncms.org using the ESP8266 wifi module.
// This file is part of OpenEnergyMonitor project.



#include <ESP8266WiFi.h>
#include "DHT.h"
#define DHTPIN 12    


#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321


DHT dht(DHTPIN, DHTTYPE);


const char* ssid     = "IoT"; //WIFI NAME
//const char* password = "xxxxxxxxxxxxx"; //WIFI PASSWORD

const char* host = "MyEmonCMS";


void setup() {
  Serial.begin(9600);//Baud rate
  delay(10);

  

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  
  dht.begin();
}

int value = 0;

void loop() {
  delay(2000);
  ++value;
//  DHT22_ERROR_t errorCode;


  
  Serial.print("Requesting data...");
//  errorCode = DHT.readData();
//  switch(errorCode)
  {
   

  float h = dht.readHumidity();
  // Read temperature as Celsius (the default)
  float t = dht.readTemperature();
  
  float f = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(h) || isnan(t) || isnan(f)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.print("connecting to ");
  Serial.println(host);
  
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  
  // Compute heat index in Fahrenheit (the default)
  //float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  //float hic = dht.computeHeatIndex(t, h, false);
  Serial.print("\n");
  Serial.print("Humidity: ");
  Serial.print(h);
  Serial.print(" %\n");
  Serial.print("Temperature: ");
  Serial.print(t);
  Serial.print(" *C\n ");

  // We now create a URI for the request
  //String url = "/input/post.json?csv="+String(h)+","+String(t)+"&apikey=XXXXXXXXXXXXXXXXXXXXX"; //Enter api key here
  //String url = "input/post.json?node=ESP8266Test&fulljson="Temperature:String(t),Humidity:String(h)&apikey=****APIKEY****"; //Enter api key here
  //String url = "/input/post.json?csv="+String(h)+","+String(t)+"&apikey=****APIKEY****"; //Enter api key here
  String url = "/input/post.json?node=ESP8266Test&fulljson={"Humitity":"+String(h)+","Temperature":"+String(t)+"}&apikey=****APIKEY****"; //Enter api key here
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }
  
  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  
  Serial.println();
  Serial.println("closing connection");
  }
}

(Paul) #5

The double quotes in your url string are being read as code rather than included in the string text, try escaping the double quotes you want carried through to the url.
so

String url = "/input/post.json?node=ESP8266Test&fulljson={"Humitity":"+String(h)+","Temperature":"+String(t)+"}&apikey=****APIKEY****"; //Enter api key here

becomes

String url = "/input/post.json?node=ESP8266Test&fulljson={\"Humitity\":"+String(h)+",\"Temperature\":"+String(t)+"}&apikey=****APIKEY****"; //Enter api key here
  

(The code color coding above should look more in keeping with what you are trying to do)

[edit]

Although I think you want some more escaped quotes in there like this (untested)

String url = "/input/post.json?node=ESP8266Test&fulljson={\"Humitity\":\""+String(h)+"\",\"Temperature\":\""+String(t)+"\"}&apikey=****APIKEY****"; //Enter api key here
  

(Dave) #6

The first one worked - Thanks!!

So in the end, the code that worked was:

//simple sketch reading from DHT22 and posting up to emoncms.org using the ESP8266 wifi module.
// This file is part of OpenEnergyMonitor project.



#include <ESP8266WiFi.h>
#include "DHT.h"
#define DHTPIN 12    


#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321


DHT dht(DHTPIN, DHTTYPE);


const char* ssid     = "IoT"; //WIFI NAME
//const char* password = "xxxxxxxxxxxxx"; //WIFI PASSWORD

const char* host = "MyEmonCMS"; //Enter the EmonCMS Server address here
const char* apikey = "****MyAPIKey****"; //Enter api key here

void setup() {
  Serial.begin(9600);//Baud rate
  delay(10);

  

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  
  dht.begin();
}

int value = 0;

void loop() {
  delay(30000);
  //delay(2000);
  ++value;
//  DHT22_ERROR_t errorCode;


  
  Serial.print("Requesting data...");
//  errorCode = DHT.readData();
//  switch(errorCode)
  {
  
  float DHTh; 
  float DHTtC;
  float DHTtF;
  
  DHTh = dht.readHumidity();
  // Read temperature as Celsius (the default)
  DHTtC = dht.readTemperature();
  // Read temperature as Farenheiht
  DHTtF = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(DHTh) || isnan(DHTtC) || isnan(DHTtF)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.print("connecting to ");
  Serial.println(host);
  
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  
  // Compute heat index in Fahrenheit (the default)
  //float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  //float hic = dht.computeHeatIndex(t, h, false);
  Serial.print("\n");
  Serial.print("Humidity: ");
  Serial.print(DHTh);
  Serial.print(" %\n");
  Serial.print("Temperature: ");
  Serial.print(DHTtF);
  Serial.print(" *F\n ");

  // We now create a URI for the request
  String url = "/input/post.json?node=ESP8266Test&fulljson={\"Humidity\":"+String(DHTh)+",\"Temperature\":"+String(DHTtF)+"}&apikey="+String(apikey);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }
  
  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  
  Serial.println();
  Serial.println("closing connection");
  }
}

It’s amazing how the simplest things can make everything come crashing down.

Now that that’s figured out, maybe I’ll try and see if I can figure out how to make it use DS18B20 sensors, and then I might try my luck at a DHT22 and DS18B20’s on the same board.

Actually, since it’s all Arduino code, aside from the HTTP post portions, I wonder if the EmonTH code would work?

Edit: Updated code


(Robert Wall) #7

Just to add a bit of explanation to Paul’s post, when the compiler said

‘expected ‘,’ or ‘;’ before ‘Humidity’’

it was trying to tell you that what it saw as the quoted string had ended and it was expecting either a second item (as in a for loop or a declaration) or the statement terminator ;. The golden rule when looking at compiler errors is to remember that the error message is where the compiler got confused, the error itself is before that - immediately before if you’re lucky, but sometimes a long way before.

If all the sensor addresses are correct, I don’t see why not. (Take out all the RFM stuff - it’s not needed.)


(Dave) #8

So as previously stated and with code posted, I got a ESP8266 working beautifully with a DHT22 and posting properly to EmonCMS.

After HOURS of messing around, pulling my hair out, wondering what stupid little thing I was missing (All stuff that someone that actually knows what they’re doing would probably take 10 minutes to hammer out), I FINALLY got it working with a DHT22 and two DS18B20s. The last hour plus I finally got the serial print and report to EmonCMS reporting the same thing, but it was ‘1’. I finally found what worked and is properly reporting on the serial port as well as EmonCMS.

Without further adoo, here’s my (messy) code that works:

//simple sketch reading from DHT22 and posting up to emoncms.org using the ESP8266 wifi module.
// This file is part of OpenEnergyMonitor project.



#include <ESP8266WiFi.h>
#include "DHT.h"
#define DHTPIN 12    


#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321


DHT dht(DHTPIN, DHTTYPE);


const char* ssid     = "IoT"; //WIFI NAME
//const char* password = "xxxxxxxxxxxxx"; //WIFI PASSWORD

const char* host = "MyEmonCMS"; //Enter the EmonCMS Server address here
const char* apikey = "****MyAPIKey****"; //Enter api key here

void setup() {
  Serial.begin(9600);//Baud rate
  delay(10);

  

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  
  dht.begin();
}

int value = 0;

void loop() {
  delay(30000);
  //delay(2000);
  ++value;
//  DHT22_ERROR_t errorCode;


  
  Serial.print("Requesting data...");
//  errorCode = DHT.readData();
//  switch(errorCode)
  {
  
  float DHTh; 
  float DHTtC;
  float DHTtF;
  
  DHTh = dht.readHumidity();
  // Read temperature as Celsius (the default)
  DHTtC = dht.readTemperature();
  // Read temperature as Farenheiht
  DHTtF = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(DHTh) || isnan(DHTtC) || isnan(DHTtF)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.print("connecting to ");
  Serial.println(host);
  
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  
  // Compute heat index in Fahrenheit (the default)
  //float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  //float hic = dht.computeHeatIndex(t, h, false);
  Serial.print("\n");
  Serial.print("Humidity: ");
  Serial.print(DHTh);
  Serial.print(" %\n");
  Serial.print("Temperature: ");
  Serial.print(DHTtF);
  Serial.print(" *F\n ");

  // We now create a URI for the request
  String url = "/input/post.json?node=ESP8266Test&fulljson={\"Humidity\":"+String(DHTh)+",\"Temperature\":"+String(DHTtF)+"}&apikey="+String(apikey);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }
  
  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  
  Serial.println();
  Serial.println("closing connection");
  }
}

I’m sure it’s messy and I know there’s a bunch of commented stuff that could be removed, but that’s the raw code that I finally got working.

I would have to say overall, once I started kind of understanding how some things interact with each other, this was easier to get working than the Arduino/RFM version probably due to the way the coding is structured for the RFM payload and such.

Edit: modified the code a bit to try and clean a few things up.
Edit2: A Little more cleanup/modification.

Now I need to figure out why it all works perfectly on my Adafruit Feather Huzzah, but when I upload the same code to either of my ‘Generic’ NodeMCU’s, nothing happens.Only real difference I can see between the two is the Huzzah is a ESP-12S and the ‘Generic’ ones are ESP-12N.

IDEALLY, I’d like it to be able to connect to a WPA/WPA2 encrypted SSID, not sure what it would take to do that - maybe I’ll be able to figure it out, but technically, leaving my IoT network open isn’t that big of a deal - it doesn’t get you on the internet unless I allow it (Only device I would do that for is the IoTaWatt), you can only get to one address on my LAN (The EmonCMS server) on two ports (80 & 443 in case I switch to HTTPS) and all IoT clients are isolated, so if you get on it, you’re not going to see any other devices or IPs. So if you don’t know my EmonCMS servers IP, there’s pretty much zero you can do on it.


(Glyn Hudson) #9

I would recomend using Easy ESP this supports all the usual sensors (ds18b20 temperature / DHT22 humidity) and posts data to MQTT:

You could then forward the data from MQTT to Emocms at a central point. Or use an emonPi which has na MQTT server ready configured to log data locally to Emoncms.


(Dave) #10

I’ll admit I haven’t looked at the link, but I’m guessing the ESPEasy makes it easy(er) to set up the DHT22 and DS18B20 sensors on the ESP8266 nodes… but considering the fact that I’ve worked out the code to where the ESP8266’s can post straight to EmonCMS via JSON, is there a particular reason you’re recommending this? Personally, part of the reason I wanted to work this out was to eliminate the intermediate (EmonPi/EmonBase/EmonHub) as much as possible. I’ve got an Adafruit Feather Huzzah that has been posting a DHT22 and two DS18B20’s straight to my EmonCMS for almost 24 hours beautifully, and I just flashed one of the 8 pin ESP8266 variants (these guys) with the DHT22 code (modified for the pin assignment) that has been posting data from a DHT22 beautifully ever since (This code and module will likely become my ‘go to’ DHT22 only node to ‘replace’ the EmonTH’s - I just need to design the PCB for it).

The problem, in my setup, with the EmonHub 433Mhz setup, is coverage. I’m probably losing transmissions from my garage and my safe (which are at extreme opposite ends of my house), at the very least (the Garage EmonTH is set to transmit every 30 seconds, but it’s VERY rare that I see posts anywhere close to that), to the RPi that receives the 433 transmissions (and my alarm, which operates in the 433 band could potentially be causing some sort of interference). My WiFi coverage is WAY better than the 433 coverage, with an AP at each end of my house.

Unless there’s some glaring reason a programming moron like me doesn’t see, is there REALLY any reason not to use the code I posted for the DHT22 only and DHT+DS18B20 nodes (unlike the ino file in the ‘guides’ folder which was a disaster as published)?

But again, why would I want to publish to a MQTT intermediate to then relay to EmonCMS, when the code I posted posts straight to EmonCMS beautifully?
I’m not going to lie - considering how stupid I am when it comes to programming (I’m quite knowledgeable in things that make a LOT of peoples heads spin - but programming ISN’T one of them), I’m pretty proud that I got these working. There are those out there that say ‘pffft - I could have done that in 10 minutes’ - I have no doubt of that, but despite all the reading and attempting to understand programming I’ve done, I haven’t found that ‘rosetta stone’ that makes it all click, and I’m a moron when it comes to programming.

Had I not worked it out and was still struggling, I might see your point… but since I’ve worked it out and it’s working nicely, I’m kinda lost.

This is of course just my opinion, but it might make sense to develop/release an ‘EmonTH3’ that is based on one of these ‘micro’ ESP8266’s - although power usage could be an issue for some (They seem like they might be capable of low power usage similar to that of at least the EmonThV1, but I’m far from an expert on that). In my case, I have no issue with supplying mains power to most of the nodes, an those that I can’t for one reason or another, I can preserve the 433 receiver to address them.


(Glyn Hudson) #11

Just had a look it seems like you can post direct to Emoncms using ESP easy

https://www.letscontrolit.com/wiki/index.php/EasyProtocols#EmonCMS

However, it’s great you have worked your own solution. I’m sure you have learnt a lot in the process. Your own solution will be easier for you to customise in the future. Nice work. I was more posting the link to help others in the future.


(Dave) #12

I learned a thing or two for sure, but programming expert I am NOT. It was all trial and error, hair pulling, a fair amount of cussing and trying to figure out what in the heck it wanted, but in the end, I prevailed, making some usable code. In the end, the code I figured out seems to work well for me, and I hope others can benefit from it (Might I suggest maybe cleaning my DHT22 code up a little if needed and replacing the train wreck that is in the ‘guide’ folder with it (It really is totally unusable as it sits)? Mine may not be perfect (or heck, it might be nearly perfect by some miracle), but it posts right…). The one I have yet to play with is the multiple DHT22 (or similar) sensors. I’m sure it can be done… if/when I do, I’ll post it up.

I have an update or so that further simplifies basic customization that I’ll edit my posts to reflect sometime tomorrow.


(Dave) #13

Adding in my latest code for the ‘mini’ 8-pin ESP8266 modules (these guys)

//simple sketch reading from DHT22 and posting up to emoncms.org using the ESP8266 wifi module.
// This file is part of OpenEnergyMonitor project.



#include <ESP8266WiFi.h>
#include "DHT.h"
#define DHTPIN 2    


#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321


DHT dht(DHTPIN, DHTTYPE);


const char* ssid     = "IoT"; //WIFI NAME
//const char* password = "xxxxxxxxxxxxx"; //WIFI PASSWORD

const char* host = "192.168.41.14"; //Enter the EmonCMS Server address here
const char* apikey = "e95794b3164272b8f1365a2d6e6fff76"; //Enter api key here
const char* NodeName = "ESP8266Testa"; // Enter your node name here

void setup() {
  Serial.begin(9600);//Baud rate
  delay(10);

  

  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid);
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  
  dht.begin();
}

int value = 0;

void loop() {
  delay(30000);
  //delay(2000);
  ++value;
//  DHT22_ERROR_t errorCode;


  
  Serial.print("Requesting data...");
//  errorCode = DHT.readData();
//  switch(errorCode)
  {
  
  float DHTh; 
  float DHTtC;
  float DHTtF;
  
  DHTh = dht.readHumidity();
  // Read temperature as Celsius (the default)
  DHTtC = dht.readTemperature();
  // Read temperature as Farenheiht
  DHTtF = dht.readTemperature(true);

  // Check if any reads failed and exit early (to try again).
  if (isnan(DHTh) || isnan(DHTtC) || isnan(DHTtF)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.print("connecting to ");
  Serial.println(host);
  
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  
  // Compute heat index in Fahrenheit (the default)
  //float hif = dht.computeHeatIndex(f, h);
  // Compute heat index in Celsius (isFahreheit = false)
  //float hic = dht.computeHeatIndex(t, h, false);
  Serial.print("\n");
  Serial.print("Humidity: ");
  Serial.print(DHTh);
  Serial.print(" %\n");
  Serial.print("Temperature: ");
  Serial.print(DHTtF);
  Serial.print(" *F\n ");

  // We now create a URI for the request
  String url = "/input/post.json?node="+String(NodeName)+"&fulljson={\"Humidity\":"+String(DHTh)+",\"Temperature\":"+String(DHTtF)+"}&apikey="+String(apikey);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }
  
  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  
  Serial.println();
  Serial.println("closing connection");
  }
}

Since they have limited input pins, they’re really best suited (IMO) for single DHT11/22 setups. But I may play with them and determine if they’d be plenty for a DHT22 and DS18B20’s as well (There might be a sedond usable IO pin, so if there is, they would suffice)…

Edit: The 8 pin units have GPIO 0 and GPIO2 available at the pins, so they will work for both single DHT22 nodes and DHT22 + DS18B20 nodes.


(Dave) #14

Just another update. I got a configuration page on the devices working, so they can now connect to a WPA/WPA2 protected SSID. Before getting that working, for whatever reason, I could not get them to connect to anything that wasn’t wide open.

While it would be really nice if the code could be static, and everything from what sensors (and how many) are connected (and in the case of DS18B20’s, their addresses) to the Node name, EmonCMS server and your API key could be set up through a web interface, while I’m sure it’s possible, I’d say I’ve pretty much hit the limit of my (insignificant) abilities when it comes to programming/coding. Truthfully, if even just the node name could be configured through a web interface, that would be great, but really, this is quite workable for me - should I choose to lock my IoT network down with WPA/WPA2, which to be honest, isn’t that critical considering how I have it locked down, I can do so. And if anyone else wants to use the code and can’t lock their network down the way mine is with guest isolation and no internet access, that’s a win for them too.

So unless I have some kind of epiphany and suddenly can figure out those few remaining things that would be nice, this is probably my last and best revision to the code:

//Sketch using ESP8266 ESP-01 modules, reading from DHT22 & DS18B20, posting up to emoncms using the ESP8266 wifi module.
// This file is part of OpenEnergyMonitor project.

#include <ESP8266WiFi.h>
#include "DHT.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WebServer.h>
#include <WiFiManager.h>

#define DHTPIN 2 // Pin to which DHT sensor is connected
#define ONE_WIRE_BUS 0 // Pin to which one or more DS18B20 temperature sensors are attached
#define ONE_WIRE_MAX_DEV 15 // The maximum number of devices
#define DHTTYPE DHT22   // DHT 22  (AM2302), AM2321
#define SENSOR_RESOLUTION 11 // How many bits to use for temperature values: 9, 10, 11 or 12

DHT dht(DHTPIN, DHTTYPE);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature DS18B20(&oneWire);

DeviceAddress Sensor1 = {0x28, 0x17, 0x6F, 0xD4, 0x05, 0x00, 0x00, 0x84};
//DeviceAddress Sensor2 = {0x28, 0xFF, 0xC2, 0x72, 0x60, 0x14, 0x02, 0x88};

const char* host = "YourServerIPAddress"; //Enter the EmonCMS Server address here
const char* apikey = "****YourAPIKey****"; //Enter your api key here
const char* NodeName = "ESP8266Testa"; // Enter your node name here

//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;

void setup() {
  Serial.begin(9600);//Baud rate
  delay(10);
  
  WiFi.mode(WIFI_STA); // Force to station mode because if device was switched off while in access point mode it will start up next time in access point mode.

   // Uncomment for testing wifi manager  - If used, flash, boot, comment out and flash again
  //wifiManager.resetSettings();

  //or use this for auto generated name ESP + ChipID
  wifiManager.autoConnect();

  //Manual Wifi
  //WiFi.begin(WIFI_SSID, WIFI_PWD);
  
  Serial.println();
  Serial.println();
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");  
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  DS18B20.begin();
  dht.begin();
}

int value = 0;

void loop() {
  delay(30000);
  ++value;
 
  Serial.print("Requesting data...");
//  errorCode = DHT.readData();
//  switch(errorCode)
  {
  float DSTemp1;
  //float DSTemp2;
  float DHT1h;
  float DHT1tC;
  float DHT1tF;
  
  DS18B20.requestTemperatures(); 
  DSTemp1 = DS18B20.getTempF(Sensor1);
  //DSTemp2 = DS18B20.getTempF(Sensor2);
  DHT1h = dht.readHumidity(); // Read Humidity
  DHT1tC = dht.readTemperature(); // Read temperature as Celsius (the default)
  DHT1tF = dht.readTemperature(true); // Read temperature as Farenheit


  // Check if any reads failed and exit early (to try again).
  if (isnan(DHT1h) || isnan(DHT1tC) || isnan(DHT1tF)) {
    Serial.println("Failed to read from DHT sensor!");
    return;
  }
  Serial.print("connecting to ");
  Serial.println(host);
  
  // Use WiFiClient class to create TCP connections
  WiFiClient client;
  const int httpPort = 80;
  if (!client.connect(host, httpPort)) {
    Serial.println("connection failed");
    return;
  }
  
  Serial.print("\n");
  Serial.print("Humidity: ");
  Serial.print(DHT1h);
  Serial.print(" %\n");
  Serial.print("Temperature: ");
  Serial.print(DHT1tF);
  Serial.print(" *F\n ");
  Serial.print("DS1 Temperature: ");
  Serial.print(DSTemp1),4;
  Serial.print(" *F\n ");
  //Serial.print("DS2 Temperature: ");
  //Serial.print(DSTemp2),4;
  //Serial.print(" *F\n ");
  
  // We now create a URI for the request
  String url = "/input/post.json?node="+String(NodeName)+"&fulljson={\"Humidity\":"+String(DHT1h)+",\"Temperature\":"+String(DHT1tF)+",\"DS1\":"+String(DSTemp1)+"}&apikey="+String(apikey);
  Serial.print("Requesting URL: ");
  Serial.println(url);
  
  // This will send the request to the server
  client.print(String("GET ") + url + " HTTP/1.1\r\n" +
               "Host: " + host + "\r\n" + 
               "Connection: close\r\n\r\n");
  unsigned long timeout = millis();
  while (client.available() == 0) {
    if (millis() - timeout > 5000) {
      Serial.println(">>> Client Timeout !");
      client.stop();
      return;
    }
  }
  
  // Read all the lines of the reply from server and print them to Serial
  while(client.available()){
    String line = client.readStringUntil('\r');
    Serial.print(line);
  }
  
  Serial.println();
  Serial.println("closing connection");
  }
}

As previously mentioned, if you want to add this to the GitHub in place of the existing sketch in the ‘Guide’ folder, feel free to do so (and if I may be so bold, it’s probably a good idea considering how broken the sketch that’s in there is).