Comments (8)
Hi, can you give me an example of code that I can verify?
P.S.
I'm sorry if I answer with such delays, but I keep this library in my spare time and lately it's been less and less.
from uble.
Close for no, reopen it if you need help.
from uble.
Apologies, I am not sure how I missed your response!
dmazella_imitation_BLESPItest.txt
In the file I attached (which I ran from the REPL), I attempted to copy your SPI code almost line-for-line, and was met with the same issue I described above. As you can see, I did have to port my code to fit the microcontroller I was using, the STM32 B-L475E-IOT01A, which contains an SPBTLE-RF on board.
from uble.
no problem,
I just tried your code and the problem is in not sending the reset command.
As you can see without the reset, the result of the script is identical to yours:
➜ micropython (master) ✗ python3 -B tools/pyboard.py --device /dev/tty.usbmodem3167398C35352 /Users/damianomazzella/Downloads/ww.py
bytearray(b'\x04\x10\x01\x00')
➜ micropython (master) ✗
Adding the reset, the behavior is correct:
➜ micropython (master) ✗ python3 -B tools/pyboard.py --device /dev/tty.usbmodem3167398C35352 /Users/damianomazzella/Downloads/ww.py
bytearray(b'\x04\xff\x03\x01\x00\x01')
➜ micropython (master) ✗
This is the code I tried:
# hail mary BLE SPI test
import machine
import pyb
import utime
import micropython
from micropython import const
from machine import Pin
# spi = machine.SPI(3, baudrate=8000000, polarity=0, phase=0,
# bits=8, firstbit=machine.SPI.MSB)
spi = machine.SPI(2, baudrate=8000000, polarity=0)
#CS = Pin('D13', Pin.OUT_PP, pull=Pin.PULL_NONE)
CS = machine.Pin('B12', machine.Pin.OUT_PP)
CS.on()
#RS = Pin('A8', Pin.OUT_PP, pull=Pin.PULL_NONE)
RS = machine.Pin('B9', machine.Pin.OUT_PP)
RS.on()
_READ_HEADER_MASTER = b'\x0B\x00\x00\x00\x00'
_WRITE_HEADER_MASTER = b'\x0A\x00\x00\x00\x00'
HCI_READ_PACKET_SIZE = const(128)
# IR = Pin('E6', Pin.IN, pull=Pin.PULL_DOWN)
IR = machine.Pin('B8', machine.Pin.IN, machine.Pin.PULL_DOWN)
class CSContext(object):
def __init__(self, pin):
self._pin = pin
def __enter__(self):
# Assert CS line
self._pin.off()
def __exit__(self, exc_type, exc_value, traceback):
# Release CS line
self._pin.on()
# return all(map(lambda x: x is None, [exc_type, exc_value, traceback]))
def write(retry=5, header=b'\x10\x03', param=0):
"""
Write packet to BlueNRG-MS module
"""
_rw_header_slave = bytearray(len(_WRITE_HEADER_MASTER))
result = None
while retry:
with CSContext(CS):
# Exchange header
spi.write_readinto(
_WRITE_HEADER_MASTER,
_rw_header_slave
)
rx_write_bytes = _rw_header_slave[1]
rx_read_bytes = (
_rw_header_slave[4] << 8
) | _rw_header_slave[3]
if _rw_header_slave[0] == 0x02 and (
rx_write_bytes > 0 or rx_read_bytes > 0):
# SPI is ready
if header:
# avoid to write more data that size of the buffer
if rx_write_bytes >= len(header):
result = bytearray(len(header))
spi.write_readinto(header, result)
if param:
rx_write_bytes -= len(header)
# avoid to read more data that size of the
# buffer
if len(param) > rx_write_bytes:
tx_bytes = rx_write_bytes
else:
tx_bytes = len(param)
result = bytearray(tx_bytes)
spi.write_readinto(param, result)
break
else:
break
else:
break
else:
break
else:
utime.sleep_us(50)
retry -= 1
return result
def read(size=HCI_READ_PACKET_SIZE, retry=5):
"""
Read packet from BlueNRG-MS module
"""
result = None
_rw_header_slave = bytearray(len(_WRITE_HEADER_MASTER))
while retry:
with CSContext(CS):
# Exchange header
spi.write_readinto(
_READ_HEADER_MASTER,
_rw_header_slave
)
rx_read_bytes = (
_rw_header_slave[4] << 8
) | _rw_header_slave[3]
if _rw_header_slave[0] == 0x02 and rx_read_bytes > 0:
# SPI is ready
# avoid to read more data that size of the buffer
if rx_read_bytes > size:
rx_read_bytes = size
data = b'\xFF' * rx_read_bytes
result = bytearray(rx_read_bytes)
spi.write_readinto(data, result)
break
else:
utime.sleep_us(50)
retry -= 1
# Add a small delay to give time to the BlueNRG to set the IRQ pin low
# to avoid a useless SPI read at the end of the transaction
utime.sleep_us(150)
return result
def run():
# reset
RS.off()
utime.sleep_us(5)
RS.on()
utime.sleep_us(5)
write() # retry=5, header=b'\x10\x03', param=0)
while True:
utime.sleep_us(12)
if (IR.value() == 1):
hi = read(size=HCI_READ_PACKET_SIZE, retry=5)
print(hi)
break
utime.sleep_us(25)
run()
Let me know how it goes.
best regards,
D.
from uble.
Ok, I probably should have mentioned in my previous post that I always reset the BlueNRG-MS module before running the code. My mistake.
When I run the code you posted, I get the correct initialization response like you did, but all of my following commands are met with the 0x04 0x10 0x01 0x00 error code. Below is an example with a few further modifications I added to continuously send commands to the chip. As you can see, I am trying to send the HCI_Read_Local_Supported_Features command. I get the same response if I send HCI_Read_Local_Supported_Commands, HCI_Read_Remote_Version_Information, or HCI_Read_Local_Version_Information as defined on page 7 in the blueNRG-MS document found here:
[https://www.st.com/content/ccc/resource/technical/document/user_manual/6d/a1/5b/6c/dc/ab/48/76/DM00162667.pdf/files/DM00162667.pdf/jcr:content/translations/en.DM00162667.pdf]. I have tried many other commands, but those are 4 that I believe should work without any initialization other than a reset.
code:
def run():
RS.off()
utime.sleep_us(5)
RS.on()
utime.sleep_us(5)
write() # HCI_Read_Local_Supported_Features
while True:
utime.sleep_us(12)
if (IR.value() == 1):
hi = read(size=HCI_READ_PACKET_SIZE, retry=5)
print(hi)
utime.sleep(2)
write() # HCI_Read_Local_Supported_Features
run()
and here is the output from the REPL:
from BLEProj.test import dmzBLESPI
bytearray(b'\x04\xff\x03\x01\x00\x01')
bytearray(b'\x04\x10\x01\x00')
bytearray(b'\x04\x10\x01\x00')
bytearray(b'\x04\x10\x01\x00')
bytearray(b'\x04\x10\x01\x00')
bytearray(b'\x04\x10\x01\x00')
bytearray(b'\x04\x10\x01\x00')
bytearray(b'\x04\x10\x01\x00')
bytearray(b'\x04\x10\x01\x00')
from uble.
with your example:
# hail mary BLE SPI test
import machine
import pyb
import ustruct
import utime
import micropython
from micropython import const
from machine import Pin
# spi = machine.SPI(3, baudrate=8000000, polarity=0, phase=0,
# bits=8, firstbit=machine.SPI.MSB)
spi = machine.SPI(2, baudrate=8000000, polarity=0)
#CS = Pin('D13', Pin.OUT_PP, pull=Pin.PULL_NONE)
CS = machine.Pin('B12', machine.Pin.OUT_PP)
CS.on()
#RS = Pin('A8', Pin.OUT_PP, pull=Pin.PULL_NONE)
RS = machine.Pin('B9', machine.Pin.OUT_PP)
RS.on()
_READ_HEADER_MASTER = b'\x0B\x00\x00\x00\x00'
_WRITE_HEADER_MASTER = b'\x0A\x00\x00\x00\x00'
HCI_READ_PACKET_SIZE = const(128)
# IR = Pin('E6', Pin.IN, pull=Pin.PULL_DOWN)
IR = machine.Pin('B8', machine.Pin.IN, machine.Pin.PULL_DOWN)
class CSContext(object):
def __init__(self, pin):
self._pin = pin
def __enter__(self):
# Assert CS line
self._pin.off()
def __exit__(self, exc_type, exc_value, traceback):
# Release CS line
self._pin.on()
# return all(map(lambda x: x is None, [exc_type, exc_value, traceback]))
def write(retry=5, header=b'', param=0):
"""
Write packet to BlueNRG-MS module
"""
_rw_header_slave = bytearray(len(_WRITE_HEADER_MASTER))
result = None
while retry:
with CSContext(CS):
# Exchange header
spi.write_readinto(
_WRITE_HEADER_MASTER,
_rw_header_slave
)
rx_write_bytes = _rw_header_slave[1]
rx_read_bytes = (
_rw_header_slave[4] << 8
) | _rw_header_slave[3]
if _rw_header_slave[0] == 0x02 and (
rx_write_bytes > 0 or rx_read_bytes > 0):
# SPI is ready
if header:
# avoid to write more data that size of the buffer
if rx_write_bytes >= len(header):
result = bytearray(len(header))
spi.write_readinto(header, result)
if param:
rx_write_bytes -= len(header)
# avoid to read more data that size of the
# buffer
if len(param) > rx_write_bytes:
tx_bytes = rx_write_bytes
else:
tx_bytes = len(param)
result = bytearray(tx_bytes)
spi.write_readinto(param, result)
break
else:
break
else:
break
else:
break
else:
utime.sleep_us(50)
retry -= 1
return result
def read(size=HCI_READ_PACKET_SIZE, retry=5):
"""
Read packet from BlueNRG-MS module
"""
result = None
_rw_header_slave = bytearray(len(_WRITE_HEADER_MASTER))
while retry:
with CSContext(CS):
# Exchange header
spi.write_readinto(
_READ_HEADER_MASTER,
_rw_header_slave
)
rx_read_bytes = (
_rw_header_slave[4] << 8
) | _rw_header_slave[3]
if _rw_header_slave[0] == 0x02 and rx_read_bytes > 0:
# SPI is ready
# avoid to read more data that size of the buffer
if rx_read_bytes > size:
rx_read_bytes = size
data = b'\xFF' * rx_read_bytes
result = bytearray(rx_read_bytes)
spi.write_readinto(data, result)
break
else:
utime.sleep_us(50)
retry -= 1
# Add a small delay to give time to the BlueNRG to set the IRQ pin low
# to avoid a useless SPI read at the end of the transaction
utime.sleep_us(150)
return result
def run():
# reset
RS.off()
utime.sleep_us(5)
RS.on()
utime.sleep_us(5)
# wait event "device ready"
while True:
if IR.value() and read() == b'\x04\xff\x03\x01\x00\x01':
break
# HCI_Read_Local_Version_Information: OGF: 0x04 OCF: 0x01 OPCODE: 0x1001
param = b''
ogf = 0x04
ocf = 0x01
opcode = ustruct.pack("<H", (ocf & 0x03ff) | (ogf << 10)) # OPCODE
header = ustruct.pack("<B3s", 0x01, opcode)
print(header, param)
write(header=header, param=param)
while True:
if IR.value():
hi = read()
print("-------", hi)
break
# HCI_Read_Local_Supported_Features: OGF: 0x04 OCF: 0x03 OPCODE: 0x1003
param = b''
ogf = 0x04
ocf = 0x03
opcode = ustruct.pack("<H", (ocf & 0x03ff) | (ogf << 10)) # OPCODE
header = ustruct.pack("<B3s", 0x01, opcode)
print(header, param)
write(header=header, param=param)
while True:
if IR.value():
hi = read()
print("-------", hi)
break
run()
expected output:
➜ micropython (master) ✗ python3 -B tools/pyboard.py --device /dev/tty.usbmodem3167398C35352 /Users/damianomazzella/Downloads/test_uble.py
b'\x01\x01\x10\x00' b''
------- bytearray(b'\x04\x0e\x0c\x01\x01\x10\x00\x07\x071\x070\x00#\x00')
b'\x01\x03\x10\x00' b''
------- bytearray(b'\x04\x0e\x0c\x01\x03\x10\x00\x00\x00\x00\x00`\x00\x00\x00')
➜ micropython (master) ✗
Please try it and give me feedback.
from uble.
It worked! I can't believe it. The issue was definitely the header format. For example, when I told you I sent the HCI_Read_Local_Supported_Features command, I was sending the header in a simple bytearray as it was given in the spec: OpCode = 0x1003.
I can see now that, when the header gets packed into a ustruct, its formatting changes and it becomes 0x0103. I am not sure where or if that ever gets clarified in the BlueNRG-MS spec I linked above.
I can't thank you enough, especially because you mentioned this is an old project. Without your help I doubt I ever would have ever solved this problem. I am a relative newcomer when it comes to embedded python, and never would have thought to use a struct. Many thanks!
from uble.
I'm glad that everything works.
Best regards,
D.
from uble.
Related Issues (7)
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 uble.