ME 405 Pen Plotter
tasks.py File Reference

This file contains the main function for controlling the plotter, along with task functions for sending position commands to the stepper drivers and to a PC via UART. More...

Functions

def tasks.onButtonPressFCN (IRQ_src)
 Sets the button flag when the button is pressed. More...
 
def tasks.get_velocity_setting (rad_per_sec)
 Converts the velocity value that is passed in. More...
 
def tasks.get_acceleration_setting (rad_per_sec2)
 Converts the acceleration value that is passed in. More...
 
def tasks.get_pmul_and_pdiv_setting (a_max)
 Finds values for PMUL and PDIV. More...
 
def tasks.convert_motor1_target (microsteps)
 Converts a motor1 target value to send to the TMC4210. More...
 
def tasks.convert_motor2_target (microsteps)
 Converts a motor2 target value to send to the TMC4210. More...
 
def tasks.g (x, theta)
 g(x, theta) function for use in the Newton-Raphson algorithm. More...
 
def tasks.dg_dtheta (theta)
 dg/dtheta(theta) function for use in the Newton-Raphson algorithm. More...
 
def tasks.NewtonRaphson (fcn, jacobian, guess, thresh)
 Iteratively solves the roots of y = g(theta). More...
 
def tasks.create_cmd_list ()
 Creates a list of motor commands from an hpgl file. More...
 
def tasks.print_cmd_list (cmd_list)
 Prints out the passed in cmd_list. More...
 
def tasks.task_cmds_fun ()
 Task function for sending commands to the TMC4210s. More...
 
def tasks.task_comms_fun ()
 Task function for sending current commands to the PC. More...
 

Variables

string tasks.FILENAME = 'drawing.hpgl'
 
int tasks.DPI = 1016
 
float tasks.MM_PER_IN = 25.4
 
float tasks.MAX_MM_DIST = 0.5
 
int tasks.W = 270
 
int tasks.H = 90
 
int tasks.D = 42
 
int tasks.RD = 40
 
int tasks.STEPS_PER_ROTATION = 200
 
int tasks.MICROSTEPS = 8
 
int tasks.F_CLK = 20000000
 
int tasks.PULSE_DIV = 5
 
int tasks.RAMP_DIV = 5
 
int tasks.MS_PER_RADIAN = 1 / (2 * math.pi) * STEPS_PER_ROTATION * MICROSTEPS
 
 tasks.MOTOR1_HOMING_ANGLE = -int(68.27 / 360 * STEPS_PER_ROTATION * MICROSTEPS * 6)
 
int tasks.MOTOR1_POLARITY = 1
 
 tasks.MOTOR2_HOMING_ANGLE = -int((34.7/2 + 60.24 + 0.9) / 40 * STEPS_PER_ROTATION * MICROSTEPS)
 
int tasks.MOTOR2_POLARITY = -1
 
float tasks.PEN_DOWN_DEG = 65.5
 
 tasks.PEN_DOWN_MS = int(PEN_DOWN_DEG / 360 * STEPS_PER_ROTATION * MICROSTEPS)
 
int tasks.PEN_UP_DEG = 40
 
 tasks.PEN_UP_MS = int(PEN_UP_DEG / 360 * STEPS_PER_ROTATION * MICROSTEPS)
 
int tasks.MOTOR1_SPEED = 15
 
int tasks.MOTOR1_HOMING_SPEED = 3
 
int tasks.MOTOR2_SPEED = 15
 
int tasks.MOTOR2_HOMING_SPEED = 6
 
int tasks.MOTOR3_SPEED = 15
 
int tasks.MOTOR3_HOMING_SPEED = 6
 
int tasks.MOTOR1_X_MAX = 20000
 
int tasks.MOTOR2_X_MAX = 20000
 
int tasks.MOTOR3_X_MAX = 20000
 
int tasks.MOTOR1_V_MIN = 10
 
int tasks.MOTOR2_V_MIN = 10
 
int tasks.MOTOR3_V_MIN = 1
 
int tasks.MOTOR1_A_MAX = 80
 
int tasks.MOTOR2_A_MAX = 80
 
int tasks.MOTOR3_A_MAX = 60
 
int tasks.TYPE_PEN_UP = 1
 
int tasks.TYPE_PEN_DOWN = 2
 
int tasks.TYPE_CMDS_DONE = 3
 
int tasks.TYPE_COMMS_DONE = 4
 
 tasks.share_button_flag = None
 Button flag. More...
 
 tasks.cmd_list = None
 List of stepper commands, in units of microsteps. More...
 
list tasks.drivers = [3]
 Stepper_Driver objects for controlling the 3 steppers. More...
 
 tasks.button_int
 Button interrupt. More...
 
 tasks.clk_pin = pyb.Pin(pyb.Pin.board.PB6, pyb.Pin.OUT_PP)
 Clock pin.
 
 tasks.tim = pyb.Timer(4, period=3, prescaler=0)
 Timer for TMC4210 clock signal.
 
 tasks.clk = tim.channel(1, pin=clk_pin, mode=pyb.Timer.PWM, pulse_width=2)
 Timer channel for TMC4210 clock signal.
 
 tasks.spi = pyb.SPI(2, pyb.SPI.CONTROLLER, baudrate=1000000, polarity=1, phase=1)
 SPI.
 
 tasks.cs1 = pyb.Pin(pyb.Pin.board.PB8, mode=pyb.Pin.OUT_PP, value=1)
 Chip select pin for driver1.
 
 tasks.cs2 = pyb.Pin(pyb.Pin.board.PB9, mode=pyb.Pin.OUT_PP, value=1)
 Chip select pin for driver2.
 
 tasks.cs3 = pyb.Pin(pyb.Pin.cpu.C7, mode=pyb.Pin.OUT_PP, value=1)
 Chip select pin for driver3.
 
 tasks.en1 = pyb.Pin(pyb.Pin.cpu.C2, mode=pyb.Pin.OUT_PP, value=1)
 TMC2208 enable pin for driver1.
 
int tasks.x_max = MOTOR1_X_MAX
 Max position for driver1. More...
 
int tasks.v_min = MOTOR1_V_MIN
 V_MIN register value for driver1. More...
 
def tasks.v_max = get_velocity_setting(MOTOR1_SPEED)
 V_MAX register value for driver1. More...
 
def tasks.a_max = get_acceleration_setting(MOTOR1_A_MAX)
 A_MAX register value for driver1. More...
 
 tasks.pmul
 PMUL and PDIV register values for driver1. More...
 
 tasks.pdiv
 
 tasks.driver1
 driver1 Stepper_Driver object More...
 
 tasks.en2 = pyb.Pin(pyb.Pin.cpu.C3, mode=pyb.Pin.OUT_PP, value=1)
 TMC2208 enable pin for driver2.
 
 tasks.driver2
 driver2 Stepper_Driver object More...
 
 tasks.en3 = pyb.Pin(pyb.Pin.cpu.C6, mode=pyb.Pin.OUT_PP, value=1)
 TMC2208 enable pin for driver3.
 
 tasks.driver3
 driver3 Stepper_Driver object More...
 
 tasks.share_cmd_type
 Command type share. More...
 
 tasks.share_theta0
 theta0 share More...
 
 tasks.share_theta1
 theta1 share More...
 
 tasks.task_cmds
 Task for sending commands to the TMC4210s. More...
 
 tasks.task_comms
 Taskf for sending commands to the PC. More...
 

Detailed Description

This file contains the main function for controlling the plotter, along with task functions for sending position commands to the stepper drivers and to a PC via UART.

Author
Ryan Ghosh
Date
June 10, 2022

Function Documentation

◆ convert_motor1_target()

def tasks.convert_motor1_target (   microsteps)

Converts a motor1 target value to send to the TMC4210.

Takes in a target value for motor1 in units of microsteps And converts it to a corresponding value to send to the TMC4210, based on the direction of the motor and its angle when the limit switch is triggered.

Parameters
microstepsTarget position in microsteps.
Returns
Target position for motor1 that can be sent to the TMC4210.

◆ convert_motor2_target()

def tasks.convert_motor2_target (   microsteps)

Converts a motor2 target value to send to the TMC4210.

Takes in a target value for motor2 in units of microsteps And converts it to a corresponding value to send to the TMC4210, based on the direction of the motor and its angle when the limit switch is triggered.

Parameters
microstepsTarget position in microsteps.
Returns
Target position for motor2 that can be sent to the TMC4210.

◆ create_cmd_list()

def tasks.create_cmd_list ( )

Creates a list of motor commands from an hpgl file.

Converts each command in an hpgl file to a tuple containing the type ("PU" or "PD" for "pen up" or "pen down"), an array of theta0 values to send to the driver1 TMC4210, and an array of theta1 values to send to the driver2 TMC4210.

Returns
A list of command tuples.

◆ dg_dtheta()

def tasks.dg_dtheta (   theta)

dg/dtheta(theta) function for use in the Newton-Raphson algorithm.

A function of theta that is used to iteratively find the value of theta that satisfies x = f(theta), where x is the desired pen position and theta is the motor positions.

Parameters
thetatuple of (theta0, theta1).
Returns
dg(theta)/dtheta for the theta guess that is passed in.

◆ g()

def tasks.g (   x,
  theta 
)

g(x, theta) function for use in the Newton-Raphson algorithm.

A function of x and theta that should be driven to 0 to iteratively find the value of theta that satisfies x = f(theta), where x is the desired pen position and theta is the motor positions.

Parameters
xtuple of (x_target, y_target).
thetatuple of (theta0, theta1).
Returns
g(theta) for the theta guess that is passed in.

◆ get_acceleration_setting()

def tasks.get_acceleration_setting (   rad_per_sec2)

Converts the acceleration value that is passed in.

Takes in an acceleration value in rad/s^2 and converts it to a corresponding value to be used in the A_MAX register of a TMC4210.

Parameters
rad_per_sec2Acceleration value in rad/s^2.
Returns
Corresponding acceleration value to be used in the TMC4210 registers.

◆ get_pmul_and_pdiv_setting()

def tasks.get_pmul_and_pdiv_setting (   a_max)

Finds values for PMUL and PDIV.

Finds suitable values for PMUL and PDIV to match the A_MAX value that is passed in, along with the existing RAMP_DIV and PULSE_DIV settings.

Parameters
a_maxA_MAX value to match with.
Returns
A tuple containing PMUL, PDIV values.

◆ get_velocity_setting()

def tasks.get_velocity_setting (   rad_per_sec)

Converts the velocity value that is passed in.

Takes in a velocity value in rad/s and converts it to a corresponding value to be used in the V_MIN or V_MAX register of a TMC4210.

Parameters
rad_per_secVelocity value in rad/s.
Returns
Corresponding velocity value to be used in the TMC4210 registers.

◆ NewtonRaphson()

def tasks.NewtonRaphson (   fcn,
  jacobian,
  guess,
  thresh 
)

Iteratively solves the roots of y = g(theta).

Iteratively finds values for theta to drive the passed in fcn to within thresh of 0.

Parameters
fcnThe function to find the roots of.
jacobianJacobian matrix for the system
guessInitial guess for theta.
threshAllowable error when driving fcn to 0.
Returns
Resulting theta roots.

◆ onButtonPressFCN()

def tasks.onButtonPressFCN (   IRQ_src)

Sets the button flag when the button is pressed.

An interrupt function triggered when the blue button on the Nucleo is pressed. This function sets the button_flag share to 1 to indicate the button has been pressed.

Parameters
IRQ_srcReference to the hardware device that caused the interrupt to occur.

◆ print_cmd_list()

def tasks.print_cmd_list (   cmd_list)

Prints out the passed in cmd_list.

Prints out each command type ("PU" or "PD") with the corrsponding coordinate list below it.

◆ task_cmds_fun()

def tasks.task_cmds_fun ( )

Task function for sending commands to the TMC4210s.

Generator function that waits for a button press to begin, then reads through cmd_list and sets the targets for each stepper driver. The function waits for the current targets to be reached before sending the next ones.

◆ task_comms_fun()

def tasks.task_comms_fun ( )

Task function for sending current commands to the PC.

Generator function that waits for a button press to begin, then sends the current commands to the PC for live plotting in sync with the physical plotter.

Variable Documentation

◆ a_max

def tasks.a_max = get_acceleration_setting(MOTOR1_A_MAX)

A_MAX register value for driver1.

A_MAX register value for driver3.

A_MAX register value for driver2.

◆ button_int

tasks.button_int
Initial value:
1= pyb.ExtInt(pyb.Pin.cpu.C13, pyb.ExtInt.IRQ_FALLING,
2 pyb.Pin.PULL_NONE, callback=onButtonPressFCN)

Button interrupt.

◆ cmd_list

def tasks.cmd_list = None

List of stepper commands, in units of microsteps.

List of plotter commands.

◆ driver1

tasks.driver1
Initial value:
1= Stepper_Driver(spi, en1, cs1,
2 x_max, v_min, v_max, PULSE_DIV, RAMP_DIV,
3 a_max, pmul, pdiv)

driver1 Stepper_Driver object

◆ driver2

tasks.driver2
Initial value:
1= Stepper_Driver(spi, en2, cs2,
2 x_max, v_min, v_max, PULSE_DIV, RAMP_DIV,
3 a_max, pmul, pdiv)

driver2 Stepper_Driver object

◆ driver3

tasks.driver3
Initial value:
1= Stepper_Driver(spi, en3, cs3,
2 x_max, v_min, v_max, PULSE_DIV, RAMP_DIV,
3 a_max, pmul, pdiv)

driver3 Stepper_Driver object

◆ drivers

list tasks.drivers = [3]

Stepper_Driver objects for controlling the 3 steppers.

List of stepper drivers.

◆ pmul

tasks.pmul

PMUL and PDIV register values for driver1.

PMUL and PDIV register values for driver3.

PMUL and PDIV register values for driver2.

◆ share_button_flag

tasks.share_button_flag = None

Button flag.

Button flag share.

◆ share_cmd_type

tasks.share_cmd_type
Initial value:
1= task_share.Share('H', thread_protect = False,
2 name = "Share Command Type")

Command type share.

◆ share_theta0

tasks.share_theta0
Initial value:
1= task_share.Share('L', thread_protect = False,
2 name = "Share Theta0")

theta0 share

◆ share_theta1

tasks.share_theta1
Initial value:
1= task_share.Share('L', thread_protect = False,
2 name = "Share Theta1")

theta1 share

◆ task_cmds

tasks.task_cmds
Initial value:
1= cotask.Task(task_cmds_fun, name='Task_Commands',
2 priority=1, period=1, profile=True, trace=False)

Task for sending commands to the TMC4210s.

◆ task_comms

tasks.task_comms
Initial value:
1= cotask.Task(task_comms_fun, name='Task_Comms',
2 priority=2, period=100, profile=True, trace=False)

Taskf for sending commands to the PC.

◆ v_max

def tasks.v_max = get_velocity_setting(MOTOR1_SPEED)

V_MAX register value for driver1.

V_MAX register value for driver3.

V_MAX register value for driver2.

◆ v_min

int tasks.v_min = MOTOR1_V_MIN

V_MIN register value for driver1.

V_MIN register value for driver3.

V_MIN register value for driver2.

◆ x_max

int tasks.x_max = MOTOR1_X_MAX

Max position for driver1.

Max position for driver3.

Max position for driver2.