Domotiocz + Rain gauge
-
Domoticz just recently changed the method of rain rate calculation. It does not interpret rainrate values sent by sensors but calculates this by the total value coming in.
-
@sundberg84 Using a real pulse counter instead of a 1mm pulse counter seems to work perfectly. Luckily it makes the sketch a bunch easier to implement and read. And there will also be no loss of 0.2 or 0.5 mm rain fall whenever you reset the node while it didn't have a .0 value.
Great to see this project continuing to grow legs!
-
This is great!
1 year - times fly by, but my rainsensor is going strong!I just wanted to celebrate 1 year for my Rainsensor on batteries, reporting every hour (or less when it rains). Still going strong and 81% battery left! Except for some range issues in the beginning you can see its working as it should:
Also It will be my (almost) 1000th post so thank you all for making MySensors such a great community. I just love every minute here!

@sundberg84 said:
I just wanted to celebrate 1 year for my Rainsensor on batteries, reporting every hour (or less when it rains). Still going strong and 81% battery left! Except for some range issues in the beginning you can see its working as it should:
WOW, nice. Would it be possible to see your Battery graph, if you have one?
I am send data every 2h or often when it rains but my battery is draining much quicker than yours. Maybe I will get 1 year out of it, so I am happy anyway.
But I am interested in your graph if the voltage is going down quicker in the beginning. -
-
Maybe a stupid question, but it is possible to replace the SI7021 sensor with a DHT-22 sensor (the code has to be changed offsourse)? And get everything to work with ThresholdUtil? I have all parts, but not the SI7021 sensor to build the rain gauge.
@Hilltan That should really be easy. I've created the threshold util especially for this. You only have to replace the si7021 init part with the DHT22 init part and replace the reading part of the si7021 in the threshold util callback with reading the DHT22 part. Then you're done.
Just give it a try yourself. It's really not that hard.
There's however a reason why I use the si7021 instead of the DHT's. I've had serious troubles with the DHT sensors. Some of them wouldn't report the values to the gateway for a week. After the that the node spontaneously started reporting again. I have a sense bender running for more than a half year flawlessly. So in my opinion the si7021 is superior to the DHT.
-
Maybe a stupid question, but it is possible to replace the SI7021 sensor with a DHT-22 sensor (the code has to be changed offsourse)? And get everything to work with ThresholdUtil? I have all parts, but not the SI7021 sensor to build the rain gauge.
@Hilltan Like @TheoL mentioned, try to avoid the DHT22, especially for battery powered operation. The DHT-22 is (apart from other disadvantages) specified for a working voltage from 3.3-6V. And tend to get unstable at low voltages.
-
-
-
-
Yep, note that the BMP180/BMP085 is described in the https://www.mysensors.org/build/pressure example. BME280 might be a better choice nowadays perhaps.
-
@Hilltan That should really be easy. I've created the threshold util especially for this. You only have to replace the si7021 init part with the DHT22 init part and replace the reading part of the si7021 in the threshold util callback with reading the DHT22 part. Then you're done.
Just give it a try yourself. It's really not that hard.
There's however a reason why I use the si7021 instead of the DHT's. I've had serious troubles with the DHT sensors. Some of them wouldn't report the values to the gateway for a week. After the that the node spontaneously started reporting again. I have a sense bender running for more than a half year flawlessly. So in my opinion the si7021 is superior to the DHT.
How will the numbers affect the Thresholds reading and reporting of the sensor?
registerThresholdedSensor( CHILD_ID_TEMP, 1, TEMPERATURE_SENSOR, 0.5, 30, 20 );
0.5 //What will this do?
30 //What will this do?
20 //That one I assume is how often the value will be sent to the gateway?void updatedTHSensorValue( uint8_t child_id, uint8_t sensor_id, ThreshHoldedSensorType sensor_type, float value ) {
switch ( child_id ) {
case CHILD_ID_TEMP:
Serial.print( "Sending temp " );
Serial.println( value, 1 ); //What will this do?
send( msgTemp.set( value, 1 ) ); //What will this do?
break;I don’t have the SI7021 sensor yet so therefore my questions
And a problem with the DHT sensor is correct me if I am wrong, is that the DHT sensor does not like to be “read” to often. How will I do this? Or maybe the answer to my question is in the registerThresholdedSensor code ;).
-
How will the numbers affect the Thresholds reading and reporting of the sensor?
registerThresholdedSensor( CHILD_ID_TEMP, 1, TEMPERATURE_SENSOR, 0.5, 30, 20 );
0.5 //What will this do?
30 //What will this do?
20 //That one I assume is how often the value will be sent to the gateway?void updatedTHSensorValue( uint8_t child_id, uint8_t sensor_id, ThreshHoldedSensorType sensor_type, float value ) {
switch ( child_id ) {
case CHILD_ID_TEMP:
Serial.print( "Sending temp " );
Serial.println( value, 1 ); //What will this do?
send( msgTemp.set( value, 1 ) ); //What will this do?
break;I don’t have the SI7021 sensor yet so therefore my questions
And a problem with the DHT sensor is correct me if I am wrong, is that the DHT sensor does not like to be “read” to often. How will I do this? Or maybe the answer to my question is in the registerThresholdedSensor code ;).
@Hilltan I assume that you've downloaded my ThresholdUtil library from my github.
The three values are:
- theshHold: The value of threshold is indicates how much the new value needs to differ from the last send value before it triggers a resend.
- readingInterval: The amount of seconds the library waits before it request a new value for this sensor
- forcedTransmissionInterval: The amount of measurements without retransmissions, before a retransmission is triggered. In other words if the values of a sensor don't extend the threshold, a retransmissionis triggered of this given amount of readings.
I just checked my github and there's a none MySensors example handling a DHT22 and a Lux sensors. You can find it here
I initialize the threshold util as follows
#include "ThresholdUtil.h" #include "DHT.h" DHT dht; #define DHT 0 #define CHILD_ID_TEMP 0 #define CHILD_ID_HUMIDITY 1 #define CHILD_ID_LIGHT_SENSOR 2 #define DHT22_PIN 14 void setup() { Serial.begin( 115200 ); registerThresholdedSensor( CHILD_ID_TEMP, DHT, TEMPERATURE_SENSOR, 0.5, 30, 20 ); // every 30 seconds report at least every 10 minutes registerThresholdedSensor( CHILD_ID_HUMIDITY, DHT, HUMIDTY_SENSOR, 1.0, 60, 10 ); // every 60 seconds dht.setup( DHT22_PIN ); // data pin 2 delay( dht.getMinimumSamplingPeriod() ); checkThresholdedSensors( checkThrsedSensor, reportSensorValue ); // Necessary call for intializing ThresholdUtil }This means that I read the temp value every 30 seconds and report the temperature at least every 10 minutes or if the temperature lowers a half degree. But it would be better to change the half degree into 1 degree.
The humidity gets read every minute and will report at least every 10 minutes as well. Or when the humidity drops or raises 1 %. But I think I would use 2 percent in production.To make sure the DHT is not being read to often. I remember the humidity when I read the temperature from the DHT. So when the ThresholdUtil requests the humidity state I return the humidity we last read.
float dhtHumidity; void checkThrsedSensor( uint8_t aSensorId, ThreshHoldedSensorType aType, float *value ) { if ( aSensorId == DHT ) { if ( aType == TEMPERATURE_SENSOR ) { dhtHumidity = dht.getHumidity(); *value = dht.getTemperature(); } else { *value = dhtHumidity; } } if ( aSensorId == LUX_SENSOR && aType == LIGHTLEVEL_SENSOR ) { *value = random( 30, 40 ); // not sure why but I apparently just fake the light level sensor } }The remainder of the sketch contains a callback handler for reporting the sensor values e.g. to MySensors. But I've noticed that I need to update that example on github
void reportSensorValue( uint8_t child_id, uint8_t sensor_id, ThreshHoldedSensorType sensor_type, float value ) { Serial.print( millis() ); Serial.print( ": new sensor value " ); Serial.print( value ); Serial.print( child_id == CHILD_ID_TEMP ? " C" : " %" ); Serial.print( " for child " ); Serial.println( child_id == CHILD_ID_TEMP ? "temp" : ( child_id == CHILD_ID_HUMIDITY ? "hum" : "light" ) ); }And in the loop we continuously call the checkThresholdedSensors method, that well handle all the timing part for you. So that the check only gets called when needed and the report only when a sensor value needs to be reported.
void loop() { checkThresholdedSensors( checkThrsedSensor, reportSensorValue ); }Hope this helps you a bit. I'm currently to occupied to update the sketch for you.
-
Finally I get it to run with a light sensor (BH1750), temp/hum sensor (DHT22), and the rain tipping sensor. But there are some problems:
Domoticz seems not to want to divide the DHT sensor in to two, one humidity and one temperature. What I get in Domoticz is one WTGR800 (temp/hum) and one LaCrosse TX3 (temp). Have played around with the code a little bit, just ending up with one WTGT800 (temp/hum) and one LaCrosse TX3 (temp or humidity).
The rain sensor gets fault impulse from time to time, the sensor got trigged without that the sensor have been set off?
Overall your @TheoL Threshhold util is a very nice tool to work with, but the DHT sensor is not that easy to deal with I think…// Enable and select radio type attached #define MY_RADIO_NRF24 /* Include libraries used by the sketch */ #include "ThresholdUtil.h" #include <math.h> #include <Time.h> #include <MySensors.h> #include <BH1750.h> #include "DHT.h" #include <Wire.h> DHT dht; #define DHT 0 #define BUCKET_PIN 3 // The Arduino pin to which the bucket is attached. We need an interrupt pin (2 or 3 on the Uno and the Pro Mini) #define SKETCH_INFO "Outside weather" // The name of the sketch as presented to the gateway #define SKETCH_VERSION "1.0" // The version of the sketch as presented to the gateway #define CHILD_ID_RAIN_LOG 4 // The child id of the rain gauge #define MS_WAIT 100 // short delay used to give the NRF24L01+ antenna some time to recover from the last data sending #define bucketSize 0.3 // I've used a MI-SOL Rain Guage which has a bucket size of 0.3 mm #define LIGHTLEVEL_SENSOR_CHILD_ID 0 #define LIGHTLEVEL_SENSOR_ID 3 #define CHILD_ID_TEMP 5 #define DHT_TEMP 6 #define CHILD_ID_HUMIDITY 7 #define DHT_HUM 9 #define DHT_DATA_PIN 8 MyMessage lightLevelMsg(LIGHTLEVEL_SENSOR_CHILD_ID, V_LIGHT_LEVEL); MyMessage msgHum( CHILD_ID_HUMIDITY, V_HUM ); MyMessage msgTemp( CHILD_ID_TEMP, V_TEMP ); MyMessage msgRain( CHILD_ID_RAIN_LOG, V_RAIN ); MyMessage lastCounterMsg( CHILD_ID_RAIN_LOG, V_VAR1 ); BH1750 lightSensor; float hwRainVolume = 0; // Current rainvolume calculated in hardware. unsigned long hwPulseCounter = 0; // Pulsecount recieved from GW boolean pcReceived = false; // If we have recieved the pulscount from GW or not unsigned long lastTipTime = millis(); // TS of when the bucket tip has been detected for the last time volatile unsigned long wasTippedCounter; // Queue for storing the tipped counter as been set by the interrupt handler. byte lastHour; // Stores the hour used for checking if time needs to be synchronized void presentation() { // Send the sketch version information to the gateway sendSketchInfo( SKETCH_INFO, SKETCH_VERSION ); wait( MS_WAIT ); present(LIGHTLEVEL_SENSOR_CHILD_ID, S_LIGHT_LEVEL, "Light level" ); wait( MS_WAIT ); present( CHILD_ID_HUMIDITY, S_HUM, "Outside Humidity" ); wait( MS_WAIT ); present( CHILD_ID_TEMP, S_TEMP, "Outside Temperature" ); wait( MS_WAIT ); present( CHILD_ID_RAIN_LOG, S_RAIN, "Rain fall" ); wait( MS_WAIT ); unsigned long functionTimeout = millis(); while ( pcReceived == false && millis() - functionTimeout < 30000UL ) { request( CHILD_ID_RAIN_LOG, V_VAR1); Serial.println(F("Getting pulse count")); Serial.println(F(".")); wait( 1000 ); } attachInterrupt( digitalPinToInterrupt( BUCKET_PIN ), sensorTipped, LOW ); //FALLING ); // depending on location of the hall effect sensor may need CHANGE } void setup() { Serial.begin( 115200 ); pinMode( BUCKET_PIN, INPUT_PULLUP ); lightSensor.begin(); registerThresholdedSensor( LIGHTLEVEL_SENSOR_CHILD_ID, LIGHTLEVEL_SENSOR_ID, LIGHTLEVEL_SENSOR, 20, 30, 20 ); // read every 5 sec and report at least every 5 minute ändrat 300 till 20 registerThresholdedSensor( CHILD_ID_TEMP, DHT_TEMP, TEMPERATURE_SENSOR, 0.5, 30, 20 ); // every 30 seconds report at least every 10 minutes registerThresholdedSensor( CHILD_ID_HUMIDITY, DHT_HUM, HUMIDTY_SENSOR, 1.0, 60, 10 ); // every 60 seconds dht.setup( DHT_DATA_PIN ); // data pin 8 delay( dht.getMinimumSamplingPeriod() ); unsigned long functionTimeout = millis(); while ( timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL ) { requestTime(); Serial.println(F("Getting Time")); Serial.println(F(".")); wait( 1000 ); } lastHour = hour(); } /** Sends the value of the rain gauge to the Gateway. */ void sendRainVolumeData() { float hwRainVolume = hwPulseCounter * bucketSize; Serial.print( "Tipped " ); Serial.print( hwPulseCounter ); Serial.println( " times." ); Serial.print( "Rain fall is " ); Serial.print( hwRainVolume, 1 ); Serial.println( " mm." ); send( msgRain.set( (float)hwRainVolume, 1 ) ); wait( MS_WAIT ); send( lastCounterMsg.set( hwPulseCounter ) ); wait( MS_WAIT ); } void loop() { if ( wasTippedCounter != hwPulseCounter ) { hwPulseCounter = wasTippedCounter; sendRainVolumeData(); } byte currentHour = hour(); if (currentHour != lastHour) { Serial.println( "Resyncing hour" ); requestTime(); // sync the time every hour wait( MS_WAIT ); lastHour = currentHour; sendRainVolumeData(); // Send heart beat } checkThresholdedSensors( readSensorValue, updatedSensorValue ); } void sensorTipped() { unsigned long thisTipTime = millis(); if (thisTipTime - lastTipTime > 100UL) { wasTippedCounter++; } lastTipTime = thisTipTime; } float dhtHumidity; void readSensorValue( uint8_t aSensorId, ThreshHoldedSensorType aType, float *value ) { switch ( aSensorId ) { case LIGHTLEVEL_SENSOR_ID: if ( aType == LIGHTLEVEL_SENSOR ) { *value = lightSensor.readLightLevel(); } break; case DHT_TEMP: if ( aType == TEMPERATURE_SENSOR ) { *value = dht.getTemperature(); } break; case DHT_HUM: if ( aType == HUMIDTY_SENSOR ) { *value = dht.getHumidity(); } break; } } void updatedSensorValue( uint8_t child_id, uint8_t sensor_id, ThreshHoldedSensorType sensor_type, float value ) { switch ( child_id ) { case LIGHTLEVEL_SENSOR_CHILD_ID: Serial.print( "Light level " ); Serial.print( value, 0 ); Serial.println( "%" ); send( lightLevelMsg.set( value, 5 ) ); wait( MS_WAIT ); break; case CHILD_ID_TEMP: Serial.print( "Temperatur " ); Serial.print( value, 0 ); Serial.print( "C" ); send( msgTemp.set( value, 1 ) ); wait( MS_WAIT ); break; case CHILD_ID_HUMIDITY: Serial.print( "HUMIDITY " ); Serial.print( value, 0 ); Serial.print( "%" ); send( msgHum.set( value, 1 ) ); wait( MS_WAIT ); break; } } void receiveTime(unsigned long time) { Serial.println( F("Time received...")); setTime(time); char theTime[6]; sprintf(theTime, "%d:%2d", hour(), minute()); Serial.println(theTime); } void receive(const MyMessage &message) { if ( message.sensor == CHILD_ID_RAIN_LOG && message.type == V_VAR1) { // We only expect pulse count values from the gateway hwPulseCounter = message.getULong(); wasTippedCounter = hwPulseCounter; pcReceived = true; Serial.print("Received last pulse count from gw: "); Serial.println(hwPulseCounter); } }There are probably strange things in the sketch, I am new to this ;)
-
Finally I get it to run with a light sensor (BH1750), temp/hum sensor (DHT22), and the rain tipping sensor. But there are some problems:
Domoticz seems not to want to divide the DHT sensor in to two, one humidity and one temperature. What I get in Domoticz is one WTGR800 (temp/hum) and one LaCrosse TX3 (temp). Have played around with the code a little bit, just ending up with one WTGT800 (temp/hum) and one LaCrosse TX3 (temp or humidity).
The rain sensor gets fault impulse from time to time, the sensor got trigged without that the sensor have been set off?
Overall your @TheoL Threshhold util is a very nice tool to work with, but the DHT sensor is not that easy to deal with I think…// Enable and select radio type attached #define MY_RADIO_NRF24 /* Include libraries used by the sketch */ #include "ThresholdUtil.h" #include <math.h> #include <Time.h> #include <MySensors.h> #include <BH1750.h> #include "DHT.h" #include <Wire.h> DHT dht; #define DHT 0 #define BUCKET_PIN 3 // The Arduino pin to which the bucket is attached. We need an interrupt pin (2 or 3 on the Uno and the Pro Mini) #define SKETCH_INFO "Outside weather" // The name of the sketch as presented to the gateway #define SKETCH_VERSION "1.0" // The version of the sketch as presented to the gateway #define CHILD_ID_RAIN_LOG 4 // The child id of the rain gauge #define MS_WAIT 100 // short delay used to give the NRF24L01+ antenna some time to recover from the last data sending #define bucketSize 0.3 // I've used a MI-SOL Rain Guage which has a bucket size of 0.3 mm #define LIGHTLEVEL_SENSOR_CHILD_ID 0 #define LIGHTLEVEL_SENSOR_ID 3 #define CHILD_ID_TEMP 5 #define DHT_TEMP 6 #define CHILD_ID_HUMIDITY 7 #define DHT_HUM 9 #define DHT_DATA_PIN 8 MyMessage lightLevelMsg(LIGHTLEVEL_SENSOR_CHILD_ID, V_LIGHT_LEVEL); MyMessage msgHum( CHILD_ID_HUMIDITY, V_HUM ); MyMessage msgTemp( CHILD_ID_TEMP, V_TEMP ); MyMessage msgRain( CHILD_ID_RAIN_LOG, V_RAIN ); MyMessage lastCounterMsg( CHILD_ID_RAIN_LOG, V_VAR1 ); BH1750 lightSensor; float hwRainVolume = 0; // Current rainvolume calculated in hardware. unsigned long hwPulseCounter = 0; // Pulsecount recieved from GW boolean pcReceived = false; // If we have recieved the pulscount from GW or not unsigned long lastTipTime = millis(); // TS of when the bucket tip has been detected for the last time volatile unsigned long wasTippedCounter; // Queue for storing the tipped counter as been set by the interrupt handler. byte lastHour; // Stores the hour used for checking if time needs to be synchronized void presentation() { // Send the sketch version information to the gateway sendSketchInfo( SKETCH_INFO, SKETCH_VERSION ); wait( MS_WAIT ); present(LIGHTLEVEL_SENSOR_CHILD_ID, S_LIGHT_LEVEL, "Light level" ); wait( MS_WAIT ); present( CHILD_ID_HUMIDITY, S_HUM, "Outside Humidity" ); wait( MS_WAIT ); present( CHILD_ID_TEMP, S_TEMP, "Outside Temperature" ); wait( MS_WAIT ); present( CHILD_ID_RAIN_LOG, S_RAIN, "Rain fall" ); wait( MS_WAIT ); unsigned long functionTimeout = millis(); while ( pcReceived == false && millis() - functionTimeout < 30000UL ) { request( CHILD_ID_RAIN_LOG, V_VAR1); Serial.println(F("Getting pulse count")); Serial.println(F(".")); wait( 1000 ); } attachInterrupt( digitalPinToInterrupt( BUCKET_PIN ), sensorTipped, LOW ); //FALLING ); // depending on location of the hall effect sensor may need CHANGE } void setup() { Serial.begin( 115200 ); pinMode( BUCKET_PIN, INPUT_PULLUP ); lightSensor.begin(); registerThresholdedSensor( LIGHTLEVEL_SENSOR_CHILD_ID, LIGHTLEVEL_SENSOR_ID, LIGHTLEVEL_SENSOR, 20, 30, 20 ); // read every 5 sec and report at least every 5 minute ändrat 300 till 20 registerThresholdedSensor( CHILD_ID_TEMP, DHT_TEMP, TEMPERATURE_SENSOR, 0.5, 30, 20 ); // every 30 seconds report at least every 10 minutes registerThresholdedSensor( CHILD_ID_HUMIDITY, DHT_HUM, HUMIDTY_SENSOR, 1.0, 60, 10 ); // every 60 seconds dht.setup( DHT_DATA_PIN ); // data pin 8 delay( dht.getMinimumSamplingPeriod() ); unsigned long functionTimeout = millis(); while ( timeStatus() == timeNotSet && millis() - functionTimeout < 30000UL ) { requestTime(); Serial.println(F("Getting Time")); Serial.println(F(".")); wait( 1000 ); } lastHour = hour(); } /** Sends the value of the rain gauge to the Gateway. */ void sendRainVolumeData() { float hwRainVolume = hwPulseCounter * bucketSize; Serial.print( "Tipped " ); Serial.print( hwPulseCounter ); Serial.println( " times." ); Serial.print( "Rain fall is " ); Serial.print( hwRainVolume, 1 ); Serial.println( " mm." ); send( msgRain.set( (float)hwRainVolume, 1 ) ); wait( MS_WAIT ); send( lastCounterMsg.set( hwPulseCounter ) ); wait( MS_WAIT ); } void loop() { if ( wasTippedCounter != hwPulseCounter ) { hwPulseCounter = wasTippedCounter; sendRainVolumeData(); } byte currentHour = hour(); if (currentHour != lastHour) { Serial.println( "Resyncing hour" ); requestTime(); // sync the time every hour wait( MS_WAIT ); lastHour = currentHour; sendRainVolumeData(); // Send heart beat } checkThresholdedSensors( readSensorValue, updatedSensorValue ); } void sensorTipped() { unsigned long thisTipTime = millis(); if (thisTipTime - lastTipTime > 100UL) { wasTippedCounter++; } lastTipTime = thisTipTime; } float dhtHumidity; void readSensorValue( uint8_t aSensorId, ThreshHoldedSensorType aType, float *value ) { switch ( aSensorId ) { case LIGHTLEVEL_SENSOR_ID: if ( aType == LIGHTLEVEL_SENSOR ) { *value = lightSensor.readLightLevel(); } break; case DHT_TEMP: if ( aType == TEMPERATURE_SENSOR ) { *value = dht.getTemperature(); } break; case DHT_HUM: if ( aType == HUMIDTY_SENSOR ) { *value = dht.getHumidity(); } break; } } void updatedSensorValue( uint8_t child_id, uint8_t sensor_id, ThreshHoldedSensorType sensor_type, float value ) { switch ( child_id ) { case LIGHTLEVEL_SENSOR_CHILD_ID: Serial.print( "Light level " ); Serial.print( value, 0 ); Serial.println( "%" ); send( lightLevelMsg.set( value, 5 ) ); wait( MS_WAIT ); break; case CHILD_ID_TEMP: Serial.print( "Temperatur " ); Serial.print( value, 0 ); Serial.print( "C" ); send( msgTemp.set( value, 1 ) ); wait( MS_WAIT ); break; case CHILD_ID_HUMIDITY: Serial.print( "HUMIDITY " ); Serial.print( value, 0 ); Serial.print( "%" ); send( msgHum.set( value, 1 ) ); wait( MS_WAIT ); break; } } void receiveTime(unsigned long time) { Serial.println( F("Time received...")); setTime(time); char theTime[6]; sprintf(theTime, "%d:%2d", hour(), minute()); Serial.println(theTime); } void receive(const MyMessage &message) { if ( message.sensor == CHILD_ID_RAIN_LOG && message.type == V_VAR1) { // We only expect pulse count values from the gateway hwPulseCounter = message.getULong(); wasTippedCounter = hwPulseCounter; pcReceived = true; Serial.print("Received last pulse count from gw: "); Serial.println(hwPulseCounter); } }There are probably strange things in the sketch, I am new to this ;)
@Hilltan it is a Domoticz 'feature' to combine temperature, humidity and barometric sensors. There is a method to separate them if you have (or pretend to have) multiple sensors of the same type. This is done by presenting the one you want to combine right after each other.
In your case I would just keep it...