Jump to content
43oh

[Energia Library] Nordic nRF24L01+ library


Recommended Posts

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

 

 

Link to post
Share on other sites
  • Replies 352
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Popular Posts

Hi folks... So I'm a little new to Energia, but since I wrote a library for the nRF24L01+ digital transceivers for native C-based apps I figured it'd be a great idea to port this to Energia.   I'm r

Ok, so I ported the Enrf library over so that it works with both MSP430 and Stellaris.  Seems to work great.  I am watching the tx rx demo between msp430g2553 (on the RX side), and the StellarPad doin

Okie doke - https://github.com/spirilis/Enrf24   The examples are the same as the ones I posted... I'll write up the API in a wiki page soon.  Alternately, I put documentation in the Enrf24.h file f

Posted Images

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).
 

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?

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.

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

Link to post
Share on other sites

So, I turned off the auto ACK and changed the check for lastTXfailed to check what address the message was sent to, because I know the two which exists. That means, that the program is doing the same... sending message to all addresses, but it's waiting for the response only for the two of them. And the result is, that it's working well

 

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

Link to post
Share on other sites

I tried put delays to different places with no result.

 

On device - wait 100ms before sending reply

 

on sender - wait 500ms in the wait() before giving it up

                 - wait 500ms before the wait()

                 - wait 500ms after the wait() before .read

 

nothing helped, still the same problem

 

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

Link to post
Share on other sites

Here's my code for everyone who would like test it:

 

Sender device periodically checks all addresses from dev-a to dev-z and all found devices prints to serial

 

Receiver device is listening on it's address and if receives the right command, it send's back identification string which should be printed to serial by sender device

 

Sender 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','-','0'};
char txaddr[] = {'d','e','v','-','a'};

unsigned long mil;
unsigned long prev_time;

char ch='a';
int verbosity=2; //0 - none, 1 - only responsive devices, 2 - only found devices, 3 - all tries
char packet[]={0,0,0};

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

  // error
  pinMode(P1_0,OUTPUT);
  digitalWrite(P1_0,LOW);
  // success
  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

  for(int i=0; i<10; i++)
  {
    digitalWrite(P1_0,HIGH);
    digitalWrite(P2_3,HIGH);
    delay(50);
    digitalWrite(P1_0,LOW);
    digitalWrite(P2_3,LOW);
    delay(50);
  }
  digitalWrite(P1_0,HIGH);
  digitalWrite(P2_3,HIGH);
  delay(1000);
  digitalWrite(P1_0,LOW);
  digitalWrite(P2_3,LOW);
 
  radio.setTXaddress((void*)txaddr);
  radio.setRXaddress((void*)rxaddr);
  radio.enableRX();
  //radio.autoAck(false);
}

void identifyDevices(int slow=0)
{
  char inbuf[33];
 
  if(ch>'z'){ch='a';}
  txaddr[4]=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(ch!='a' && ch!='g'){radio.lastTXfailed=true;}
 
  //Serial.println(ch);
 
  //if(ch!='a' && ch!='g')
  if(radio.lastTXfailed)
  {
    digitalWrite(P1_0,HIGH);
    delay(1);
    digitalWrite(P1_0,LOW);
    
    if(verbosity>2)
    {
      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
  {
    digitalWrite(P2_3,HIGH);
    delay(5);
    digitalWrite(P2_3,LOW);
    //
    delta_set();
    while (!radio.available(true) && delta_get()<500)
    {
      
    }
    if (radio.read(inbuf))
    {
      if(verbosity>0)
      {
        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
    {
      radio.lastTXfailed=false;
      radio.print(packet);
      radio.flush();
      if(!radio.lastTXfailed)
      {
        delta_set();
        while (!radio.available(true) && delta_get()<500){}
        if (radio.read(inbuf))
        {
          if(verbosity>0)
          {
            Serial.print("OK #2[");
            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)
          {
            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("]");
          }
        }
      }
      else
      {
        if(verbosity>2)
        {
          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("]");
        }
      }
    }
    //
  }
  ch++;
  delay(slow);
}

void loop()
{  
  identifyDevices(100);
}

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;
}

receiver 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'};
char txaddr[] = {'d','e','v','-','0'};

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);
 
  digitalWrite(P1_0, HIGH);
  delay(100);
  digitalWrite(P1_0, LOW);
  delay(100);
  digitalWrite(P1_0, HIGH);
  delay(100);
  digitalWrite(P1_0, LOW);
  delay(100);
 
  radio.enableRX();  // Start listening
}

void loop() {
 
  char inbuf[33];
 
  while (!radio.available(true))
  {
 
  }
  if (radio.read(inbuf))
  {
    Serial.println(inbuf);
    if (inbuf[0]==IDENTIFY)
    {
     radio.lastTXfailed=false;
     radio.print("Demo device #1");
     radio.flush();
     if(radio.lastTXfailed)
     {
       radio.print("Demo device2 #1");
       radio.flush();
     }
    }
  }
 
}
Link to post
Share on other sites

I have a question for you who know how to calculate it.

 

I woud like to make small device which would periodically (every 10s) sent (let's say 5 bytes if it's important). I would use MCU MSP430G2553 (or better G2452?)

 

My question is, how long will it work on battery CR2032 3V 220mAh?

 

I'm planning to use deepsleep and such to maximize the time, but I have no idea what time it could be, I don't know the consumption of NRF24 and the G2553 (or G2452) and don't know how to calculate it.

 

EDIT: Could someone show me an example how to sleep G2553 for 10s, blink LED and sleep again? Thank you

 

Thank you

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...