CO2 messen mit Node MCU (falls man keinen Octopus zur Hand hat)

by

Nicht immer hat eine Octopus Platine zur Hand. Deshalb haben mich einige gefragt, wie man eine CO2 Ampel bzw. eine Meßgerät mit einer anderen Platine bauen kann. Im Chaos Computer Club hier in Freiburg wurde schließlich so eine Ampel gebaut. Wir haben hier – auch aus Kostengründen, diese Teile dürften etwa bei 55 EUR liegen – etwa auf eine NeoPixel LED verzichtet. Später wird es hier Tipps geben, wie man dieses Meßgerät mit anderen Ausgabegeräten verbinden kann. Wer aber dazu noch Tipps sucht, dem seien die anderen Artikel zum Thema Ocotopus auf dem Blog angeraten. Dieser Post ist in Teilen identisch mit der Anleitung CO2 Messen mit dem Octopus.

Teile

  • Node MCU (Platine die steuert) (bei Amazon, bei Mouser)
  • SCD30 (CO2 Sensor) (Digikey ab 53 EUR inklusive Mwst, RS Online ab 72 EUR mit MwSt, bei Mouser derzeit ausverkauft)
  • Grove LCD Display (bei Mouser)
  • I2C Hub (für die Bequemlichkeit, bei Mouser)
  • Kabel (es reicht eine Packung, bei Mouser)
  • USB Kabel (zur Stromversorgung und zum flashen)
  • Stromversorgung, entweder Powerbank oder Handyladegerät

Programmcode

Hier gibt es zunächst eine Anleitung, eigenen Code mithilfe der Ardublock Software zu schreiben bzw. zusammen zu klicken, wer das nicht will und einfach mit der Arduino IDE Code reinkopieren, der findet unten ein Beispiel mit einer Anleitung.

ein ganz einfacher Code im Ardublockly, der aber alles zeigt was wir zum Meßen brauchen.

Am einfachsten verwendet man ein Windows PC und installiert es sich nach Anleitung (mit Downloadlinks) auf der Website vom Umweltcampus Birkenfeld. Auf der Übersichtsseite zum Projekt Octopus finden sich auf die Anleitungen für Pi und MacOs. Ich habe für MacOs auch eine Anleitung auf diesem Blog.

Für Windows ist es relativ einfach, download des aktuellen Zip-File der Werkstatt-Plattform und dann den Chipsatz Treiber installieren. Wie es geht haben sie in einem PDF erklärt. Wichtig ist unter Werkzeuge den richtigen „Com“ Port auszuwählen.

Für MacOS ist es ein wenig komplizierter, aber mit der Anleitung auch gut zu machen. Auch hier den Chipsatz Treiber installieren, die Arduino IDE von Arduino herunterladen, dann installieren. Dann in den Ordner Programme gehen, dort rechtsklick und „Paketinhalt zeigen“ auswählen. Wir sehen dann was sich hinter dem Icon verbrigt, nämlich die Struktur des Arduino Programms. Jetzt das Archiv „IoTW.zip“ herunterladen, dann entpacken und öffnen. Da gibt es ein Unterordner namens „Portable“, diesen nehmen und in die auf dem Mac installiere Arduino IDE und da in den Unterordner „Java“ ziehen.

Noch sind wir nicht ganz fertig, wir gehen noch unter „Werkzeuge“ auf „Boardverwalter“, da gibt es ganz viele Boards. Wir gehen auf „ESP Community“ Package und führen ggf. eine Update durch.

Bei „Werkzeuge“ wählen wir noch unter Port: „/dev/cu.SLAB…“ aus. Als Board stellen wir „Generic ESP8266 Module“ ein. Mehr müßen wir nicht einstellen.

Sollte etwas beim flashen der Software auf das Board nicht klappen, vielleicht mal ein anderes USB Kabel verwenden.

Verkabelung

Gelb an D1, Weiß an D2, Schwarz an GND und Rot and 3V.

Wir verkabeln an den Node MCU wie folgt und löten dann ggf.:

Node MCU BeinchenI2C / Grove Kabel
3,3 Vrot
GNDschwarz
D1gelb / SCL
D2weiß / SDA

Hier können wir die Kabel auch schon an den Node MCU anlöten. Danach stecken wir auf dem I2C Hub sowohl das Kabel an das Grove LCD Display als auch an den SCD 30 CO2 Sensor.

Auch hier werden wir löten müßen.
SensorKabel
VINrot
GND (schlecht zu lesen)schwarz
SCLgelb
RXSDAweiß
Verkabelungsschema

Die Umweltwerkstatt Birkenfeld hat die Überlegungen, Hintergründe und ein wenig eine Anleitung auch auf ihrer Website zusamemngefasst.

Fertiger Programcode

Im CCC haben wir es uns nicht nehmen lassen, einen fertigen Programcode zu machen. Dieser Code hat noch einige Schmankerl: Er zeigt neben CO2, auch Temperatur und Luftfeuchte an, ab 900 ppm CO2 zeigt er auch im LCD Display Alarm an. Daneben ist auch WLAN und die Möglichkeit die Daten per MQTT zu versenden eingetragen. Das braucht man nicht notwendigerweise, kann aber hilfreich sein.

Nutzen wir Ardublockly nicht, müßen wir noch folgende Dinge mit der Arduino IDE machen: Im Board Manager, der findet sich unter Datei/Einstellungen, ganz unten bei „zusätzliche Boardmanager“ den Link http://arduino.esp8266.com/stable/package_esp8266com_index.json eintragen.

Jetzt noch das Node MCU als ESP 8266 im Boardmanager suchen und installieren.

Jetzt im Board Manager „Node MCU suchen“ und dann wird die ESP8266 Community Version angezeigt, diese wollen wir installieren.

Unter Linux müßte man ggf. den Benutzer noch der Dialout Gruppe hinzufügen und neu einloggen.

Jetzt müße wir noch drei Libraries hinzufügen. Bei Werkzeuge/Bibliotheken verwalten.

Dort fügen wir „pubsubclient“, „grove lcd“ und „scd30“ hinzu.

Hier nun der Code:

/* This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details. */


#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <SparkFun_SCD30_Arduino_Library.h>
#include <Wire.h>
#include <rgb_lcd.h>

// ESP Wifi und PubSub Client sind für Wifi und Mqtt, sie werden nicht unbedingt gebraucht

String matrixausgabe_text  = " "; // Ausgabetext als globale Variable


volatile int matrixausgabe_index = 0;// aktuelle Position in Matrix


IPAddress myOwnIP; // ownIP for mDNS 


//-------------- definition mqtt-object ueber WiFi
WiFiClient   espClient; 
PubSubClient mqttclient(espClient);


//--------- list of mqtt callback functions 
#define MAX_MQTT_SUB 10 // maximal 10 subscriptions erlaubt
typedef void (*mqtthandle) (byte*,unsigned int);
typedef struct {       // Typdeklaration Callback
  String topic;        // mqtt-topic
  mqtthandle fun;      // callback function 
}
subscribe_type; 
subscribe_type mqtt_sub[MAX_MQTT_SUB];
int mqtt_sub_count=0;


String MQTT_Rx_Payload = "" ;
//--------- mqtt callback function 
void mqttcallback(char* to, byte* pay, unsigned int len) {
  String topic   = String(to);
  String payload = String((char*)pay);
  MQTT_Rx_Payload=payload.substring(0,len);
  Serial.println("\ncallback topic:" + topic + ", payload:" + MQTT_Rx_Payload);
  for (int i=0;i<mqtt_sub_count;i++) { // durchsuche alle subscriptions, bis topic passt 
    if (topic==mqtt_sub[i].topic) 
      mqtt_sub[i].fun(pay,len);         // Aufruf der richtigen callback-Funktion
  }
}


//------------ reconnect mqtt-client
void mqttreconnect() { // Loop until we're reconnected 
  if (!mqttclient.connected()) { 
    while (!mqttclient.connected()) { 
      Serial.print("Attempting MQTT connection...");
      if (mqttclient.connect("StrandiCO2")) {
        Serial.println("connected");
        for (int i=0;i<mqtt_sub_count;i++) { // subscribe topic
          mqttclient.subscribe(mqtt_sub[i].topic.c_str());
          Serial.println("\nsubscribe");
          Serial.print(mqtt_sub[i].topic);
        }
      } 
      else { 
        Serial.print("failed, rc=");
        Serial.print(mqttclient.state());
        Serial.println(" try again in 5 seconds");
        delay(5000);
      }
    }
  } 
  else { 
    mqttclient.loop(); 
  }
}

//Initialwerte vom Program gesetzt
String alarm = "" ;
int hum = 99 ;
int tmp = 99 ;
int co2 = 9999 ;
//Reading CO2, humidity and temperature from the SCD30 By: Nathan Seidle SparkFun Electronics 


//https://github.com/sparkfun/SparkFun_SCD30_Arduino_Library


SCD30 airSensorSCD30; // Objekt SDC30 Umweltsensor
//LCD RGB, 2013 Copyright (c) Seeed Technology Inc.   Author:Loovee
rgb_lcd lcd;




void setup(){ // Einmalige Initialisierung
  Serial.begin(115200);
  //----------------------------------MQTT-Client 
  mqttclient.setServer("172.16.0.69", 1883);
  mqttclient.setCallback(mqttcallback);
//hier ändern wenn man einen anderen Server für MQTT hat

  Wire.begin(); // ---- Initialisiere den I2C-Bus 


  if (Wire.status() != I2C_OK) Serial.println("Something wrong with I2C");


  if (airSensorSCD30.begin() == false) {
    Serial.println("The SCD30 did not respond. Please check wiring."); 
    while(1) {
      yield(); 
      delay(1);
    } 
  }


  airSensorSCD30.setAutoSelfCalibration(false); // Sensirion no auto calibration


  airSensorSCD30.setMeasurementInterval(2);     // CO2-Messung alle 5 s


  Serial.println();
  lcd.begin(16, 2);// LCD Backlight initialisieren 


  //------------ WLAN initialisieren 
//Wlan Name eintragen bei "my_wifi" und Passwort anstelle "topsecret" Anführungszeichen lassen!
  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);
  delay(100);
  Serial.print ("\nWLAN connect to:");
  Serial.print("my_wifi");
  WiFi.begin("my_wifi","topsecret");
  while (WiFi.status() != WL_CONNECTED) { // Warte bis Verbindung steht 
    delay(500); 
    Serial.print(".");
  };
  Serial.println ("\nconnected, meine IP:"+ WiFi.localIP().toString());
  matrixausgabe_text = " Meine IP:" + WiFi.localIP().toString();
  myOwnIP = WiFi.localIP();
  matrixausgabe_index=0;




  Wire.setClock(100000L);            // 100 kHz SCD30 
  Wire.setClockStretchLimit(200000L);// CO2-SCD30
}


void loop() { // Kontinuierliche Wiederholung 
  delay(2000);
  co2 = airSensorSCD30.getCO2() ;
  tmp = airSensorSCD30.getTemperature();
  hum = airSensorSCD30.getHumidity();
  alarm = "      ";
  if (co2 > 900) alarm = "Alarm";  
  Serial.print("co2 (ppm) : "+String(String(co2)));
  Serial.println();
  lcd.setCursor(0,0);
  lcd.print(String(String(String(co2)))+"ppm co2 ");
  lcd.setCursor(0,1);
  lcd.print(String(String(String(tmp))+"'C "+String(String(hum)))+"% "+String(String(alarm)));
  mqttreconnect();
  {
    String pay=String("CO2:_"+String(String(co2)));
    mqttclient.publish("CO2",pay.c_str());
    Serial.print("\nmqtt publish: "); 
    Serial.print(pay);
  };
}

Schlagwörter: , , , , , ,

Hinterlasse einen Kommentar

Diese Seite verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden..