Pages: [1]   Go Down
Author Topic: LØST rotary encoder og trykknap  (Read 3978 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 2
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hej

Jeg prøver at få en rotary encoder til at virke som "bank selector" for en gruppe trykknapper. Encoder delen virker, jeg får et brugbart tal ud "number".
Jeg vil så indsætte "number" i forskellige if statements (for trykknap) som så bestemmer handlingen for trykknappen.
Men det virker bare ikke.
Er der nogen der kan se hvor det går galt???????
(har selv en formodning om det er "number" der ikke bliver "husket"...)

Vh
LYDFANGER

Code:
volatile int number = 0;          //encoder      

int oldnumber = number;

volatile boolean halfleft = false;    
volatile boolean halfright = false;

int kon=8;          //Kontakt
int currState1;
int prevState1;

void setup(){
  Serial.begin(9600);
  pinMode(2, INPUT);
  digitalWrite(2, HIGH);                
  pinMode(3, INPUT);
  digitalWrite(3, HIGH);                
  attachInterrupt(0, isr_2, FALLING);  
  attachInterrupt(1, isr_3, FALLING);

  pinMode(kon, INPUT);
  digitalWrite(kon, HIGH);



}

void loop(){                    //encoder "koder"
  if(number != oldnumber){              
    Serial.println(number);            
    oldnumber = number;       //denne værdi jeg gerne vil bruge
  }
}

void isr_2(){                                              
  delay(1);                                                
  if(digitalRead(2) == LOW){                              
    if(digitalRead(3) == HIGH && halfright == false){    
      halfright = true;                                    
    }  
    if(digitalRead(3) == LOW && halfleft == true){        
      halfleft = false;                                    
      number--;                                            
    }
  }
}
void isr_3(){                                            
  delay(1);                                              
  if(digitalRead(3) == LOW){                              
    if(digitalRead(2) == HIGH && halfleft == false){      
      halfleft = true;                                    
    }                                                    
    if(digitalRead(2) == LOW && halfright == true){      
      halfright = false;                                  
      number++;
    }
  }

  {
    currState1 = digitalRead(kon);

    if(currState1 !=prevState1)               //tryk på knap "koder"
    {
      if(currState1 == LOW && number == 3)
      {
        Serial.println("UDSAGN 1");
      }
    }
    prevState1 = currState1;




    if(currState1 !=prevState1)    
    {
      if(currState1 == LOW && number == 4)
      {
        Serial.println("UDSAGN 2");
      }
    }
    prevState1 = currState1;

  }
}

« Last Edit: November 30, 2012, 06:09:31 pm by lydfanger » Logged

Copenhagen, Denmark
Offline Offline
Edison Member
*
Karma: 33
Posts: 1225
Have you testrun your INO file today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hvad får du på Serial-monitor? Som jeg læser koden så skulle den sprøjte "number" hvert øjeblik den ikke er det samme som oldnumber. Passer det? Hvis ikke så er din logic med at se om encoderen drejer højre eller venstre om forkert (jeg har ikke helt gjort mig umagen at genemskue den)

Er den her encoder noget der skifter ofte/hurtigt? Interrupts bør holdes til ting som går sk.. hurtigt. Du begår to "fejl" (der gør koden usikker og random under visse betingelser) Når man læser en variable (andet end enkel bytes) som bliver modificeret i en ISR bør man disable interrupts i det tidsrum. En ISR skal være færdig hurtig, man skal ikke putte delay i dem. En ISR blokkerer andre ISR (lang liste af priotitet snillersnaller udeladt) Sidste men ikke mindst (ja, en 3. ting) laver du Serial.print in din ISR. Det går godt (ikke den gamle IDE022) fordi Serial kun putter din streng i en buffer og så er det lutter interrupts der putter den ud på linjen, men det er også en skidt ting at gøre.

Eller er det nogen som en person drejer? Så skulle der være rigelig tid at læse encoderen i loop med lidt polling (så længe du holder dig fra delay af enhver art og kun bruger timers)

Nåh - til Du skriver at "den virker" - du får et number. Men "number" bliver jo løbende ændret - en af de ting ISR'en gør for dig. Da du ikke udskriver oldnumber ved vi ikke hvad det er den modtager.
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hej

Monitoren viser 1 ved første step på rotary'en, 2 ved næste step, osv. osv. virker i begge retninger. Den har på intet tidspunkt været ustabil. (det er en "potmeter type")
Første gang jeg vælger step 3 (number == 3) og trykker på trykknapen skriver monitoren "udsagn 1" som jeg gerne vil have. Går jeg videre op i step'ene og trykke på knappen sker der ikke noget, med andre ord virker  if(currState1 == LOW && number == 3) kun den ene gang og if(currState1 == LOW && number == 4) kommer aldrig til at virke.
Monitoren viser stadig nye værdier når jeg drejer på rotary'en.



Logged

Copenhagen, Denmark
Offline Offline
Edison Member
*
Karma: 33
Posts: 1225
Have you testrun your INO file today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Aha - ja - så forstår jeg hvad du melder som "Men det virker bare ikke".

Fejlen er 
Code:
   prevState1 = currState1;
if (currState1 !=prevState1)
du kan se at du sætter de to variabler til samme indhold og så vil du kun komme ind og teste for nummer==4 hvis de ikke er det samme.

Kommer aldrig at ske. smiley
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hej igen

Nu virker det.
Mit projekt har 8 trukknapper(currState 1-8) og en "variations vælger--rotary encoder" ,som skal virker for alle 8 knapper,(number x)

Hvis jeg har forstået det rigtigt, skal jeg først sætte
Code:
prevState1 = currState1;
når alle
Code:
if(currState1 == LOW && number == x)
er læst.

Logged

Copenhagen, Denmark
Offline Offline
Edison Member
*
Karma: 33
Posts: 1225
Have you testrun your INO file today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Jo.

Men der er mange andre måder at kode det du gør på, men virker det, så virker det.

Jeg har nævnt at interrupts er "overkill" for opgaven (men hvis man vil lave noget med interrupts som et mål i sig selv er det jo en OK måde at prøve det). Din kode for at fange numret vil jeg gøre med en switch..case. Testen for currState1 !=prevState1 behøvs kun gøres en gang. Kort skitseret (ikke hele koden - kun ide grundlag)
Code:
if (currState1 !=prevState1)
   switch (number) {
     case 3 : Serial.print("Tre"); break;
     case 4 : Serial.print("Fire"); break;
     case 7: Serial.print("Syv"); break;
     default:
    }
prevState1=currState1 ;
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hej igen

tak for din ide. Det fungerer godt.
dog har jeg et lille problem. Efter skiftet til Switch Case skriver Serial.println flere gange, uvilkårligt.
Jeg SKAL kun have Serial.println til at skrive 1 gang,(for hvert tryk på knap) fordi den skal aktivere en fil på computer via Gobetwino. Hvis Serial.println skriver mere end en gang, starter Gobetwino'en filen flere gange.
I sketch'en er "rotary-emneskift-delen" udskiftet med  "trykknap op/ned-emneskift-del".

Code:
const int  KonUP = 13;           //up & down//
const int KonDO = 12;

int buttonPushCounter = 0;   
int buttonState = 0;
int buttonState2 = 0;
int lastButtonState = 0;     
int lastButtonState2 = 0;

const int kon1 = 2;       //knapper//
const int kon2 = 3;


int currState1;
int prevState1;
int currState2;
int prevState2;







void setup() {

  pinMode(KonUP, INPUT);       // Up & down//
  digitalWrite(KonUP, HIGH);
  pinMode(KonDO, INPUT);
  digitalWrite(KonDO, HIGH);

  pinMode(kon1, INPUT);        // knapper//
  digitalWrite(kon1, HIGH);
  pinMode(kon2, INPUT);
  digitalWrite(kon2, HIGH);


  Serial.begin(9600);
}


void loop()

{



  buttonState = digitalRead(KonUP);


  if (buttonState != lastButtonState) {

    if (buttonState == LOW) {

      buttonPushCounter++;

      Serial.print("emne:  ");
      Serial.println(buttonPushCounter);

    }
  }

  lastButtonState = buttonState;

  {

    buttonState2 = digitalRead(KonDO);


    if (buttonState2 != lastButtonState2) {

      if (buttonState2 == LOW) {

        buttonPushCounter--;

        Serial.print("emne:  ");
        Serial.println(buttonPushCounter);

      }
    }

    lastButtonState2 = buttonState2;

  }

  //kontakter koder//


  {
    currState1 = digitalRead(kon1);
    currState2 = digitalRead(kon2);
 



    if (currState1 !=prevState1)            //trykknap 1//
      switch (buttonPushCounter) {
      case 1 :
        Serial.println("1");
        break;
      case 2 :
        Serial.println("11");
        break;
      case 3:
        Serial.println("21");
        break;
      }
    prevState1=currState1 ;
  }

  if (currState2 !=prevState2)            //trykknap 2//
    switch (buttonPushCounter) {
    case 1 :
      Serial.println("2");
      break;
    case 2 :
      Serial.println("12");
      break;
    case 3:
      Serial.println("22");
      break;
    }
  prevState2=currState2 ;
}
Logged

Copenhagen, Denmark
Offline Offline
Edison Member
*
Karma: 33
Posts: 1225
Have you testrun your INO file today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hvor mange gange, eller hvordan bliver det til flere? Hvis ud ikke har gjort noget særligt i dit kredsløb så får du "Contact bounce" og de skal tages højde for. Der er mange eksempler på forum og i tutorials. Du må ikke bruge delay() men brug noget med timers der undtrykker at man læser kontakten i nogle millisekunder efter en tilstandsændring er set. Hvis du ikke vil gøre det i software må du lave et RC-kredsløb. Da det er menneske fingre der trykker gør det ike noget at RC-kredsen vil forsinke knaptrykket med nogle millisekunder. Dit valg: Software/Hardware Contact Debounce.
Logged

Offline Offline
Newbie
*
Karma: 2
Posts: 38
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hej

Ja....det var kontakt-debounce, så problemet er løst.
endnu engang yak for hjælpen.

LYDFANGER
Logged

Copenhagen, Denmark
Offline Offline
Edison Member
*
Karma: 33
Posts: 1225
Have you testrun your INO file today?
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Tak for tilbagemeldningen. Der er for mange på forumet der glemmer det. For ekstra bonus kan man endda rette sin subject linje og tilføje "Løst" eller noget i den stil. (den ny subject linje bliver gældende for nye posts, men ses i sin nye form på oversigten)
Logged

Pages: [1]   Go Up
Jump to: