Comments (17)
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.
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.
I can try to come up with a better minimal case using a different SPI device instead of the LoRa
from adafruit_blinka.
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.
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.
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.
nice - thank you
from adafruit_blinka.
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?
from adafruit_blinka.
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.
OK -- I'll go back to other projects for awhile -- Let me know if you need anything else.
from adafruit_blinka.
npnp
thank you for the help!
from adafruit_blinka.
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.
from adafruit_blinka.
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.
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.
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.
Thanks for digging into it. There's always one troublemaker ;-)
from adafruit_blinka.
closing as this is now documented
from adafruit_blinka.
Related Issues (20)
- Orange PI 5 Plus HOT 2
- Latest version doesn't work on rp2040 pico due to a pin/digitalio error. HOT 1
- Jetson Orin Nano no SCLK_1 HOT 3
- MCP2221A import board error issue HOT 2
- Mellow Fly Pi V2
- add support in Blinka for orange pi zero 3 HOT 1
- running the Windows platform. HOT 1
- ft232h output signal HOT 1
- ft232h with MLX90640 HOT 2
- Big Tree Tech BTT pi
- RPI 5 - python library piod: 'Chip' has no attribute 'OPEN_BY_NUMBER' HOT 24
- Breadboard HOT 2
- Arduino Uno HOT 5
- STM32F405 Feather Request
- rpi_ws281x not compatible with pi 5 HOT 4
- Exception thrown in Lockable.unlock() does not follow CircuitPython behavior
- Raspberry Pi5 RuntimeError: Timed out waiting for PulseIn message. Make sure libgpiod is installed. HOT 6
- Please add support for the OrangePiCM4 HOT 3
- board HOT 1
- Accessing digitalio CE0 results in a device busy error on Pi5 HOT 20
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from adafruit_blinka.