Skip to content

Commit

Permalink
Rotary driver adjusted for MiDesk if selected
Browse files Browse the repository at this point in the history
Rotary driver adjusted accordingly if Mi Desk Lamp module is selected (#9399)
  • Loading branch information
arendst committed Oct 20, 2020
1 parent 500fb14 commit 83a090b
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 158 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ All notable changes to this project will be documented in this file.
- Command ``Gpios`` replaces command ``Adcs``
- Management of serial baudrate (#9554)
- ``#define MQTT_FINGERPRINT`` from string to hexnumbers (#9570)
- Rotary driver adjusted accordingly if Mi Desk Lamp module is selected (#9399)

### Fixed
- Convert AdcParam parameters from versions before v9.0.0.2
Expand Down
1 change: 1 addition & 0 deletions RELEASENOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ The attached binaries can also be downloaded from http://ota.tasmota.com/tasmota
- IRremoteESP8266 library from v2.7.10 to v2.7.11
- NeoPixelBus library from v2.5.0.09 to v2.6.0
- Management of serial baudrate (#9554)
- Rotary driver adjusted accordingly if Mi Desk Lamp module is selected (#9399)

### Fixed
- Ledlink blink when no network connected regression from v8.3.1.4 (#9292)
Expand Down
198 changes: 40 additions & 158 deletions tasmota/support_rotary.ino
Original file line number Diff line number Diff line change
Expand Up @@ -37,57 +37,30 @@
#define ROTARY_MAX_STEPS 10 // Rotary step boundary
#endif

#define ROTARY_OPTION1 // Up to 4 interrupts and pulses per step
//#define ROTARY_OPTION2 // Up to 4 interrupts but 1 pulse per step
//#define ROTARY_OPTION3 // 1 interrupt and pulse per step

#ifdef ROTARY_OPTION1
// up to 4 pulses per step
const uint8_t rotary_dimmer_increment = 100 / (ROTARY_MAX_STEPS * 3); // Dimmer 1..100 = 100
const uint8_t rotary_ct_increment = 350 / (ROTARY_MAX_STEPS * 3); // Ct 153..500 = 347
const uint8_t rotary_color_increment = 360 / (ROTARY_MAX_STEPS * 3); // Hue 0..359 = 360
#endif // ROTARY_OPTION1

#ifdef ROTARY_OPTION2
// 1 pulse per step
const uint8_t rotary_dimmer_increment = 100 / ROTARY_MAX_STEPS; // Dimmer 1..100 = 100
const uint8_t rotary_ct_increment = 350 / ROTARY_MAX_STEPS; // Ct 153..500 = 347
const uint8_t rotary_color_increment = 360 / ROTARY_MAX_STEPS; // Hue 0..359 = 360
#endif // ROTARY_OPTION2

#ifdef ROTARY_OPTION3
// 1 pulse per step
const uint8_t rotary_dimmer_increment = 100 / ROTARY_MAX_STEPS; // Dimmer 1..100 = 100
const uint8_t rotary_ct_increment = 350 / ROTARY_MAX_STEPS; // Ct 153..500 = 347
const uint8_t rotary_color_increment = 360 / ROTARY_MAX_STEPS; // Hue 0..359 = 360
const uint8_t ROTARY_DEBOUNCE = 10; // Debounce time in milliseconds
#endif // ROTARY_OPTION3

const uint8_t ROTARY_TIMEOUT = 10; // 10 * RotaryHandler() call which is usually 10 * 0.05 seconds
// (0) = Mi Desk lamp (1) = Normal rotary
// ---------------------------- ----------------------
const uint8_t rotary_dimmer_increment[2] = { 100 / (ROTARY_MAX_STEPS * 3), 100 / ROTARY_MAX_STEPS }; // Dimmer 1..100 = 100
const uint8_t rotary_ct_increment[2] = { 350 / (ROTARY_MAX_STEPS * 3), 350 / ROTARY_MAX_STEPS }; // Ct 153..500 = 347
const uint8_t rotary_color_increment[2] = { 360 / (ROTARY_MAX_STEPS * 3), 360 / ROTARY_MAX_STEPS }; // Hue 0..359 = 360

const uint8_t ROTARY_TIMEOUT = 10; // 10 * RotaryHandler() call which is usually 10 * 0.05 seconds
const uint8_t ROTARY_DEBOUNCE = 10; // Debounce time in milliseconds

struct ROTARY {
uint8_t model = 1;
bool present = false;
} Rotary;

struct tEncoder {
#ifdef ROTARY_OPTION1
volatile uint8_t state = 0;
volatile int8_t pina = -1;
#endif // ROTARY_OPTION1
#ifdef ROTARY_OPTION2
volatile uint16_t store;
volatile uint8_t prev_next_code;
volatile int8_t pina = -1;
#endif // ROTARY_OPTION2
#ifdef ROTARY_OPTION3
volatile uint32_t debounce = 0;
#endif // ROTARY_OPTION3
volatile int8_t direction = 0; // Control consistent direction
volatile int8_t pinb = -1;
volatile uint8_t state = 0;
volatile uint8_t position = 128;
uint8_t last_position = 128;
int8_t abs_position[2] = { 0 };
uint8_t timeout = 0; // Disallow direction change within 0.5 second
int8_t abs_position[2] = { 0 };
int8_t pina = -1;
int8_t pinb = -1;
bool changed = false;
volatile bool busy = false;
};
Expand Down Expand Up @@ -117,63 +90,12 @@ bool RotaryButtonPressed(uint32_t button_index) {
return false;
}

void ICACHE_RAM_ATTR RotaryIsrArg(void *arg) {
void ICACHE_RAM_ATTR RotaryIsrArgMiDesk(void *arg) {
tEncoder* encoder = static_cast<tEncoder*>(arg);

if (encoder->busy) { return; }

#ifdef ROTARY_OPTION1
// https://github.com/PaulStoffregen/Encoder/blob/master/Encoder.h
/*
uint8_t p1val = digitalRead(encoder->pina);
uint8_t p2val = digitalRead(encoder->pinb);
uint8_t state = encoder->state & 3;
if (p1val) { state |= 4; }
if (p2val) { state |= 8; }
encoder->state = (state >> 2);
switch (state) {
case 1: case 7: case 8: case 14:
encoder->position++;
return;
case 2: case 4: case 11: case 13:
encoder->position--;
return;
case 3: case 12:
encoder->position += 2;
return;
case 6: case 9:
encoder->position -= 2;
return;
}
*/

/*
uint8_t p1val = digitalRead(encoder->pina);
uint8_t p2val = digitalRead(encoder->pinb);
uint8_t state = encoder->state & 3;
if (p1val) { state |= 4; }
if (p2val) { state |= 8; }
encoder->state = (state >> 2);
int direction = 0;
int multiply = 1;
switch (state) {
case 3: case 12:
multiply = 2;
case 1: case 7: case 8: case 14:
direction = 1;
break;
case 6: case 9:
multiply = 2;
case 2: case 4: case 11: case 13:
direction = -1;
break;
}
if ((0 == encoder->direction) || (direction == encoder->direction)) {
encoder->position += (direction * multiply);
encoder->direction = direction;
}
*/

uint8_t state = encoder->state & 3;
if (digitalRead(encoder->pina)) { state |= 4; }
if (digitalRead(encoder->pinb)) { state |= 8; }
Expand All @@ -192,58 +114,13 @@ void ICACHE_RAM_ATTR RotaryIsrArg(void *arg) {
encoder->position -= 2;
return;
}
#endif // ROTARY_OPTION1
}

#ifdef ROTARY_OPTION2
// https://github.com/FrankBoesing/EncoderBounce/blob/master/EncoderBounce.h
/*
const uint16_t rot_enc = 0b0110100110010110;
uint8_t p1val = digitalRead(encoder->pinb);
uint8_t p2val = digitalRead(encoder->pina);
uint8_t t = encoder->prev_next_code;
t <<= 2;
if (p1val) { t |= 0x02; }
if (p2val) { t |= 0x01; }
t &= 0x0f;
encoder->prev_next_code = t;
// If valid then store as 16 bit data.
if (rot_enc & (1 << t)) {
encoder->store = (encoder->store << 4) | encoder->prev_next_code;
if (encoder->store == 0xd42b) { encoder->position++; }
else if (encoder->store == 0xe817) { encoder->position--; }
else if ((encoder->store & 0xff) == 0x2b) { encoder->position--; }
else if ((encoder->store & 0xff) == 0x17) { encoder->position++; }
}
*/
const uint16_t rot_enc = 0b0110100110010110;

uint8_t p1val = digitalRead(encoder->pinb);
uint8_t p2val = digitalRead(encoder->pina);
uint8_t t = encoder->prev_next_code;
t <<= 2;
if (p1val) { t |= 0x02; }
if (p2val) { t |= 0x01; }
t &= 0x0f;
encoder->prev_next_code = t;

// If valid then store as 16 bit data.
if (rot_enc & (1 << t)) {
encoder->store = (encoder->store << 4) | encoder->prev_next_code;
int direction = 0;
if (encoder->store == 0xd42b) { direction = 1; }
else if (encoder->store == 0xe817) { direction = -1; }
else if ((encoder->store & 0xff) == 0x2b) { direction = -1; }
else if ((encoder->store & 0xff) == 0x17) { direction = 1; }
if ((0 == encoder->direction) || (direction == encoder->direction)) {
encoder->position += direction;
encoder->direction = direction;
}
}
#endif // ROTARY_OPTION2
void ICACHE_RAM_ATTR RotaryIsrArg(void *arg) {
tEncoder* encoder = static_cast<tEncoder*>(arg);

if (encoder->busy) { return; }

#ifdef ROTARY_OPTION3
// Theo Arends
uint32_t time = millis();
if ((encoder->debounce < time) || (encoder->debounce > time + ROTARY_DEBOUNCE)) {
Expand All @@ -254,24 +131,29 @@ void ICACHE_RAM_ATTR RotaryIsrArg(void *arg) {
}
encoder->debounce = time + ROTARY_DEBOUNCE; // Experimental debounce
}
#endif // ROTARY_OPTION3
}

void RotaryInit(void) {
Rotary.present = false;
Rotary.model = 1;
#ifdef ESP8266
if (MI_DESK_LAMP == my_module_type) {
Rotary.model = 0;
}
#endif // ESP8266
for (uint32_t index = 0; index < MAX_ROTARIES; index++) {
Encoder[index].pinb = -1;
if (PinUsed(GPIO_ROT1A, index) && PinUsed(GPIO_ROT1B, index)) {
Encoder[index].pinb = Pin(GPIO_ROT1B, index);
pinMode(Encoder[index].pinb, INPUT_PULLUP);
#ifdef ROTARY_OPTION3
pinMode(Pin(GPIO_ROT1A, index), INPUT_PULLUP);
attachInterruptArg(Pin(GPIO_ROT1A, index), RotaryIsrArg, &Encoder[index], FALLING);
#else
Encoder[index].pina = Pin(GPIO_ROT1A, index);
pinMode(Encoder[index].pina, INPUT_PULLUP);
attachInterruptArg(Pin(GPIO_ROT1A, index), RotaryIsrArg, &Encoder[index], CHANGE);
attachInterruptArg(Pin(GPIO_ROT1B, index), RotaryIsrArg, &Encoder[index], CHANGE);
#endif
Encoder[index].pinb = Pin(GPIO_ROT1B, index);
pinMode(Encoder[index].pinb, INPUT_PULLUP);
if (0 == Rotary.model) {
attachInterruptArg(Encoder[index].pina, RotaryIsrArgMiDesk, &Encoder[index], CHANGE);
attachInterruptArg(Encoder[index].pinb, RotaryIsrArgMiDesk, &Encoder[index], CHANGE);
} else {
attachInterruptArg(Encoder[index].pina, RotaryIsrArg, &Encoder[index], FALLING);
}
}
Rotary.present |= (Encoder[index].pinb > -1);
}
Expand Down Expand Up @@ -320,20 +202,20 @@ void RotaryHandler(void) {
if (0 == index) { // Rotary1
if (button_pressed) {
if (second_rotary) { // Color RGB
LightColorOffset(rotary_position * rotary_color_increment);
LightColorOffset(rotary_position * rotary_color_increment[Rotary.model]);
} else { // Color Temperature or Color RGB
if (!LightColorTempOffset(rotary_position * rotary_ct_increment)) {
LightColorOffset(rotary_position * rotary_color_increment);
if (!LightColorTempOffset(rotary_position * rotary_ct_increment[Rotary.model])) {
LightColorOffset(rotary_position * rotary_color_increment[Rotary.model]);
}
}
} else { // Dimmer RGBCW or RGB only if second rotary
LightDimmerOffset(second_rotary ? 1 : 0, rotary_position * rotary_dimmer_increment);
LightDimmerOffset(second_rotary ? 1 : 0, rotary_position * rotary_dimmer_increment[Rotary.model]);
}
} else { // Rotary2
if (button_pressed) { // Color Temperature
LightColorTempOffset(rotary_position * rotary_ct_increment);
LightColorTempOffset(rotary_position * rotary_ct_increment[Rotary.model]);
} else { // Dimmer CW
LightDimmerOffset(2, rotary_position * rotary_dimmer_increment);
LightDimmerOffset(2, rotary_position * rotary_dimmer_increment[Rotary.model]);
}
}
} else {
Expand Down

0 comments on commit 83a090b

Please sign in to comment.