Rotary Dimmer to LED Control
Make a LED controller with rotary encoder control. To create LED Controller need next components:# | Component | Photo | Price |
1 | Z-Wave plate Z-Uno | 59.49€ | |
2 | MOSFET IRLR8729 | 0.5€ | |
3 | Encoder EC11 | 1€ |
#define PUSH_BUTTON 23
#define ENCODER_CHA_PIN 19
#define ENCODER_CHB_PIN 20
#define LEV_SHIFT 8
#define ENCODER_DEBONCE 4
#define STATE_IDLE 0xFF
#define STATE_SKIP 0xFE
ZUNO_SETUP_ISR_GPTIMER(gpt_handler);
ZUNO_SETUP_CHANNELS(ZUNO_SWITCH_MULTILEVEL(getter, setter));
byte level = 0;
byte last_reported_level = 0;
byte g_state = STATE_IDLE;
byte g_pins = 0;
byte g_debounce_time = 0;
byte last_push_button_state = HIGH;
byte stored_level = 0;
dword last_level_changed_time = 0;
// Runs every 128 μs
void gpt_handler() {
byte pins = 0;
pins = !digitalRead(ENCODER_CHA_PIN);
if(!digitalRead(ENCODER_CHB_PIN))
pins |= 2;
if(g_pins == pins) {
// Is the state stable?
g_debounce_time++;
if(g_debounce_time>ENCODER_DEBONCE) {
if(g_state == STATE_IDLE) {
g_state = pins;
}
else if(g_state == STATE_SKIP) {
if(pins == 0)
g_state = 0;
}
else {
if((g_state == 0 && pins == 1) ||
(g_state == 1 && pins == 3) ||
(g_state == 3 && pins == 2) ||
(g_state == 2 && pins == 0) ) {
if (level < 39) {
level++;
}
else if ((level + LEV_SHIFT) <= 255) {
level += LEV_SHIFT;
}
else if ((level + LEV_SHIFT) > 255){
level = 255;
}
}
else
if((g_state == 0 && pins == 2) ||
(g_state == 2 && pins == 3) ||
(g_state == 3 && pins == 1) ||
(g_state == 1 && pins == 0) ) {
if (level <= 39 && level !=0) {
level--;
}
else if (level >= LEV_SHIFT) {
level -= LEV_SHIFT;
}
else if (level < 0) {
level = 0;
}
}
if(g_state != pins)
g_state = STATE_SKIP;
}
g_debounce_time = 0;
}
}
else {
g_debounce_time = 0;
}
g_pins = pins;
}
void setup() {
Serial.begin();
pinMode(PUSH_BUTTON, INPUT_PULLUP);
pinMode(ENCODER_CHA_PIN, INPUT);
pinMode(ENCODER_CHB_PIN, INPUT_PULLUP);
zunoGPTInit(ZUNO_GPT_SCALE1024|ZUNO_GPT_CYCLIC); // 32 MHz/1024 = 31.25 kHz (tick is 32 μs)
zunoGPTSet(4); // 32 μs * 4 = 128 μs
zunoGPTEnable(1);
}
void loop() {
// Do we need to report the level?
if(last_reported_level != level) {
if (level > 0) {
stored_level = level;
}
last_reported_level = level;
analogWrite(PWM1, level);
last_level_changed_time = millis();
Serial.print("Level: ");
Serial.println(level);
}
// Button handler
byte current_push_button_state = digitalRead(PUSH_BUTTON);
if (current_push_button_state != last_push_button_state) {
last_push_button_state = current_push_button_state;
// if button pressed
if (last_push_button_state == LOW) {
// if LED turned ON, turn OFF
if (level > 0) {
analogWrite(PWM1, 0);
level = 0;
}
// Restore last level
else {
analogWrite(PWM1, stored_level);
level = stored_level;
}
}
}
// Send report if 2 seconds level not changed
if (last_level_changed_time && millis() > last_level_changed_time + 2000) {
last_level_changed_time = 0;
zunoSendReport(1);
}
}
void setter(byte value) {
if (value > 99) {
value = 99;
}
level = (long)value * 255 / 99;
analogWrite(PWM1, level);
}
byte getter(void) {
return last_reported_level * 99 / 255;
}
PCB
Case based on Z-Wave.Me Switch
In room Link to detailed project description (in Russian, use Google to translate)