Skip to content

Instantly share code, notes, and snippets.

@teddokano
Last active July 8, 2023 08:58
Show Gist options
  • Save teddokano/4571d26e0a3f1228938fdc665148275e to your computer and use it in GitHub Desktop.
Save teddokano/4571d26e0a3f1228938fdc665148275e to your computer and use it in GitHub Desktop.
PCA9955B control by audio envelope
from machine import Pin, ADC, Timer
import utime
import sys
from machine import I2C
from nxp_periph import PCA9955B, LED, PCA9629A
if "MicroPython v1.19" in sys.version:
TIMER_ID = 0
else:
TIMER_ID = -1
class periodic_adc:
def __init__( self, pin_name = "A0", *, interval = 10, scaling = (2 ** 16) ):
self.timer_flag = False
self.adc = ADC( Pin( pin_name ) )
self.scaling = scaling
self.interval = interval
self.tim = Timer( TIMER_ID )
self.tim.init( period = interval, mode = Timer.PERIODIC, callback = self.timer_callback )
def read( self, blocking = True ):
if blocking:
while not self.timer_flag:
pass
self.timer_flag = False
return self.adc.read_u16() / self.scaling
def timer_callback( self, _ ):
self.timer_flag = True
class peak_detect( periodic_adc ):
def __init__( self, pin_name = "A0", *, interval = 10, scaling = (2 ** 16), threshold_half_life = 350, ignore_interval = 200, squelch = 0.02 ):
super().__init__( interval = interval, scaling = scaling )
self.det_lev_decay = 0.5 ** (1 / (threshold_half_life / interval))
self.det_ignore_interval = ignore_interval / interval
self.squelch = squelch
self.count = 0
self.ref_level = 0
self.last_count = 0
self.det = False
def detect( self, level = None ):
if level is None:
level = self.read()
if self.count < self.det_ignore_interval:
self.count += 1
self.det = False
return self.det
if (self.ref_level < level) and (self.squelch < level):
self.last_count = self.count
self.count = 0
self.det = True
self.ref_level = level
print( self.last_count )
else:
self.count += 1
self.det = False
self.ref_level *= self.det_lev_decay
return self.det
class motor:
def __init__( self, i2c ):
self.motor = PCA9629A( i2c, address = 0xE0 >> 1 )
self.direction = False
self.motor.stop()
self.motor.home()
utime.sleep( 2 )
self.motor.drv_phase( 2 ) # 0.5 = half_step, 1 = 1_phase, 2 = 2_phase
self.motor.pps( 96 )
self.motor.pps( 96, reverse = True )
self.motor.steps( 192 * 5 )
self.motor.steps( 192 * 5, reverse = True )
def start( self ):
self.motor.start()
def invert( self ):
self.direction = False if self.direction else True
self.motor.stop()
self.motor.start( reversr = self.direction )
def main():
i2c = I2C( 0, freq = (400 * 1000) )
led_c = PCA9955B( i2c, 0xEC >>1, iref = 0xFF )
leds = [ LED( led_c, i ) for i in range( led_c.CHANNELS ) ]
peak = peak_detect( "A0", interval = 10, threshold_half_life = 350, ignore_interval = 200 )
enabling_channel = [ x for x in range( 16 ) ]
groups = [ [ 1, 6, 11, 13 ], [ 2, 7, 9, 14 ], [ 3, 5, 10, 15 ], [ 0, 4, 8, 12 ] ]
all = [ 1.0 for i in range( led_c.CHANNELS ) ]
led_c.pwm( all )
led_c.gradation_channel_enable( enabling_channel )
led_c.gradation_group_assign( groups )
ramp_time = 1.0
off_time = ramp_time
# RGB gradation on group 0, 1, 2
rgb_cycle_time = led_c.set_gradation( 0, 1.0, ramp_time, up = True, down = True, on = 0, off = off_time )
led_c.set_gradation( 1, 1.0, ramp_time, up = True, down = True, on = 0, off = off_time )
led_c.set_gradation( 2, 1.0, ramp_time, up = True, down = True, on = 0, off = off_time )
print( f"rgb_cycle_time = {rgb_cycle_time}" )
# White gradation on group 3
white_cycle_time = led_c.set_gradation( 3, 1, 0.3, up = False, down = True, on = 0, off = 0 )
led_c.gradation_start( 0 )
utime.sleep( rgb_cycle_time / 3 )
led_c.gradation_start( 1 )
utime.sleep( rgb_cycle_time / 3 )
led_c.gradation_start( 2 )
vp = 0
while True:
if peak.detect():
led_c.gradation_stop( 3 )
led_c.gradation_start( 3, continuous = False )
vp = 1.0
led_c.write_registers( "PWMALL", int( vp * 255.0 ) )
vp *= 0.9
vp = 0.1 if vp < 0.1 else vp
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment