spirilis

[Energia Library] Nordic nRF24L01+ library

352 posts in this topic

I collapsed LM4Bits.h into Enrf24.h and included the new #include's for the platform.

 

Can you guys verify this works--it builds just fine for me with board set to Stellaris LaunchPad:

Enrf24_v1_5.zip

 

 

Changes:

Version promoted to v1.5

#include's for Stellaris LaunchPad

BITx defines for Stellaris LaunchPad

Enrf24_ChannelScan example modified to use while(1); to halt CPU instead of LPM4 since that isn't available on Stellaris LaunchPad.

AStelTXdemo example included.

 

The original Enrf24_* examples only need the pin names changed in the constructor up above to work.  (Haven't actually tested these myself on the Stellaris LP though)

 

Past changes not included in the prior zip file in this thread:

Subsequent hits to .available(1) will return TRUE until data is actually read.  Normally .available(1) (only reports data available if RX IRQ present) will report false after the first hit b/c the IRQ is cleared behind the scenes.

.write() auto-sends only when you try to send a 33rd byte into the buffer

A .lastTXfailed variable exposed to the user so they can test if the last write() or flush() performed failed (only available with AutoACK, and only at 1Mbps & 2Mbps)

Pradeepa, reaper7 and OzGrant like this

Share this post


Link to post
Share on other sites

Yup,

Works great(or should I say just the same) Will now have a play getting to scan my ten temperature sensors.

Grant

Share this post


Link to post
Share on other sites

Can someone guide me on pin mapping...

Not sure what you mean ... Pin mapping for what?  If you mean the transceiver, track where you put the CE, CSN and IRQ pins from the transceiver module and see which port they correspond to on the LaunchPad, then specify those in the Enrf24 constructor parameters.

 

E.g. in the new AStelTXdemo he specified:

 

Enrf24 radio(PE_1, PE_2, PE_3);  // P2.0=CE, P2.1=CSN, P2.2=IRQ
 

Comment wasn't updated, think I'll go edit that now :smile:  but he's using PE_1 for the CE pin on the nRF24, PE_2 for CSN, PE_3 for IRQ.  That's on the Stellaris LaunchPad.

Share this post


Link to post
Share on other sites

Not sure what you mean ... Pin mapping for what?  If you mean the transceiver, track where you put the CE, CSN and IRQ pins from the transceiver module and see which port they correspond to on the LaunchPad, then specify those in the Enrf24 constructor parameters.

 

E.g. in the new AStelTXdemo he specified:

 

Enrf24 radio(PE_1, PE_2, PE_3);  // P2.0=CE, P2.1=CSN, P2.2=IRQ
 

Comment wasn't updated, think I'll go edit that now :smile:  but he's using PE_1 for the CE pin on the nRF24, PE_2 for CSN, PE_3 for IRQ.  That's on the Stellaris LaunchPad.

 

I got it spirilis. It's using SPI module 3 for SPI. And other pins as you mentioned here :)

Now I'm trying to convert this to 'C' so that I can use it in Code Composer Studio. I hope i'll get help on this too. Thank you very much.

Share this post


Link to post
Share on other sites

G'day.

Have got the Stellaris sending to the 430 OK, led flashing and all that. I'm now trying to get data back from the 430.

The 430 is normally in RX mode, so when I want to send data back to Stellaris  I do a radio.flush() then have a radio.enableRX() as the next instruction (also put a delay in but made no difference) . But the data not sent, and the 430 can no longer Rx Stellaris commands

What noob thing am I doing.

Grant.

Share this post


Link to post
Share on other sites

G'day,

Seems whenever I do a post I often find the answer.

My problem was solved by a  radio.autoAck(false). This turns auto ack off.  Anyway all is good in the land of Oz.

Share this post


Link to post
Share on other sites

Not sure, just used all the default settings and let the lib set them up.

Now that I have got good comms will start to play around with some of these settings.

Share this post


Link to post
Share on other sites

Hello,

I have a small problem with the library. I need to understand how radio.setRXaddress(); works. I mean, I don't understand, why the address in examples is { 0xDE, 0xAD, 0xBE, 0xEF, 0x01 }

 

What I need is loop going through some number of addresses and send message to each of them.

 

For example:

I have 100 of devices waiting for "start" message. I want the main unit to call each of the devices separately and send the "start" command. I need to know how to incrementaly set the address and call the devices. And of course those devices would have set the RX address permanently on exact address. But my point is, I don't know how to work with the addresses.

 

could someone show me example code of loop going through some number (256) or all possible addresses?

 

what is the address structure, are all five bytes arbitrary or are some of them fixed?

 

Thank you

 

Share this post


Link to post
Share on other sites

G'day

Am sure there are smarter guys than me (heck there always is) but do have a few  RF remotes talking to me.  I put a hex switch in each slave that sets the last byte in the address array..

The other address bytes  don't matter, as long as radio.setTxaddress in master (in my case have a stellaris polling the slaves) is the same as radio.setRXaddress in the 430.

 

A simple for loop incrementing the LSB address then polls each slave.

 

There is also an option to reduce the total number of byte in the address, but have not bothered with that at this stage.

Grant

hawwwran likes this

Share this post


Link to post
Share on other sites

Ok, so you are saying what I thought, that this approach would work? Ok, I'll use it. Thank you

const uint8_t rxaddr[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0x01 };
.
.
.
for(uint8_t i=0x01; i<0xff; i++)
{
  txaddr[4]=i
  radio.setTXaddress(txaddr);
}
.
.
.

Still would be nice if someone would describe how the addressing works.

Share this post


Link to post
Share on other sites

Addressing is quite simple, it's 5 bytes. Incoming packets are continually filtered to find packets whose address matches the 5 byte RX address configured on the transceiver.

 

There is more to it under the hood but this library is intentionally designed for you to ignore them.

 

Btw since the .setRXaddress() and .setTXaddress() methods just take a pointer, you could pass a string to it and that would work. Just be sure it is 5-chars long.

 

Sent from my Galaxy Note II with Tapatalk

 

 

hawwwran likes this

Share this post


Link to post
Share on other sites

Great!

So, let's say I plan to have maximum 20 devices (in fact about five, but just to be sure). That makes an alphabet enough big to use it as ID's like this to go through ids from dev-a to dev-z to make the addresses easy to remember.

const uint8_t txaddr[] = "dev-a";
.
.
.
for(uint8_t i='a'; i<='z'; i++)
{
  txaddr[4]=i
  radio.setTXaddress(txaddr);
}
.
.
.

and of course on the RX side (for example)

const uint8_t rxaddr[] = "dev-a";

So you say it's valid?

 

Thank you

Share this post


Link to post
Share on other sites

Great!

So, let's say I plan to have maximum 20 devices (in fact about five, but just to be sure). That makes an alphabet enough big to use it as ID's like this to go through ids from dev-a to dev-z to make the addresses easy to remember.

 

const uint8_t txaddr[] = "dev-a";

.

.

.

for(uint8_t i='a'; i<='z'; i++)

{

txaddr[4]=i

radio.setTXaddress(txaddr);

}

.

.

.

 

and of course on the RX side (for example)

 

const uint8_t rxaddr[] = "dev-a";

So you say it's valid?

 

Thank you

 

Yep that should work. If there are any compilation errors or warnings it's probably a type cast required or something, but I don't think it should error.

 

Sent from my Galaxy Note II with Tapatalk

 

 

hawwwran likes this

Share this post


Link to post
Share on other sites

If someone else is interested in scanning for active devices on known array of addresses, here is my working solution:

 

Device finder code:

#include "Enrf24.h"
#include "nRF24L01.h"
#include <string.h>
#include <SPI.h>

Enrf24 radio(P2_0, P2_1, P2_2);  // P2.0=CE, P2.1=CSN, P2.2=IRQ

const char IDENTIFY=1;

char rxaddr[] = {'d','e','v','-','0'}; // address of commander (note that it's out of sequence of device addresses)
char txaddr[] = {'d','e','v','-','a'}; // address of the first device

unsigned long mil;
unsigned long prev_time;

char ch='a';  // set first "address"
int verbosity=2; //0 - none, 1 - only responsive devices, 2 - only found devices, 3 - all tries
char packet[]={0,0,0}; // set empty packet. First byte is command ID, the rest is DATA

void setup() {
  Serial.begin(9600);

  // error led
  pinMode(P1_0,OUTPUT);
  digitalWrite(P1_0,LOW);
  // success led
  pinMode(P2_3,OUTPUT);
  digitalWrite(P2_3,LOW);

  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(1); // MSB-first

  radio.begin();  // Defaults 1Mbps, channel 0, max TX power
 
  radio.setTXaddress((void*)txaddr);
  radio.setRXaddress((void*)rxaddr);
  radio.enableRX();
}

void identifyDevices(int slow=0) // slow var is because of the serial output. If you need high verbosity, the serial could be overloaded
{
  char inbuf[33];
 
  if(ch>'z'){ch='a';}
  txaddr[4]=ch;
  ch++;
  radio.setTXaddress((void*)txaddr);
 
  digitalWrite(P1_0,LOW);
  digitalWrite(P2_3,LOW);
 
  packet[0]=IDENTIFY;
 
  radio.lastTXfailed=false;
  radio.print(packet);
  radio.flush();
  if(radio.lastTXfailed)
  {
    // blink error led (data was not received)
    digitalWrite(P1_0,HIGH);
    delay(1);
    digitalWrite(P1_0,LOW);
    
    if(verbosity>2)
    {
      // No device detected on tested address
      Serial.print("NONE [");
      Serial.print(txaddr[0]);
      Serial.print(txaddr[1]);
      Serial.print(txaddr[2]);
      Serial.print(txaddr[3]);
      Serial.print(txaddr[4]);
      Serial.println("]");
    }
  }
  else
  {
    // blink success led (data was received)
    digitalWrite(P2_3,HIGH);
    delay(5);
    digitalWrite(P2_3,LOW);
    //
    delta_set(); // set delta (start timer)
    while (!radio.available(true) && delta_get()<10) // wait 10ms for data to receive
    {
      
    }
    if (radio.read(inbuf))
    {
      if(verbosity>0)
      {
        // device found and respond received
        Serial.print("OK [");
        Serial.print(txaddr[0]);
        Serial.print(txaddr[1]);
        Serial.print(txaddr[2]);
        Serial.print(txaddr[3]);
        Serial.print(txaddr[4]);
        Serial.print("] - ");
        Serial.println(inbuf);
      }
    }
    else
    {
      if(verbosity>1)
      {
        // device found, but no response
        Serial.print("NO RESPONSE [");
        Serial.print(txaddr[0]);
        Serial.print(txaddr[1]);
        Serial.print(txaddr[2]);
        Serial.print(txaddr[3]);
        Serial.print(txaddr[4]);
        Serial.println("]");
      }
    }
    //
  }
  delay(slow);
}

void loop()
{  
  identifyDevices(1000);
}

unsigned long delta_set() {
      prev_time = millis();
      return prev_time;
}

unsigned long delta_get() {
      unsigned long time;
      unsigned long delta;
      
      time = millis();
      if (time < prev_time) { // Timer overflow
            delta = 0xffffffff - prev_time + time + 1;
      } else {
            delta = time - prev_time;
      }
      return delta;
}

Demo device code:

#include "Enrf24.h"
#include "nRF24L01.h"
#include <string.h>
#include <SPI.h>

Enrf24 radio(P2_0, P2_1, P2_2); // P2.0=CE, P2.1=CSN, P2.2=IRQ

const char IDENTIFY=1;

char rxaddr[] = {'d','e','v','-','g'}; // address of the device
char txaddr[] = {'d','e','v','-','0'}; // address of the commander

void setup() {
  Serial.begin(9600);

  SPI.begin();
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(1); // MSB-first
 
  radio.begin();  // Defaults 1Mbps, channel 0, max TX power

  radio.setRXaddress((void*)rxaddr);
  radio.setTXaddress((void*)txaddr);
 
  pinMode(P1_0, OUTPUT);
  digitalWrite(P1_0, LOW);
  pinMode(P1_3, OUTPUT);
  digitalWrite(P1_3, LOW);
  pinMode(P1_4, OUTPUT);
  digitalWrite(P1_4, LOW);
 
  radio.enableRX();  // Start listening
}

void loop() {
  char inbuf[33];
 
  while (!radio.available(true))
  {
 
  }
  if (radio.read(inbuf))
  {
    Serial.println(inbuf);
    if (inbuf[0]==IDENTIFY)
    {
     // if IDENTIFIcation is required, respond
     radio.print("Demo device #1");
     radio.flush();
    }
  }
 
}

It goes through all addresses (dev-a to dev-z) in about half a second (without the slow variable, with serial output verbosity 2 and with delays for led blink).
 

gssmahadevan and bluehash like this

Share this post


Link to post
Share on other sites

But I found one problem I don't understand.

If there are more devices (two), every second device is marked ad non responding. It does not seem to be problem of the device, but the finder. It simply looks, that sometimes, the message is not sent, but on the sender device it looks like it was, so it is waiting for the response, but the response does not happen. But next time it's ok and then it's not and so on.

 

Any idea?

Share this post


Link to post
Share on other sites

Have you tried it with radio.autoAck(false). I had some funny things going on awhile ago and stopping the acks fixed it up.

Share this post


Link to post
Share on other sites

I think it's a good idea to keep the autoAck's enabled, but 10ms seems like it would lie inside the window of retransmits so his finder might be missing some reply packets from the device that might be deep into its retransmits.

 

edit:

What I'm thinking of here, is the default autoack settings are specified as:

    void setAutoAckParams(uint8_t autoretry_count=15, uint16_t autoretry_timeout=2000);

 

timeout in microseconds, so the transmitter waits up to 2ms for the ACK reply packet from the receiver before retrying.  It will do that up to 15 times before giving up.  Keep in mind in between those 2ms windows the transmitter is busy re-transmitting the frame, so that takes up more time.  So the bare minimum you should wait is 30ms plus a bit, see the nRF24L01+ datasheet for more details on estimating the OTA time for a particular bitrate/packet length.

 

If these lost packets happen sporadically/randomly then it is probably just random noise in the 2.4GHz band screwing things up (and that is common as it's shared with WiFi, Bluetooth, other proprietary 2.4GHz like some wireless headphones or cordless telephones); extending the timeout gives you more of a fighting chance of receiving one of the retransmits before giving up.  If it's very very regular--like every 4th packet--then it might be a bug in my library or your code that's not obvious at the moment.

Share this post


Link to post
Share on other sites

Hi. The auto ACK is essential for me.

I use MSP430G2553

 

If you are talking about the 10ms in the wait() waiting for receiving message from device after confirmed package was sent, then I think it's not the problem. Don't know why or how, but even 1ms wait works the same and 1000ms as well. If the message is received, the delta_time is 0ms. If it does the "bug", it waits all 1000ms (or other time whatever I set) and still receive no data. So my Idea is... the problem has to be that the problem is on the side of the device (but auto ack says it's delivered) or on sender (discarded received message somehow, but even waiting on the side of the device 100ms before sending back message didn't work)

 

I'll try again some ideas to confirm the behavior, the devices are one next to the other, no noise on the channel 0

 

EDIT: And it's happening precisely regurarely. Here is small dump from my serial reader when I added second try send/read if first failed. You can see the "OK #2" which is second attempt success. And it's not just the dev-a device's problem. If I turn one off and on again, I can change the #2 to the dev-g device. and another thing to think, If there is only one device, it works everytime for the first attempt

 

OK #2[dev-a] - CameraMover
OK [dev-g] - Demo device #1
OK #2[dev-a] - CameraMover
OK [dev-g] - Demo device #1
OK #2[dev-a] - CameraMover
OK [dev-g] - Demo device #1

Share this post


Link to post
Share on other sites

Not saying to permanently disable it, just turn it off [radio.autoAck(false)]for a test and see is it makes any difference

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