Spektrum AR610 Receiver |
See the closeup of the receiver to the right. The channels mappings by default in the first setup are:
Channel 0 - THRO
Channel 1 - AILE
Channel 2 - ELEV
Channel 3 - RUDD
Channel 4 - GEAR
Channel 5 - AUX1
Spektrum Receiver Output |
At the end of my previous post Raspberry Pi Based Java Hex Robot: PiHexJ Radio Control Intro - The Control Event I has some open questions regarding the processing of the receiver signals by the AVR microprocessor. I outlined my design for multiplexing the signals to take advantage of the AVR microprocessors input capture feature for PWM decoding. I had concerns about how this would operate.
Multiplexing the PWM signals from the AR610 Spektrum Receiver
The test bed is shown in the picture below. I am using a 74HC4051 8 Channel Multiplexer to multiplex the Spektrum AR610 6 channel receiver. The questions to address are will there be issues with overlapping signals causing incorrect results on switching and what will the latency be.
Test Setup for RC Receiver Multiplexing |
74HC4051 Pin Description |
74HC4051 Function Table |
AVR Mega 328 pin diagram |
My Pin mappings are:
AVR | Multiplexer |
PD0 | S0 |
PD1 | S1 |
PD2 | S2 |
PD3 | E |
PB0 | Z |
And PD4 is used to connect to the raspberry pi to signal when the control input has changed.
For the AVR firmware C code check out my github the file is in the hexfirmware repository https://github.com/margic/hexfirmware/blob/master/Firmware/firmware.c rather than the main PiHexJ repository. The AVR is initialized with the input capture interrupt enabled. The following code is triggered when the ICR interrupt is fired. It grabs the value from the timer register and stores it in an array channels[]. The index, plex, is then updated. The value is compared and if changed the update count is updated. I do this so I don't trigger updates to the raspberry pi if no input changed have occurred. PORTD pin PIEVENT is turned on to signal the pi to read the channels via I2C as per my design. PIEVENT corresponds to pin PD4.
Finally the multiplexer is stepped to the next input.
ISR(TIMER1_CAPT_vect){ // Input capture interrupt handler // first time is triggered in leading edge if(PINB & (0x01)){ // pin high // clear counter and set to trailing edge TCNT1 = 0; TCCR1B &= ~(1<<ICES1); }else{ // get counter from ICR1 // reset to look for leading edge uint_fast16_t counter = ICR1 + 47; // add some counts for processor over head // if(channels[plex] != counter){ updatedCount += 1; } channels[plex] = counter; if(plex == NUMCHANNELS - 1){ if(updatedCount != 0){ PORTD |= (1 << PIEVENT); } updatedCount = 0; plex = 0; }else{ plex += 1; } switchMultiplex(); TCCR1B |= (1<<ICES1); } } void switchMultiplex(){ uint8_t temp = PORTD & 0xF0; PORTD = temp | plex; }
The code works as intended. The following diagram shows the output on channel 6 of the logic analyzer.
Multiplexed Signal at AVR ICR Pin Channel 6 |
Optimized Receiver Channels |
Failed Multiplexing Channel 6 |
The output of all 6 channels are being sent to the AVR and measured. Shown on channel 6 above. The total time is 31.7ms. While not as quick as the optimal, it does work and it is still faster than over 50ms. This will be the layout I used for the initial RC control of the robot.
Conclusion
There will be additional latency as the Raspberry Pi will read the values from the AVR controller to determine the values the receiver is receiving from the radio. In other applications this would not be acceptable. However in this application a estimated 50ms latency before the robot responds should negligible. This can be revisited if it proves to be a problem.
Next Steps
The next tasks are to make the Raspberry Pi respond to the AVR signal (PD4 going high) and have it request the values via I2C. I am currently developing the simulator file that will test the AVR code. I will publish it when complete.