Ankündigung

Einklappen
Keine Ankündigung bisher.

Arduino-Sensor für CO² bzw. VOC

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • ThorstenGehrig
    antwortet
    So - der Sensor läuft und liefert schön Werte. Letzte Nacht mal den "Luftverbrauch" im Schlafzimmer gemessen - liefert eine schöne Kurfe (siehe Anhang).
    Man kann schön erkennen dass ich um 22 Uhr ins Bett bin - ab ca. 6Uhr keiner mehr auf der Etage war - und ab 8 Uhr die KWL die Luft komplett ausgetauscht hat.
    Interessant ist auch am ende - heute 19 Uhr - sind die Kinder auf der Etage und due Luftqualität ist bis ins Schlafzimmer "beeinträchtigt".

    Mal schauen wie ich damit die KWL steuern kann. Ich werde auch mal versuchen einen VOC in die KWL Zuluft reinzuhängen um schlechte Luft von außen zu detektieren (Nachtbar Grillt etc.)

    Zum Lesen gebe ich auch mal meinen aktzellen Code.
    Hier wird sowohl periodisch gesendet (derzeit alle 30 Sekunden) wenn sich der Wert geändert hat - als auch das Lesen über KNX unterstützt.
    Ich hab noch einige "delay" zwischen den Lesebefehlen zur sicherheit eingebaut...
    Code:
    // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
    // is used in I2Cdev.h
    #include "Wire.h"
    
    // I2Cdev and IAQ2000 must be installed as libraries, or else the .cpp/.h files
    // for both classes must be in the include path of your project
    #include "I2Cdev.h"
    #include "IAQ2000.h"
    
    //KNX
    #include <KnxTpUart.h>
    #define KNX_PHYSICAL_ADRESS                 "1.1.77"
    #define KNX_WRITE_GROUPADRESS_STATUS        "7/0/200"
    #define KNX_WRITE_GROUPADRESS_CO2           "7/0/201"
    #define KNX_WRITE_GROUPADRESS_TVOC          "7/0/202"
    #define KNX_SEND_INTERVAL_MS                30000
    
    KnxTpUart knx(&Serial, KNX_PHYSICAL_ADRESS);
    
    // class default I2C address is 0x5A
    // specific I2C addresses may be passed as a parameter here
    // but this device only supports one I2C address (0x5A)
    IAQ2000 iaq;
    
    uint16_t airQuality;
    uint8_t iAQstatus;
    uint16_t airTvoc;
    
    unsigned long startTime;
    uint16_t oldairQuality;
    uint8_t oldiAQstatus;
    uint16_t oldairTvoc;
    
    bool result;
    
    void setup() {
      // join I2C bus (I2Cdev library doesn't do this automatically)
      Wire.begin();
    
      Serial.begin(19200);
      while (!Serial) {
        ; // wait for serial port to connect
      }
      UCSR0C = UCSR0C | B00100000;
    
      // Reset UART
      knx.uartReset();
    
      startTime = millis();
    
      delay(1000);
      iaq.initialize();
      // test of IAQ. Send a to STATUS-KO a 2 if all is fine - and a 3 if the iaq does not work
      iaq.testConnection() ? result = knx.groupWrite1ByteInt(KNX_WRITE_GROUPADRESS_STATUS, 2) : result = knx.groupWrite1ByteInt(KNX_WRITE_GROUPADRESS_STATUS, 3);
      delay(1000);
    
      // Register Addresses for read-requests
      knx.addListenGroupAddress(KNX_WRITE_GROUPADRESS_STATUS);
      knx.addListenGroupAddress(KNX_WRITE_GROUPADRESS_CO2);
      knx.addListenGroupAddress(KNX_WRITE_GROUPADRESS_TVOC);
    
    }
    
    void loop() {
      if (abs(millis() - startTime) < KNX_SEND_INTERVAL_MS) {
        delay(1);
        return;
      }
    
      startTime = millis();
    
      // read sensor status
      iAQstatus = iaq.getIaqstatus();
      if (iAQstatus != oldiAQstatus) {
        result = knx.groupWrite1ByteInt(KNX_WRITE_GROUPADRESS_STATUS, iAQstatus);
      }
      oldiAQstatus = iAQstatus;
    
      delay(1000);
    
      // read seansor CO2
      airQuality = iaq.getIaqpred();
      if (airQuality != oldairQuality) {
        result = knx.groupWrite2ByteInt(KNX_WRITE_GROUPADRESS_CO2, airQuality);
      }
      oldairQuality = airQuality;
    
      delay(1000);
    
      // read seansor TVoc
      airTvoc = iaq.getIaqtvoc();
      if (airTvoc != oldairTvoc) {
        result = knx.groupWrite2ByteInt(KNX_WRITE_GROUPADRESS_TVOC, airTvoc);
      }
      oldairTvoc = airTvoc;
    }
    
    
    void serialEvent() {
      //Get Serial Event
      KnxTpUartSerialEventType eType = knx.serialEvent();
    
      //Check Serial Event
      if (eType == KNX_TELEGRAM) {
        KnxTelegram* telegram = knx.getReceivedTelegram();
    
        // Telegrammauswertung auf KNX (bei Empfang immer notwendig)
        String target =
          String(0 + telegram->getTargetMainGroup())   + "/" +
          String(0 + telegram->getTargetMiddleGroup()) + "/" +
          String(0 + telegram->getTargetSubGroup());
          //result = knx.groupWrite14ByteText("0/0/130", target );
    
        // Auswertung der Gruppenadresse des empfangenen Telegrammes und Zwischenspeicherung in Variable target
        if (telegram->getCommand() == KNX_COMMAND_READ) {
          if (target == KNX_WRITE_GROUPADRESS_TVOC) {
            airQuality = iaq.getIaqpred();
            result = knx.groupAnswer2ByteInt(KNX_WRITE_GROUPADRESS_TVOC, airQuality);
            oldairTvoc = airTvoc;
          }
          if (target == KNX_WRITE_GROUPADRESS_CO2) {
            airTvoc = iaq.getIaqtvoc();
            result = knx.groupAnswer2ByteInt(KNX_WRITE_GROUPADRESS_CO2, airTvoc);
            oldairQuality = airQuality;
          }
          if (target == KNX_WRITE_GROUPADRESS_STATUS) {
            iAQstatus = iaq.getIaqstatus();
            result = knx.groupAnswer1ByteInt(KNX_WRITE_GROUPADRESS_STATUS, iAQstatus);
            oldiAQstatus = iAQstatus;
          }
        }
      }
    }
    Mann kann sicherlich erkennen das ich ein "copy&paste programmierer" bin... aber es läuft.
    Danke an alle Code-Spender :-)

    Nachtrag: was man noch ändern könnte/sollte: bisher wird alle "send-intervall"-Sekunden die Werte gesendet - wenn Sie sich denn verändert haben.
    Manchmal springt der CO2 oder VOC-Wert nur +-1... das muss man nicht unbedigt senden.
    Daher könnte man auch nur senden wenn die Variablen mehr als 10 kleiner oder gößer sind...
    Müsste so gehen, oder?
    Code:
    if ((airQuality >= oldairQuality+10) || (airQuality <= oldairQuality-10)) {
    Gruß
    Thorsten
    Angehängte Dateien
    Zuletzt geändert von ThorstenGehrig; 19.11.2015, 20:51.

    Einen Kommentar schreiben:


  • dreamy1
    antwortet
    Hi Thorsten,

    freut mich dass es jetzt läuft!

    Einen Kommentar schreiben:


  • ThorstenGehrig
    antwortet
    Gefunden und Gefixt!
    Die (zumindest meine alte) Arduino Lib hatte die groupWrite2ByteInt nicht richtig implementiert.
    Meine Lib ist nun gefixt - die Werte passen jetzt :-)

    Einen Kommentar schreiben:


  • ThorstenGehrig
    antwortet
    Hi,
    alte männer soll man nicht Löten lassen!
    Ich hab den Pegelwandler 180 Grad gedreht verwendet - damit passte natürlich nichts mehr.
    Kein Wunder das nichts ging - und ein wunder das es noch geht.
    Jetzt läuft alles wie es soll. Die IAQ2000-Library hatte noch einen Bug - den ich aber korrigiert habe. Das commit ist auf Github und vermutlich morgen bestätigt.
    Hier mein Link: https://github.com/thorsten-gehrig/i2cdevlib

    Jetzt muss ich meinen Code noch verschöndern - und vermutlich alles nochmal sauber aufbauen (derzeit sieht das "übel" aus).

    Gruß
    Thorsten (ich muss zum Optiker mir ne Lesebrille besorgen)

    Nachtrag: noch ein BUG oder Programmierfehler?
    Wenn ich mir die Werte Seriell ausgeben lasse sieht alles gut aus - aber auf dem Bus kommen falsche werte :-(
    Code:
     uint16_t airQuality;
    airQuality = iaq.getIaqpred();
      result = knx.groupWrite2ByteInt(KNX_WRITE_GROUPADRESS_CO2, airQuality);
     Serial.print("CO2 = ");
     Serial.print(airQuality);
    Laut Doku sind Pred und Tvoc ja beides uint16.
    Wie geschrieben werden mir seriell gültige Werte ausgegeben.
    Auf dem HS habe ich 16 Bit / EIS10 (0-65535) angegeben... die Werte sind aber nicht die selben...
    Hier ein eibd:
    2015-11-17 21:13:52.326,A_GroupValue_Write,1.1.77,7/0/202,1E 27,,,,0,low,6,T_DATA_XXX_REQ,0
    2015-11-17 21:14:22.343,A_GroupValue_Write,1.1.77,7/0/202,1E 1B,,,,0,low,6,T_DATA_XXX_REQ,0

    Ich vermute mal "knx.groupWrite2ByteInt" passt nicht? Ist ja meine Lib - aber ich habe schon lange nicht mehr drann geschraubt. Eigentlich ist "2 byte Int (DTP 7 - 0…65 535])" und DTP8 (-32768 bis +32768) == EIS10.... arg.

    Ein simples "knx.groupWrite2ByteInt(KNX_WRITE_GROUPADRESS_ CO2, 450);" zeit mir am Homeserver aber keine 450 an....

    Gruß
    Thorsten
    Zuletzt geändert von ThorstenGehrig; 17.11.2015, 21:34.

    Einen Kommentar schreiben:


  • dreamy1
    antwortet
    Ja, genau so!

    Einen Kommentar schreiben:


  • ThorstenGehrig
    antwortet
    Also den Pin5 vom BCU (5v) auf HW beim Pegelwandler (wie jetzt schon) und RAW beim Arduino an (statt VIN beim Regler).
    Die 3,3 Volt schiene müsste dann ja schon passen (am Arduino kommen dann ja 3.3V raus).
    Richtig?

    Gruß
    Thorsten

    Einen Kommentar schreiben:


  • dreamy1
    antwortet
    Ich nehme auf meinen gerade aktuellen Platinenentwürfen nur noch den internen Längsregler...wenn man sich das alles durch den Kopf gehen lässt, sind die Verluste doch recht vernachlässigbar.

    Einen Kommentar schreiben:


  • dreamy1
    antwortet
    Das ist nur ein doofer Längsregler...da kannst Du auch gleich den internen aufm Arduino nehmen :-)

    Einen Kommentar schreiben:


  • ThorstenGehrig
    antwortet
    Ja - klar. Daher messe ich ja auch die 3,05 Volt wenn ich per USB Adapter versorge.
    Scheinbar hat der Arduino und der VOC aber schon mehrfach die 5V überstanden (uff).
    Ich hab mir jetzt mal den Spannungsregler bestellt:
    http://www.ebay.de/itm/5x-AMS1117-3-...0AAOSwpDdVewDI
    Vielleicht läuft der besser als der Pololu bei mir...

    Gruß
    Thorsten

    Einen Kommentar schreiben:


  • dreamy1
    antwortet
    Den USB-Adapter hast Du aber hoffentlich auf 3,3V gejumpert, oder?

    Einen Kommentar schreiben:


  • ThorstenGehrig
    antwortet
    Hi
    wenn ich am USB bin - ist der Polou ja nicht in Betrieb. Die Spannung kommt dann vom USB-Adapter...
    Ich muss mal schauen ob ich eine andere Spannungsquelle an den Eingang des Pololu anschließe und ob er dann besser funktioniert.

    Gruß
    Thorsten

    Einen Kommentar schreiben:


  • dreamy1
    antwortet
    Also wenns am USB funktioniert, wird der Pololu nicht defekt sein. Möglicherweise ist auf dem 5V-Zweig der BCU ein Ripple drauf, der dem Pololu nicht gefällt und ihn am Ausregeln hindert...oder der Pegelwandler hat nen Schuss weg.

    Alternativ würde ich den Pololu und Pegelwandler halt dann doch weglassen. Am TX der BCU einen einfachen Spannungsteiler zum RX des Arduino und die 5V auf den RAW des Arduino. TX des Arduino direkt auf den RX der BCU. Rest dann über den 3,3V-Ausgang des Arduino...

    Einen Kommentar schreiben:


  • ThorstenGehrig
    antwortet
    So - heute mal wieder am basteln. Am Step-Down-Converter have ich mal zwischen VIN und SHDN eine Brücke gelötet - müsste aber nicht nötig sein durch integrierten Pull-Up sollte der eh auf high gezogen werden.
    Zwischen VIN und GND messe ich so 4,8V mit meinem alten digitalmultimeter - zwischen VOUT und GND aber AUCH(!!)
    Wenn ich meine Schaltung am USB angeschlossen habe messe ich nur 3,05...
    Kann es sein dass der Step-Down kaputt ist?
    Wenn der Arduino am BCU angeschlossen ist heutet die LED auch "viel heller"... und wenn am Pegelwandler auf beiden Seiten 5V TTL anlegt würde es auch erklären warum ich nichts auf den Bus kriege...

    Gruß
    Thorsten

    Einen Kommentar schreiben:


  • ThorstenGehrig
    antwortet
    Hi
    Strom habe ich nun - der Arduino "rennt" - allerdings scheint mir die rote Power-LED heller zu leuchten als am TTL Interface... muss mal nachmessen ob da 5 Volt ankommen :.-( (bisher haben es Arduino und VOC überlebt).
    Außerdem schreibt er mir nicht auf den Bus :-( - muss wohl mal schauen ob der Pegelwandler was ausgibt...
    Heute hab ich leider keine Zeit mehr - vermutlich nächstes Wochenende gehts weiter.

    Gruß
    Thorsten

    Einen Kommentar schreiben:


  • dreamy1
    antwortet
    Und klemme den VOC vorsichtshalber mal vorher ab :-)

    Einen Kommentar schreiben:

Lädt...
X