/*** * 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. * * DESCRIPTION * This sketch provides a Dimmable LED Light using PWM and based Henrik Ekblad * Vera Arduino Sensor project. * Developed by Bruce Lacey, inspired by Hek's MySensor's example sketches. * * The circuit uses a MOSFET for Pulse-Wave-Modulation to dim the attached LED or LED strip. * The MOSFET Gate pin is connected to Arduino pin 3 (LED_PIN), the MOSFET Drain pin is connected * to the LED negative terminal and the MOSFET Source pin is connected to ground. * * This sketch is extensible to support more than one MOSFET/PWM dimmer per circuit. * * REVISION HISTORY * Version 1.0 - February 15, 2014 - Bruce Lacey * Version 1.1 - August 13, 2014 - Converted to 1.4 (hek) * ***/ #define SN "DimmableLEDSwitch" #define SV "1.2" #include #include #include #define SERIAL_RATE 57600L // BAUD_RATE #if 0 // Choose dimmer or light switch here (0 or 1) #define DIMMER_CHILD_ID 0 #else #define LIGHT_CHILD_ID 1 #endif #define LED_PIN 6 // 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) int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point int RESET_EERPOM_PIN = A4; int TEST_MODE_PIN = A5; unsigned long SLEEP_TIME = 60000; // sleep time between reads (seconds * 1000 milliseconds) MySensor gw; static int currentLevel = 0 ; // Current dim level... #ifdef DIMMER_CHILD_ID MyMessage dimmerMsg(DIMMER_CHILD_ID, V_DIMMER); #endif #ifdef LIGHT_CHILD_ID MyMessage lightMsg(LIGHT_CHILD_ID, V_LIGHT); #endif /*** * Dimmable LED initialization method */ void setup() { Serial.begin(SERIAL_RATE); Serial.println( SN ); pinMode(RESET_EERPOM_PIN,INPUT); digitalWrite(RESET_EERPOM_PIN,HIGH); pinMode(TEST_MODE_PIN,INPUT); digitalWrite(TEST_MODE_PIN,HIGH); pinMode(LED_PIN,OUTPUT); gw.begin( incomingMessage ); // Register the LED Dimmable Light with the gateway #ifdef DIMMER_CHILD_ID gw.present( DIMMER_CHILD_ID, S_DIMMER ); #endif #ifdef LIGHT_CHILD_ID gw.present( LIGHT_CHILD_ID, S_LIGHT ); #endif gw.sendSketchInfo(SN, SV); #ifdef DIMMER_CHILD_ID Serial.print( "Initial level:" ); Serial.println( currentLevel ); // Pull the gateway's current dim level - restore light level upon sendor node power-up gw.request( DIMMER_CHILD_ID, V_DIMMER ); Serial.print( "Current level:" ); Serial.println( currentLevel ); gw.requestTime( incomingTime ); delay(5000); Serial.print( "Current level after 5 sec:" ); Serial.println( currentLevel ); // This IS needed for the initial device creation in Domoticz gw.send( dimmerMsg.set(currentLevel) ); #endif // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value... #ifdef LIGHT_CHILD_ID gw.request( LIGHT_CHILD_ID, V_LIGHT ); // This IS needed for the initial device creation in Domoticz gw.send(lightMsg.set(currentLevel > 0 ? 1 : 0)); #endif fadeToLevel( currentLevel ); } /*** * Dimmable LED main processing loop */ void loop() { gw.process(); if (digitalRead(RESET_EERPOM_PIN) != HIGH) { Serial.println("Reset EEPROM"); if ( 1 ) ClearEEPROM(); } if (digitalRead(TEST_MODE_PIN) != HIGH) { Serial.println("Test mode"); SLEEP_TIME = 5000; } // gw.sleep(0, CHANGE, 100); } void incomingTime(unsigned long t) { Serial.print( "Received time " ); Serial.println( t ); } void incomingMessage(const MyMessage &message) { if (message.type == V_LIGHT || message.type == V_DIMMER) { // Retrieve the power or dim level from the incoming request message int requestedLevel = atoi( message.data ); // Adjust incoming level if this is a V_LIGHT variable update [0 == off, 1 == on] requestedLevel *= ( message.type == V_LIGHT ? 100 : 1 ); // Clip incoming level to valid range of 0 to 100 requestedLevel = requestedLevel > 100 ? 100 : requestedLevel; requestedLevel = requestedLevel < 0 ? 0 : requestedLevel; Serial.print( "Changing level to " ); Serial.print( requestedLevel ); Serial.print( ", from " ); Serial.println( currentLevel ); fadeToLevel( requestedLevel ); #ifdef LIGHT_CHILD_ID // Inform the gateway of the current DimmableLED's SwitchPower1 and LoadLevelStatus value... gw.send(lightMsg.set(currentLevel > 0 ? 1 : 0)); #endif #ifdef DIMMER_CHILD_ID gw.send( dimmerMsg.set(currentLevel) ); #endif } } /*** * This method provides a graceful fade up/down effect */ void fadeToLevel( int toLevel ) { int delta = ( toLevel - currentLevel ) < 0 ? -1 : 1; while ( currentLevel != toLevel ) { currentLevel += delta; analogWrite( LED_PIN, 255 * currentLevel / 100 ); delay( FADE_DELAY ); } Serial.print( "Set to level " ); Serial.print( currentLevel ); Serial.println(" ..done"); } void ClearEEPROM() { Serial.println("Clearing EEPROM"); for (int i=0;i<512;i++) { EEPROM.write(i, 0xff); } Serial.println("Cleared EEPROM"); }