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?


  • Mod

    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/gps

    I 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* ?


  • Mod

    @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.


 

446
Online

7.9k
Users

8.8k
Topics

93.8k
Posts