Solved

AVR (Arduino) Convert char array to double?

Posted on 2010-11-11
5
4,211 Views
Last Modified: 2012-05-10
i'm having a lot of trouble with this.

I have a text array and i've done all the stuff to extract just the numbers so i get something like this:

CurrentXascii[9]=1234.5678

but when i do an atof

CurrentX=atof(CurrentXascii);

it truncates to two decimal places.

How do I fix this? I need those four decimal places, it is pretty important.

if I serial.print the CurrentX with 9 digits it does show all 8 digits (and the period), but after the first 6 numbers the last are not consistently accurate, and the difference in .0001 is VERY significant, some of our X values are as much as 0.0003 off and some of our Y values have gone as high as 0.0009 off. This is pretty unacceptable but I'm not sure how to work around it.

here's my FULL snippet:

#include <String.h>
#include <ctype.h>
#include <Wire.h>

int compassAddress = 0x32 >> 1;
int heading = 0;
int tilt = 0;
int roll = 0;
int ledPin = 13;
int rxPin = 0;
int txPin = 1;
int byteGPS=-1;
char linea[300] = "";
char comandoGPR[7] = "$GPRMC";
int cont=0;
int bien=0;
int conta=0;
int indices[13];
char CurrentXascii[9];
char CurrentYascii[10];
float CurrentX;
float CurrentY;
float CurrentHeading;
float CurrentHeading0;
float CurrentHeadingF;
byte responseBytes[6];
int GPStimer=0;
double DeltaX=0.000;
double DeltaY=0.000;
int Instance=0;
int InstanceSize=0;
int buttonState=0;
int buttonPin = 22;
int lastButtonState=0;
int buttonPushCounter=0;
float DesiredHeading=0.0;
int LeftSpeed=0;
int RightSpeed=0;
int LeftSpeed0=0;
int RightSpeed0=0;
int LeftSpeedF=0;
int RightSpeedF=0;
double ParkingLotX[3] = {4031.24554, 4031.24116, 4031.23294};
double ParkingLotY[3] = {-7427.58914,-7427.57996,-7427.5853};
void setEngineSpeed1(signed char cNewMotorSpeedH)
{
  unsigned char cSpeedVal_Motor1 = 0;
  if(cNewMotorSpeedH==0)
  {
    Serial3.print(0,BYTE);
    return;
  }
  cSpeedVal_Motor1 = map(cNewMotorSpeedH,-100,100,1,127);
  Serial3.print(cSpeedVal_Motor1, BYTE);
}

void setEngineSpeed2(signed char cNewMotorSpeed2)
{
  unsigned char cSpeedVal_Motor2 = 0;
  if(cNewMotorSpeed2 == 0)
  {
    Serial3.print(0,BYTE);
    return;
  }
  cSpeedVal_Motor2 = map(cNewMotorSpeed2,-100,100,128,255);
  Serial3.print(cSpeedVal_Motor2, BYTE);
}

void readSensor()
{
  Wire.beginTransmission(compassAddress);
  Wire.send(0x50);
  Wire.endTransmission();
  delay(2);
  Wire.requestFrom(compassAddress, 6);
  if(6 <= Wire.available())
  {
    for(int i = 0; i<6; i++) {
	responseBytes[i] = Wire.receive();
    }
  }
  heading = ((int)responseBytes[0]<<8) | ((int)responseBytes[1]);
  tilt = (((int)responseBytes[2]<<8) | ((int)responseBytes[3]));
  roll = (((int)responseBytes[4]<<8) | ((int)responseBytes[5]));
  CurrentHeadingF = heading/10;
  CurrentHeading0=(CurrentHeadingF+CurrentHeading0)/2;
  CurrentHeading=(CurrentHeading0+CurrentHeading)/2;

}

void readGPS()
{
  GPStimer=0;
  do{
    byteGPS=Serial2.read();
    if (byteGPS == -1)
    {
	delay(100);
    }
    else {
	linea[conta]=byteGPS;
	conta++;
	if (byteGPS==13){
	  digitalWrite(ledPin, LOW);
	  cont=0;
	  bien=0;
	  for (int i=1;i<7;i++){
	    if (linea[i]==comandoGPR[i-1]){
		bien++;
	    }
	  }
	  if(bien==6){
	    for (int i=0;i<300;i++){
		if (linea[i]==','){
		  indices[cont]=i;
		  cont++;
		}
		if (linea[i]=='*'){
		  indices[12]=i;
		  cont++;
		}
	    }
	    Serial.println("");
	    Serial.println("");
	    Serial.println("---------------");
	    for (int i=0;i<12;i++){
		for (int j=indices[i],k=0;j<(indices[i+1]-1);j++,k++){
		  switch(i){
		  case 2 :
		    CurrentXascii[k]=linea[j+1];
		   break;
		  case 4 :
		    CurrentYascii[k]=linea[j+1];
		    break;
		  }
		}
	    }
/*	  for (int i=0;i<5;i++){
		CurrentX1[i]=atof(CurrentXascii[i]);
	    }
	    for (int i=5,i<10,i++){
		CurrentX2[i]=atof(CurrentXascii[i]);
	    }
	    CurrentX=CurrentX1"."CurrentX2; */
	    CurrentX=atof(CurrentXascii);
	    CurrentY=-atof(CurrentYascii);
	  }
	  conta=0;
	  for (int i=0;i<300;i++){
	    linea[i]=' ';
	  }
	}
    }
    GPStimer++;
  }
  while(GPStimer<300);
}

void setup()
{
  delay(500);
  Wire.begin();
  Wire.send(0x82);
  delay(500);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
  Serial2.begin(4800);
  for (int i=0;i<300;i++){
    linea[i]=' ';
  }
  Serial3.begin(9600);
  delay(2000);
  setEngineSpeed1(0);
  setEngineSpeed2(0);
  Instance=0;
}

void loop()
{
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
	buttonPushCounter++;
    }
    lastButtonState = buttonState;
  }
  Instance=buttonPushCounter;
  readSensor();
  Serial.print("Heading: ");
  Serial.print(CurrentHeading);
  Serial.print("\t Tilt: ");
  Serial.print(tilt / 10, DEC);
  Serial.print("\t Roll: ");
  Serial.println(roll / 10, DEC);
  delay(50);
  readGPS();
  Serial.print("Current X Value: ");
  Serial.print(CurrentX, 10);
  Serial.print("\t");
  Serial.print("Current Y Value: ");
  Serial.println(CurrentY, 10);
  Serial.println("---------------");
  do{
    readGPS();
    DeltaX=ParkingLotX[Instance]-CurrentX;
    DeltaY=ParkingLotY[Instance]-CurrentY;
    if (DeltaY<0){
	if (DeltaX<0){
	  DesiredHeading=270-atan(DeltaY/DeltaX)*180/3.14159265;
	}else if (DeltaX>0){
	  DesiredHeading=180-atan(DeltaY/DeltaX)*180/3.14159265;
	}
    }else if (DeltaY>0){
	if (DeltaX<0){
	  DesiredHeading=360-atan(DeltaY/DeltaX)*180/3.14159265;
	}else if (DeltaX>0){
	  DesiredHeading=90-atan(DeltaY/DeltaX)*180/3.14159265;
	}
    }
    readSensor();
    if (((DesiredHeading-CurrentHeading) < 15)&&((DesiredHeading-CurrentHeading)>6)){
	LeftSpeed=40;
	RightSpeed=30;
    }else if (((DesiredHeading-CurrentHeading) <= 30)&&((DesiredHeading-CurrentHeading)>15)){
	LeftSpeed=40;
	RightSpeed=20;
    }else if (((DesiredHeading-CurrentHeading) <= 60)&&((DesiredHeading-CurrentHeading)>30)){
	LeftSpeed=40;
	RightSpeed=10;
    }else if (((DesiredHeading-CurrentHeading) <= 360)&&((DesiredHeading-CurrentHeading)>60)){
	LeftSpeed=40;
	RightSpeed=-40;
    }else if (((DesiredHeading-CurrentHeading) <= -6)&&((DesiredHeading-CurrentHeading)>-15)){
	LeftSpeed=30;
	RightSpeed=40;
    }else if (((DesiredHeading-CurrentHeading) <= -15)&&((DesiredHeading-CurrentHeading)>-30)){
	LeftSpeed=20;
	RightSpeed=40;
    }else if (((DesiredHeading-CurrentHeading) <= -30)&&((DesiredHeading-CurrentHeading)>-60)){
	LeftSpeed=10;
	RightSpeed=40;
    }else if (((DesiredHeading-CurrentHeading) <= -60)&&((DesiredHeading-CurrentHeading) >- 360)){
	LeftSpeed=-40;
	RightSpeed=40;
    }else if (((DesiredHeading-CurrentHeading) <= 6)&&((DesiredHeading-CurrentHeading) >= -6)){
	LeftSpeed=40;
	RightSpeed=40;
    }
    LeftSpeed0=.8*LeftSpeed+.2*LeftSpeed0;
    RightSpeed0=.8*RightSpeed+.2*RightSpeed0;
    setEngineSpeed1(LeftSpeed0);
    setEngineSpeed2(RightSpeed0);
    Serial.print("LeftSpeed: ");
    Serial.print(LeftSpeedF);
    Serial.print("\t");
    Serial.print("RightSpeed:");
    Serial.print(RightSpeedF);
    Serial.print("\t");
    Serial.print("DesiredHeading:");
    Serial.print(DesiredHeading);
    Serial.print("\t");
    Serial.print("CurrentHeading:");
    Serial.print(CurrentHeading);
    Serial.print("\t");
    Serial.print("CurrentX:");
    Serial.print(CurrentX, 4);
    Serial.print("\t");
    Serial.print("CurrentY:");
    Serial.print(CurrentY, 4);
    Serial.print("\t");
    Serial.print("Y:");
    Serial.print(ParkingLotY[Instance], 4);
    Serial.print("\t");
    Serial.print("X:");
    Serial.print(ParkingLotX[Instance], 4);
    Serial.print("\t");
    Serial.print("Instance:");
    Serial.println(Instance);
    delay(50);
  }while((abs(DeltaX)>0.0001)&&(abs(DeltaY)>0.0001));
  setEngineSpeed1(0);
  setEngineSpeed2(0);
}
 

Open in new window


as of now i'm using:

           CurrentX=atof(CurrentXascii);
           CurrentY=-atof(CurrentYascii);

and it's coming out a bit inaccurate, these are the coordinates i'm pulling:

http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=40.5202916,+-74.459635&sll=37.0625,-95.677068&sspn=48.15347,79.013672&ie=UTF8&ll=40.520431,-74.459603&spn=0.000711,0.001206&t=h&z=20

when the gps is actually located in the parking lot.....not good haha

the code I wrote to extract individual strings and make it into a double (basically a home made atod function) is coming up with total trash numbers:

  for (int i=0,k=5;i<5;i++,k--){
            CurrentX1=CurrentX1+(10^k)*((int)CurrentXascii[i]);
            Serial.println(CurrentX1);
          }
          for (int i=6,k=8;i<13;i++,k--){
            CurrentX2=CurrentX2+(10^k)*((int)CurrentXascii[i]);
            Serial.println(CurrentX2);
          }
          for (int i=1,k=5;i<6;i++,k--){
            CurrentY1=CurrentY1+(10^k)*((int)CurrentYascii[i]);
            Serial.println(CurrentY1);
          }
          for (int i=7,k=7;i<13;i++,k--){
            CurrentY2=CurrentY2+(10^k)*((int)CurrentYascii[i]);
            Serial.println(CurrentY2);
          }
          CurrentXi=CurrentX1+(CurrentX2/10000);
          CurrentYi=-(CurrentY1+(CurrentY2/10000));
          CurrentX=CurrentXi;
          CurrentY=CurrentYi;
          CurrentX1,CurrentX2,CurrentY1,CurrentY2,CurrentXi,CurrentYi=0;
        }

Open in new window


don't mind the serial.prints they are from when I was trying to trouble shoot the for loops. CurrentX and CurrentY are coming out to be insane numbers.

I can't seem to figure out how to convert it to a double.
0
Comment
Question by:BleedScarlet
  • 3
  • 2
5 Comments
 
LVL 9

Expert Comment

by:masheik
ID: 34117809
Try like below, I am usig codeblocks IDE it prints the digits correctely for me

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *currentXascii[2];
    double currentX;
    currentXascii[0] = (char *)calloc(10,sizeof(char));
    strcpy(currentXascii[0],"12345.45678");
    currentX = atof(currentXascii[0]);
    printf(" currentX = %f ",currentX);
    return 0;
}

/*console output 
-----------------
 currentX = 12345.456780
Process returned 0 (0x0)   execution time : 0.000 s
Press any key to continue. */

Open in new window

0
 

Author Comment

by:BleedScarlet
ID: 34117948
I don't what works on codeblocks or not, but it doesn't work on arduino.

the main difficulty here is the character array stores each digit as a value in the array

so the array appears as: CurrentXascii={4,0,3,1,.,2,4,5,6,} and converting that array to a usable number is the problem, it's not a single value in the array that i can't pull, it's the WHOLE array.

I'm looking into how to delete the period and convert it but I think the atof and atol commands by default turn any character it doesn't understand into a 0, so if I remove the period it'll appear as 403102456 instead and while that is problematic I think I could make it worth with some creative division and floor commands. I've been at it for a while and it's more difficult than I thought, I don't know how I would do that either.
0
 
LVL 9

Expert Comment

by:masheik
ID: 34119778
 I have given some code below, may be it will help you on this issue,
it is a quick and dirty fix.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* prototypes */
void test(void);
char* InttoChar(int i);
/* end of programs */



int main()
{
    /*char *currentXascii[2];//= {'1','2','3','4','.','5','6','7','8'};
    double currentX;
    currentXascii[0] = (char *)calloc(10,sizeof(char));
    strcpy(currentXascii[0],"12345.456781");
    currentX = atof(currentXascii[0]);
    printf("currentX = %f \n",currentX);
    free(currentXascii[0])*/
    test();
    return 0;
}


void test(void)
{

    char currentXascii[10] = {4,0,3,'.',2,0,5,6,9,'\0'};
    /* I Took period as character */
    //char currentXascii[10] = {'4','0','3','1','.','2','4','5','6','\0'};
    /* The commented code only contatins the signle char values not ints inside char array */
    char digit[10] = {'\0'};
    char decimal[10] = {'\0'};
    char wholeDigit[10]= {'\0'};
    int len = 0;
    int i = 0,j = 0, k = 0;
    int value;
    double digit_d;
    printf("Digit before          = %s \n",currentXascii);
    for(len = 0; (currentXascii[len]!= '\0') || (len <(sizeof(currentXascii)/sizeof(currentXascii[0]))-1); len++);
    printf("Length                = %d \n",len);
    for(i = 0; currentXascii[i] != '.'; i++);
    printf("Dot found at          = %d \n",i);
    for(j= 0 ; j < i ; j++)
    {
        digit[j] = *(char *)InttoChar(currentXascii[j]);
    }
    digit[j] = '\0';
    for(i = 0,k= j+1; i <(len+j) ,k < len; i++,k++)
    {
        decimal[i] = *(char *)InttoChar(currentXascii[k]);
    }
    decimal[i] = '\0';
    printf("digit = %s , Decimal = %s\n",digit,decimal);
    strcat(wholeDigit,digit);
    strcat(wholeDigit,decimal);
    printf("whole digit           = %s \n",wholeDigit);
    strcat(digit,".");
    strcat(digit,decimal);
    digit_d = atof(digit);
    printf("String len of digit   = %d \n",strlen(digit));
    printf("Digit only            = %s \n",digit);
    value = atoi(wholeDigit);
    printf("Int value             = %d \n",value);
    printf("Float value           = %f \n",digit_d);
    //printf("Testing\n");
    getchar();

}

char* InttoChar(int i)
{
    static char string[1];
    sprintf(string,"%d",i);
    return string;
}

Open in new window

0
 

Accepted Solution

by:
BleedScarlet earned 0 total points
ID: 34140537
I fixed it on my own with some help from one of my professors...we did something totally different and mind numbingly simple, and it worked.

closing this question as unsolved since I got no answers here.
0
 

Author Closing Comment

by:BleedScarlet
ID: 34179076
unsolved
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

If you’re thinking to yourself “That description sounds a lot like two people doing the work that one could accomplish,” you’re not alone.
When there is a disconnect between the intentions of their creator and the recipient, when algorithms go awry, they can have disastrous consequences.
The goal of this video is to provide viewers with basic examples to understand and use structures in the C programming language.

777 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question