Achtergrond
Ik “probeer code te schrijven om signalen van een zeskanaals RC-ontvanger op een Arduino Mega 2560 . Momenteel bewaar ik de code om slechts één kanaal te lezen om problemen gemakkelijk op te lossen. Het probleem is dat mijn gedeelde variabele niet wordt bijgewerkt, waardoor ik denk dat mijn interrupt serviceroutine detecteert geen stijgende flanken.
Ik dacht dat mijn ontvanger kapot was, dus ik heb hem getest met de standaard Arduino attach-interruptfunctie . Het werkte perfect, dus mijn ontvanger is in orde.
Ik gebruikte Serial.print () om te zien of mijn vluchtige kanaalvariabele aan het updaten was (dat wil zeggen, verander de waarde ervan in de vlagwaarde van kanaal 1). Het werd niet bijgewerkt, dus mijn ISR moet onjuist zijn. Je kunt de originele code vinden in de blogpost.
Wat is er mis? Ik heb geen ideeën meer.
#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; } }
Reacties
- Probeer je code te vereenvoudigen. Laat de ISR bijvoorbeeld een led oplichten. Ik zie ‘ niets inherent verkeerd.
- Ik heb het uitgezocht. Om de een of andere reden werkt het alleen op pinnen 10, 11 en 12. Ik weet niet ‘ waarom. PinchangeInt zou op elke digitale pin moeten werken
- Maar je gebruikt pin 10? Hoe dan ook, blij dat het werkt.
Antwoord
Alleen sommige poorten op de Atmega2560 ondersteunen pin-change interrupts, met name poorten B, E (bit 0), J (bits 0 tot 6) en K.
Als we naar het referentieschema kijken, betekent dit dat deze pinnen op het bord worden ondersteund:
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
Dus je kunt zien dat D10 tot D12, waarvan je zegt dat ze werken, in die lijst staan. Andere willekeurige zouden dat niet zijn.
SoftwareSerial
U kunt de bevestiging zien op de pagina voor SoftwareSerial waar staat:
Niet alle pinnen op de Mega en Mega 2560 ondersteunen interrupts voor wijzigingen, dus alleen het volgende kan worden gebruikt voor 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).
Dit komt omdat SoftwareSerial pin-change interrupts gebruikt om inkomende seriële data te detecteren, en dus de disclaimer op die pagina over met welke pinnen het zal werken.
Atmega2560 pin-outs
PinchangeInt zou op elke digitale pin moeten werken
Merk op dat de Atmega328P (zoals gebruikt in de Uno) minder poorten heeft, en ze zijn allemaal beschikbaar voor pin-change interrupts op dat board.
Reacties
- Dit kan ‘ niet kloppen. De pagina die voor het eerst is gelinkt door OP-claims pinnen 2, 3, 18, 19, 20 en 21 kunnen worden gebruikt voor interrupts. Deze verwijzen naar PE4, PE5, PD3, PD2, PD1 en PD0, volgens goo.gl/DvHEUA en goo.gl/xAwBGM Wat mij betreft, ik ‘ heb me meer zorgen gemaakt of PORTC kan worden gebruikt, zoals in ros_arduino_bridge: goo.gl/rq6yQO
- De gelinkte pagina verwijst naar externe interrupts, maar het OP gebruikt pin change interrupts als je kunt zien vanaf
#include <PinChangeInt.h>
. De onderbrekingspinnen voor het wijzigen van de pincode zijn degene die ik heb vermeld. - Ik begrijp het. Ik had een vermoeden dat dit het onderscheid zou kunnen zijn, maar ging ervan uit dat alle pinnen die geschikt zijn voor externe interrupts, ook in staat zouden zijn om pinnen te vervangen, maar niet andersom.
Antwoord
Op de ATmega1280 / 2560 hebben alleen poorten B, J, F en K de mogelijkheid om de pinnen te onderbreken. Deze komen ongeveer overeen met pinnen 10 t / m 15, 50 t / m 53 en A6 t / m A15 (hoewel een deel van poort J niet is toegewezen aan Arduino-pinnen, zijn PCINT11 t / m PCINT15 daarom niet beschikbaar op de Arduino Mega / Mega 2560).