Go Down

Topic: Controlling Arduino with C# (Read 9 times) previous topic - next topic

Reynal74

Hello everyone,

can any body tell me how to link more than one pin from Arduino to C#?
I'm trying to control Arduino directly from a small code from C# but i can't get it to work.  ;D
If you think you have it, you don't. If you think you don't have it, you still don't.

billroy

One technique you might consider is to put Bitlash on the Arduino and send commands through the serial port to control the digital IO.

Bitlash is an interpreter that runs on Arduino, available at http://bitlash.net

-br
http://bitlash.net
http://entropymouse.com

PaulS

I have a C# application that sends serial data to the Arduino, and reads any responses.

Altering that application to send specific commands to the Arduino when specific buttons are pressed is easy.

Making the Arduino do something in response to a serial command is easy. That can include sending serial data back to the C# application.

Quote
I'm trying to control Arduino directly from a small code from C# but i can't get it to work.

Post your C# code and Arduino code. We can then help you figure out what the problem is.

Reynal74

This is my Arduino code:
Code: [Select]

int ledPinA = A1;//Setting Pin A1 for the LED
int ledPin = 2;//Setting Pin 2 for the LED

void setup()
{
 pinMode(ledPin, OUTPUT);//ledPin as an output
 Serial.begin(9600);
}

void loop()
{
 
if(Serial.available())//checking for serial
 {
   int LedStatus = Serial.read();//reading from serial ports
   if (LedStatus == '1')
   {    
     digitalWrite(ledPin,HIGH);//turn on LED
   }
   else if (LedStatus == '0')
   {
    digitalWrite(ledPin,LOW);
    int LedIntensity_Scroll = Serial.read();//reading from serial port
    analogWrite(ledPinA, LedIntensity_Scroll);//What to use this to change the intensity of the led light.
   }
   Serial.flush();
 }
}




This is the C# code:
Code: [Select]

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;
using System.IO;

namespace ArduinoLedControl
{
   public partial class ArduinoLEDControl : Form
   {
       bool ledState = false;//setting initial led status

       public ArduinoLEDControl()
       {
           InitializeComponent();
       }

       private void LedOn_Click(object sender, EventArgs e)
       {
           if (serialPort1.IsOpen == true)
           {
               serialPort1.Write("1");//tells arduino that the port is ON
               LedStatusBox.Text = "THE LED IS ON";//tells the user that the led is ON
               LedOnButton.Enabled = false;//disable the ON button
               LedOffButton.Enabled = true;//enable the OFF button
               ledState = true;//turn on LED
               LedIntensity.Enabled = false;//disabling he led intensity track bar
           }
           else
           {
               MessageBox.Show("There is no Serial Ports open.");//message box telling user that there is not ports open
           }
       }

       private void LedOff_Click(object sender, EventArgs e)
       {
           if (serialPort1.IsOpen == true)
           {
               serialPort1.Write("0");//tells arduino that the port is OFF
               LedStatusBox.Text = "THE LED IS OFF";//tells the user that the led is OFF
               LedOnButton.Enabled = true;//enable the ON button
               LedOffButton.Enabled = false;//disable the OFF button
               ledState = false;//turn off LED
               LedIntensity.Enabled = true;//enabling he led intensity track bar
           }
           else
           {
               MessageBox.Show("There is no Serial Ports open.");//message box telling user that there is not ports open
           }
       }

       private void ArduinoLEDControl_Load(object sender, EventArgs e)
       {

       }

       private void LedStatusBox_TextChanged(object sender, EventArgs e)
       {

       }

       private void StartPortButton_Click(object sender, EventArgs e)
       {
           if (SelectPortBox.SelectedItem == null)
           {
               MessageBox.Show("No Serial Ports was selected, Try again.");//message box telling user that there is not ports open
           }

           else
           {
               serialPort1.PortName = SelectPortBox.SelectedItem.ToString();//setting serialPort1 to a selected port by user
               serialPort1.BaudRate = 9600;//this value most be the same as in serial.begin(9600) of arduino's code

               if (serialPort1.IsOpen == true)
               {
                   serialPort1.Write("0");
                   serialPort1.Close();//closing port if previously open
                   LedStatusBox.Clear();
               }
               else
               {
                   serialPort1.Open();//opening port when the program starts
               }
           }
       }

       private void SelectPortBox_SelectedIndexChanged(object sender, EventArgs e)
       {

       }

       private void ClosePortButton_Click(object sender, EventArgs e)
       {
           if (serialPort1.IsOpen == true)//checking if any port is open in order to close it
           {
               serialPort1.Write("0");
               serialPort1.Close(); //close serialPort1
               MessageBox.Show("Serial Port: " + serialPort1.PortName + " have been closed.");//message box telling user that the port is closed
               LedStatusBox.Clear();
           }
           else
           {
               MessageBox.Show("There is no Serial Ports open.");//message box telling user that there is not ports open
               LedStatusBox.Clear();
           }
       }

       private void LedIntensity_Scroll(object sender, EventArgs e)
       {
           serialPort1.Write(LedIntensity.Value.ToString());//This is where the problem happens
           //Console.WriteLine(LedIntensity.Value.ToString());
       }
   }
}



I can not operate arduino with the line :   serialPort1.Write(LedIntensity.Value.ToString());      and receive the command/data at arduino with  int LedIntensity_Scroll = Serial.read();



I will really appreciate your help, also, how many ports can i use with the Duemilanove ATmega328P? :-/

If you think you have it, you don't. If you think you don't have it, you still don't.

PaulS

Lets take the questions in reverse order.

Quote
how many ports can i use with the Duemilanove ATmega328P?

All of them. All one of them, to be specific. The Duemilanove has just one hardware serial port, connected to the USB port.

Quote
I can not operate arduino with the line :   serialPort1.Write(LedIntensity.Value.ToString());      and receive the command/data at arduino with  int LedIntensity_Scroll = Serial.read();

You are getting the numeric value from a field and converting it to a string, and sending that string to the serial port.

You are then trying to read the number that was sent.  Where is the magic conversion of the string back to a number supposed to occur?

You are trying to read the 2nd byte of the string as a number only if the first byte is not a 1 (which it never is, since 1 is not a printable ASCII value, and you are only sending printable ASCII values).

Code: [Select]
   Serial.flush();
Throw away the rest of the string. Good idea. NOT.

First, you need to define a protocol. You want the sending application to be able to turn an LED on or off, using digitalWrite on the Arduino OR control the brightness of an LED using analogWrite. Currently, you are not telling the Arduino WHICH action it is to perform, just the data that it needs to perform the action, if it knew which action to perform.

You should be sending something like <D0>, <D1>, or <A32>, where < is a start of packet marker, D and A are commands, 0, 1, and 32 are values for the commands, and > is an end of packet marker.

All data is to be sent as strings.

Then, the Arduino needs to read the strings, store the data in an array, parse the array when the end of the packet arrives, and use the command and value to perform an action.

Search the forum for "started && ended" for an example of how to receive strings with start and end markers. There is a section in the code that I posted where you then perform the parsing and action.

Parsing is simple in your case. The command is a single letter. After determining the command, replace that letter with a 0, and call atoi with the rest of the string, to get an integer value. If the command is D, test the integer value for 0 or 1. If the command is A, analogWrite can be passed the value.

Reynal74

Thank you PaulS, your post was of great guidance to me specially because I'm not familiar with Arduino or coding over all. Is this the post you are refering to http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1282127488/24 ??? Can you provide me any other examples related to what I want to do? ;D
If you think you have it, you don't. If you think you don't have it, you still don't.

PaulS

Reply #20 in that thread has one example of the code I was referring to.

You can send serial data to the Arduino, and have it do nothing but echo the data back.

This allows you to develop the sending application, first. Make the LED On button send <D1>. Then, make the LED Off button send <D0>. Then, make the slider callback send <Axxx> where the string returned by LedIntensity.Value.ToString();.

When all three callbacks send the right data, then work on the collecting, parsing, and using code on the Arduino, one step at a time. Collect the data, and echo it back to the C# application. Then, parse it, and echo the parsed information. Finally, use the parsed data to control stuff.

Reynal74

Thanks a lot Paul, I'm going on my epic journey to find the secrets of communicating with Arduino.  ;D
If you think you have it, you don't. If you think you don't have it, you still don't.

Reynal74

Hello again,

I stored the data received from C# into a buffer. I managed to get the on and off ( <D0> and <D1> ) work ( Thank a lot PaulS ), but how can I get the analog ( <Axxx> ). I can identify the A, but how can i get the number xxx to be in int???  
If you think you have it, you don't. If you think you don't have it, you still don't.

PaulS

Quote
I can identify the A, but how can i get the number xxx to be in int???

After determining that the first character in the array is indeed an 'A', replace the 'A' with a '0'. Then, call atoi() with the string as the argument.

Code: [Select]
char inData[] = "A382";
if(inData[0] == 'A')
{
  inData[0] = '0'; // inData now holds '0', '3', '8', '2', NULL

  int val = atoi(inData); // val now holds 382
}

robtillaart

#10
Nov 02, 2010, 01:36 pm Last Edit: Nov 02, 2010, 01:37 pm by robtillaart Reason: 1
0r start conversion at index 1, just after the A. This keeps the original string intact, optionally for later use. Note: added a var cmd to hold the type of command.

Code: [Select]
char cmd = inData[0];
int val = atoi( &inData[1] );  
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Reynal74

I finally got the code to work properly. This is the final version of the code. Actually, I could say my real first code  8-). PaulS should make a book of advises/codes and sell it...
Code: [Select]

/*
Code by: Reynal74
special thanks to PaulS for all his help
*/
//Variable Declaration
int ledPin = 9;//Setting Pin 9PWM for the LED
boolean started = false;
boolean ended = false;
char buffer[300];//creating buffer large enough
int serialIn = 0;//counter for the incoming data
int atoiHolder = 0;//holds the value of atoi

void setup(){
 pinMode(ledPin, OUTPUT);//ledPin as an output
 Serial.begin(9600);
}

void loop(){
 while(Serial.available() > 0){
   char incomingData = Serial.read(); //reading from the serial ( data from C# )

   if(incomingData == '<'){//check for started packet
     started = true;//the string started
     ended = false;
   }
   else if(incomingData == '>'){//check for ended packet
     ended = true;//indicated end of the reading
     break; //break out of the loop
   }
   else{
     buffer[serialIn] = incomingData;//begining to store data in the buffer
     serialIn++;
     buffer[serialIn] = '\0';// NULL terminate the array
   }
 }//END OF WHILE LOOP
 //--------------CHECKING & TESTING -------------------
 if(started && ended){
   //GETTING THE ON AND OFF BUTTON FROM C# WORKING
   if(buffer[0] == 'D' && buffer[1] == '0'){//turn off the light
     digitalWrite(ledPin,LOW);
   }
   else if(buffer[0] == 'D' && buffer[1] == '1'){//turn on the light
     digitalWrite(ledPin,HIGH);
   }
   //GETTING THE TRACK BAR FROM C# WORKING (TO VARY THE LED LIGHT INTENSITY)
   else if(buffer[0] == 'A'){
     buffer[0] = '0';//replaces A by '0' and now buffer holds '0','X','X','X',NULL
     atoiHolder = atoi(buffer);//atoiHolder (LED Intensity) now holds XXX
     
     /*ALTERNATIVE METHOD SUGGESTED BY: robtillaart
     start conversion at index 1, just after the A. This keeps the original string intact,
     optionally for later use. Note: added a var cmd to hold the type of command.
         char cmd = inData[0];
         int val = atoi( &inData[1] );
     */
     analogWrite(ledPin,atoiHolder);
   }
   else {
     //If no data matches the descriptions above, give a blinking light to indicate an error
     digitalWrite(ledPin,HIGH);
     delay(100);
     digitalWrite(ledPin,LOW);
     delay(100);
   }
   serialIn = 0;//resetting serialIn
   buffer[serialIn] = '\0';//Null the buffer array
   started = false; //reset to false
   ended = false; //reset to false
 }//END OF CHECKING & TESTING
}


Can Arduino tell C# or any other program what to do ( like control the other program )? If so, can those commands be made into graphic? what is the maximum amount of FLOPS that Arduino can put out? Can Arduino board program any other chips?
If you think you have it, you don't. If you think you don't have it, you still don't.

PaulS

Can Arduino tell C# or any other program what to d
The Arduino can send data to the serial port, which the C# application can read. It is up to you to define commands for the Arduino to send, and to write the code to make the C# application respond in appropriate ways.

Quote
If so, can those commands be made into graphic?

I have a pretty neat 3D graphics application written in C#. Has nothing to do with Arduino, and it's company proprietary so I can't share it. But, C# can do graphics. If you send sensor data to the application, C# could create a plot of it.

Quote
what is the maximum amount of FLOPS that Arduino can put out?

The Arduino executes 16,000,000 instructions per second.


mecharius

Not sure if it is relevant, however I'm building an open C# application to send instructions to and receive "telemetry" from the Arduino.  (I'll have to post the link in a second reply because I'm new here!)

There is a brief tutorial there on parsing messages on the Arduino and the C# code is available on github.

mecharius


Go Up