Hello World! Me and a friend are working on an arduino project where we're sending multiple values over serial (13 to be specific (14 if you count the carriage return)). We're sending it with SerialPort and byte arrays through C# .Net 4.0 and then receiving it on an arduino mega which uses the messenger library. We're having some problems receiving the data on the arduino side. It receives the data, but it appears to be in the wrong order (i.e. values will be in different places each time). I checked and it appears we're reading the same amount as we're receiving, so I don't see how it could get scrambled.
Thank you very much for the help.
Here's the code for arduino and C# respectively:
#include <Messenger.h>
Messenger message = Messenger();
//int pins[] = { 2,3,4,5,6,7,8,9,10,11 };
void setup() {
Serial.begin(115200);
message.attach(messageReady);
pinMode(2, OUTPUT);
pinMode(3, OUTPUT);
//for (int i = 0; i <11; i++)
//pinMode(pins[i], OUTPUT);
}
void messageReady(){
int xspeed = message.readInt();
int xstrafe = message.readInt();
int xhandvert = message.readInt();
int xhandopen = message.readInt();
byte xupdown = message.readChar();
byte xsyringe = message.readChar();
byte xdrill = message.readChar();
byte xrotate = message.readChar();
byte xdrillio = message.readChar();
byte derp = message.readChar();
Serial.println(xspeed);
analogWrite(2, abs(xspeed));
}
void loop() {
digitalWrite(3, HIGH);
if (!Serial.available()) {
return;
}
if (Serial.available()) {
message.process(Serial.read());
}
}
(Here's the C# program. Sorry that it's so long.)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace ROV
{
public partial class Form1 : Form
{
Controller controller;
SerialPort port = null;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
controller = new Controller();
controller.InputChanged += new Controller.ControllerHandler(controller_InputChanged);
port = new SerialPort("COM15", 115200);
if (!port.IsOpen)
{
port.Open();
}
}
void controller_InputChanged(ControllerEventArgs e)
{
byte[] data = new byte[14]; //the data to send over the port
float speedMap = map(controller.LS.Y, -1, 1, -255, 255);
//byte speedTEST = (byte)speedMap;
byte[] portSpeed = BitConverter.GetBytes((short)speedMap);
lspeed.Invoke((Action)delegate { lspeed.Text = ((short)speedMap).ToString(); });
data[0] = portSpeed[0];
data[1] = portSpeed[1];
//0-1
#region Old Code
//come back to this later
//differentiate motor speeds
//if negative, value will be added (subtracted) from left motor and subtracted (added) to right motor = net left rotation
//if positive, inverse ^________________________________________________________________________________________________^
//c# side. do later
//rotation changed to pulsing rotation with select/start
//float rotationMap = map(controller.LS.X, -1, 1, -255, 255);
//byte[] portRotation = BitConverter.GetBytes((short)rotationMap);
//lrotation.Invoke((Action)delegate { lrotation.Text = ((short)rotationMap).ToString(); });
#endregion
float strafeMap = map(controller.LS.X, -1, 1, -255, 255);
byte[] portStrafe = BitConverter.GetBytes((short)strafeMap);
lstrafe.Invoke((Action)delegate { lstrafe.Text = ((short)strafeMap).ToString(); });
data[2] = portStrafe[0];
data[3] = portStrafe[1];
//2-3
float handVerticalMap = map(controller.RS.Y, -1, 1, -255, 255);
handVerticalMap = -handVerticalMap; //this is to invert the value like flight simulation
byte[] portHandVertical = BitConverter.GetBytes((short)handVerticalMap);
larmVert.Invoke((Action)delegate { larmVert.Text = ((short)handVerticalMap).ToString(); });
data[4] = portHandVertical[0];
data[5] = portHandVertical[1];
//4-5
#region Old Code
//phased out rs x usage on 3/19
//float handExtensionMap = map(controller.RS.X, -1, 1, -255, 255);
//byte[] portHandExtension = BitConverter.GetBytes((short)handExtensionMap);
//larmExt.Invoke((Action)delegate { larmExt.Text = ((short)handExtensionMap).ToString(); });
#endregion
float handOpenCloseMap = controller.RT - controller.LT; //lt = open, rt = close
handOpenCloseMap = map(handOpenCloseMap, -1, 1, -255, 255);
byte[] portHandOpenClose = BitConverter.GetBytes((short)handOpenCloseMap);
lhand.Invoke((Action)delegate { lhand.Text = ((short)handOpenCloseMap).ToString(); });
data[6] = portHandOpenClose[0];
data[7] = portHandOpenClose[1];
//6-7
byte portUpDown = controller.LB == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)1 : (byte)0;
portUpDown = controller.RB == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)2 : portUpDown;
lvertical.Invoke((Action)delegate { lvertical.Text = portUpDown == (byte)0 ? "Vertically Still." : (portUpDown == (byte)1 ? "Going up!" : "Going down!"); });
data[8] = portUpDown;
//8
byte portSyringe = controller.B == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)2 : (byte)0;
portSyringe = controller.A == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)1 : portSyringe;
lsyringe.Invoke((Action)delegate { lsyringe.Text = portSyringe == (byte)0 ? "Syringe Inactive." : (portSyringe == (byte)1 ? "Filling!" : "Emptying!"); });
data[9] = portSyringe;
//9
byte portDrill = controller.X == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)1 : (byte)0;
ldrill.Invoke((Action)delegate { ldrill.Text = portDrill == (byte)0 ? "Drill inactive." : "Drill active"; });
data[10] = portDrill;
//10
byte portRotate = controller.Select == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)1 : (byte)0;
portRotate = controller.Start == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)2 : portRotate;
lrotation.Invoke((Action)delegate { lrotation.Text = portRotate == (byte)0 ? "Not rotating." : (portRotate == (byte)1 ? "Rotating left." : "Rotating right."); });
data[11] = portRotate;
//11
//those are the mappable buttons so we need to map them to something for them to work.
//I suggest mapping lb2 to select and rb2 to start
byte portDrillIO = controller.Up == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)1 : (byte)0;
portDrillIO = controller.Down == Microsoft.Xna.Framework.Input.ButtonState.Pressed ? (byte)2 : portDrillIO;
lDrillIO.Invoke((Action)delegate { lDrillIO.Text = portDrillIO == (byte)0 ? "Not moving." : (portDrillIO == (byte)1 ? "Extending." : "Retracting."); });
data[12] = portDrillIO;
//12
data[13] = ASCIIEncoding.ASCII.GetBytes("\r")[0];
//port.Write(new byte[] { speedTEST }, 0, 1);
port.Write(data, 0, 14);
port.DataReceived += new SerialDataReceivedEventHandler(port_DataReceived);
//ldata.Invoke((Action)delegate { ldata.Text = BitConverter.ToString(data); });
//char[] buffer = new char[13];
//if (port.BytesToRead > 0)
//{
// ldata.Invoke((Action)delegate
// {
// port.Read(buffer, 0, 13);
// ldata.Text = new string(buffer); //this is to stop epic, hardcore, vomit-inducing lag
// });
//}
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
ldata.Invoke((Action)delegate
{
ldata.Text = port.ReadExisting();
});
}
float map(float x, float in_min, float in_max, float out_min, float out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//because of the polling thread, app doesn't close when exit button is hit.
//this fixes that
controller.ExitPollingThread();
Application.Exit();
}
}
}