Robotics-II-Circuit-Python

Circuit Python tutorials in Robotics II

View the Project on GitHub MrPrattASH/Robotics-II-Circuit-Python

Table of Contents

CircuitPython - FlySky FS-I6X Controller - FS-iA6B Reciever

This page will show you how to use the rc.py library for controlling a FlySky FS-i6(X) controller with an FS-iA6B reciever in circuitpython.

Let’s get into remote controlled rovers! We will start simple and build up to a full state-machine-controlled system.

  1. Wiring the transmitter (video OR text tutorial)
  2. Programming the transmitter (ONLY text tutorial)

1. Transmitter & receiver Wiring/Controls

Option 1: Video tutorial. Option 2: Text Tutorial

The FlySky transmitter/receiver consists of 2 parts. The transmitter is the controller with the joysticks & switches, the receiver is the small box with the antenna.


Video Tutorial


Controlling the FlySky Transmitter

Powering on

As this is a drone controller, it has a few safeguards in place to prevent your robot from immediately driving off or turning on it’s attack mechanisms. Your transmitter should have the following setup:

Screen Shot 2022-10-18 at 20 25 43

Transmitter outputs

The transmitter can send values for 6 different channels at any one time. It does have the option to have up to x4 toggle switches, and x2 potentiometers, but this is the intended output for our controller in this class.

Eventually, we will drive the robot throttle with CH2, and steer with CH1. CH3/4 will likely not be used, and CH 5/6 will be used for various mechanisms attached to our robot.


Wiring the receiver

It is important to know that the receiver outputs a 5V signal. However, our Metro board has both 3.3 and 5v logic pins (or 5V tolerant at least), meaning that we don’t need to change voltage to read our signals.

You’ll need a wiring harness for the receiver, and the receiver itself

You can simply attach the wiring harness into the reciver, so that:

connected


2. Programming the FLY-Sky

Now that you’re wired up, lets program this board and start recieving signals.

Required Library

1. Reading a Single Channel 1

To start, we will read only the horizontal movement of the right joystick (Channel 1). This channel returns a float (a decimal number) between -1.0 and 1.0.

import time
import board
from rc import RCReceiver

# Initialize the receiver. We only care about Channel 1 for now.
# Connect the signal wire of Channel 1 on your receiver to D0.
rc = RCReceiver(ch1=board.D0)

while True:
    # Read the value of Channel 1
    spin = rc.read_channel(1)
                
    print("Steering (Ch 1):", spin)

    # CRITICAL: This 0.02 sleep is required to stay in sync with the PWM cycle.
    # Without this, the receiver readings will fail!
    time.sleep(0.02) 

Experiment

Try to get the console to print exactly 0.0 by letting go of the stick. Then, try to hold it at exactly 0.5.

Click to reveal a hint

# Make sure your RC Transmitter is turned on! 
# If you see "None" or errors, check that the signal wire is on D0 
# and the receiver has power (Red/Black wires).

2. Adding the Second Axis (Channels 1 & 2)

Now let’s add the vertical movement of the right joystick (Channel 2). Like Channel 1, this returns a value from -1.0 to 1.0.

import time
import board
from rc import RCReceiver

# Initialize with two channels
rc = RCReceiver(ch1=board.D0, ch2=board.D1)

while True:
    spin = rc.read_channel(1)
    throttle = rc.read_channel(2)
                
    print("Ch1 (X):", spin, " | Ch2 (Y):", throttle)

    time.sleep(0.02) 

Experiment

Create a script that prints “Forward” if the throttle (Ch 2) is greater than 0.5, and “Reverse” if it is less than -0.5.

Click to reveal a hint

# Use an 'if' and 'elif' statement inside the loop.
# Compare the variable 'throttle' to the numbers 0.5 and -0.5.
Click to reveal a solution

while True:
    throttle = rc.read_channel(2)
    
    if throttle > 0.5:
        print("Forward")
    elif throttle < -0.5:
        print("Reverse")
    else:
        print("Neutral")
        
    time.sleep(0.02)

3. Working with Switches (Channels 5 & 6)

Joysticks provide a range, but switches provide specific steps.

import time
import board
from rc import RCReceiver

# Initialize sticks and switches
rc = RCReceiver(ch1=board.D0, ch2=board.D1, ch5=board.D2, ch6=board.D3)

while True:
    ch1 = rc.read_channel(1)
    ch2 = rc.read_channel(2)
    sw_l = rc.read_channel(5)
    sw_r = rc.read_channel(6)
                
    print("Sticks:", ch1, ch2, " | Left Switch (2-way):", sw_l, " | Right Switch (3-way):", sw_r)

    time.sleep(0.02) 

Experiment

Modify the code so that Channel 5 acts as a “Safety Switch.”

Click to reveal a hint

# Wrap your print statements for Ch1 and Ch2 inside an 'if' statement.
# Check if the value of Channel 5 is equal to 1 (sw_a == 1).
Click to reveal a solution

while True:
    sw_a = rc.read_channel(5)
    
    if sw_a == 1:
        ch1 = rc.read_channel(1)
        ch2 = rc.read_channel(2)
        print("Active - X:", ch1, "Y:", ch2)
    else:
        print("SYSTEM DISARMED")
        
    time.sleep(0.02)

4. RC State Machine Logic

In advanced robotics, we don’t want to just “if/else” everything. We want to switch between different modes of operation. We can use the 3-way switch (Channel 6) to change the “State” of our robot.

Experiment

Create a State Machine with three states: "MANUAL", "AUTO", and "OFF".

Click to reveal a hint

# 1. Create a variable called 'robot_state' and set it to "OFF" initially.
# 2. In the loop, read Channel 6. Use 'if/elif' to change the 'robot_state' string.
# 3. Create a second set of 'if/elif' statements to perform actions based on the string.
Click to reveal a solution

import time
import board
from rc import RCReceiver

rc = RCReceiver(ch1=board.D0, ch2=board.D1, ch6=board.D3)
robot_state = "OFF"

while True:
    # 1. Update State based on RC Switch
    mode_switch = rc.read_channel(6)
    
    if mode_switch == 0:
        robot_state = "OFF"
    elif mode_switch == 1:
        robot_state = "MANUAL"
    elif mode_switch == 2:
        robot_state = "AUTO"

    # 2. Perform actions based on State
    if robot_state == "MANUAL":
        x = rc.read_channel(1)
        y = rc.read_channel(2)
        print("Manual Control Mode -> X:", x, "Y:", y)
    
    elif robot_state == "AUTO":
        print("Autonomous Mode -> Robot is thinking...")
        
    elif robot_state == "OFF":
        print("System is OFF")

    time.sleep(0.02)