Arduino Interupt on Port/pin Change

algemene C code
Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Arduino Interupt on Port/pin Change

Berichtdoor astrofrostbyte » 23 Feb 2013, 12:16

Ik wil gebruik maken van de mogenlijkheid van de 'pin change interupt'.
Dit is niet de zelfde interupt die je gebruikt met attachInterrupt(), de Uno heeft maar 2 interupt pootje.

Ik wil een pin change interupt op 4 pinnen op portC. dit schijnt te kunnen, echter 'lijkt'het heel omslachtig/moeilijk
Iemand hier ervaring mee ? of wat code voorbeeldjes ??

Doel:
Ik heb twee rotary encoders op Pinnen C0,C1 en C2,C3 van PortC.
Deze draaien soms heel snel en asynchroon van elkaar.
Om deze met zo min mogelijk software overhead af te handelen gebruik ik een grote 'state change jumptabel'
Deze tabel bevat alle mogelijke veranderingen aan de vier pinnen en wat er dan moet gebeuren.

Pseudo Code
    1- Interupt treed op omdat 1 of meer van de vier pinnen(twee rotary encoders) veranderd is
    2- We springen automatisch naar de interupt routine <- Deze sprong moet ik nog uitvogelen/coderen
    3- we berekenen een positie in een array aan de hand van huidige en vorige 4 pinnen status
    4- we halen met deze bepaalde sprong een code uit het array bv 'dd' decrement|decrement
    Dit wil dus zeggen dat beide rotary encoders naar links zijn gedraait
    5- met deze code 'dd' springen we in een case naar de uit te voeren acties ch0-- en ch1--
    6 klaar.
Bij elkaar zo'n 10tal instructies om de rotary encoder event bij te houden.

Code: Alles selecteren

//-------------------------------------------------------------
// All possible action, first char is Ch0, second char is ch1
// n=nothing, d=Decrement, i=Increment, e=Error
#define nn 0
#define nd 1
#define ni 2
#define ne 3
#define dn 4
#define dd 5
#define di 6
#define de 7
#define in 8
#define id 9
#define ii 10
#define ie 11
#define en 12
#define ed 13
#define ei 14
#define ee 15
//-------------------------------------------------------------
byte statechange[] = { // jumptable with all 256 possible statechanges
    nn,nd,ni,ne, dn,dd,di,de, in,id,ii,ie ,en,ed,ei,ee ,
    ni,nn,ne,nd, di,dn,de,dd, ii,in,ie,id ,ei,en,ee,ed ,
    nd,ne,nn,ni, dd,de,dn,di, id,ie,in,ii ,ed,ee,en,ei ,
    ne,ni,nd,nn, de,di,dd,dn, ie,ii,id,in ,ee,ei,ed,en ,
    //--
    // ...  all possible , ommited for code clarity
    //--
  };
//-------------------------------------------------------------
byte state, newstate, oldstate;
volatile int  Err, Ch0, Ch1;
//-------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  DDRC = B00000000;         // set PortC pins as inputs
  // rotary encoder Ch0 on PortC, C0 (pin23), C1 (pin24)
  // rotary encoder Ch1 on PortC, C2 (pin25), C3 (pin26)
 
}
//-------------------------------------------------------------
// 'pin change interrupt' on 4 PortC C0..C3 pins (2 rotary encoders)
void StateChange()
{ state    =  PINC<<4 & 0xF0;          // read portC
  state   |= (oldstate);
  oldstate = state>>4 & 0x0F;
  // state contains : newstate in upper nibble, oldstate in low nibble.
  switch ( statechange[state] ) //[ch0][ch1]
  { case nn:                 break;
    case nd:        Ch1--;   break;
    case ni:        Ch1++;   break;
    case ne:        Err++;   break;
    case dn: Ch0--;          break;
    case dd: Ch0--; Ch1--;   break;
    case di: Ch0--; Ch1++;   break;
    case de: Ch0--; Err++;   break;
    case in: Ch0++;          break;
    case id: Ch0++; Ch1--;   break;
    case ii: Ch0++; Ch1++;   break;
    case ie: Ch0++; Err++;   break;
    case en: Err++;          break;
    case ed: Err++; Ch1--;   break;
    case ei: Err++; Ch1++;   break;
    case ee: Err++; Err++;   break;
  }//switch
}//StateChange

//-------------------------------------------------------------
void loop() {
 Serial.print("\r");
 Serial.print(Ch0); Serial.print(" ");
 Serial.print(Ch1); Serial.print(" ");
 Serial.print(Err);
 delay(100);
}
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Advertisement

Berichten: 27
Geregistreerd: 23 Feb 2013, 12:07

Re: Arduino Interupt on Port/pin Change

Berichtdoor walker » 23 Feb 2013, 13:10

Zelf heb ik daar ook nog geen ervaring mee, maar misschien kun je hier iets mee:
http://playground.arduino.cc/Main/PcInt

Gebruikers-avatar
Berichten: 229
Geregistreerd: 20 Jan 2013, 12:01

Re: Arduino Interupt on Port/pin Change

Berichtdoor astrofrostbyte » 25 Feb 2013, 12:02

Thank's zit dat net een beetje door te pluizen.. ff doorbijten .. moet wel lukken denk ik. Heb de datasheet van de ATmega328 ook open staan voor al die register bitjes.

update:
De Pcint library is bijna onleesbaar , vind ik altijd wat lastig om te gebruiken als je geen idee hebt wat het beesie doet.
De onderliggende basis is eigenlijk vrij simpel:
Code: Alles selecteren
void setup() {
  Serial.begin(115200);
  DDRC = B00000000;         // set PortC pins as inputs
  // rotary encoder Ch0 on PortC, C0 (pin23), C1 (pin24)
  // rotary encoder Ch1 on PortC, C2 (pin25), C3 (pin26)
  PCICR |= _BV(PCIE1);  //Enable PCINT //PinChangeIntControlReg
  PCMSK1 = B00001111;  // PinChangeMaskReg
}
//-------------------------------------------------------------
// 'pin change interrupt' on 4 PortC C0..C3 pins (2 rotary encoders)
//void StateChange()
ISR(PCINT1_vect)
{ state    =  PINC<<4 & 0xF0;          // read portC
  state   |= (oldstate);
  //  ...  knip ...


Een goede referentie gevonden : http://arduino.cc/forum/index.php/topic,141363.0.html

Kortom de Arduino heeft Veeeel meer interupts dan standaard aangeboden wordt door de omgeving.
Gear: Arduino- Uno,Due,Ethernet,Mega2560 , OLS LogicAnalyser, TDS1002, Rigol DG1022, J-Link EDU, BusPirate

Berichten: 85
Geregistreerd: 10 Jan 2013, 14:51
Woonplaats: Waddinxveen

Re: Arduino Interupt on Port/pin Change

Berichtdoor Karel » 25 Feb 2013, 13:26

Daar was ik precies naar op zoek. Voor mijn brandstofmeterproject heb ik al twee interrupts nodig voor de volumetellers van de aanvoer en retourleidingen. En dan wil ik daar sinds gisteren nog een rotaryswitch aan toevoegen voor het doorlopen van een menuutje met opties voor nulstellen van div. tussenstanden. Dan moeten in de tussentijd de pulstellers wel doorgaan met tellen natuurlijk. Dit berichtje komt dus precies op tijd.

Dank je wel!

Karel
If you think education is expensive, try ignorance! (Derek Bok)

Terug naar C code

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 6 gasten