2
\$\begingroup\$

I am trying to send an integer through an Rf24 node to another. Unfortunately, the radio.write() functions sends an unsigned int only. How can I send a phrase or an integer through it ?

EDIT: this is the link to the library https://github.com/maniacbug/RF24

This is the code of the transmitter & receiver:

/*
 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 RF Radio Ping Pair
 *
 * This is an example of how to use the RF24 class.  Write this sketch to two different nodes,
 * connect the role_pin to ground on one.  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(8,7);

// sets the role of this unit in hardware.  Connect to GND to be the 'pong' receiver
// Leave open to be the 'ping' transmitter
const int role_pin = 3;

//
// 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 hardware itself specifies
// which node it is.
//
// This is done through the role_pin
//

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

void setup(void)
{
  //
  // Role
  //

  // set up the role pin
  pinMode(role_pin, INPUT);
  digitalWrite(role_pin,HIGH);
  delay(20); // Just to get a solid reading on the role pin

  // read the address pin, establish our role
  if ( ! digitalRead(role_pin) )
    role = role_ping_out;
  else
    role = role_pong_back;

  //
  // Print preamble
  //

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

  //
  // 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 int got_time_unsigned;
      int got_time = (int) got_time_unsigned;
      bool done = false;
      while (!done)
      {
        // Fetch the payload, and see if this was the last one.
        done = radio.read( &got_time_unsigned, 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();
    }
  }
}
// vim:cin:ai:sts=2 sw=2 ft=cpp

This is where magic happens:

unsigned long time = millis();
        printf("Now sending %lu...",time);
        bool ok = radio.write( &time, sizeof(unsigned long) );

This is where information gets received and displayed :

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);
\$\endgroup\$
2
  • \$\begingroup\$ Wouldnt casting it as an unsigned work, and then on your receiver side, cast it as a signed ? \$\endgroup\$
    – efox29
    Jul 6, 2013 at 22:38
  • \$\begingroup\$ 16-bits is 16-bits ... \$\endgroup\$
    – vicatcu
    Jul 6, 2013 at 23:05

3 Answers 3

4
\$\begingroup\$

Now you've included the library the read and write functions are declared as follows:

bool read( void* buf, uint8_t len );
bool write( const void* buf, uint8_t len );

So the first parameter is a pointer to any data type followed by the length to be transferred. In your case you could just use something like:

int16_t my_var;
bool ok = radio.write( &my_var, sizeof(my_var) );
radio.read( & my_var, sizeof(my_var) );

I normally prefer to include the variable name in the call to sizeof rather than the data type so that if you change it in the future you don't have to remember to change it in two or more places. For a string exactly the same code would work as long as it's declared as a fixed length, for example:

char my_var[10] = "Test";

Just be careful when using strings that you allow the extra character required for null terminating it, so the example above could hold a maximum of nine characters.

\$\endgroup\$
7
  • \$\begingroup\$ and in case of a string or a word ? \$\endgroup\$
    – Radolino
    Jul 7, 2013 at 6:34
  • 1
    \$\begingroup\$ @RobertoDelgazzo, I've added a string example. For other numeric types exactly the same code will work as long as they are declared the same way on the transmit and receive end and comms is between a pair of Arduinos. With a PC the byte order will be the same but some other processors use a different byte order, see en.wikipedia.org/wiki/Endianness. \$\endgroup\$
    – PeterJ
    Jul 7, 2013 at 6:43
  • \$\begingroup\$ I did what you said, and my_var = 100; so now it seems that it sends a number "6553700" all the time. I suppose "100" gets converted to 6553700 somehow.. \$\endgroup\$
    – Radolino
    Jul 7, 2013 at 6:44
  • 1
    \$\begingroup\$ @RobertoDelgazzo, just converting to binary and I can't think of a common problem that would give that result. Did the original code work? Also you probably have a problem displaying the number - that's above the range a 16 bit number can hold so even if you received total junk I wouldn't expect it to display a number that large. Just noticed you have a %lu - change that to %d for 16-bit signed number. \$\endgroup\$
    – PeterJ
    Jul 7, 2013 at 6:49
  • 1
    \$\begingroup\$ @RobertoDelgazzo, it's worth a read of the printf format strings at en.wikipedia.org/wiki/Printf_format_string but in that case it was expecting a long number, so it would have been including another two bytes of 'junk' of whatever happened to be in memory after your variable. \$\endgroup\$
    – PeterJ
    Jul 7, 2013 at 6:58
2
\$\begingroup\$

To expand on what efox29 and vicatcu said, in principle there's nothing stopping you casting your data to an unsigned int (I suspect the function uses a uint8_t) and then casting back on the other end, provided both ends can agree on what the original type was (for example if you send an integer but cast back to a char it won't make sense).

When you switch between signed and unsigned, all that changes is the interpretation when mathematical operations are applied. For example in unsigned you roll around from zero to the highest positive number instead of going negative, and with something like 2's complement the underlying bits won't even change.

However for your application there could be another pitfall, if the integer you want to send is wider than the function can take, for example if your integer is 16 bits wide but your function only expects a uint8_t, the high and low bytes need to be sent separately, ie by shifting down by 8 bits for one call to the write() function, and truncating the top 8 bits for another. The width of an integer is platform-dependent, but I suspect its 16 bits for your Arduino based on the language reference.

If you give a link to the radio library you're using you may get better answers as well.

\$\endgroup\$
1
  • \$\begingroup\$ I have updated my question with more data, please check \$\endgroup\$
    – Radolino
    Jul 7, 2013 at 5:39
0
\$\begingroup\$

I've made my own library. I think you'll find it appealing and easy to use. Check the example video.

https://www.youtube.com/watch?v=YpasceYkimI

You'll be able to send an int, unsigned int, long, unsigned long, byte; basically the most common types used when programming with Arduino language. And also arrays and String.

The library will be finished by Monday or Tuesday.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.