Bakgrunn
Jeg prøver å skrive kode for å lese signaler fra en seks-kanals RC-mottaker på en Arduino Mega 2560 . For tiden holder jeg koden for å bare lese en kanal for å gjøre det enkelt å feilsøke. Problemet er at den delte variabelen min ikke oppdateres, noe som får meg til å tro at avbruddet mitt servicerutinen oppdager ikke stigende kanter.
Jeg trodde at mottakeren min var ødelagt, så jeg testet den med standard Arduino attach interrupt-funksjon . Det fungerte perfekt, så mottakeren min er grei.
Jeg brukte Serial.print () for å se om den ustabile kanalvariabelen min oppdaterte seg. (det vil si endre verdien til flaggverdien kanal 1). Den oppdaterte ikke, så min ISR må være feil. Du kan finne den originale koden i blogginnlegget.
Hva er galt? Jeg er ute av ideer.
#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; } }
Kommentarer
- Prøv å forenkle koden din. Få ISR til å lyse opp en LED, for eksempel. Jeg ser ikke ' ikke noe som er feil.
- Jeg skjønte det. Av en eller annen grunn fungerer det bare på pinner 10,11 og 12. Jeg vet ikke ' hvorfor ikke. PinchangeInt burde fungere på en hvilken som helst digital pin
- Men du bruker pin 10? Uansett; glad for at du fikk den til å fungere.
Svar
Bare noen porter på Atmega2560 støtter pin-endringsavbrudd, spesielt porter B, E (bit 0), J (bits 0 til 6) og K.
Ser på referanseskjemaet som betyr at disse pinnene på brettet støttes:
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
Dermed du kan se at D10 til D12, som du sier fungerer, er i den listen. Andre tilfeldige ville ikke være.
SoftwareSerial
Du kan se bekreftelse på siden for SoftwareSerial der det står:
Ikke alle pinnene på Mega og Mega 2560-støtteendringen forstyrrer, så bare følgende kan brukes til 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).
Dette skyldes at SoftwareSerial bruker avbrudd med pin-endring for å oppdage innkommende serielle data, og dermed ansvarsfraskrivelsen på den siden om hvilke pinner den vil fungere med.
Atmega2560 pin-outs
PinchangeInt skal fungere på en hvilken som helst digital pin
Merk at Atmega328P (som brukt i Uno) har mindre porter, og alle er tilgjengelige for pin-endringsavbrudd på kortet.
Kommentarer
- Dette kan ' ikke være riktig. Siden som først er lenket av OP hevder pin 2, 3, 18, 19, 20 og 21 kan brukes til avbrudd. Disse kartlegges til PE4, PE5, PD3, PD2, PD1 og PD0, i henhold til goo.gl/DvHEUA og goo.gl/xAwBGM Jeg for min del ' er mer konserne med om PORTC kan brukes, som i ros_arduino_bridge: goo.gl/rq6yQO
- Den koblede siden refererer til eksterne avbrudd, men OP bruker pin-endring avbryter som du kan se fra
#include <PinChangeInt.h>
. Pinneskift-avbruddspinnene er de jeg har oppført. - Ser jeg. Jeg hadde en anelse som kan være skillet, men antok at alle pinner som er i stand til eksterne avbrudd, også vil være i stand til å bytte pinne, men ikke omvendt.
Svar
På ATmega1280 / 2560 er det bare porter B, J, F og K som har pin-endringsfunksjon. Disse kartlegges omtrent til pinne 10 til 15, 50 til 53 og A6 til og med A15 (selv om en del av port J ikke er kartlagt til Arduino-pinner, er derfor PCINT11 til PCINT15 ikke tilgjengelig på Arduino Mega / Mega 2560).