Messung CO2 Luftfeuchtigkeit Z-Wave XBee Arduino

Die hier machen VOC und extra nochmal CO2…
SENSOAIR - SIEGENIA AUBI - Solutions Inside

Habe gerade ein CO2-Sensor-OEM-Modul von MB bestellt. Werde es mal so richtig testen und dann meine Erfahrungen hier loswerden.

Hier ist einer meld :wink: Arduino-Uno, Fio, JeeNode-Clones, alles an Bord :cool:

Hallo sysrun,

diese JeeNode hören sich ja sehr interessant an! Wie bist du damit zufrieden? Hast du die in IPS eingebunden?

Ich bin gerade dabei, ein Board zu entwerfen mit einem FIO und einem SHT11 und serieller Schnittstelle zu einem CO2 Sensor. Wenn ich so rechne, kommt mir nur das FIO mit dem XBEE auf so ca. 50 Euro. Da bekomme ich aber auch schon ein JeeNode+JeeLink. Und die Interface-boards gibts auch schon fertig.

Kannst du mal kurz deine Erfahrungen mit den JeeNodes im Vergleich zum XBee sagen? Jetzt könnte ich mein Projekt noch stoppen und auf Jee umsteigen.

Gruß
Rubberduck

Also ich habe derzeit schon 8 JeeNodes und diverse „Plugs“ für verschiedene Dinge im Einsatz. Die Modularität ist echt genial.

Wenn du nicht dringend eine schnelle RS232-Funkstrecke brauchst oder Mesh (Point-to-Multipoint) machen willst sind die dinger echt eine Alternative. Klein, RF-Funktionalität im 868Mhz-Bereich. Und die passenden Arduino-Libraries für die Kommunikation über Funk.

Du kannst mir 3 Befehlen Daten senden und musst dir um CRC o.Ä. keine Gedanken machen. Ist alles implementiert. Für jeden Node musst du eine eindeutige ID vorgeben und das „Subnetz“ in dem es spricht. Ziemlich easy alles.

Nachteil ist das du pro Sendevorgang nur ca. 60 Bytes Nutzdaten hast und das die Daten dann vom JeeLink einfach per Serial an IPS ankommen. Da musst du dann die Daten per PHP auseinandernehmen. Aber das musst du ja bei der XBEE-Lösung auch.

Der Support zu den Dingern ist echt genial; in dem Forum findest du alles und bekommst auch reichlich antworten.

Schau dich einfach mal im Blog um (jeenode.org). Lies alles von vorne bis hinten. So hab ich mich infiziert. :slight_smile:

Hier nen Post über den SHT11: http://jeelabs.org/2009/02/17/hooking-up-an-sht11-sensor/

Das klingt easy. Ich denke, ich werde mich da mal einlesen und so wie ich mich kenne, bald auch zuschlagen :rolleyes:

jou, dann oute ich mich mal:

  • duemilanove
  • xbee; aber keine Zeit
  • Lötkolben…

Gruß Joachim

Dürfte ziemlich ansteckend sein. Bin auch schon infiziert:D

Hab gerade geschafft, dass meine beiden Jeenodes miteinander Daten austauschen. War wirklich eine leichte Übung. Als nächster Schritt kommt der CO2-Sensor über RS232 auf eine I/O (Sensor liegt schon da) und dann gehts auch schon ab ins IPS.

Na, wie ist dein Status?

Schaut schon gut aus! Aktueller Status: JeeNode wertet CO2-Sensor und DS1820 aus und sendet Daten zyklisch zum JeeLink, welcher am PC steckt. Wenn ich endlich das Steckernetzteil von ELV bekomme wird alles fix verbaut und dann gleich in IPS eingebunden… Und dann hab ich schon eine Menge Ideen für die nächsten Jeenodes.

Witziges Detail: ELV schreibt mir Mitte Februar, dass das Netzteil Anfang Februar nachgeliefert wird. Hoffe ja nur, die meinen nicht 2012.

@ Rubberduck: holst du dir die MB-CO2-SensorDaten über die UART- oder über die CON1-Schnittstelle auf den JeeNode? … direkt auf einen Port oder über ein Plug?

Hast Du den JeeNode-Sketch irgendwo veröffentlicht? … oder kannst du ihn verfügbar machen?

DANKE und weiterhin viel Erfolg mit IPS und den JeeNodes.

Hi Bauhaus,

sorry für die späte Antwort. Bin zur Zeit mehr auf Dienstreise als zu Hause.

Also, ich habe es der Einfachheit halber doch nicht über die serielle Schnittstelle realisiert sondern über das PWM-Signal des CO2-Sensor. Das funktioniert auch bestens.

Das ist der Sketch. Bitte mit Nachsicht betrachten. Ist mein erster Sketch. Großteil ist sowieso von diversen Quellen zusammenkopiert.


#include <Ports.h>
#include <RF12.h>
#include <avr/sleep.h>
#include <util/atomic.h>
#include <OneWire.h>
#include <DallasTemperature.h>


#define SERIAL  1   // set to 1 to also report readings on the serial port
#define DEBUG   0   // set to 1 to display each loop() run and PIR trigger

#define RADIO_SYNC_MODE 2
#define MEASURE_PERIOD  50 // how often to measure, in tenths of seconds

#define ONE_WIRE_BUS 5  //Pin für DS18B20
#define CO2_PWM      4  //Pin für CO2-Sensor 

static byte myNodeID = 10;   // node ID used for this unit

// This defines the structure of the packets which get sent out by wireless:
struct {
    byte control; // status-/controlbyte der I/O (D0..BootUp - Data invalid)
    int temp   :10; // temperature: -500..+500 (tenths)
    int co2; //CO2 Wert in ppm
    byte lobat :1;  // supply voltage dropped under 3.1V: 0..1
} payload;

// The scheduler makes it easy to perform various tasks at various times:
enum { MEASURE, REPORT, TASK_END };
static word schedbuf[TASK_END];
Scheduler scheduler (schedbuf, TASK_END);

// Other variables used in various places in the code:
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire);// Pass our oneWire reference to Dallas Temperature. 
DeviceAddress insideThermometer;// arrays to hold device address


// has to be defined because we're using the watchdog for low-power waiting
ISR(WDT_vect) { Sleepy::watchdogEvent(); }

//----------------------------------------------------------------------------------------

//function berechnet vergangene Zeit in ms
unsigned long elapsed_ms(unsigned long start) {
  unsigned long t;
  
  //aktuellen Zeitpunkt holen
  unsigned long now = millis();
  //delta ausrechnen
  //kein overflow?
  if (start <= now) 
  {
    return now - start;
  }else{ //overflow
    return 4294967295 - start + now;
  }    
  
}  




// function misst die Pulselänge in ms
unsigned long pulseIn_ms(int Pin){
  unsigned long t1;
  
  t1 = millis();
  //Warte bis 1->0 Flanke
  while (digitalRead(Pin)==HIGH)  if (elapsed_ms(t1) > 1500)  return 0;
  t1 = millis();
  //Warte bis 0->1 Flanke
  while (digitalRead(Pin)==LOW)  if (elapsed_ms(t1) > 1500)  return 0;
  t1 = millis();
  //Warte bis 1->0 Flanke
  while (digitalRead(Pin)==HIGH)  if (elapsed_ms(t1) > 1500)  return 0;
  t1 = elapsed_ms(t1);
  return t1;

}




// readout all the sensors and other values
static void doMeasure() {

    //Versorgungsproblem des Funkmodul melden
    payload.lobat = rf12_lowbat();
    
    //CO2 Sensor-Pulselänge ermitteln
    payload.co2 = pulseIn_ms(CO2_PWM) * 2;

    //1-Wire DS18B20 Sensor
    sensors.requestTemperatures(); // Send the command to get temperatures
    delay(1000);
    payload.temp =sensors.getTempC(insideThermometer)*10; //Readout temperature
    
}

// periodic report, i.e. send out a packet and optionally report on serial port
static void doReport() {
    rf12_sleep(-1);
    while (!rf12_canSend())
        rf12_recvDone();
    rf12_sendStart(0, &payload, sizeof payload);
    rf12_sendWait(0);
    rf12_sleep(0);

    #if SERIAL
        Serial.print("Send ");
        Serial.print((int) payload.temp);
        Serial.print(' ');
        Serial.print((int) payload.co2);
        Serial.print(' ');
        Serial.print((int) payload.lobat);
        Serial.println();
        delay(2); // make sure tx buf is empty before going back to sleep
    #endif
}



// function to print a 1-Wire device address
void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}
//----------------------------------------------------------------------------------------

void setup () {
    Serial.begin(57600);
    Serial.print("
Sensor Node Schlafzimmer");
    Serial.print("
");
    rf12_initialize(myNodeID, RF12_868MHZ, 15);

    //1-Wire boot-up
    // locate devices on the bus
    Serial.print("Locating 1-Wire devices...");
    sensors.begin();
    Serial.println("done");
    Serial.print("  Found ");
    Serial.print(sensors.getDeviceCount(), DEC);
    Serial.println(" devices.");
    // report parasite power requirements
    Serial.print("  Parasite power is: "); 
    if (sensors.isParasitePowerMode()) Serial.println("ON");
    else Serial.println("OFF");
    if (!sensors.getAddress(insideThermometer, 0)) Serial.println("  Unable to find address for Device 0"); 
    Serial.print("  Device 0 Address: ");
    printAddress(insideThermometer);
    Serial.println();
    // set the resolution to 9 bit (Each Dallas/Maxim device is capable of several different resolutions)
    sensors.setResolution(insideThermometer, 12);
    Serial.print("  Device 0 Resolution: ");
    Serial.print(sensors.getResolution(insideThermometer), DEC); 
    Serial.println();



    // CO2-Sensor Eingang init
    pinMode(CO2_PWM,INPUT);
    digitalWrite(CO2_PWM,HIGH);

    
    //Bootup-Flag setzen und senden
    Serial.print("Send bootup...");
    payload.control = 1;
    //senden
    while (!rf12_canSend())
        rf12_recvDone();
    rf12_sendStart(RF12_HDR_ACK, &payload, sizeof payload);
    rf12_sendWait(0);
    //BootUp_flag löschen
    payload.control = 0;
    Serial.println("done");
    rf12_sleep(0); // power down
    
    // start the measurement loop going
    scheduler.timer(MEASURE, 0);    
}

//----------------------------------------------------------------------------------------

void loop () {
    #if DEBUG
        Serial.print('.');
        delay(2);
    #endif

    switch (scheduler.pollWaiting()) {

        case MEASURE:
            // reschedule these measurements periodically
            scheduler.timer(MEASURE, MEASURE_PERIOD);
    
            doMeasure();

            //do report next
            scheduler.timer(REPORT, 0);
            break;
            
        case REPORT:
            doReport();
            break;
    }
}

Den IPS-Teil habe ich noch nicht. Warte noch immer auf mein Netzteil. Danach wird programmiert. Aber immerhin, die Versandbestätigung ist schon da.

Gruß
Rubberduck

hallo rubberduck,
darf ich fragen welchen sensor du bei dir einsetzt?
ich frage weil ich auch an einem sensor für 1-wire dran bin.

ciao
andrge

Hallo Rubberduck;

Danke für den Sketch; werde ich am Wochenende gleich probieren. Im Ziel möchte ich schon den UART abfragen. Mir sind noch die Pegel unklar; habe dazu eine Supportanfrage beim Hersteller offen.

… und dann wünsche ich dir eine baldige Zustellung des Netzteils … :wink:

@ Andreas: ich denke: MB-Systemtechnik ? Produkte für CO2-/CO-/O3-/VOC-Messung (CO2 Ampel, Sensoren, Messgeräte) - Startseite

Gruß
Bauhaus

@andrge: bauhaus hat recht. Ist ein „SEN CO2 S 100“ von mb-systemtechnik.

@bauhaus: warum den uart? PWM ist genauso genau und bedeutet weniger Aufwand (PWM Ausgang -> Vorwiderstand -> JeeNode Eingang)

Habe die Teile heute mal ins Gehäuse eingebaut. Werde in den nächsten Tagen den IPS-Teil „schnitzen“. Ach ja, bevor sich jemand wundert: Ich habe die IO-Pins geändert. Im Sketch sind noch andere. Wollte aber nur eine Sub-Print machen.

Gruß
Rubberduck

… Du hast Recht - PWM ist einfacher – aber warum einfach wenn´s auch kompliziert geht?

noch ne Frage: Die Decodierung der payload(s) – machst du das auf dem JeeLink oder in IPS?

:confused:verstehe die Frage nicht so ganz. Aber gerade ist der erste IPS-Testcode fertig geworden:

<?
	
   //Buffer auslesen: Dateneingang ist Register Variable
   $buffer = $IPS_VALUE;

	IPS_LogMessage("TEST",$buffer);
	
	//valide Telegrammlänge?
	if (strlen($buffer) > 5)
	{

      $data = explode(" ",$buffer);

	   //Daten von Unterstation
	   if ($data[0]=="OK")
	   {
	      //Station extrahieren
			$station = $data[1] & 0x1f;
			//nur mehr Nutzdaten überlassen
			$data = array_slice($data,2);
			
			//Daten stationsabhängig decodieren
			switch ($station)
			{
			
				case 10: //Node#10 Schlafzimmer
					$temp = ($data[1] + $data[2]*256)/10;
					$co2 = $data[3] + $data[4]*256;
					IPS_LogMessage("JeeLink", "temp:".$temp."  co2:".$co2);
					break;
			
			
			   default:
			      IPS_LogMessage("JeeLink","Station not found: ".$buffer);
			   
			}
	   }
	}
	
	

?>

Aufbau: Serial-Port Instanz versorgt Cutter Instanz. Im Cutter sind als rechte Trennzeichen 0D 0A eingetragen und als Timeout 500. Am Cutter hängt eine Register-Variable Instanz welche dann das Script aufruft.
Serial Port -> Cutter -> Register Variable -> Script