User Tools

Site Tools


add_temperature_sensor_in_domoticz

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
add_temperature_sensor_in_domoticz [2016/04/03 21:26]
sgripon created
add_temperature_sensor_in_domoticz [2016/11/11 20:01] (current)
sgripon [Reference]
Line 6: Line 6:
  
 In a previous post, I have shown how to [[record_temperature_from_lexibook_asm30_sensor|record temperature from Lexibook ASM30 sensor with Arduino]]. Now, we will import the temperature in Domoticz. In a previous post, I have shown how to [[record_temperature_from_lexibook_asm30_sensor|record temperature from Lexibook ASM30 sensor with Arduino]]. Now, we will import the temperature in Domoticz.
 +
 +===== Assembly =====
 +
 +First, prepare the assembly from page [[record_temperature_from_lexibook_asm30_sensor|Record temperature from Lexibook ASM30 sensor with Arduino]]. Then, just plug the arduino to the raspberry pi USB.
 +
 +===== Arduino =====
 +
 +==== The Arduino sketch ====
 +
 +I modified a little bit the previous sketch in order to read from the serial line and send the temperature only when it is requested by client.
 +
 +<file C++ SmartHomeBox_sgripon.ino>​
 +#include <​RFControl.h>​
 +
 +// Save current temperature and channel
 +int temperature = 0;
 +int channel = 0;
 +
 +void setup() {
 +  ​
 +  // Initialize serial line
 +  Serial.begin(9600);​
 +
 +  // Start receiving RF signals
 +  RFControl::​startReceiving(0);​
 +}
 +
 +// The function prints current data to the serial line
 +void printData() {
 +    Serial.print("​{ ");
 +    Serial.print("​\"​temp\":​ ");
 +    Serial.print(temperature);​
 +    Serial.print(",​ \"​channel\":​ ");
 +    Serial.print(channel);​
 +    Serial.print("​ }\n");
 +}
 +
 +void loop() {
 +  ​
 +  // Decode data when received
 +  if(RFControl::​hasData()) {
 +    unsigned int *timings;
 +    unsigned int timings_size;​
 +    unsigned int pulse_length_divider = RFControl::​getPulseLengthDivider();​
 +    RFControl::​getRaw(&​timings,​ &​timings_size);​
 +
 +    int iTemperatureTmp = 0;
 +    int iChannelTmp = 0;
 +    ​
 +    for(int i=0; i < timings_size;​ i++) {
 +      unsigned long timing = timings[i] * pulse_length_divider;​
 +
 +      // Temperature is at bit 16*2 coded in decimal x 10 on 8 bits
 +      if( (i >= 16*2) && (i < (16*2 + 8*2)) ) {
 +        if(i == 16*2) iTemperatureTmp = 0;
 +
 +        if(timing < 1000) {
 +          // bit separator, do nothing
 +        }
 +        else if(timing < 2000) {
 +          iTemperatureTmp = iTemperatureTmp<<​1;​
 +        }
 +        else if(timing < 5000) {
 +          iTemperatureTmp = iTemperatureTmp<<​1;​
 +          iTemperatureTmp++;​
 +        }
 +      }
 +      // Sensor Channel is after byte 3, on 2 bits, decimal encoded
 +      else if((i >= 24*2) && i <= 26*2) {
 +        if(i == 24*2) channel = 0;
 +        if(timing < 1000) {
 +          // bit separator, do nothing
 +        }
 +        else if(timing < 2000) {
 +          iChannelTmp = iChannelTmp<<​1;​
 +        }
 +        else if(timing < 5000) {
 +          iChannelTmp = iChannelTmp<<​1;​
 +          iChannelTmp++;​
 +        }
 +      }
 +      // Other data
 +      else {
 +        // Do nothing for now
 +      }
 +    }
 +
 +    temperature = iTemperatureTmp;​
 +    channel = iChannelTmp;​
 +        ​
 +    RFControl::​continueReceiving();​
 +  }
 +
 +  if(Serial.available() > 0) {
 +    // For now, send data whatever the received command is
 +    Serial.read();​
 +
 +    // Wait a little
 +    delay(500);
 +    ​
 +    printData();  ​
 +  }
 +  ​
 +}
 +</​file>​
 +
 +==== The Auto-reset issue ====
 +
 +The Arduino Uno automatically reset when the serial line is open by a client. This is due to the DTR signal used by the Arduino to reset. This signal cannot be disabled on the raspberry pi. The official Arduino website gives some hardware tricks to [[http://​playground.arduino.cc/​Main/​DisablingAutoResetOnSerialConnection|disable the auto-reset]]. However, I choose here a pure software method as a workaround: the reset is not disabled, but this method allows the serial communication:​
 +  - Open a serial connection on the client
 +  - Wait 2 seconds that the Arduino Uno reset
 +  - The serial connection must remain open
 +  - Communicate
 +
 +This workaround is used in the Domoticz LUA script after.
 +===== Domoticz =====
 +
 +==== Create virtual sensor ====
 +
 +The first thing to do is to add a dummy device with virtual sensor in Domoticz:
 +  * In Setup/​Hardware,​ add "​Dummy"​ type hardware
 +  * In hardware list, click "​Create virtual sensor"​ next to your dummy hardware.
 +  * Choose "​Temperature"​ for the sensor type
 +
 +{{ ::​domoticz-hardware_list.png |}}
 +
 +Then, in Setup/​Device list, note the ID of your virtual sensor: it must be reused in the LUA script.
 +
 +==== Update temperature with a script ====
 +
 +Domoticz provides a way to update its data through custom scripts written in LUA language. To use scripts, just create a file called //​script_time_HardwareName.lua//​ in domoticz installation path //​domoticz/​scripts/​lua//​. The script will be automatically called every minute by Domoticz.
 +
 +This is the source code of my own script. The script reads the temperature value by asking the arduino to write the value to the serial line. The script use an external library to decode JSON data (see http://​regex.info/​blog/​lua/​json).
 +
 +<file lua script_time_HardwareName.lua>​
 +-- Serial port must be configured before opening the file
 +-- stty -F /​dev/​ttyACM0 9600
 +
 +local deviceNum = 1
 +local serialPort = "/​dev/​ttyACM0"​
 +
 +JSON = (loadfile "/​home/​pi/​bin/​domoticz/​scripts/​lua/​JSON.lua"​)() -- one-time load of the routines
 +
 +commandArray = {}
 +
 +-- Open seria port in read and write
 +wserial=io.open(serialPort,​ "​w"​)
 +rserial=io.open(serialPort,​ "​r"​)
 +
 +-- Because Arduino auto-reset when a serial line is open, wait the end of reset before doing anything
 +os.execute("​sleep 2")
 +
 +-- First send a command to read the temperature.
 +rserial:​flush()
 +wserial:​write("​r"​)
 +wserial:​flush()
 +rserial:​read()
 +rserial:​flush()
 +
 +-- Do it another time in order to ensure we have a full frame
 +wserial:​write("​r"​)
 +wserial:​flush()
 +read_value = rserial:​read()
 +
 +-- Ask a new read until a signal has been received from the sensor. It should be available within next 30 seconds with this sensor.
 +local nbTries = 0;
 +local json_value = JSON:​decode(read_value)
 +while json_value.channel==0 and nbTries < 16 do
 + nbTries = nbTries + 1
 + os.execute("​sleep 2")
 + wserial:​write("​r"​)
 + wserial:​flush()
 + read_value = rserial:​read()
 + json_value = JSON:​decode(read_value)
 +end
 +
 +-- Update the sensor value with the new temperature if a temperature has been read
 +if json_value.channel==1 then
 + commandArray['​UpdateDevice'​]=deviceNum..'​|0|'​..json_value.temp/​10
 + -- print("​[DEBUG] Temperature:​ "​..json_value.temp)
 +end
 +
 +return commandArray
 +</​file>​
 +===== The Temperature dashboard =====
 +
 +{{ ::​domoticz-temperature.png |}}
 +
 +===== See also =====
 +  * [[add_temperature_and_humidity_sensor_dht11_in_domoticz|Add temperature and humidity sensor DHT11 in Domoticz]]
 +  * [[record_temperature_from_lexibook_asm30_sensor|Record temperature from Lexibook ASM30 sensor with Arduino]]
  
 ===== Reference ===== ===== Reference =====
  
   * Domoticz: https://​www.domoticz.com/​   * Domoticz: https://​www.domoticz.com/​
 +  * Arduino: Disabling Auto Reset On Serial Connection : http://​playground.arduino.cc/​Main/​DisablingAutoResetOnSerialConnection
 +  * JSON encoding/​decoding in LUA by Jeffrey Friedl: http://​regex.info/​blog/​lua/​json
 +
 +**Share this page:**
 +
 +~~socialite~~
add_temperature_sensor_in_domoticz.1459711599.txt.gz ยท Last modified: 2016/04/03 21:26 by sgripon