BleedScarlet
asked on
AVR (Arduino) Convert char array to double?
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(CurrentXasci i);
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:
as of now i'm using:
CurrentX=atof(CurrentXasci i);
CurrentY=-atof(CurrentYasc ii);
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:
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.
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(CurrentXasci
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);
}
as of now i'm using:
CurrentX=atof(CurrentXasci
CurrentY=-atof(CurrentYasc
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;
}
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.
ASKER
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.
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
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.
I have given some code below, may be it will help you on this issue,
it is a quick and dirty fix.
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;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
unsolved
Open in new window