Author Topic: Error using NRF24L01  (Read 1544 times)

digi_guy

  • Jr. Member
  • **
  • Posts: 87
Error using NRF24L01
« on: January 31, 2018, 10:17:21 am »
{second try}

Curious if anyone has gotten the NRF examples to load on their Digispark Pro.

I tried the examples originally found in Arduino, then tried the "newer" RF24-master but keep getting the same message

Code: [Select]
C:\Users\ericm\AppData\Local\Temp\build92734951072125737.tmp\SPI\SPI.cpp.o C:\Users\ericm\AppData\Local\Temp\build92734951072125737.tmp\RF24-master\RF24.cpp.o {archive_file_path} -LC:\Users\ericm\AppData\Local\Temp\build92734951072125737.tmp -lm

{archive_file_path}(wiring_digital.c.o):(.progmem.data.digital_pin_to_bit_mask_PGM+0x0): multiple definition of `digital_pin_to_bit_mask_PGM'
{archive_file_path}(pins_arduino.c.o):(.progmem.data.digital_pin_to_bit_mask_PGM+0x0): first defined here
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/bin/ld.exe: Warning: size of symbol `digital_pin_to_bit_mask_PGM' changed from 6 in {archive_file_path}(pins_arduino.c.o) to 14 in {archive_file_path}(wiring_digital.c.o)
{archive_file_path}(wiring_digital.c.o): In function `turnOffPWM':
C:\Users\ericm\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\pro/wiring_digital.c:33: multiple definition of `digital_pin_to_port_PGM'
{archive_file_path}(pins_arduino.c.o):(.progmem.data.digital_pin_to_port_PGM+0x0): first defined here
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/bin/ld.exe: Warning: size of symbol `digital_pin_to_port_PGM' changed from 6 in {archive_file_path}(pins_arduino.c.o) to 14 in {archive_file_path}(wiring_digital.c.o)
{archive_file_path}(wiring_digital.c.o): In function `turnOffPWM':
C:\Users\ericm\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\pro/wiring_digital.c:33: multiple definition of `port_to_mode_PGM'
{archive_file_path}(pins_arduino.c.o):(.progmem.data.port_to_mode_PGM+0x0): first defined here
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/bin/ld.exe: Warning: size of symbol `port_to_mode_PGM' changed from 2 in {archive_file_path}(pins_arduino.c.o) to 6 in {archive_file_path}(wiring_digital.c.o)
{archive_file_path}(wiring_digital.c.o): In function `turnOffPWM':
C:\Users\ericm\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\pro/wiring_digital.c:33: multiple definition of `port_to_output_PGM'
{archive_file_path}(pins_arduino.c.o):(.progmem.data.port_to_output_PGM+0x0): first defined here
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/bin/ld.exe: Warning: size of symbol `port_to_output_PGM' changed from 2 in {archive_file_path}(pins_arduino.c.o) to 6 in {archive_file_path}(wiring_digital.c.o)
{archive_file_path}(wiring_digital.c.o): In function `turnOffPWM':
C:\Users\ericm\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\pro/wiring_digital.c:33: multiple definition of `digital_pin_to_timer_PGM'
{archive_file_path}(pins_arduino.c.o):(.progmem.data.digital_pin_to_timer_PGM+0x0): first defined here
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/bin/ld.exe: Warning: size of symbol `digital_pin_to_timer_PGM' changed from 6 in {archive_file_path}(pins_arduino.c.o) to 16 in {archive_file_path}(wiring_digital.c.o)
{archive_file_path}(wiring_digital.c.o): In function `turnOffPWM':
C:\Users\ericm\AppData\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\cores\pro/wiring_digital.c:33: multiple definition of `port_to_input_PGM'
{archive_file_path}(pins_arduino.c.o):(.progmem.data.port_to_input_PGM+0x0): first defined here
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/bin/ld.exe: Warning: size of symbol `port_to_input_PGM' changed from 2 in {archive_file_path}(pins_arduino.c.o) to 6 in {archive_file_path}(wiring_digital.c.o)
c:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/bin/ld.exe: avr:25 architecture of input file `{archive_file_path}(pins_arduino.c.o)' is incompatible with avr:35 output
collect2.exe: error: ld returned 1 exit status
Error compiling.

The program I was trying to run was "Getting Started"

It seems to be specific to the Oak , I wonder if there is a error in assigning pins.

If anyone has gotten NRF working on their Oak please let me know.

PeterF

  • Hero Member
  • *****
  • Posts: 883
Re: Error using NRF24L01
« Reply #1 on: February 02, 2018, 11:06:08 pm »
Ok, I'm a bit confused here... you start talking about the Digispark Pro (and are posting in the Digispark Pro Support forum)... and then end up talking about the Oak... whilst the compile errors you're showing are for an AVR processor, so probably the Pro??

If it's the Digispark Pro, one thing to be aware of very quickly is that it only has 512 byes of SRAM ("dynamic memory" in the Arduino IDE)... and you can only use 496 bytes of that due to some minor overhead. The RF24 GettingStarted sketch without any changes blows it out to 510 bytes... so that ain't going to play nicely. If you shorten or comment out one or two of the longer printf statements that will cure that problem... that stuff really should have been stored in flash memory to free up the SRAM, but isn't a problem for the boards that demo is designed for...

After trimming a few bits, I was able to compile it fine on Windows on Arduinio IDE 1.8.5... Don't have a Digispark setup with NRF24 handy, so can't tell if it actually works atm...

Code: [Select]
Sketch uses 9236 bytes (62%) of program storage space. Maximum is 14844 bytes.
Global variables use 398 bytes (80%) of dynamic memory, leaving 98 bytes for local variables. Maximum is 496 bytes.
Low memory available, stability problems may occur.

Code: [Select]
/*
 Copyright (C) 2011 J. Coliz <maniacbug@ymail.com>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */

/**
 * Example for Getting Started with nRF24L01+ radios.
 *
 * This is an example of how to use the RF24 class.  Write this sketch to two
 * different nodes.  Put one of the nodes into 'transmit' mode by connecting
 * with the serial monitor and sending a 'T'.  The ping node sends the current
 * time to the pong node, which responds by sending the value back.  The ping
 * node can then see how long the whole cycle took.
 */

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "printf.h"

//
// Hardware configuration
//

// Set up nRF24L01 radio on SPI bus plus pins 9 & 10

RF24 radio(9,10);

//
// Topology
//

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

//
// Role management
//
// Set up role.  This sketch uses the same software for all the nodes
// in this system.  Doing so greatly simplifies testing. 
//

// The various roles supported by this sketch
typedef enum { role_ping_out = 1, role_pong_back } role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};

// The role of the current running sketch
role_e role = role_pong_back;

void setup(void)
{
  //
  // Print preamble
  //

  Serial.begin(57600);
  printf_begin();
  //printf("\n\rRF24/examples/GettingStarted/\n\r");
  printf("ROLE: %s\n\r",role_friendly_name[role]);
  printf("'T' to begin transmitting\n\r");

  //
  // Setup and configure rf radio
  //

  radio.begin();

  // optionally, increase the delay between retries & # of retries
  radio.setRetries(15,15);

  // optionally, reduce the payload size.  seems to
  // improve reliability
  //radio.setPayloadSize(8);

  //
  // Open pipes to other nodes for communication
  //

  // This simple sketch opens two pipes for these two nodes to communicate
  // back and forth.
  // Open 'our' pipe for writing
  // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)

  //if ( role == role_ping_out )
  {
    //radio.openWritingPipe(pipes[0]);
    radio.openReadingPipe(1,pipes[1]);
  }
  //else
  {
    //radio.openWritingPipe(pipes[1]);
    //radio.openReadingPipe(1,pipes[0]);
  }

  //
  // Start listening
  //

  radio.startListening();

  //
  // Dump the configuration of the rf unit for debugging
  //

  radio.printDetails();
}

void loop(void)
{
  //
  // Ping out role.  Repeatedly send the current time
  //

  if (role == role_ping_out)
  {
    // First, stop listening so we can talk.
    radio.stopListening();

    // Take the time, and send it.  This will block until complete
    unsigned long time = millis();
    printf("Now sending %lu...",time);
    bool ok = radio.write( &time, sizeof(unsigned long) );
   
    if (ok)
      printf("ok...");
    else
      printf("failed.\n\r");

    // Now, continue listening
    radio.startListening();

    // Wait here until we get a response, or timeout (250ms)
    unsigned long started_waiting_at = millis();
    bool timeout = false;
    while ( ! radio.available() && ! timeout )
      if (millis() - started_waiting_at > 200 )
        timeout = true;

    // Describe the results
    if ( timeout )
    {
      printf("Failed, response timed out.\n\r");
    }
    else
    {
      // Grab the response, compare, and send to debugging spew
      unsigned long got_time;
      radio.read( &got_time, sizeof(unsigned long) );

      // Spew it
      printf("Got response %lu, round-trip delay: %lu\n\r",got_time,millis()-got_time);
    }

    // Try again 1s later
    delay(1000);
  }

  //
  // Pong back role.  Receive each packet, dump it out, and send it back
  //

  if ( role == role_pong_back )
  {
    // if there is data ready
    if ( radio.available() )
    {
      // Dump the payloads until we've gotten everything
      unsigned long got_time;
      bool done = false;
      while (!done)
      {
        // Fetch the payload, and see if this was the last one.
        done = radio.read( &got_time, sizeof(unsigned long) );

        // Spew it
        printf("Got payload %lu...",got_time);

// Delay just a little bit to let the other unit
// make the transition to receiver
delay(20);
      }

      // First, stop listening so we can talk
      radio.stopListening();

      // Send the final one back.
      radio.write( &got_time, sizeof(unsigned long) );
      printf("Sent response.\n\r");

      // Now, resume listening so we catch the next packets.
      radio.startListening();
    }
  }

  //
  // Change roles
  //

  if ( Serial.available() )
  {
    char c = toupper(Serial.read());
    if ( c == 'T' && role == role_pong_back )
    {
      printf("TRANSMIT ROLE -'R' TO SWITCH\n\r");

      // Become the primary transmitter (ping out)
      role = role_ping_out;
      radio.openWritingPipe(pipes[0]);
      radio.openReadingPipe(1,pipes[1]);
    }
    else if ( c == 'R' && role == role_ping_out )
    {
      printf("RECEIVE ROLE - PRESS 'T' TO SWITCH\n\r");
     
      // Become the primary receiver (pong back)
      role = role_pong_back;
      radio.openWritingPipe(pipes[1]);
      radio.openReadingPipe(1,pipes[0]);
    }
  }
}

« Last Edit: February 05, 2018, 02:54:18 pm by PeterF »

digi_guy

  • Jr. Member
  • **
  • Posts: 87
Re: Error using NRF24L01
« Reply #2 on: February 05, 2018, 11:05:01 am »
Sorry for the confusion. I started with the Pro, couldn't get it to compile, and assumed something was wrong with the libraries. Then tried the Oak.

Still haven't managed to get anything to work. Currently going back and forth between the Pro, Oak, and RPi.

The code you posted isn't for the Pro since it still has the printf.h libraries. I swapped that out for digikeyboard hoping that might help, but I think there are some issues with the pins. Same issue with the Oak.

I've also noticed that setting the channels is messed up, especially on the RPi. Really curious to know how anyone managed to get this to work. I'm also not 100% convinced the NRF modules are working.

PeterF

  • Hero Member
  • *****
  • Posts: 883
Re: Error using NRF24L01
« Reply #3 on: February 05, 2018, 02:52:46 pm »
lol... we might be struggling to get some of the same stuff working at the moment then... I'm trying to get a RPi Zero W to talk NRF, and it's being stubborn. I have older Arduino Uno/Pro Mini code that is working just fine for transmit and receive, and according to the getting started sketch the RPi Zero W is detecting the NRF24, but doesn't seem to be able to transmit or receive...

No, that is the library and example for the Digispark Pro, and it did successfully compile for the Digispark Pro board type. And if you check the last version of the gettingstarted code on github for the Digispark boards (AVR), it does use the printf library. It is NOT the library or example code for the Oak. Possibly what is happening is you have installed both the Digispark and then Oak boards and core libraries, and now the two are conflicting when you try to compile it for the Digispark

I run a setup whereby each architecture/board type (Digispark, Oak, STM32, etc) has a unique sketchbook folder, which means any libraries that are customised for that architecture or board don't get overwritten or conflicted. Plus it means all the sketches for that given board type stay together. Might be worth considering as you'll have no end of issues. Essentially, create a sketchbook folder for each major architecture you might have different libraries for (Arduino AVR, Digispark, STM32, ESP8266, Oak, etc, etc), and then install only the necessary board support package for each. Install the specific libraries into each. And then choose which one to use via a desktop shortcut that runs a script I have in each sketchbook folder. (I have all my sketchbook folders in Dropbox so I can use the same setup and code on multiple machines... so I have multiple scripts to suit each machine and Arduino IDE insall path).

Hopefully, this is of some help to you. The different preferences file makes it so that the sketchbook path, and selected board type don't need to be changed manually every time, and also means any other specific settings are preserved just for that profile. I used to just tweak the preferences file, but it took way too long. This seems to be working quite well now once it is setup up.

Code: [Select]
@ECHO OFF
SET IDE_PATH=E:\Programming\arduino-1.8.5
"%IDE_PATH%\arduino.exe" --preferences-file preferences-desktop.txt

« Last Edit: February 05, 2018, 02:59:16 pm by PeterF »

digi_guy

  • Jr. Member
  • **
  • Posts: 87
Re: Error using NRF24L01
« Reply #4 on: February 06, 2018, 01:21:36 pm »
Hey Peter, thanks for all that. I wanted to share where I'm at with things.

Right now I've gotten a Pro to write (send) which returned an "okay" (see code below) which up until this point had always returned 0 (false). It seems the trick was to switch the MISO/MOSI pins (8 and 10). I have CE on pin 9, and CS on pin 12. It's really sensitive to those pins. I haven't been able to get any other pins to work.

What I've noticed is that it's not stable/consistent. I'll get lots of "failed" and then a few "okays."

I've also noticed that I think at least 1 of my 4 NRFs doesn't work. Which makes for a fun extra variable. I've also noticed that the NRF is very sensitive to touch, and moving it around seems to help, lots of obvious jokes there.

So far I haven't gotten this to work with the Oak. I have the Arduino IDE set up for both, and haven't made the changes you suggested since I currently have a glimmer of hope.

And right now I don't think the Raspberry Pis are able to make use of the NRF boards. I tried dozens of variations, using three different Pis. I think one of the biggest problems is that the NRFs take a huge amount of power, which the Pis can't support on their own. Oddly enough, I'm right now using one of the Oaks to provide reasonably stable 3.3V.

Keep me posted.

Code: [Select]
#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include "DigiKeyboard.h"

// #include "printf.h" print doesn't work with the pro


//
// Hardware configuration
//

// Set up nRF24L01 radio on SPI bus plus pins 9 & 12

RF24 radio(9,12);  //will have to change the pins for the pro

//
// Topology
//

// Radio pipe addresses for the 2 nodes to communicate.
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL }; // i should set up both pi's to scan
unsigned long set_channel = 32;
unsigned long get_channel;

//
// Role management
//
// Set up role.  This sketch uses the same software for all the nodes
// in this system.  Doing so greatly simplifies testing. 
//

// The various roles supported by this sketch
typedef enum { role_ping_out = 1, role_pong_back } role_e;

// The debug-friendly names of those roles
const char* role_friendly_name[] = { "invalid", "Ping out", "Pong back"};

// The role of the current running sketch
role_e role = role_ping_out;

void setup(void)
{
  //
  // Print preamble
  //
 
  DigiKeyboard.println("Hello Digispark!");
  DigiKeyboard.print("ROLE: ");

  //
  // Setup and configure rf radio
  //

  radio.begin();

  // optionally, increase the delay between retries & # of retries

  radio.setRetries(15,15);
  radio.setDataRate(RF24_1MBPS);

  // optionally, reduce the payload size.  seems to
  // improve reliability
  //radio.setPayloadSize(8);

  //
  // Open pipes to other nodes for communication
  //

  // This simple sketch opens two pipes for these two nodes to communicate
  // back and forth.
  // Open 'our' pipe for writing
  // Open the 'other' pipe for reading, in position #1 (we can have up to 5 pipes open for reading)

  if ( role == role_ping_out )
  {
    DigiKeyboard.println("ping_out");
    radio.openWritingPipe(pipes[0]);
    radio.openReadingPipe(1,pipes[1]);
  }
  else
  {
    DigiKeyboard.println("pong_back");
    radio.openWritingPipe(pipes[1]);
    radio.openReadingPipe(1,pipes[0]);
    radio.startListening();
  }

  //
  // Start listening
  //
  radio.setChannel(set_channel);
  get_channel= set_channel;
  DigiKeyboard.print("listening on channel: ");
  if (get_channel == 32) DigiKeyboard.println("32");
  else DigiKeyboard.println("don't know");
 
 

}

void loop(void)
{

  //
  // Ping out role.  Repeatedly send the current time
  //

  if (role == role_ping_out)
  {
    // First, stop listening so we can talk.
    radio.stopListening();

    // Take the time, and send it.  This will block until complete
    unsigned long time = millis();
    DigiKeyboard.println("Now sending "+String(time));
    bool ok = radio.write( &time, sizeof(unsigned long) );
    delay(200);
    if (ok)
      DigiKeyboard.println("ok...");
    else
      DigiKeyboard.println("failed");

    // Now, continue listening
    radio.startListening();

    // Wait here until we get a response, or timeout (250ms)
    unsigned long started_waiting_at = millis();
    bool timeout = false;
    while ( ! radio.available() && ! timeout )
      if (millis() - started_waiting_at > 200 )
        timeout = true;

    // Describe the results
    if ( timeout )
    {
      DigiKeyboard.println("Failed, response timed out.");
    }
    else
    {
      // Grab the response, compare, and send to debugging spew
      unsigned long got_time;
      radio.read( &got_time, sizeof(unsigned long) );

      // Spew it
      DigiKeyboard.println("Got response "+String(got_time)+" round-trip delay: "+String(millis()-got_time));
    }

    // Try again 1s later
    delay(1000);
  }

  //
  // Pong back role.  Receive each packet, dump it out, and send it back
  //

  if ( role == role_pong_back )
  {
    // if there is data ready
    if ( radio.available() )
    {
      DigiKeyboard.println("heard something");
      // Dump the payloads until we've gotten everything
      unsigned long got_time;
      bool done = false;
      while (!done)
      {
        // Fetch the payload, and see if this was the last one.
        done = radio.read( &got_time, sizeof(unsigned long) );

        // Spew it
        DigiKeyboard.println("Got payload ");

   // Delay just a little bit to let the other unit
   // make the transition to receiver
   delay(20);
      }

      // First, stop listening so we can talk
      radio.stopListening();

      // Send the final one back.
      radio.write( &got_time, sizeof(unsigned long) );
      DigiKeyboard.println("Sent response");

      // Now, resume listening so we catch the next packets.
      radio.startListening();
    }
  }


}


/*


Hello Digispark!
ROLE: ping_out
listening on channel: 32

failed
Failed, response timed out.

failed
Failed, response timed out.

ok...


failed
Failed, response timed out.




 */

PeterF

  • Hero Member
  • *****
  • Posts: 883
Re: Error using NRF24L01
« Reply #5 on: February 06, 2018, 04:35:08 pm »
Power shouldn't be a problem for the NRFs, as the low range ones (the ones without the extra RF preamps on them) actually don't need a lot of lower. A lot of the mysensor guys have had no problems running them from an RPis 3.3v supply, although usually with a 10 or 100 uf Capacitor for some buffering for when it transmits. In my case I'm using an adapter board that plugs directly in, so will have to double check the pinout, and then see what's going on. In my case, I'm running it from the 5v of the RPi through a 3.3v regulator on the adapter, although I could change it to 3.3v via a jumper if I want.

I'll see what luck I have with an Oak, pretty sure I have a NRF shield knocking around for it...