Very close I think...

  • Hi folks! I'm glad to be in this community. I've done quite a bit of dabbling and have the network up and running and integrated well with HA. I'm now on to my first project of some complexity. I decided to tackle this since it involved many different things.

    The project is a controller for a low-voltage gas fireplace. It allows HA to control ON/OFF, and also retains the ability to turn it ON/OFF with a wall switch (via a digital pin). It also integrates a gas leak sensor, and sensing of the thermopile voltage. and before it goes live it will have a couple more safety features incorporated. Attributions and stuff will come when I publish.

    As background, I'm new to Arduino, MySensors, and C++ so I have bitten off a bit more than I can chew. But, that's how I learn... Anyway, I've gotten stuck and have been noodling and cursing for a few hours over a problem. When I use the wall switch to turn ON or OFF the fireplace, I want to have HA updated with the new status of the switch. I've gotten closer than the sketch below, but I thought I'd ask if any of you can offer any suggestions or nudges in the right direction.

    Also, since I am a totally new programmer (I did some Cobol back in the day), I welcome any code review if I'm doing anything in a very crappy way.

    // Override Setting for Manual Node ID
    #define MY_NODE_ID 6
    // Enable debug prints to serial monitor
    #define MY_DEBUG 
    // Enable radio type attached
    #define MY_RADIO_NRF24
    // Libraries
    #include <MySensors.h>
    // Child IDs
    #define CHILD_ID_GAS_VOLTS 1
    #define CHILD_ID_GAS_ALARM 2
    #define CHILD_ID_RELAY 3
    // Relay Module GPIO States.
    #define RELAY_ON 0    // Low (0):ON
    #define RELAY_OFF 1   // High (1):OFF
    // Pin Assignments
    #define RELAY_PIN 3
    #define GAS_ALARM_PIN A4
    #define WALL_SWITCH_PIN 5
    // Variables
    bool initialValueSent = false;     // Stores if an initial relay value has been sent
    int lastGasAlarm = -1;
    int wallSwitch = -1;
    int lastWallSwitch = -1;
    int relayState = -1
    long interval = 2000;              // interval at which to sample voltages (milliseconds)
    long gas_warmup_time = 1000;       // Wait time to allow the MQ-5 gas sensor to heat before continuing (milliseconds)
    unsigned long previousMillis = 0;  // Stores last time voltages were updated
    float thermopile_voltage = 0.0;    // Stores the output voltage from the thermopile
    float gas_voltage = 0.0;           // Stores the output voltage from the MQ-5 gas sensor
    //Init MyMessage for Each Child ID
    MyMessage msgGasVolt(CHILD_ID_GAS_VOLTS, V_VOLTAGE);
    MyMessage msgGasAlarm(CHILD_ID_GAS_ALARM, V_TRIPPED);
    MyMessage msgRelay(CHILD_ID_RELAY, V_LIGHT);
    void before() { 
      // Using a Normally Open relay, set the pin high before defining it as output.
      // This prevents the fireplace from igniting during boot.
      digitalWrite(RELAY_PIN, HIGH);
      //Set Relay Pin to output.
      pinMode(RELAY_PIN, OUTPUT);
      //Set Gas Alarm Pin to input
      pinMode(GAS_ALARM_PIN, INPUT);
      //Set wall switch Pin to input
    void setup() {
      wallSwitch = digitalRead(WALL_SWITCH_PIN);     // read the input pin 
      (lastWallSwitch = wallSwitch);
      // Allow the MQ-5 gas sensor to heat before continuing
      Serial.print  ("Warming up the MQ-5 gas sensor for ");
      Serial.print (gas_warmup_time);
      Serial.println (" milliseconds.");
    void presentation()  
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("GasFireplace", "0.1");
      // Present sensors to the gateway
      present(CHILD_ID_GAS_ALARM, S_SMOKE);  
      present(CHILD_ID_RELAY, S_LIGHT);
    void loop() 
      if (!initialValueSent) {
      int gasAlarm = digitalRead(GAS_ALARM_PIN);     // read the input pin
      if (gasAlarm != lastGasAlarm) {
        // Send in the new value
        send(msgGasAlarm.set(gasAlarm==HIGH ? 0 : 1));
         (lastGasAlarm = gasAlarm);
      wallSwitch = digitalRead(WALL_SWITCH_PIN);     // read the input pin
      //Serial.print("WALL_SWITCH_PIN: ");
      Serial.print("wallSwitch: ");
      Serial.print("   lastWallSwitch: ");
      if (wallSwitch != lastWallSwitch) {
        digitalWrite(RELAY_PIN, !digitalRead(RELAY_PIN));
        (lastWallSwitch = wallSwitch);
        (relayState = RELAY_PIN)
        //send(msgRelay.set(RELAY_PIN==HIGH ? 0 : 1));
        send(msgRelay.set(RELAY_PIN), false);         // notify controller of current state
      unsigned long currentMillis = millis();
       if(currentMillis - previousMillis > interval) {
        // save the last time voltage was sampled 
        previousMillis = currentMillis;   
        thermopile_voltage = ((float)analogRead(A2) * 5.015) / 1024.0;
        gas_voltage = ((float)analogRead(A3) * 5.015) / 1024.0;
        Serial.print (" V    ");
        Serial.println (" V");
        send(msgTPVolt.set(thermopile_voltage, 3));
        send(msgGasVolt.set(gas_voltage, 3));    
    void receive(const MyMessage &message) {
      // We only expect one type of message from controller but we better check anyway.
      if (message.type==V_LIGHT)
        if (!initialValueSent) {
          Serial.println("Receiving initial value from controller");
          initialValueSent = true;
         // Update Relay State based on received message from gateway.
          digitalWrite(RELAY_PIN, message.getBool()?RELAY_ON:RELAY_OFF);
         // Send updated relay state back to gateway.

    Thanks in advance for any input!

  • Mod

    @iteafreely said in Very close I think...:

    (relayState = RELAY_PIN)

    Hi welcome to the forum.

    I think you meant to assign something else to relaystate, otherwise it would always be "3"

  • Yes thank you. I want to assign to it the current state of the relay.
    Ultimately though, I don't know if I even need that variable. I just can't figure out how to get the current state of the relay and then send it in a message to the controller.
    It must be obvious, but my brain is fried at this point.

  • Mod

    Have you looked at the relay with button example sketch?

    Then look also here

    You don't have to to read relay status because you are controlling it, so whenever you are doing the digitalwrite just set the relaystate with the same value

Log in to reply

Suggested Topics

  • 6
  • 25
  • 2
  • 15
  • 7
  • 4
  • 11
  • 33