Sending standard input to Arduino C# - c#

I am trying to take the standard input from the console and send it to my Arduino Uno as plain ASCII.
I get the Input and strip \r\n from it using this code:
String Input = Console.Read().ToString().Replace("\r",string.Empty).Replace("\n",string.Empty);
When I perform doConsole.WriteLine(Input);, it outputs "72" which is correct, but when I do serialPort.Write(Input); the Arduino returns "55", which it does for everything.
What am I doing wrong?
My code for the C# side (host/PC):
String Input = Console.Read().ToString().Replace("\r", string.Empty).Replace("\n",string.Empty);
//Console.WriteLine(Input);
//serialPort.Write(Input);
char[] InputChar = Input.ToCharArray();
serialPort.Write(InputChar,0,1);
//byte[] InputByte = Encoding.ASCII.GetBytes(Input);
//Console.WriteLine(Input);
//serialPort.WriteLine(Input);
Thread.Sleep(25); //Wait 0.025 second.
//***************************************************************//
// Read anything from the serial port. //
//***************************************************************//
numBytes = serialPort.BytesToRead;
for (int i = 0; i < numBytes; i++)
rxPacket[i] = (byte)serialPort.ReadByte();
result = new char[numBytes];
for (int i = 0; i < numBytes; i++)
result[i] = (char)rxPacket[i];
Console.Write("Read this from Arduino:");
Console.WriteLine(result);
Console.WriteLine("press Enter to continue");
Console.ReadKey(); //Read nothing.
And my Arduino sketch:
const int ledPin = 13; // The pin that the LED is attached to.
int incomingByte; // A variable to read incoming serial data into.
void setup() {
// Initialize serial communication:
Serial.begin(9600);
// Initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
}
void loop() {
// see if there's incoming serial data:
if (Serial.available() > 0) {
// Read the oldest byte in the serial buffer:
incomingByte = Serial.read();
// If it's a capital H (ASCII 72), turn on the LED:
if (incomingByte == 'H') {
digitalWrite(ledPin, HIGH);
Serial.print(incomingByte);
}
// If it's an L (ASCII 76), turn off the LED:
else if (incomingByte == 'L') {
digitalWrite(ledPin, LOW);
Serial.print(incomingByte);
}
else{
Serial.print(incomingByte);
}
}
}
Edit: changed the code to the following. Still no luck; I am getting same reply.
String Input = Console.Read().ToString().Replace("\r",string.Empty).Replace("\n",string.Empty);
Console.Write(Input,0,1);
//serialPort.Write(Input);
byte[] inputByte = Encoding.ASCII.GetBytes(Input);
serialPort.Write(inputByte,0,1);

Well, I looked it up... As it turns out, ASCII code 55 = 7.
7 is the first digit of 72.
Hmm, so perhaps your sending decimal numbers to the Arduino here and the Arduino sees a 7 first. May I suggest to convert your byte and send it as a byte (a byte can only contain 0..255), but it is a single ASCII code.
Maybe for the Arduino to think about, but maybe it is not related to this. Instead of
int incomingByte; // ints are made of 2 bytes an int isn't an incomming byte
try
Byte incomingByte;

So I managed to get it working
Basically, converting it to a byte took me a while to work out.
this is the code I ended up with
String Input = Console.Read().ToString().Replace("\r", string.Empty).Replace("\n",string.Empty);
Console.Write(Input,0,1);
byte[] inputByte = new byte[1];
inputByte[0] = Convert.ToByte(Input);
serialPort.Write(inputByte, 0, 1);
//byte[] inputByte = Encoding.ASCII.GetBytes(Input);
//serialPort.Write(inputByte,0,2);
//String num = inputByte.ToString();
//serialPort.WriteLine(num);
//Console.WriteLine(Input);
//serialPort.Write(InputByte,0,1);
Thread.Sleep(25); //Wait 0.025 second.
//***************************************************************//
// Read anything from the serial port. //
//***************************************************************//
numBytes = serialPort.BytesToRead;
for (int i = 0; i < numBytes; i++)
rxPacket[i] = (byte)serialPort.ReadByte();
result = new char[numBytes];
for (int i = 0; i < numBytes; i++)
result[i] = (char)rxPacket[i];
Console.Write("Read this from Arduino:");
Console.WriteLine(result);
Console.WriteLine("press Enter to continue");
Console.ReadKey(); //Read nothing.
Seems to work Perfectly now.

Related

How to send numbers from C# to Arduino Uno with a usb port?

I want to send integer numbers (between 101 and 1616)from the c# program to the arduino Uno using a usb port.
I know how to use registers of the arduino Uno and wanted to know if there is a interrupt when reviving data over this USB port.
At the moment I am using this but it isn't working.
if(Serial.available()!=0)
{
input= (unsigned char)Serial.read();
}
And on the C# program I am using this code:
byte[] b = BitConverter.GetBytes(MyIntx);
SerialPort.Write(b, 0, 4);
How can i send bigger numbers between the c# program and the arduino uno?
And is there a special interrupt for receiving these type of numbers?
What you need to do is send byte by byte. There are complex solutions and there are easy ones
Complex: from https://www.baldengineer.com/arduino-multi-digit-integers.html
void setup() {
Serial.begin(9600);
}
unsigned int integerValue=0; // Max value is 65535
char incomingByte;
void loop() {
if (Serial.available() > 0) { // something came across serial
integerValue = 0; // throw away previous integerValue
while(1) { // force into a loop until 'n' is received
incomingByte = Serial.read();
if (incomingByte == '\n') break; // exit the while(1), we're done receiving
if (incomingByte == -1) continue; // if no characters are in the buffer read() returns -1
integerValue *= 10; // shift left 1 decimal place
// convert ASCII to integer, add, and shift left 1 decimal place
integerValue = ((incomingByte - 48) + integerValue);
}
Serial.println(integerValue); // Do something with the value
}
}
My Version:
Convert Int to Char, Send byte by byte and In Arduino Convert it back to Int.
int x=150;
string x_char = x.ToString();
for(int i=0;i<x_char.length();i++)
{
//Send Each Character to Arduino "c_char[i]".
}
//Send a new line or any special character to mark the break. For Instance "\n";
IN Arduino:
String a;
void setup() {
Serial.begin(9600); // opens serial port, sets data rate to 9600 bps
}
void loop() {
while(Serial.available()) {
a= Serial.readStringUntil('\n'); //Read until new line
x = Serial.parseInt(); //This is your Integer value
}
}
Connect();
if (serialPort1.IsOpen)
{
int MyInt = ToInt32(lblMixerCase.Text);
byte[] b = GetBytes(MyInt);
serialPort1.Write(b, 0, 1);
int MyInt2 = ToInt32(txtRPM.Text);
if (MyInt2<=255)
{
byte[] z = GetBytes(MyInt2);
serialPort1.Write(z, 0, 1); //For first 1 byte numbers
}
else if (MyInt2<=510)
{
byte[] r = GetBytes(MyInt2);
serialPort1.Write(r, 0, 2); for 2 byte numbers
}
else if (MyInt2<=765)
{
byte[] a = GetBytes(MyInt2);
serialPort1.Write(a, 0, 3); //for 3 byte numbers
}
else if (MyInt2<=1020)
{
byte[] q = GetBytes(MyInt2);
serialPort1.Write(q, 0, 4); //for 4 byte numbers
}

Random arithmetic overflows when reading from serial port

What I'm doing is taking a user entered string, creating a packet with the data, then sending the string out to a serial port. I am then reading the data I send via a loopback connector. My send is working flawlessly, however my receive is randomly throwing an arithmetic overflow exception.
I say randomly because it is not happening consistently. For example, I send the message "hello" twice. The first time works fine, the second time outputs nothing and throws an exception. I restart my program, run the code again, and send hello only to receive "hell" and then an exception. On rare occasion, I'll receive the packet 3 or 4 times in a row without error before the exception.
Here is my relevant code:
public void receivePacket(object sender, SerialDataReceivedEventArgs e)
{
byte[] tempByte = new byte[2];
int byteCount = 0;
while (serialPort1.BytesToRead > 0)
{
if (byteCount <= 1)
{
tempByte[byteCount] = (byte)serialPort1.ReadByte();
}
if (byteCount == 1)
{
receivedString = new byte[tempByte[byteCount]];
receivedString[0] = tempByte[0];
receivedString[1] = tempByte[1];
}
else if (byteCount > 1)
{
byte b = (byte)serialPort1.ReadByte();
receivedString[byteCount] = b;
}
byteCount++;
}
int strLen = (byteCount - 3);
tempByte = new byte[strLen];
int newBit = 0;
for (int i = 2; i <= strLen+1; i++)
{
tempByte[newBit] = receivedString[i];
newBit++;
}
string receivedText = encoder.GetString(tempByte);
SetText(receivedText.ToString());
}
I'm well aware that my implementation using byteCount (which I use to traverse the byte array) is rather sloppy. When I step through the code, I find that when I get the error byteCount == 1, which is making strLen a negative number (since strLen is byteCount - 3, which is done because the packet contains a header, length, and CRC i.e. byteCount - 3 == # of actual data bytes received). This leads to by tempByte having a size of -2, which throws my exceptions. I, however, am having a very hard time figuring out why byteCount is being set to 1.
The code after this basically just traverses the data section of the array, copies it into the tempByte, then is sent off to a function to append the text in another thread.
I am guessing that byteCount is 1 because you only received one byte - or rather, you processed the first byte before the second one arrived in the buffer.
The ReadByte function will wait for a certain amount of time for a byte to arrive if there isn't one waiting.
Maybe if instead of checking BytesToRead, you did something more like this:
byte headerByte = serialPort1.ReadByte();
byte length = serialPort1.ReadByte();
receivedString = new byte[length];
receivedString[0] = headerByte;
receivedString[1] = length;
for (int i = 2; i < length; i++) {
receivedString[i] = serialPort1.ReadByte();
}

How to convert little endian to big and send it over UDP?

I need to conver little endian which is float to the big and send them through UDP. The code snipped receives coord data and assigns it to the float array, then converts to the byte data array and finaly should be send over UDP connection but it doesn't work!
public void SendUDP()
{
try
{
lockObj.EnterReadLock();
try
{
foreach(CoordData datam in coordDataList)
{
float[] dfv = {datam.X, datam.Y, datam.Z, datam.Alpha, datam.Theta, datam.Phi};
/*
data = BitConverter.GetBytes(datam.Y);
data = BitConverter.GetBytes(datam.Z);
data = BitConverter.GetBytes(datam.Alpha);
data = BitConverter.GetBytes(datam.Theta);
data = BitConverter.GetBytes(datam.Phi);
*/
data = BitConverter.GetBytes(dfv);
Array.Reverse(data);
}
client.Send(data, data.Length, remoteEndPoint);
}
finally
{
lockObj.ExitReadLock();
}
}
catch (Exception err)
{
print(err.ToString());
}
}
Your problem is that you are reversing the entire array of floats. You need to reverse the bytes of each individual float.
In fact, what you wrote in your question won't even compile since there is no overload of BitConverter.GetBytes that takes an array.
What you'd have to do (other than use the library functions that exist to handle this for you) is something like this:
List<byte> myData = new List<byte>();
myData.AddRange(Array.Reverse(BitConverter.GetBytes(datam.x));
myData.AddRange(Array.Reverse(BitConverter.GetBytes(datam.y));
//....etc....
byte[] bytesToSend = myData.ToArray();
You should use IPAddress.HostToNetworkOrder() to make sure your value is correct for your environment.
Here is a solution for the problem:
int width = sizeof(float);
int nDataIndex = 0;
byte[] data = new byte[myData.Count * width];
for (int i = 0; i < myData.Count; ++i)
{
byte[] converted = BitConverter.GetBytes(myData[i]);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(converted);
}
for (int j = 0; j < width; ++j)
{
data[nDataIndex+j] = converted[j];
}
nDataIndex+=width;
}
client.Send(data, data.Length, remoteEndPoint);

Error in recieving data from TCP Client

I've written an application which listens to a port and receives some packets,according to my customized protocol, the packets are either 49 byte to 1500 byte, which i can tell from data length in the packet. the way i should interpret and deal with data in 49 byte packets and bigger packets are different.
The problem is that when i receive packets less than 1374 byte everything is ok, but when the packet length gets more, i receive the following exception and i also lose 4 last bytes of my data(i've tested with a 1384byte packet and i lost the last 4 bytes)
Exception which is raised:
Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: startIndex
each 49 byte packet has 35 byte of data, and the data length of bigger packets are non-deterministic(because of compression).
i found out sometimes the last 4 bytes are in a seperate "bytes" and "result" variables,meaning they are being treated like new packets and are not being attached to the packet they belong to.
here's the code for receiving data:
TcpClient Client = obj as TcpClient;
EndPoint ep = Client.Client.RemoteEndPoint;
List<Byte> result = new List<byte>();
result.Capacity = 2000;
try
{
NetworkStream stream = Client.GetStream();
int i = 49;
while ((i = stream.Read(bytes, 0,49)) != 0)
{
for (int id = 0; id < i; id++)
{
result.Add(bytes[id]);
}
//reading data length to determine packet length
byte[] tmp = new byte[2];
tmp = BitConverter.GetBytes(BitConverter.ToUInt16(result.ToArray(), 9));
if (BitConverter.IsLittleEndian)
{
Array.Reverse(tmp);
}
Int16 l = BitConverter.ToInt16(tmp, 0);
if (l>35)
{
stream.Read(bytes, result.Count, l - 35);
for (int id = 49; id <((l-35)+49); id++)
{
result.Add(bytes[id]);
}
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytes, 0, 2000);
result.Capacity = 2000;
}
}
else
{
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytes, 0, 2000);
result.Capacity = 2000;
}
}
}
System.Diagnostics.Debug.WriteLine("client Close");
Client.Close();
}
catch (System.Exception ex)
{
throw ex;
}
finally
{
Client.Close();
this.clients.Remove(Client);
}
According to Greg Suggestion and my researches,i also tried using following method:
NetworkStream stream = Client.GetStream();
int bytesread = 0, OffsetTemp = 0;
while (stream.CanRead)
{
OffsetTemp = 0;
bytesread += stream.Read(bytess, OffsetTemp, 11);
OffsetTemp = OffsetTemp + 11;
byte[] tmp = new byte[2];
tmp = BitConverter.GetBytes(BitConverter.ToUInt16(bytess.ToArray(), 9));
if (BitConverter.IsLittleEndian)
{
Array.Reverse(tmp);
}
Int16 l = BitConverter.ToInt16(tmp, 0);
bytesread += stream.Read(bytess, OffsetTemp++, 11 + l + 3);
for (int id = 0; id < l + 14; id++)
{
result.Add(bytess[id]);
}
if (this.TCPDataReceivedHandler != null)
{
this.TCPDataReceivedHandler(ep, result.Count, result.ToArray());
result.Clear();
Array.Clear(bytess, 0, 2000);
}
}
When using TCP, you must keep in mind that the size of the data blocks you put in is not guaranteed to be the same size of data blocks you get out on the receiving side. TCP is a stream protocol, so it guarantees that the same bytes get to the other side in the same order as they were sent (if not, the socket connection will be reset). TCP does not maintain any kind of block boundaries between calls to send(), and blocks may be arbitrarily split or coalesced depending on network conditions.
Your receiver must be prepared to handle receiving any amount of data from the calls to stream.Read(), but your code does not appear to do this. For example, correctly written receiver code should continue to work correctly even if stream.Read() receives only one byte at a time.

How to send and recieve over rs-485 serial port?

I want to communicate between my PC and some controller boards.
The expectation is that the PC will send an identifier of the board on RS-485 and then it should receive the answer from the board.
When I try to receive the response, I receive the wrong data.
Here is my code:
public void set()
{
SerialPort sp = new SerialPort("COM1");
sp.Open();
if (sp.IsOpen)
{
byte[] id = new byte[]{0,0,0,0,0,0,0,0,0,0};
byte[] rec = new byte[540];
while (!end)
{
sp.Write(id,0,id.Length);
sp.Read(rec,0,rec.Length);
//do some with rec
//WORKING
//do soem with rec
}
}
sp.Close();
}
It works if I am using RS-232, but not when I am using RS-485.
UPDATE :
It is RS-485 2 wire.(http://en.wikipedia.org/wiki/RS-485)
I found the problem.
sp.Read(rec,0,rec.Length);
Read is a non-blocking method so it reads the buffer but does not wait for all of the bytes. So you need to use the return value of this function which returns an integer with a number of bytes that it could read.
I am using this:
int read = 0;
int shouldRead = readData1.Length;
int len;
while (read < shouldRead )
{
len = serialport.Read(buffer, 0, readData1.Length);
if (len == 0)
continue;
Array.Copy(buffer, 0, readData1, read, len);
read += len;
Thread.Sleep(20);
}

Categories

Resources