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