Exemple #1
0
class NRF24L01:

    SCK = 5
    MOSI = 4
    MISO = 0

    def __init__(self, ce, csn, spi=None, baudrate=400000, payload_size=16):
        self._csn = Pin(csn) if type(csn) == int else csn
        self._ce = Pin(ce) if type(ce) == int else ce
        self._payload_size = payload_size
        self._spi = spi

        self._init_spi(baudrate)

        self._ce.init(Pin.OUT, value=0)
        self._csn.init(Pin.OUT, value=1)

        self._buf = bytearray(1)
        self._write_reg(SETUP_AW, FIVE_BYTE_ADDRESS)
        if self._read_reg(SETUP_AW) != FIVE_BYTE_ADDRESS:
            print('Failed to set address width!')

        self._flush_tx()
        self._flush_rx()

    def _write_reg(self, reg, data):
        self._csn(0)
        self._spi.readinto(self._buf, 0x20 | reg)
        ret = self._buf[0]
        self._spi.readinto(self._buf, data)
        self._csn(1)
        return ret

    def _write_reg_bytes(self, reg, data):
        self._csn(0)
        self._spi.readinto(self._buf, 0x20 | reg)
        self._spi.write(data)
        self._csn(1)
        return self._buf[0]

    def _read_reg(self, reg):
        self._csn(0)
        self._spi.readinto(self._buf, 0x00 | reg)
        self._spi.readinto(self._buf)
        self._csn(1)
        return self._buf[0]

    def read_reg(self, reg):
        return bin(self._read_reg(reg))

    def _init_spi(self, baudrate):
        if self._spi is None:
            self._spi = SoftSPI(baudrate=baudrate, polarity=0, phase=0,
                                sck=Pin(self.SCK), mosi=Pin(self.MOSI),
                                miso=Pin(self.MISO))
        self._spi.init(baudrate=baudrate)

    def _flush_rx(self):
        self._csn(0)
        self._spi.readinto(self._buf, FLUSH_RX)
        self._csn(1)

    def _flush_tx(self):
        self._csn(0)
        self._spi.readinto(self._buf, FLUSH_TX)
        self._csn(1)

    def set_channel(self, channel):
        self._write_reg(RF_CH, channel)

    def set_speed(self, speed):
        self._write_reg(RF_SETUP, self._read_reg(RF_SETUP) | speed)

    def set_power(self, power):
        self._write_reg(RF_SETUP, self._read_reg(RF_SETUP) | power)

    def _get_address(self, address):
        # Ensure that address is in byte-format
        if type(address) == list:
            address = bytes(address)
        elif type(address) == str:
            address = binascii.unhexlify(address)
        return address

    # Set both RX and TX address to the given value.
    # Default pipe used is PIPE 0
    def open_tx_pipe(self, address):
        address = self._get_address(address)

        self._write_reg_bytes(RX_ADDR_P0, address)
        self._write_reg_bytes(TX_ADDR, address)
        # Must enable RX pipe by writing data-length to it (CAN'T be 0)
        self._write_reg(RX_PW_P0, self._payload_size)
        self._ce(0)


    # Default pipe is PIPE 0
    def open_rx_pipe(self, address):
        address = self._get_address(address)
        # Set RX address
        self._write_reg_bytes(RX_ADDR_P0, address)
        # Nbr of bytes in RX payload
        self._write_reg(RX_PW_P0, self._payload_size)
        # Enable RX
        self._write_reg(EN_RXADDR, self._read_reg(EN_RXADDR) | ERX_P0)

        self._write_reg(EN_AA, self._read_reg(EN_AA) & ~ENAA_P0)

    def enable_auto_ack(self):
        self._write_reg(EN_AA, self._read_reg(EN_AA) | ENAA_P0)

    # The parameter crc is the ammount of bytes to be used.
    # Only 1 or 2 is accepted.
    def set_crc(self, crc):
        # read config reg (wihtout the current CRC value)
        config = self._read_reg(CONFIG) & ~CRC
        if crc == 1:
            config |= CRC_ENA
        elif crc == 2:
            config |= CRC_ENA | CRC
        self._write_reg(CONFIG, config)

    def start_listening(self):
        # Power-up and enable RX
        self._write_reg(CONFIG, self._read_reg(CONFIG) | PWR_UP | PRIM_RX)
        self._write_reg(STATUS,
                        self._read_reg(STATUS) | RX_DR | TX_DS | MAX_RT)

        # Flush fifos and set CE HIGH to start listening.
        self._flush_rx()
        self._flush_tx()
        self._ce(1)

    def stop_listening(self):
        self._ce(0)
        self._flush_rx()
        self._flush_tx()

    def read(self):
        # Read the data from the payload reg
        self._ce(0)
        self._csn(0)            # R_RX_PAYLOAD = 0x61
        self._spi.readinto(self._buf, 0x61)
        data = self._spi.read(self._payload_size)

        # Must toggle CE here as well, to disable receiver temporarly
        self._ce(1)
        self._csn(1)

        # Clear RX ready flag when done
        self._write_reg(STATUS, self._read_reg(STATUS) | RX_DR)
        return data

    def send(self, buf, timeout=500):
        self._send_start(buf)
        start = time.ticks_ms()
        result = None
        while (result is None and
               time.ticks_diff(time.ticks_ms(), start) < timeout):
            result = self._send_done()

        print('result: %s' % result)

    def _send_done(self):
        status = self._read_reg(STATUS)
        if not (status & (TX_DS | MAX_RT)):
            # Haven't finished yet
            return None

        # Transmission is over, clear the interrupt bits in the status-reg
        self._write_reg(STATUS, status | RX_DR | TX_DS | MAX_RT)

        if status & TX_DS:
            # Successfull send
            return 1
        else:
            # MAX attempts have passed, return 2 to indicate failure
            return 2

    def _send_start(self, buf):
        # Power-up and enable TX
        self._write_reg(CONFIG, (self._read_reg(CONFIG) | PWR_UP) & ~PRIM_RX)
        time.sleep_us(200)

        # Send the data
        self._csn(0)             # W_TX_PAYLOAD = 0xA0
        self._spi.readinto(self._buf, 0xA0)
        self._spi.write(buf)
        # Need to pad the rest of the packet if data ist too small.
        if len(buf) < self._payload_size:
            self._spi.write(b'\x00' * (self._payload_size - len(buf)))

        self._csn(1)

        # Toggle the ce-signal to send that data
        self._ce(1)
        time.sleep_us(15)   # MINIMUM 10 us according to datasheet
        self._ce(0)

    def close(self):
        self._spi.deinit()
adc.atten(ADC.ATTN_11DB)  # set 11dB input attenuation (voltage range roughly 0.0v - 3.6v)
adc.width(ADC.WIDTH_9BIT)  # set 9 bit return values (returned range 0-511)
adc.read()  # read value using the newly configured attenuation and width


# Software SPI bus


from machine import Pin, SoftSPI

# construct a SoftSPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SoftSPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))

spi.init(baudrate=200000)  # set the baudrate

spi.read(10)  # read 10 bytes on MISO
spi.read(10, 0xFF)  # read 10 bytes while outputting 0xff on MOSI

buf = bytearray(50)  # create a buffer
spi.readinto(buf)  # read into the given buffer (reads 50 bytes in this case)
spi.readinto(buf, 0xFF)  # read into the given buffer and output 0xff on MOSI

spi.write(b"12345")  # write 5 bytes on MOSI

buf = bytearray(4)  # create a buffer
spi.write_readinto(b"1234", buf)  # write to MOSI and read from MISO into the buffer
spi.write_readinto(buf, buf)  # write buf to MOSI and read MISO back into buf

# Hardware SPI