truncated ints and conversion to chars

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.

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).

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

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

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

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.

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

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

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

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?

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 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...

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.

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.

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

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*

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?

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 int vals[5] = {1, 100, 255, 258, 1023};
This actually is stored in memory as bytes:

0x1, 0x0,   0x64, 0x0,   0xFF, 0x0,   0x2, 0x1,   0xFF, 0x3

You could transmit it as binary bytes with something like: udp_transmit((char *)vals, sizeof(vals));
Or you could transmit it as text ("1 100 255 258 1023") by doing something like:

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)

Very well explained. Thanks!