spirilis

[Energia Library] Nordic nRF24L01+ library

349 posts in this topic

Ok, so I tried using deepsleep() after flush() and it works for me, including serial output (I have patched my Energia core manually), doing a deepsleep() after flush() I still get my LED blinking once a second on the RX launchpad.

 

To patch it, find the Energia install, look for the "hardware/msp430/cores/msp430" directory...

Find "usci_isr_handler.c"

 

Find the section in my post above (http://forum.43oh.com/topic/3237-energia-library-nordic-nrf24l01-library/page-2#entry28498) and add in the "(UCB0CTL0 & UCMODE_3) == UCMODE_3 &&" to the beginning of that if() statement so the i2c_rxtx_isr() only runs if UCMODE = 3.

Share this post


Link to post
Share on other sites

As for LPM3, I'm not sure that'll work right with Energia, because what's waking it up periodically is the WDT ... and that runs off SMCLK, which is disabled in LPM3 mode.

 

You'd have to manually configure Timer_A to run off ACLK, set up the VLOCLK or XT1CLK (for 32.768KHz crystal) yourself, and have a Timer_A ISR that wakes up your chip.

Share this post


Link to post
Share on other sites

thanks,will try patch it.

yes, i am triing figuring out how to change timer in energia to VLO and after that return it back :smile:

without power saving  it get near 0.9mA,that is too much.

 

ps got 0.50mA by patching wiring.c to start at 8mhz. unfortanly at 2mhz nrf just not work.

Share this post


Link to post
Share on other sites

Couple git commits-

 

flush() had a bug where if you ran it while in RX mode, it wouldn't work.  Now flush() has been reworked so it detects a present RX mode, backs out of it (remembering whether or not it was in RX mode when flush() was called), then after all the TX business has completed and IRQs fired, it will run enableRX() to re-enter RX mode.

 

Also flush() now checks if the txbuf is zero-length and return immediately (nothing to send).

Share this post


Link to post
Share on other sites

thanks,will try patch it.

yes, i am triing figuring out how to change timer in energia to VLO and after that return it back :smile:

without power saving  it get near 0.9mA,that is too much.

 

Maybe try this:

 

WDTCTL = WDT_ADLY_1_9;  // WDT triggered from ACLK after ~6ms, millis() will be skewed BTW

LPM3;

WDTCTL = WDT_MDLY_0_5; // WDT back to original Energia setting, SMCLK 0.5ms/IRQ

 

It looks like Energia does set up the ACLK = VLOCLK already.  You can also use WDT_ADLY_16, _250, or _1000 (those numbers assume 32.768KHz ACLK btw, at ~11KHz VLOCLK they'd be 46ms, 744ms and 2.97 seconds respectively).  The millis() value will be very skewed (running slow) as a result.

 

disclaimer: I have not tried this yet :D

lunakid likes this

Share this post


Link to post
Share on other sites

thank you very much for your suggestion. following replace of delay work ok:

 

 

void mdelay(uint32_t milliseconds)
{
    WDTCTL = WDT_ADLY_1_9;  // WDT triggered from ACLK after ~6ms, millis() will be skewed BTW
    uint32_t wakeTime = (milliseconds*10)/51;
        while(wakeTime>0){
                /* Wait for WDT interrupt in LMP0 */
                wakeTime--;
                __bis_status_register(LPM3_bits+GIE);
        }
   WDTCTL = WDT_MDLY_0_5; // WDT back to original Energia setting, SMCLK 0.5ms/IRQ
}

 


it not very accurate, but ok.

 

note, there are no need in timer interrupt, since energia already supply compatible one.

 

i can't measure transmit power, it go from 0 to 0.06mA(i have no uA in my tool)

Share this post


Link to post
Share on other sites

This is great thanks spirilis. Just got my radios in the mail today and less than an hour later after reading some docs and finding pin descriptions on my radio modules I had it going.  I loaded up the TX_demo on a g2452 and the RX_demo on a g2553.  Powered em up, opened 2 serial windows and watch it successfully set the red led remotely.  Nice work!

 

I did apply the usci code change you suggest in my energia core code and the usci spi g2553 fix (github issue #164)

 

I got my radios on ebay.  10 for ~$12 .. amazing .. cheaper than dumb 433MHz radios

 

ebay search string: '10Pcs NRF24L01+ 2.4GHz Antenna Wireless Transceiver For Microcontroller EA New'

 

looks like since i purchased they cost even less.

 

-rick

Share this post


Link to post
Share on other sites

Added a new example to the github version (not in the zipfile up above)-- Enrf24_ChannelScan

 

Scans each channel 0-125, spending about 1 second on each one, trying to determine ambient noise level on each of those channels.  Should help you find a clear channel for your I/O.

 

It scans at the default 1Mbps bitrate, you can test 250Kbps or 2Mbps by placing those in the radio.begin() arguments (e.g. radio.begin(2000000);)

Share this post


Link to post
Share on other sites

Couple changes-

 

1. I forgot to expose the interface that shows whether your TX was successful or not.  So I made the variable "lastTXfailed" public.

 

How to use this:

a. Manually stuffing buffer to <32 bytes and running flush()-

Write your data, run flush(), then test the .lastTXfailed boolean:

 

if (radio.lastTXfailed) {

  // Handle packet loss...

}

 

b. Stuffing buffer without knowledge of whether you're going over the 32-byte limit, but catching all failures-

 

radio.lastTXfailed = false;  // Set it to a known value

while(some condition) {

  radio.print(blahblah); ...

  if (radio.lastTXfailed) {

    // Handle packet loss situation

  }

}

radio.flush();  // Flush final contents of buffer

if (radio.lastTXfailed) {

  // Handle packet loss situation

}

 

 

2. I modified the auto-send behavior slightly; instead of it auto-transmitting when 32 bytes are filled, it will auto-transmit when a 33rd byte is attempted.  The buffer write will be preempted by the TX, blocking the program, clearing the buffer and then that 33rd byte is written to the first byte of the buffer.

 

That way folks who manage their own buffers and use a 32-byte count in their application can expect the data won't actually be sent until they manually run radio.flush().

Share this post


Link to post
Share on other sites

Hello,

Thanks for this library :thumbup: , I am trying to use it and face some problems.

I use the following hardware/software:

  • launchpad 1.5
  • MSP430G2553
  • hardware serial for programming the launchpad (J3 jumpers RXD and TXD are perpendiculars to the other 3 jumpers) as described in the Energia Wiki for the MSP430G2553
  • Energia 0101E0009 (unpatched as I don't clearly get what has to be patched although spirilis has some github changes going on )
  • the github library cloned yesterday
  • the nrf24L01 module is different from the one described in this post. It is a 10 pins, green, not a nrf24L01+.

    I got it from ebay there. As far as I know, it is plug replaceable and only differs on the allowed radio speeds (no 250 Kbauds).

With the scan channels example provided, after pressing the reset button, it seems that the first channel is detected but none of  the other ones.

Literrally, I got the following serail terminal results

nRF24L01+ Channel Activity Scan
-------------------------------
Channel 0 (2400MHz): ******** 
Channel 1 (2401MHz):  
Channel 2 (2402MHz):  
Channel 3 (2403MHz):  
Channel 4 (2404MHz):  
Channel 5 (2405MHz):  
Channel 6 (2406MHz):  
Channel 7 (2407MHz):  
... (cutted because all the same)
 

 

Another reset just produces the same result.

 

My connections, software are as descibed in this post. I checked it 2 or 3 times...

nRF pin / LaunchPad pin
------------------
Vcc   ->   Vcc
GND   ->   GND
 
SCK   ->   P1.5
MO    ->   P1.7
MI    ->   P1.6 (note-- MO and MI should be reversed for the G2xx2 and G2xx1 chips)
CE    ->   P2.0
CSN   ->   P2.1
IRQ   ->   P2.2
  

WIth the TX example I got more or less the same kind of problem:

Enrf24 radio transceiver status: DEEP SLEEP <1uA power consumption
Sending packet: ON

 

and it hangs, not displaying the next status. As if the module was disconnected or something like that.

 

With the RX example I confirm some disconnections problems of the module

Enrf24 radio transceiver status: DEEP SLEEP <1uA power consumption
Enrf24 radio transceiver status: NO TRANSCEIVER PRESENT

 

So, how can I go any further and check something.

 

Apparently,

  • there is no connections problems. Otherwise the module would never report a DEEP SLEEP status.
  • after a reset, it gets back in a predefined status. But is it a real one or a default answer of the library? I have not found any thing in the github source that could explain this.
  • If it is a hardware problem within the module how can I diagnosed it?

Getting out of the deep sleep status might be the problem but I can't figure why...

So far, I will investigate with a second launchpad and module and try RX & TX examples all at the same time just to see.

 

I you have any clue or suggestion please help me. ;-)

Share this post


Link to post
Share on other sites

Ok, hello again...

So after rereading this topic, I patched Energia and got the correct resulst in the TX, RX and scan examples

Enrf24 radio transceiver status: DEEP SLEEP <1uA power consumption
Sending packet: ON
Enrf24 radio transceiver status: IDLE module powered up w/ oscillators running
Sending packet: OFF
Enrf24 radio transceiver status: IDLE module powered up w/ oscillators running
 
 
Enrf24 radio transceiver status: DEEP SLEEP <1uA power consumption
Enrf24 radio transceiver status: Receive Mode
 
nRF24L01+ Channel Activity Scan
-------------------------------
Channel 0 (2400MHz):  
Channel 1 (2401MHz):  
Channel 2 (2402MHz):  
Channel 3 (2403MHz):  
Channel 4 (2404MHz):  
Channel 5 (2405MHz):  
Channel 6 (2406MHz):  
Channel 7 (2407MHz):  
Channel 8 (2408MHz):   

 

 

So this is really related to the Energia problem, I have to improve my github skills...

I will go on and try receive/transmit examples on 2 launchpad soon.

Sorry for disturbing you with this.

neborkia likes this

Share this post


Link to post
Share on other sites

Hi there,

i have some nRF24L01+ hooked up to the v1.5 Launchpad, which works fine with the rx/tx examples of the Enrf24 library.

I've seen the idea of deploying the mash network based on arduino boards. Nice word indeed...

I do not plan to set any mash network, but one or two access point(s) / bridge(s) to Ethernet and a couple of nodes (maybe 60-100).

It looks like it is possible to address about 5000 different nodes.

I do not need them to actively talk to the root, but I need them to response to the requests of the root. 

 

To keep it simple: 1 root polls the information from the rfm24 network / another one from the rfm12 network. All nodes are passively waiting for the poll responding with the information like temperature or ack of the order the root have sent to the node.

 

My questions (finally)

--> is it possible to let all the nodes to listen and only to respond, once identified by an int ID?

--> is it possible to switch between rx and tx as quick and be able to scan about 100 nodes per second and get all information sent back to the root?

 

I should mention, that I am new to Energia. Some of you will remember me from previous questioning.

Share this post


Link to post
Share on other sites

Spirilis,

A small favor. Could you update your first post when you make a release. You can add a link to the post in this thread with the release. Makes it easier for members for find updates.

Thanks for your contribution!

Share this post


Link to post
Share on other sites

Hi there,

i have some nRF24L01+ hooked up to the v1.5 Launchpad, which works fine with the rx/tx examples of the Enrf24 library.

I've seen the idea of deploying the mash network based on arduino boards. Nice word indeed...

I do not plan to set any mash network, but one or two access point(s) / bridge(s) to Ethernet and a couple of nodes (maybe 60-100).

It looks like it is possible to address about 5000 different nodes.

I do not need them to actively talk to the root, but I need them to response to the requests of the root. 

 

To keep it simple: 1 root polls the information from the rfm24 network / another one from the rfm12 network. All nodes are passively waiting for the poll responding with the information like temperature or ack of the order the root have sent to the node.

 

My questions (finally)

--> is it possible to let all the nodes to listen and only to respond, once identified by an int ID?

--> is it possible to switch between rx and tx as quick and be able to scan about 100 nodes per second and get all information sent back to the root?

 

I should mention, that I am new to Energia. Some of you will remember me from previous questioning.

 

Q1: It certainly is, in fact there is no such concept as a "broadcast" with the nRF24L01+ (multiple devices can listen on one address but you have to turn autoack off to do that).  Just have each node register with a unique RX address and the root node/gateway can hit them individually.

Q2: It is possible to switch quickly, and my latest git commit to Enrf24 reworks flush() so it will do just that--it detects if RX mode is enabled and makes sure to re-enable it once it's done transmitting.

Scanning about 100 nodes per second gives you around 10ms per node, which might be a tall order with this stuff though.  I'm assuming for the size of the network you're talking you'll probably have the various nodes spread apart a bit, so I'd suggest 250Kbps mode which doesn't allow auto-ack anyhow (autoack can consume a good bit of time).  Keep the "scan" message very short and 10ms per node might be doable.  Never really tried it myself.  If your main loop is pretty tight on the slave nodes (watches the .available() method frequently and reacts quickly, turning around to TX when it's validated a scan request from the root) it should be fast.

 

Just be sure the root node spends a short delay--start with 10ms perhaps, watching for an RX reply from the slave node before it gives up & goes on to the next one.  You don't want the root node to move on to the next slave node, entering TX mode when in fact the previous slave node is trying to transmit (the root node will miss its message and/or cause an over-the-air collision).

 

An example of implementing this 10ms delay would be:

boolean rxready;
unsigned long mstart = millis();
while ( (millis() - mstart) < 10 && !(rxready = nrf24.available(TRUE)) )
  ;
if (rxready) {
  // Process slave node's reply
}
// Else the slave node never replied, and we timed out the 10ms window.

 

 

On both the remote node and the root node, use .available(TRUE) for performance; it will check the IRQ pin state first to determine if there's any IRQ present, saving some time by having it NOT poll the transceiver over SPI to determine whether an IRQ has fired or not.  It should help tighten up the response time all around.  (With .available() or .available(FALSE), it will go out and physically talk to the nRF24L01+ chip over SPI to determine if the RX queue is empty in order to determine whether data is available or not.  Takes a little more time.)

 

Anyway I realize you are new to Energia so I apologize if I explained a bit too much :smile:

johnnybravo likes this

Share this post


Link to post
Share on other sites

Thanks a lot spirilis, that was exactly what I was looking for. 

I am new to Energia, indeed. A couple of years ago I did my job in Enterprise Development Area, whatever ... Once stepped forward in the carrier, I could only keep my focus on ASM and embedded C development privately, what I've learned during my studies. ;-) Now it is my hobby, 25 years later. 

After beginning with the TI tools like Code Composer or Grace, I had a gap and tried to find a working solution for my Mac. Energia came across and here I am. So yes, Here here is the real beginner. Your explanation is more than understandable.

Thanks! Now I can go for it without having to use a logic analyser. 

 

Q1: switch of the auto ack. got it.

Q2: regarding the rx address, once using the unique tx address and different rx addresses per node, will I need to switch the address when sending to each node? I mean sending from 0xDE, 0xAD, 0xBE, 0xEF, 0x01  needs the receiver to have the same parameters 0xDE, 0xAD, 0xBE, 0xEF, 0x01 ? I do refer to your examples. Which file should I have a look at to see which of those parameter defines the channel, frequency band, node id? I was about to use the same parameter as your example and put the ID as int, but the all nodes would sent the ack message back, which I did not know before.

 

Guys, I am really sorry for bothering you and for flooding this board. I will get better!

Cheers!

Share this post


Link to post
Share on other sites

Oh gotcha... Umm, couldn't quite follow what you wrote but let me explain addressing:

 

The RX address is the only address the transceiver will look for when watching the air in RX mode.

The TX address is just stored on an internal buffer in the transceiver so it knows where to send the next packet you transmit.  There is no way to supply both the TX address and the packet payload in one SPI command, so instead you have to load the TXaddr using .setTXaddress() and then issue your writes and/or flush.

 

nRF24L01+ packets only have one address in the frame--the destination address.  There is no "source" address to reveal who the packet came from.  Therefore you can have any address you want loaded into the TXaddr buffer for any of the transceivers, in terms of response the transceiver will only react to packets bearing its RX address.  You just have to make sure you change the TXaddr value if you wish to send data to a different transceiver/MCU node.

johnnybravo likes this

Share this post


Link to post
Share on other sites

Small addition- A private state variable 'readpending' has been implemented that is set in _maintenanceHook() and not cleared until read().  This allows persistent testing of .available(1) for more freedom in your coding.

 

An example of a scenario this would fix:

while ( (millis()-saved_time) < 5000 && !nrf.available(1) )  // Two different tests
  ;
// Ambiguity here--Which condition broke the while() loop?

// This will always fail because if nrf.available(1) succeeded up above, the internal
// _maintenanceHook() call will have cleared the IRQ and nrf.available(1) checks that.
// Can use .available(0) instead.
if (nrf.available(1)) {
  .... read packet and handle ...
}

 

Now that scenario could be handled by just testing if the millis() condition was the one that broke it, but what if both conditions occurred simultaneously?  It's tricky.  Then the user would have to remember to use .available(0) in the 2nd instance instead of .available(1).  Adding extra SPI I/O imo.

 

With this "readpending" variable added, the 2nd nrf.available(1) will succeed since _maintenanceHook() from the "!nrf.available(1)" condition in the while() loop will have set readpending=1 once it discovered an IRQ was raised and went to clear it.  Further executions of nrf.available(1) will continue to report TRUE until nrf.read() is finally executed.

 

This does not affect the behavior of nrf.available(0) at all.  nrf.available(0) goes out over SPI and asks the transceiver if its RX buffers are empty to determine whether there is data pending or not.  It's more thorough.

 

Note that if an error packet (size=0 or >32) was found during the _maintenanceHook() execution, readpending is forcibly set to 0 (because a FLUSH_RX command is required to clear the error packet, throwing out everything in the RX queues).

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now