Rotary encoder

Sekcia určená pre Arduino nadšencov

Moderátor: Moderátori

jankrizan
Nový člen
Nový člen
Príspevky: 53
Dátum registrácie: 04 Mar 2011, 00:00
Vek: 64

Rotary encoder

Príspevok od používateľa jankrizan » 21 Júl 2022, 13:42

Zdravím.
na tejto stránke (https://simple-circuit.com/arduino-rota ... t-display/), je uverejnený príspevok s rotačným enkoderom. Chcem poprosiť niekoho, kto ovláda arduino, či by mi vedel upraviť čítanie enkodéra, tak aby pri dosiahnutí čísla 359 preskočilo čítanie na 0, aj v kladnej aj zápornej hodnote. Tento číta až do 999 a neviem si poradiť, ako na to. Ujo Google mi vytrvalo "odmieta poradiť". Programovanie neovládam, preto by som prosil priamo o úpravu programu, kde a čo vložiť. Potrebujem to na zobrazenie úhlu natočenia pracovného stola. Ďakujem.

Kód: Vybrať všetko

/*
 * Interfacing Arduino with common anode 7-segment display.
 * Print rotary encoder values on 4-digit 7-segment display.
 * This is a free software with NO WARRANTY.
 * https://simple-circuit.com/
 */

// segment pin definitions
#define SegA   12
#define SegB   11
#define SegC   10
#define SegD    9
#define SegE    8
#define SegF    7
#define SegG    6
// common pins of the four digits definitions
#define Dig1    5
#define Dig2    4
#define Dig3    3
#define Dig4    2

// variable declarations
byte   current_digit, last_read;
int8_t quad = 0, change;
int    enc_value = 0;

void setup()
{
  pinMode(SegA, OUTPUT);
  pinMode(SegB, OUTPUT);
  pinMode(SegC, OUTPUT);
  pinMode(SegD, OUTPUT);
  pinMode(SegE, OUTPUT);
  pinMode(SegF, OUTPUT);
  pinMode(SegG, OUTPUT);
  pinMode(Dig1, OUTPUT);
  pinMode(Dig2, OUTPUT);
  pinMode(Dig3, OUTPUT);
  pinMode(Dig4, OUTPUT);

  pinMode(A4, INPUT_PULLUP);
  pinMode(A5, INPUT_PULLUP);
  last_read = digitalRead(A5) << 1 | digitalRead(A4);
  disp_off();  // turn off the display

  // Timer1 module overflow interrupt configuration
  TCCR1A = 0;
  TCCR1B = 1;  // enable Timer1 with prescaler = 1 ( 16 ticks each 1 µs)
  TCNT1  = 0;  // set Timer1 preload value to 0 (reset)
  TIMSK1 = 1;  // enable Timer1 overflow interrupt

  // pin change interrupt configuration
  PCICR  = 2;      // enable pin change interrupt for pins PCINT14..8 (Arduino A0 to A5)
  PCMSK1 = 0x30;   // enable pin change interrupt for pins PCINT12 & PCINT13 (Arduino A4 & A5)

}

ISR(TIMER1_OVF_vect)   // Timer1 interrupt service routine (ISR)
{
  disp_off();  // turn off the display
  uint16_t abs_value = abs(enc_value);  // abs: absolute value

  switch (current_digit)
  {
    case 1:
      if(enc_value < 0)  // if negative value
      {  // print minus sign (-) on digit 1 (most left digit)
        disp(10);   // prepare to display digit 1
        digitalWrite(Dig1, LOW);  // turn on digit 1
      }
      break;

    case 2:
      disp( (abs_value / 100) % 10);   // prepare to display digit 2
      digitalWrite(Dig2, LOW);     // turn on digit 2
      break;

    case 3:
      disp( (abs_value / 10) % 10);   // prepare to display digit 3
      digitalWrite(Dig3, LOW);    // turn on digit 3
      break;

    case 4:
      disp(abs_value % 10);   // prepare to display digit 4 (most right)
      digitalWrite(Dig4, LOW);  // turn on digit 4
  }

  current_digit = (current_digit % 4) + 1;
}

ISR (PCINT1_vect)  // ISR for Arduino A4 (PCINT12) and A5 (PCINT13) pins
{
  uint8_t encoderRead = 0;

  encoderRead = digitalRead(A5) << 1 | digitalRead(A4);

  if(encoderRead == last_read)
    return;

  if(bitRead(encoderRead, 0) == bitRead(last_read, 1))
    quad -= 1;
  else
    quad += 1;
  last_read = encoderRead; 
}

int8_t EncoderGet(void)
{
  int8_t val = 0;
  while(quad >= 4){
    val += 1;
    quad -= 4;
  }
  while(quad <= -4){
    val -= 1;
    quad += 4;
  }
  return val;
}

// main loop
void loop()
{
  change = EncoderGet();
  if(change)
    enc_value += change;
  delay(100);  // wait 100 milliseconds
}

void disp(byte number)
{
  switch (number)
  {
    case 0:  // print 0
      digitalWrite(SegA, LOW);
      digitalWrite(SegB, LOW);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, LOW);
      digitalWrite(SegE, LOW);
      digitalWrite(SegF, LOW);
      digitalWrite(SegG, HIGH);
      break;

    case 1:  // print 1
      digitalWrite(SegA, HIGH);
      digitalWrite(SegB, LOW);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, HIGH);
      digitalWrite(SegE, HIGH);
      digitalWrite(SegF, HIGH);
      digitalWrite(SegG, HIGH);
      break;

    case 2:  // print 2
      digitalWrite(SegA, LOW);
      digitalWrite(SegB, LOW);
      digitalWrite(SegC, HIGH);
      digitalWrite(SegD, LOW);
      digitalWrite(SegE, LOW);
      digitalWrite(SegF, HIGH);
      digitalWrite(SegG, LOW);
      break;

    case 3:  // print 3
      digitalWrite(SegA, LOW);
      digitalWrite(SegB, LOW);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, LOW);
      digitalWrite(SegE, HIGH);
      digitalWrite(SegF, HIGH);
      digitalWrite(SegG, LOW);
      break;

    case 4:  // print 4
      digitalWrite(SegA, HIGH);
      digitalWrite(SegB, LOW);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, HIGH);
      digitalWrite(SegE, HIGH);
      digitalWrite(SegF, LOW);
      digitalWrite(SegG, LOW);
      break;

    case 5:  // print 5
      digitalWrite(SegA, LOW);
      digitalWrite(SegB, HIGH);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, LOW);
      digitalWrite(SegE, HIGH);
      digitalWrite(SegF, LOW);
      digitalWrite(SegG, LOW);
      break;

    case 6:  // print 6
      digitalWrite(SegA, LOW);
      digitalWrite(SegB, HIGH);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, LOW);
      digitalWrite(SegE, LOW);
      digitalWrite(SegF, LOW);
      digitalWrite(SegG, LOW);
      break;
    
    case 7:  // print 7
      digitalWrite(SegA, LOW);
      digitalWrite(SegB, LOW);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, HIGH);
      digitalWrite(SegE, HIGH);
      digitalWrite(SegF, HIGH);
      digitalWrite(SegG, HIGH);
      break;

    case 8:  // print 8
      digitalWrite(SegA, LOW);
      digitalWrite(SegB, LOW);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, LOW);
      digitalWrite(SegE, LOW);
      digitalWrite(SegF, LOW);
      digitalWrite(SegG, LOW);
      break;

    case 9:  // print 9
      digitalWrite(SegA, LOW);
      digitalWrite(SegB, LOW);
      digitalWrite(SegC, LOW);
      digitalWrite(SegD, LOW);
      digitalWrite(SegE, HIGH);
      digitalWrite(SegF, LOW);
      digitalWrite(SegG, LOW);
      break;

    case 10:  // print -
      digitalWrite(SegA, HIGH);
      digitalWrite(SegB, HIGH);
      digitalWrite(SegC, HIGH);
      digitalWrite(SegD, HIGH);
      digitalWrite(SegE, HIGH);
      digitalWrite(SegF, HIGH);
      digitalWrite(SegG, LOW);
  }
}

void disp_off()
{
   digitalWrite(Dig1, HIGH);
   digitalWrite(Dig2, HIGH);
   digitalWrite(Dig3, HIGH);
   digitalWrite(Dig4, HIGH);
}

// end of code.
0

peterple
Ultimate člen
Ultimate člen
Príspevky: 2328
Dátum registrácie: 25 Jún 2013, 21:06
Bydlisko: Krajné
Vek: 57
Kontaktovať používateľa:

Re: Rotary encoder

Príspevok od používateľa peterple » 21 Júl 2022, 19:58

toto

Kód: Vybrať všetko

  change = EncoderGet();
  if(change)
    enc_value += change;
  delay(100);  // wait 100 milliseconds
zmeň takto

Kód: Vybrať všetko

  change = EncoderGet();
  if(change)
    enc_value += change;
  if (enc_value>359) enc_value=0;
  if (enc_value<-359) enc_value=0;
  delay(100);  // wait 100 milliseconds
0
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.

jankrizan
Nový člen
Nový člen
Príspevky: 53
Dátum registrácie: 04 Mar 2011, 00:00
Vek: 64

Re: Rotary encoder

Príspevok od používateľa jankrizan » 21 Júl 2022, 20:25

Si pašák peterple,
Srdečné Ďakujem. A pritom také jednoduché.
0

peterple
Ultimate člen
Ultimate člen
Príspevky: 2328
Dátum registrácie: 25 Jún 2013, 21:06
Bydlisko: Krajné
Vek: 57
Kontaktovať používateľa:

Re: Rotary encoder

Príspevok od používateľa peterple » 21 Júl 2022, 20:59

Niet za čo.
Nuž toto nevygoogliš. Tu musíš pochopiť ako to pracuje - naučiť sa programovať.
0
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.

pocitujlasku
Ultimate člen
Ultimate člen
Príspevky: 6205
Dátum registrácie: 20 Júl 2007, 00:00
Vek: 41

Re: Rotary encoder

Príspevok od používateľa pocitujlasku » 21 Júl 2022, 22:15

a keby tie 2 if nahradil

Kód: Vybrať všetko

  if (abs(enc_value)>359) enc_value=0;
0
Jedním z největších projevů nedůvěry v Boha je hromosvod na kostele.

Používateľov profilový obrázok
budvar10
Pokročilý člen
Pokročilý člen
Príspevky: 989
Dátum registrácie: 15 Dec 2014, 10:55
Bydlisko: Košice

Re: Rotary encoder

Príspevok od používateľa budvar10 » 22 Júl 2022, 07:12

A dôvod tejto náhrady?

Ja by som to dal takto:

Kód: Vybrať všetko

if (enc_value>359) enc_value=0;
 else if (enc_value<-359) enc_value=0;
alebo takto:

Kód: Vybrať všetko

if (enc_value>359 || enc_value<-359) enc_value=0;
Dôvodom je, že ak sa naplní prvá podmienka, druhá sa už nebude testovať a nie je to ani potrebné. Druhá možnosť nenastane, ak sa prvá napní. Zvýši sa tak rýchlosť behu programu nepatrne ale čím viac takýchto častí programu bude, tým svižnejšie pobeží a pre MCU ako je ATmega je to dosť dôležité.
Pre úplnosť dodám, že aj keď prekladač by mal preložiť oba C kódy rovnako, druhý je čistejší lebo iba jedenkrát je priradenie enc_value=0. Technicky vzaté je to ten istý príkaz a zbytočne je tam dvakrát. Šetrenie FLASH pamäte je tiež dôležité pri MCU.
0

peterple
Ultimate člen
Ultimate člen
Príspevky: 2328
Dátum registrácie: 25 Jún 2013, 21:06
Bydlisko: Krajné
Vek: 57
Kontaktovať používateľa:

Re: Rotary encoder

Príspevok od používateľa peterple » 22 Júl 2022, 19:06

Dobre borci. Viete mi z fleku povedať ktorý z tých troch kódov bude optimálny:
  1. na minimálny počet slov programu?
  2. na minimálny počet vykonaných inštrukcií?
a ešte vysvetlite 62 ročnému pánovi čo sú tie dve paličky, abs a ako a prečo ten výraz prekladač vyhodnotí.
Ja osobne by som použil druhé budvarove riešenie, lebo je tam iba jedno priradenie. Ale myslím si že rozdiel medzi jednotlivými riešeniami bude pod 1µs (16 inštukcií)
0
Ukáž múdremu chybu a on sa ti poďakuje. Ukáž chybu hlupákovi a on sa urazí.

Používateľov profilový obrázok
balu
Pokročilý člen
Pokročilý člen
Príspevky: 540
Dátum registrácie: 21 Feb 2022, 12:06

Re: Rotary encoder

Príspevok od používateľa balu » 22 Júl 2022, 20:15

Vzhledem ke 100ms dlouhýmu delay je úplně jedno, co tam napíšete. Procesor bude 99,99999999% času plně vytížený tímto příkazem. Tahle zrůdnost do programů vůbec nepatří a pokud, tak maximálně na pár us. Vše ostatní je třeba řešit tak, aby procesor při čekání vykonával jiné čášti programu.
0

pocitujlasku
Ultimate člen
Ultimate člen
Príspevky: 6205
Dátum registrácie: 20 Júl 2007, 00:00
Vek: 41

Re: Rotary encoder

Príspevok od používateľa pocitujlasku » 22 Júl 2022, 22:09

abs je absolutna hodnota - cize bez znamienka,
tie 2 palicky je logicky vyraz OR (alebo), arduino berie aj or, ale takto sa to pouziva vo viacerych jazykoch.
napr. AND je &&
negacia !
0
Jedním z největších projevů nedůvěry v Boha je hromosvod na kostele.

Napísať odpoveď