tangled
alpha
login
or
join now
dunkirk.sh
/
myrus
0
fork
atom
a scrappy gimbal that insults you in shakespearean english
0
fork
atom
overview
issues
pulls
pipelines
feat: move firmware to firmware dir
Kieran Klukas
1 year ago
8e14d23a
fa78c0c6
+82
-134
2 changed files
expand all
collapse all
unified
split
code.py
firmware
code.py
-134
code.py
···
1
1
-
import sys
2
2
-
import board
3
3
-
import time
4
4
-
import digitalio
5
5
-
import supervisor
6
6
-
7
7
-
# Define pins for stepper motors
8
8
-
motor1_step = digitalio.DigitalInOut(board.GP11)
9
9
-
motor1_step.direction = digitalio.Direction.OUTPUT
10
10
-
motor1_dir = digitalio.DigitalInOut(board.GP10)
11
11
-
motor1_dir.direction = digitalio.Direction.OUTPUT
12
12
-
motor2_step = digitalio.DigitalInOut(board.GP8)
13
13
-
motor2_step.direction = digitalio.Direction.OUTPUT
14
14
-
motor2_dir = digitalio.DigitalInOut(board.GP7)
15
15
-
motor2_dir.direction = digitalio.Direction.OUTPUT
16
16
-
enable = digitalio.DigitalInOut(board.GP9)
17
17
-
enable.direction = digitalio.Direction.OUTPUT
18
18
-
19
19
-
command_buffer = ""
20
20
-
last_serial_check = time.monotonic()
21
21
-
SERIAL_CHECK_INTERVAL = 0.1 # Check serial every 1ms
22
22
-
23
23
-
# Enable motors
24
24
-
enable.value = False
25
25
-
print("Motors enabled")
26
26
-
27
27
-
STEPS_PER_REVOLUTION = 200 # For a typical 1.8° stepper motor
28
28
-
29
29
-
# Motor state tracking
30
30
-
class MotorState:
31
31
-
def __init__(self):
32
32
-
self.running = False
33
33
-
self.direction = True # True for forward
34
34
-
self.speed = 1.0
35
35
-
self.last_step_time = 0
36
36
-
37
37
-
motor1 = MotorState()
38
38
-
motor2 = MotorState()
39
39
-
40
40
-
def calculate_step_delay(speed):
41
41
-
return 1 / (STEPS_PER_REVOLUTION * speed)
42
42
-
43
43
-
def handle_command(command):
44
44
-
parts = command.split()
45
45
-
speed = 1 # Default speed
46
46
-
if len(parts) > 1:
47
47
-
try:
48
48
-
speed = float(parts[1])
49
49
-
except ValueError:
50
50
-
print("Invalid speed value")
51
51
-
return
52
52
-
command = parts[0]
53
53
-
54
54
-
if command == "forward1":
55
55
-
motor1.running = True
56
56
-
motor1.direction = True
57
57
-
motor1.speed = speed
58
58
-
motor1_dir.value = True
59
59
-
print(f"Moving motor 1 forward at {speed} rotations per second...")
60
60
-
61
61
-
elif command == "forward2":
62
62
-
motor2.running = True
63
63
-
motor2.direction = True
64
64
-
motor2.speed = speed
65
65
-
motor2_dir.value = True
66
66
-
print(f"Moving motor 2 forward at {speed} rotations per second...")
67
67
-
68
68
-
elif command == "reverse1":
69
69
-
motor1.running = True
70
70
-
motor1.direction = False
71
71
-
motor1.speed = speed
72
72
-
motor1_dir.value = False
73
73
-
print(f"Moving motor 1 in reverse at {speed} rotations per second...")
74
74
-
75
75
-
elif command == "reverse2":
76
76
-
motor2.running = True
77
77
-
motor2.direction = False
78
78
-
motor2.speed = speed
79
79
-
motor2_dir.value = False
80
80
-
print(f"Moving motor 2 in reverse at {speed} rotations per second...")
81
81
-
82
82
-
elif command == "stop1":
83
83
-
motor1.running = False
84
84
-
print("Motor 1 stopped")
85
85
-
86
86
-
elif command == "stop2":
87
87
-
motor2.running = False
88
88
-
print("Motor 2 stopped")
89
89
-
90
90
-
elif command == "stop":
91
91
-
motor1.running = False
92
92
-
motor2.running = False
93
93
-
enable.value = True
94
94
-
print("All motors stopped")
95
95
-
96
96
-
else:
97
97
-
print("Unknown command. Use 'forward1/2 [speed]', 'reverse1/2 [speed]' or 'stop1/2'")
98
98
-
99
99
-
def step_motor(motor_state, step_pin):
100
100
-
if not motor_state.running:
101
101
-
return
102
102
-
103
103
-
current_time = time.monotonic()
104
104
-
step_delay = calculate_step_delay(motor_state.speed)
105
105
-
106
106
-
if (current_time - motor_state.last_step_time) >= step_delay:
107
107
-
step_pin.value = not step_pin.value # Toggle the pin
108
108
-
motor_state.last_step_time = current_time
109
109
-
110
110
-
while True:
111
111
-
current_time = time.monotonic()
112
112
-
113
113
-
# Check serial input less frequently
114
114
-
if current_time - last_serial_check >= SERIAL_CHECK_INTERVAL:
115
115
-
if supervisor.runtime.serial_bytes_available:
116
116
-
byte = sys.stdin.read(1)
117
117
-
118
118
-
if byte in ('\x08', '\x7f'):
119
119
-
if command_buffer:
120
120
-
command_buffer = command_buffer[:-1]
121
121
-
print('\x08 \x08', end='')
122
122
-
elif byte == '\n' or byte == '\r':
123
123
-
print()
124
124
-
if command_buffer:
125
125
-
handle_command(command_buffer.strip().lower())
126
126
-
command_buffer = ""
127
127
-
else:
128
128
-
command_buffer += byte
129
129
-
print(byte, end='')
130
130
-
last_serial_check = current_time
131
131
-
132
132
-
# Handle motor stepping
133
133
-
step_motor(motor1, motor1_step)
134
134
-
step_motor(motor2, motor2_step)
+82
firmware/code.py
···
1
1
+
import board
2
2
+
import time
3
3
+
import digitalio
4
4
+
import supervisor
5
5
+
6
6
+
class MotorState:
7
7
+
def __init__(self, step_pin, dir_pin, min_delay=0.001):
8
8
+
self.step_pin = step_pin
9
9
+
self.dir_pin = dir_pin
10
10
+
self.position = 0
11
11
+
self.min_delay = min_delay
12
12
+
13
13
+
def step(self):
14
14
+
self.step_pin.value = True
15
15
+
time.sleep(self.min_delay)
16
16
+
self.step_pin.value = False
17
17
+
time.sleep(self.min_delay)
18
18
+
19
19
+
# Define pins for stepper motors
20
20
+
motor1_step = digitalio.DigitalInOut(board.GP11)
21
21
+
motor1_step.direction = digitalio.Direction.OUTPUT
22
22
+
motor1_dir = digitalio.DigitalInOut(board.GP10)
23
23
+
motor1_dir.direction = digitalio.Direction.OUTPUT
24
24
+
motor2_step = digitalio.DigitalInOut(board.GP8)
25
25
+
motor2_step.direction = digitalio.Direction.OUTPUT
26
26
+
motor2_dir = digitalio.DigitalInOut(board.GP7)
27
27
+
motor2_dir.direction = digitalio.Direction.OUTPUT
28
28
+
enable = digitalio.DigitalInOut(board.GP9)
29
29
+
enable.direction = digitalio.Direction.OUTPUT
30
30
+
31
31
+
# Enable motors
32
32
+
enable.value = False
33
33
+
print("Motors enabled")
34
34
+
35
35
+
STEPS_PER_ROT = 200 * 16 # Steps per rotation
36
36
+
37
37
+
motor1 = MotorState(motor1_step, motor1_dir, 0.0001)
38
38
+
motor2 = MotorState(motor2_step, motor2_dir, 0.0001)
39
39
+
40
40
+
while True:
41
41
+
if supervisor.runtime.serial_bytes_available:
42
42
+
command = input().strip().lower()
43
43
+
parts = command.split()
44
44
+
45
45
+
if len(parts) != 2:
46
46
+
print("Invalid command. Use '[motor#] [position/zero]'")
47
47
+
continue
48
48
+
49
49
+
motor_num = int(parts[0])
50
50
+
target = parts[1]
51
51
+
52
52
+
if motor_num not in [1,2]:
53
53
+
print("Invalid motor number. Use 1 or 2")
54
54
+
continue
55
55
+
56
56
+
motor = motor1 if motor_num == 1 else motor2
57
57
+
58
58
+
try:
59
59
+
if target == "zero":
60
60
+
motor.position = 0
61
61
+
print(f"Motor {motor_num} position zeroed")
62
62
+
continue
63
63
+
64
64
+
target_pos = float(target) * STEPS_PER_ROT
65
65
+
steps = int(target_pos - motor.position)
66
66
+
67
67
+
if steps > 0:
68
68
+
motor.dir_pin.value = True
69
69
+
else:
70
70
+
motor.dir_pin.value = False
71
71
+
steps = -steps
72
72
+
73
73
+
print(f"Moving motor {motor_num} to position {target} rotations...")
74
74
+
75
75
+
for _ in range(steps):
76
76
+
motor.step()
77
77
+
78
78
+
motor.position = target_pos
79
79
+
print(f"Motor {motor_num} movement complete")
80
80
+
81
81
+
except ValueError:
82
82
+
print("Invalid position. Use number or 'zero'")