-
Notifications
You must be signed in to change notification settings - Fork 0
/
motor_control.py
206 lines (175 loc) · 5.49 KB
/
motor_control.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
"""
Module for providing access to the tmcm1070 motor controller
via Raspberry Pi GPIO
author: Rainer Jacob
date: Feb. 23, 2020
"""
import time
import RPi.GPIO as GPIO
import serial
# change the following constants according to hardware
# see https://www.element14.com/community/docs/DOC-92640/l/raspberry-pi-4-model-b-default-gpio-pinout-with-poe-header
PIN_STEP = 32
PIN_DIRECTION = 36
PIN_ENABLE_MOTOR = 40
class Motor():
"""
Class that allows control of the motor.
"""
def __init__(self):
"""
Initialize Class instance
"""
# prevent multiple instances accessing the hardware
if getattr(self.__class__, '_has_instance', False):
raise RuntimeError('Cannot create another instance')
self.__class__._has_instance = True
# allocate hardware ressources
self.open()
# motor is off
self._enabled = False
self._ser = serial.Serial('/dev/ttyAMA0', baudrate=9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS)
# command to disable microstep
command = [1, 5, 140, 0, 0, 0, 0]
self._write_command(command)
# check status
self._read_command()
print('Setup done.')
def __del__(self):
"""
Finalize class. Close GPIO if required
Returns
-------
None-type
"""
self.close()
del self
def open(self):
"""
Open motor connection
"""
# set Pin numbering mode
GPIO.setmode(GPIO.BOARD)
# setup the hardware, initial low
GPIO.setup(PIN_DIRECTION, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(PIN_STEP, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(PIN_ENABLE_MOTOR, GPIO.OUT, initial=GPIO.LOW)
def close(self):
"""
Close motor connection.
"""
# Hardware ressources need to be released properly.
print('Closing hardware connections')
self.motor_disable()
GPIO.cleanup(PIN_STEP)
GPIO.cleanup(PIN_DIRECTION)
GPIO.cleanup(PIN_ENABLE_MOTOR)
def motor_enable(self):
"""
Enable the motor
"""
self._enabled = True
GPIO.output(PIN_ENABLE_MOTOR, GPIO.HIGH)
def motor_disable(self):
"""
Disable the motor
"""
self._enabled = False
GPIO.output(PIN_ENABLE_MOTOR, GPIO.LOW)
@property
def motor_is_enabled(self):
"""
Return the motor state.
Returns
-------
Bool
Motor enabled True/False
"""
return self._enabled
def step(self, direction=None):
"""
Make a step.
"""
# check motor enabled
if self.motor_is_enabled:
# get current direction
tmp = int(GPIO.input(PIN_DIRECTION))
# print('Current direction: {}'.format(tmp))
# move in same direction as before when not specified
if not direction:
GPIO.output(PIN_STEP, GPIO.HIGH)
time.sleep(0.1)
GPIO.output(PIN_STEP, GPIO.LOW)
time.sleep(0.5)
# use direction given
else:
# same direction as before
if direction == tmp:
GPIO.output(PIN_STEP, GPIO.HIGH)
time.sleep(0.1)
GPIO.output(PIN_STEP, GPIO.LOW)
time.sleep(0.5)
# the other direction, but direction is resetted afterwards
else:
# print('Turning in direction: {}'.format(direction))
GPIO.output(PIN_DIRECTION, direction)
GPIO.output(PIN_STEP, GPIO.HIGH)
time.sleep(0.1)
GPIO.output(PIN_STEP, GPIO.LOW)
time.sleep(0.5)
GPIO.output(PIN_DIRECTION, tmp)
else:
print('Motor is not enabled')
@property
def motor_direction(self):
"""
Return the motor direction.
Returns
-------
int
Motor direction (level of corresponding pin)
"""
return int(GPIO.input(PIN_DIRECTION))
@motor_direction.setter
def motor_direction(self, direction):
"""
Set the motor direction.
Parameters
----------
direction : int
Direction the motor should turn
"""
GPIO.output(PIN_DIRECTION, direction)
def _write_command(self, command):
"""
Write es command given to the serial port.
Parameters
----------
command : list
command list given es integers
"""
tmp = command
# convert the command to bytes
command_bytes = serial.to_bytes(tmp)
# calculate the checksum
checksum = command_bytes[0]
for i in range (1, len(command_bytes)):
checksum += command_bytes[i]
# add the checksum and convert to bytes again
tmp.append(checksum)
command_bytes = serial.to_bytes(tmp)
# send to serial
if not self._ser.is_open:
self._ser.open()
self._ser.write(command_bytes)
def _read_command(self):
"""
Reads the serial port
"""
if not self._ser.is_open:
self._ser.open()
response = self._ser.read(8)
print(response)