Society of Robots - Robot Forum

Software => Software => Topic started by: Resilient on February 22, 2009, 10:52:13 PM

Title: Sending a number greater than 255
Post by: Resilient on February 22, 2009, 10:52:13 PM
I am a bit puzzled about how to solve my problem here.

I want to be able to send numbers via a terminal to test different servo position.  But I can only send a single byte at a time.  So how do I send a number bigger than 255?  I can get an array of digits, but I am not sure how to turn that array into an actual int.

Thanks!
Title: Re: Sending a number greater than 255
Post by: Razor Concepts on February 22, 2009, 10:57:22 PM
Try
long int num = 1000;
Title: Re: Sending a number greater than 255
Post by: Resilient on February 22, 2009, 11:08:29 PM
Here is what have got right now:

Code: [Select]
void input_test(void)
{
while(1)
{
long int temp;
temp=uart1GetByte();
if (temp != -1)//if data received
{
rprintf ("You sent: %d \n", temp);
}

}
}
I can send numbers, from the terminal, 0-255 and it will reply "You sent: 0" to "You sent: 255" but it wont go higher than that.   I am using RealTerm, so I don't know what side the limitation is on.

If I send 2000 as ASCII it will say "You sent: 50", "You sent: 48", "You sent: 48" and "You sent: 48".

I need it to say "You sent: 2000" and I need that 2000 to be an int rather than an array of chars.
Title: Re: Sending a number greater than 255
Post by: Razor Concepts on February 22, 2009, 11:15:07 PM
http://www.societyofrobots.com/programming_printf.shtml

Try replacing %d with %lu and make temp a long unisgned int
Title: Re: Sending a number greater than 255
Post by: Resilient on February 22, 2009, 11:27:55 PM
Nope, now it keeps telling me I "You sent: lu"

And my code:

Code: [Select]
void input_test(void)
{
unsigned long int temp;
while(1)
{
temp=uart1GetByte();

if (temp != -1)//if data received
{
rprintf ("You sent: %lu \n", temp);
}
}
}

I think the problem is I either need to make an array of digits and turn that into an int somehow or I need to combine two bytes because it can only get one byte at a time... but I'm not sure RealTerm can send numbers of more than 1 byte.
Title: Re: Sending a number greater than 255
Post by: cosminprund on February 23, 2009, 01:33:11 AM
You need to rethink your problem a bit. Serial communication doesn't work with integers, jpegs, coordinates, whatever - it only works with bytes! If you need to send something other then an actual "byte" then you'll need to put it throw an process called "serialization" - ie: split it into small byte-size parts and send those parts one by one. Since you want it to work with HyperTerminal (or any other kind of terminal application) then you'll most likely want an ASCII serialization: If you want to send the 2000 number, just send it as the following 4 bytes: "2", followed by "0", followed by "0", followed by "0"! In fact when you type "2000" in the terminal application that's exactly what's happening, you're not sending one integer number, you're sending 4 ASCII chars. In fact the hyper terminal couldn't care less about what you typed: try typing "two thousand", it will not complain.

ASCII Char '2' has ASCII code 50;
ASCII Char '0' has ASCII code 48;

So you see why you're getting "You sent: 50"; "You sent: 48"; "You sent: 48"; "You sent: 48" - the MCU sees the ASCII codes for the chars you typed into your HyperTerminal application!

In order to fix this you'll need to know a few more ASCII codes:

ASCII Char '0' has ASCII code 48 (hex: 0x30);
ASCII Char '1' has ASCII code 49 (hex: 0x31);
...
ASCII Char '9' has ASCII code 57 (hex: 0x39);

An other interesting ASCII code:
ASCII Char CARIAGE RETURN (this is sent when you hit ENTER on the keyboard) has ASCII code 13 (hex: 0x0D)

You'll need to write an algorithm that initialises the number that's being read, reads the ASCII numbers one by one and only considers it read an number (the "You sent:" line) when an CR char (code 13) is received, ie: when you hit ENTER in HyperTerminal.

I don't want to kill all the fun by writing the algorithm for you, so give it a try yourself.
Title: Re: Sending a number greater than 255
Post by: paulstreats on February 23, 2009, 07:00:20 AM
C compilers come with an algorythm called itoa() that turns int's into their ascii counterparts. It returns an array of bytes that represent the number.
Title: Re: Sending a number greater than 255
Post by: cosminprund on February 23, 2009, 07:41:00 AM
Joke: I don't think he's programming his biological brain in "C" :) He's typing the "2000" in HyperTerminal, so he has just done the conversion from "2000" (oops, cant even type that without converting it to ASCII first) to "2000" - no need to convert the integer to an ASCII string!

The reverse library function would be "atoi" - but I'd say it's more work to prepare the call to the function then it is to actually implement the conversion algorithm.
Title: Re: Sending a number greater than 255
Post by: Resilient on February 23, 2009, 12:02:59 PM
So I can get as far as having an array of chars '2', '0', '0', '0' and I can have it check for \n and do 'something' when it receives that.  I could also turn those chars into ints by just using the char codes and subtracting 48 from them.

But I still cant figure out how to concatenate either 4 ints or 4 chars into one longer int.

I suppose I could do something like:

Code: [Select]
array digits[]
int number
int power = 0
for (i=number_of_digits -1   i>=0   i--)
    number = number + 10^power * digits[i]
    power++

It seems like that ought to work.  It also seems like there ought to be a better way.  :P
Title: Re: Sending a number greater than 255
Post by: Asellith on February 23, 2009, 12:34:26 PM
I think we need to take the terminal program out of the equation for a minute. What are you trying to make happen and what are the end results of the communication. For instance do you want to type 2000 into your terminal program and have it sent to the MCU. then the MCU will "translate" that into servo movement. It seems your testing backwards then. If this is between two MCUs then the problem is totally different. 2 MCUs can talk easier then a terminal program to MCU.

If you want to terminal program to talk to the MCU then you need to create a command structure for the MCU to interpret. Such as SM2000 for Servo move 2000. Then the MCU waits for a serial input and will have to put them all into memory till it receives the /n command. Then it needs to analyze the command. So the MCU will break off the first 2 characters and compare them to a list of possible commands. Then it can parse the rest of the stored data into a specific function call for that command. In this case the string or char array (which is what a string is essentially) is sent to the servo move function. There it needs to convert it to an int.

If I'm on the right track I have a good idea how to convert the string to an int easily but I'll need to verify if it would work. Let me know and I can help.
Title: Re: Sending a number greater than 255
Post by: Resilient on February 23, 2009, 04:23:26 PM
For this particular bit of code, I just wanted to type, for example, 800 in the console and just send that to servo C1.

I know I want the servo in C1 to oscillate between two positions, but I don't know what value corresponds to those positions.  So I want to test that via a console.

Later I may want to be able to type C4 900 to send the C4 servo to 900.  But for now I really just want to get the basic task of entering a value and having that value always get sent to C1 servo position.

Thanks for the help so far!

Title: Re: Sending a number greater than 255
Post by: cosminprund on February 24, 2009, 12:25:39 AM
Don't bother with the array of digits, you don't need the digits - you only need the int! The way to make the conversion is the same for any numeration base (decimal, hex, octal, binary, you name it). You start with an ZERO. When the first digit shows up you multiply the previous number with the base of numeration (10 in the case of decimal) and then you add the new digit.

Ex: Start with 0;
I see digit "7"; 0 * 10 + 7 = 7
I see digit "3"; 7 * 10 + 3 =  70 + 3 = 73
I see digit "2"; 73 * 10 + 2 = 730 + 2 = 732;
I see an CR => I do something with the number and then reset it to zero so I can read the next number.

Code: [Select]
In pseudo-code it would look like this:

int Number=0;

while(1) {
  temp=uart1GetByte();
  if ((temp >= '0') && (temp <= '9')) Number = Number * 10 + temo -'0';
  else if (temp == 13)
    {
       // Do something with the number!
       rprintf("got this: %d", Number);
       // Start the next number
       Number := 0;
    }
}