-
Notifications
You must be signed in to change notification settings - Fork 469
/
inventor.py
151 lines (118 loc) · 3.66 KB
/
inventor.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
import gc
from machine import Pin, PWM
from pimoroni_i2c import PimoroniI2C
from plasma import WS2812
from motor import Motor
from servo import Servo
from encoder import Encoder, MMME_CPR
# IO Pin Constants
GP0 = 0
GP1 = 1
GP2 = 2
A0 = 26
A1 = 27
A2 = 28
GPIOS = (GP0, GP1, GP2, A0, A1, A2)
ADCS = (A0, A1, A2)
# Index Constants
MOTOR_A = 0
MOTOR_B = 1
SERVO_1 = 0
SERVO_2 = 1
SERVO_3 = 2
SERVO_4 = 3
SERVO_5 = 4
SERVO_6 = 5
LED_GP0 = 0
LED_GP1 = 1
LED_GP2 = 2
LED_A0 = 3
LED_A1 = 4
LED_A2 = 5
LED_SERVO_1 = 6
LED_SERVO_2 = 7
LED_SERVO_3 = 8
LED_SERVO_4 = 9
LED_SERVO_5 = 10
LED_SERVO_6 = 11
# Count Constants
NUM_GPIOS = 6
NUM_ADCS = 3
NUM_MOTORS = 2
NUM_SERVOS = 6
NUM_LEDS = 12
class Inventor2040W():
AMP_EN_PIN = 3
I2C_SDA_PIN = 4
I2C_SCL_PIN = 5
MOTOR_A_PINS = (6, 7)
MOTOR_B_PINS = (8, 9)
ENCODER_A_PINS = (19, 18)
ENCODER_B_PINS = (17, 16)
SERVO_1_PIN = 10
SERVO_2_PIN = 11
SERVO_3_PIN = 12
SERVO_4_PIN = 13
SERVO_5_PIN = 14
SERVO_6_PIN = 15
LED_DATA_PIN = 20
PWM_AUDIO_PIN = 21
USER_SW_PIN = 22
AMP_CORRECTION = 4
DEFAULT_VOLUME = 0.2
def __init__(self, motor_gear_ratio=50, init_motors=True, init_servos=True):
# Free up hardware resources
gc.collect()
# Set up the motors and encoders, if the user wants them
self.motors = None
if init_motors:
cpr = MMME_CPR * motor_gear_ratio
self.motors = [Motor(self.MOTOR_A_PINS), Motor(self.MOTOR_B_PINS)]
# Set the encoders to use PIO 0 and State Machines 0 and 1
self.encoders = [Encoder(0, 0, self.ENCODER_A_PINS, counts_per_rev=cpr, count_microsteps=True),
Encoder(0, 1, self.ENCODER_B_PINS, counts_per_rev=cpr, count_microsteps=True)]
# Set up the servos, if the user wants them
self.servos = None
if init_servos:
self.servos = [Servo(i) for i in range(self.SERVO_1_PIN, self.SERVO_6_PIN + 1)]
# Set up the i2c for Qw/st and Breakout Garden
self.i2c = PimoroniI2C(self.I2C_SDA_PIN, self.I2C_SCL_PIN, 100000)
# Set up the amp enable
self.__amp_en = Pin(self.AMP_EN_PIN, Pin.OUT)
self.__amp_en.off()
self.audio_pwm = PWM(Pin(self.PWM_AUDIO_PIN))
self.__volume = self.DEFAULT_VOLUME
# Set up the user switch
self.__switch = Pin(self.USER_SW_PIN, Pin.IN, Pin.PULL_DOWN)
# Set up the WS2812 LEDs, using PIO 0 and State Machine 2
self.leds = WS2812(NUM_LEDS, 0, 2, self.LED_DATA_PIN)
self.leds.start()
def switch_pressed(self):
return self.__switch.value()
def play_tone(self, frequency):
try:
self.audio_pwm.freq(frequency)
except ValueError:
self.play_silence()
raise ValueError("frequency of range. Expected greater than 0")
corrected_volume = (self.__volume ** 4) # Correct for RC Filter curve
self.audio_pwm.duty_u16(int(32768 * corrected_volume))
self.unmute_audio()
def play_silence(self):
self.audio_pwm.freq(44100)
corrected_volume = (self.__volume ** 4) # Correct for RC Filter curve
self.audio_pwm.duty_u16(int(32768 * corrected_volume))
self.unmute_audio()
def stop_playing(self):
self.audio_pwm.duty_u16(0)
self.mute_audio()
def volume(self, volume=None):
if volume is None:
return self.__volume
if volume < 0.01 or volume > 1.0:
raise ValueError("volume out of range. Expected 0.0 to 1.0")
self.__volume = volume
def mute_audio(self):
self.__amp_en.off()
def unmute_audio(self):
self.__amp_en.on()