Infineon Team
Published © MIT

Servo Motor Control using PSOC™ 6 and MicroPython

Do you need a a simple way to control a servo motor in your project? Look no further!

BeginnerProtip1 hour176
Servo Motor Control using PSOC™ 6 and MicroPython

Things used in this project

Hardware components

SG90 Micro-servo motor
SG90 Micro-servo motor
×1
MG995 Micro Digital Servo Motor
×1
Infineon PSOC™ 6 Wi-Fi BT Prototyping Kit
×1

Software apps and online services

Thonny
MicroPython
MicroPython

Story

Read more

Schematics

Motor pin out

This is how you connect the motor to the CY8CPROTO-062-4343W.

Code

Continuous Servo Code

MicroPython
Contains function: set_motor_to_speed() that takes a rotational speed as an input, calculates the required pulse width and sends that signal to the motor.
# import libraries needed for pin communication
from machine import PWM

# Set parameters
pw_min = 1000000 #ns
pw_max = 2000000 #ns
pw_stationary = (pw_max-pw_min)/2 + pw_min #ns
gradient = -777846 #ns/Hz

'''Example: gradient calculations using MG995
1. pw_min -> 18 turns,28sec -> +0.6428 turns per second! (clockwise)
2. 1250000 -> 14 turns, 28 sec -> +0.5
3. 1750000 ->14 turns, 26 sec -> -0.5384 turns per second! (anticlockwise)
4. pw_max -> 16 turns, 22sec -> -0.7272 turns per second!
smallest max speed: min(0.6428, 0.7272) = 0.6428 
gradient: -500000ns/Hz / 0.6428 = -500000/0.6428 ns/Hz = -777846ns/Hz (negative gradient, see graph)
'''

# Initialize PWM at pin 9.7 and set the initial pulse width to pw_stationary 
#-> motor is stationary
cont_servo = PWM('P9_7', freq = 50, duty_ns = int(pw_stationary)) # PWM is initialized for the given pin with respective frequency & duty cycle given as raw value.

'''Maps speed (in Hertz) to pulse width (in ns).
Clockwise is positive, anti clockwise is negative'''
def speed_to_ns(speed):
    ns = gradient*speed + pw_stationary
    return ns

'''Takes speed, calculates pulse width and sends signal to servo'''
def set_motor_to_speed(speed):
    ns = speed_to_ns(speed)
    ns = int(ns)
    # Print ns to help with troubleshooting later on
    print(ns, "ns")
    # Check if in range
    if(pw_min <= ns and ns <= pw_max):
        cont_servo.duty_ns(ns)
    else:
        # Calculate the max speed (can use pw_min or max)
        max_speed = (pw_min - pw_stationary)/gradient # y = ax + b -> x = (y-b)/a
        print("Error: Speed not in range!")
        print("Max Speed is:", -max_speed)

Positional Servo Code

MicroPython
Contains function: set_motor_to_angle(angle) that takes an angle as an input, calculates the required pulse width and sends that signal to the motor.
# Import libraries needed for pin communication and time measurement
from machine import PWM
import time

# Set parameters
pw_min = 500000 #ns
pw_max = 2500000 #ns
angle_min = 0 #degrees
angle_max = 180 #degrees
frequency = 50 #Hz

# Initialize PWM at pin 9.7 and set the initial pulse width to pw_min 
pos_servo = PWM('P9_7', freq=frequency, duty_ns=pw_min)

'''Auxiliary function, maps angle to pulse width'''
def angle_to_ns(angle):
    # Check if angle is in range
    if(angle_min <= angle and angle <= angle_max):
        # In range -> Calculate pulse width 
        angle_percentage = (angle - angle_min)/(angle_max - angle_min)
        ns_percentage = angle_percentage
        ns = ns_percentage*(pw_max - pw_min) + pw_min
        # Print ns to help with troubleshooting later on
        print(ns, "ns")
        return ns
    else:
        # Not in range -> Return error
        print("Error: Angle not in range!")
        return False
        
'''Takes angle, calucates pulse width and sends signal to servo'''
def set_motor_to_angle(angle):
    # Gets the pulse width from auxiliary function
    ns = angle_to_ns(angle)
    if (ns is False): return
    # Convert float to int 
    ns = int(ns)
    # Check if the conversion has pushed the pulse width out of bounds
    #-> adjust accordingly 
    if(ns > pw_max):
        ns = pw_max
    elif (ns < pw_min):
        ns = pw_min
    # Send signal to motor
    pos_servo.duty_ns(ns)
    
''' Test function, uncomment to test
while (True):
    set_motor_to_angle(200) #should return error message
    time.sleep(0.5)
    set_motor_to_angle(180) #should set motor angle to 180
    time.sleep(0.5)
    set_motor_to_angle(10) #should set motor angle to 10
    time.sleep(0.5)
'''

Credits

Infineon Team
118 projects • 193 followers
Hands-on projects, tutorials, and code for sensors, MCUs, connectivity, security, power, and IoT. Follow for new builds and ideas.

Comments