UNSOLVED: Servo Signal Passthrough

In my electronics project, need to read the current servo value from a Spektrum AR8360T RC Receiver, on at least 2 channels, using my pico.

I would also like to be able to pass through this signal directly to other pins connected to the servos themselves.

Currently on my PCB (already printed) I have the receiver inputs and the servo outputs on seperate digital pins on my Pico WH. From some testing on a nano, I have gotten rough values of analog pins, however it hasn’t been very accurate. If I need to i can pass through the signals from the analog to the digital pins with a jumper wire. I would also consider an analog to the digital logic converter, however I don’t know how much this would help.

If all else fails, would it damage the board to connect the receiver directly to the pins (and the subsequent trace) as it is operating PWM at 5v

This program would also need to run in conjunction with rapidly updating and transmitting sensor values.

I have tested with a simple read value and write the same value on a while true, and somehow it only works for one of the servos. I tested for a possible pico issue, but it can write fine when you put in your own values into servo write.

1 Like

Code I have tested with, this code works with both servos sometimes but mainly only works with one (of the servos) somehow.

from machine import Pin
import time
import utime
from servo import Servo




# Set up LEDs
led_pins = [Pin(16, Pin.OUT), Pin(17, Pin.OUT), Pin(18, Pin.OUT), Pin(19, Pin.OUT), Pin(20, Pin.OUT)]
led_colors = ['Yellow', 'White', 'Green', 'Blue', 'Red']

# Function to blink all LEDs (pins 16-20) at startup
def blink_all_leds():
    # Turn all LEDs on
    for led in led_pins:
        led.on()  # Turn on each LED
    utime.sleep(1)  # Keep them on for 1 second

    # Turn all LEDs off
    for led in led_pins:
        led.off()  # Turn off each LED
    utime.sleep(1)  # Keep them off for 1 second

    # Turn all LEDs back on to stay on during the loop
    for led in led_pins:
        led.on()  # Turn them on again

# Call the blink function at the beginning of your setup
blink_all_leds()  # Call this function before the main loop
print("Blink LEDs")

# Set up servos for ballasting
fore_ballast_servo = Servo(pin_id=10)
aft_ballast_servo = Servo(pin_id=11)

fore_ballast_servo.write(0)
utime.sleep(1)
print("Fore 0")
aft_ballast_servo.write(0)
utime.sleep(1)
print("Aft 0")
fore_ballast_servo.write(90)
print("Fore 90")
utime.sleep(1)
print("Aft 90")
aft_ballast_servo.write(90)
utime.sleep(1)
fore_ballast_servo.write(180)
print("Fore 180")
utime.sleep(1)
aft_ballast_servo.write(180)
utime.sleep(1)
print("Aft 180")


# Define the pins for signal passing
input_pin1 = Pin(6, Pin.IN)   # Source pin 1 (GP6)
output_pin1 = Pin(10, Pin.OUT) # Target pin 1 (GP10)

input_pin2 = Pin(7, Pin.IN)   # Source pin 2 (GP7)
output_pin2 = Pin(11, Pin.OUT) # Target pin 2 (GP11)


while True:
    print("Loop")
    # Read the state of the first input pin and write to the first output pin
    state1 = input_pin1.value()
    output_pin1.value(state1)
    
    # Read the state of the second input pin and write to the second output pin
    state2 = input_pin2.value()
    output_pin2.value(state2)

1 Like

Welcome James!

What servo’s are you using? If they are digital PWM or PPM servo’s you’ll likely have to use interrupts and timers to do anything meaningful with the signals coming in.

Yeah it would, the Pico operates at 3.3V so you’ll need some kind of way to step that down, a workable method for both analog and digital servo’s would be to use a voltage divider.

With a couple of servo’s you’ll be strapped for time in the loop. And maybe stretching how fast micropython can operate(?)

If they are digital servo’s I’d have a go at using an interrupt to capture the time difference in pulses (the exact method to reverse engineer the output will depend if the servo’s are PWM or PPM).

If the above doesn’t work I would consider looking into PIO on the pico, it might be the way to go.

Then feed that back, is there any reason you cant use the same output from the RX?

1 Like

Thank you for the kind welcome :slight_smile:

Here is the link to the servo I am using: Hitec HS-646WP Ultra Torque HV Waterproof Servo, MG | Buy Servos from Modelflight

I am under the understanding they are PWM.

Currently the signals coming in go through a 1khz Resistor before touching the pico, this seems to have worked for now.

I agree that micropython would struggle with the rapid loop, and this may be why only one of the two work with the aforementioned code.

I agree that using an interrupt would most likely be the best approach, however this (to my knowledge) would hold up the rest of my code, this I would like to avoid.

The reason I am not intending to use the same output is I would like to have the opportunity to switch between sensor based automatic positioning of the servos, and direct passthrough from my DX8 controller.

Thank you for your help so far.

It depends on the application. The rest of the code is held up while the interrupt processes, but it is being held up now as the PWM input state is passed through to the output. The difference is that with interrupts you can easily control when this hold up happens.

Your current procedure assumes that the servo setting must be passed through immediately it changes. To do this you have to monitor the PWM input continuously, and that will restrict the processing of other tasks.

If you use interrupts to detect the servo input you can calculate the current pulse width and work out the servo setting. You can then output that setting as a PWM (using the same code I presume you are using when the sensor is driving the output servo). That checking and setting can occur in the time frame that suits the rest of the application, within whatever constraints you have on how quickly the passthrough must respond to changes in the settings. If the response does not have to be immediate then you can control the checking of the input PWM value by only enabling interrupts when you need to make the check. At all other times the PWM input signal is ignored and the rest of the code executes at full speed.

2 Likes

It does not have to be passed through immediately, but I would prefer it to be within 2 seconds.
The hold up I am concerned with is this pico is running the sensor fusion of 5 or so sensors and I would like these updating as fast as possible, especially MPU6050 and leak sensor readings.

I actually have 5 servo signal wires all coming into the pico, with the intention of being able to have their current values all available. From what I am understanding, this most likely would require some sort of seperate processor, some sort of board may help with this?

How difficult would this program be to make?

Thank you for your help so far, James

1 Like

There is a tutorial here the explains the procedure:
Reading PWM Values from an RC Receiver using Arduino (youtube.com)

4 Likes

This tutorial looks good, I’ll be sure to reference this.

My primary concern would be integrating this into the rest of my project, for the current iteration it is looking like I will just hardwire it and ensure my pico doesn’t get fried with 5v. However for the next iteration (new PCB) I am thinking about using a nano (already works with 5v) and using a second serial channel on the pico for sending just the numerical values from the nano to the pico.

This would allow my pico to run the sensors as intended, and send out via serial to my pi, the pico could also send the servo positions itself after receiving the signal from the receiver.

3 Likes

That’s actually quite generous. I would suggest using a timer interrupt set at 1s or thereabout. In the timer interrupt you can simply enable the interrupt for the PWM pin. Then, when the PWM interrupt occurs, find the value of the setting and set the output PWM to that value and disable the PWM interrupt.

If it is not OK to manage interrupts within an interrupt (check the list of things you should or shouldn’t do inside an interrupt) then in the timer interrupt just set a flag to indicate that the PWM interrupt needs to be set or unset, and check that flag in the main loop.

1 Like

Sounds good. I’ll have a go at intergrating it.

I’m still interested in how feasible this would be ^

1 Like

Yeah I like that plan. :slight_smile:
I’m a fan of compartmentalising my circuits into chuncks where each part is responsible for one job.

If I understand you correctly, the reason your interested in splitting the problem between two micro-controllers is mostly because you have some 5v circuitry and some 3.3v circuitry. If that’s the primary reason, an alternative solution would be a voltage regulator.
If you have a supply of 5v you might fork it between the rails and a 3.3v the voltage regulator. Now you have both 5v and 3.3v available to you having split the circuit in twain with your voltage regulator (ensuring a common ground).

If the pico ever needs to control 5v circuitry with 3.3v GPIOs you can use a mosfet or even a logic-level-converter like this one.

Have you had experience with mosfets or voltage regulators in the past?

1 Like

Yes that is half the reason, the other half is breaking up the reading of the servo motor signals into a separate microcontroller, this will lessen the load on the pico and allow a higher refresh rate. I could have chosen another pico, but as I am working with 5v a nano will easily fit better and support serial comms with the pico.

Yes I have, my project has quite a few step down regulators from core (2x 12v4a, 1x5v9a) and using VSYS on the pico i can use it as my step down to 3.3v. Currently everything coming into the pico is going through a 1k resistor, both for voltage into the pico and also ensuring it is still strong enough when travelling into the servo itself (in the case where I’m just ‘snooping’ the signal)

Thank you for your and everyone’s help, I’m feeling confident I can take this on. And as always, happy making :slight_smile:

This is solved :+1:

1 Like

UPDATE:
Found this YouTube video, and this would work perfectly, however Spektrum Receivers don’t support iBUS

This:

Looks to be my best bet, however I would be ‘snooping’ on the serial cables, not completely removing the receiver itself. This shouldn’t be difficult for my next iteration as I already have those data pins going through my board, so using either a nano or even directly into my pico I can pull the values.

1 Like

Hey @J.a.m.e.s,

That guide looks pretty good! Glad to see you’re making progress.

Wanted to butt in regarding interrupts. Jeff had mentioned you could use a very simple form of “nested” interrupts (for lack of a better term). The idea here is great, though I would use the flag method. Keeping your interrupts independent will cause fewer headaches from priority management.

Thanks for everyone’s input on this, good luck!

2 Likes