Hi , i just created some sketch for single push button dimming .
(and communication with my homeautomation setup)
As i was not able to find anything good already made .
The sketch is intended to use with an arduino Mega but can be easily modified if you have knowledge.
It is a stripped down version from what i really use in my home but it must work .
(i have UDP connectivity and some other feature in my skecth )
The electrical part is up to you , there is many tutorial on the internet to wire a MOSFET.
Dont hesitate to ask question or propose any correction .
Have a nice day
// by TfouTfou for Arduino Forum , beta version 1.00
// preferably use with arduino MEGA
// Pin 22 to 34 used as Input
// Each Input control this list of PWM ouput in the same order
// 2 3 5 6 7 8 9 11 12 44 45 46
// CHANGE THIS TO SET FADE TIME FROM OFF TO FULL
// PwmFadeTime X 255 = total time
// so 3922 X 255 = 1000110 microsecond = 1 second
unsigned long PwmFadeTime = 3922;
// CHANGE THIS TO CHANGE THE BUTTON PRESS TIME FOR DIMMING
// FROM OFF TO FULL = DimButtonLoopValue X 255 = 4.33 seconds
byte DimButtonLoopValue = 17; // value in Milliseconds
byte count;
// list of PWM pins on arduino MEGA
byte PwmPins[12] = { 2, 3, 5, 6, 7, 8, 9, 11, 12, 44, 45, 46};
byte VirtualInput[12] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
byte TriggerVirtualInput[12];
byte DimCounter[12];
byte PwmStatusUpdateTrigger[12];
bool DimDirection[12] = {true, true, true, true, true, true, true, true, true, true, true, true};
short PwmSetValue[12];
short PwmFadeValue[12];
unsigned long DimButtonLoop[12];
unsigned long TimerStartVirtualInput[12];
unsigned long TimerEndVirtualInput[12];
unsigned long ResultVirtualInput[12];
unsigned long TimerDimCounter[12];
unsigned long PwmStatusUpdateTimer[12];
unsigned long FadeTimerLast[12];
void SingleButtonDimmer() {
for (count = 0; count < 12; count++) {
//FUNCTION FOR BUTTON PRESS SHORTER THAN 345 milliseconds
if (VirtualInput[count] == 0) {
TimerEndVirtualInput[count] = millis();
if (TriggerVirtualInput[count] == 0) {
TriggerVirtualInput[count] = 1;
TimerStartVirtualInput[count] = millis();
}
}
if (VirtualInput[count] == 1) {
if (TriggerVirtualInput[count] == 1) {
TriggerVirtualInput[count] = 0;
// INVERT DIM DIRECTION AFTER BUTTON PRESS
DimDirection[count] = !DimDirection[count];
ResultVirtualInput[count] = TimerEndVirtualInput[count] - TimerStartVirtualInput[count];
//INCREMENT COUNTER ON SHORT PRESS OF THE BUTTON (less than 345 milliseconds)
if (ResultVirtualInput[count] > 10 && ResultVirtualInput[count] < 345) {
TimerDimCounter[count] = millis();
DimCounter[count] += 1;
}
}
}
//PROCESS COUNTER VALUE
if (millis() - TimerDimCounter[count] > 345 && millis() - TimerDimCounter[count] < 350 && VirtualInput[count] == 1) {
if (DimCounter[count] == 1) {
//IF ONE PRESS AND LIGHT ON , TURN LIGHT OFF , THEN UPDATE STATUS TO HOME AUTOMATION SERVER AFTER
if (PwmSetValue[count] > 0) {
DimDirection[count] = true;
PwmSetValue[count] = 0;
PwmStatusUpdateTimer[count] = millis();
PwmStatusUpdateTrigger[count] = 1;
}
//IF ONE PRESS AND LIGHT OFF , ASK HOME AUTOMATION SERVER TO RESTORE STORED VALUE
//(temporarily restore to 50% right now , my actual use case is irelevant to you)
else if (PwmSetValue[count] == 0) {
DimDirection[count] = true;
// ANY COMMAND TO HOME AUTOMATION SERVER
// WE CAN WORK IN STANDALONE BY ADDING SOME FUNCTION TOO
// right now i put 50% brightness temporarily for you
PwmSetValue[count] = 128;
}
}
//IF FAST DOUBLE TAP ON BUTTON , SET FULL BRIGHTNESS (same behaviour as my Hardware Fibaro Dimmer)
if (DimCounter[count] >= 2) {
PwmSetValue[count] = 255;
PwmStatusUpdateTimer[count] = millis();
PwmStatusUpdateTrigger[count] = 1;
}
//RESET TAP COUNTER AT THE END OF THE FUNCTION
DimCounter[count] = 0;
}
//RESET TAP COUNTER IF WAS NOT RESETED PREVIOUSLY
if (millis() - TimerDimCounter[count] > 350) {
DimCounter[count] = 0;
}
//IF BUTTON NOT RELEASED AFTER 350ms THEN START DIMMING LIGHT LEVEL (one step every 17ms)
if (VirtualInput[count] == 0 && millis() - TimerStartVirtualInput[count] > 350 && millis() - DimButtonLoop[count] >= DimButtonLoopValue) {
DimButtonLoop[count] = millis();
PwmStatusUpdateTimer[count] = millis();
PwmStatusUpdateTrigger[count] = 1;
if (DimDirection[count] == true) {
PwmSetValue[count] = PwmSetValue[count] + 1;
PwmSetValue[count] = constrain(PwmSetValue[count], 3, 255);
}
if (DimDirection[count] == false) {
PwmSetValue[count] = PwmSetValue[count] - 1;
PwmSetValue[count] = constrain(PwmSetValue[count], 3, 255);
}
}
// 1500 milliseconds after button released send STATUS UPDATE TO HOMEAUTOMATION SERVER
// THIS FUNCTION MAY BE USELESS TO YOU
if (millis() - PwmStatusUpdateTimer[count] > 1500 && PwmStatusUpdateTrigger[count] == 1) {
PwmStatusUpdateTrigger[count] = 0;
// SEND COMMAND TO HOMEAUTOMATION SERVER HERE
}
}
}
void PWMCheck() {
for (count = 0; count < 12; count++) {
// LOOP TO SET PWM SMOOTHLY
if ((micros() - FadeTimerLast[count]) >= PwmFadeTime) {
FadeTimerLast[count] = micros();
if(PwmSetValue[count] > PwmFadeValue[count]) {
PwmFadeValue[count] = PwmFadeValue[count] + 1;
}
if(PwmSetValue[count] < PwmFadeValue[count]) {
PwmFadeValue[count] = PwmFadeValue[count] - 1;
}
PwmFadeValue[count] = constrain(PwmFadeValue[count], 0, 255);
}
analogWrite(PwmPins[count], PwmFadeValue[count]);
}
}
void setup() {
// set PWM output
pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(5, OUTPUT);
pinMode(6, OUTPUT); pinMode(7, OUTPUT); pinMode(8, OUTPUT);
pinMode(9, OUTPUT); pinMode(11, OUTPUT); pinMode(12, OUTPUT);
pinMode(44, OUTPUT); pinMode(45, OUTPUT); pinMode(46, OUTPUT);
// set Input pin
for (count = 0; count < 12; count++) {
pinMode(count + 22, INPUT_PULLUP);
}
}
void loop() {
//update VirtualInput with actual button value for pin 22 to 34
for (count = 0; count < 12; count++) {
VirtualInput[count] = digitalRead(count + 22);
}
SingleButtonDimmer();
PWMCheck();
}