Perché il mio codice di interruzione non funziona?

Background

Sto cercando di scrivere del codice per leggere i segnali da un ricevitore RC a sei canali su un Arduino Mega 2560 . Attualmente sto mantenendo il codice per leggere solo un canale per semplificare la risoluzione dei problemi. Il problema è che la mia variabile condivisa non si aggiorna, il che mi porta a credere che il mio interrupt la routine di servizio non rileva alcun fronte di salita.

Pensavo che il mio ricevitore fosse guasto, quindi lho testato utilizzando la funzione di interruzione di collegamento Arduino standard . Ha funzionato perfettamente, quindi il mio ricevitore va bene.

Ho usato Serial.print () per vedere se la mia variabile di canale volatile si stava aggiornando (vale a dire, cambia il suo valore nel valore flag del canale 1). Non si stava aggiornando, quindi il mio ISR deve essere sbagliato. Puoi trovare il codice originale in il post del blog.

Cosa cè che non va? Sono a corto di idee.

 #include <PinChangeInt.h> //Pin assignment #define channel1PIN 10 //Bit flags #define Channel1FLAG 1 //Flag holder volatile uint8_t bFLAGUPDATESHARED; //Shared variables: Accessed by the interrupt service routine and read in "void loop". volatile uint16_t unCHANNEL1SHARED; //Start time variables: These are used to set the start time of the rising edge of //a pulse. They are only accessed by the ISR, and thus they are unsigned integers and //not volatiles. uint32_t ulCHANNEL1START; void setup() { Serial.begin(9600); Serial.print("RC Channel PWM Read Interrupt Test"); //PinChangInt library function. Used to set attach interrupts. PCintPort::attachInterrupt(channel1PIN, calcCHANNEL1, CHANGE); } void loop() { //In-loop variables to hold local copies of channel inputs. //This is static so it retains values between call loops. static uint16_t unCHANNEL1IN; //The in-loop copy of the bSHAREDFLAGUPDATE volatile flag holder static uint8_t bFLAGUPDATELOCAL; //Check to see if any channels have received signals. If so, copy //shared variables to local in loop variables. if (bFLAGUPDATESHARED) { //Switch off interrupts when I copy shared variables to local variables noInterrupts(); bFLAGUPDATELOCAL = bFLAGUPDATESHARED; if (bFLAGUPDATELOCAL & Channel1FLAG) { unCHANNEL1IN = unCHANNEL1SHARED; } bFLAGUPDATESHARED = 0; interrupts(); } Serial.println(unCHANNEL1IN); //Clear local update flags copy as all values have been copied to local variables bFLAGUPDATELOCAL = 0; } void calcCHANNEL1() { if (digitalRead(channel1PIN) == HIGH) { //If pin goes high, start timer and set ulCHANNEL1START to timer start ulCHANNEL1START = micros(); } else { //If it is not rising, it must be falling so set shared //variable to current time-start time unCHANNEL1SHARED = (uint16_t)(micros() - ulCHANNEL1START); //Tell that channel 1 has received a signal bFLAGUPDATESHARED |= Channel1FLAG; } }  

Commenti

  • Prova a semplificare il tuo codice. Fai accendere un led sullISR, ad esempio. Non ‘ non vedo nulla di intrinsecamente sbagliato.
  • Lho capito. Per qualche motivo, funziona solo sui pin 10,11 e 12. Non ‘ non so perché. PinchangeInt dovrebbe funzionare su qualsiasi pin digitale
  • Ma stai usando il pin 10? Comunque; contento che tu abbia funzionato.

Rispondi

Solo alcune su Atmega2560 supportano gli interrupt di cambio pin, in particolare le porte B, E (bit 0), J (bit Da 0 a 6) e K.

Guardando lo schema di riferimento significa che questi pin sulla scheda sono supportati:

 Chip Name Pin Pin on board ----------------------- Port B PB0 - 19 - D53 (SS) PB1 - 20 - D52 (SCK) PB2 - 21 - D51 (MOSI) PB3 - 22 - D50 (MISO) PB4 - 23 - D10 PB5 - 24 - D11 PB6 - 25 - D12 PB7 - 26 - D13 Port E PE0 - 2 - D0 (RXD0) Port J PJ0 - 63 - D15 (RXD3) PJ1 - 64 - D14 (TXD3) PJ2 to PJ6 - not connected on board Port K PK0 - PK7 - (89 - 82) - A8 - A15 

Quindi puoi vedere che da D10 a D12, che dici funzionano, sono in quella lista. Altri non lo sarebbero.


SoftwareSerial

Puoi vedere la conferma sulla pagina per SoftwareSerial dove dice:

Non tutti i pin su Mega e Mega 2560 supportano gli interrupt di modifica, quindi solo i seguenti possono essere usati per RX: 10, 11, 12, 13, 14, 15, 50, 51, 52, 53, A8 (62), A9 (63), A10 (64), A11 (65), A12 (66), A13 (67), A14 (68), A15 (69).

Questo perché SoftwareSerial utilizza interrupt di cambio pin per rilevare i dati seriali in arrivo, e quindi la dichiarazione di non responsabilità su quella pagina su quali pin funzionerà.


Pin-out Atmega2560

Pin-out Atmega2560


PinchangeInt dovrebbe funzionare su qualsiasi pin digitale

Notare che lAtmega328P (come usato in Uno) ha meno porte e tutte sono disponibili per interrupt di cambio pin su quella scheda.

Commenti

  • Questo ‘ non può essere corretto. La pagina collegata per prima dalle rivendicazioni OP per i pin 2, 3, 18, 19, 20 e 21 può essere utilizzata per gli interrupt. Questi vengono mappati a PE4, PE5, PD3, PD2, PD1 e PD0, secondo goo.gl/DvHEUA e goo.gl/xAwBGM Da parte mia, ‘ mi chiedo se PORTC possa essere utilizzato, come in ros_arduino_bridge: goo.gl/rq6yQO
  • La pagina collegata fa riferimento a interruzioni esterne , tuttavia lOP utilizza interruzioni cambio pin come puoi vedere da #include <PinChangeInt.h>. I pin di interruzione del cambio di pin sono quelli che ho elencato.
  • Vedo. Avevo la sensazione che potesse essere la distinzione, ma presumo che tutti i pin capaci di interruzioni esterne sarebbero anche in grado di cambiare pin, anche se non il contrario.

Risposta

Su ATmega1280 / 2560, solo le porte B, J, F e K hanno capacità di interruzione del cambio pin. Questi si mappano approssimativamente ai pin da 10 a 15, da 50 a 53 e da A6 ad A15 (sebbene parte della porta J non sia mappata sui pin Arduino, quindi da PCINT11 a PCINT15 non sono disponibili su Arduino Mega / Mega 2560).

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *