Pages: [1]   Go Down
Author Topic: Send int from C# over Serial  (Read 1123 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I am writing a .NET program that can send integer values to my Arduino program (over Serial Port) and when received, Arduino will perform some action based on its value. The integer is of unknown digits and has to be of type int in C#.

Currently, I am able to send the values to my Arduino program by the following code in C#:
Code:
byte sendByte = 234;
serialPort.write(sendByte);

I receive this data in my Arduino program as follows:
Code:
char bufferType[20];

serial.readBytesUntil(10, bufferType, 1); //10 is ASCII code for line feed used for terminating character
if (bufferType[0] == 234){
//this condition comes out as  true in my Arduino program
}

With this above method however, I can only send integer from my C# program that are limited to 255 (1byte => 8bits => 2^8-1).
Since C# has a char which is of size 2 bytes, the int that it can accept should be of the size (2bytes => 16bits => -2^15 to 2^15-1). If I have an int of say value 65535, how do I write this char value to Serial and receive it in Arduino program?

In addition to this, in my current code, I am assigning integer value to byte data type such as byte sendData = 123;. I think there’s an implicit conversion here from integer to byte (right?) till the number 255. However, if I choose to send my data only by bytes in C# and choose to receive multiple bytes in Arduino, how do I assemble them to the correct integer again?
I was assuming, since transmitting integer seems to be a common value, there would be an inbuilt function that could have helped me avoid this encoding/assembling etc. Any guidance on this would be very helpful.
Logged

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

Code:
serial.readBytesUntil(10, bufferType, 1); //10 is ASCII code for line feed used for terminating character
Why are you using this? You are not sending a 10, so reading until one arrives is pointless.

Why are you lying to the function? There is plenty of room in the array for more than one character.

If you want to send an int, why not use Serial.parseInt() to read it?
Logged

UK
Offline Offline
Tesla Member
***
Karma: 135
Posts: 7724
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you send an integer from C# (or any other PC program) it will be received by the Arduino as 2 bytes - let's call them b0 and b1. You can convert them to an integer simply by multiplying b0 x 256 and adding b1.

BUT ... you have to know whether C# sends the high byte or the low first. The maths in my first para assume the high byte is sent first (I don't know C#).

If you want a more sophisticated approach (which works if C# uses the same byte order as the Arduino) you could use a C/C++ UNION to define an area of memory both as an array (into which the two bytes are saved) and as an INT from which the integer is read.

...R
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@PaulS and Robin2: Thanks for replying.  I've been looking at different methods to do this kind of serial transfer and I think I'll list them down here for folks who come and check this later as well. But I'd some small doubts in each of these techniques, which I believe you can help me with.

1. Sending data through byte data type:
Code:
byte b = 234; //limited to value 255
serialPort.write(b);

Arduino side:
Code:
int i = Serial.read(); //read the byte into int data type

What will happen if I try to assign char by passing byte from C#?
Code:
char c = Serial.read(); //

A byte typically means any data which can be binary/hex etc. as well. When I'd written byte b= 234; in the above program, is there an implicit conversion from int to byte in C#?

2. Sending multi-digit integers through byte data type
In C#, I can use BitConverter class to convert int (4 bytes in C#) to convert to 4 bytes of data and write to Serial as:
Code:
byte b[]; //where the values to b will be assigned by BitConverter class.
serialPort.write(b); //writes 4 bytes to serial

Arduino side:
How do I concatenate these 4 bytes to get my integer now in this Arduino C++ program?

3. Sending multi-digit integers through strings data type:
We can build a string (which is a collection of chars) and end it with a line feed or newline character explicitly in my program. Then, we can transfer this string over Serial which can be read by Arduino program to build an integer using decimal weight.
Code:
string s = "123\n"
serialPort.write(s);

Arduino side:
Code:
char incomingByte;
int incomingValue;
void loop(){
   if(Serial.available() > 0)
   incomingValue = 0;
   while(1){
       incomingByte = Serial.read();
       if(incomingByte == '\n') break;
      integerValue = (incomingByte - 48) + integerValue;
   }
}

4.
Code:
Serial.parseInt()
as PaulS mentioned. Don't know how it's used. Maybe PaulS can throw some light.

What's the most efficient way to send the data out the above? Assume that the length of digits in the integer will not be known and the Arduino program should be able to accept values >255.
« Last Edit: May 18, 2014, 10:36:45 am by rahulkashyap » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you send an integer from C# (or any other PC program) it will be received by the Arduino as 2 bytes - let's call them b0 and b1. You can convert them to an integer simply by multiplying b0 x 256 and adding b1.

BUT ... you have to know whether C# sends the high byte or the low first. The maths in my first para assume the high byte is sent first (I don't know C#).

@Robin2 : int in C# is 4 bytes. So, I think you meant that - if I send int from C#, it will be received in Arduino as 4 bytes. In the above post of mine which has different methods to send the data, one of them is BitConverter class which helps to get bytes for corresponding data(type).

Probably somebody could give more clarity on this, but Serial transfer is done by agreement on endian-ness of data and I think in this case lowest significant byte/data goes first and then higher significance and so on. If this is correct, then I can use the shift operation to shift the incoming higher significance byte by 256/512 etc. and then add the lower significance byte to get my integer. Not sure if this is correct, but will be helpful to hear from somebody.
Logged

Cincinnati, OH
Offline Offline
God Member
*****
Karma: 49
Posts: 871
I'm not bossy...I just know what you should be doing.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I think Robin2 still has a viable alternative even with a 4-byte int. With a  union:

Code:
union ImportData {
   char val[4];
   int myLong;
} fetch;

you could read the bytes coming in from Serial into val[] and then extract them from myLong and then cast to the int you need. If there is an endian problem, you would have to manipulate the val[] array before extracting the long.
Logged

UK
Offline Offline
Tesla Member
***
Karma: 135
Posts: 7724
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I didn't know C# uses 4-byte integers. Presumably if you are sending stuff to the Arduino you are only sending numbers that fit in a 2-byte integer so the two high bytes will be 0 - but what about the sign bit?

I think the simplest thing is to read the C# integer into a long on the Arduino and then convert the long to an int.

YOU are the person who has to agree on endianness.

Serial.parseInt() converts characters to their numeric equivalent. It doesn't work with bytes that are already parts of an integer.

Why do you have
Code:
int i = Serial.read(); //read the byte into int data type
rather than the more obvious
Code:
byte i = Serial.read(); //read the byte into int data type
?

...R
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I wrote a library that does exactly this, and more: it allows you to send commands with arguments from .NET (C#) to your Arduino and vice versa. It supports both sending commands in clear text as well as in binary format.

see this forum topic
forum.arduino.cc/index.php?topic=186928.msg1408426

And the playground entry:
http://playground.arduino.cc/Code/CmdMessenger

Note that in C# Ints are indeed 4 bytes, but at Arduino side it depends on the board: The ATMega chips work with 2 byte Ints, whereas the ARM chips work with 4 byte Ints. Something similar applies to Doubles, see http://thijs.elenbaas.net/2014/05/arduino-to-pc-messaging-improved-speed-compatibility-and-testing/:



This is why you should probably use int16_t and int32_t instead. I have never experienced Endianess issues. Good luck!
« Last Edit: May 20, 2014, 04:13:12 pm by mrTee » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 15
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In .net, use unsigned char for your data to arduino. Within arduino sketch, use String data type and getBytes() to receive as int.  To output integer values to .net from arduino, use int data type and serial out int value.
Logged

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

Quote
Within arduino sketch, use String data type
Dumbest advice of the week!
Logged

Pages: [1]   Go Up
Jump to: