2

I'm using two Arduinos with the rf24 modules.

I want to control a process with those, but for now I'm just checking the connection.

This is the code of the master:

#include  <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
unsigned char msg[4];
unsigned char serial_msg[1];

String mensaje = "ii";

int CE = 9;
int CSN = 10;

RF24 radio(9,10);

//const uint64_t pipe = 0xE8E8F0F0E1LL;
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

bool done;
int incomingByte = 0; 

String stringOne  = "";

void setup(void){
    Serial.begin(9600);
    radio.begin();
    radio.setRetries(15,15);   
    radio.openWritingPipe(pipes[1]);
}

void loop() {

    radio.stopListening();  

    if (Serial.available() == 3) {

        while(Serial.available() > 0)
        {
            incomingByte= Serial.read();

            stringOne = String(stringOne + String((char)incomingByte));

        }
        Serial.println(mensaje);

        incomingByte = Serial.read();
        serial_msg[0] = incomingByte;

        radio.write(stringOne.c_str() ,2);

    }

    stringOne  = "";

    radio.startListening();    // Volvemos a la escucha para recibir mas paquetes
    delay(10); // necesario para activar el modo de esucha

    if (radio.available())
    done = false;
    {
        while (!done)
        {
            if (sizeof(msg)==4)
            {
                done = radio.read(msg,sizeof(msg) );
                Serial.print("Estado: ");
                Serial.println(msg[0]); 
                Serial.print("Voltaje: ");
                Serial.print(msg[1]);
                Serial.print(msg[2]);
                Serial.println(msg[3]);
            }

        }


    }
    mensaje = "";
}

What t does is read data for the serial monitor, convert it to a string and them send the string.

The code of the receiver is this:

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

int CE = 6;    
int CSN = 7;
RF24 radio(CE,CSN);  /// ()
const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };

bool done = false;

int voltaje = 141;
String string_vol= "789";
enum states { 
    ESPERA,
    ENCENDIDO,
    PAUSA
};
enum states state = ESPERA;

unsigned char msg[2];
char incomingByte = '_';
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
unsigned long interval = 1000;

void setup() {

    Serial.begin(9600);            
    radio.begin();         
    radio.startListening();             
    radio.openWritingPipe(pipes[1]);              
    radio.openReadingPipe(1,pipes[0]);  

}

void loop() {

    string_vol= "789";
    currentMillis = millis();
    if ((currentMillis-previousMillis)>interval)
    {
        previousMillis = currentMillis;
        msg[0] = char(state);
        radio.stopListening(); // Dejamos d escuchar para poder hablar
        string_vol = String(String((char)state)  + string_vol );
        radio.write(string_vol.c_str() ,4);
        radio.startListening();    // Volvemos a la escucha para recibir mas paquetes
        delay(10);
    }
    if (radio.available())
    done = false;
    {
        while (!done)
        {
            done = radio.read(msg,sizeof(msg));
        }
    }

    switch(state) {
    case ESPERA:

        if (msg[0] == 'i')
        {
            state =  ENCENDIDO;
        }

        break;
    case ENCENDIDO:

        currentMillis = millis();

        if (msg[0]=='r')

        {
            state =  ESPERA;
        }
        else if  (msg[0]=='d')
        {
            state =  PAUSA;
        }
        break;
    case PAUSA:
        if (msg[0]=='r')
        {
            state =  ESPERA;
        }
        else if  (msg[0]=='c')
        {
            state =  ENCENDIDO;
        }
        break;
    }
}

This one acts as a state machine, and sends a string in this case:

string_vol= "789";

plus the actual state of the Arduino:

string_vol = String(String((char)state)  + string_vol );

When this Arduino is in state one:

In the other side I got:

Estado: 1
Voltaje: 555657

When is in state II I got:

Estado: 2
Voltaje: 555657

But if it's in state zero, which is the initial one, I got:

Estado: 55
Voltaje: 56570

It change the position of the state for one of the chars of the string

EDIT.

The issue is when sending the '0' of the first state, I changed enum to:

enum states { 
    foo, //  revisar, solo usada para comenzar en 1
    ESPERA,
    ENCENDIDO,
    PAUSA
};

Now it works fine because the first state is '1', still don't now why it doesn't work if I use the '0'

2
+100

The problem you run into is that you are trying to insert the binary value of 0 into an Arduino String. That may actually be possible, but the way you attempt to to do it utilizes some C-style mechanisms, specifically representing a string as a pointer to some characters terminated by a null byte - which is to say 0.

Your code:

string_vol = String(String((char)state)  + string_vol );

Invokes this String constructor from WString.cpp

String::String(char c)
{
    init();
    char buf[2];
    buf[0] = c;
    buf[1] = 0;
    *this = buf;
}

Which tries to turn the input char into a C-style string containing the input and then its own terminating null. But in the case where state=0, that ends up being a buffer of two 0's. A C-style string is terminated by the first 0, so when interpreted that way, the buffer is considered empty. The last line of this constructor uses the buffer to invoke yet another constructor, that treats the input as a C-style null terminated string:

String::String(const char *cstr)
{
    init();
    if (cstr) copy(cstr, strlen(cstr));
}

Since strlen() finds the input here in the state=0 case to be empty, it produces an empty String. You then append some other data, and that is all that you see, with no state included in the packet.


As this demonstrates, it is necessary to to be careful mixing binary and textual representations.

One thing you might do would be to add an offset to the state before transmitting, and subtract it out on the receiver. If you have 9 or fewer states, adding the character code of '0' (ie, 0x30) would transmit them as potentially printable digits. If you have more, you could add 'A' and transmit them as letters of the alphabet. In the end it doesn't really matter what you add, as long as any value you intend to transport can be represented in all the intermediate data formats it passes through.

Of course the nRF24L01 parts will transmit binary data just fine; if you want to go ahead and move binary data through them you can, you just have to avoid using anything with C-style char * mechanics that is going to see 0 in the data as a terminator, not a character.

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.