Question: Considering Wafer...for NRF24 Driver #1
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Hey, more of a question than issue. I'm looking at the nrf24 radio, and notice there isn't first-class support within the Nerves ecosystem. My need is really simple (rx-only), but thinking about "porting" a Python/CircuitPython driver to Elixir, and found Wafer. The radio is SPI plus GPIO for both control and optional interrupt. Do you think this would be a decent fit for this potential project? Fair warning I'm also new to all this (Elixir, Nerves and the hardware stuff) but am willing to bite into it.
changed title from Question: Considering Wafer... to Question: Considering Wafer...{+for NRF24 Driver+}
Hi @kitplummer.
This is exactly the sort of project that Wafer was designed to support. Technically you don't need Wafer to enable support, but while writing drivers I found a lot of repeated code which Wafer eliminates.
That said, I haven't written any drivers for SPI devices yet, so Wafer's support for them is just a best guess at this stage. If you find any rough edges then feel free to open an issue for me to take a look.
Good luck with your project!
Thanks. I'm going to start digging, I like the abstraction and could already sense a need for it (which is what lead me to search in the first place). I know I could get by with Circuits.SPI and Circuits.GPIO but the "bit" work had me scratching my head a lot (between Erlang stuff and trying to decipher the other Python driver). Appreciate the docs and other examples you've made available.
I was just re-reading the docs and thinking that they're a little sparse 😄!
Let me know how you get on with your project.
Ha. Ok, here's the deal - in exchange for a bit of support as I get on
with it, I'm going to start with a "blinky" helloworld experiment. Once I
have that, I'll write a simple blog post and link to Wafer and submit a
simple PR with the 'pre-getting started' steps.
Works for me!
@jimsy - sorry to bug already. need a pointer.
I've been using the pca9641 as my guide and know the registers it is accessing are on the I2C driver. Is this a declaration problem, or have I run into the first missing SPI functionality?
Ah I see now, SPI just has
transfer
which pretty much always write_read in a single thing in the Circuits.SPI library.That's right. That's because that's just how the SPI protocol works - there's really only one operation which is basically swapping a byte from the host for a byte from the client. I'm not really sure about what the conventions for reading/writing registers are. I'll happily help you implement them though. Can you link me to the datasheet for the device you're working with?
https://www.sparkfun.com/datasheets/Components/nRF24L01_prelim_prod_spec_1_2.pdf and here's the Python driver I was learning from too: https://github.com/2bndy5/CircuitPython_nRF24L01/blob/master/circuitpython_nrf24l01/rf24.py
I was able to write and registers via the
SPI.transfer()
directly in learning some things too.Cool. I'll take a look over the weekend and see what I can find. Do you have a repo somewhere I can take a look at?
Awesome. Much appreciated.
This is as far as I go before I found wafer: https://gitlab.com/kitplummer/nrf24l01/snippets/1974729
Just pushed up my what I got to this morning: https://gitlab.com/kitplummer/nrf24l01 - not very far.
Okay. So it looks like we need to implement the
Wafer.Chip
protocol for yourConn
. Looking at the datasheet, there's a handy list of instructions:I'll take a swing at it and send you a PR - I don't have the actual hardware to test, but it should at least give you an idea how to go forward.
Rad, much appreciated. I'd be willing to send a couple radios your way for the effort.
Okay, so I've sent you a PR to try. Note that the
Chip
protocol is only interested in reading and writing registers and you're going to have to write your own code to drive the actual data transfers using the other six instructions above.Merged it, now will see if I can grok this register and bit stuff. :) Thanks again.
Heyo. Stumped by something...
Code:
output:
Perhaps a red-herring but the
<<14>>
is my "config" data. But I can't for the life of me figure this out.The
Registers
forrf_setup
is:Here's the Chip
write_register
:Any troubleshooting pointers @jimsy? It appears that any call to
write_register
only ever returns the same data as<<14>>
, which was the first write.Remember that an SPI transfer is a "swap". You should discard the results of the write register instruction - in this case I believe you're getting the old register contents, but I could be wrong.
In this case if you want to verify what was written to the register then you should immediately follow it with a read register instruction.
SparkFun has a good description of how SPI works.
I've thought about that, and that's where I started, but have been scrambling to figure out why it appears the write isn't happening. It is the same output when I follow the write of <<6>>, the subsequent read is <<14>> all the time, for each register. Will keep poking. Thanks for the link.
I'm an idiot. Was looking at the wrong byte that is returned with
read_register
. Damn.You're not an idiot. You just made a mistake. We all do it.
Which makes me realise that problem is one of my creation.
The
read_register
andswap_register
implementations should probably drop the first byte of data in the response, since it's the instruction byte.I'd been paying attention to that as I was reading the code and docs...so I
knew what it was. Continuously improving...
Hey @jimsy - probably a simple question. I need to access the Wafer.Chip.impl.read_register directly from my driver, in order to do a read with a dynamic number of bytes (thinking that eliminates the
defregister
macro).If I call it with the
conn
I'm using for accessing the registers like this:I get:
If I call it this way:
I get:
Am I wrong to think I can access the Chip implementation?
Help!?
Remember that
Chip
is a protocol, so you should just be able to callWafer.Chip.read_register(conn, 0x61, curr_pl_size)
. We implemented it for theRf24l01
type, so it should just work.I thought so too, but the same
Protocol.UndefinedError
if I callWafer.Chip.read_register()
instead ofWafer.Chip.Rf24l01.read_register()
..The way to call it should definitely be:
result = Wafer.Chip.read_register(%Rf24l01{conn: conn}, 0x61, curr_pl_size)
Make sure that you derive theSPI
protocol for your Conn type.Yep. https://gitlab.com/kitplummer/nrf24l01/-/blob/config/lib/rf24l01.ex#L2
I believe that's happening, here's my sketch/test:
I had a look over the
Chip
implementation in your project (I know I wrote it - but I couldn't remember), and it looks like it uses the SPI conn directly anyway, so callingWafer.Chip.read_register(%Rf24l01{conn: conn}, 0x61, curr_pl_size)
whereconn
is the result of theSPI.acquire/1
should work. Can you cut your example down to simply reading the contents of a register and verify that it works?ie:
Yep, just did that:
works. Hrm.
Okay, so it's working then?
Need to work backwards and figure out what is blowing up the function now.
Okay. I suggest you also fix your Chip impl so that read_register looks like this:
Hopefully helps with your sanity so that you don't have to drop the instruction byte every time you access a register.
Wilco. Thanks!
@kitplummer how are you getting on?
Oh, slow. Actually had my free time re-prioritized a little bit. Have
been able to RX on the radio, so think I'm good on the
wafer
front. Nowit's a matter of implementing the rest of functionality needed, cleaning
things up, and push it out there. I'll get there. Thanks for checking in,
super appreciated.
Pretty stuck now, have debugged about as best as I can to make sure the config/initialization registers are good. But whenever I go to read received data I only ever get:
???????????????
Completely baffled. Any generic ideas?
Actually, I think it is the "address" I am trying to use. I need to get
0xF0F0F0F0D2
as a bytearray.Hrm...this is hard. :D Sorry for using this issue as a mental/historical reference. Currently trying to debug through all of the radio config to figure out why the actual read of the payload register isn't working. Since flush_rx is write only, I'm left to guess if it is actually working...
@jimsy - ok, i need to access the
read_register
function that I've got in thedefimpl Wafer.Chip, for Rf24l01
from myRf24l01
module. How should I be doing that?Like this:
Or some other way?
When I do the above I get
???????????
or some series of the question marks no matter what. All the register stuff up to this works fine, can verify my writes with subsequent reads. Thecurr_pl_size
is a read on a register to know how much data is in the receive buffer at that0x61
address.Any ideas?
Hi @kitplummer - sorry I've taken so long to respond - there's been a lot going on here for the last while. To access the protocol implementation you just need to call the protocol with the correct type of data - which it looks like you're doing. Are you still stuck?
@kitplummer how are you getting on?
Heyo. Stopped in my tracks. Have had to reprioritize to a few other
things. Thanks for checkin' in. Feel free to close this out if you want.