class SquareOscillator: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, square_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count self._count_freq = count_freq def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still # produces a narrow pulse value = clamp(value, -1, self._max_count) self._sm.put(value) # Converts Hertz to the value the state machine running the PIO # program needs def get_pitch(self, hertz): return int(-1 * (((self._count_freq / hertz) - (self._max_count * 4)) / 4))
class PIOBeep: def __init__(self, sm_id, pin): self.square_sm = StateMachine(0, square_prog, freq=freq, sideset_base=Pin(pin)) #pre-load the isr with the value of max_count self.square_sm.put(max_count) self.square_sm.exec("pull()") self.square_sm.exec("mov(isr, osr)") #note - based on current values of max_count and freq # this will be slightly out because of the initial mov instructions, #but that should only have an effect at very high frequencies def calc_pitch(self, hertz): return int(-1 * (((1000000 / hertz) - 20000) / 4)) def play_value(self, note_len, pause_len, val): self.square_sm.active(1) self.square_sm.put(val) sleep(note_len) self.square_sm.active(0) sleep(pause_len) def play_pitch(self, note_len, pause_len, pitch): self.play_value(note_len, pause_len, self.calc_pitch(pitch))
class PIOPWM: def __init__(self, sm_id, pin, count_freq, max_count=(1 << 16) - 1): print(pin) self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count self._pin = pin def _set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse if value>self._max_count: self._sm.active(0) print("off: ", value) Pin(self._pin, Pin.OUT).value(1) else: if not(self._sm.active()): self._sm.put(self._max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) print("on: ", value) value = max(value, -1) value = min(value, self._max_count) self._sm.put(value) def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) print(value) self._sm.put(value)
class WS2812(): def __init__(self, pin, num): # Configure the number of WS2812 LEDs. self.led_nums = num self.pin = pin self.sm = StateMachine(0, ws2812, freq=8000000, sideset_base=self.pin) # Start the StateMachine, it will wait for data on its FIFO. self.sm.active(1) self.buf = array.array("I", [0 for _ in range(self.led_nums)]) def write(self): self.sm.put(self.buf, 8) def write_all(self, value): for i in range(self.led_nums): self.__setitem__(i, value) self.write() def list_to_hex(self, color): if isinstance(color, list) and len(color) == 3: c = (color[0] << 8) + (color[1] << 16) + (color[2]) return c elif isinstance(color, int): value = (color & 0xFF0000) >> 8 | (color & 0x00FF00) << 8 | ( color & 0x0000FF) return value else: raise ValueError( "Color must be 24-bit RGB hex or list of 3 8-bit RGB") def hex_to_list(self, color): if isinstance(color, list) and len(color) == 3: return color elif isinstance(color, int): r = color >> 8 & 0xFF g = color >> 16 & 0xFF b = color >> 0 & 0xFF return [r, g, b] else: raise ValueError( "Color must be 24-bit RGB hex or list of 3 8-bit RGB") def __getitem__(self, i): return self.hex_to_list(self.buf[i]) def __setitem__(self, i, value): value = self.list_to_hex(value) self.buf[i] = value
class PIOPWM: def __init__(self, sm_id, pin, max_count, count_freq): self._sm = StateMachine(sm_id, pwm_prog, freq=2 * count_freq, sideset_base=Pin(pin)) # Use exec() to load max count into ISR self._sm.put(max_count) self._sm.exec("pull()") self._sm.exec("mov(isr, osr)") self._sm.active(1) self._max_count = max_count def set(self, value): # Minimum value is -1 (completely turn off), 0 actually still produces narrow pulse value = max(value, -1) value = min(value, self._max_count) self._sm.put(value)
def button2_handler(pin): @asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def ws2812(): T1 = 2 T2 = 5 T3 = 3 label("bitloop") out(x, 1).side(0)[T3 - 1] jmp(not_x, "do_zero").side(1)[T1 - 1] jmp("bitloop").side(1)[T2 - 1] label("do_zero") nop().side(0)[T2 - 1] # Create the StateMachine with the ws2812 program, outputting on Pin(22). sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(28)) # Start the StateMachine, it will wait for data on its FIFO. sm.active(1) for i in up: buzzer.freq(i) buzzer.duty_u16(19660) utime.sleep(0.15) buzzer.duty_u16(0) utime.sleep(0.5) ar = array.array("I", [0 for _ in range(NUM_LEDS)]) ar[0] = 100 sm.put(ar, 8) time.sleep_ms(500) ar[0] = 100 << 8 sm.put(ar, 8) time.sleep_ms(500) ar[0] = 100 << 16 sm.put(ar, 8) time.sleep_ms(500) ar[0] = 0 sm.put(ar, 8)
mov(y, osr) # step pattern pull() mov(x, osr) # num steps jmp(not_x, "end") label("loop") jmp(not_osre, "step") # loop pattern if exhausted mov(osr, y) label("step") out(pins, 4)[31] nop()[31] nop()[31] nop()[31] jmp(x_dec, "loop") label("end") set(pins, 8)[31] # 8 sm = StateMachine(0, prog, freq=10000, set_base=Pin(2), out_base=Pin(2)) sm.active(1) sm.put(2216789025) #1000 0100 0010 0001 1000010000100001 sm.put(1000) sleep(5) sm.active(0) sm.exec("set(pins,0)")
# Create the StateMachine with the ws2812 program, outputting on Pin(0). sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(0)) # Start the StateMachine, it will wait for data on its FIFO. sm.active(1) # Display a pattern on the LEDs via an array of LED RGB values. ar = array.array("I", [0 for _ in range(NUM_LEDS)]) print("blue") for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = j sm.put(ar,8) utime.sleep_ms(10) print("red") for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = j<<8 sm.put(ar,8) utime.sleep_ms(10) print("green") for j in range(0, 255): for i in range(NUM_LEDS): ar[i] = j<<16
class neopixel: ########### Variables ########### numLED = 1 # Number of LEDs in series dataPin = 22 # DIN Pin on RP2040 def RGB(R,G,B): return int(R<<16 | G <<8 | B) # Color definitions BLACK = RGB(0,0,0) WHITE = RGB(255,255,255) RED = RGB(255,0,0) GREEN = RGB(0,255,0) BLUE = RGB(0,0,255) YELLOW = RGB(255,255,0) MAGENTA = RGB(255,0,255) CYAN = RGB(0,255,255) COLORS = [BLACK, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, WHITE] # Placeholders dataArray = None stateMachine = None brightnessOffset = 1 ########### Functions ########### # State Machine Assembly for sending the bitstream to LEDs @asm_pio(sideset_init=PIO.OUT_LOW, out_shiftdir=PIO.SHIFT_LEFT, autopull=True, pull_thresh=24) def driver(): T1 = 2 T2 = 5 T3 = 3 label("bitloop") out(x, 1) .side(0) [T3 - 1] jmp(not_x, "do_zero") .side(1) [T1 - 1] jmp("bitloop") .side(1) [T2 - 1] label("do_zero") nop() .side(0) [T2 - 1] # Constructor def __init__(self, LEDS=1, PIN=22): self.numLED = LEDS self.dataPin = PIN # Create the State Machine with the driver program. self.stateMachine = StateMachine(0, self.driver, freq=8000000, sideset_base=Pin(self.dataPin)) # Start the StateMachine self.stateMachine.active(1) # Create data buffer for holding RGB Values self.dataArray = array.array("I", [0 for _ in range(self.numLED)]) # Set single or all LEDs def set(self, LED_NUMBER=None, R=0xFF, G=0xFF, B=0xFF, COLOR=None, brightness=1): self.brightnessOffset = brightness if(LED_NUMBER==None): if(COLOR==None): for LED_NUMBER in range(self.numLED): self.dataArray[LED_NUMBER] = int(self.brightnessOffset * (R<<8 | G <<16 | B)) else: for LED_NUMBER in range(self.numLED): self.dataArray[LED_NUMBER] = int(self.brightnessOffset *(((COLOR&0xFF0000)>>8) | ((COLOR&0xFF00)<<8) | ((COLOR&0xFF)))) else: if(COLOR==None): self.dataArray[LED_NUMBER] = int(self.brightnessOffset * (R<<8 | G <<16 | B)) else: self.dataArray[LED_NUMBER] = int(self.brightnessOffset * (((COLOR&0xFF0000)>>8) | ((COLOR&0xFF00)<<8) | ((COLOR&0xFF)))) self.stateMachine.put(self.dataArray,8) # Reset Given or All LED def reset(self, LED_NUMBER=None): if(LED_NUMBER==None): for LED_NUMBER in range(self.numLED): self.dataArray[LED_NUMBER] = 0 self.stateMachine.put(self.dataArray,8) else: self.dataArray[LED_NUMBER] = 0 self.stateMachine.put(self.dataArray,8) # Change Brightness of Single or All LEDs def setBrightness(self, LED_NUMBER=None, brightness=1): self.brightnessOffset = brightness if(LED_NUMBER==None): for LED_NUMBER in range(self.numLED): self.dataArray[LED_NUMBER] = int(brightness * self.dataArray[LED_NUMBER]) else: self.dataArray[LED_NUMBER] = int(brightness * self.dataArray[LED_NUMBER]) self.stateMachine.put(self.dataArray,8) # For testing individual LEDs def test(self): for j in range(0,self.numLED): for i in range(0,len(self.COLORS)): self.setLED(LED_NUMBER=j, COLOR=self.COLORS[i]) time.sleep_ms(500) self.resetALL()
class DHT(object): def __init__(self, pin: Pin, state_machine_id: int = 0, min_interval: int = 2000): """ Create a DHT object to get communication and get data from DHT sensor. :param pin: Pin connected to DHT's data pin :param state_machine_id: State Machine ID, default value 1 :param min_interval: Minimum interval between communication with DHT, default value 2000 (for DHT22) :type pin: machine.Pin :type state_machine_id: int :type min_interval: int """ self._pin = pin self._last_pull_time = None self._temperature = None self._humidity = None self._min_interval = min_interval # 1 cycle should be 10 us, 1s = 1,000,000us so freq should be 100,000 self._sm = StateMachine(state_machine_id, dht_get_data, freq=100000, set_base=pin) self._sm.irq(handle_dht_irq) self._sm.active(1) def _get_data_from_sensor(self, force: bool = False): if force or self._last_pull_time is None or \ fabs(ticks_diff(ticks_ms(), self._last_pull_time)) > self._min_interval: global _irq_count, temp_data _irq_count = 0 for i in range(5): temp_data[i] = 0 # start state machine self._sm.put(0) # Wait for state machine work utime.sleep_ms(20) if _irq_count != 5: print( "Didn't receive enough data. Received {} byte(s).".format( len(temp_data))) return # data validation, 1st byte + 2nd byte + 3rd byte + 4th byte == 5th byte (last 8 bits) check_sum = (temp_data[0] + temp_data[1] + temp_data[2] + temp_data[3]) & EIGHT_1_BIT_MASK if check_sum != temp_data[4]: print('Data validation error.') return # temperature data is last 15 bits, first bit if 1, is negative. data is 10x of actual value raw_temperature = ( (temp_data[2] & SEVEN_1_BIT_MASK) << 8) + temp_data[3] self._temperature = raw_temperature / 10 if temp_data[2] >> 7 == 1: self._temperature *= -1 raw_humidity = (temp_data[0] << 8) + temp_data[1] # humidity data is 10x of actual value self._humidity = raw_humidity / 10 self._last_pull_time = ticks_ms() def get_temperature(self, force: bool = False) -> float: """ Get temperature from DHT :param force: Force communicate with DHT sensor :type force: bool :return: Last measured temperature :rtype: float """ self._get_data_from_sensor(force) return self._temperature def get_humidity(self, force: bool = False) -> float: """ Get humidity from DHT :param force: Force communicate with DHT sensor :type force: bool :return: Last measured humidity :rtype: float """ self._get_data_from_sensor(force) return self._humidity def get_temperature_and_humidity(self, force: bool = False) -> (float, float): """ Get temperature and humidity from DHT :param force: Force communicate with DHT sensor :type force: bool :return: Last measured temperature and humidity :rtype: (float, float) """ self._get_data_from_sensor(force) return self._temperature, self._humidity
# parallel byte from data from machine import Pin from rp2 import PIO, StateMachine, asm_pio from utime import sleep @asm_pio(out_init=(rp2.PIO.OUT_HIGH, ) * 8, out_shiftdir=PIO.SHIFT_RIGHT, autopull=True, pull_thresh=16) def paral_prog(): pull out(pins, 8) sm = StateMachine(0, paral_prog, freq=10000000, out_base=Pin(0)) sm.active(1) while True: for i in range(500): sm.put(i) # print(i) # sleep(0.01)
# Y gets a value of 500. Say a value of 200 is put to the OSR (then X) # via the put() command. In each instance of the asm codeexecution, # the asm code will first set the pin low, then decrement Y by 1 in a loop # until y matches x. When y = x = 200, line 14 is called once, setting # the pin high. With the pin set high, y continues to decrement by 1 until 0. # Then the asm is repeated and the pin is set to low again. Therefore, # setting x to 200 will result the pin to be high 200/500 of the times, # corresponding to a 40% duty cycle. # State Machine init pwm_sm = StateMachine(0, pwm_prog, freq=10000000, sideset_base=Pin(16)) # State Machine pwm_sm.put(max_count) # Put data in output FIFO pwm_sm.exec("pull()") pwm_sm.exec("mov(isr, osr)") # Load val into ISR pwm_sm.active(1) # PWM Test #while True: # for i in range(max_count): # pwm_sm.put(i) # sleep(0.001) # for i in range(max_count): # pwm_sm.put(max_count - i) # sleep(0.001) # Jerkky Motion # pwm_sm.put(0)
@asm_pio(sideset_init=PIO.OUT_LOW) def pwm_prog(): pull(noblock).side(0) mov(x, osr) mov(y, isr) label("pwmloop") jmp(x_not_y, "skip") nop().side(1) label("skip") jmp(y_dec, "pwmloop") pwm_sm = StateMachine(0, pwm_prog, freq=10000000, sideset_base=Pin(25)) pwm_sm.put(max_count) pwm_sm.exec("pull()") pwm_sm.exec("mov(isr, osr)") pwm_sm.active(1) def sweep_up(): for i in range(500): pwm_sm.put(i) sleep(0.001) def sweep_down(): for i in range(500, 0, -1): pwm_sm.put(i) sleep(0.001)
#mirror the above loop, but with the pin high to form the second #half of the square wave label("down") mov(y, isr) label("down_loop") jmp(x_not_y, "skip_down") nop() .side(0) jmp("restart") label("skip_down") jmp(y_dec, "down_loop") square_sm = StateMachine(0, square_prog, freq=freq, sideset_base=Pin(0)) #pre-load the isr with the value of max_count square_sm.put(max_count) square_sm.exec("pull()") square_sm.exec("mov(isr, osr)") #note - based on current values of max_count and freq # this will be slightly out because of the initial mov instructions, #but that should only have an effect at very high frequencies def calc_pitch(hertz): return int( -1 * (((1000000/hertz) -20000)/4)) notes = [392, 440, 494, 523, 587, 659, 698, 784] notes_val = [] for note in notes: notes_val.append(calc_pitch(note))
@asm_pio( out_init = (rp2.PIO.OUT_LOW,) * 8, # initialize 8 consecutive pins out_shiftdir = rp2.PIO.SHIFT_RIGHT) # output lsb bits first def parallel_prog(): pull(block) # pull data from Tx FIFO. Wait for data out(pins, 8) # send 8 bits from OSR to pins # create an instance of the state machine sm = StateMachine(0, parallel_prog, freq=1000000, out_base=Pin(0)) # start the state machine sm.active(1) for n in range(256): sm.put(n) time.sleep(0.01) %serialconnect from machine import Pin import time from rp2 import PIO, StateMachine, asm_pio # decorator to translate to PIO machine code @asm_pio( out_init = (rp2.PIO.OUT_LOW,) * 4, # initialize 8 consecutive pins out_shiftdir = rp2.PIO.SHIFT_RIGHT) # output lsb bits first def stepper_step():
## from machine import Pin import time import rp2 from rp2 import PIO, StateMachine, asm_pio @asm_pio(out_init=rp2.PIO.OUT_LOW) def count_blink(): pull(block) set(pins, 1)[19] nop()[19] nop()[19] nop()[19] nop()[19] set(pins, 0)[19] nop()[19] nop()[19] nop()[19] nop()[19] # create an instance of the state machine sm0 = StateMachine(0, count_blink, freq=2000, out_base=Pin(0)) # start the state machine sm0.active(1) sm0.put(1) time.sleep(2) sm0.active(0)