Led dimmer with touch sensor



  • I'm working on modifying the led dimmer with rotary input to use a touch pad but have ran into issues. It works exactly the way I want it to when the arduino is still plugged into my pc, but it I use my laptop or just the power brick the capsense values fluctuate wildly and even smoothing is not helping.

    I'm thinking it is hardware, I have the default led dimmer setup with a 1M ohm resistor between pins 2 & 4 and a wire coming off 2 for the cap sensing. I am using the capsense library from arduino.

    Here is my wall of code. It is still a bit messy due to troubleshooting.

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Developed by Bruce Lacey and GizMoCuz (Domoticz)
     * Version 1.1 - Modified by hek to incorporate a rotary encode to adjust 
     *                                light level locally at node
     * 
     * DESCRIPTION
     *
     * Default MOSFET pin is 3
     * 
     */
    
     
    #include <SPI.h>
    #include <Encoder.h>
    #include <MySensor.h>  
    #include <Bounce2.h>
    
    #include <CapacitiveSensor.h>
    
    // touch sensor smoothing
    const int numReadings = 10;
    
    int readings[numReadings];      // the readings from the analog input
    int readIndex = 0;              // the index of the current reading
    int total = 0;                  // the running total
    int average = 0;                // the average
    
    
    
    CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        // 11M resistor between pins 4 & 2, pin 2 is sensor pin
    
    // value returned by cap sensor that is a touch if exceeded
    #define TOUCH_THRESHOLD 3000
    #define TOUCH_HOLD_THRESHOLD 200
    
    #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
    #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    #define SEND_THROTTLE_DELAY 2000 // Number of milliseconds before sending after user stops turning knob
    #define SN "DimmableLED /w touch"
    #define SV "0.1"
    
    #define CHILD_ID_LIGHT 1
    
    #define EEPROM_DIM_LEVEL_LAST 1
    #define EEPROM_DIM_LEVEL_SAVE 2
    
    #define LIGHT_OFF 0
    #define LIGHT_ON 1
    
    int touchHoldCount = 0;
    int isTouched;
    int totalraw = 0;
    int dimValue;
    int fadeTo;
    int fadeDelta;
    int oldTotal1;
    int total1;
    bool dimIncrease=true;
    bool sendDimValue=false;
    bool changedByTouch=false;
    unsigned long lastFadeStep;
    unsigned long sendDimTimeout;
    char convBuffer[10];
    
    MySensor gw;
    MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
    Bounce debouncer = Bounce(); 
    
    void setup()  
    { 
      // turn off autocalibrate on channel 1
      // cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);
      
      // oldTotal1 = cs_4_2.capacitiveSensor(30);
    
      // initialize smoothing readings to 0
      for (int thisReading = 0; thisReading < numReadings; thisReading++)
        readings[thisReading] = 0;
    
      // Set analog led pin to off
      analogWrite( LED_PIN, 0);
    
      // Init mysensors library
      gw.begin(incomingMessage, AUTO, false);
    
      // Send the Sketch Version Information to the Gateway
      gw.present(CHILD_ID_LIGHT, S_DIMMER);
      gw.sendSketchInfo(SN, SV);
      Serial.begin(9600);
      // Retreive our last dim levels from the eprom
      fadeTo = dimValue = 0;
      byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
      Serial.print("Sending in last known light level to controller: ");
      Serial.println(oldLevel);  
      gw.send(dimmerMsg.set(oldLevel), true);   
    
      Serial.println("Ready to receive messages...");  
    }
    
    void loop()      
    {
      // Process incoming messages (like config and light state from controller)
      gw.process();
      
      // Check if someone turned the rotary encode
      checkTouchSensor();
      
      // Fade light to new dim value
      fadeStep();
    }
    
    void incomingMessage(const MyMessage &message)
    {
      if (message.type == V_LIGHT) {
        // Incoming on/off command sent from controller ("1" or "0")
        int lightState = message.getString()[0] == '1';
        int newLevel = 0;
        if (lightState==LIGHT_ON) {
          // Pick up last saved dimmer level from the eeprom
          newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
        } 
        // Send dimmer level back to controller with ack enabled
        gw.send(dimmerMsg.set(newLevel), true);
        // We do not change any levels here until ack comes back from gateway 
        return;
      } else if (message.type == V_DIMMER) {
        // Incoming dim-level command sent from controller (or ack message)
        fadeTo = atoi(message.getString(convBuffer));
        // Save received dim value to eeprom (unless turned off). Will be
        // retreived when a on command comes in
        if (fadeTo != 0)
          saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
      }
      saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
      
      Serial.print("New light level received: ");
      Serial.println(fadeTo);
    
      // Stard fading to new light level
      startFade();
    }
    
    void checkTouchSensor() {
      byte newLevel = 0;
      // cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);
      int totalraw = cs_4_2.capacitiveSensor(30);
      if (totalraw > 3200) {
        totalraw = 3200;
      }
      // subtract the last reading:
      total = total - readings[readIndex];
      // read from the sensor:
      readings[readIndex] = totalraw;
      // add the reading to the total:
      total = total + readings[readIndex];
      // advance to the next position in the array:
      readIndex = readIndex + 1;
    
      // if we're at the end of the array...
      if (readIndex >= numReadings)
        // ...wrap around to the beginning:
        readIndex = 0;
    
      // calculate the average:
      total1 = total / numReadings;
      Serial.print(total1);
      Serial.print('\n');
      unsigned long currentTime  = millis();
      //fadeTo = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
      if (total1 > TOUCH_THRESHOLD) {
    //    Serial.print(touchHoldCount);
    //    Serial.print('\n');
        Serial.print(total1);
        Serial.print('\n');
        if (touchHoldCount > TOUCH_HOLD_THRESHOLD) {
          if (fadeTo >= 100) {
            dimIncrease = false;
          }
          if (fadeTo <= 0) {
            dimIncrease = true;
          }
          if (dimIncrease == true) {
            fadeTo = fadeTo +1;
          }
          if (dimIncrease == false) {
            fadeTo = fadeTo -1;
          }
    
          //changedByTouch = true;
          sendDimValue = true;
          sendDimTimeout = currentTime;
          saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
          analogWrite( LED_PIN, (int)(fadeTo / 100. * 255) );
          delay(20);
          dimValue = fadeTo;
          //startFade();
        }else if (touchHoldCount < (TOUCH_HOLD_THRESHOLD + 5)) {
          touchHoldCount = touchHoldCount +1;
        }    
      }else if (total1 < TOUCH_THRESHOLD && dimValue==0 && touchHoldCount != 0 && touchHoldCount < TOUCH_HOLD_THRESHOLD) {
        Serial.print("set old dim");
        Serial.print('\n');
        // Turn on light. Set the level to last saved dim value
        int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
        newLevel = saved > 0 ? saved : 100;
        if (newLevel > 100) {
          newLevel = 100;
        } else if (newLevel < 0) {
          newLevel = 0;
        }
        touchHoldCount = 0;
        sendDimValue = true;
        sendDimTimeout = currentTime;
        fadeTo = newLevel;
        startFade();
      }else if (total1 < TOUCH_THRESHOLD && dimValue>0 && touchHoldCount != 0 && touchHoldCount < TOUCH_HOLD_THRESHOLD) {
        Serial.print("set dim zero");
        Serial.print('\n');
        // Turn off
        newLevel = 0;
        touchHoldCount = 0;
        sendDimValue = true;
        sendDimTimeout = currentTime;
        fadeTo = newLevel;
        startFade();
      }
      //oldTotal1 = total1;
      if (total1 < TOUCH_THRESHOLD && touchHoldCount >= 1) {
       // gw.send(dimmerMsg.set(newLevel),true);
        touchHoldCount = 0;
      }
      if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
         // We're done fading.. send in new dim-value to controller.
         // Send in new dim value with ack (will be picked up in incomingMessage) 
        gw.send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
        sendDimValue = false;
      }
    }
    
    
    void startFade() {
      fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
      lastFadeStep = millis();
    }
    
    // This method provides a graceful none-blocking fade up/down effect
    void fadeStep() {
      unsigned long currentTime  = millis();
      if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
        dimValue += fadeDelta;
        analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
        lastFadeStep = currentTime;
        
        Serial.print("Fading level: ");
        Serial.println(dimValue);
    
        if (fadeTo == dimValue && changedByTouch) {
          sendDimValue = true;
          sendDimTimeout = currentTime;
        }
    
      } 
      // Wait a few millisecs before sending in new value (if user still turns the knob)
      if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
         // We're done fading.. send in new dim-value to controller.
         // Send in new dim value with ack (will be picked up in incomingMessage) 
        gw.send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
        sendDimValue = false;
      }
    }
    
    // Make sure only to store/fetch values in the range 0-100 from eeprom
    int loadLevelState(byte pos) {
      return min(max(gw.loadState(pos),0),100);
    }
    void saveLevelState(byte pos, byte data) {
      gw.saveState(pos,min(max(data,0),100));
    }
    


  • I thought about it a little bit and realized that the reliability issue arose when I was not connected to a really good ground. Referred to the docs and it appears that this is a known issue with capacitive sensing and that a good ground is needed.
    http://playground.arduino.cc/Main/CapacitiveSensor?from=Main.CapSense

    Apparently another work around is a large grounding plate under the touch sensor separated by an insulator. I may just hang some rebar in the middle of my lamp to act as a grounding plate.

    I think the code above can be considered an alpha or rough beta of adding touch. My gateway died so I have not tested that part of the code to make sure I did not break it.

    Basically, the code should take the normal dimmable led and add touch dimming to it. Touching for less than TOUCH_HOLD_THRESHOLD will toggle on/off, longer than that will start a dim up to max, then down to zero and repeat till you let go. What you release at is saved so that if you tap off then back on it returns to the dim level you selected.

    Once I iron out the code I'll post a final version with some instructions. With this you can add touch dimming with a resistor and wire if you have good grounding.



  • Ok, got it working. Probably could use some code cleanup but it works so I don't care. lol

    Code is set up so you can tap on/off, tap and hold to dim with dim value at release getting saved to eeprom and you can double tap to 100% brightness.

    This can be added to any led dimmer by adding a 1M ohm resistor and a touch wire. aka, on the cheap. The Arduino capSense library is needed as well as a good ground.
    http://playground.arduino.cc/Main/CapacitiveSensor?from=Main.CapSense

    @hek you are more than welcome to add this code to the led dimmer build page, I recommend cleaning it up first though. Touch sense could be broken into functions, noted better, and I am pretty sure there is at least one variable declared but not used. lol

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0 - Developed by Bruce Lacey and GizMoCuz (Domoticz)
     * Version 1.1 - Modified by hek to incorporate a rotary encode to adjust 
     *                                light level locally at node
     * Version 1.2 - Modified FreakOfNature to replace rotary encode with touch dim
     * DESCRIPTION
     *
     * Default MOSFET pin is 3
     * 
     */
    
     
    #include <SPI.h>
    #include <Encoder.h>
    #include <MySensor.h>  
    #include <Bounce2.h>
    
    #include <CapacitiveSensor.h>
    
    // touch sensor smoothing
    const int numReadings = 10;
    
    int readings[numReadings];      // the readings from the analog input
    int readIndex = 0;              // the index of the current reading
    int total = 0;                  // the running total
    int average = 0;                // the average
    
    
    
    CapacitiveSensor   cs_4_2 = CapacitiveSensor(4,2);        // 1M resistor between pins 4 & 2, pin 2 is sensor pin
    
    // value returned by cap sensor that is a touch if exceeded
    #define TOUCH_THRESHOLD 500
    // lenght in time before touch is hold, 200 ~1.5 seconds on 16mhz pro mini
    #define TOUCH_HOLD_THRESHOLD 200
    
    #define LED_PIN 3           // Arduino pin attached to MOSFET Gate pin
    #define FADE_DELAY 10       // Delay in ms for each percentage fade up/down (10ms = 1s full-range dim)
    #define TOUCH_FADE_DELAY 40 // Delay() value in dim while touched loop
    #define SEND_THROTTLE_DELAY 4000 // Number of milliseconds before sending after user stops turning knob
    #define DOUBLE_TAP_DELAY 500
    #define SN "DimmableLED /w touch"
    #define SV "1.2"
    
    #define CHILD_ID_LIGHT 1
    
    #define EEPROM_DIM_LEVEL_LAST 1
    #define EEPROM_DIM_LEVEL_SAVE 2
    
    #define LIGHT_OFF 0
    #define LIGHT_ON 1
    
    int tapCount = 0;
    int touchHoldCount = 0;
    int isTouched;
    int totalraw = 0;
    int dimValue;
    int fadeTo;
    int fadeDelta;
    int oldTotal1;
    int total1;
    bool dimIncrease=true;
    bool sendDimValue=false;
    bool changedByTouch=false;
    unsigned long lastFadeStep;
    unsigned long sendDimTimeout;
    char convBuffer[10];
    
    MySensor gw;
    MyMessage dimmerMsg(CHILD_ID_LIGHT, V_DIMMER);
    Bounce debouncer = Bounce(); 
    
    void setup()  
    { 
      // turn off autocalibrate on channel 1
      // cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);
      
      // oldTotal1 = cs_4_2.capacitiveSensor(30);
    
      // initialize smoothing readings to 0
      for (int thisReading = 0; thisReading < numReadings; thisReading++)
        readings[thisReading] = 0;
    
      // Set analog led pin to off
      analogWrite( LED_PIN, 0);
    
      // Init mysensors library
      gw.begin(incomingMessage, AUTO, false);
    
      // Send the Sketch Version Information to the Gateway
      gw.present(CHILD_ID_LIGHT, S_DIMMER);
      gw.sendSketchInfo(SN, SV);
      Serial.begin(9600);
      // Retreive our last dim levels from the eprom
      fadeTo = dimValue = 0;
      byte oldLevel = loadLevelState(EEPROM_DIM_LEVEL_LAST);
      Serial.print("Sending in last known light level to controller: ");
      Serial.println(oldLevel);  
      gw.send(dimmerMsg.set(oldLevel), true);   
    
      Serial.println("Ready to receive messages...");  
    }
    
    void loop()      
    {
      // Process incoming messages (like config and light state from controller)
      gw.process();
      
      // Check if someone turned the rotary encode
      checkTouchSensor();
      
      // Fade light to new dim value
      fadeStep();
    }
    
    void incomingMessage(const MyMessage &message)
    {
      if (message.type == V_LIGHT) {
        // Incoming on/off command sent from controller ("1" or "0")
        int lightState = message.getString()[0] == '1';
        int newLevel = 0;
        if (lightState==LIGHT_ON) {
          // Pick up last saved dimmer level from the eeprom
          newLevel = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
        } 
        // Send dimmer level back to controller with ack enabled
        gw.send(dimmerMsg.set(newLevel), true);
        // We do not change any levels here until ack comes back from gateway 
        return;
      } else if (message.type == V_DIMMER) {
        // Incoming dim-level command sent from controller (or ack message)
        fadeTo = atoi(message.getString(convBuffer));
        // Save received dim value to eeprom (unless turned off). Will be
        // retreived when a on command comes in
        if (fadeTo != 0)
          saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
      }
      saveLevelState(EEPROM_DIM_LEVEL_LAST, fadeTo);
      
      Serial.print("New light level received: ");
      Serial.println(fadeTo);
    
      // Stard fading to new light level
      startFade();
    }
    
    void checkTouchSensor() {
      byte newLevel = 0;
      // cs_4_2.set_CS_AutocaL_Millis(0xFFFFFFFF);
      int totalraw = cs_4_2.capacitiveSensor(30);
      // prevent touch from rolling to negative
      if (totalraw > 3200) {
        totalraw = 3200;
      }
    
      // average last numReadings to stabalize touch
      // subtract the last reading:
      total = total - readings[readIndex];
      // read from the sensor:
      readings[readIndex] = totalraw;
      // add the reading to the total:
      total = total + readings[readIndex];
      // advance to the next position in the array:
      readIndex = readIndex + 1;
    
      // if we're at the end of the array...
      if (readIndex >= numReadings)
        // ...wrap around to the beginning:
        readIndex = 0;
    
      // calculate the average:
      total1 = total / numReadings;
    
      
      
      
      unsigned long currentTime  = millis();
      //fadeTo = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
      if (total1 > TOUCH_THRESHOLD) {
        if (touchHoldCount > TOUCH_HOLD_THRESHOLD) {
          if (fadeTo >= 100) {
            dimIncrease = false;
          }
          if (fadeTo <= 0) {
            dimIncrease = true;
          }
          if (dimIncrease == true) {
            fadeTo = fadeTo +1;
          }
          if (dimIncrease == false) {
            fadeTo = fadeTo -1;
          }
    Serial.print(fadeTo);
        Serial.print('\n');
          sendDimValue = true;
          sendDimTimeout = currentTime;
          saveLevelState(EEPROM_DIM_LEVEL_SAVE, fadeTo);
          analogWrite( LED_PIN, (int)(fadeTo / 100. * 255) );
          delay(TOUCH_FADE_DELAY);
          dimValue = fadeTo;
        }else if (touchHoldCount < (TOUCH_HOLD_THRESHOLD + 5)) {
          touchHoldCount = touchHoldCount +1;
        }    
      }else if (total1 < TOUCH_THRESHOLD && tapCount >= 2) {
        newLevel = 100;
        touchHoldCount = 0;
        tapCount = 0;
        sendDimValue = true;
        sendDimTimeout = currentTime;
        fadeTo = newLevel;
        startFade();
      }else if (total1 < TOUCH_THRESHOLD && dimValue==0 && touchHoldCount != 0 && touchHoldCount < TOUCH_HOLD_THRESHOLD) {
        Serial.print("set old dim");
        Serial.print('\n');
        // Turn on light. Set the level to last saved dim value
        int saved = loadLevelState(EEPROM_DIM_LEVEL_SAVE);
        newLevel = saved > 0 ? saved : 100;
        if (newLevel > 100) {
          newLevel = 100;
        } else if (newLevel < 0) {
          newLevel = 0;
        }
        tapCount = tapCount + 1;
        touchHoldCount = 0;
        sendDimValue = true;
        sendDimTimeout = currentTime;
        fadeTo = newLevel;
        startFade();
      }else if (total1 < TOUCH_THRESHOLD && dimValue>0 && touchHoldCount != 0 && touchHoldCount < TOUCH_HOLD_THRESHOLD) {
        Serial.print("set dim zero");
        Serial.print('\n');
        // Turn off
        tapCount = tapCount + 1;
        newLevel = 0;
        touchHoldCount = 0;
        sendDimValue = true;
        sendDimTimeout = currentTime;
        fadeTo = newLevel;
        startFade();
      }
      //oldTotal1 = total1;
      if (total1 < TOUCH_THRESHOLD && touchHoldCount >= 1) {
       // gw.send(dimmerMsg.set(newLevel),true);
        touchHoldCount = 0;
        dimIncrease = !dimIncrease;
      }
      if (tapCount > 0 && currentTime > sendDimTimeout + DOUBLE_TAP_DELAY) {
        tapCount = 0;
        Serial.print("tap count zero");
        Serial.print('\n');
      }
      if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
         // We're done fading.. send in new dim-value to controller.
         // Send in new dim value with ack (will be picked up in incomingMessage) 
        gw.send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
        sendDimValue = false;
      }
    }
    
    
    void startFade() {
      fadeDelta = ( fadeTo - dimValue ) < 0 ? -1 : 1;
      lastFadeStep = millis();
    }
    
    // This method provides a graceful none-blocking fade up/down effect
    void fadeStep() {
      unsigned long currentTime  = millis();
      if ( dimValue != fadeTo && currentTime > lastFadeStep + FADE_DELAY) {
        dimValue += fadeDelta;
        analogWrite( LED_PIN, (int)(dimValue / 100. * 255) );
        lastFadeStep = currentTime;
        
        Serial.print("Fading level: ");
        Serial.println(dimValue);
    
        if (fadeTo == dimValue && changedByTouch) {
          sendDimValue = true;
          sendDimTimeout = currentTime;
        }
    
      } 
      // Wait a few millisecs before sending in new value (if user still turns the knob)
      if (sendDimValue && currentTime > sendDimTimeout + SEND_THROTTLE_DELAY)  {
         // We're done fading.. send in new dim-value to controller.
         // Send in new dim value with ack (will be picked up in incomingMessage) 
        gw.send(dimmerMsg.set(dimValue), true); // Send new dimmer value and request ack back
        sendDimValue = false;
      }
    }
    
    // Make sure only to store/fetch values in the range 0-100 from eeprom
    int loadLevelState(byte pos) {
      return min(max(gw.loadState(pos),0),100);
    }
    void saveLevelState(byte pos, byte data) {
      gw.saveState(pos,min(max(data,0),100));
    }
    
    
    


  • Before I forget, I should add a few notes for anyone else that wants to try this.

    1. grounding is required unless you want to do trial and error on a ground plane. I just bought a 3 wire extension cord and modified it. Please do not do this unless you know how to mess with things connected to mains without killing yourself.

    2. any capacitance added to the system will skew results, aka you may get good results via serial, but remember even a laptop on batteries adds capacitance, and if you touch it you add more. So, while it looks to work connected to a computer or laptop, do not expect it to work when connected to a lamp the first time.

    3. the larger the metal mass connected to the sensor pin, the less likely it is to work. a small wire, works great. A small lamp, probably works fine I did not test. A six foot tall metal lamp when you live near high voltage lines.... will not work. I had to go with a wire running to a touch pad rather than the entire lamp being the touch surface.

    4. if touch is not working in final install location, get the smallest battery powered computer you have and keep an eye on serial output. print out total1 as this is the value measured against TOUCH_THRESHOLD.



  • Hi @FreakOfNature (hehe, feels awkward saying it like this but its your nickname ūüôā )
    I would like to use same functionality as you use here, to control LED with touch. And I got it working up to some point, but could you post latest version of your code please?
    I see that there are quire a few things missing, and you say it is working for you
    Thanks



  • actually it is working fine, I was just trying to integrate motion sensor as well and made some fail ūüôā
    There are a few very specific "glitches" but I will edit the code a bit. Thank you for sharing the code



  • Dear all,

    first of all, many thanks for this thread which helps me a lot.

    I know this post is old, but I give you my contribution in return.

    I completely rewrite the code to make it modular and more reusable.

    I wrote 3 classes (Dimmer, DimmerDriver an extendedCapacitiveSensor) and a two sketches for Arduino (one without MySensors and one with it).

    In order to compile the scketches, all files must be saved either in the same directory or in a directory listed in the ARDUINO_LIB_PATH or in the USER_LIB_PATH environnement variable.

    Have fun.
    DoccY.

    PS since the posts are limited in length and I can't upload files due to forum policy, I will provide the files in the next messages.



  • File "dimmer.h"

    /******************************************************************************
    *                                                                             *
    *  Copyright © 2018 -- DoccY's productions                                    *
    *                                                                             *
    *  Auteurs/Authors: DoccY <doccy@mancheron.fr>                                *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  Ce  fichier  permet  de  représenter  l'état  d'un variateur  de  lumière  *
    *  (typiquement un ruban de LED).                                             *
    *                                                                             *
    *  Ce logiciel est régi par la licence CeCILL-C soumise au droit français et  *
    *  respectant les principes  de diffusion des logiciels libres.  Vous pouvez  *
    *  utiliser, modifier et/ou redistribuer ce programme sous les conditions de  *
    *  la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA sur  *
    *  le site "http://www.cecill.info".                                          *
    *                                                                             *
    *  En contrepartie de l'accessibilité au code source et des droits de copie,  *
    *  de modification et de redistribution accordés par cette licence, il n'est  *
    *  offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,  *
    *  seule une responsabilité  restreinte pèse  sur l'auteur du programme,  le  *
    *  titulaire des droits patrimoniaux et les concédants successifs.            *
    *                                                                             *
    *  À  cet égard  l'attention de  l'utilisateur est  attirée sur  les risques  *
    *  associés  au chargement,  à  l'utilisation,  à  la modification  et/ou au  *
    *  développement  et à la reproduction du  logiciel par  l'utilisateur étant  *
    *  donné  sa spécificité  de logiciel libre,  qui peut le rendre  complexe à  *
    *  manipuler et qui le réserve donc à des développeurs et des professionnels  *
    *  avertis  possédant  des  connaissances  informatiques  approfondies.  Les  *
    *  utilisateurs  sont donc  invités  à  charger  et  tester  l'adéquation du  *
    *  logiciel  à leurs besoins  dans des conditions  permettant  d'assurer  la  *
    *  sécurité de leurs systêmes et ou de leurs données et,  plus généralement,  *
    *  à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.         *
    *                                                                             *
    *  Le fait  que vous puissiez accéder  à cet en-tête signifie  que vous avez  *
    *  pris connaissance de la licence CeCILL-C, et que vous en avez accepté les  *
    *  termes.                                                                    *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  This File  allows to modelise the state a light dimmer state (typically a  *
    *  led strip).                                                                *
    *                                                                             *
    *  The Gk-arrays-MPI library aims at indexing k-factors from a huge set of    *
    *  sequencing reads generated by High Throughput Sequencing by using the MPI  *
    *  protocol, which is implemented by OpenMPI.                                 *
    *                                                                             *
    *  This software is governed by the CeCILL-C license under French law and     *
    *  abiding by the rules of distribution of free software. You can use,        *
    *  modify and/ or redistribute the software under the terms of the CeCILL-C   *
    *  license as circulated by CEA, CNRS and INRIA at the following URL          *
    *  "http://www.cecill.info".                                                  *
    *                                                                             *
    *  As a counterpart to the access to the source code and rights to copy,      *
    *  modify and redistribute granted by the license, users are provided only    *
    *  with a limited warranty and the software's author, the holder of the       *
    *  economic rights, and the successive licensors have only limited            *
    *  liability.                                                                 *
    *                                                                             *
    *  In this respect, the user's attention is drawn to the risks associated     *
    *  with loading, using, modifying and/or developing or reproducing the        *
    *  software by the user in light of its specific status of free software,     *
    *  that may mean that it is complicated to manipulate, and that also          *
    *  therefore means that it is reserved for developers and experienced         *
    *  professionals having in-depth computer knowledge. Users are therefore      *
    *  encouraged to load and test the software's suitability as regards their    *
    *  requirements in conditions enabling the security of their systems and/or   *
    *  data to be ensured and, more generally, to use and operate it in the same  *
    *  conditions as regards security.                                            *
    *                                                                             *
    *  The fact that you are presently reading this means that you have had       *
    *  knowledge of the CeCILL-C license and that you accept its terms.           *
    *                                                                             *
    ******************************************************************************/
    #ifndef __DIMMER_H__
    #define __DIMMER_H__
    
    #include <Arduino.h>
    
    class Dimmer {
     public:
    
      enum Part {
        LIGHT = 1,
        SWITCH,
        BOTH 
      };
    
      enum Level {
        CURRENT,
        WANTED,
        SAVED
      };
    
      typedef void (*_delay_fct)(unsigned long);
    
     private:
      byte pin; // the pin to control
      bool switch_state; // the switch state (true is ON, false is OFF)
      byte current; // the actual light level
      byte wanted; // the desired light level
      mutable byte saved; // the last saved light level
      bool direction; // the dimmer direction (true to increase, false to decrease)
      unsigned int fade_delay;
      _delay_fct delay_fct;
      int eeprom_level_register;
      int eeprom_state_register;
    
      /*
       * Load (and set) the light level stored in the EEPROM.
       *
       * This function DOES NOT change the switch state neither the real
       * light level. It only reset the value of the wanted light level.
       */
      void loadLevel();
    
      /*
       * Store the specified light level into the EEPROM.
       *
       * This function DOES NOT change the switch state neither the real
       * light level. It only set the value to the wanted light level.
       */
      void saveLevel() const;
    
      /*
       * Load (and set) the switch state stored in the EEPROM.
       *
       * This function DOES NOT change the switch state.
       * It only reset the value of the wanted switch state.
       */
      void loadState();
    
      /*
       * Store the switch state into the EEPROM.
       *
       * This function DOES NOT change the real switch state.
       */
      void saveState() const;
    
      /*
       * Set the wanted light level to the specified level.
       *
       * The light level is increased/decreased towards the wanted light
       * level.
       *
       * If the light level has changed and if the switch is on, a call to
       * delay() is done according to the fade_delay parameter.
       *
       * If the switch state is OFF, then no signal is sent to the N-MOSFET
       * (you need to switch the light ON to see it...)
       */
      void setLevel(byte level);
    
     public:
    
      /*
       * Build a Dimmer Object.
       *
       * The pin correspond to the -- analog or PWM -- pin controlled by
       * the dimmer.
       *
       * The fade delay is specified in ms and the delay function should
       * have the same signature than the delay() function (which is the
       * default).
       *
       * If the eeprom_level_register (respectively the
       * eeprom_state_register) is set to an invalid value (negative or too
       * large or the same), then the dimmer will not use EEPROM to save and restore
       * previous level (resp. switch state). Otherwise, the
       * eeprom_level_register (resp. eeprom_state_register) ID is used to
       * save and restore respectively the dimmer light level (resp. dimmer
       * switch state) on reboot.
       */
      Dimmer(byte pin,
    	 unsigned long fade_delay = 10ul,
    	 _delay_fct delay_fct = delay,
    	 int eeprom_level_register = -1,
    	 int eeprom_state_register = -1);
    
      /*
       * set the delay function (which should have the same signature than
       * the delay() function).
       */
      void setDelayFunction(_delay_fct delay_fct);
    
      /*
       * Load (and set) the light level and/or the switch state stored in
       * the EEPROM.
       *
       * The part parameter can be either LIGHT or SWITCH or both LIGHT
       * and SWITCH (default).
       *
       * This function DOES NOT change the switch state neither the real
       * light level. It only reset the value of the wanted light level
       * and/or switch state.
       */
      void load(Part part = BOTH);
    
      /*
       * Store the specified light level and/or switch state into the
       * EEPROM.
       *
       * The part parameter can be either LIGHT or SWITCH or both LIGHT
       * and SWITCH (default).
       *
       * This function DOES NOT change the switch state neither the real
       * light level not the switch state.
       */
      void save(Part part = BOTH) const;
      
      /*
       * set the fading delay when dimming.
       */
      void setFadingDelay(unsigned long fade_delay);
    
      /*
       * Set the wanted light level to the specified level.
       *
       * The light level is increased/decreased towards the wanted light
       * level.
       *
       * If the light level has changed and if the switch is on, a call to
       * delay() is done according to the fade_delay parameter.
       *
       * If the switch state is OFF, then no signal is sent to the N-MOSFET
       * (you need to switch the light ON to see it...)
       */
      Dimmer &operator=(byte level);
    
      /*
       * Increments the wanted light level (prefix operation).
       */
      Dimmer &operator++();
    
      /*
       * Increments the wanted light level (postfix operation).
       */
      Dimmer operator++(int);
    
      /*
       * Decrements the wanted light level (prefix operation).
       */
      Dimmer &operator--();
    
      /*
       * Decrements the wanted light level (postfix operation).
       */
      Dimmer operator--(int);
    
      /*
       * Switch the dimmer ON
       */
      void ON();
    
      /*
       * Switch the dimmer ON
       */
      void OFF();
    
      /*
       * Toggle the dimmer state (from ON to OFF and vice-versa)
       */
      void toggle();
    
      /*
       * Switch the light ON or OFF according to the value of the parameter
       * on_off.
       *
       * The wanted switch state is stored in the EEPROM (only) if it is
       * modified. If the switch is set to ON and the light level is 0, then
       * the level is changed to 50% with a speed fading delay.
       */
      void setState(bool on_off);
    
      /*
       * Cast the dimmer into its switch state 
       */
      operator bool() const;
    
      /*
       * Returns the CURRENT/WANTED/SAVED light level according to
       * parameter 'level'.
       */
      byte getLevel(Level level) const;
    
      /*
       * Set the dimming direction (true for increasing, false for
       * decreasing).
       */
      void setDirection(bool direction);
    
      /*
       * Returns the dimming direction (true for increasing, false for
       * decreasing).
       */
      bool getDirection() const;
    
      /*
       * One step update of the dimmer according to the current light
       * level and the desired light level.
       */
      void update();
    
    };
    #endif
    // Local Variables:
    // mode:c++
    // End:
    


  • File "dimmer.cpp"

    /******************************************************************************
    *                                                                             *
    *  Copyright © 2018 -- DoccY's productions                                    *
    *                                                                             *
    *  Auteurs/Authors: DoccY <doccy@mancheron.fr>                                *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  Ce  fichier  permet  de  représenter  l'état  d'un variateur  de  lumière  *
    *  (typiquement un ruban de LED).                                             *
    *                                                                             *
    *  Ce logiciel est régi par la licence CeCILL-C soumise au droit français et  *
    *  respectant les principes  de diffusion des logiciels libres.  Vous pouvez  *
    *  utiliser, modifier et/ou redistribuer ce programme sous les conditions de  *
    *  la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA sur  *
    *  le site "http://www.cecill.info".                                          *
    *                                                                             *
    *  En contrepartie de l'accessibilité au code source et des droits de copie,  *
    *  de modification et de redistribution accordés par cette licence, il n'est  *
    *  offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,  *
    *  seule une responsabilité  restreinte pèse  sur l'auteur du programme,  le  *
    *  titulaire des droits patrimoniaux et les concédants successifs.            *
    *                                                                             *
    *  À  cet égard  l'attention de  l'utilisateur est  attirée sur  les risques  *
    *  associés  au chargement,  à  l'utilisation,  à  la modification  et/ou au  *
    *  développement  et à la reproduction du  logiciel par  l'utilisateur étant  *
    *  donné  sa spécificité  de logiciel libre,  qui peut le rendre  complexe à  *
    *  manipuler et qui le réserve donc à des développeurs et des professionnels  *
    *  avertis  possédant  des  connaissances  informatiques  approfondies.  Les  *
    *  utilisateurs  sont donc  invités  à  charger  et  tester  l'adéquation du  *
    *  logiciel  à leurs besoins  dans des conditions  permettant  d'assurer  la  *
    *  sécurité de leurs systêmes et ou de leurs données et,  plus généralement,  *
    *  à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.         *
    *                                                                             *
    *  Le fait  que vous puissiez accéder  à cet en-tête signifie  que vous avez  *
    *  pris connaissance de la licence CeCILL-C, et que vous en avez accepté les  *
    *  termes.                                                                    *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  This File  allows to modelise the state a light dimmer state (typically a  *
    *  led strip).                                                                *
    *                                                                             *
    *  The Gk-arrays-MPI library aims at indexing k-factors from a huge set of    *
    *  sequencing reads generated by High Throughput Sequencing by using the MPI  *
    *  protocol, which is implemented by OpenMPI.                                 *
    *                                                                             *
    *  This software is governed by the CeCILL-C license under French law and     *
    *  abiding by the rules of distribution of free software. You can use,        *
    *  modify and/ or redistribute the software under the terms of the CeCILL-C   *
    *  license as circulated by CEA, CNRS and INRIA at the following URL          *
    *  "http://www.cecill.info".                                                  *
    *                                                                             *
    *  As a counterpart to the access to the source code and rights to copy,      *
    *  modify and redistribute granted by the license, users are provided only    *
    *  with a limited warranty and the software's author, the holder of the       *
    *  economic rights, and the successive licensors have only limited            *
    *  liability.                                                                 *
    *                                                                             *
    *  In this respect, the user's attention is drawn to the risks associated     *
    *  with loading, using, modifying and/or developing or reproducing the        *
    *  software by the user in light of its specific status of free software,     *
    *  that may mean that it is complicated to manipulate, and that also          *
    *  therefore means that it is reserved for developers and experienced         *
    *  professionals having in-depth computer knowledge. Users are therefore      *
    *  encouraged to load and test the software's suitability as regards their    *
    *  requirements in conditions enabling the security of their systems and/or   *
    *  data to be ensured and, more generally, to use and operate it in the same  *
    *  conditions as regards security.                                            *
    *                                                                             *
    *  The fact that you are presently reading this means that you have had       *
    *  knowledge of the CeCILL-C license and that you accept its terms.           *
    *                                                                             *
    ******************************************************************************/
    #include "dimmer.h"
    #include <EEPROM.h>
    
    #ifdef DEBUG
    #  define DBG(msg) if (Serial) Serial.print(msg)
    #  define DBGln(msg) if (Serial) Serial.println(msg)
    #else
    #  define DBG(msg) (void) 0
    #  define DBGln(msg) (void) 0
    #endif
    
    /*
     * Load (and set) the light level stored in the EEPROM.
     *
     * This function DOES NOT change the switch state neither the real
     * light level. It only reset the value of the wanted light level.
     */
    void Dimmer::loadLevel() {
      if (eeprom_level_register >= 0) {
        saved = wanted = min(max(EEPROM.read(eeprom_level_register), 0), 100);
      } else {
        saved = wanted = 50;
      }
      DBG("Restoring saved light level to ");
      DBG(saved);
      DBGln("%");
    }
    
    /*
     * Store the specified light level into the EEPROM.
     *
     * This function DOES NOT change the switch state neither the real
     * light level. It only set the value to the wanted light level.
     */
    void Dimmer::saveLevel() const {
      if (saved != wanted) {
        saved = wanted;
        DBG("Saving light level: ");
        DBG(saved);
        DBGln("%");
        if (eeprom_level_register >= 0) {
          EEPROM.update(eeprom_level_register, saved);
        }
      }
    }
    
    /*
     * Load (and set) the switch state stored in the EEPROM.
     *
     * This function DOES NOT change the switch state.
     * It only reset the value of the wanted switch state.
       */
    void Dimmer::loadState() {
      if (eeprom_state_register >= 0) {
        switch_state = EEPROM[eeprom_state_register];
      } else {
        switch_state = false;
      }
      DBG("Restoring saved switch state to ");
      DBGln(switch_state ? "ON" : "OFF");
    }
    
    /*
     * Store the switch state into the EEPROM.
     *
     * This function DOES NOT change the real switch state.
     */
    void Dimmer::saveState() const {
      DBG("Saving switch state: ");
      DBGln(switch_state ? "ON" : "OFF");
      if (eeprom_state_register >= 0) {
        EEPROM.update(eeprom_state_register, switch_state);
      }
    }
    
    /*
     * Set the wanted light level to the specified level.
     *
     * The light level is increased/decreased towards the wanted light
     * level.
     *
     * If the light level has changed and if the switch is on, a call to
     * delay() is done according to the fade_delay parameter.
     *
     * If the swith state is OFF, then no signal is sent to the N-MOSFET
     * (you need to switch the light ON to see it...)
     */
    void Dimmer::setLevel(byte level) {
      level = min(max(level, 0), 100);
      if (level != wanted) {
        wanted = level;
      }
    
      if (current != wanted) {
        if (wanted > current) {
          ++current;
        } else {
          --current;
        }
        if (switch_state) {
          if (!current && !wanted) {
    	switch_state = false;
    	saveState();
    	setDirection(true);
          }
          analogWrite(pin, max(0, min(current * 255 / 100, 100)));
          delay_fct(fade_delay);
        }
      }
    }
    
    /*
     * Build a Dimmer Object.
     *
     * The pin correspond to the -- analog or PWM -- pin controlled by
     * the dimmer.
     *
     * The fade delay is specified in ms and the delay function should
     * have the same signature than the delay() function (which is the
     * default).
     *
     * If the eeprom_level_register (respectively the
     * eeprom_state_register) is set to an invalid value (negative or too
     * large or the same), then the dimmer will not use EEPROM to save and restore
     * previous level (resp. switch state). Otherwise, the
     * eeprom_level_register (resp. eeprom_state_register) ID is used to
     * save and restore respectively the dimmer light level (resp. dimmer
     * switch state) on reboot.
     */
    Dimmer::Dimmer(byte pin,
    	       unsigned long fade_delay,
    	       _delay_fct delay_fct,
    	       int eeprom_level_register,
    	       int eeprom_state_register):
      pin(pin), switch_state(false),
      current(0), wanted(0), saved(0),
      direction(true),
      fade_delay(fade_delay), delay_fct(delay_fct), 
      eeprom_level_register((eeprom_level_register
    			 && (eeprom_level_register < (int) EEPROM.length())
    			 && (eeprom_level_register != eeprom_state_register))
    			? eeprom_level_register
    			: -1),
      eeprom_state_register((eeprom_state_register
    			 && (eeprom_state_register < (int) EEPROM.length())
    			 && (eeprom_level_register != eeprom_state_register))
    			? eeprom_state_register
    			: -1)
    {
    }
    
    /*
     * set the delay function (which should have the same signature than
     * the delay() function).
     */
    void Dimmer::setDelayFunction(_delay_fct delay_fct) {
      this->delay_fct = delay_fct;
    }
    
    /*
     * Load (and set) the light level and/or the switch state stored in
     * the EEPROM.
     *
     * The part parameter can be either LIGHT or SWITCH or both LIGHT
     * and SWITCH (default).
     *
     * This function DOES NOT change the switch state neither the real
     * light level. It only reset the value of the wanted light level
     * and/or switch state.
     */
    void Dimmer::load(Part part) {
      if (part & LIGHT) {
        loadLevel();
      }
      if (part & SWITCH) {
        loadState();
      }
    }
    
    /*
     * Store the specified light level and/or switch state into the
     * EEPROM.
     *
     * The part parameter can be either LIGHT or SWITCH or both LIGHT
     * and SWITCH (default).
     *
     * This function DOES NOT change the switch state neither the real
     * light level not the switch state.
     */
    void Dimmer::save(Part part) const {
      if (part & LIGHT) {
        saveLevel();
      }
      if (part & SWITCH) {
        saveState();
      }
    }
      
    /*
     * set the fading delay when dimming.
     */
    void Dimmer::setFadingDelay(unsigned long fade_delay) {
      this->fade_delay = fade_delay;
    }
    
    /*
     * Set the wanted light level to the specified level.
     *
     * The light level is increased/decreased towards the wanted light
     * level.
     *
     * If the light level has changed and if the switch is on, a call to
     * delay() is done according to the fade_delay parameter.
     *
     * If the swith state is OFF, then no signal is sent to the N-MOSFET
     * (you need to switch the light ON to see it...)
     */
    Dimmer &Dimmer::operator=(byte level) {
      setLevel(level);
      return *this;
    }
    
    /*
     * Increments the wanted light level (prefix operation).
     */
    Dimmer &Dimmer::operator++() {
      operator=(wanted + 1);
      return *this;
    }
    
    /*
     * Increments the wanted light level (postfix operation).
     */
    Dimmer Dimmer::operator++(int) {
      Dimmer tmp(*this);
      ++(*this);
      return tmp;
    }
    
    /*
     * Decrements the wanted light level (prefix operation).
     */
    Dimmer &Dimmer::operator--() {
      operator=(wanted - 1);
      return *this;
    }
    
    /*
     * Decrements the wanted light level (postfix operation).
     */
    Dimmer Dimmer::operator--(int) {
      Dimmer tmp(*this);
      --(*this);
      return tmp;
    }
    
    /*
     * Switch the dimmer ON
     */
    void Dimmer::ON() {
      setState(true);
    }
    
    /*
     * Switch the dimmer ON
     */
    void Dimmer::OFF() {
      setState(false);
    }
    
    /*
     * Toggle the dimmer state (from ON to OFF and vice-versa)
     */
    void Dimmer::toggle() {
      setState(!switch_state);
    }
    
    /*
     * Switch the light ON or OFF according to the value of the parameter
     * on_off.
     *
     * The wanted switch state is stored in the EEPROM (only) if it is
     * modified. If the switch is set to ON and the light level is 0, then
     * the level is changed to 50% with a speed fading delay.
     */
    void Dimmer::setState(bool on_off) {
      if (on_off ^ switch_state) {
        // Need to change switch state
        if (on_off) {
          current = 0;
          // Switching ON
          switch_state = true;
          saveState();
          if (!saved) {
    	wanted = 10;
    	saveLevel();
    [0_1525852948035_dimmer.h](Uploading 100%) 	setDirection(true);
          }
          DBG("Switching light on to level: ");
          DBG(saved);
          DBGln("%");
          setLevel(saved);
          setDirection(saved < 75);
        } else {
          // Switching OFF
          saveLevel();
          DBGln("Switching light off.");
          setLevel(0);
        }
      }
    }
    
    /*
     * Cast the dimmer into its switch state 
     */
    Dimmer::operator bool() const {
      return switch_state;
    }
    
    /*
     * If _current is true, then returns the current light level,
     * otherwise returns the wanted light level.
     */
    byte Dimmer::getLevel(Dimmer::Level level) const {
      return ((level == CURRENT)
    	  ? current
    	  : ((level == WANTED)
    	     ? wanted
    	     : saved));
    }
    
    /*
     * Set the dimming direction (true for increasing, false for
     * decreasing).
     */
    void Dimmer::setDirection(bool direction) {
      this->direction = direction;
    }
    
    /*
     * Returns the dimming direction (true for increasing, false for
     * decreasing).
     */
    bool Dimmer::getDirection() const {
      return direction;
    }
    
    /*
     * One step update of the dimmer according to the current light
     * level and the desired light level.
     */
    void Dimmer::update() {
      while (switch_state && (wanted != current)) {
        setLevel(wanted);
        delay_fct(fade_delay);
      }
    }
    


  • File 'dimmerDriver.h'

    /******************************************************************************
    *                                                                             *
    *  Copyright © 2018 -- DoccY's productions                                    *
    *                                                                             *
    *  Auteurs/Authors: DoccY <doccy@mancheron.fr>                                *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  Ce fichier  permet de monitorer  un variateur de lumière  (typiquement un  *
    *  ruban de LED).                                                             *
    *                                                                             *
    *  Ce logiciel est régi par la licence CeCILL-C soumise au droit français et  *
    *  respectant les principes  de diffusion des logiciels libres.  Vous pouvez  *
    *  utiliser, modifier et/ou redistribuer ce programme sous les conditions de  *
    *  la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA sur  *
    *  le site "http://www.cecill.info".                                          *
    *                                                                             *
    *  En contrepartie de l'accessibilité au code source et des droits de copie,  *
    *  de modification et de redistribution accordés par cette licence, il n'est  *
    *  offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,  *
    *  seule une responsabilité  restreinte pèse  sur l'auteur du programme,  le  *
    *  titulaire des droits patrimoniaux et les concédants successifs.            *
    *                                                                             *
    *  À  cet égard  l'attention de  l'utilisateur est  attirée sur  les risques  *
    *  associés  au chargement,  à  l'utilisation,  à  la modification  et/ou au  *
    *  développement  et à la reproduction du  logiciel par  l'utilisateur étant  *
    *  donné  sa spécificité  de logiciel libre,  qui peut le rendre  complexe à  *
    *  manipuler et qui le réserve donc à des développeurs et des professionnels  *
    *  avertis  possédant  des  connaissances  informatiques  approfondies.  Les  *
    *  utilisateurs  sont donc  invités  à  charger  et  tester  l'adéquation du  *
    *  logiciel  à leurs besoins  dans des conditions  permettant  d'assurer  la  *
    *  sécurité de leurs systêmes et ou de leurs données et,  plus généralement,  *
    *  à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.         *
    *                                                                             *
    *  Le fait  que vous puissiez accéder  à cet en-tête signifie  que vous avez  *
    *  pris connaissance de la licence CeCILL-C, et que vous en avez accepté les  *
    *  termes.                                                                    *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  This File allows to drive a light dimmer (typically a led strip).          *
    *                                                                             *
    *  The Gk-arrays-MPI library aims at indexing k-factors from a huge set of    *
    *  sequencing reads generated by High Throughput Sequencing by using the MPI  *
    *  protocol, which is implemented by OpenMPI.                                 *
    *                                                                             *
    *  This software is governed by the CeCILL-C license under French law and     *
    *  abiding by the rules of distribution of free software. You can use,        *
    *  modify and/ or redistribute the software under the terms of the CeCILL-C   *
    *  license as circulated by CEA, CNRS and INRIA at the following URL          *
    *  "http://www.cecill.info".                                                  *
    *                                                                             *
    *  As a counterpart to the access to the source code and rights to copy,      *
    *  modify and redistribute granted by the license, users are provided only    *
    *  with a limited warranty and the software's author, the holder of the       *
    *  economic rights, and the successive licensors have only limited            *
    *  liability.                                                                 *
    *                                                                             *
    *  In this respect, the user's attention is drawn to the risks associated     *
    *  with loading, using, modifying and/or developing or reproducing the        *
    *  software by the user in light of its specific status of free software,     *
    *  that may mean that it is complicated to manipulate, and that also          *
    *  therefore means that it is reserved for developers and experienced         *
    *  professionals having in-depth computer knowledge. Users are therefore      *
    *  encouraged to load and test the software's suitability as regards their    *
    *  requirements in conditions enabling the security of their systems and/or   *
    *  data to be ensured and, more generally, to use and operate it in the same  *
    *  conditions as regards security.                                            *
    *                                                                             *
    *  The fact that you are presently reading this means that you have had       *
    *  knowledge of the CeCILL-C license and that you accept its terms.           *
    *                                                                             *
    ******************************************************************************/
    
    /*
     * The driver functionnalities is merely inspired by the code given at:
     * https://forum.mysensors.org/topic/2510/led-dimmer-with-touch-sensor/3
     */
    
    #ifndef __DIMMER_DRIVER_H__
    #define __DIMMER_DRIVER_H__
    
    #include <Arduino.h>
    #include "dimmer.h"
    
    // Capacitive Sensor variables
    class DimmerDriver {
     private:
      unsigned long start_time; // First time the CS was touched.
      unsigned long last_time; // Last time the CS was touched.
      unsigned long previous_last_time; // Previous last time the CS was touched.
      byte count; // Number of time the CS was touched.
      Dimmer &dimmer; // The dimmer to drive
    
      unsigned long short_active_max_time; // Maximum activation time for the driver to be considered as short activation
      unsigned long counting_time_window; // Maximum time window to consider a past short activation
    
     public:
      /*
       * Create a driver for the given dimmer.
       *
       * If the dimmer is OFF and is shortly activated once, then it is
       * switched on and restored to its preceeding known level.
       *
       * If the dimmer is ON and is shortly activated once, then its level
       * is saved and the dimmer is switched OFF.
       *
       * If the dimmer is shortly activated twice (or more), then the
       * light level varies in a four scale light level (25%, 50% 75%
       * 100%) in ascending, then descending order and so on.
       *
       * If the dimmer is longly activated, the light level varies
       * incremently towards 100%, then decremently towards 0% and so on.
       *
       * The first parameter sets the maximal activation time for the
       * driver to be considered as short activation.
       *
       * The second parameter defines the window time for counting short
       * activation events.
       */
      DimmerDriver(Dimmer &d,
    	       unsigned long short_active_max_time = 250ul,
    	       unsigned long counting_time_window = 250ul);
    
      /*
       * Activates the driver.
       */
      void activate();
    
      /*
       * Deactivates the driver.
       */
      void deactivate();
    
      /*
       * Set the maximal activation time (in milliseconds) to consider as
       * a short activation.
       */
      void setShortActiveMaxTime(unsigned long ms);
    
      /*
       * Set the time window (in milliseconds) between two short
       * activations to consider them as a multiple short activations.
       */
      void setCountingTimeWindow(unsigned long ms);
    
      /*
       * Delay in ms for each percentage fade up/down when switching on/off (10ms = 1s full-range dim)
       */
      static const unsigned long SHORT_FADE_DELAY;
    
      /*
       * Delay in ms for each percentage fade up/down on long activation (20ms = 4s full-range dim)
       */
      static const unsigned long NORMAL_FADE_DELAY;
    
    };
    #endif
    // Local Variables:
    // mode:c++
    // End:
    


  • File 'dimmerDriver.cpp'

    /******************************************************************************
    *                                                                             *
    *  Copyright © 2018 -- DoccY's productions                                    *
    *                                                                             *
    *  Auteurs/Authors: DoccY <doccy@mancheron.fr>                                *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  Ce fichier  permet de monitorer  un variateur de lumière  (typiquement un  *
    *  ruban de LED).                                                             *
    *                                                                             *
    *  Ce logiciel est régi par la licence CeCILL-C soumise au droit français et  *
    *  respectant les principes  de diffusion des logiciels libres.  Vous pouvez  *
    *  utiliser, modifier et/ou redistribuer ce programme sous les conditions de  *
    *  la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA sur  *
    *  le site "http://www.cecill.info".                                          *
    *                                                                             *
    *  En contrepartie de l'accessibilité au code source et des droits de copie,  *
    *  de modification et de redistribution accordés par cette licence, il n'est  *
    *  offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,  *
    *  seule une responsabilité  restreinte pèse  sur l'auteur du programme,  le  *
    *  titulaire des droits patrimoniaux et les concédants successifs.            *
    *                                                                             *
    *  À  cet égard  l'attention de  l'utilisateur est  attirée sur  les risques  *
    *  associés  au chargement,  à  l'utilisation,  à  la modification  et/ou au  *
    *  développement  et à la reproduction du  logiciel par  l'utilisateur étant  *
    *  donné  sa spécificité  de logiciel libre,  qui peut le rendre  complexe à  *
    *  manipuler et qui le réserve donc à des développeurs et des professionnels  *
    *  avertis  possédant  des  connaissances  informatiques  approfondies.  Les  *
    *  utilisateurs  sont donc  invités  à  charger  et  tester  l'adéquation du  *
    *  logiciel  à leurs besoins  dans des conditions  permettant  d'assurer  la  *
    *  sécurité de leurs systêmes et ou de leurs données et,  plus généralement,  *
    *  à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.         *
    *                                                                             *
    *  Le fait  que vous puissiez accéder  à cet en-tête signifie  que vous avez  *
    *  pris connaissance de la licence CeCILL-C, et que vous en avez accepté les  *
    *  termes.                                                                    *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  This File allows to drive a light dimmer (typically a led strip).          *
    *                                                                             *
    *  The Gk-arrays-MPI library aims at indexing k-factors from a huge set of    *
    *  sequencing reads generated by High Throughput Sequencing by using the MPI  *
    *  protocol, which is implemented by OpenMPI.                                 *
    *                                                                             *
    *  This software is governed by the CeCILL-C license under French law and     *
    *  abiding by the rules of distribution of free software. You can use,        *
    *  modify and/ or redistribute the software under the terms of the CeCILL-C   *
    *  license as circulated by CEA, CNRS and INRIA at the following URL          *
    *  "http://www.cecill.info".                                                  *
    *                                                                             *
    *  As a counterpart to the access to the source code and rights to copy,      *
    *  modify and redistribute granted by the license, users are provided only    *
    *  with a limited warranty and the software's author, the holder of the       *
    *  economic rights, and the successive licensors have only limited            *
    *  liability.                                                                 *
    *                                                                             *
    *  In this respect, the user's attention is drawn to the risks associated     *
    *  with loading, using, modifying and/or developing or reproducing the        *
    *  software by the user in light of its specific status of free software,     *
    *  that may mean that it is complicated to manipulate, and that also          *
    *  therefore means that it is reserved for developers and experienced         *
    *  professionals having in-depth computer knowledge. Users are therefore      *
    *  encouraged to load and test the software's suitability as regards their    *
    *  requirements in conditions enabling the security of their systems and/or   *
    *  data to be ensured and, more generally, to use and operate it in the same  *
    *  conditions as regards security.                                            *
    *                                                                             *
    *  The fact that you are presently reading this means that you have had       *
    *  knowledge of the CeCILL-C license and that you accept its terms.           *
    *                                                                             *
    ******************************************************************************/
    
    /*
     * The driver functionnalities is merely inspired by the code given at:
     * https://forum.mysensors.org/topic/2510/led-dimmer-with-touch-sensor/3
     */
    
    #include "dimmerDriver.h"
    
    #ifdef DEBUG
    #  define DBG(msg) if (Serial) Serial.print(msg)
    #  define DBGln(msg) if (Serial) Serial.println(msg)
    #else
    #  define DBG(msg) (void) 0
    #  define DBGln(msg) (void) 0
    #endif
    
    /*
     * Delay in ms for each percentage fade up/down when switching on/off (10ms = 1s full-range dim)
     */
    const unsigned long DimmerDriver::SHORT_FADE_DELAY = 10ul;
    
    /*
     * Delay in ms for each percentage fade up/down on long activation (20ms = 4s full-range dim)
     */
    const unsigned long DimmerDriver::NORMAL_FADE_DELAY = 20ul;
    
    /*
     * Create a driver for the given dimmer.
     *
     * If the dimmer is OFF and is shortly activated once, then it is
     * switched on and restored to its preceeding known level.
     *
     * If the dimmer is ON and is shortly activated once, then its level
     * is saved and the dimmer is switched OFF.
     *
     * If the dimmer is shortly activated twice (or more), then the
     * light level varies in a four scale light level (25%, 50% 75%
     * 100%) in ascending, then descending order and so on.
     *
     * If the dimmer is longly activated, the light level varies
     * incremently towards 100%, then decremently towards 0% and so on.
     *
     * The first parameter sets the maximal activation time for the
     * driver to be considered as short activation.
     *
     * The second parameter defines the window time for counting short
     * activation events.
     */
    DimmerDriver::DimmerDriver(Dimmer &d,
    			   unsigned long short_active_max_time,
    			   unsigned long counting_time_window):
      start_time(0), last_time(0), previous_last_time(0), count(0),
      dimmer(d),
      short_active_max_time(short_active_max_time),
      counting_time_window(counting_time_window)
    {
    }
     
    /*
     * Activates the driver.
     */
    void DimmerDriver::activate() {
      unsigned long now = millis();
      if (start_time) {
        if ((now - start_time) > short_active_max_time) {
          // It is a long activation. Dimming the light
          DBG(dimmer.getDirection() ? "+" : "-");
          dimmer.setDirection(dimmer.getDirection()
    			  && (dimmer.getLevel(Dimmer::CURRENT) < 100)
    			  || (dimmer.getLevel(Dimmer::CURRENT) == 0));
          if ((dimmer.getLevel(Dimmer::WANTED) > 1) || dimmer.getDirection()) {
    	dimmer.setFadingDelay(SHORT_FADE_DELAY);
    	dimmer.ON();
    	dimmer.setFadingDelay(NORMAL_FADE_DELAY);
    	if (dimmer.getDirection()) {
    	  ++dimmer;
    	} else {
    	  --dimmer;
    	}
    	dimmer.update();
          } else {
    	dimmer.setFadingDelay(SHORT_FADE_DELAY);
    	dimmer = 0;
    	dimmer.OFF();
          }
        }
      } else {
        // The driver starts being activated
        DBG("[");
        start_time = now;
      }
      last_time = now;
    }
    
    /*
     * Deactivates the driver.
     */
    void DimmerDriver::deactivate() {
      unsigned long now = millis();
      if (start_time) {
        // Driver was previously activated
        DBG("] ");
        DBG(now - start_time);
        DBG("ms: ");
        if ((last_time - start_time) <= short_active_max_time) {
          // driver was activated for a short time
          if (!previous_last_time
    	  || ((now - previous_last_time) > counting_time_window)) {
    	DBGln("Considering it as a first touch.");
    	// Don't take the touch before this last into account
    	count = 1;
          } else {
    	DBG("Considering it as a second (or more) touch.");
    	// Two or more touches
    	count = 2;
          }
          previous_last_time = last_time;
        } else {
          previous_last_time = 0;
          dimmer.save(Dimmer::LIGHT);
          dimmer.setDirection(!dimmer.getDirection());
          if (dimmer.getLevel(Dimmer::CURRENT) == 0) {
    	dimmer.setDirection(true);
          } else {
    	if (dimmer.getLevel(Dimmer::CURRENT) == 100) {
    	  dimmer.setDirection(false);
    	}
          }
          DBG("Long touch. Next will ");
          DBG(dimmer.getDirection() ? "increase" : "decrease");
          DBGln(" the light level");
        }
        // Force the dimmer direction if light level is either 0 or 100
        if (!dimmer.getLevel(Dimmer::WANTED)) {
          dimmer.setDirection(true);
        } else {
          if (dimmer.getLevel(Dimmer::WANTED) == 100) {
    	dimmer.setDirection(false);
          }
        }
        DBG("=> Light level is ");
        DBG(dimmer.getLevel(Dimmer::CURRENT));
        DBG("%, wanted light level is ");
        DBG(dimmer.getLevel(Dimmer::WANTED));
        DBG("%, saved light level is ");
        DBG(dimmer.getLevel(Dimmer::SAVED));
        DBGln("%.");
        last_time = start_time = 0;
      } else {
        // It may have been recently shortly activated once or twice
        if (previous_last_time) {
          // The driver was recently activated
          if ((now - previous_last_time) > counting_time_window) {
    	DBGln("The counting time window has ended:");
    	dimmer.setFadingDelay(SHORT_FADE_DELAY);
    	if (count == 1) {
    	  // Switch the light
    	  DBGln("=> The CS was touched once. Switching the light...");
    	  dimmer.toggle();
    	} else {
    	  // Swith the light ON to the previous or next preset level 
    	  DBGln("=> The CS was touched twice (or more).");
    	  if (dimmer.getLevel(Dimmer::SAVED) < 13) { // in [0;12] = near 0
    	    dimmer = 25;
    	    dimmer.setDirection(true);
    	  } else {
    	    if (dimmer.getLevel(Dimmer::SAVED) < 38) { // in [13;37] = near 25
    	      dimmer = dimmer.getDirection() ? 50 : 0;
    	      dimmer.setDirection(dimmer.getDirection() || (dimmer.getLevel(Dimmer::WANTED) == 0));
    	    } else {
    	      if (dimmer.getLevel(Dimmer::SAVED) < 63) { // in [38;62] = near 50
    		dimmer = dimmer.getDirection() ? 75 : 25;
    	      } else {
    		if (dimmer.getLevel(Dimmer::SAVED) < 88) { // in [63;87] = near 75
    		  dimmer = dimmer.getDirection() ? 100 : 50;
    		  dimmer.setDirection(dimmer.getDirection() && (dimmer.getLevel(Dimmer::WANTED) < 100));
    		} else { // in [88;100] = near 100
    		  dimmer = 75;
    		  dimmer.setDirection(false);
    		}
    	      }
    	    }
    	  }
    	  DBG("    Dimming the light to ");
    	  DBG(dimmer.getLevel(Dimmer::WANTED));
    	  DBGln("%");
    	  if (dimmer.getLevel(Dimmer::WANTED)) {
    	    dimmer.save(Dimmer::LIGHT);
    	  }
    	  dimmer.ON();
    	}
    	count = 0;
    	previous_last_time = 0;
          }
        }
      }
    }
    
    /*
     * Set the maximal activation time (in milliseconds) to consider as
     * a short activation.
     */
    void DimmerDriver::setShortActiveMaxTime(unsigned long ms) {
      short_active_max_time = ms;
    }
    
    /*
     * Set the time window (in milliseconds) to take into account when
     * counting short activations.
     */
    void DimmerDriver::setCountingTimeWindow(unsigned long ms) {
      counting_time_window = ms;
    }
    


  • File 'extendedCapacitiveSensor.h'

    /******************************************************************************
    *                                                                             *
    *  Copyright © 2018 -- DoccY's productions                                    *
    *                                                                             *
    *  Auteurs/Authors: DoccY <doccy@mancheron.fr>                                *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  Ce fichier  étend  la classe 'CapacitiveSensor'  et permet  de lisser les  *
    *  résultats renvoyés par le capteur sur un échantillon de mesures.           *
    *                                                                             *
    *  Ce logiciel est régi par la licence CeCILL-C soumise au droit français et  *
    *  respectant les principes  de diffusion des logiciels libres.  Vous pouvez  *
    *  utiliser, modifier et/ou redistribuer ce programme sous les conditions de  *
    *  la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA sur  *
    *  le site "http://www.cecill.info".                                          *
    *                                                                             *
    *  En contrepartie de l'accessibilité au code source et des droits de copie,  *
    *  de modification et de redistribution accordés par cette licence, il n'est  *
    *  offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,  *
    *  seule une responsabilité  restreinte pèse  sur l'auteur du programme,  le  *
    *  titulaire des droits patrimoniaux et les concédants successifs.            *
    *                                                                             *
    *  À  cet égard  l'attention de  l'utilisateur est  attirée sur  les risques  *
    *  associés  au chargement,  à  l'utilisation,  à  la modification  et/ou au  *
    *  développement  et à la reproduction du  logiciel par  l'utilisateur étant  *
    *  donné  sa spécificité  de logiciel libre,  qui peut le rendre  complexe à  *
    *  manipuler et qui le réserve donc à des développeurs et des professionnels  *
    *  avertis  possédant  des  connaissances  informatiques  approfondies.  Les  *
    *  utilisateurs  sont donc  invités  à  charger  et  tester  l'adéquation du  *
    *  logiciel  à leurs besoins  dans des conditions  permettant  d'assurer  la  *
    *  sécurité de leurs systêmes et ou de leurs données et,  plus généralement,  *
    *  à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.         *
    *                                                                             *
    *  Le fait  que vous puissiez accéder  à cet en-tête signifie  que vous avez  *
    *  pris connaissance de la licence CeCILL-C, et que vous en avez accepté les  *
    *  termes.                                                                    *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  This File extends the 'CapacitiveSensor' class and allows to smooth the    *
    *  results returned by the sensor on a record sample.                         *
    *                                                                             *
    *  The Gk-arrays-MPI library aims at indexing k-factors from a huge set of    *
    *  sequencing reads generated by High Throughput Sequencing by using the MPI  *
    *  protocol, which is implemented by OpenMPI.                                 *
    *                                                                             *
    *  This software is governed by the CeCILL-C license under French law and     *
    *  abiding by the rules of distribution of free software. You can use,        *
    *  modify and/ or redistribute the software under the terms of the CeCILL-C   *
    *  license as circulated by CEA, CNRS and INRIA at the following URL          *
    *  "http://www.cecill.info".                                                  *
    *                                                                             *
    *  As a counterpart to the access to the source code and rights to copy,      *
    *  modify and redistribute granted by the license, users are provided only    *
    *  with a limited warranty and the software's author, the holder of the       *
    *  economic rights, and the successive licensors have only limited            *
    *  liability.                                                                 *
    *                                                                             *
    *  In this respect, the user's attention is drawn to the risks associated     *
    *  with loading, using, modifying and/or developing or reproducing the        *
    *  software by the user in light of its specific status of free software,     *
    *  that may mean that it is complicated to manipulate, and that also          *
    *  therefore means that it is reserved for developers and experienced         *
    *  professionals having in-depth computer knowledge. Users are therefore      *
    *  encouraged to load and test the software's suitability as regards their    *
    *  requirements in conditions enabling the security of their systems and/or   *
    *  data to be ensured and, more generally, to use and operate it in the same  *
    *  conditions as regards security.                                            *
    *                                                                             *
    *  The fact that you are presently reading this means that you have had       *
    *  knowledge of the CeCILL-C license and that you accept its terms.           *
    *                                                                             *
    ******************************************************************************/
    
    /*
     * The functionnalities of this extension is *completely* inspired by
     * the code given at:
     * https://forum.mysensors.org/topic/2510/led-dimmer-with-touch-sensor/3
     */
    
    #ifndef __EXTENDED_CAPACITIVE_SENSOR_H__
    #define __EXTENDED_CAPACITIVE_SENSOR_H__
    
    #include <Arduino.h>
    #include <CapacitiveSensor.h>
    
    class ExtendedCapacitiveSensor: CapacitiveSensor {
     private:
      unsigned int sample_size;
      byte resolution;
      long int *values;
      long int total;
      long int threshold;
      unsigned int index;
     public:
      /*
       * Constructor
       */
      ExtendedCapacitiveSensor(byte send_pin, byte recv_pin, unsigned int sample_size = 3, byte resolution = 30);
    
      /*
       * Copy constructor
       */
      ExtendedCapacitiveSensor(const ExtendedCapacitiveSensor &ecs);
    
      /*
       * Destructor
       */
      ~ExtendedCapacitiveSensor();
    
      /*
       * Affectation operator
       */
      ExtendedCapacitiveSensor &operator=(const ExtendedCapacitiveSensor &ecs);
    
      /*
       * Calibrate the capacitive sensor using nb reads.
       */
      void calibrate(unsigned long nb);
    
      /*
       * Update the home made capacitive sensor values
       */
      ExtendedCapacitiveSensor &next();
    
      /*
       * Returns true on sensing
       */
      operator bool() const;
    
    };
    
    #endif
    // Local Variables:
    // mode:c++
    // End:
    


  • File 'extendedCapacitiveSensor.cpp'

    /******************************************************************************
    *                                                                             *
    *  Copyright © 2018 -- DoccY's productions                                    *
    *                                                                             *
    *  Auteurs/Authors: DoccY <doccy@mancheron.fr>                                *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  Ce fichier  étend  la classe 'CapacitiveSensor'  et permet  de lisser les  *
    *  résultats renvoyés par le capteur sur un échantillon de mesures.           *
    *                                                                             *
    *  Ce logiciel est régi par la licence CeCILL-C soumise au droit français et  *
    *  respectant les principes  de diffusion des logiciels libres.  Vous pouvez  *
    *  utiliser, modifier et/ou redistribuer ce programme sous les conditions de  *
    *  la licence CeCILL-C telle que diffusée par le CEA, le CNRS et l'INRIA sur  *
    *  le site "http://www.cecill.info".                                          *
    *                                                                             *
    *  En contrepartie de l'accessibilité au code source et des droits de copie,  *
    *  de modification et de redistribution accordés par cette licence, il n'est  *
    *  offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,  *
    *  seule une responsabilité  restreinte pèse  sur l'auteur du programme,  le  *
    *  titulaire des droits patrimoniaux et les concédants successifs.            *
    *                                                                             *
    *  À  cet égard  l'attention de  l'utilisateur est  attirée sur  les risques  *
    *  associés  au chargement,  à  l'utilisation,  à  la modification  et/ou au  *
    *  développement  et à la reproduction du  logiciel par  l'utilisateur étant  *
    *  donné  sa spécificité  de logiciel libre,  qui peut le rendre  complexe à  *
    *  manipuler et qui le réserve donc à des développeurs et des professionnels  *
    *  avertis  possédant  des  connaissances  informatiques  approfondies.  Les  *
    *  utilisateurs  sont donc  invités  à  charger  et  tester  l'adéquation du  *
    *  logiciel  à leurs besoins  dans des conditions  permettant  d'assurer  la  *
    *  sécurité de leurs systêmes et ou de leurs données et,  plus généralement,  *
    *  à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.         *
    *                                                                             *
    *  Le fait  que vous puissiez accéder  à cet en-tête signifie  que vous avez  *
    *  pris connaissance de la licence CeCILL-C, et que vous en avez accepté les  *
    *  termes.                                                                    *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  This File extends the 'CapacitiveSensor' class and allows to smooth the    *
    *  results returned by the sensor on a record sample.                         *
    *                                                                             *
    *  The Gk-arrays-MPI library aims at indexing k-factors from a huge set of    *
    *  sequencing reads generated by High Throughput Sequencing by using the MPI  *
    *  protocol, which is implemented by OpenMPI.                                 *
    *                                                                             *
    *  This software is governed by the CeCILL-C license under French law and     *
    *  abiding by the rules of distribution of free software. You can use,        *
    *  modify and/ or redistribute the software under the terms of the CeCILL-C   *
    *  license as circulated by CEA, CNRS and INRIA at the following URL          *
    *  "http://www.cecill.info".                                                  *
    *                                                                             *
    *  As a counterpart to the access to the source code and rights to copy,      *
    *  modify and redistribute granted by the license, users are provided only    *
    *  with a limited warranty and the software's author, the holder of the       *
    *  economic rights, and the successive licensors have only limited            *
    *  liability.                                                                 *
    *                                                                             *
    *  In this respect, the user's attention is drawn to the risks associated     *
    *  with loading, using, modifying and/or developing or reproducing the        *
    *  software by the user in light of its specific status of free software,     *
    *  that may mean that it is complicated to manipulate, and that also          *
    *  therefore means that it is reserved for developers and experienced         *
    *  professionals having in-depth computer knowledge. Users are therefore      *
    *  encouraged to load and test the software's suitability as regards their    *
    *  requirements in conditions enabling the security of their systems and/or   *
    *  data to be ensured and, more generally, to use and operate it in the same  *
    *  conditions as regards security.                                            *
    *                                                                             *
    *  The fact that you are presently reading this means that you have had       *
    *  knowledge of the CeCILL-C license and that you accept its terms.           *
    *                                                                             *
    ******************************************************************************/
    
    /*
     * The functionnalities of this extension is *completely* inspired by
     * the code given at:
     * https://forum.mysensors.org/topic/2510/led-dimmer-with-touch-sensor/3
     */
    
    #include "extendedCapacitiveSensor.h"
    
    #ifdef DEBUG
    #  define DBG(msg) if (Serial) Serial.print(msg)
    #  define DBGln(msg) if (Serial) Serial.println(msg)
    #else
    #  define DBG(msg) (void) 0
    #  define DBGln(msg) (void) 0
    #endif
    
    ExtendedCapacitiveSensor::ExtendedCapacitiveSensor(byte send_pin, byte recv_pin,
    						   unsigned int sample_size, byte resolution):
      CapacitiveSensor(send_pin, recv_pin),
      sample_size(sample_size),
      resolution(resolution),
      values(NULL), total(0), threshold(0), index(0)
    {
      values = new long int[this->sample_size];
      // Initialize the samples to 0
      for (index = 0; index < this->sample_size; ++index) {
        values[index] = 0;
      }
      index = 0;
    }
    
    /*
     * Copy constructor
     */
    ExtendedCapacitiveSensor::ExtendedCapacitiveSensor(const ExtendedCapacitiveSensor &ecs):
      CapacitiveSensor(ecs),
      sample_size(ecs.sample_size),
      resolution(ecs.resolution),
      values(NULL), total(ecs.total),
      threshold(ecs.threshold), index(0) {
      values = new long int[sample_size];
      for (index = 0; index < sample_size; ++index) {
        values[index] = ecs.values[index];
      }
      index = ecs.index;
    }
    
    /*
     * Destructor
     */
    ExtendedCapacitiveSensor::~ExtendedCapacitiveSensor() {
      delete [] values;
    }
    
    /*
     * Affectation operator
     */
    ExtendedCapacitiveSensor &ExtendedCapacitiveSensor::operator=(const ExtendedCapacitiveSensor &ecs) {
      if (this != &ecs) {
        CapacitiveSensor::operator=(ecs);
        if (sample_size != ecs.sample_size) {
          delete [] values;
          sample_size = ecs.sample_size;
          values = new long int[sample_size];
        }
        for (index = 0; index < sample_size; ++index) {
          values[index] = ecs.values[index];
        }
        total = ecs.total;
        threshold = ecs.threshold;
        index = ecs.index;
        resolution = ecs.resolution;
      }
      return *this;
    }
    
    /*
     * Calibrate the capacitive sensor using nb reads.
     */
    void ExtendedCapacitiveSensor::calibrate(unsigned long nb) {
      // Calibrate the unsensed threshold using the maximum sample total
      // value over 100 tries.
      threshold = 0;
      for (unsigned long i = 0; i < nb; ++i) {
        next();
        threshold = max(total, threshold);
      }
      // Using twice this threshold
      threshold <<= 1;
      threshold /= sample_size;
      DBG("threshold is set to ");
      DBGln(threshold);
    }
    
    /*
     * Update the home made capacitive sensor values
     */
    ExtendedCapacitiveSensor &ExtendedCapacitiveSensor::next() {
      long int v = capacitiveSensor(resolution);
      total -= values[index];
      values[index] = v >= 0 ? v : 0;
      total += values[index];
      /*
        DBG("CS: value[");
        DBG(index);
        DBG("] = ");
        DBG(v);
        DBG(", total = ");
        DBGln(total);
      */
      ++index %= sample_size;
      return *this;
    }
    
    /*
     * Returns true on sensing
     */
    ExtendedCapacitiveSensor::operator bool() const {
      return (total / sample_size) > threshold;
    }
    


  • File 'LightDimmer.ino'

    /******************************************************************************
    *                                                                             *
    *  Copyright © 2018 -- DoccY's productions                                    *
    *                                                                             *
    *  Auteurs/Authors: DoccY <doccy@mancheron.fr>                                *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  Ce logiciel  permet de monitorer  un variateur de lumière (typiquement un  *
    *  ruban de LED) à partir d'un (ou plusieurs) capteurs sensitifs.             *
    *                                                                             *
    *  Ce logiciel est régi par la   licence CeCILL soumise au droit français et  *
    *  respectant les principes  de diffusion des logiciels libres.  Vous pouvez  *
    *  utiliser, modifier et/ou redistribuer ce programme sous les conditions de  *
    *  la licence CeCILL telle que diffusée par   le CEA, le CNRS et l'INRIA sur  *
    *  le site "http://www.cecill.info".                                          *
    *                                                                             *
    *  En contrepartie de l'accessibilité au code source et des droits de copie,  *
    *  de modification et de redistribution accordés par cette licence, il n'est  *
    *  offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,  *
    *  seule une responsabilité  restreinte pèse  sur l'auteur du programme,  le  *
    *  titulaire des droits patrimoniaux et les concédants successifs.            *
    *                                                                             *
    *  À  cet égard  l'attention de  l'utilisateur est  attirée sur  les risques  *
    *  associés au   chargement, à   l'utilisation, à  la modification  et/ou au  *
    *  développement et   à la reproduction du  logiciel par l'utilisateur étant  *
    *  donné  sa spécificité  de logiciel libre,  qui peut le rendre  complexe à  *
    *  manipuler et qui le réserve donc à des développeurs et des professionnels  *
    *  avertis  possédant  des  connaissances  informatiques  approfondies.  Les  *
    *  utilisateurs sont   donc invités   à charger   et tester  l'adéquation du  *
    *  logiciel à   leurs besoins  dans des  conditions permettant  d'assurer la  *
    *  sécurité de leurs systèmes et ou de leurs données et, plus  généralement,  *
    *  à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.         *
    *                                                                             *
    *  Le fait que   vous puissiez accéder à cet  en-tête signifie que vous avez  *
    *  pris connaissance de la licence CeCILL,   et que vous en avez accepté les  *
    *  termes.                                                                    *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  This software allows to drive a light dimmer (typically a led strip) from  *
    *  one or more touch sensors.                                                 *
    *                                                                             *
    *  This software is governed by the CeCILL license under French law and       *
    *  abiding by the rules of distribution of free software. You can use,        *
    *  modify and/ or redistribute the software under the terms of the CeCILL     *
    *  license as circulated by CEA, CNRS and INRIA at the following URL          *
    *  "http://www.cecill.info".                                                  *
    *                                                                             *
    *  As a counterpart to the access to the source code and rights to copy,      *
    *  modify and redistribute granted by the license, users are provided only    *
    *  with a limited warranty and the software's author, the holder of the       *
    *  economic rights, and the successive licensors have only limited            *
    *  liability.                                                                 *
    *                                                                             *
    *  In this respect, the user's attention is drawn to the risks associated     *
    *  with loading, using, modifying and/or developing or reproducing the        *
    *  software by the user in light of its specific status of free software,     *
    *  that may mean that it is complicated to manipulate, and that also          *
    *  therefore means that it is reserved for developers and experienced         *
    *  professionals having in-depth computer knowledge. Users are therefore      *
    *  encouraged to load and test the software's suitability as regards their    *
    *  requirements in conditions enabling the security of their systems and/or   *
    *  data to be ensured and, more generally, to use and operate it in the same  *
    *  conditions as regards security.                                            *
    *                                                                             *
    *  The fact that you are presently reading this means that you have had       *
    *  knowledge of the CeCILL license and that you accept its terms.             *
    *                                                                             *
    ******************************************************************************/
    
    /*
     * The driver functionnalities is merely inspired by the code given at:
     * https://forum.mysensors.org/topic/2510/led-dimmer-with-touch-sensor/3
     *
     * Default MOSFET pin is 3
     */
    
    // Constants
    #define TITLE "Light Dimmer Driver for touch sensors"
    #define VERSION "1.0"
    
    // Libraries
    #include <Bounce2.h>
    
    #include "dimmer.h"
    #include "dimmerDriver.h"
    #include "extendedCapacitiveSensor.h"
    
    // Pins
    #define LED_PIN 3           // Pin attached to N-MOSFET Gate pin
    #define CS_PIN 4            // Auto alimented capacitive touch sensor pin
    #define CS_SEND_PIN 7       // Send pin for the extendedCapacitiveSensor
    #define CS_RECV_PIN 8       // Receive pin for the extendedCapacitiveSensor
    
    Bounce debouncer = Bounce();
    
    #define EEPROM_DIM_LEVEL_SAVE 1 // set to -1 to disable EEPROM saving light level state 
    #define EEPROM_DIM_STATE_SAVE 2 // set to -1 to disable EEPROM saving switch state
    Dimmer dimmer(LED_PIN, DimmerDriver::SHORT_FADE_DELAY, delay, EEPROM_DIM_LEVEL_SAVE, EEPROM_DIM_STATE_SAVE);
    // All but the led pin argument have default values (see dimmer.h).
    // 'Dimmer dimmer(LED_PIN)' is equivalent to
    // 'Dimmer dimmer(LED_PIN, 10ul,delay, -1, -1)'
    
    #define CS_SHORT_TOUCH_MAX_TIME 250ul
    #define CS_COUNTING_TIME_WINDOW 350ul
    DimmerDriver driver(dimmer, CS_SHORT_TOUCH_MAX_TIME, CS_COUNTING_TIME_WINDOW);
    // All but the dimmer argument have default values (see
    // dimmerDriver.h).
    // 'DimmerDriver driver(dimmer)' is equivalent to
    // 'DimmerDriver driver(dimmer, 250ul, 250ul)'
    
    #define CS_SAMPLE_SIZE 10
    #define CS_RESOLUTION 20
    ExtendedCapacitiveSensor cs(CS_SEND_PIN, CS_RECV_PIN, CS_SAMPLE_SIZE, CS_RESOLUTION);
    // All but the send and receive pins have default values (see
    // extendedCapacitiveSensor.h).
    // 'ExtendedCapacitiveSensor cs(x, y)' is equivalent to
    // 'ExtendedCapacitiveSensor cs(x, y, 3, 30);
    
    /*
     * Microcontroler initialization
     */
    void setup() {
    
      Serial.begin(115200);
      while (!Serial) {
        delay(10);
      }
      Serial.print(TITLE);
      Serial.print(" (version ");
      Serial.print(VERSION);
      Serial.println(")");
      Serial.println("========================");
      Serial.println("Starting the Sensor Node");
    
      // Instantiate digital pins
      pinMode(LED_PIN, OUTPUT);
      pinMode(CS_PIN, INPUT_PULLUP);
    
      cs.calibrate(100);
    
      // Restore both the switch state and the light level
      dimmer.load();
    
      // Switch the leds off
      Serial.println("Switch the leds off");
      analogWrite(LED_PIN, 0);
    
      dimmer.update();
    
      Serial.println("Sensor Node is ready...");
      Serial.println("=======================");
    }
    
    /*
     * Microcontroler loop
     */
    void loop() {
    
      // Check if someone touch the Velleman capacitive sensor
      // or the home made capacitive sensor
      bool state = (digitalRead(CS_PIN) == HIGH) || cs.next();
    
      if (state) {
        driver.activate();
      } else {
        driver.deactivate();
      }
    
      // Update the Light Level
      dimmer.update();
    
    }
    
    // Local Variables:
    // mode:c++
    // End:
    

    File 'MySensorsLightDimmer.ino'

    /*
      The MySensors Arduino library handles the wireless radio link and protocol
      between your home built sensors/actuators and HA controller of choice.
      The sensors forms a self healing radio network with optional repeaters. Each
      repeater and gateway builds a routing tables in EEPROM which keeps track of the
      network topology allowing messages to be routed to nodes.
    
      Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
      Copyright (C) 2013-2015 Sensnology AB
      Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
    
      Documentation: http://www.mysensors.org
      Support Forum: http://forum.mysensors.org
    */
    
    /******************************************************************************
    *                                                                             *
    *  Copyright © 2018 -- DoccY's productions                                    *
    *                                                                             *
    *  Auteurs/Authors: DoccY <doccy@mancheron.fr>                                *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  Ce logiciel  permet de monitorer  un variateur de lumière (typiquement un  *
    *  ruban de LED)  à partir d'un (ou plusieurs) capteurs sensitifs comme d'un  *
    *  serveur MySensors.                                                         *
    *                                                                             *
    *  Ce logiciel est régi par la   licence CeCILL soumise au droit français et  *
    *  respectant les principes  de diffusion des logiciels libres.  Vous pouvez  *
    *  utiliser, modifier et/ou redistribuer ce programme sous les conditions de  *
    *  la licence CeCILL telle que diffusée par   le CEA, le CNRS et l'INRIA sur  *
    *  le site "http://www.cecill.info".                                          *
    *                                                                             *
    *  En contrepartie de l'accessibilité au code source et des droits de copie,  *
    *  de modification et de redistribution accordés par cette licence, il n'est  *
    *  offert aux utilisateurs qu'une garantie limitée.  Pour les mêmes raisons,  *
    *  seule une responsabilité  restreinte pèse  sur l'auteur du programme,  le  *
    *  titulaire des droits patrimoniaux et les concédants successifs.            *
    *                                                                             *
    *  À  cet égard  l'attention de  l'utilisateur est  attirée sur  les risques  *
    *  associés au   chargement, à   l'utilisation, à  la modification  et/ou au  *
    *  développement et   à la reproduction du  logiciel par l'utilisateur étant  *
    *  donné  sa spécificité  de logiciel libre,  qui peut le rendre  complexe à  *
    *  manipuler et qui le réserve donc à des développeurs et des professionnels  *
    *  avertis  possédant  des  connaissances  informatiques  approfondies.  Les  *
    *  utilisateurs sont   donc invités   à charger   et tester  l'adéquation du  *
    *  logiciel à   leurs besoins  dans des  conditions permettant  d'assurer la  *
    *  sécurité de leurs systèmes et ou de leurs données et, plus  généralement,  *
    *  à l'utiliser et l'exploiter dans les mêmes conditions de sécurité.         *
    *                                                                             *
    *  Le fait que   vous puissiez accéder à cet  en-tête signifie que vous avez  *
    *  pris connaissance de la licence CeCILL,   et que vous en avez accepté les  *
    *  termes.                                                                    *
    *                                                                             *
    *  -------------------------------------------------------------------------  *
    *                                                                             *
    *  This software allows to drive a light dimmer (typically a led strip) from  *
    *  one or more touch sensors as well as from a MySensors server.              *
    *                                                                             *
    *  This software is governed by the CeCILL license under French law and       *
    *  abiding by the rules of distribution of free software. You can use,        *
    *  modify and/ or redistribute the software under the terms of the CeCILL     *
    *  license as circulated by CEA, CNRS and INRIA at the following URL          *
    *  "http://www.cecill.info".                                                  *
    *                                                                             *
    *  As a counterpart to the access to the source code and rights to copy,      *
    *  modify and redistribute granted by the license, users are provided only    *
    *  with a limited warranty and the software's author, the holder of the       *
    *  economic rights, and the successive licensors have only limited            *
    *  liability.                                                                 *
    *                                                                             *
    *  In this respect, the user's attention is drawn to the risks associated     *
    *  with loading, using, modifying and/or developing or reproducing the        *
    *  software by the user in light of its specific status of free software,     *
    *  that may mean that it is complicated to manipulate, and that also          *
    *  therefore means that it is reserved for developers and experienced         *
    *  professionals having in-depth computer knowledge. Users are therefore      *
    *  encouraged to load and test the software's suitability as regards their    *
    *  requirements in conditions enabling the security of their systems and/or   *
    *  data to be ensured and, more generally, to use and operate it in the same  *
    *  conditions as regards security.                                            *
    *                                                                             *
    *  The fact that you are presently reading this means that you have had       *
    *  knowledge of the CeCILL license and that you accept its terms.             *
    *                                                                             *
    ******************************************************************************/
    
    /*
     * The driver functionnalities is merely inspired by the code given at:
     * https://forum.mysensors.org/topic/2510/led-dimmer-with-touch-sensor/3
     *
     * Default MOSFET pin is 3
     *
     * REVISION HISTORY
     *   Version 1.0 - Developed by Bruce Lacey and GizMoCuz (Domoticz)
     *   Version 1.1 - Modified by hek to incorporate a rotary encode to adjust
     *                 light level locally at node
     *   Version 1.2 - Modified FreakOfNature to replace rotary encode with touch dim
     *   Version 1.3 - Complete rewrite and update to MySensors v.2
     */
    
    // Constants
    #define TITLE "MySensors Light Dimmer /w touch sensors"
    #define VERSION "1.3"
    
    // Enable debug prints to serial monitor
    //#define MY_DEBUG
    
    // Enable and select radio type attached
    #define MY_RADIO_RF24
    
    // Libraries
    #include <SPI.h>
    #include <MySensors.h>
    #include <Bounce2.h>
    
    #include "dimmer.h"
    #include "dimmerDriver.h"
    #include "extendedCapacitiveSensor.h"
    
    // Pins
    #define LED_PIN 3           // Pin attached to N-MOSFET Gate pin
    #define CS_PIN 4            // Auto alimented capacitive touch sensor pin
    #define CS_SEND_PIN 7       // Send pin for the extendedCapacitiveSensor
    #define CS_RECV_PIN 8       // Receive pin for the extendedCapacitiveSensor
    
    Bounce debouncer = Bounce();
    
    #define EEPROM_DIM_LEVEL_SAVE 1 // set to -1 to disable EEPROM saving light level state 
    #define EEPROM_DIM_STATE_SAVE 2 // set to -1 to disable EEPROM saving switch state
    Dimmer dimmer(LED_PIN, DimmerDriver::SHORT_FADE_DELAY, delay, EEPROM_DIM_LEVEL_SAVE, EEPROM_DIM_STATE_SAVE);
    // All but the led pin argument have default values (see dimmer.h).
    // 'Dimmer dimmer(LED_PIN)' is equivalent to
    // 'Dimmer dimmer(LED_PIN, 10ul,delay, -1, -1)'
    
    #define CS_SHORT_TOUCH_MAX_TIME 250ul
    #define CS_COUNTING_TIME_WINDOW 350ul
    DimmerDriver driver(dimmer, CS_SHORT_TOUCH_MAX_TIME, CS_COUNTING_TIME_WINDOW);
    // All but the dimmer argument have default values (see
    // dimmerDriver.h).
    // 'DimmerDriver driver(dimmer)' is equivalent to
    // 'DimmerDriver driver(dimmer, 250ul, 250ul)'
    
    #define CS_SAMPLE_SIZE 10
    #define CS_RESOLUTION 20
    ExtendedCapacitiveSensor cs(CS_SEND_PIN, CS_RECV_PIN, CS_SAMPLE_SIZE, CS_RESOLUTION);
    // All but the send and receive pins have default values (see
    // extendedCapacitiveSensor.h).
    // 'ExtendedCapacitiveSensor cs(x, y)' is equivalent to
    // 'ExtendedCapacitiveSensor cs(x, y, 3, 30);
    
    #define CHILD_ID_LIGHT 1
    MyMessage switchStateMsg(CHILD_ID_LIGHT, V_STATUS);
    MyMessage lightLevelMsg(CHILD_ID_LIGHT, V_PERCENTAGE);
    
    
    /*
     * MySensors Initialization
     */
    void presentation() {
    
      // Send the Sketch Version Information to the Gateway
    #ifdef MY_DEBUG
      Serial.print("Presenting the sensor to MySensors gateway: ");
      Serial.print(SN);
      Serial.print(" version ");
      Serial.println(SV);
    #endif
      present(CHILD_ID_LIGHT, S_DIMMER);
      sendSketchInfo(TITLE, VERSION);
    }
    
    /*
     * MySensors node receive operation
     */
    void receive(const MyMessage &message) {
      if (message.type == V_STATUS) {
        // Incoming on/off command sent from controller ("1" or "0")
        if (message.getBool()) {
          dimmer.ON();
        } else {
          dimmer.OFF();
        }
      } else {
        if (message.type == V_DIMMER) {
          // Incoming dim-level command sent from controller (or ack message)
          dimmer.setFadingDelay(DimmerDriver::SHORT_FADE_DELAY);
          dimmer = message.getUInt();
        }
      }
    }
    
    
    /*
     * Send light level and switch state to MySensors server
     */
    void sendDimmerInfos() {
      switchStateMsg.set((bool) dimmer);
      send(switchStateMsg);
      lightLevelMsg.set(dimmer.getLevel(Dimmer::CURRENT));
      send(lightLevelMsg);
    }
    
    
    /*
     * Microcontroler initialization
     */
    void setup() {
    
      Serial.begin(115200);
      while (!Serial) {
        delay(10);
      }
      Serial.print(TITLE);
      Serial.print(" (version ");
      Serial.print(VERSION);
      Serial.println(")");
      Serial.println("===========================");
      Serial.println("Starting the MySensors Node");
    
      // Instantiate digital pins
      pinMode(LED_PIN, OUTPUT);
      pinMode(CS_PIN, INPUT_PULLUP);
    
      cs.calibrate(100);
    
      // Restore both the switch state and the light level
      dimmer.load();
    
      // Switch the leds off
      Serial.println("Switch the leds off");
      analogWrite(LED_PIN, 0);
    
      dimmer.update();
    
      // Send informations to MySensors
      sendDimmerInfos();
    
      Serial.println("MySensors Node is ready...");
      Serial.println("==========================");
    }
    
    /*
     * Microcontroler loop
     */
    void loop() {
    
      // Check if someone touch the Velleman capacitive sensor
      // or the home made capacitive sensor
      bool state = (digitalRead(CS_PIN) == HIGH) || cs.next();
    
      if (state) {
        driver.activate();
      } else {
        driver.deactivate();
      }
    
      // Update the Light Level
      dimmer.update();
    
      // Send informations to MySensors
      sendDimmerInfos();
    
    }
    
    // Local Variables:
    // mode:c++
    // End:
    

 

265
Online

7.6k
Users

8.5k
Topics

91.2k
Posts