Sending integers with virtual wire

I am using an rf link from Sparkfun to transmit data to control servos. I decided to use the VirtualWire library, and I am having issues sending the data. I am fairly new to arduino and don't quite understand how this library works. The only way I was able to send data was in the const char form (modifying the examples from the library). I was able to convert the int into a string for the transmitter and it was able to transmit properly. But I don't know if there is any way to convert the const char that the receiver reads to an integer or if there is a way to send an integer without converting it to a string?

But I don't know if there is any way to convert the const char that the receiver reads to an integer

That would be what the atoi (ascii to integer) function does.

So if I use the atoi function then it will store an integer in a string? also I need to be able to use that data as an integer on the receiving arduino. I used the int() command to put the data the receiver gets into integer form. It worked but it put 256 on the end of the integer. Can I read certain digits on an integer. Also, the transmitter sends information in uint8_t, which I beleive is just a byte, should I be sending the information in another form?

So if I use the atoi function then it will store an integer in a string?

No. The atoi function converts a string to an integer. The itoa function converts an integer to a string.

The int() function casts an integer-type (but not size) value to an integer. It is NOT the function you want to be using.

Ok, let me change the code and see if it works

Well I tried it out and it still did not work exactly correct. I am trying to use the transmitted information to control a servo but every time I try it, it never works. Here is the code I am using for the transmitter (there is a pot on pin 1)

#include <VirtualWire.h>

int Rtrig;
char Rstr[5];

void setup()
{
vw_setup(2000); // Bits per sec
Serial.begin(9600);
}
void loop()
{
Rtrig = analogRead(1);
Rtrig = map(Rtrig,0,1023,148,170);
itoa(Rtrig, Rstr, 10);
const char *msg = Rstr;
Serial.println(msg);
vw_send((uint8_t *)msg, strlen(msg));
}

And the code for the Receiver (servo on pin 6)

#include <ServoTimer2.h>

#include <VirtualWire.h>

ServoTimer2 Rservo;
int Rtrig;

void setup()
{
Serial.begin(9600);
vw_setup(2000); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
Rservo.attach(6);
}
void loop()
{
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
int i;
// Message with a good checksum received, dump HEX
for (i = 0; i < buflen; i++)
{
Serial.print(buf[i], BYTE);
}
Rtrig = atoi("");
Serial.println(Rtrig, DEC);
Rservo.write(Rtrig);
}

}

According to the Serial Monitor Rtrig is 1480 to 1700. For some reason it adds a 0 to the end of the message. It should be 1747 to 1700.

For some reason it adds a 0 to the end of the message

Rtrig = atoi("");

Of course there is an extra zero, what else could atoi() return if you feed it an empty string?

what else could atoi() return if you feed it an empty string?

NaN ? :slight_smile:

I figured out what I was doing wrong. But the second servo won’t work in one direction. Also the first servo has to be moving in order for the second one to move. Is that because the second servo is getting data from the second part of the array?

Here is the new Transmitter Code

#include <VirtualWire.h>

int Rtrig;
int Ltrig;
char Istr[6];

void setup()
{
vw_setup(2000); // Bits per sec
Serial.begin(9600);
}
void loop()
{
  Rtrig = analogRead(1);
  Ltrig = analogRead(0);
  Istr[0] = map(Rtrig,0,1023,0,125);
  Istr[1] = map(Ltrig,0,1023,0,125);
  vw_send((uint8_t *)Istr, strlen(Istr));
}

And the new Receiver Code

#include <ServoTimer2.h>

#include <VirtualWire.h>

ServoTimer2 Rservo;
ServoTimer2 Lservo;

void setup()
{
    Serial.begin(9600);      // Debugging only
    Serial.println("setup");

    // Initialise the IO and ISR
    vw_set_ptt_inverted(true); // Required for DR3100
    vw_setup(2000);       // Bits per sec

    vw_rx_start();       // Start the receiver PLL running
    Rservo.attach(6);
    Lservo.attach(5);
}

void loop()
{
    int Rtrig;
    int Ltrig;
    int test;
    int msg[VW_MAX_MESSAGE_LEN];
    uint8_t buf[VW_MAX_MESSAGE_LEN];
    uint8_t buflen = VW_MAX_MESSAGE_LEN;
    if(vw_have_message() == HIGH)
    {
      vw_get_message(buf, &buflen);
      
      Rtrig = map(buf[0],0,125,1474,1800);
      if(Rtrig >1400) Rservo.write(Rtrig);
      
      Ltrig = map(buf[1],0,125,1474,1000);
      if(Ltrig >1400) Lservo.write(Ltrig); 
      
      Serial.println(Ltrig, DEC);
    }
}

I don’t know if the problem is with the ServoTimer2 Library, or the way I am reading the transmitted data.

Rtrig = map(buf[0],0,125,1474,1[glow]8[/glow]00);
Ltrig = map(buf[1],0,125,1474,1[glow]0[/glow]00);

Are the mappings correct?

according to the ServoTimer2 library it's default min is 544 and max is 2400. I am using continuous rotation servos which are not moving when they are at 1474, to go forward they need to be at 1700 (about), and to go backwards 1148. But because they are on opposite sides of the machine one needs to go forward and the other in reverse. I have had success making both servos go in the same direction. But not in opposite directions.

So, since the mappings are correct, the problem must lie in the code that follows the mappings.

      Rtrig = map(buf[0],0,125,1474,1800);
      if(Rtrig >1400) Rservo.write(Rtrig);
      
      Ltrig = map(buf[1],0,125,1474,1000);
      if(Ltrig >1400) Lservo.write(Ltrig);

For the buf[0] value, if it IS in the range 0 to 125, Rtrig will be in the range 1474 to 1800. Testing that it is above 1400 is not really necessary.

For the buf[1] value, if it IS in the range 0 to 125, Ltrig will be in the range 1474 to 1000. You then appear to be trying to move the servo only if the value is in a very small portion of that range.