Fundal
Încerc să scriu cod pentru a citi semnale de la un receptor RC cu șase canale pe un Arduino Mega 2560 . În prezent păstrez codul pentru a citi doar un canal pentru a face lucrurile mai ușor de depanat. Problema este că variabila mea partajată nu se actualizează, ceea ce mă face să cred că întreruperea mea rutina de service nu detectează margini ascendente.
Am crezut că receptorul meu este rupt, așa că l-am testat folosind funcția standard de întrerupere atașare Arduino . A funcționat perfect, deci receptorul meu este în regulă.
Am folosit Serial.print () pentru a vedea dacă variabila mea de canal volatil se actualiza (adică schimbați valoarea acestuia la valoarea semnalului canalului 1). Nu se actualiza, așa că ISR trebuie să fie greșit. Puteți găsi codul original în postarea de pe blog.
Ce nu este? Nu mai am idei.
#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; } }
Comentarii
- Încercați să vă simplificați codul. Solicitați ISR să aprindă un led, de exemplu. Nu ‘ nu văd nimic inerent greșit.
- Mi-am dat seama. Din anumite motive, funcționează doar pe pinii 10,11 și 12. Nu ‘ totuși știu de ce. PinchangeInt ar trebui să funcționeze pe orice pin digital
- Dar folosiți pinul 10? Oricum; mă bucur că ați funcționat.
Răspundeți
Doar unele porturi de pe Atmega2560 acceptă întreruperi de modificare a pinilor, în special porturile B, E (bit 0), J (biți 0 la 6) și K.
Privind schema de referință care înseamnă că acești pini de pe placă sunt acceptați:
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
Astfel puteți vedea că D10 până la D12, despre care spuneți că funcționează, se află în lista respectivă. Alte aleatoare nu ar fi.
SoftwareSerial
Puteți vedea confirmarea pe pagina pentru SoftwareSerial unde scrie:
Nu toți pinii de pe Mega și Mega 2560 acceptă schimbarea modificărilor, deci numai următoarele pot fi utilizate pentru 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).
Acest lucru se datorează faptului că SoftwareSerial folosește întreruperi de modificare a pinului pentru a detecta datele seriale primite și, astfel, responsabilitatea de pe acea pagină cu care pini va funcționa.
Pin-outs Atmega2560
PinchangeInt ar trebui să funcționeze pe orice pin digital
Rețineți că Atmega328P (așa cum este utilizat în Uno) are mai puține porturi și toate sunt disponibile pentru întreruperi de modificare a pinului pe acea placă.
Comentarii
- Acest lucru nu poate ‘ să fie corect. Prima pagină legată de OP revendică pinii 2, 3, 18, 19, 20 și 21 poate fi utilizată pentru întreruperi. Acestea se conectează la PE4, PE5, PD3, PD2, PD1 și PD0, conform goo.gl/DvHEUA și goo.gl/xAwBGM La rândul meu, ‘ mă preocupă mai mult dacă PORTC poate fi utilizat, ca în ros_arduino_bridge: goo.gl/rq6yQO
- Pagina conectată se referă la întreruperi externe , însă OP utilizează schimbare pin întrerupe ca puteți vedea din
#include <PinChangeInt.h>
. Pinii de întrerupere pentru schimbarea pinului sunt cei pe care i-am enumerat. - Înțeleg. Am avut o idee care ar putea fi distincția, dar am presupus că toți pinii capabili de întreruperi externe ar putea fi, de asemenea, capabili de schimbare a pinilor, deși nu invers.
Pe ATmega1280 / 2560, numai porturile B, J, F și K au capacitatea de întrerupere a schimbării pinului. Acestea se mapează aproximativ la pinii 10-15, 50-53 și A6 până la A15 (deși o parte a portului J nu este mapată la pinii Arduino, prin urmare PCINT11 până la PCINT15 nu sunt disponibile pe Arduino Mega / Mega 2560).