Skip to main content

Python serial interface for the Easy PID Motor Controller (EPMC)

Project description

Easy PID Motor Controller (EPMC) Python Library

Python serial interface for the Easy PID Motor Controller (EPMC). The Library Supports two and four motor EPMC controllers

you can use it in your microcomputer robotics project (e.g Raspberry Pi, PC, etc.)

Install

  • you'll need to pip install the pyserial library
      pip3 install epmc-serial   //linux or mac
    
    OR
      pip install epmc-serial  //windows
    

Uninstall

  • you'll need to pip install the pyserial library
      pip3 uninstall epmc-serial   //linux or mac
    
      pip uninstall epmc-serial  //windows
    

How to Use the Library

  • Ensure you have the EPMC MODULE interfaced with your preferred motors

  • Ensure you've already setup the encoder and PID parameters with the epmc_setup_application.

  • check the serial port the driver is connected to:

    ls /dev/ttyA* # for two motor support
    

    OR

    ls /dev/ttyU* # for four motor support
    

    you should see /dev/ttyACM0 or /dev/ttyUSB0 or ... and so on

  • use the serial port in your code

  • A simple way to get started is simply to try out the example code below

Basic Library functions and usage (Motor Control - Default)

  • connect to EPMC module

    controller = EPMCSerialClient()

    controller .supportedNumOfMotors(SupportedNumOfMotors.TWO)

    controller.connect("port_name or port_path")

  • clear speed, position, e.t.c data buffer on the EPMC module

    controller.clearDataBuffer() # returns bool -> success

  • send target angular velocity command

    controller.writeSpeed(motor0_TargetVel, motor1_TargetVel)

  • send PWM command

    controller.writePWM(motor0_PWM, motor1_PWM)

  • set motor command timeout

    controller.setCmdTimeout(timeout_ms)

  • get motor command timeout

    controller.getCmdTimeout() # returns tuple -> (success, motor_command_timeout_ms): bool, float

  • read motors angular position and angular velocity

    controller.readMotorData() # returns bool, tuple(size=4foats) -> success, (pos0, pos1, vel0, vel1)

  • read motors angular position

    controller.readPos() # returns bool, tuple(size=2floats) -> success, (pos0, pos1)

  • read motors angular velocity

    controller.readVel() # returns bool, tuple(size=2floats) -> success, (vel0, vel1)

  • read motor maximum commandable angular velocity

    controller.getMaxVel(motor_no) # returns tuple -> (success, max_vel): bool, float maxVel0 or maxVel1 based on the specified motor number

  • while these function above help communicate with the already configure EPMC module, more examples of advanced funtions usage for parameter tuning can be found in the epmc_setup_application source code

example code (Motor Control - Default)

from epmc_serial import EPMCSerialClient
import time

controller = EPMCSerialClient()

# variable for communication
pos0=0.0; pos1=0.0
vel0=0.0; vel1=0.0

# [4 rev/sec, 2 rev/sec, 1 rev/sec, 0.5 rev/sec]
targetVel = [1.571, 3.142, 6.284, 12.568] 
vel = targetVel[1]
v = 0.0

readTime = None
readTimeInterval = 0.02 # 50Hz

cmdTime = None
cmdTimeInterval = 5.0

# EPMC Connect
serial_port = '/dev/ttyACM0'
serial_baudrate = 115200
serial_timeout = 0.018 #value < 0.02 (for 50Hz comm)
controller.connect(serial_port, serial_baudrate, serial_timeout)

success = controller.clearDataBuffer()
controller.writeSpeed(0.0, 0.0)
print('configuration complete')

timeout_ms = 10000
controller.setCmdTimeout(timeout_ms)
success, val0 = controller.getCmdTimeout()
if success: # only update if read was successfull
  timeout_ms = val0
  print("command timeout in ms: ", timeout_ms)
else:
  print("ERROR: could not read motor command timeout")

sendHigh = True

readTime = time.time()
cmdTime = time.time()

while True:
  if time.time() - cmdTime > cmdTimeInterval:
    if sendHigh:
      # print("command high")
      v = vel
      controller.writeSpeed(v, v)
      vel = vel*-1
      sendHigh = False
    else:
      # print("command low")
      v = 0.0
      controller.writeSpeed(v, v)
      sendHigh = True
    
    
    cmdTime = time.time()



  if time.time() - readTime > readTimeInterval:
    try:
      # controller.writeSpeed(v, v)
      success, val = controller.readMotorData()
      if success: # only update if read was successfull
        pos0 = val[0]; pos1 = val[1]
        vel0 = val[2]; vel1 = val[3]

      print(f"motor0_readings: [{pos0}, {vel0}]")
      print(f"motor1_readings: [{pos1}, {vel1}]")
      print("")
    except:
      pass
    
    readTime = time.time()

Basic Library functions and usage (Four Motor Support)

  • connect to EPMC module

    controller = EPMCSerialClient()

    #ensure you set/call supportedNumOfMotors() before connect() as below:

    controller .supportedNumOfMotors(SupportedNumOfMotors.FOUR)

    controller.connect("port_name or port_path")

  • clear speed, position, e.t.c data buffer on the EPMC module

    controller.clearDataBuffer() # returns bool -> success

  • send target angular velocity command

    controller.writeSpeed(motor0_TargetVel, motor1_TargetVel)

  • send PWM command

    controller.writePWM(motor0_PWM, motor1_PWM)

  • set motor command timeout

    controller.setCmdTimeout(timeout_ms)

  • get motor command timeout

    controller.getCmdTimeout() # returns tuple -> (success, motor_command_timeout_ms): bool, float

  • read motors angular position and angular velocity

    controller.readMotorData() # returns bool, tuple(size=8floats) -> success, (pos0, pos1, pos2, pos3, vel0, vel1, vel2, vel3)

  • read motors angular position

    controller.readPos() # returns bool, tuple(size=4floats) -> success, (pos0, pos1, pos2, pos3)

  • read motors angular velocity

    controller.readVel() # returns bool, tuple(size=4floats) -> success, (vel0, vel1, vel2, vel3)

  • read motor maximum commandable angular velocity

    controller.getMaxVel(motor_no) # returns tuple -> (success, max_vel): bool, float maxVel0 or maxVel1 based on the specified motor number

  • while these function above help communicate with the already configure EPMC module, more examples of advanced funtions usage for parameter tuning can be found in the epmc_setup_application source code

example code (Four Motor Support)

from epmc_serial import EPMCSerialClient, SupportedNumOfMotors
import time

controller = EPMCSerialClient()

# variable for communication
pos0=0.0; pos1=0.0; pos2=0.0; pos3=0.0
vel0=0.0; vel1=0.0; vel2=0.0; vel3=0.0

# [4 rev/sec, 2 rev/sec, 1 rev/sec, 0.5 rev/sec]
targetVel = [1.571, 3.142, 6.284, 12.568] 
vel = targetVel[1]
v = 0.0

readTime = None
readTimeInterval = 0.02 # 50Hz

cmdTime = None
cmdTimeInterval = 5.0

# EPMC Connect
serial_port = '/dev/ttyUSB0'
serial_baudrate = 115200
serial_timeout = 0.018 #value < 0.02 (for 50Hz comm)
controller.supportedNumOfMotors(SupportedNumOfMotors.FOUR)
controller.connect(serial_port, serial_baudrate, serial_timeout)

success = controller.clearDataBuffer()
controller.writeSpeed(0.0, 0.0, 0.0, 0.0)
print('configuration complete')

timeout_ms = 10000
controller.setCmdTimeout(timeout_ms)
success, val0 = controller.getCmdTimeout()
if success: # only update if read was successfull
  timeout_ms = val0
  print("command timeout in ms: ", timeout_ms)
else:
  print("ERROR: could not read motor command timeout")

sendHigh = True

readTime = time.time()
cmdTime = time.time()

while True:
  if time.time() - cmdTime > cmdTimeInterval:
    if sendHigh:
      # print("command high")
      v = vel
      controller.writeSpeed(v, v, v, v)
      vel = vel*-1
      sendHigh = False
    else:
      # print("command low")
      v = 0.0
      controller.writeSpeed(v, v, v, v)
      sendHigh = True
    
    
    cmdTime = time.time()



  if time.time() - readTime > readTimeInterval:
    try:
      # controller.writeSpeed(v, v, v, v)
      success, val = controller.readMotorData()
      if success: # only update if read was successfull
        pos0 = val[0]; pos1 = val[1]; pos2 = val[2]; pos3 = val[3]
        vel0 = val[4]; vel1 = val[5]; vel2 = val[6]; vel3 = val[7]

      print(f"motor0_readings: [{pos0}, {vel0}]")
      print(f"motor1_readings: [{pos1}, {vel1}]")
      print(f"motor2_readings: [{pos2}, {vel2}]")
      print(f"motor3_readings: [{pos3}, {vel3}]")
      print("")
    except:
      pass
    
    readTime = time.time()

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

epmc_serial-1.3.1.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

epmc_serial-1.3.1-py3-none-any.whl (6.4 kB view details)

Uploaded Python 3

File details

Details for the file epmc_serial-1.3.1.tar.gz.

File metadata

  • Download URL: epmc_serial-1.3.1.tar.gz
  • Upload date:
  • Size: 6.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for epmc_serial-1.3.1.tar.gz
Algorithm Hash digest
SHA256 6bd64dd8fe0ac15f1dfe55e8609b039abbfdc6860995a63091873996848a2c80
MD5 8d20dbf4864c4fac956b534635d21fd1
BLAKE2b-256 de904382ec0a4bd9f9e17b0b4db5b502efb8f17ca26bcd0b83c314c18b429567

See more details on using hashes here.

File details

Details for the file epmc_serial-1.3.1-py3-none-any.whl.

File metadata

  • Download URL: epmc_serial-1.3.1-py3-none-any.whl
  • Upload date:
  • Size: 6.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for epmc_serial-1.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 df861f01120ca57eac78ffcf6a1f184389030d1d16e331d4b4c632a070c0812d
MD5 b5c73c9fb78696acf28528d590ff377a
BLAKE2b-256 c125277a16f982e854c1fd7d41a89da0cd8b34163ea4e7a683c6f3034fd7130b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page