Smart button / scene controller



  • The idea started when i bought a flic smart button.
    Today i use it to raise, lower and play/pause my chromecast audio.
    I want more buttons, actually a want more buttons doing the same thing.
    I have my flic in my kitchen. But when i am at my table? or in my couch?
    Of course, i could buy more flics. But..... Mysensors....
    To start with i will put these button under my tables for easy volume control.

    This is a sleeping node presenting it self as a scene controller.

    If someone want to try a sleeping mysensors smart button. Version 2.X compatible.
    Three functions from one button. Single click, double click and hold.
    You will need to install an external library called Onebutton. This is available in the library manager.

    This have been done before by @dakipro but that thread isn't that easy to find it you search and isn't 2.X compatible.
    By finding that very thread i solved the sleep.

    /*
      Mysensors Smart Button
    */
    
    #define MY_DEBUG
    #define MY_RADIO_NRF24
    
    #include "OneButton.h"
    #include <SPI.h>
    #include <MySensors.h>
    
    #define SN "MySmartButton"
    #define SV "1.0"
    #define CHILD_ID 1
    #define SLEEP_PIN 2
    // Setup a new OneButton on pin D2. true will set pin high (internal pull up), false will set pin low.
    OneButton button(2, true);
    unsigned long previousMillis = 0;
    unsigned long currentMillis = 0;
    const long interval = 5000;
    
    MyMessage on(CHILD_ID, V_SCENE_ON);
    
    // setup code here, to run once:
    void setup() {
    
      // link the doubleclick function to be called on a doubleclick event.
      button.attachClick(click);
      button.attachDoubleClick(doubleclick);
      button.attachPress(press);
    
    } // setup
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SN, SV);
      present(CHILD_ID, S_SCENE_CONTROLLER);
    }
    
    int messageA = 1;
    int messageB = 2;
    int messageC = 3;
    
    
    void loop() {
      currentMillis = millis();
      // keep watching the push button:
      button.tick();
    
      if (currentMillis - previousMillis >= interval) {
        Serial.println("Sleep");
        previousMillis = currentMillis;
        sleep(SLEEP_PIN - 2, CHANGE, 0);
      }
    } // loop
    // this function will be called when the button was pressed one time
    
    void click() {
      send(on.set(messageA));
    }
    // this function will be called when the button was pressed 2 times in a short timeframe.
    void doubleclick() {
      send(on.set(messageB));
    } // doubleclick
    // this function will be called when the button was pressed for about one second
    void press() {
      send(on.set(messageC));
    }
    

    It isn't reporting battery state yet.
    I will add that to the sketch later when i build my button node.
    Maybe i update this thread later when that is done if someone is interested.

    EDIT 2017-06-26
    Some pics.
    0_1498514681220_IMG_20170619_234627.jpg
    0_1498514728022_IMG_20170622_225859.jpg
    0_1498514691129_IMG_20170622_225651.jpg
    0_1498514754436_IMG_20170622_225715.jpg


  • Hero Member

    @xydix I have been playing around with ideas to build a MySensors whole house audio setup. Having three functions from one button is a great idea.



  • I had my node running for a while now.
    I am really happy with it. Nice to not need my phone to start my radio or adjust the volume while i am eating.

    I tried to add vcc.h to the sketch but it causes problems.
    The battery gets reported when the messages arrive but the messages don't get through every time.
    The LED (not the powerLED, i cut that one) on the pro mini just flickers instead of a solid light..

    This is the sketch.
    I searched the forum and copied stuff from the sketch @petewill uses for his chair occupancy sensor.

    /*
      Mysensors Smart Button
    */
    
    #define MY_DEBUG
    #define MY_RADIO_NRF24
    #define MY_NODE_ID 98
    
    #include "OneButton.h"
    #include <SPI.h>
    #include <MySensors.h>
    #include <Vcc.h>
    
    const float VccMin   = 1.0;           // Minimum expected Vcc level, in Volts.
    const float VccMax   = 6.0;           // Maximum expected Vcc level, in Volts.
    const float VccCorrection = 1.0 / 1.0; // Measured Vcc by multimeter divided by reported Vcc
    
    Vcc vcc(VccCorrection);
    
    #define SN "MySmartButton"
    #define SV "1.0"
    #define CHILD_ID 1
    #define SLEEP_PIN 2
    // Setup a new OneButton on pin D2. true will set pin high (internal pull up), false will set pin low.
    OneButton button(2, true);
    unsigned long previousMillis = 0;
    unsigned long currentMillis = 0;
    const long interval = 5000;
    
    MyMessage on(CHILD_ID, V_SCENE_ON);
    
    // setup code here, to run once:
    void setup() {
    
      // link the doubleclick function to be called on a doubleclick event.
      button.attachClick(click);
      button.attachDoubleClick(doubleclick);
      button.attachPress(press);
    
    } // setup
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SN, SV);
      present(CHILD_ID, S_SCENE_CONTROLLER);
    }
    
    int messageA = 1;
    int messageB = 2;
    int messageC = 3;
    
    
    void loop() {
      currentMillis = millis();
      // keep watching the push button:
      button.tick();
    //  float p = vcc.Read_Perc(VccMin, VccMax);
    
      sendBatteryLevel((uint8_t)p); //Send battery level to gateway
      if (currentMillis - previousMillis >= interval) {
        Serial.println("we go sleep");
        previousMillis = currentMillis;
        sleep(SLEEP_PIN - 2, CHANGE, 0);
      }
    } // loop
    // this function will be called when the button was pressed one time
    
    void click() {
      send(on.set(messageA));
    }
    // this function will be called when the button was pressed 2 times in a short timeframe.
    void doubleclick() {
      send(on.set(messageB));
    } // doubleclick
    // this function will be called when the button was pressed for about one second
    void press() {
      send(on.set(messageC));
    }
    


  • I really appreciate if someone would try to help me with battery report.



  • thanks you for mentioning the Onebutton thing, i wasnt aware of it and its really helpful.
    now to report battery, i used the build from my sensors mentioned here https://www.mysensors.org/build/battery
    just follow these steps and you should be fine.
    you need to create a voltage divider (a 1MΩ (R1) and 470KΩ (R2) resistor in series)
    Battery V to R1, then R1 to R2, and R2 connected to battery GND. then the point the resistor meet in the middle add a wire to A0

    #define CHILD_ID_BATTERY 1
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    int oldBatteryPcnt = 0;
    
    MyMessage voltage_msg(CHILD_ID_BATTERY, V_VOLTAGE);
    
     Setup ()
    {
        // use the 1.1 V internal reference
    #if defined(__AVR_ATmega2560__)
        analogReference(INTERNAL1V1);
    #else
        analogReference(INTERNAL);
    #endif
    }
    
    void loop()
    {
    delay(20);
     int sensorValue = analogRead(BATTERY_SENSE_PIN);
    delay(20);
    int batteryPcnt = sensorValue / 10;
    float batteryV  = sensorValue * 0.003363075;
    Serial.print(batteryV);
     if (oldBatteryPcnt != batteryPcnt) {
            // Power up radio after sleep
            sendBatteryLevel(batteryPcnt);
            oldBatteryPcnt = batteryPcnt;
        }
    }
    

    you can also remove it from the loop and create its own function and call it when the sensor wakes up.
    the reason i added delay before and after the analogRead is to let the battery settle a bit so you wont get wrong reading



  • Thank you for your answer.
    I have sensors reporting battery that way.
    It's working fine.
    My smart button sensors is using MYSbootloader and 1,8v bod.
    And my newer nodes I try to build as simple possible.
    Using the vcc library seems to be a simple way to do it.

    But the problem is, it's not working when I add vcc to my sketch. It won't send any value at all.


  • Hardware Contributor

    @xydix said in Smart button / scene controller:

    The battery gets reported when the messages arrive but the messages don't get through every time.

    The LED (not the powerLED, i cut that one) on the pro mini just flickers instead of a solid light..

    This is normal, it's connected to pin 13 which is the clock pin of the SPI so it's not on full time, and not on at all when the node is not sending.

    This is the sketch.

    I don't see the place where you read the battery level ?



  • Thank you. It is solved now.
    Here is the new sketch reporting battery level using the vcc library.

    /*
      Mysensors Smart Button
    */
    
    #define MY_DEBUG
    #define MY_RADIO_NRF24
    #define MY_NODE_ID 7
    
    #include "OneButton.h"
    #include <SPI.h>
    #include <MySensors.h>
    #include <Vcc.h>
    
    #define SN "Kitchen Table"
    #define SV "1.0"
    #define CHILD_ID 1
    #define SLEEP_PIN 2
    // Setup a new OneButton on pin D2. true will set pin high (internal pull up), false will set pin low.
    OneButton button(2, true);
    unsigned long previousMillis = 0;
    unsigned long currentMillis = 0;
    const long interval = 5000;
    
    const float VccMin   = 1.9;           // Minimum expected Vcc level, in Volts. (NRF can only go to 1.9V)
    const float VccMax   = 3.3;           // Maximum expected Vcc level, in Volts.
    const float VccCorrection = 1.0 / 1.0; // Measured Vcc by multimeter divided by reported Vcc
    
    Vcc vcc(VccCorrection);
    
    MyMessage on(CHILD_ID, V_SCENE_ON);
    
    // setup code here, to run once:
    void setup() {
    
      // link the doubleclick function to be called on a doubleclick event.
      button.attachClick(click);
      button.attachDoubleClick(doubleclick);
      button.attachPress(press);
    
    } // setup
    
    void presentation()  {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SN, SV);
      present(CHILD_ID, S_SCENE_CONTROLLER);
    }
    
    int messageA = 1;
    int messageB = 2;
    int messageC = 3;
    
    
    void loop() {
      currentMillis = millis();
      // keep watching the push button:
      button.tick();
    
      if (currentMillis - previousMillis >= interval) {
    
        previousMillis = currentMillis;
      float p = vcc.Read_Perc(VccMin, VccMax);
        sendBatteryLevel((uint8_t)p);
        Serial.println("Sleep");
        sleep(SLEEP_PIN - 2, CHANGE, 0);
      }
    } // loop
    // this function will be called when the button was pressed one time
    
    void click() {
      send(on.set(messageA));
    }
    // this function will be called when the button was pressed 2 times in a short timeframe.
    void doubleclick() {
      send(on.set(messageB));
    } // doubleclick
    // this function will be called when the button was pressed for about one second
    void press() {
      send(on.set(messageC));
    }
    

Log in to reply
 

Suggested Topics

78
Online

11.4k
Users

11.1k
Topics

112.7k
Posts