Serial Data Sensor is there an example sketch? I need help!
-
I everyone! just started using mysensors to monitor my house air quality! but i don't know if its possible this thing: i have some air quality sensors that output data to serial uart, i see it on a terminal like this:
Temperature:21.75 ,Humidity:60.66 ,Pressure:101254 ,IAQ:47 ,Gas:119387 ,Altitude:5 ,IAQ_accuracy:1
is there some serial data read mysensor sensor sketch? i don't know much of developing, but i tried to modify the AirQualitySensor mysensors sketch
this is the original working arduino sketch that asks and grabs data from the sensor and outputs it to terminal console:
//GY_MCU680 air quality sensor ARDUINO #include <SoftwareSerial.h> SoftwareSerial mySerial(4, 5); uint16_t temp1=0; int16_t temp2=0; unsigned char Re_buf[30],counter=0; unsigned char sign=0; int led = 13; void setup() { Serial.begin(9600); mySerial.begin(9600); mySerial.listen(); delay(4000); mySerial.write(0XA5); mySerial.write(0X55); mySerial.write(0X3F); mySerial.write(0X39); delay(100); mySerial.write(0XA5); mySerial.write(0X56); mySerial.write(0X02); mySerial.write(0XFD); delay(100); } void loop(){ float Temperature ,Humidity; unsigned char i=0,sum=0; uint32_t Gas; uint32_t Pressure; uint16_t IAQ; int16_t Altitude; uint8_t IAQ_accuracy; while (mySerial.available()) { Re_buf[counter]=(unsigned char)mySerial.read(); if(counter==0&&Re_buf[0]!=0x5A) return; if(counter==1&&Re_buf[1]!=0x5A) { counter=0; return; }; counter++; if(counter==20) { counter=0; sign=1; } } if(sign) { sign=0; if(Re_buf[0]==0x5A&&Re_buf[1]==0x5A ) { for(i=0;i<19;i++) sum+=Re_buf[i]; if(sum==Re_buf[i] ) { temp2=(Re_buf[4]<<8|Re_buf[5]); Temperature=(float)temp2/100; temp1=(Re_buf[6]<<8|Re_buf[7]); Humidity=(float)temp1/100; Pressure=((uint32_t)Re_buf[8]<<16)|((uint16_t)Re_buf[9]<<8)|Re_buf[10]; IAQ_accuracy= (Re_buf[11]&0xf0)>>4; IAQ=((Re_buf[11]&0x0F)<<8)|Re_buf[12]; Gas=((uint32_t)Re_buf[13]<<24)|((uint32_t)Re_buf[14]<<16)|((uint16_t)Re_buf[15]<<8)|Re_buf[16]; Altitude=(Re_buf[17]<<8)|Re_buf[18]; Serial.print("Temperature:"); Serial.print(Temperature); Serial.print(" ,Humidity:"); Serial.print(Humidity); Serial.print(" ,Pressure:"); Serial.print(Pressure); Serial.print(" ,IAQ:"); Serial.print(IAQ); Serial.print(" ,Gas:"); Serial.print(Gas ); Serial.print(" ,Altitude:"); Serial.print(Altitude); Serial.print(" ,IAQ_accuracy:"); Serial.println(IAQ_accuracy); } delay(1000); } } }
this is me trying to figure out how to modify the AirQualitySensor mysensors sketch to work with my own sensor:
//GY_MCU680 ARDUINO modified to work on mysensors platform #include <SoftwareSerial.h> SoftwareSerial mySerial(4, 5); uint16_t temp1=0; int16_t temp2=0; unsigned char Re_buf[30],counter=0; unsigned char sign=0; int led = 13; // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_NRF5_ESB //#define MY_RADIO_RFM69 //#define MY_RADIO_RFM95 #include <MySensors.h> #define CHILD_ID_MQ 0 MyMessage msg(CHILD_ID_MQ, V_LEVEL); void setup() { Serial.begin(9600); mySerial.begin(9600); mySerial.listen(); delay(5000); mySerial.write(0XA5); mySerial.write(0X55); mySerial.write(0X3F); mySerial.write(0X39); delay(200); mySerial.write(0XA5); mySerial.write(0X56); mySerial.write(0X02); mySerial.write(0XFD); delay(200); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Air Quality Sensor", "1.0"); // Register all sensors to gateway (they will be created as child devices) present(CHILD_ID_MQ, S_AIR_QUALITY); } void loop(){ float Temperature ,Humidity; unsigned char i=0,sum=0; uint32_t Gas; uint32_t Pressure; uint16_t IAQ; int16_t Altitude; uint8_t IAQ_accuracy; while (mySerial.available()) { Re_buf[counter]=(unsigned char)mySerial.read(); if(counter==0&&Re_buf[0]!=0x5A) return; if(counter==1&&Re_buf[1]!=0x5A) { counter=0; return; }; // 检查帧头 counter++; if(counter==20) { counter=0; sign=1; } } if(sign) { sign=0; if(Re_buf[0]==0x5A&&Re_buf[1]==0x5A ) { for(i=0;i<19;i++) sum+=Re_buf[i]; if(sum==Re_buf[i] ) { temp2=(Re_buf[4]<<8|Re_buf[5]); Temperature=(float)temp2/100; temp1=(Re_buf[6]<<8|Re_buf[7]); Humidity=(float)temp1/100; Pressure=((uint32_t)Re_buf[8]<<16)|((uint16_t)Re_buf[9]<<8)|Re_buf[10]; IAQ_accuracy= (Re_buf[11]&0xf0)>>4; IAQ=((Re_buf[11]&0x0F)<<8)|Re_buf[12]; Gas=((uint32_t)Re_buf[13]<<24)|((uint32_t)Re_buf[14]<<16)|((uint16_t)Re_buf[15]<<8)|Re_buf[16]; Altitude=(Re_buf[17]<<8)|Re_buf[18]; Serial.print("Temperature:"); Serial.print(Temperature); Serial.print(" ,Humidity:"); Serial.print(Humidity); Serial.print(" ,Pressure:"); Serial.print(Pressure); Serial.print(" ,IAQ:"); Serial.print(IAQ); Serial.print(" ,Gas:"); Serial.print(Gas ); Serial.print(" ,Altitude:"); Serial.print(Altitude); Serial.print(" ,IAQ_accuracy:"); Serial.println(IAQ_accuracy); } delay(1000); } } }
but i dont know what to put in the loop! can someone please helpme?
-
Hi @fosi, welcome to the MySensors community!
I think the sketch below should get you going. This is what I've done:
- Renamed setup() from the MCU680 sketch to setupMCU680()
- Renamed loop() from the MCU680 sketch to getMCU680()
- Moved the print stuff to a separate function, so it can be easily turned off
- Moved the data variables to global variables for simplicity
- Added the code from the Air temperature + humidity example
To also send Gas, Pressure and Altitude, you can probably reuse code from the following examples:
https://www.mysensors.org/build/gas
https://www.mysensors.org/build/pressure
https://www.mysensors.org/build/gpsI don't know what IAQ is, sorry.
Since I don't have a MCU680 sensor I can't test the sketch but it compiles for a Pro Mini so I think it will be fine.
//GY_MCU680 air quality sensor ARDUINO // Enable debug prints #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 //#define MY_RS485 #include <SoftwareSerial.h> #include <MySensors.h> SoftwareSerial mySerial(4, 5); uint16_t temp1 = 0; int16_t temp2 = 0; unsigned char Re_buf[30], counter = 0; unsigned char sign = 0; int led = 13; float Temperature , Humidity; uint32_t Gas; uint32_t Pressure; uint16_t IAQ; int16_t Altitude; uint8_t IAQ_accuracy; #define UPDATE_INTERVAL 1000 #define CHILD_ID_HUM 0 #define CHILD_ID_TEMP 1 MyMessage msgHum(CHILD_ID_HUM, V_HUM); MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); void setupMCU680() { Serial.begin(9600); mySerial.begin(9600); mySerial.listen(); delay(4000); mySerial.write(0XA5); mySerial.write(0X55); mySerial.write(0X3F); mySerial.write(0X39); delay(100); mySerial.write(0XA5); mySerial.write(0X56); mySerial.write(0X02); mySerial.write(0XFD); delay(100); } void getMCU680() { unsigned char i = 0, sum = 0; while (mySerial.available()) { Re_buf[counter] = (unsigned char)mySerial.read(); if (counter == 0 && Re_buf[0] != 0x5A) return; if (counter == 1 && Re_buf[1] != 0x5A) { counter = 0; return; }; counter++; if (counter == 20) { counter = 0; sign = 1; } } if (sign) { sign = 0; if (Re_buf[0] == 0x5A && Re_buf[1] == 0x5A ) { for (i = 0; i < 19; i++) sum += Re_buf[i]; if (sum == Re_buf[i] ) { temp2 = (Re_buf[4] << 8 | Re_buf[5]); Temperature = (float)temp2 / 100; temp1 = (Re_buf[6] << 8 | Re_buf[7]); Humidity = (float)temp1 / 100; Pressure = ((uint32_t)Re_buf[8] << 16) | ((uint16_t)Re_buf[9] << 8) | Re_buf[10]; IAQ_accuracy = (Re_buf[11] & 0xf0) >> 4; IAQ = ((Re_buf[11] & 0x0F) << 8) | Re_buf[12]; Gas = ((uint32_t)Re_buf[13] << 24) | ((uint32_t)Re_buf[14] << 16) | ((uint16_t)Re_buf[15] << 8) | Re_buf[16]; Altitude = (Re_buf[17] << 8) | Re_buf[18]; } } } } void setup() { sendSketchInfo("MCU680 temp+hum", "1.0"); present(CHILD_ID_HUM, S_HUM); present(CHILD_ID_TEMP, S_TEMP); setupMCU680(); } void loop() { getMCU680(); #ifdef MY_DEBUG printMCU680(); #endif send(msgTemp.set(Temperature, 1)); send(msgHum.set(Humidity, 1)); sleep(UPDATE_INTERVAL); } void printMCU680() { Serial.print("Temperature:"); Serial.print(Temperature); Serial.print(" ,Humidity:"); Serial.print(Humidity); Serial.print(" ,Pressure:"); Serial.print(Pressure); Serial.print(" ,IAQ:"); Serial.print(IAQ); Serial.print(" ,Gas:"); Serial.print(Gas ); Serial.print(" ,Altitude:"); Serial.print(Altitude); Serial.print(" ,IAQ_accuracy:"); Serial.println(IAQ_accuracy); }
-
Hi @mfalkvidd ! thank you very much for the help,
IAQ is the Index of air quality 0-500 level, its a BOSCH proprietary software that runs on a cortex arm mcu that calculates from all sensor values: temp, hum, press, gases, and some other stuff.i was trying to figure it out myself! so i did this:
/* * The MySensors Arduino library handles the wireless radio link and protocol * between your home built sensors/actuators and HA controller of choice. * The sensors forms a self healing radio network with optional repeaters. Each * repeater and gateway builds a routing tables in EEPROM which keeps track of the * network topology allowing messages to be routed to nodes. * * Created by Henrik Ekblad <henrik.ekblad@mysensors.org> * Copyright (C) 2013-2015 Sensnology AB * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors * * Documentation: http://www.mysensors.org * Support Forum: http://forum.mysensors.org * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * ******************************* * * DESCRIPTION * * BME680 GY-MCU680 UART Air Quality Sensor * * This sensor measures Temperature (xx.xx cº), Humidity (xx.xx %), Pressure, Gas (ohm), IAQ (0-500) * */ //------------------------------------------------------------------------------ // if you uncomment this, you can get test and debug updates about the sensor' wireless connection by using the serial monitor tool. #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 // A 2.4Ghz transmitter and receiver, often used with MySensors. #define MY_RF24_PA_LEVEL RF24_PA_MIN // This sets a low-power mode for the radio. Useful if you use the verison with the bigger antenna, but don't want to power that from a separate power source. It can also fix problems with fake Chinese versions of the radio. // #define MY_RADIO_RFM69 // 433Mhz transmitter and reveiver. // Libraries #include <MySensors.h> #include <SoftwareSerial.h> // Feel free to change this: unsigned long co2MeasurementInterval = 20000; // Time to wait between reads (in milliseconds). SoftwareSerial mySerial(4, 5); // RX, TX . You can choose other pins if you prefer. uint16_t temp1=0; int16_t temp2=0; unsigned char Re_buf[30],counter=0; unsigned char sign=0; //int led = 13; // Mysensors settings #define CHILD_ID_BME680 1 // The sensor' ID on this node. MyMessage msgBmeTemp(CHILD_ID_BME680, V_TEMP); MyMessage msgBmeHum(CHILD_ID_BME680, V_HUM); MyMessage msgBmePress(CHILD_ID_BME680, V_PRESSURE); MyMessage msgBmeIAQ(CHILD_ID_BME680, V_VAR1); MyMessage msgBmeGas(CHILD_ID_BME680, V_VAR2); MyMessage msgBmeIAQA(CHILD_ID_BME680, V_VAR3); void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("BOSCH Sensortec BME680 Air Quality Sensor", "1.0"); // Register attached sensor(s) to gateway present(CHILD_ID_BME680, S_CUSTOM); } void setup() { delay(1000); Serial.begin(115200); delay(1000); mySerial.begin(9600); delay(1000); mySerial.listen(); delay(3000); mySerial.write(0XA5); mySerial.write(0X55); mySerial.write(0X3F); mySerial.write(0X39); delay(200); mySerial.write(0XA5); mySerial.write(0X56); mySerial.write(0X02); mySerial.write(0XFD); delay(500); } void loop() { float Temperature ,Humidity; unsigned char i=0,sum=0; uint32_t Gas; uint32_t Pressure; uint16_t IAQ; int16_t Altitude; uint8_t IAQ_accuracy; // You should not change these variables: static unsigned long previousCo2Millis = 0; // Used to remember the time of the last temperature measurement. unsigned long currentMillis = millis(); // The time since the sensor started, counted in milliseconds. This script tries to avoid using the Sleep function, so that it could at the same time be a MySensors repeater. if (currentMillis - previousCo2Millis >= co2MeasurementInterval) { // this only gets triggered when enough time has passed. while (mySerial.available()) { Re_buf[counter]=(unsigned char)mySerial.read(); if(counter==0&&Re_buf[0]!=0x5A) return; if(counter==1&&Re_buf[1]!=0x5A) { counter=0; return; }; counter++; if(counter==20) { counter=0; sign=1; } } if(sign) { sign=0; if(Re_buf[0]==0x5A&&Re_buf[1]==0x5A ) { for(i=0;i<19;i++) sum+=Re_buf[i]; if(sum==Re_buf[i] ) { temp2=(Re_buf[4]<<8|Re_buf[5]); Temperature=(float)temp2/100; temp1=(Re_buf[6]<<8|Re_buf[7]); Humidity=(float)temp1/100; Pressure=((uint32_t)Re_buf[8]<<16)|((uint16_t)Re_buf[9]<<8)|Re_buf[10]; IAQ_accuracy= (Re_buf[11]&0xf0)>>4; IAQ=((Re_buf[11]&0x0F)<<8)|Re_buf[12]; Gas=((uint32_t)Re_buf[13]<<24)|((uint32_t)Re_buf[14]<<16)|((uint16_t)Re_buf[15]<<8)|Re_buf[16]; Altitude=(Re_buf[17]<<8)|Re_buf[18]; Serial.print("Temperature:"); Serial.print(Temperature); Serial.print(" ,Humidity:"); Serial.print(Humidity); Serial.print(" ,Pressure:"); Serial.print(Pressure); Serial.print(" ,IAQ:"); Serial.print(IAQ); Serial.print(" ,Gas:"); Serial.print(Gas ); Serial.print(" ,Altitude:"); Serial.print(Altitude); Serial.print(" ,IAQ_accuracy:"); Serial.println(IAQ_accuracy); delay(1000); // return Humidity; } } } Serial.println("BME680 - Sending data request to sensor."); previousCo2Millis = currentMillis; float temp = Temperature; float hum = Humidity; uint32_t pressu = Pressure; uint16_t iaq = IAQ; uint32_t gas = Gas; uint8_t iaqaccur = IAQ_accuracy; Serial.println("Temperature = " + String(temp)); send(msgBmeTemp.set(Temperature, 2)); Serial.println("Humidity = " + String(hum)); send(msgBmeHum.set(Humidity, 2)); Serial.println("Pressure = " + String(pressu)); send(msgBmePress.set(Pressure, 0)); Serial.println("IAQ = " + String(iaq)); send(msgBmeIAQ.set(IAQ, 0)); Serial.println("Gas = " + String(gas)); send(msgBmeGas.set(Gas, 0)); Serial.println("IAQ_accuracy = " + String(iaqaccur)); send(msgBmeIAQA.set(IAQ_accuracy, 0)); Serial.print("BME680 - zzzzZZZZzzzzZZZZzzzz\n"); } }
but your example seems cleaner than mine, i will try
my example is working almost 100%, but this messages:
MyMessage msgBmeIAQ(CHILD_ID_BME680, V_VAR1); MyMessage msgBmeGas(CHILD_ID_BME680, V_VAR2); MyMessage msgBmeIAQA(CHILD_ID_BME680, V_VAR3);
i see that they are sending:
BME680 UART - Sending data request to sensor. Temperature = 21.33 901008 TSF:MSG:SEND,1-1-0-0,s=0,c=1,t=0,pt=7,l=5,sg=0,ft=0,st=OK:21.33 Humidity = 59.43 901019 TSF:MSG:SEND,1-1-0-0,s=0,c=1,t=1,pt=7,l=5,sg=0,ft=0,st=OK:59.43 Pressure = 98988 901027 TSF:MSG:SEND,1-1-0-0,s=0,c=1,t=4,pt=7,l=5,sg=0,ft=0,st=OK:98988 IAQ = 29 901036 TSF:MSG:SEND,1-1-0-0,s=0,c=1,t=24,pt=7,l=5,sg=0,ft=0,st=OK:29 Gas = 127960 901045 TSF:MSG:SEND,1-1-0-0,s=0,c=1,t=25,pt=7,l=5,sg=0,ft=0,st=OK:127960 IAQ_accuracy = 3 901053 TSF:MSG:SEND,1-1-0-0,s=0,c=1,t=26,pt=7,l=5,sg=0,ft=0,st=OK: 3 BME680 - zzzzZZZZzzzzZZZZzzzz
but they are not showing up on the controller, maybe because its because this type : V_VAR* ?
-
@fosi Nice work. Each message needs to have a different child id.
Do something similar to this:MyMessage msgBmeIAQ(CHILD_ID_AQ, V_VAR1); MyMessage msgBmeGas(CHILD_ID_GAS, V_VAR2); MyMessage msgBmeIAQA(CHILD_ID_AQA, V_VAR3);
and define them as different numbers.