Re: New build, work in progress.
Posted: Fri Jul 23, 2021 6:39 pm
Come on now, please deliver!
A friendly LED grow light community.
https://ledgardener.com/forum/
Code: Select all
//espAir v1
// PM,
// temperature & humidity,pressure, voc
//this device ++++++++++++++++++++++++++++++++++++++++++
const char* espName = "espAir";
//loop delay ms
int interval = 3500;
//dual core
TaskHandle_t Task1;
//For display of Wifi Kit 32
#include "heltec.h"
char line[64];
//WIFI Stuff
#include <WiFi.h>
const char* ssid = "homeWifi";
const char* password = "***";
IPAddress staticIP(192,168,2,53);
IPAddress gateway(192,168,0,1);
IPAddress subnet(255,255,0,0);
bool online=false;
//i2c stuff
#include <Wire.h>
//MQTT stuff
#include <PubSubClient.h>
WiFiClient espClient;
PubSubClient client(espClient);
const char* mqtt_server = "192.168.2.1";
char tempString[8];
unsigned char payload[64];
String mesg;
//MQTT BROKER Stuff
#include "TinyMqtt.h"
MqttBroker broker(1883);
//for SPS30
#include <sps30.h>
int16_t ret;
uint8_t auto_clean_days = 4;
uint32_t auto_clean;
struct sps30_measurement m;
char serial[SPS30_MAX_SERIAL_LEN];
uint16_t data_ready;
// for BME680
#include <Zanshin_BME680.h>
BME680_Class BME680;
static int32_t temp, humidity, pressure, gas;
//////////////////////////////////////// SETUP CODE
void led_setup() {
pinMode(LED,OUTPUT);
digitalWrite(LED,HIGH);
Heltec.begin(true /*DisplayEnable Enable*/, false /*LoRa Enable*/, false /*Serial Enable*/);
digitalWrite(25, LOW);
}
void wifi_setup() {
char i =0;
WiFi.persistent(false);
WiFi.begin(ssid, password);
WiFi.config(staticIP, gateway, gateway, subnet);
while (WiFi.status() != WL_CONNECTED & i < 25) {
i++;
delay(100);
}
if (WiFi.status() == WL_CONNECTED) online = true;
else {
WiFi.softAPConfig(staticIP, gateway, subnet);
WiFi.softAP(espName, password);
}
if (online) Serial.println("online");
else Serial.println("offline");
}
void brokerLoop(void * param) {
for (;;) {
broker.loop();
delay(250);
}
}
void mqtt_setup() {
if (online) {
client.setServer(mqtt_server, 1883);
} else {
broker.begin();
xTaskCreatePinnedToCore(brokerLoop, "Broker Loop", 2000, NULL, 1, &Task1, 1);
client.setServer("127.0.0.1", 1883);
}
client.setCallback(callback);
mqtt_connect();
client.subscribe("espAir/getStatus");
client.subscribe("espAir/setInterval");
//client.subscribe("espAir/setMode");
client.publish("espAir/status", "espAir Online");
}
void sps_setup() {
sensirion_i2c_init();
while (sps30_probe() != 0) {
Serial.print("SPS sensor probing failed\n");
client.publish("espAir/status", "SPS sensor probing failed");
delay(500);
}
ret = sps30_set_fan_auto_cleaning_interval_days(auto_clean_days);
if (ret) {
client.publish("espAir/status", "error setting the auto-clean interval");
//Serial.println(ret);
}
ret = sps30_start_measurement();
if (ret < 0)
client.publish("espAir/status", "sps30 error starting measurement\n");
}
void bme_setup() {
if (!BME680.begin()) {
client.publish("espAir/status", "Could not find a valid BME680 sensor");
Serial.print("no BME680");
}
// Set up oversampling and filter initialization
BME680.setOversampling(TemperatureSensor, Oversample16); // Use enumerated type values
BME680.setOversampling(HumiditySensor, Oversample16); // Use enumerated type values
BME680.setOversampling(PressureSensor, Oversample16); // Use enumerated type values
BME680.setIIRFilter(IIR4); // Use enumerated type values
BME680.setGas(320, 150); // 320degC for 150 milliseconds
}
void mqtt_connect() {
while (!client.connected()) {
if (client.connect(espName)) {
} else {
delay(5000);
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
if (0==strcmp(topic, "espAir/getStatus")) {
mesg = "get_status: interval: ";
dtostrf(interval, 8, 0, tempString);
mesg += tempString;
mesg.toCharArray((char *)payload, 127);
client.publish("espAir/status", (char *)payload);
}
else if (0 == strcmp(topic, "espOne/setInterval")) {
client.publish("espAir/status", "setInterval");
interval = atoi((char *)payload);
}
}
void setup() {
led_setup();
Serial.begin(115200);
Serial.println();
Wire.begin(SDA_OLED, SCL_OLED);
wifi_setup();
mqtt_setup();
bme_setup();
sps_setup();
}
////////////////////////////////////////// RUNTIME CODE
void do_sps30()
{
do {
ret = sps30_read_data_ready(&data_ready);
if (ret < 0) {
Serial.print("error reading data-ready flag: ");
Serial.println(ret);
} else if (!data_ready)
Serial.print("data not ready, no new measurement available\n");
else
break;
delay(200); /* retry in ms */
} while (1);
ret = sps30_read_measurement(&m);
if (ret < 0)
Serial.print("error reading measurement\n");
else {
dtostrf(m.nc_0p5, 4, 2, tempString);
client.publish("espAir/nc05", tempString);
dtostrf(m.nc_1p0 - m.nc_0p5, 4, 2, tempString);
client.publish("espAir/nc1", tempString);
dtostrf(m.nc_2p5 - m.nc_1p0, 4, 2, tempString);
client.publish("espAir/nc25", tempString);
dtostrf(m.nc_4p0 - m.nc_2p5, 4, 2, tempString);
client.publish("espAir/nc4", tempString);
dtostrf(m.nc_10p0 - m.nc_4p0, 4, 2, tempString);
client.publish("espAir/nc10", tempString);
dtostrf(m.typical_particle_size, 4, 2, tempString);
client.publish("espAir/typ", tempString);
dtostrf(m.mc_2p5, 4, 2, tempString);
client.publish("espAir/PM25", tempString);
}
}
void do_bme680()
{
BME680.getSensorData(temp, humidity, pressure, gas);
sprintf(tempString, "%3d.%1d", (int8_t)(temp / 100), (uint8_t)(temp % 100));
client.publish("espAir/temperature", tempString);
sprintf(tempString, "%3d.%1d", (int8_t)(humidity / 1000), (uint16_t)(humidity % 1000)); // Humidity milli-pct
client.publish("espAir/humidity", tempString);
sprintf(tempString, "%7d.%1d", (int16_t)(pressure / 100), (uint8_t)(pressure % 100)); // Pressure Pascals
client.publish("espAir/pressure (hPa)", tempString);
sprintf(tempString, "%4d.%1d\n", (int16_t)(gas / 100), (uint8_t)(gas % 100));
client.publish("espAir/gas", tempString);
}
void odisplay() {
Heltec.display -> clear();
sprintf(line, "PMmc: %3.0f, %3.0f, %3.0f, %3.0f", m.mc_1p0, m.mc_2p5, m.mc_4p0, m.mc_10p0);
Heltec.display -> drawString(0,0, line);
sprintf(line, "PM:nc %3.0f, %3.0f, %3.0f, %3.0f, %3.0f", m.nc_0p5, m.nc_1p0, m.nc_2p5, m.nc_4p0, m.nc_10p0);
Heltec.display -> drawString(0,10, line);
sprintf(line, "PM: %3.0f, %3.0f, %3.0f, %3.0f, %3.0f", m.nc_0p5, m.nc_1p0 - m.nc_0p5, m.nc_2p5-m.nc_1p0, m.nc_4p0-m.nc_2p5, m.nc_10p0-m.nc_4p0);
Heltec.display -> drawString(0,20, line);
sprintf(line, "Temp: %3d.%1d Humi: %2d.%1d", (int8_t)(temp / 100), (uint8_t)(temp % 100), (int8_t)(humidity / 1000), (uint16_t)(humidity % 1000));
Heltec.display -> drawString(0,30, line);
sprintf(line, "Pres: %4d.%1d Gas: %4d.%1d", (int16_t)(pressure / 100), (uint8_t)(pressure % 100), (int16_t)(gas / 100), (uint8_t)(gas % 100));
Heltec.display -> drawString(0,40,line);
//sprintf(line, "PMtype: %s", m.typical_particle_size);
//Heltec.display -> drawString(0,50,line);
Heltec.display -> display();
}
void chatty () {
Serial.print("PM 1.0: ");
Serial.println(m.mc_1p0);
Serial.print("PM 2.5: ");
Serial.println(m.mc_2p5);
Serial.print("PM 4.0: ");
Serial.println(m.mc_4p0);
Serial.print("PM 10.0: ");
Serial.println(m.mc_10p0);
Serial.print("NC 0.5: ");
Serial.println(m.nc_0p5);
Serial.print("NC 1.0: ");
Serial.println(m.nc_1p0);
Serial.print("NC 2.5: ");
Serial.println(m.nc_2p5);
Serial.print("NC 4.0: ");
Serial.println(m.nc_4p0);
Serial.print("NC 10.0: ");
Serial.println(m.nc_10p0);
Serial.print("Typical partical size: ");
Serial.println(m.typical_particle_size);
Serial.print(m.nc_0p5);
Serial.print(" ");
Serial.print(m.nc_1p0 - m.nc_0p5);
Serial.print(" ");
Serial.print(m.nc_2p5 - m.nc_1p0);
Serial.print(" ");
Serial.print(m.nc_4p0 - m.nc_2p5);
Serial.print(" ");
Serial.print(m.nc_10p0 - m.nc_4p0);
Serial.println();
}
void loop() {
digitalWrite(25, HIGH);
if (online)
if (WiFi.status() != WL_CONNECTED )
wifi_setup();
if (!client.connected())
mqtt_connect();
do_bme680();
do_sps30();
odisplay();
//chatty();
client.loop();
digitalWrite(25, LOW);
delay(interval);
}