Ejemplo n.º 1
0
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))
Ejemplo n.º 2
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))
Ejemplo n.º 3
0
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)
Ejemplo n.º 4
0
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
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
    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)")
Ejemplo n.º 8
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
Ejemplo n.º 9
0
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()
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
# 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)
Ejemplo n.º 12
0

# 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)
Ejemplo n.º 14
0
    
    #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))
Ejemplo n.º 15
0
@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():
Ejemplo n.º 16
0
##
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)