Request: New Sensor Type ? Thermostatically controlled switch



  • Would like to suggest a new sensor type, maybe V_SWTEMP?

    It would allow the controller to set a temp as a trip point for the switch/relay that could be stored in EEPROM. This would allow the sensor node to continue to operate as a thermostat even when all comm with the gateway/controller might be lost. Under normal operation the controller could change the thermostat setting or even override the thermostat to force the sw/relay on/off. What is needed to implement this?

    Currently have testbed: Arduino clone as sensor node talking to RPi as Gateway (via the NRF24L01+'s) - The RPi communicates via TCP/IP (had to mod the mySensors/Raspberry port to build a PiGatewayNetwork module to use the Domoticz's 'MySensors to gateway with LAN interface' setting) with a virtual machine on my development pc running Domoticz.

    Have tried to use the Domoticz's dimmer (virtual) as a way to transfer values into the sensor node but it doesn't seem to be fully implemented yet (using V2.2383) - sends a non-sensical string back to gateway. Like Domoticz but still can't seem to 'get there' with it yet.

    Any help would be appreciated,
    thanks, littlejohn


  • Admin

    Yes, agree we need to have another look at the HVAC device.

    We could perhaps steal some ideas from the Vera controller
    http://wiki.micasaverde.com/index.php/Luup_UPNP_Files#HVAC_OperatingState1

    It has a HVAC_UserOperatingMode1, HVAC_OperatingState1, HVAC_FanOperatingMode1 and TemperatureSetpoint1_Heat/Cool which seems to cover most use cases when it comes to controlling HVACs.

    Verde - Dashboard.png



  • I went with your suggestion, its definitely a work in progress, but there is progress.
    I have a nano with DHT22 sensor and a relay for heating on/off.
    I played with the I_Arduino.xml and L_Arduino.lua files and added

    HVAC = {26, "urn:schemas-upnp-org:device:HVAC_ZoneThermostat:1", "D_HVAC_ZoneThermostat1.xml", "HVAC "}
    
    HVAC = {40, "urn:upnp-org:serviceId:TemperatureSetpoint1", "CurrentSetpoint", "" }
    
    function SetTheNewHvacTemp(device, NewCurrentSetpoint)
    	sendCommand(luup.devices[device].id,"HVAC",NewCurrentSetpoint)
    end
    

    to L_Arduino.lua

    and

    <action>
      <serviceId>urn:upnp-org:serviceId:TemperatureSetpoint1</serviceId>
        <name>SetCurrentSetpoint</name>
          <job>
            if (p ~= nil) then p.SetTheNewHvacTemp(lul_device, lul_settings.NewCurrentSetpoint)  end
      			return 4,0
          </job>
    </action>
    

    to I_Arduino.xml

    Also added V_HVAC and S_HVAC to MyMessage.h for Arduino.

    And I get this on Vera Edge UI7

    vera_arduino_hvac.png

    As of now I can change the setpoint, although it comes back from the node as 27.6 which throws off the vera temp display, makes it 2 line but shows it, I can also send the states "CoolOn", "HeatOn" and so on.

    I haven't worked out how to get the temp on the card instead of separate, or the battery level yet.

    Here is serial from node
    vera_arduino_hvac_serial.png

    Here is my node sketch

    #include <SPI.h>
    #include <MySensor.h>  
    #include <DHT.h>
    #include <Bounce2.h>
    
    #define NODE_ID AUTO
    #define SKETCH_NAME "MySensor_Heater"
    #define SKETCH_VERSION "1.1"
    #define NODE_REPEAT true
    
    #define CHILD_ID_HUM 0
    #define CHILD_ID_TEMP 1
    #define CHILD_ID_HVAC 2
    #define CHILD_ID_BATT 3
    #define CHILD_ID_HEATER_SW 4
    
    #define HUMIDITY_SENSOR_DIGITAL_PIN 3
    #define RELAY_PIN  4  // Arduino Digital I/O pin number for relay 
    #define BUTTON_PIN  5  // Arduino Digital I/O pin number for button 
    #define RELAY_ON 0
    #define RELAY_OFF 1
    unsigned long SLEEP_TIME = 30000; // Sleep time between reads (in milliseconds)
    
    Bounce debouncer = Bounce(); 
    int oldValue=0;
    bool state;
    MySensor gw;
    DHT dht;
    float lastTemp;
    float lastHum;
    boolean metric = true;
    unsigned long CHECK_TIME = millis();
    String heaterMode = "Off";
    int setPoint = 20;
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgHeaterSW(CHILD_ID_HEATER_SW,V_HEATER_SW);
    //MyMessage msgHeaterState(CHILD_ID_HEATER_STATE,V_HEATER);
    MyMessage msgHvac(CHILD_ID_HVAC, V_HVAC);
    MyMessage msgBattery(CHILD_ID_BATT, I_BATTERY_LEVEL);
    
    void setup()  
    { 
      gw.begin(incomingMessage,NODE_ID,NODE_REPEAT);
      dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
    
      // Send the Sketch Version Information to the Gateway
      gw.sendSketchInfo(SKETCH_NAME, SKETCH_VERSION);
      
      // Setup the button
      pinMode(BUTTON_PIN,INPUT);
      // Activate internal pull-up
      digitalWrite(BUTTON_PIN,HIGH);
      
      // After setting up the button, setup debouncer
      debouncer.attach(BUTTON_PIN);
      debouncer.interval(5);
    
      // Register all sensors to gw (they will be created as child devices)
      gw.present(CHILD_ID_HUM, S_HUM);
      gw.present(CHILD_ID_TEMP, S_TEMP);
      //gw.present(CHILD_ID_HEATER_SW, S_HEATER);
      //gw.present(CHILD_ID_HEATER_STATE, S_HEATER);
      gw.present(CHILD_ID_HVAC, S_HVAC);
      
      metric = gw.getConfig().isMetric;
      
      // Make sure relays are off when starting up
      digitalWrite(RELAY_PIN, RELAY_OFF);
      // Then set relay pins in output mode
      pinMode(RELAY_PIN, OUTPUT);   
          
      // Set relay to last known state (using eeprom storage) 
      //state = gw.loadState(CHILD_ID);
      //digitalWrite(RELAY_PIN, state?RELAY_ON:RELAY_OFF);
    }
    
    void loop()      
    {
      gw.process();
      debouncer.update();
      // Get the update value
      int value = debouncer.read();
      if (value != oldValue && value==0) {
          gw.send(msgHvac.set(state?false:true), true); // Send new state and request ack back
      }
      oldValue = value;
      
      // Check Temp and Humidity sensor every set ammount of time
      unsigned long NOW_TIME = millis();
      if(NOW_TIME - CHECK_TIME >= SLEEP_TIME) {
        getTemps();
        CHECK_TIME = NOW_TIME;
      }
      
      
    }
    
    void getTemps(){
      delay(dht.getMinimumSamplingPeriod());
    
      float temperature = dht.getTemperature();
      if (isnan(temperature)) {
          Serial.println("Failed reading temperature from DHT");
      } else if (temperature != lastTemp) {
        lastTemp = temperature;
        if (!metric) {
          temperature = dht.toFahrenheit(temperature);
        }
        gw.send(msgTemp.set(temperature, 1));
        //gw.send(msgHvac.set(temperature, 1));
        gw.send(msgBattery.set(65, 1));
        Serial.print("T: ");
        Serial.println(temperature);
      }
      
      float humidity = dht.getHumidity();
      if (isnan(humidity)) {
          Serial.println("Failed reading humidity from DHT");
      } else if (humidity != lastHum) {
          lastHum = humidity;
          gw.send(msgHum.set(humidity, 1));
          Serial.print("H: ");
          Serial.println(humidity);
      }
    
      //gw.sleep(SLEEP_TIME); //sleep a bit
      
    }
    
    void incomingMessage(const MyMessage &message) {
      Serial.println(message.type);
      //Serial.println(message.value);
      // We only expect one type of message from controller. But we better check anyway.
      if (message.isAck()) {
         Serial.println("This is an ack from gateway");
      }
    
      if (message.type == V_HVAC) {
         // Change relay state
         Serial.println("Message received");
         setPoint = String(message.data).toInt();
         Serial.println("New Set Temp is : " + String(setPoint));
         gw.send(msgHvac.set(setPoint, 1));
         // Store state in eeprom
         //gw.saveState(CHILD_ID, state);
        
         // Write some debug info
         Serial.print("Incoming change for sensor:");
         Serial.print(message.sensor);
         Serial.print(", New status: ");
         Serial.println(message.data);
       }
      if (message.type == V_HEATER_SW) {
        Serial.println("Switch Message received");
        Serial.println(String(message.data));
        if(String(message.data) == "HeatOn"){
          Serial.println("Heating ON");
          digitalWrite(RELAY_PIN, RELAY_ON);
          //gw.send(msgHeaterSW.set("HeatOn", 1));
        }
        if(String(message.data) == "CoolOn"){
          Serial.println("Heating OFF");
          digitalWrite(RELAY_PIN, RELAY_OFF);
          //gw.send(msgHeaterSW.set("CoolOn", 1));
        }
      }
    }
    

    L_Arduino.lua
    I_Arduino1.xml
    MyMessage.h

    I have a couple of StellaZ Zwave radiator thermostats that use the hvac files, and they have many variables for temps and batteries and setpoints, but it is beyond me how to enable these for the mysensors nodes.

    We also need to be able to add a scene that goes

    If currentTemp is > currentSetpoint
      Turn on heat
    

    and looking at scenes to switch on heating, it seems you have to add a temp to create a scene involving temperature. I don't know LUUA code at all at the moment so I do not know if you can create a function that ignores the temp you had to add to create it and looks at current temp and setpoint. babbling now.

    Over to you 🙂


  • Admin

    Damn! Great work!

    I'll merge this ASAP.


  • Hero Member

    Nice Indeed!, too bad I left Vera.. 😢 .. Well Not really.. 🙂



  • Nice work 👍

    http://forum.mysensors.org/topic/1471/s_setpoint-v_setpoint-for-thermostat-devices
    SetPoint is the thing I need to make the next step.
    I'll start my project soon as this is merged 🙂



  • Would this require something else but adding new message types to MyMessage.h?

    hek: Looks like in Vera it can handle many cases + many other I cant imagine yet. So it would be good idea to not invent wheel again 😄

    Just throwing some ideas(mainly naming) about this:

    (already) V_HEATER (while it supports needed modes already) == HVAC_UserOperatingMode1
    Perhaps rename to V_HVAC_MODE and V_HVAC_SW?

    With setpoints, do we really need two separate values?
    (needed) V_SETPOINT_HEAT == TemperatureSetpoint1_Heat
    (needed) V_SETPOINT_COOL == TemperatureSetpoint1_Cool
    OR:
    (needed) V_SETPOINT == TemperatureSetpoint1

    Couple ques tions to make some discussion:
    Could V_SETPOINT be enough? Just use two instances of these?
    Or should MySensors have all three options?

    Are these two mainly for controlling fans? Could general naming for fans, circulating pumps etc. be for example FLOW?
    (needed) V_FLOW_STATE(Do we need some additional states compared to Vera?) == HVAC_OperatingState1
    (needed) V_FLOW_MODE == HVAC_FanOperatingMode1 (why to use only for fans. it could be circulating pumpt etc..)

    Should there be HVAC prefix on every of these?

    And would it be good idea to rename S_HEATER to S_HVAC?


  • Hero Member

    This post is deleted!

  • Admin

    Thanks for the help to interpret the needed changes @prj. The Heater/HVAC thing is a bit messy.

    So what about this:

    Rename
    V_HEATER => V_HVAC_SETPOINT_HEAT (Used for heating devices setpoint). We must be able to handle both HEAT/COLD setpoint for this to be compatible with Vera.
    V_HEATER_SW => V_HVAC_FLOW_STATE ("Off", "HeatOn", "CoolOn", or "AutoChangeOver")

    New variables
    V_HVAC_SETPOINT_COLD (Used for setting setpoint on hvac devices)
    V_HVAC_FLOW_MODE ("Auto", "ContinuousOn", or "PeriodicOn")

    New device type
    S_HVAC (As Vera seems to distinguish between Heater and HVAC devices)

    I will also backport new device types and variables from development to master branch to keep things in sync.



  • Sorry for my answer took a while. I was having weekend trip with my family.

    IMO the FLOW -keyword is not so needed for the "main" function mode. I was thinking FLOW as container for different set of enum values additional to HVAC mode. For fans or liquid pumps the machine may contain.

    So in the end these would be the things I think:
    S_HVAC
    V_HVAC_SETPOINT_HEAT
    V_HVAC_SETPOINT_COLD
    V_HVAC_MODE ("Off", "HeatOn", "CoolOn", "AutoChangeOver" or "Dry") Some heat pumps has also "Dry/Dehumidifying" mode.
    V_HVAC_FLOW_STATE ("Auto", "ContinuousOn", or "PeriodicOn") How the fan/liquid pump behaves
    V_HVAC_FLOW_SPEED ("Auto", "Min", "Normal" or "Max") And what speed it uses.

    In documentation there is:

    V_HEATER	21	Mode of header. One of "Off", "HeatOn", "CoolOn", or "AutoChangeOver"
    V_HEATER_SW	22	Heater switch power. 1=On, 0=Off
    

    So porting to new arrangement would require sketch update like this?
    V_HEATER -> V_HVAC_MODE (has identical states)
    V_HEATER_SW -> Could the V_HEATER_SW remain or be renamed to V_HVAC_SW as we might need it to some alternative functionality? Electronic air filtering for example.

    V_HVAC_FLOW_SPEED for example in ventilation I could use Min when no one is home, Normal when my family is at home and Max when there is lot of quests and Auto it would run based on sensors.

    About V_HVAC_MODE I'm wondering could the node report the states it can use to controller? Then the controller could be able to filter its UI based on this information.

    I'm not sure about other heat pumps/ventilation systems but with these I'm able interface my two pumps + ventilation.

    @hek thank you very much in advance 🙂



  • I've been thinking of integrating my HeatpumpIR library into MySensors. The S_HVAC isn't quite 1:1 mapping to what I've been thinking of, here's a Visual Studio screenshot of my current remote control app (sorry, not a fruit company one :)):

    heatpump.png

    So, I think I'd need to pass this data for example from Domoticz to the MySensors node:

    • Heatpump model (could be an index number to the list of supported models)
    • Power mode (on/off)
    • Operating mode (auto, heat, cool, dry, fan, maintenance heating)
    • Temperature (8,10, 16-30 degrees Celcius)
    • Fan speed (auto, 1-5)

    As this is technically an infrared device, I've been also thinking of using the S_IR node type. I think I could pack the data into a 32-bit integer as an alternative. There's also no Domoticz support for this yet.

    Any ideas would be welcome.


  • Hero Member

    @stephenmhall would you mind sharing your latest version of the HVAC device arduino sketch?



  • i am also very interested in the arduino sketch and how you wired it 🙂


  • Hero Member

    I finally put together a thermostat device sketch. Unfortunately it got a bit out of hand and I implemented lots of features that most people probably not need.

    Not sure if I'm using the V_HVAC_FLOW_STATE and V_HVAC_SETPOINT_HEAT correctly but it seems to work with my Vera UI5 presented as a S_HEATER device.

    Here is the sketch in case someone needs it.

    https://codebender.cc/sketch:169733



  • @hek some new ideas for this:

    There is now new switch type(SELECTOR) presented in Domoticz. With that its now possible to handle with V_HVAC enum switches.

    I was thinking this functionality and new functionality of MySensors for presenting (enum)switch values would be more than nice. With this the controller could build the switch dynamically with values the HVAC device really has.

    For example:

    1. gw.presentcaps(childId, listOfValues) (user could give names for these in the controller)
    2. or even better: gw.presentcaps(childId, listOfKeys) (in this case values would be from 0 to count of list but names are provided automatically)
    3. or the best: gw.presentcaps(childId, listOfValues, listOfKeys). The contoller could buid up the switch from this info.

    It would be alternative for gw.present(...) or called after?

    Keys would be used in UI of contoller and values(list of 8 bit int?) are what is transferred in messages.
    For example my air source heat pump has only V_HVAC_MODE modes "Off", "HeatOn", "CoolOn". Values for these could be 0, 1 and 2.


  • Admin

    @pjr

    Interesting idea. Please add an issue on github.



  • @hek Just added: 356



  • @hek do you know anyone who would like to implement this for some "beer"?


 

461
Online

7.9k
Users

8.8k
Topics

94.3k
Posts