Minule som písal stručne o enkodéroch, a teraz v jednom projekte som ho použil na nastavenie prevádzkových premenných. Potreboval som ale nastavovať parametre v jednotkách milisekúnd, ale v rozsahu od pár desiatok až po tisíce. Najskôr som to riešil tým, že som do menu dal položku step, kde sa nastavil krok prírastku (od 0 do XXX v krokoch po 1), a ďalšie premenné sa upravovali v týchto krokoch. Funkčné, ale otravné.
Takže som sa rozhodol po vzore kuchynskej rúry na pečenie naprogramovať prírastky nelineárne / dynamicky – podľa rýchlosti otáčania enkodérom. Pri pomalom otáčaní sa upravuje hodnota o 1, pri rýchlejšom otáčaní (menej ako 500 ms medzi pootočením) sa krok zvyšuje nelineárne – čím rýchlejšie, tým väčší krok. Takto sa dá s presnosťou na jednotky nastaviť hodnota v širokom rozsahu – na jedno svižné pootočenie kľudne aj o 250000.
Nech sa páči, zdrojový kód (knižnica je v prvom článku) a video.
#include <rotary.h>
#define non_lin 50.0 // cim vyssie cislo, tym agresivnejsie prirastky
volatile unsigned long tm_enc;
volatile unsigned long num;
boolean do_update = true;
Rotary r = Rotary(5, 6);
void setup(){
Serial.begin(9600);
PCICR |= _BV(PCIE2);
PCMSK2 |= _BV(PCINT21) | _BV(PCINT22);
sei();
}
void loop(){
if (do_update){ // vypis na seriovu konzolu len ak je zmena
Serial.println(num);
do_update = false;
}
}
ISR(PCINT2_vect){
char result = r.process();
if (result){
do_update = true; // urob vypis na seriovu konzolu
uint32_t span = millis() - tm_enc;
uint16_t step = 1; // prirastok je normalne 1
if (span < 500){ // ak tocime rychlejsie...
step = pow(10, non_lin / (float)span); // nelinearitu zabezpecuje mocnina (10^x)
}
result == DIR_CCW ? num += step : num -= step;
tm_enc = millis();
}
}

Pridaj komentár