This C# class combined with the Arduino sketch allows you to plug an Arduino into a PC's USB port and then have its com port detected by the C# application. Once the com port is known the C# application can then send/receive messages from the Arduino.
I used an Arduino Uno, C# 4.0, Windows 7.
This code does not work on Leonardo's because, apparently, a Leonardo requires setting the DtrEnable property of the SerialPort object to true. I don't have a Leonardo so can't test this but I believe it to be true based on the forum posts.
The concept is quite simple. The C# application polls all the com ports and sends a query using a simple protocol (explained below). Once the Arduino receives the request it replies. The C# application that notes the com port that caused the Arduino to reply and saves the name of the com port. The C# application can then use this com port in subsequent communications.
Comms Protocol
This uses a 5 byte message
Byte 0 is the start of command marker. This is always decimal 16 converted to byte (Convert.ToByte(16);)
Byte 1 is the type of command:
127 = Send data to pins
128 = Identify
Byte 2 is the pin to receive data
Byte 3 is the valus for the pin
Byte 4 was used as an "end of Message" marker but is redundant
So send 100 to pin 3 is: 16,127,3,100,4
And ask the Arduino to return the identify message is: 16,128,0,0,4
You can easily add to the protocol. In one projects I use command 129 to request data back from the Arduino.
If you have questions send me a personal message via the forum Richard210363
Sketch
/*
* Serial Port Monitor * * */
//Setup Output
int ledPin_3 = 3;
//Setup message bytes
byte inputByte_0;
byte inputByte_1;
byte inputByte_2;
byte inputByte_3;
byte inputByte_4;
//Setup
void setup() {
pinMode(ledPin_3, OUTPUT); Serial.begin(9600); digitalWrite(ledPin_3, HIGH);// delay(250);// digitalWrite(ledPin_3, LOW);// delay(250);//
}
//Main Loop
void loop() {
//Read Buffer if (Serial.available() == 5) { //Read buffer inputByte_0 = Serial.read(); delay(100); inputByte_1 = Serial.read(); delay(100); inputByte_2 = Serial.read(); delay(100); inputByte_3 = Serial.read(); delay(100); inputByte_4 = Serial.read(); } //Check for start of Message if(inputByte_0 == 16) { //Detect Command type switch (inputByte_1) { case 127: //Set PIN and value switch (inputByte_2) { case 4: if(inputByte_3 == 255) { digitalWrite(ledPin_3, HIGH); break; } else { digitalWrite(ledPin_3, LOW); break; } break; } break; case 128: //Say hello Serial.print("HELLO FROM ARDUINO"); break; } //Clear Message bytes inputByte_0 = 0; inputByte_1 = 0; inputByte_2 = 0; inputByte_3 = 0; inputByte_4 = 0; //Let the PC know we are ready for more data Serial.print("-READY TO RECEIVE"); }
}
C#
using System;
using System.Threading;
using System.IO.Ports;
using System.IO;
public class ArduinoControllerMain {
SerialPort currentPort;
bool portFound;
private void SetComPort() { try { string[] ports = SerialPort.GetPortNames(); foreach (string port in ports) { currentPort = new SerialPort(port, 9600); if (DetectArduino()) { portFound = true; break; } else { portFound = false; } } } catch (Exception e) { } }
private bool DetectArduino() { try { //The below setting are for the Hello handshake byte[] buffer = new byte[5]; buffer[0] = Convert.ToByte(16); buffer[1] = Convert.ToByte(128); buffer[2] = Convert.ToByte(0); buffer[3] = Convert.ToByte(0); buffer[4] = Convert.ToByte(4);
int intReturnASCII = 0; char charReturnValue = (Char)intReturnASCII;
currentPort.Open(); currentPort.Write(buffer, 0, 5); Thread.Sleep(1000);
int count = currentPort.BytesToRead; string returnMessage = ""; while (count > 0) { intReturnASCII = currentPort.ReadByte(); returnMessage = returnMessage + Convert.ToChar(intReturnASCII); count--; } ComPort.name = returnMessage;
currentPort.Close();
if (returnMessage.Contains("HELLO FROM ARDUINO")) { return true; } else { return false; } } catch (Exception e) { return false; } }
}