Convert char array to integer

I am trying to modify a sketch I found online. (to send a servo command via 433Mhz)

My question only pertains to the Receive sketch. The program is working as it was originally intended to by the person who posted it. It does an analog read at the transmitter side and converts the 3 or 4 digit integer value to characters and sends those one at a time . They are received and printed to the serial
monitor as ASCII values (ie:31 30 30 35 = 1005, 39 39 39 = 999 , 39 37 35 = 975.

What I am trying to do is reconstruct the integer to integer type at the receive end and use it as an input
for a servo routine that moves an RC servo to track the position of a poteniometer knob. (Called 'Knob" in the Servo Library Examples folder)

I have tried CAST and that doesn’t seem to work.

Attached is the serial monitor terminal capture file which shows the original code successfully
printing “Got: 31 30 30 35” (ASCII characters that represent analog Read value 1005)
This part:

480

4800

-8536

n = -3256

is the output of my added code in an unsuccessful attempt to obtain the integer value. I know my approach is probable not even in the ballpark of what it should be which is why I am posting.

Here is the receive sketch:

 #include <VirtualWire.h>
#include <stdio.h>
#include <stdlib.h>
#undef int

#undef abs

#undef double

#undef float

#undef round


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

}

 

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;
   digitalWrite(13, HIGH); // Flash a light to show received good message
   delay(500);
// Message with a good checksum received, dump it.

  Serial.print("Got: ");
  for (i = 0; i < buflen; i++)
     {
       Serial.print(buf[i], HEX);
       Serial.print(" " );
      // sendstatus;
      }
      Serial.println();
 for (i = 0; i < buflen; i++)
      {
        byte a;
         byte b;
         byte c;
         byte d;
       
       
       
          int w; 
          int x; 
          int y; 
          int z;
          int n;
            
           if (i=0)
             {
              
              a = (byte)  buf[i],HEX;;
              w = (int) a ;
              Serial.print(w);
              delay(500);
              Serial.println();
              } 
              
            if (i=1)
              {
               b = (byte) buf[i],HEX; 
               x = (int) b;
               x = x * 10;
               Serial.print(x);
                delay(500);
                Serial.println();
               }
       
             if (i=2)
             {
              c = (byte) buf[i],HEX; 
              y = (int) c;
              y = y * 100;
               Serial.print(y);
                delay(500);
                Serial.println();
              }
       
             if (i=3)
               {
                d = (byte) buf[i],HEX; 
                z = (int) d;
                z = z * 1000;
                 Serial.println(z);
                  delay(500);
                  Serial.println();
                }
        
        
        n = w + x + y + z;
        Serial.print("n = " ); 
        Serial.println(n );
         delay(500);

         } 
Serial.println();

Serial.println("");

        digitalWrite(13, LOW);
         delay(500);
    }

}
void sendstatus()
{
    digitalWrite(13, HIGH); // Flash a light to show received good message
    delay(500);
    digitalWrite(13, LOW);
    delay(500);
}

This is the part I added (which doesn’t work)
The output result is the same if I use “char” instead of “byte”

 for (i = 0; i < buflen; i++)
      {
        byte a;
         byte b;
         byte c;
         byte d;
       
       
       
          int w; 
          int x; 
          int y; 
          int z;
          int n;
            
           if (i=0)
             {
              
              a = (byte)  buf[i],HEX;;
              w = (int) a ;
              Serial.print(w);
              delay(500);
              Serial.println();
              } 
              
            if (i=1)
              {
               b = (byte) buf[i],HEX; 
               x = (int) b;
               x = x * 10;
               Serial.print(x);
                delay(500);
                Serial.println();
               }
       
             if (i=2)
             {
              c = (byte) buf[i],HEX; 
              y = (int) c;
              y = y * 100;
               Serial.print(y);
                delay(500);
                Serial.println();
              }
       
             if (i=3)
               {
                d = (byte) buf[i],HEX; 
                z = (int) d;
                z = z * 1000;
                 Serial.println(z);
                  delay(500);
                  Serial.println();
                }
        
        
        n = w + x + y + z;
        Serial.print("n = " ); 
        Serial.println(n );
         delay(500);

         }

What I need to do is take the two to four characters (it varies with the analog read integer value) and
reconstruct the integer to a usable integer that can be used for decision making at the receive end.

Just FYI, (in case anyone wants to know),

here is the transmitter sketch:

/* 

Sensor Transmitter
By Markus Ulfberg 2012-07-06

Takes a sensor reading 0-1023
converts it to a char array and sends 
to RF receiver unit via VirtualWire  

*/

#include <VirtualWire.h>

// LED's
const int ledPin = 13;

// Sensors 
const int Sensor1Pin = A2;
// const int Sensor2Pin = 3; 

int Sensor1Data;
//int Sensor2Data;
char Sensor1CharMsg[4]; 

void setup() {

 // PinModes 
 // LED 
 pinMode(ledPin,OUTPUT);
 // Sensor(s)
 pinMode(Sensor1Pin,INPUT);
 
 // for debugging
 Serial.begin(9600); 
 
 // VirtualWire setup
 vw_setup(2000);     // Bits per sec


}

void loop() {
  
  // Read and store Sensor 1 data
  Sensor1Data = analogRead(Sensor1Pin);
  
  // Convert integer data to Char array directly 
  itoa(Sensor1Data,Sensor1CharMsg,10);
  
  // DEBUG
  Serial.print("Sensor1 Integer: ");
  Serial.print(Sensor1Data);
  Serial.print(" Sensor1 CharMsg: ");
  Serial.print(Sensor1CharMsg);
  Serial.println(" ");
  delay(1000);

  // END DEBUG
 
 digitalWrite(13, true); // Turn on a light to show transmitting
 vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
 vw_wait_tx(); // Wait until the whole message is gone
 digitalWrite(13, false); // Turn off a light after transmission
 delay(200); 
 
} // END void loop..

I only have one FTDI module and I’m using standalone ATmega328s. If I move the cable to the Tx, I can
see the integer value (see attached Tx capture file) This is how I compare the result at the receiver end
with the original transmitted value.

If anyone can tell me how to do this (convert the received characters to a single data type integer) OR
modify the TX sketch to send something different that is easier to convert to an integer at the receive end. The end result is I turn the knob at the transmitter end and the servo tracks the position at the receiver end.

Send_servo_command_ClearTerminal_Capture__02.15.2015_16.32.14.txt (950 Bytes)

Send_servo_command_Tx_ClearTerminal_Capture__02.15.2015_17.05.47.txt (2.47 KB)

Your code is incomplete. The read portion is not there so I have no way to tell how you terminate your transmission, with a special character or does the rf module have a way to tell the end of transmission. Do you know sscanf or atoi?

byte received[8]; //received[0] is the MSB
unsigned long result = 0;
...receive values...
for(int i = 0; i < 8; i++)
{
  result *= 10L;
  result += received[i];
}
..result now contains reconstructed array to integer

Although there is a better way…
Why not send parts of the integer as full bytes? for example
11110000 10101010 00100100 11001100
Then you send 4 bytes, they dont even need to be ascii characters…
Then to reconstruct them, just do result += received[ i ] << (8 * i);
Its faster and quicker

The receiver sketch is right under that label.
Here it is again:

 #include <VirtualWire.h>
#include <stdio.h>
#include <stdlib.h>
#undef int

#undef abs

#undef double

#undef float

#undef round


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

}

 

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;
   digitalWrite(13, HIGH); // Flash a light to show received good message
   delay(500);
// Message with a good checksum received, dump it.

  Serial.print("Got: ");
  for (i = 0; i < buflen; i++)
     {
       Serial.print(buf[i], HEX);
       Serial.print(" " );
      // sendstatus;
      }
      Serial.println();
 for (i = 0; i < buflen; i++)
      {
        byte a;
         byte b;
         byte c;
         byte d;
       
       
       
          int w; 
          int x; 
          int y; 
          int z;
          int n;
            
           if (i=0)
             {
              
              a = (byte)  buf[i],HEX;;
              w = (int) a ;
              Serial.print(w);
              delay(500);
              Serial.println();
              } 
              
            if (i=1)
              {
               b = (byte) buf[i],HEX; 
               x = (int) b;
               x = x * 10;
               Serial.print(x);
                delay(500);
                Serial.println();
               }
       
             if (i=2)
             {
              c = (byte) buf[i],HEX; 
              y = (int) c;
              y = y * 100;
               Serial.print(y);
                delay(500);
                Serial.println();
              }
       
             if (i=3)
               {
                d = (byte) buf[i],HEX; 
                z = (int) d;
                z = z * 1000;
                 Serial.println(z);
                  delay(500);
                  Serial.println();
                }
        
        
        n = w + x + y + z;
        Serial.print("n = " ); 
        Serial.println(n );
         delay(500);

         } 
Serial.println();

Serial.println("");

        digitalWrite(13, LOW);
         delay(500);
    }

}
void sendstatus()
{
    digitalWrite(13, HIGH); // Flash a light to show received good message
    delay(500);
    digitalWrite(13, LOW);
    delay(500);
}

I don't know how to tell you this , but , I haven't done anything more copy the code and paste it into the IDE and save it. I'll admit I made a lame attempt to concoct some solution (that's the part that doesn't work), but let me put it to you this way, if I were working with anything dangerous like I wrote that code I'd probably be dead by now. I just threw it together using google searches for the function CAST. I first
tried using "char" and then tried "byte" and they yielded the same result. At that point I gave up and posted. That's the truth, the whole truth, and nothing but the truth.

It seems to me, the multipliers for your 10x 100x 1000x are in the wrong order.

Also, if your byte contains a char representing the ascii character digits '0', '1' , '2', etc,

then you can get the integer number that the character represents, by

char digit = '7'  ;
int value = digit - '0'  ;

This will result in the variable "value" having the number 7 in it. 0x0000000000000111

If I understand correctly what is being stored in buf, you can throw out everything from here

 Serial.print("Got: ");

down to here

Serial.println("");

inclusive and replace it with this:

  buf[buflen] = 0;
  int n = atoi(buf);
  Serial.println(n);

[+edit] One quick addition. Make the buffer a bit bigger just to be sure it has room for the null:

    uint8_t buf[VW_MAX_MESSAGE_LEN+1];

[++edit] and a P.S. what were statements like this supposed to do?

     a = (byte)  buf[i],HEX;;

Pete

Tried that and got compile error:
“**Invalid convertsion from ‘uint8_t’ to ‘const char’ **”

This is the code I ran:

#include <VirtualWire.h>
#include <stdio.h>
#include <stdlib.h>
#undef int

#undef abs

#undef double

#undef float

#undef round


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

}

 

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;
   digitalWrite(13, HIGH); // Flash a light to show received good message
   delay(500);
// Message with a good checksum received, dump it.

  Serial.print("Got: ");
  buf[buflen] = 0;
  int n = atoi(buf);
  buf[buflen] = 0;
  int n = atoi(buf);
  Serial.print("n= ");
  Serial.println(n);
 
   digitalWrite(13, LOW);
   delay(500);
    }

}
void sendstatus()
{
    digitalWrite(13, HIGH); // Flash a light to show received good message
    delay(500);
    digitalWrite(13, LOW);
    delay(500);
}

what were statements like this supposed to do?
Code: [Select]
a = (byte) buf*,HEX;; [/quote]*
That was supposed to copy the received character from the buf*,HEX array, using CAST.*

A good way to send and receive something other than character strings is using a cast to uint8_t on the tx and memcpy of the received buffer on the rx.

In both the tx and rx sketches you will declare your array of integers so that the data structures look the same in both sketches.

On the tx you then send it with the following

Code: [Select]
int data = {1234,2345,3456,4567,5678};
vw_send((uint8_t *) & data, sizeof(data));

The cast to uint8_t take care of breaking the data into bytes for transmission. The * and & are a pointer to the address of the variable. sizeof(data) will be the number of bytes.

On the rx you have the data in a received buffer and a buffer length. You should have some code which looks like this

Code: [Select]
int data[5] = {0};
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;

if (vw_get_message(buf, &buflen))

You can then use memcpy to transfer the buffer to the address of your variable and it will be recast to //the integer.
Code: [Select]

if (vw_get_message(buf, &buflen))
{
memcpy (& data, buf, buflen);
}

This method of using uint8_t* on the tx and memcpy on the rx can be adapted for use with multiple variables in arrays, or different types of variables in a structure.

Currently , it is being sent like this:

Sensor1Data = analogRead(Sensor1Pin);

 // Convert integer data to Char array directly 
  itoa(Sensor1Data,Sensor1CharMsg,10);





 vw_send((uint8_t *)Sensor1CharMsg, strlen(Sensor1CharMsg));
 vw_wait_tx(); // Wait until the whole message is gone

the problem with this:

 int data[] = {1234,2345,3456,4567,5678};
vw_send((uint8_t *) & data, sizeof(data));

is that it assumes the data are known. All I have at the transmitter end is an analog
Read value (type integer). It gets changed here:

  itoa(Sensor1Data,Sensor1CharMsg,10);

I don't know how to use your example because your data type for the data is different.
(your array is separated by commas. My integer is a single number obtained from analogRead.

Ooops, just add a cast:

 int n = atoi((const char *)buf);

But you don't need to do this conversion twice.

You must also make the buffer one character longer:

uint8_t buf[VW_MAX_MESSAGE_LEN+1];

Pete

int data = analogRead(Sensor1Pin);
vw_send((uint8_t *) & data, sizeof(data));

YIPPEE !!!

IT WORKS !

SEE ATTACHED TERMINAL CAPTURE FILE FROM RECEIVE ARDUINO

 #include <VirtualWire.h>
#include <stdio.h>
#include <stdlib.h>
#undef int

#undef abs

#undef double

#undef float

#undef round


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

}

 

void loop()

{

    uint8_t buf[VW_MAX_MESSAGE_LEN+1];

    uint8_t buflen = VW_MAX_MESSAGE_LEN;

 

    if (vw_get_message(buf, &buflen)) // Non-blocking

    {

   int i;
   digitalWrite(13, HIGH); // Flash a light to show received good message
   delay(500);
// Message with a good checksum received, dump it.

  Serial.print("Got: ");
 buf[buflen] = 0;
  int n = atoi((const char *)buf);
  Serial.println(n);

        digitalWrite(13, LOW);
         delay(500);
    }

}
void sendstatus()
{
    digitalWrite(13, HIGH); // Flash a light to show received good message
    delay(500);
    digitalWrite(13, LOW);
    delay(500);
}

Send_servo_command_EL_SURPREMO_WORKING_ClearTerminal_Capture__02.15.2015_19.32.12.txt (649 Bytes)

The sender side has no mechanism to delimit the string. So it is heuristic, hoping that the delay between sending is long enough and the receiver receives complete message in one shot. I recommend you do a better job. If one byte is misaligned, all future transmissions are garbled. Send with a new line character as the end of message should work.

Given enough buffer size:

  itoa(Sensor1Data,Sensor1CharMsg,10);
  strcat(Sensor1CharMsg,"\n");

Then you can send the delimited message. In the receiver code, read until you either received 5 number characters and none of it being the delimiter (discard everything, wait for a delimiter and reset), or up to 4 number characters and a new line character. Then replace the new line with '\0' and use atoi to restore the characters into integer. If at any time you receive a non-number non-new-line character, discard everything, wait for a delimiter and reset).

Read about finite state machines for direction of programming.

It was fine until I added the servo code and then I started getting a compile error that suggests the software servo library AND the servo library are incompatible with the Virtualwire library.

See attached compiler output

COMPILE_ERROR_.txt (3.46 KB)

SoftwareServo.h:4:22: warning: WProgram.h: No such file or directory

This says the SoftwareServo library is not up to Arduino IDE 1.0 standard. Do you have a newer version of this library? Arduino IDE 1.0 and up no longer uses this file. Which IDE version are you using?

I’m using v. 1.05-r2. I tried the regular servo library and also got errors. (see attached)
Something about “multiple definitions of _vector_11”

COMPILE_ERROR_servo_library.txt (18.5 KB)

Learning how to actually program would be nice after so many posts you have. You placed a copy of servo library in sketch and that is a duplicate to the one in arduino ide folder. Get rid of the servo library from arduino sketch folder.

Learning how to actually program would be nice after so many posts you have.

That would be nice, however my area of expertise is hardware. I will start studying programming and try to expand my knowledge in that area.

My interpretation of the compiler output is that this virtualwire library reference:

VirtualWire\VirtualWire.cpp.o: In function __vector_11': C:\Users\Robert\Documents\Arduino\libraries\VirtualWire/VirtualWire.cpp:**568**: multiple definition of __vector_11’

conflicts with this SERVO library reference:

Servo\Servo.cpp.o:C:\Program Files (x86)\arduino\libraries\Servo/Servo.cpp:103: first defined here

You placed a copy of servo library in sketch and that is a duplicate to the one in arduino ide folder

I looked and haven’t found any copies of the servo library in my sketch folder.’

COMPILE_ERROR_servo_library.txt (18.5 KB)

You're right. I was using my small tablet between bites of breakfast so I read across lines. This problem occurs when two libraries defined the same names. such as the __vector_11. The only way to resolve it is to redefine the one in virtualwire into a different name such as VirtualWire__vector_11 so it will never (with quotes) conflict with another name. This requires you to search and replace the keyword in VirtualWire.h and .cpp. I've not used this library, let alone together with servo so I didn't know this problem existed. I've had similar problem when I defined some generic names in my library that has already been defined in other libraries (again my own). Only changing names will resolve the conflict.