more class definitions

This commit is contained in:
Mikayla Dobson
2023-04-15 11:35:41 -05:00
parent 338b0756c8
commit 5b9629a2ca
3 changed files with 252 additions and 108 deletions

View File

@@ -1,22 +1,105 @@
"""
MicroPython Library for MCP3008 8-channel ADC with SPI
Datasheet for the MCP3008: https://www.microchip.com/datasheet/MCP3008
This code makes much use of Adafruit's CircuitPython code at
https://github.com/adafruit/Adafruit_CircuitPython_MCP3xxx
adapted for MicroPython.
Tested on the Raspberry Pi Pico.
Thanks, @Raspberry_Pi and @Adafruit, for all you've given us!
"""
import machine
# adapted from MCCP3008 class by @romilly, which was adapted from Adafruit CircuitPython driver
# source: https://github.com/romilly/pico-code/blob/master/src/pico_code/pico/mcp3008/mcp3008.py
class MCP3008:
def __init__(self, spi: machine.SPI, chip_select: machine.Pin, ref_voltage=3.3):
self.chip_select = chip_select
self.chip_select.value(1)
class MCP3008:
def __init__(self, spi, cs, ref_voltage=3.3):
"""
Create MCP3008 instance
Args:
spi: configured SPI bus
cs: pin to use for chip select
ref_voltage: r
"""
self.cs = cs
self.cs.value(1) # ncs on
self._spi = spi
self._out_buffer = bytearray(3)
self._out_buffer[0] = 0x01
self._in_buffer = bytearray(3)
self._out_buf = bytearray(3)
self._out_buf[0] = 0x01
self._in_buf = bytearray(3)
self._ref_voltage = ref_voltage
def get_voltage(self):
def reference_voltage(self) -> float:
"""Returns the MCP3xxx's reference voltage as a float."""
return self._ref_voltage
def read(self, pin, is_differential=False):
"""
read a voltage or voltage difference using the MCP3008.
Args:
pin: the pin to use
is_differential: if true, return the potential difference between two pins,
Returns:
voltage in range [0, 1023] where 1023 = VREF (3V3)
"""
self.cs.value(0) # select
self._out_buf[1] = ((not is_differential) << 7) | (pin << 4)
self._spi.write_readinto(self._out_buf, self._in_buf)
self.cs.value(1) # turn off
return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2]
# And here's the code for the loop-back test.
from machine import Pin, SPI
from time import sleep
spi = SPI(0, sck=Pin(2),mosi=Pin(3),miso=Pin(4), baudrate=100000)
cs = Pin(22, Pin.OUT)
cs.value(1) # disable chip at start
chip = MCP3008(spi, cs)
def loop():
cv_one = chip.read(0)
cv_two = chip.read(1)
cv_three = chip.read(2)
print(f"input one: {cv_one}, input two: {cv_two}, input three: {cv_three}")
sleep(0.01)
cv_one = chip.read(0)
cv_two = chip.read(1)
cv_three = chip.read(2)
print(f"input one: {cv_one}, input two: {cv_two}, input three: {cv_three}")
sleep(0.01)
class Module(MCP3008):
def __init__(self, module_function, spi, cs, ref_voltage=3.3):
super().__init__(spi, cs, ref_voltage)
self.module_function = module_function
def read_all(self):
return {
'pot_one': self.read(0),
'pot_two': self.read(1),
'pot_three': self.read(2),
'pot_four': self.read(3),
'cv_in_one': self.read(4),
'cv_in_two': self.read(5),
'cv_in_three': self.read(6),
'cv_in_four': self.read(7)
}
def read(self, pin):
self.chip_select.value(0)
self._out_buffer[1] = pin << 4
self._spi

231
main.py
View File

@@ -1,7 +1,7 @@
from machine import Pin, ADC, PWM, SPI
from utime import sleep
from random import randint
from math import floor, ceil
from time import sleep
__SYSTEM_PWM_FREQUENCY__ = 1000
@@ -118,6 +118,25 @@ class Hertz:
self.tick_freq = self.ONE_HERTZ * hz
pass
class Oscillator:
def __init__(self, waveform = 'sine', downsampling: int = 0, current_tick: int = 0) -> None:
self.waveform = waveform if waveform in WAVEFORMS else None
self.downsampling = downsampling
self.current_tick = current_tick
self.value = 0
def out(self):
if (self.waveform is 'square'):
self.value = not self.value
else:
current_step = SINE_WAVE[floor(self.current_tick)]
interval = self.downsampling if self.downsampling > 0 else 1
self.current_tick = self.current_tick + interval if self.current_tick + interval < len(SINE_WAVE) else 0
return current_step
def out_u16(self):
return polar_to_u16(self.out())
# basic set of analog input behaviors
class AnalogInput:
def __init__(self, ADC_PIN):
@@ -168,121 +187,145 @@ class DigitalOut:
DEFINITIONS FOR HARDWARE PERIPHERALS
"""
# adapted from MCCP3008 class by @romilly, which was adapted from Adafruit CircuitPython driver
# from MCCP3008 class by @romilly, which was adapted from Adafruit CircuitPython driver
# source: https://github.com/romilly/pico-code/blob/master/src/pico_code/pico/mcp3008/mcp3008.py
class MCP3008:
def __init__(self, spi: SPI, chip_select: Pin, ref_voltage=3.3):
self.chip_select = chip_select
self.chip_select.value(1)
def __init__(self, spi, cs, ref_voltage=3.3):
"""
Create MCP3008 instance
Args:
spi: configured SPI bus
cs: pin to use for chip select
ref_voltage: r
"""
self.cs = cs
self.cs.value(1) # ncs on
self._spi = spi
self._out_buffer = bytearray(3)
self._out_buffer[0] = 0x01
self._in_buffer = bytearray(3)
self._out_buf = bytearray(3)
self._out_buf[0] = 0x01
self._in_buf = bytearray(3)
self._ref_voltage = ref_voltage
def get_voltage(self):
def reference_voltage(self) -> float:
"""Returns the MCP3xxx's reference voltage as a float."""
return self._ref_voltage
def read(self, pin, is_differential=False):
"""
read a voltage or voltage difference using the MCP3008.
Args:
pin: the pin to use
is_differential: if true, return the potential difference between two pins,
Returns:
voltage in range [0, 1023] where 1023 = VREF (3V3)
"""
self.cs.value(0) # select
self._out_buf[1] = ((not is_differential) << 7) | (pin << 4)
self._spi.write_readinto(self._out_buf, self._in_buf)
self.cs.value(1) # turn off
return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2]
def read(self, pin):
self.chip_select.value(0)
self._out_buffer[1] = pin << 4
self._spi.write_readinto(self._out_buffer, self._in_buffer)
self.chip_select.value(1) # turn off
return ((self._in_buffer[1] & 0x03) << 8) | self._in_buffer[2]
class Module:
def __init__(self, mcp3008: MCP3008, out_one: int, out_two: int):
self.chip = mcp3008
self.cv_out_one = PWMOutput(out_one)
self.cv_out_two = PWMOutput(out_two)
def cleanup(self):
self.cv_out_one.set_duty(0)
self.cv_out_two.set_duty(0)
def read_one(self, pin: int):
return self.chip.read(pin)
def read_all(self):
return {
'pot_one': chip.read(0),
'pot_two': chip.read(1),
'pot_three': chip.read(2),
'pot_four': chip.read(3),
'cv_in_one': chip.read(4),
'cv_in_two': chip.read(5),
'cv_in_three': chip.read(6),
'cv_in_four': chip.read(7)
}
class Oscillator:
def __init__(self, waveform = 'sine', downsampling: int = 0, current_tick: int = 0) -> None:
self.waveform = waveform if waveform in WAVEFORMS else None
self.downsampling = downsampling
self.current_tick = current_tick
self.value = 0
def out(self):
if (self.waveform is 'square'):
self.value = not self.value
def loop(self, sleep_interval=0.01, function=None):
if function:
function()
else:
current_step = SINE_WAVE[floor(self.current_tick)]
interval = self.downsampling if self.downsampling > 0 else 1
self.current_tick = self.current_tick + interval if self.current_tick + interval < len(SINE_WAVE) else 0
return current_step
print()
# convert to u16
# cv_in_value = self.chip.read(4) * 64
# print(cv_in_value)
# self.cv_out_one.set_duty(cv_in_value)
class Synthesizer:
# PIN CONFIGURATION
p1 = None # GP0
p2 = None # GP1
# p3 = GND
p4 = None # GP2
p5 = None # GP3
p6 = None # GP4
p7 = None # GP5
# p8 = GND
p9 = None # GP6
p10 = None
p11 = None
p12 = None
# p13 = GND
p14 = None # GP10
p15 = None
p16 = None
p17 = None
# p18 = GND
p19 = None # GP14
p20 = None
p21 = None
p22 = None
# p23 = GND
p24 = None # GP18
p25 = None
p26 = None
p27 = None
# p28 = GND
p29 = None # GP22
# p30 = RUN
p31 = None # GP26, ADC0
p32 = None # GP27, ADC1
# p33 = GND, AGND
p34 = None # GP28, ADC2
p35 = None # ADC_VREF
# p36 = 3v3(out)
# p37 = 3V3_EN
# p38 = GND
# p39 = VSYS
# p40 = VBUS
sleep(sleep_interval)
def __init__(self, config):
self.config = config
gate_out = PWMOutput(15, 0)
voct_out = PWMOutput(16, 0)
class ADSR(Module):
def __init__(self, mcp3008: MCP3008, out_one: int, out_two: int):
super().__init__(mcp3008, out_one, out_two)
# spi = SPI(0, sck=Pin(2), mosi=Pin(3), miso=Pin(4), baudrate=100_000)
# chip_select = Pin(22, Pin.OUT)
# chip_select.value(1)
def loop(self, time_interval=0.01):
if time_interval < 0:
raise Exception("Time interval may not be less than 0")
elif time_interval > 1:
raise Exception("Time interval may not be greater than 1")
# square = Pin(21, Pin.OUT)
# mcp = MCP3008(spi, chip_select)
# only move on to envelope generation when a gate is detected
if self.chip.read(4) is not 0:
# get data and convert to polar
attack = (self.chip.read(0) / 1024)
decay = (self.chip.read(1) / 1024)
sustain = self.chip.read(2) / 1024
release = (self.chip.read(3) / 1024)
cv_one = PWMOutput(16)
led_one = PWMOutput(17)
counter = 0
value = 0
pot = Potentiometer(0)
print(self.chip.read(4))
osc = Oscillator('sine', 32)
attack_steps = floor(attack / time_interval)
while counter < attack_steps:
value = value + time_interval
counter = counter + 1
print(value)
self.cv_out_one.set_duty(floor(value))
timer = 1
sleep_interval = 0.01
decay_steps = floor(decay / time_interval)
while counter < attack_steps + decay_steps:
value = value - time_interval
counter = counter + 1
print(value)
self.cv_out_one.set_duty(floor(value))
sleep(time_interval)
"""
variable initialization and prep for loop
"""
spi = SPI(0, sck=Pin(2),mosi=Pin(3),miso=Pin(4), baudrate=100000)
cs = Pin(22, Pin.OUT)
cs.value(1) # disable chip at start
chip = MCP3008(spi, cs)
module = Module(chip, out_one=14, out_two=15)
adsr = ADSR(chip, out_one=14, out_two=15)
try:
while True:
current_step = polar_to_u16(osc.out())
led_one.set_duty(current_step)
cv_one.set_duty(current_step)
sleep(0.001 + (pot.read_polar() / 32))
adsr.loop()
except KeyboardInterrupt:
module.cleanup()
print("Exiting program...")
led_one.set_duty(0)
cv_one.set_duty(0)

18
sandbox.py Normal file
View File

@@ -0,0 +1,18 @@
def envelope_generator(start=1, target=10, slew_rate=512):
"""
Creates a generator function returning the absolute value differece between
the start and target voltages over the given duration in ms.
"""
cv_diff = abs(target - start)
cur = min(start, target)
_target = max(start, target)
slew_rate = max(slew_rate, 1) # avoid div by zero
env_progress = 1
while cur < _target:
cur = env_progress * cv_diff
yield cur
result = envelope_generator()
print(result)