How to manage dynamic number of sensors?



  • Hello

    I build mqtt mysensors gateway with DS2482-100 to handle many (currently 15 DS18B20) 1wire sensors.

    My idea was that the gateway will dynamically start to report each attached 1wire sensors 1wire address and value automatically without necessity to change the sketch before attaching new sensor. But from what I see I need to set MyMessage(uint8_t childSensorId, uint8_t variableType); first.

    Is there some best practice pattern how to do it?

    Thanks

    Tomas


  • Mod

    @tssk have you tried the temperature example sketch? It supports a dynamic number of sensors.



  • @mfalkvidd I did not see it - thanks for mentioning it.

    I think this is what I was looking for - the sketch uses one MyMessage msg(0,V_TEMP); for values from all DS18B20 with such code construction

      // Read temperatures and send them to controller 
      for (int i=0; i<numSensors && i<MAX_ATTACHED_DS18B20; i++) {
          ...
          // Send in the new temperature
          send(msg.setSensor(i).set(temperature,1));
          ...
      }
    

    I thought I will need to set up MyMessage msg(0,V_TEMP) x number_of_sensors which would be terrible.

    I guess if I extend the code with MyMessage msg(0,V_ID) to send also the 1wire address it will be what I am looking for.

    Thanks!



  • @tssk I hope I've not misunderstood what you intend, but possibly a further consideration ?
    I have 14 sensors defined in an array with their digital addresses.

    During presentation a similar "for" loop to the above ties each sensor digital address with a dedicated "i" to the Controller as in your sketch. That way the sensor location is fixed - if one goes faulty it only requires that specific address edited in the array for the replacement device and reprogram the Node.

    In reality the last 2 devices in the array (Boiler) are on a separate data line to the first 12 (Spaces), but it is relatively simple to call each defined data line and address them by altering the "i" and "MAX_ATTACHED..." for each instance.



  • @zboblamont Thanks for the tip. I am trying to avoid hardcoding any addresses - maybe I find out that it will be necessary at some point. But so far it looks fine:

    23:08:43.873 -> 0 MCO:BGN:INIT GW,CP=R-NGA---,FQ=8,REL=255,VER=2.3.2
    23:08:44.438 -> 585 GWT:TPC:IP=192.168.1.113
    23:08:45.468 -> 1589 MCO:BGN:STP
    23:08:45.468 -> 1591 MCO:REG:NOT NEEDED
    23:08:45.468 -> 1595 MCO:BGN:INIT OK,TSP=NA
    23:08:45.468 -> 1597 GWT:TPC:IP=192.168.1.113
    23:08:46.464 -> 2600 GWT:RMQ:CONNECTING...
    23:08:46.464 -> 2611 GWT:RMQ:OK
    23:08:46.464 -> 2613 GWT:TPS:TOPIC=1wire-out/0/255/0/0/17,MSG SENT
    23:08:46.497 -> 2619 GWT:TPS:TOPIC=1wire-out/0/255/3/0/11,MSG SENT
    23:08:46.497 -> 2625 GWT:TPS:TOPIC=1wire-out/0/255/3/0/12,MSG SENT
    23:08:46.497 -> DBG: loop start
    23:08:47.559 -> 0 : 280838211713012D
    23:08:47.559 -> 3704 GWT:TPS:TOPIC=1wire-out/0/0/1/0/42,MSG SENT
    23:08:47.592 -> 0 : 5A014B467FFF0C1044 : 21.62
    23:08:47.626 -> 3753 GWT:TPS:TOPIC=1wire-out/0/0/1/0/0,MSG SENT
    23:08:47.692 -> 1 : 28A82B7D17130189
    23:08:47.692 -> 3825 GWT:TPS:TOPIC=1wire-out/0/1/1/0/42,MSG SENT
    23:08:47.692 -> 1 : 53014B467FFF0C102D : 21.19
    23:08:47.758 -> 3876 GWT:TPS:TOPIC=1wire-out/0/1/1/0/0,MSG SENT
    23:08:47.824 -> 2 : 28949D2816130138
    23:08:47.824 -> 3948 GWT:TPS:TOPIC=1wire-out/0/2/1/0/42,MSG SENT
    23:08:47.824 -> 2 : 5F014B467FFF0C1012 : 21.94
    23:08:47.858 -> 3999 GWT:TPS:TOPIC=1wire-out/0/2/1/0/0,MSG SENT
    23:08:47.924 -> 3 : 282C3C2A16130167
    23:08:47.924 -> 4071 GWT:TPS:TOPIC=1wire-out/0/3/1/0/42,MSG SENT
    23:08:47.957 -> 3 : 56014B467FFF0C107B : 21.37
    23:08:47.990 -> 4122 GWT:TPS:TOPIC=1wire-out/0/3/1/0/0,MSG SENT
    23:08:48.057 -> 4 : 28FC801F16130104
    23:08:48.057 -> 4194 GWT:TPS:TOPIC=1wire-out/0/4/1/0/42,MSG SENT
    23:08:48.057 -> 4 : 5C014B467FFF0C10D7 : 21.75
    23:08:48.123 -> 4245 GWT:TPS:TOPIC=1wire-out/0/4/1/0/0,MSG SENT
    23:08:48.190 -> 5 : 2832312A161301C3
    23:08:48.190 -> 4317 GWT:TPS:TOPIC=1wire-out/0/5/1/0/42,MSG SENT
    23:08:48.190 -> 5 : 58014B467FFF0C10C2 : 21.50
    23:08:48.223 -> 4368 GWT:TPS:TOPIC=1wire-out/0/5/1/0/0,MSG SENT
    23:08:48.322 -> 6 : 28CAD31F16130180
    23:08:48.322 -> 4440 GWT:TPS:TOPIC=1wire-out/0/6/1/0/42,MSG SENT
    23:08:48.322 -> 6 : 57014B467FFF0C1038 : 21.44
    23:08:48.356 -> 4489 GWT:TPS:TOPIC=1wire-out/0/6/1/0/0,MSG SENT
    23:08:48.422 -> 7 : 28FFE4493118014F
    23:08:48.422 -> 4560 GWT:TPS:TOPIC=1wire-out/0/7/1/0/42,MSG SENT
    23:08:48.422 -> 7 : 58014B467FFF0C10C2 : 21.50
    23:08:48.488 -> 4612 GWT:TPS:TOPIC=1wire-out/0/7/1/0/0,MSG SENT
    23:08:48.555 -> 8 : 28FF345E311801AF
    23:08:48.555 -> 4683 GWT:TPS:TOPIC=1wire-out/0/8/1/0/42,MSG SENT
    23:08:48.555 -> 8 : 5B014B467FFF0C1007 : 21.69
    23:08:48.621 -> 4734 GWT:TPS:TOPIC=1wire-out/0/8/1/0/0,MSG SENT
    23:08:48.687 -> 9 : 28FF094131180165
    23:08:48.687 -> 4806 GWT:TPS:TOPIC=1wire-out/0/9/1/0/42,MSG SENT
    23:08:48.687 -> 9 : 55014B467FFF0C10BE : 21.31
    23:08:48.721 -> 4855 GWT:TPS:TOPIC=1wire-out/0/9/1/0/0,MSG SENT
    23:08:48.787 -> 10 : 28FFE513311802A3
    23:08:48.787 -> 4927 GWT:TPS:TOPIC=1wire-out/0/10/1/0/42,MSG SENT
    23:08:48.820 -> 10 : 51014B467FFF0C10AB : 21.06
    23:08:48.853 -> 4980 GWT:TPS:TOPIC=1wire-out/0/10/1/0/0,MSG SENT
    23:08:48.920 -> 11 : 28FF2B1F31180231
    23:08:48.920 -> 5052 GWT:TPS:TOPIC=1wire-out/0/11/1/0/42,MSG SENT
    23:08:48.920 -> 11 : 56014B467FFF0C107B : 21.37
    23:08:48.986 -> 5103 GWT:TPS:TOPIC=1wire-out/0/11/1/0/0,MSG SENT
    23:08:48.986 -> DBG: loop end
    


  • In case someone is interested in the code for mysensors mqtt gateway using the DS2482.h library from https://github.com/paeaetech/paeae. The temperature conversion code is from example. I am omitting the mysensors setup.

    ...
    
    #include <DS2482.h>
    #include <Ethernet.h>
    #include <MySensors.h>
    #include <Wire.h>
    
    
    DS2482 ds( 0 );  //channels ds2482-800 is 0 to 7, DS2482-100 is just set 0
    byte dsData[8]; //holding for onewire capture
    byte dsAddr[8]; //1wire wire address and CRC
    
    MyMessage msgAddr( 0, V_ID );
    MyMessage msgTemp( 0, V_TEMP );
    
    
    void setup() {
    
      //Uses Wire library to communicate with DS2482 so be sure to call Wire.begin() before using the library.
      Wire.begin();
      ds.reset();
    
    }
    
    void presentation() {
    
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo( SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER );
    
    }
    
    void loop() {
    
      #ifdef MY_DEBUG
        Serial.println( "DBG: loop start" );
      #endif
    
      ds.wireResetSearch();
      ds.wireReset();
      ds.wireSkip();
      //need to send high power to bus??  Adding 5 volts to devices makes it work.
      ds.wireWriteByte( 0x44 ); //convert temperature on all devices
      delay( 1000 );
    
      byte sensorId = 0;
      while( ds.wireSearch( dsAddr ) ) {
    
        #ifdef MY_DEBUG
          Serial.print( sensorId );
          Serial.print( " : " );
        #endif
    
        char sensorAddr[17]; //eg. 280838211713012D
    
        for( int i = 0; i < 8; i++ ) {
          
          sensorAddr[i*2] = ( dsAddr[i] >> 4 ) + 0x30;
          if ( sensorAddr[i*2] > 0x39 ) {
            sensorAddr[i*2] += 7;
          }
          
          sensorAddr[i*2+1] = ( dsAddr[i] & 0x0f ) + 0x30;
          if ( sensorAddr[i*2+1] > 0x39 ) {
            sensorAddr[i*2+1] += 7;
          }
    
        }
    
        sensorAddr[16]  = '\0'; //always zero terminate string
        
        #ifdef MY_DEBUG
          Serial.print( sensorAddr );
          Serial.print( "\n" );
        #endif
    
        send( msgAddr.setSensor( sensorId ).set( sensorAddr ) );
    
        #ifdef MY_DEBUG
          Serial.print( sensorId );
          Serial.print( " : " );
        #endif
    
        if ( ds.crc8( dsAddr, 7 ) != dsAddr[7] ) {
          Serial.print( "CRC is not valid!" );
          return;
        }
    
        /*
        //test if device code DS18B20
        if ( dsAddr[0]==0x28 ) {
    
        //test if device code MAX31850
        if ( dsAddr[0]==0x3B ) {
        */
    
        //read temperature data.
        ds.wireReset(); //ds.reset();
        ds.selectChannel( 0 ); //necessary on -800
        ds.wireSelect( dsAddr );
        ds.wireWriteByte( 0xbe ); // Read Scratchpad command
    
        //display hex values of scratchpad
        for ( int i = 0; i < 9; i++ ) { // we need 9 bytes
          dsData[i] = ds.wireReadByte();
    
          #ifdef MY_DEBUG
            if ( dsData[i] < 16 ) {
              Serial.print( "0" );
            }
            Serial.print( dsData[i], HEX );
          #endif
        }
        
        //convert to decimal temperature
        int LowByte = dsData[0];
        int HighByte = dsData[1];
        int TReading = ( HighByte << 8 ) + LowByte;
        int SignBit = TReading & 0x8000; // test most sig bit
        if ( SignBit ) // negative
        {
                TReading = ( TReading ^ 0xffff ) + 1; // 2's comp
        }
    
        float Tc_100 = (double) TReading * 0.0625;
    
        if ( SignBit ) { // If its negative
                Tc_100 = 0 - Tc_100;
        }
    
        //print temp for each device
        #ifdef MY_DEBUG
          Serial.print( " : " );
          Serial.println( Tc_100 );
        #endif
    
        send ( msgTemp.setSensor( sensorId ).set( Tc_100, 2 ) );
    
        sensorId++;
      }
    
      #ifdef MY_DEBUG
        Serial.println( "DBG: loop end" );
      #endif
    
      delay( 60000 );
    }
    

    I am of course happy for any feedback. Especially if I am doing anything stupid as I am no programmer 🙂


Log in to reply
 

Suggested Topics

14
Online

11.4k
Users

11.1k
Topics

112.7k
Posts