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 __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 __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 __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)")
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)
class DHT11_PIO: def __init__(self, data_pin): pin = Pin(data_pin, Pin.IN, Pin.PULL_UP) self.sm = StateMachine(0) self.sm.init(DHT11, freq=500000, set_base=pin, in_base=pin) self.start = SmAddr(0) def read(self): # Reset the state machine to start a fresh transaction SmRestart(0) SmExec(0, self.start) # Activate the state machine and then sleep until it should be complete self.sm.active(1) utime.sleep_ms(20) self.sm.active(0) # Exception if the amount of data is wrong if SmRxLevel(0) != 2: while SmRxLevel(0): self.sm.get() raise Timeout() # Read back the data from the Rx FIFO as data = self.sm.get() data = (data << 20) + self.sm.get() # Calculate and check checksum if (sum(data >> i * 8 for i in range(1, 5)) - data) & 255: raise BadChecksum() return self.decode(data) def decode(self, data): humidity = (data >> 32 ) & 255 #DHT11 provides integer humidity (no decimal part) temperature = ( data >> 16 ) & 255 #DHT11 provides signed integer temperature (no decimal part) return humidity, temperature
def f2b(f): sm = StateMachine(3, nop, freq=f) print(sm.active()) sm.active(0) return mem32[SM3_CLKDIV]
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,) * 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
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
@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 progam, putputting on Pin(15) sm = StateMachine(0, ws2812, freq=8000000, sideset_base=Pin(15)) # Start the StateMachine, it will wait for datat on its FIFO sm.active(1) ar = array.array("I", [0 for _ in range(NUM_LEDS)]) button = machine.Pin(16, machine.Pin.IN) MODE = 0 button_count = 0 modes = [ random_twinkle, rainbow_spin,
#setup waveform. frequency is 125MHz/nsamp nsamp = 100 #must be a multiple of 4 wave = array("I", [0] * nsamp) for isamp in range(nsamp): val = 128 + 127 * sin((isamp + 0.5) * 2 * pi / nsamp) #sine wave #val=isamp*255/nsamp #sawtooth #val=abs(255-isamp*510/nsamp) #triangle #val=int(isamp/20)*20*255/nsamp #stairs wave[int(isamp / 4)] += (int(val) << ((isamp % 4) * 8)) #start sm = StateMachine(0, stream, freq=1250000, out_base=Pin(10)) sm.active(1) startDMA(wave, int(nsamp / 4)) sleep(3) sm.active(0) sm = StateMachine(1, stream, freq=125000, out_base=Pin(10)) sleep(0.5) sm.active(1) sleep(1) sm.active(0) #sm = StateMachine(0, stream, freq=12500000, out_base=Pin(10)) #sm.active(1) #sleep(1) #sm.active(0) #processor free to do anything else
# 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)
nop().side(1) label("skip") jmp(y_dec, "pwmloop") # 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)
max_count = 500 @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)
def __init__(self, data_pin): pin = Pin(data_pin, Pin.IN, Pin.PULL_UP) self.sm = StateMachine(0) self.sm.init(DHT11, freq=500000, set_base=pin, in_base=pin) self.start = SmAddr(0)
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))
jmp("down") label("skip_up") jmp(y_dec, "uploop") #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]