I want to read PWM signals from an RC receiver. I have done this previously using pin change interupts on an UNO. This code doesn't appear to work with the Nano Every. The information isn't going to be output to a servo or ESC, instead the values of the PWM signals will be output to another device using a serial connection. Does anyone have code to do this that they can share?
What is the frequency of the PWM signal ?
Do you just want to extract the duty cycle ( 0 to 100%) at various sample periods ?
Post the code you currently have.
Usually around 50Hz ?
OK. I don't know what is usual here. For an Arduino PWM would generally be 490Hz/ 980Hz. 50Hz could easily be analysed by polling in the loop()
I guessed that was the clue.
The signals will have 50 Hz frequency.
I really don't care if the channel is reported as 0-100% or 1000 - 2000 microseconds.
[PWMread_RCfailsafe.ino|attachment](upload://j0c0N9nUPwGRa1pp8b5DqVaEF5o.ino) (24.6 KB)
[rc_read_example.ino|attachment](upload://9kT5IoealKd2X1H134qJtPIbAKb.ino) (1.3 KB)
Here is a solution using one of the Timer/Counter B0, which precludes using it for PWM generation on pin 6. The analogWrite function is used to generate a pulse train alternating 256µs high and 768µs low. You will need to eliminate the analogWrite and instead connect your external signal to pin 3. The Event System is used to route that waveform directly to the event input of TCB0. The counter counts at full system clock speed. The rising edge of the pulse starts the counter from zero. The falling edge saves the counter in CCMP and triggers an interrupt. The interrupt service routine copies the value in CCMP into a variable representing the pulse width which is then printed to the terminal. If the EDGE bit is set then the period of the negative pulse is measured.
void setup() {
Serial.begin(9600);
analogWrite(3, 64); // 256us high, 768us low
EVSYS.CHANNEL4 = EVSYS_GENERATOR_PORT1_PIN5_gc; // Route pin 3, PF5
EVSYS.USERTCB0 = EVSYS_CHANNEL_CHANNEL4_gc; // to TCB0
TCB0.CTRLA = 0; // Turn off channel for configuring
TCB0.CTRLB = 0x4; // pulse width mode
TCB0.EVCTRL = 0x41; // Enable input capture, positive pulse
// TCB0.EVCTRL = 0x51; // Enable input capture, negative pulse
TCB0.INTCTRL = 1; // Enable interrupt
TCB0.CTRLA = 1; // Enable and use system clock
}
volatile uint16_t width;
void loop() {
uint16_t tempVal;
delay(1000);
cli();
tempVal = width;
sei();
Serial.println((tempVal + 8) / 16); // Time in microseconds
}
ISR(TCB0_INT_vect) {
width = TCB0.CCMP; // reading CCMP clears interrupt flag
}
This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.