• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
program obsługi enkodera, lcd 4x20
#1
Smile 
Witam, napisałem kod do obsługi enkodera. Generalnie docelowo ma to być prymitywny wskaźnik wartości osi x,y,z,a cnc.
Założenie jest takie  ,że po starcie programu wyświetlić mi się mają zerowe położenia  każdej z osi.
Przyciskiem zdefiniowanym jako "int xyz" mam wybierać dla której osi enkoder będzie mi zmieniał wartość.
jedno naciśnięcie -oś x , drugie naciśnięcie przechodzi w oś y itd.  Po przejściu na inną oś poprzednia wartosć musi zostać zachowana dopóki jej nie wyzeruje (docelowo mają być jeszcze 4 przycicki do zerowania każdej z osi).

Niestety chociaż sam enkoder działa -a przynajmniej dobrze zlicza tylko w jedną stroną (w drugą się gubi)[Obrazek: smile.png]
to przechodzenie pomiędzy osiami zupełnie nie działa. na wszystkich osiach wyświetla mi siędokładnie to samo.
Być może nie tędy droga ( instrukcja switch /case )
Nie potrafię jeszcze dobrze programować więc zwracam się z prośbą do Was o pomoc jak to ma być żeby "grało" Smile
...oraz podpowiedź co jest nie tak ,że zliczanie enkodera działa jak działa.
Pozdrawiam.
Kod:
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

int encoderA = 2;
int encoderB = 3;
int encoder0PinALast = 0;
int pozycja_x = 0;
int pozycja_y = 0;
int pozycja_z = 0;
int pozycja_a = 0;
long int n = 0;
int xyz =4;
int zerowanie =5;
long int licznik =0;

void setup() {
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, INPUT_PULLUP);
 
   lcd.begin(20, 4);
   lcd.setCursor(0,0);
  lcd.print("os X :");
   lcd.setCursor(0,1);
   lcd.print("os Y :");
   lcd.setCursor(0,2);
   lcd.print("os Z :");
   lcd.setCursor(0,3);
   lcd.print("os A :");  
 }
int obsluga_enc (){
n = digitalRead(encoderA);
 if((encoder0PinALast == LOW) && (n == HIGH)) {
   if(digitalRead(encoderB) == LOW) {
     licznik--;
   }
   else {
     licznik++;
   }
 }
  encoder0PinALast = n;
 return licznik;
 }
 void loop (){
int n = digitalRead(xyz);
 for ( n =0 ; n<4 ; n++){
   switch (n)
   {
   case 0:
       lcd.setCursor(7,0);
  lcd.print(pozycja_x+(obsluga_enc ()));
         break;
  case 1:
      lcd.setCursor(7,1);
  lcd.print(pozycja_y+(obsluga_enc ()));
         break;
  case 2:
      lcd.setCursor(7,2);
  lcd.print(pozycja_z+(obsluga_enc ()));

    break;
  case 3:
      lcd.setCursor(7,3);
  lcd.print(pozycja_y+(obsluga_enc ()));
    break;
   }
 
 }
 
}
 
Odpowiedź
#2
Witam,
W funkcji do obsługi encodera zmieniasz wartość zmiennej globalnej licznik.
Pozdrawiam.
 
Odpowiedź
#3
Można jaśniej, na co to wpływa..? gdziekolwiek nie dam tej zmiennej to efekt mam taki sam.
 
Odpowiedź
#4
Witam,
Zmienne: pozycja_x, pozycja_y. .. mają cały czas wartość 0. W funkcji zmieniasz wartość zmiennej licznik i tę wartość zwraca funkcja. A wyswietlasz dla każdej osi ich sumę. Czyli 0 Plus wartość zmiennej licznik jest identyczna dla każdej osi.
Pozdrawiam.
 
Odpowiedź
#5
no tak racja Smile
Jakieś sugestje do tego jak napisać część programu która będzie mi ustawiac kursor np w pozycji oś x (7,0) i w tej lini wartość zczytana z enkodera będzie wpisywana, a pozostałe linie będą zachowywały wcześniej wpisaną wartość?
Mam totalną pustkę w głowie ;/
 
Odpowiedź
#6
Witam,
Moim zdaniem błędem jest umieszczenie pętli for wewnątrz kooperacji (przynajmniej w takiej formie w jakiej jest). Poza tym funkcję obsługi encodera wywolywalbym z parametrem mówiący dla jakiej osi funkcja jest wywolywana i nie tylko...
No i najważniejsze:
pozycja_x += obsluga_enc ();
lcd.print (pozycja_x);
Pozdrawiam,
Tomek.
 
Odpowiedź
#7
Popatrzmy na kod...
int n = digitalRead(xyz);
W tej linii zmienna n przybiera wartość 0 lub 1, w zależności od stanu pinu "xyz".

for ( n =0 ; n<4 ; n++)
W tej zaś linii, zmienna n przybiera wartość 0 i dla tej wartości wykonywany jest kod:
lcd.setCursor(7,0);
lcd.print(pozycja_x+(obsluga_enc ()));
break;
Teraz następuje inkrementacja (n++), n przybiera wartość 1 i wykonywana jest instrukcja dla case 1

i tak dalej, aż warunek n<4 stanie się fałszem.
Jesteśmy w funkcji loop() więc znowu int n = digitalRead(xyz);

Dla każdego n jeszcze wyskakujesz do obsługi enkodera, ale to i tak nie ma znaczenia na tym etapie.

Mógłbyś napisać coś w tym stylu:

Deklaracje zmiennych globalnych
int iOs=0; //oś którą chcesz sterować
int axis=0// zmienna pomocnicza

W funkcji loop

int n = digitalRead(xyz);
if (n==LOW) {
iOs=wyborOsi(); //wykonujemy funkcję wyborOsi()
};
//tutaj możesz sobie dać tą swoją funkcję switch ... case
switch(iOs)
{
case 0:
lcd.setCursor(7,0);
lcd.print(pozycja_x+(obsluga_enc ()));
break;
..................itd.itd...............


I napisać funkcję wyboru osi.
Coś w tym stylu:

int wyborOsi() {
// wartość początkowa zmiennej axis przechowującej numer osi wynosi 0, co oznacza że mamy wybraną oś X

if (axis==0) axis=1;
else if (axis==1) axis=2;
else axis=3;
return axis;
}



A dla czego enkoder nie działa prawidłowo?
Wykorzystaj gotową bibliotekę do jego obsługi, albo dodaj jakąś pauzę aby wyeliminować drgania styków, albo obsługuj go w przerwaniu.
Zresztą w przerwaniu było by najpewniej, ale musisz enkoder podpiąć pod piny z przerwaniem int0 oraz int1.
Jeśli masz problem z kodem lub sprzętem, zadaj pytanie na forum. Nie odpowiadam na PW, jeśli nie dotyczą one spraw forum lub innych tematów prywatnych.

[Obrazek: SsIndaG.jpg]
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości