Skip to content

Instantly share code, notes, and snippets.

@dt
Created November 22, 2018 00:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dt/76f1b7ffaee59af9f70a949ec0365eb5 to your computer and use it in GitHub Desktop.
Save dt/76f1b7ffaee59af9f70a949ec0365eb5 to your computer and use it in GitHub Desktop.
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPClient.h>
#include <ESP8266WebServer.h>
#include <ArduinoOTA.h>
#include <SoftwareSerial.h>
byte cmdRead[2] = {0x86, 0x00};
byte cmdCalibrateZero[2] = {0x87, 0x00};
byte cmdEnableABC[2] = {0x79, 0xA0};
byte cmdDisableABC[2] = {0x79, 0x00};
byte cmdReset[2] = {0x8d, 0x00};
const int rx_pin = 4;
const int tx_pin = 5;
SoftwareSerial sensor(rx_pin, tx_pin, false, 256);
const char* ssid = "<my-wifi-ssid>";
const char* password = "<my-wifi-password>";
ESP8266WebServer server ( 80 );
HTTPClient http;
void setup(void)
{
Serial.begin(115200);
delay(100);
sensor.begin(9600); // init CO2 sensor serial port
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
server.on ( "/", handleRoot );
server.begin();
Serial.println("webserver started");
MDNS.addService("http", "tcp", 80);
ArduinoOTA.setHostname("sniffer");
ArduinoOTA.begin();
delay(5000);
sendCmd(cmdDisableABC);
}
void handleRoot() {
String page = String(
"<html><head><meta charset='utf-8'/>"
"<meta http-equiv=\"refresh\" content=\"60\" />"
"<title>Sniffer</title>"
"<link href='https://fonts.googleapis.com/icon?family=Material+Icons' rel='stylesheet'/>"
"<style>"
"body { font-family: Helvetica, Arial, Sans-Serif; background-color: #eee; }"
"</style>"
"<meta name='viewport' content='width = device-width, initial-scale = 1.0, maximum-scale = 1.0, user-scalable=0'>"
"</head>"
"<body>\n"
"<div class='sniffer'>\n"
"<p>CO2: "+String(sendCmd(cmdRead)) +" ppm </p>"
"</div>" // /stc
"</body></html>"
);
server.send(200, "text/html", page);
}
void logToInflux() {
int ppm = sendCmd(cmdRead);
Serial.print("CO2: ");
Serial.print(ppm);
Serial.println("ppm");
if (ppm < 1) {
return;
}
http.begin("<my-logging-service>");
int httpCode = http.POST(String("co2 ppm="+String(ppm)));
if(httpCode > 299) {
Serial.print("Reply(");
Serial.print(httpCode);
Serial.print("): ");
Serial.print(http.getString());
}
http.end();
}
unsigned long lastReport;
unsigned long nextReport;
uint32 ticks;
void loop() {
ArduinoOTA.handle();
server.handleClient();
ticks++;
if (ticks > 10000) {
ticks = 0;
unsigned long now = millis();
if (now > nextReport || now < lastReport) {
nextReport = now + 1000 * 30;
logToInflux();
lastReport = now;
}
}
}
byte checksum(byte *array)
{
byte checksum = 0;
for (byte i = 1; i < 8; i++)
checksum+=array[i];
checksum = 0xFF - checksum;
return (checksum+1);
}
unsigned int sendCmd(byte* cmd) {
byte req[9];
memset(req, 0, 9);
req[0] = 0xFF;
req[1] = 0x01;
req[2] = cmd[0];
req[3] = cmd[1];
req[8] = checksum(req);
bool header_found = false;
sensor.write(req, 9);
if (cmd[0] != cmdRead[0]) {
return 0;
}
// read until we see the first two bytes of the reply.
while (sensor.available() && (!header_found)) {
if (sensor.read() == 0xff ) {
if (sensor.read() == 0x86 ) {
header_found = true;
}
}
}
if (!header_found) {
Serial.println("conn closed before header not found");
return 0;
}
// already read first two bytes while looking for the beginning so
// a) put those in the buffer so the checksum matches
// b) read the remaining 9-2=7 bytes into the buffer.
unsigned char resp[9];
memset(resp, 0, 9);
resp[0] = 0xff;
resp[1] = 0x86;
sensor.readBytes(&resp[2], 7);
// Check that the checksum matches.
byte crc = checksum(resp);
if ( !(resp[8] == crc) ) {
Serial.println(String("CO2: CRC error: ") + String(crc) + String(" vs ") + String(resp[8]));
return 0;
}
// Compute the result.
unsigned int ppmHigh = (unsigned int) resp[2];
unsigned int ppmLow = (unsigned int) resp[3];
unsigned int ppm = (256 * ppmHigh) + ppmLow;
return ppm;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment