Loading...
Pages: [1]   Go Down
Author Topic: truncated ints and conversion to chars  (Read 473 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have two issues for which I'm not sure the solutions.  First, the following code seems to be truncating my ints so I get a max value of somewhere around 180, rather than 255.  Any idea what I'm doing wrong here?  Ignore the variable uip_appdata- this is part of the WiShield library (ugh), references to the rest of which have been omitted for simplicity.

Code:
int sensors[10] = {0,0,0,0,0,0,0,0,0,0};
int motors[10] = {0,0,0,0,0,0,0,0,0,0};

void setup()
{
   Serial.begin(57600);
}

void loop()
{  
   for(int i = 0; i < 10; i++){
     sensors[i] = map(analogRead(i), 0, 1023, 0, 255);
   }
}

extern "C"
{
   static void send_data(void)
   {
     memcpy(uip_appdata, &sensors, sizeof(sensors));
     memcpy(&motors, uip_appdata, sizeof(sensors));
     for(int i = 0; i < 10; i++){
       Serial.println(motors[i]);
     }
   }
}

Second, trying the same thing with either chars or unsigned chars is giving me all zeros upon conversion back to ints.  I think the root of both these issues is that integers take up two bytes and I'm losing the second one, but it seems I should be able to fit an integer into one unsigned char, no?  

I'm also wondering if there's a more robust C function to convert chars to ints than atoi.  I much prefer sprintf to itoa, as I have had problems with the latter handling larger integers (not longs, just something in the range of 1023).  

Code:
unsigned char sensors[10] = {0,0,0,0,0,0,0,0,0,0};
unsigned char motorsTemp[10] = {0,0,0,0,0,0,0,0,0,0};
int motors[10] = {0,0,0,0,0,0,0,0,0,0};

void setup()
{
   Serial.begin(57600);
}

void loop()
{  
   for(int i = 0; i < 10; i++){
     sensors[i] = byte(map(analogRead(i), 0, 1023, 0, 255));
   }
}

extern "C"
{
   static void send_data(void)
   {
     memcpy(uip_appdata, sensors, sizeof(sensors));
     memcpy(motorsTemp, uip_appdata, sizeof(sensors));
     for(int i = 0; i < 10; i++){
       motors[i] = atoi((const char*)motorsTemp[i]);      
       Serial.println(motors[i]);
     }
   }
}

OR

Code:
int sensors[10] = {0,0,0,0,0,0,0,0,0,0};
int motors[10] = {0,0,0,0,0,0,0,0,0,0};

void setup()
{
   Serial.begin(57600);
}

void loop()
{  
   for(int i = 0; i < 10; i++){
     sensors[i] = map(analogRead(i), 0, 1023, 0, 255);
   }
}

extern "C"
{
   static void send_data(void)
   {
     char str[20];
     sprintf(str, "%i", sensors);
     memcpy(uip_appdata, str, strlen(str));
     memcpy(str, uip_appdata, strlen(str));
     for(int i = 0; i < strlen(str); i++){
       motors[i] = atoi((const char*)str[i]);      
       Serial.println(motors[i]);
     }
   }
}

Thanks!

-Zach
Logged

UK
Offline Offline
Faraday Member
**
Karma: 15
Posts: 2852
Gorm deficient
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Sounds like you're converting 3.3v signals with a 5v reference.
(Edit:) Make that 3.5v

« Last Edit: September 10, 2010, 11:41:34 am by GrooveFlotilla » Logged

Per Arduino ad Astra

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You mean the max analog value for 5v is 1023, while for 3.5v it's smaller?  What is it?

Also, still looking for an answer to my second question, although realize it's more complicated.  
Logged

UK
Offline Offline
Faraday Member
**
Karma: 15
Posts: 2852
Gorm deficient
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Don't have a calculator to hand, but if your reference is 5V, then the maximum reading for 3.3V is going to be (3.3 / 5) * 1023, or arond about the 675 mark
Logged

Per Arduino ad Astra

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Cool, thanks.  Just wasn't sure it was linear.  
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 35507
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Also, still looking for an answer to my second question, although realize it's more complicated.

Quote
Second, trying the same thing with either chars or unsigned chars is giving me all zeros upon conversion back to ints.
Trying what same thing?
Logged

SF Bay Area (USA)
Offline Offline
Faraday Member
**
Karma: 78
Posts: 5453
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
it seems I should be able to fit an integer into one unsigned char, no?
Um.  No.
An integer is 16 bits, and an unsigned char is 8 bits.

You seem to be confusing "char" (which is just an 8-bit integer), with "character string" (which is a sequence of 8-bit integers that contain/represent text.)  For example this
Code:
motors[i] = atoi((const char*)motorsTemp[i]);
is pretty much nonsensical.

atoi() converts text to an integer, not a char to an integer.
I can't imagine the problems you have with itoa; care to describe them in more detail?

i can't actually tell what your code is trying to do...
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have 10 analog sensors being read in from one Arduino and transmitted over WiFi via UDP to another Arduino which uses the values to PWM dc motors.  For various compatibility issues with other systems receiving the data, I would prefer to transmit the values as an array of chars or unsigned chars rather than as ints.

What I can't figure out is how to read the ints into the array, when they will take up 2 index places each and, similarly, how to parse them out into an array of ints.  Whatever method I use, it needs to be able to be read into uip_appdata using the memcpy function in order to work with the WiShield library.  The problem with itoa was that it would halt the program whenever I sent a number around 1023.  This was likely due to my implementation and I am now scaling the value to 255, but I still prefer sprintf for it's robustness and the fact that I understand better how it works.  
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 35507
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I would prefer to transmit the values as an array of chars or unsigned chars rather than as ints.
This is the part that is hard to understand. Why chars?

Why not use a byte array, with twice as many positions as the integer array?

You can then use memcpy to copy the integer array to the byte array. Or, use a for loop, and the lowByte abd highBYte functions to split each integer into two bytes to store in the byte array.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have to be honest, I thought an unsigned char and a byte were the same thing.  What is the distinction?

Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 138
Posts: 19066
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I thought an unsigned char and a byte were the same thing
You were absolutely correct.

However,
unsigned char != unsigned char*

and similarly,

byte != byte*
Logged

Pete, it's a fool looks for logic in the chambers of the human heart.

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

But given:

unsigned char foo[3];

and

char *bar = &foo[0];

doesn't

foo == bar

for all intents and purposes or am I getting it completely wrong here?
Logged

SF Bay Area (USA)
Offline Offline
Faraday Member
**
Karma: 78
Posts: 5453
Strongly opinionated, but not official!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I would prefer to transmit the values as an array of chars or unsigned chars rather than as ints.
Do you mean that you want to transmit it as TEXT?  You don't have much choice about transmitting as bytes; since ethernet chips and whatnot (including the Arduino itself) tend to be very byte oriented...

So you have
Code:
int vals[5] = {1, 100, 255, 258, 1023};
This actually is stored in memory as bytes:
Code:
0x1, 0x0,   0x64, 0x0,   0xFF, 0x0,   0x2, 0x1,   0xFF, 0x3

You could transmit it as binary bytes with something like:
Code:
udp_transmit((char *)vals, sizeof(vals));
Or you could transmit it as text ("1 100 255 258 1023") by doing something like:
Code:
sprintf(buffer, "%d %d %d %d %d", vals[0], vals[1], vals[2], vals[3], vals[4]);
udp_transmit(buffer, strlen(buffer));
But you don't need to do any actual CONVERSION for the first style (you just need to get the code to treat the memory as bytes instead of ints), and the second style will require more than an "int" worth of storage for each number (at least 4 bytes to handle the range of 0..1023)
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 57
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very well explained.  Thanks!
Logged

Pages: [1]   Go Up
Print
 
Jump to: