Interfacing the arduino board with C#.

Hello all,

My question will go a little further than the title i've submitted but i couldn't make a longer discription in the title box.

I'm doing a final project for my graduate course in manufacturing automatisation. For this project i designed a small CNC - engraving machine. Originally i wanted to use a Make controller board for controlling the X-Y servo amplifiers with an analog output signal. Why the Make controller? Because it was programmable from the .NET environment. I have some talent and some experience in C# and .NET and was convinced i could write a small & simple cad application to program the Make board. Basic idea: user draws a simple line-drawing, my application compiles it to board instructions to send analog outputs which drive the servo's along the path i've compiled through my application.

But to my horror it seems the make board is no longer available, and my project is already over half its development time.

So my question is:

Is it doable to program the arduino board through a self written small Cad-application in C#. I've read another post here that u can send serial data to the arduino board using C#. Would this be a possibility to send instructions to create the desired analog outputs for the servo-amplifiers?

I've only got 3 months left to find a replacement that i can use with my own application to control 2 servo Axis through analog inputs. The servo's are way to big to use with the on board servo connectors so my only choice is the way i just described (i think).

Or does anybody have other recommendation which controller board would fit my needs.

Thank u for your time to provide any help

regards

Bender

I've read another post here that u can send serial data to the arduino board using C#

But using what? As long as your C# environment can end serial then the Arduino can receive it. The bit the arduino does is simply turn those coordinates into movement, you don't write that in C#.

By the way you might be better off using stepping motors for this sort of thing.

Yes it's possible from C#, just use the SerialPort class. I am working on a sensor/control board for a solar heater. My board listens for temperature readings and sends an XML document back to the PC once a minute. The PC grabs these and uts them in an SQL database. You can also send commands to the board. I just have a simple 8 byte command code that i put together. Here's my serial client code. It listens on a serial port and sends it back to the main thread.

One gotcha in this is that the SerialPort is it's own thread and if you are interacting with windows directly from a message handler it won't be thread safe and will error out. If this hapens, you can use Invoke to do this in a thread safe way. Here's the code from my main window that adds the message received from the arduino to a text box.

Hope this helps.

michael

private delegate void SetTextCallback(string text);

private void AddText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.serialOutputTextBox.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(AddText);
this.Invoke(d, new object[] { text });
}
else
{
this.serialOutputTextBox.Text = this.serialOutputTextBox.Text + text;
}
}

Here's the SerialClient code.

class SerialClient : ArduinoClient
{
SerialPort port;

public SerialClient(string name, int baud)
{
port = new SerialPort();
port.PortName = name;
port.BaudRate = baud;

port.DataReceived += OnSerialData;
port.ErrorReceived += OnSerialError;
}

public void Connect()
{
Console.WriteLine("Attempting to Connect on " + port.PortName);
try
{
port.Open();
Connected = true;
}
catch (IOException ioex)
{
Console.WriteLine("Unable to open port " + port.PortName);
Console.WriteLine(ioex.Message);
Connected = false;
}
catch (UnauthorizedAccessException uae)
{
Console.WriteLine("Unable to open port " + port.PortName);
Console.WriteLine(uae.Message);
Connected = false;
}
}

private void OnSerialData(Object sender, SerialDataReceivedEventArgs args)
{
SerialPort port = (SerialPort)sender;
if (args.EventType == SerialData.Chars)
{
string data = port.ReadExisting();
this.AddData(data.ToCharArray());

}
}

public void OnSerialError( Object sender, SerialErrorReceivedEventArgs e)
{
Console.WriteLine("Received error on socket");
port.Close();
SendError();
}

public override string ToString()
{
return "Arduino Serial Client: port " + port.PortName + ", baud " + port.BaudRate;
|

}

Well that seems doable for me to set up the serial communication between my application and the arduino board with some trial and error.

But then i must be sure that i can send byte-commands that make the board set an analog signal on two of its analog outputs.

In a more concrete way here's my plan:

My application has to compile for instance an arc the user has drawn to analog values that form a sinusoid signal for each servo axis. (considering that the coordinates of arc-point can be defined by a mere mathmetical function, in my case it won't be spacial coordinates but speedpercentages along X and Y)

Then my application needs to send instructions to the board to set the outputvalues and each x-milliseconds updates this value to achieve a flow that makes the 2 servo's move in the correct variating speed. Whether my application has to update these values or whether the board has functionality to achieve something similar (go to x-value in x-ms and then return to 0 in x-ms)

The actual resolution (value steps/sec) will have to be high enough though if i want a smooth end-result and not a jagged one.

Thanks for your reply

p.s: i have no choice in using stepper motor, i'm required to use servo's to keep the project closely related to my courses.

All you need to do is write data out on the SerialPort. Here,s a simple write command code. I have an 8 byte command language. The first four bytes are the command and the next 4 parameters that are command specific.

The arduino code checkds for available data on the serial port and reads it in, when it gets 8 bytes, it processes the command.

You can divide things up between the PC and the Arduino however you want. I have temperature and light sensors. The arduino knows what each sensor is and does the math to convert the raw input to degrees and returns this, but you could return raw data as well. Same goes for output, you could send raw values and figure the values on the PC or convert some other value to what is needed.

I also wrote this to use the ethernet shield. So, I can plug my sensor board in on the network and listen anywhere.

One problem I have is space. Once you add the ethernet library you use up a lot of space. There isn't much room for code. Right now, I have about 80 bytes left. So, I have to do more stuff on the PC.

Here's the C# code, arduino code below:

public void SendCommand(string command)
{
if (command.Length != 8)
{
Console.WriteLine("Invalid Command {0}, all commands must be eight bytes.\n", command);
return;
}
try
{
char[] data = command.ToCharArray();
port.Write(data, 0, 8);
}
catch (ArgumentNullException ane)
catch (InvalidOperationException ioe)
catch (TimeoutException te)
}

Here's the checkSerial and processCommand routine.

byte inputBuffer[8];
int byteCount = 0;

void
checkSerial()
{
int nbytes = Serial.available();
if (nbytes>0)
{
inputBuffer[byteCount++] = Serial.read();
if ( byteCount == 8 )
ProcessCommand();
}
}

// Command set
// ENET nnnn - n - 0/1 - turn ethernet on or off
// SERI nnnn - turn serial writing on or off
// SENS mmnn - m - sensor number, n - type, set sensor type
// SAVE 0000 - save configuration
// RATE nnnn - set sampling rate (delay in seconds between cycles)
// SMPL nnnn - n - sensor number - sample sensor
// SALL 0000 - read all sensors

void
ProcessCommand()
{
char command[5];
memcpy( command, inputBuffer, 4);
command[5] = '\0';
if (strcmp( command, "ENET") == 0 )
{
if ( command[7] == '0')
config.useEthernet = FALSE;
else
config.useEthernet = TRUE;
}
else if (strcmp( command, "SERI") == 0 )
{
if ( command[7] == '0')
config.writeSerial = FALSE;
else
config.writeSerial = TRUE;
}
else if (strcmp( command, "SENS") == 0 )
{
int nsens = command[5] - '0';
if ( nsens >= 0 && nsens < NUMBER_SENSORS )
{
int ntype = command[7] - '0';
if ( ntype >= 0 && ntype < 2 )
config.sensors[nsens] = ntype;
}
}
else if (strcmp( command, "SAVE") == 0 )
{
WriteConfig();
}
else if (strcmp( command, "RATE") == 0 )
{
char s[5];
memcpy( s, &command[4], 4 );;
s[5] = '\0';
config.reportInterval = ParseInt(s);
}
else if (strcmp( command, "NSMP") == 0 )
{
char s[5];
memcpy( s, &command[4], 4 );;
s[5] = '\0';
config.numberSamples = ParseInt(s);
}
else if (strcmp( command, "DLAY") == 0 )
{
char s[5];
memcpy( s, &command[4], 4 );;
s[5] = '\0';
config.sampleDelay = ParseInt(s);
}
else if (strcmp( command, "SMPL") == 0 )
{
int nsensor = command[7] - '0';
WriteSensor(nsensor);
}
else if (strcmp( command, "SALL") == 0 )
{
WriteSensors();
}
byteCount = 0;
}

michael

If you want to see the whole C# project, I could post it somewhere along with the whole arduino sketch. It uses VS 2008. It's too big to post here, need someplace to put it.

michael

Ok, first of all, i owe u many thanks for bringing up the possibility of serial communication with C#. Didn't know how to do it before, let alone it could be done at all. (my programming skills with C# and NET have only reached moderate level in winforms, webforms, ADO.NET, etc)

It also turns out that i don't need an analog signal anymore, i can communicate directly with the servo amplifiers with a PC's serial port over RS 232. The amps RS 232 instruction set doesn't even seem to be that complicated. Could be my euphoria clouding my reason, but at least i've got a better feeling about meeting my deadline.

The good/bad news is this way i don't need any controllerboard as an interface between PC and amps.

I would be most interested in your C# project, is it emailable? if so i'll pm u my adress. If not i don't have any virtual space for u to put in on.

Thanks again for the help, i'm off to the painfull trial and error that custom communication can be as i've been told.

regards

Bender