Giter Club home page Giter Club logo

Comments (17)

ladyada avatar ladyada commented on July 21, 2024

its probably due to the weird way we use the SPI peripheral locking & CS lines. i can fix if i get some example code

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

Do you just want the code that fails -- here is an example -- If you leave the first temperature reading comment out, it will fails and the temperature will be corrupted -- If you read it twice - the second reading is OK.

import board
import busio
import digitalio
import adafruit_rfm9x
import adafruit_lsm9ds1
from digitalio import DigitalInOut, Direction
import time

RADIO_FREQ_MHZ   = 915.0

CS    = digitalio.DigitalInOut(board.D24)
RESET = digitalio.DigitalInOut(board.D17)

spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

csag = DigitalInOut(board.D21)
csm = DigitalInOut(board.D20)

rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ)
sensor = adafruit_lsm9ds1.LSM9DS1_SPI(spi,csag,csm)

rfm9x.tx_power = 23

while True:
# read twice -- first reading is corrupted
    temp = sensor.temperature
    temp = sensor.temperature
    gyro_x, gyro_y, gyro_z = sensor.gyro
    accel_x, accel_y, accel_z = sensor.acceleration
    mag_x, mag_y, mag_z = sensor.magnetic

    stri = '{0:0.3f},{1:0.3f},{2:0.3f},{3:0.3f},{4:0.3f},{5:0.3f},{6:0.3f},{7:0.3f},{8:0.3f},{9:0.3f}'.format(accel_x, accel_y, accel_z,mag_x, mag_y, mag_z,gyro_x, gyro_y, gyro_z,temp)
    print(stri)
    
    packet = rfm9x.receive(with_header=True,rx_filter=0xff)
    # you can remove everything below here if you don't want to see the radio packets
    # Optionally change the receive timeout from its default of 0.5 seconds:
    #packet = rfm9x.receive(timeout=5.0)
    # If no packet was received during the timeout then None is returned.
    if packet is None:
        continue
    else:
        # Received a packet!
        # Print out the raw bytes of the packet:
        print('Received (raw bytes): {0}'.format(packet))
        print([hex(x) for x in packet])
        # And decode to ASCII text and print it too.  Note that you always
        # receive raw bytes and need to convert to a text format like ASCII
        # if you intend to do string processing on your data.  Make sure the
        # sending side is sending ASCII data before you try to decode!
        packet_text = str(packet[4:], 'ascii')
        print('Received (ASCII): {0}'.format(packet_text))
        # Also read the RSSI (signal strength) of the last received message and
        # print it.
        rssi = rfm9x.rssi
        print('Received signal strength: {0} dB'.format(rssi))
    

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

I can try to come up with a better minimal case using a different SPI device instead of the LoRa

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

but for now this is a bit more minimal

import board
import busio
import digitalio
import adafruit_rfm9x
import adafruit_lsm9ds1
import time

RADIO_FREQ_MHZ   = 915.0

CS    = digitalio.DigitalInOut(board.D24)
RESET = digitalio.DigitalInOut(board.D17)

spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

csag = DigitalInOut(board.D21)
csm = DigitalInOut(board.D20)

rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ)
sensor = adafruit_lsm9ds1.LSM9DS1_SPI(spi,csag,csm)

rfm9x.tx_power = 23

while True:
# read twice -- first reading is corrupted
    temp = sensor.temperature
    temp = sensor.temperature
    gyro_x, gyro_y, gyro_z = sensor.gyro
    accel_x, accel_y, accel_z = sensor.acceleration
    mag_x, mag_y, mag_z = sensor.magnetic

    stri = '{0:0.3f},{1:0.3f},{2:0.3f},{3:0.3f},{4:0.3f},{5:0.3f},{6:0.3f},{7:0.3f},{8:0.3f},{9:0.3f}'.format(accel_x, accel_y, accel_z,mag_x, mag_y, mag_z,gyro_x, gyro_y, gyro_z,temp)
    print(stri)
    
    packet = rfm9x.receive()

the line before the while() loop to set the tx power -- causes the sensor reading to be corrupted - if you comment it out, then the first reading is OK and subsequent reading fail. If you comment out the last line then only th firs reading is bad and it reads normally after that since there is no communication to the rfm9x in the loop.

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

here is a simpler example using the lsm9ds1 and a bmp280 - same issue
here I read the accel sensor twice -- the first is corrupted, the second is OK

import board
import busio
import digitalio
import adafruit_bmp280
import adafruit_lsm9ds1
from digitalio import DigitalInOut, Direction
import time

spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
bmp_cs = digitalio.DigitalInOut(board.D22)
bmp280 = adafruit_bmp280.Adafruit_BMP280_SPI(spi, bmp_cs)

# change this to match the location's pressure (hPa) at sea level
bmp280.sea_level_pressure = 1013.25

csag = DigitalInOut(board.D21)
csm = DigitalInOut(board.D20)

sensor = adafruit_lsm9ds1.LSM9DS1_SPI(spi,csag,csm)


while True:
    bmp_temp=bmp280.temperature
    accel_x, accel_y, accel_z = sensor.acceleration
    accel_x, accel_y, accel_z = sensor.acceleration
    temp = sensor.temperature
    gyro_x, gyro_y, gyro_z = sensor.gyro
    mag_x, mag_y, mag_z = sensor.magnetic

    stri = '{0:0.3f},{1:0.3f},{2:0.3f},{3:0.3f},{4:0.3f},{5:0.3f},{6:0.3f},{7:0.3f},{8:0.3f},{9:0.3f},{10:0.3f}'.format(accel_x, accel_y, accel_z,mag_x, mag_y, mag_z,gyro_x, gyro_y, gyro_z,temp,bmp_temp)
    print(stri)

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

even simpler test case

import board
import busio
import digitalio
import adafruit_bmp280
import adafruit_lsm9ds1
from digitalio import DigitalInOut, Direction
import time

spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
bmp_cs = digitalio.DigitalInOut(board.D22)
bmp280 = adafruit_bmp280.Adafruit_BMP280_SPI(spi, bmp_cs)

# change this to match the location's pressure (hPa) at sea level
bmp280.sea_level_pressure = 1013.25

csag = DigitalInOut(board.D21)
csm = DigitalInOut(board.D20)

sensor = adafruit_lsm9ds1.LSM9DS1_SPI(spi,csag,csm)


while True:
    bmp_temp=bmp280.temperature
    accel_x, accel_y, accel_z = sensor.read_accel_raw()
    accel_x2, accel_y2, accel_z2 = sensor.read_accel_raw()
    print(accel_x, accel_y,accel_z, accel_x2, accel_y2, accel_z2)

and output

pi@gjnpi3p-1:~/projects/blinka/lsm9ds1 $ python3.6 raw_bmp.py 
SPI(): __init()
spiPorts: ((0, 11, 10, 9), (1, 21, 20, 19))
for:
0 11 10 9
Line 91
<class 'adafruit_blinka.microcontroller.generic_linux.spi.SPI'>
<adafruit_blinka.microcontroller.generic_linux.spi.SPI object at 0x768d7e30>
30977 -28399 6692 31 -40 12453
30977 -28399 6692 -147 33 14302
30977 -28399 6692 -495 49 19184
30977 -28399 6692 -244 54 15883
30977 -28399 6692 254 178 12700
30977 -28399 6692 -325 -7 14864
30977 -28399 6692 79 -142 13965
30977 -28399 6692 -658 29 14777
30977 -28399 6692 -3 -176 14946
30977 -28399 6692 147 166 16666

from adafruit_blinka.

ladyada avatar ladyada commented on July 21, 2024

nice - thank you

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

Is this significant? -- I set up my Sales for the SPI polarity/phase of the LSM9DS1 and it shows the two reads from the sensor and rejects the first. Note how the LSM CS goes low before the clock polarity switches. Is that causing the problem?

screenshot

from adafruit_blinka.

ladyada avatar ladyada commented on July 21, 2024

could be - but 99% of sensors use MODE 0 so i dont think thats all of it! i mean, i know where the problem probably is, its how we configure the SPI device when we send data, something amiss there

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

OK -- I'll go back to other projects for awhile -- Let me know if you need anything else.

from adafruit_blinka.

ladyada avatar ladyada commented on July 21, 2024

npnp
thank you for the help!

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

just for comparison -- here is a logic analyzer capture of the same code running on a feather_m4_express -- note how the CS goes low after the SCK has changed polarity for the first transaction - both reads are successful.

feather_m4

from adafruit_blinka.

caternuson avatar caternuson commented on July 21, 2024

Just throwing in my 2c FWIW:

The SPIDevice context manager notionally takes care of configuring the port each time:
https://github.com/adafruit/Adafruit_CircuitPython_BusDevice/blob/master/adafruit_bus_device/spi_device.py#L82
so in theory, should be able to switch between two devices with different modes. And it works on the Feather (see @jerryneedell 's trace above), so that's good.

On the RPi, this is also notionally happening. The blinka configure:
https://github.com/adafruit/Adafruit_Blinka/blob/master/src/busio.py#L97
calls init:
https://github.com/adafruit/Adafruit_Blinka/blob/master/src/adafruit_blinka/microcontroller/generic_linux/spi.py#L18
which sets mode:
https://github.com/adafruit/Adafruit_Blinka/blob/master/src/adafruit_blinka/microcontroller/generic_linux/spi.py#L30
But it appears, and can be seen in the traces above, that the actual changes to SCK do not occur until a write or read operation is done. Which corrupts the first attempt.

The python spidev module is just doing ioctl under the hood to the linux spidev kernel module.
https://github.com/doceme/py-spidev/blob/master/spidev_module.c#L864
So maybe this is just a "feature"?

from adafruit_blinka.

ladyada avatar ladyada commented on July 21, 2024

ok did a little more lookin yeah this is due to us sharing an SPI peripheral amongst multiple devices. and yeah it only happens with mixed modes
i dont have a good solution for now. sorry :( we dont have many mode=1 devices, looks like lsm9ds1 is one of the only ones. we can start a Blinka Troubleshooting page for now, but i dont think i can get into this quite yet, or solve it :/

from adafruit_blinka.

ladyada avatar ladyada commented on July 21, 2024

https://learn.adafruit.com/circuitpython-on-raspberrypi-linux/faq-troubleshooting

lol the LSM9DS1 is the only board that has this issue, nice work finding the one incompatibility, isn't that how it always is with programming :D

from adafruit_blinka.

jerryneedell avatar jerryneedell commented on July 21, 2024

Thanks for digging into it. There's always one troublemaker ;-)

from adafruit_blinka.

ladyada avatar ladyada commented on July 21, 2024

closing as this is now documented

from adafruit_blinka.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.