How to output from UNO R3 commands from a C# application ?

My very good friend @horace !
I believe this is the last piece of the puzzle with this project.
If we can code this part, project finished and good for expansion. Right?
Very good job so far !
And many thanks and also happy holidays to everyone involved here !

something as simple as

private void button1_Click(object sender, EventArgs e)
        {
            if (serialPort1.IsOpen)
                serialPort1.Write("<3H>");
        }


1 Like

My friend ! You are a genius!
I didn't see it at all ! Excelent !
It is working PERFECTLY !
Now Im happy !
Aaah, 1000 thank you !

Hi, my dear friend @horace !
Im planning to do a input reading from arduino pins. My plan is to insert into a pin, a variable square wave oscillator made with a 555, which is already build. Then open the C# program and listen to it. I believe, I would have to change a little bit the arduino code, make pin6 for ex, as an Input, and probably hard code it as I did with the signal from c# last time? or I may add a direct read to that pin and transmit whatever is sending, probably 0 and 1, Im expecting. My question to you -was- if c# program will read the signal on the COM, not only send it.


Here is some progress:


I made pin6 as an input, as I said, then I inserted this code specifically for input:

And from my C# program, nothing is updated, but when Im pressing any Button to insert data into textbox, immediately I can see some random 0 or 1, from my input !!
I think I have to Update() or Refresh() my textbox? in a timer? Hmmmm....


next, in C#, Ive added that line in the serialPort1_DataReceived event.


But.... I got an error:
"Cross-thread operation not valid: Control 'textBox1' accessed from a thread other than the thread it was created on."
I dealt with multi threads before and I know is getting complicated very quickly.
Hmmmm.....
Ill try with a timer, hopefully it will not interfere with the other thread?
And it didnt interfere with the other thread but it didnt helped either. Nothing is displayed. I believe we have to go into the hole of threads now? Huuuuuuhhh.

this where Delegates are use to pass information between threads, i.e. the serialport event handler and the textbox1 are running on different threads
the call

textBox1.Invoke(this.myDelegate, new Object[] { s });

passes the string s to the delegate

AddDataMethod(String myString)

which will update textBox1 so there is no need for you do a testBox1.refresh() - if you do need it put it in the delegate

also avoid using images of screenshots - they waster space, are difficult to read and cannot be copied
copy the text from the screen and paste it using code tags </>

1 Like

yes - if you are sending different information from the Arduino to C# start the line of text with an identifier, e.g. a digit

1 followed by error message
2 followed by pin data 
3 etc etc

the C# code checks the first character then takes appropriate action

1 Like

I understand that the data is updated in textbox1 already,
but why it is not showing in the textbox1 when is received?

private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            //textBox1.AppendText(serialPort1.ReadExisting());  // not thread safe
            string s = serialPort1.ReadExisting();
            textBox1.Invoke(this.myDelegate, new Object[] { s });
           
            textBox1.AppendText(s); //thread error
        }
        public void AddDataMethod(String myString)
        {
            textBox1.AppendText(myString);
            serialPort1.Write(myString); //doing nothing
        }

but it did nothing...

hey...I managed to make something:

        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            //textBox1.AppendText(serialPort1.ReadExisting());  // not thread safe
            string s = serialPort1.ReadExisting();
            textBox1.Invoke(this.myDelegate, new Object[] { s });
            
           serialPort1.Write( "<>" );
           //serialPort1.Read(new byte[2], 0, 2);  //this didn't worked
        }

and Im getting this result here:

You can click on the image with your mouse and it will pop out in a bigger resolution, actually the resolution it was uploaded, and it will be very easy to read the details inside it. You can always right-click on the image and choose Save-as on your PC. You can then open it with your favorite image viewer and zoom into it way more than you can in a browser. You only have to get used to it, thats all. I am very used to work with images so its easy and intuitive for me to do so. I told you my pov about this matter. Images are a very useful tool to convey an idea which would take too many explanations in written form.

Ok so Im getting that "This just in ..." every time Im receiving an input of 0 or 1.
I modified my arduino program to write "input" and "output":
This is how is looking so far:

But I can not implement a --Pause-- button in there.
Can you help? This code is running continuously. A pause/play would be very nice.
here is the modified arduino code: ReceiveOutput.ino (2.6 KB)

if you just pause the C# textBox output you will probably loose serial data
get PAUSE button to send a command to the Arduino to stop transmission
another PAUSE resumes transmission

I did it already, this way:

        // data received from serial port - display on textbox
        private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
        {
            //textBox1.AppendText(serialPort1.ReadExisting());  // not thread safe
            string s = serialPort1.ReadExisting();
            textBox1.Invoke(this.myDelegate, new Object[] { s });

            if (isActivated) serialPort1.Write("<>");
        }


        bool isActivated = false;
        private void buttonPausePlayData_Click(object sender, EventArgs e)
        {
            if (isActivated)
            {
                isActivated = false;
                buttonPausePlayData.Text = "Play";
            }
            else
            {
                isActivated = true;
                buttonPausePlayData.Text = "Pause";
            }
        }

yes, I tried that already and the program freezed !

very interesting idea !

I managed to make it work ! Many thanks.

I managed to make it work ! Many thanks.

Another Problem !
in this code I am trying to input: 1 or input: 0, but only once, in the first occurrence. When it first gets 1 and when it first gets 0.
If I let it run free without that counter variable inside it, on the c# side I get a bunch of 0000 and 1111 as long as my oscilator is slowly changing.
I want to synchronize the speed of my oscilator on the arduino input, with the Serial output text. Pretty much the Serial to print a 1 only once, in the exact time when the 1 is at the input, and not continue to print 1's after that. The same for 0's.

int input1 = 0;
int counter = 0;

void showNewData() 
{
    if (newData == true) 
    {
          //this line is only used for C# internal comunication
          if (strncmp(receivedChars,"Pause", 2) == 0) {Serial.println("-P-"); goto end;}
   
          
          if (strncmp(receivedChars,"",1) == 0)//if is an empty "" string, is a input reading request
          {
                      //read the Input pin # from Arduino
          input1 = digitalRead(6);
          //if (input1 == HIGH) Serial.println("input: 1");
          //else   Serial.println("input: 0");

          
          
            if (input1 == HIGH) 
            {
              if (counter==1) 
              { 
                Serial.println("input: 1");
                counter=0;
              }
              else 
              {
                Serial.println("input: 0"); 
                counter=1;
              }
            }
          }
          
          else //if containing characters, is an output request
          {
                      //send Output to Arduino pin #
           
                      
           if (strncmp(receivedChars,"2H", 2) == 0) {digitalWrite(2, HIGH);}
           if (strncmp(receivedChars,"2L", 2) == 0) {digitalWrite(2, LOW);}
           
           if (strncmp(receivedChars,"3H", 2) == 0) {digitalWrite(3, HIGH);}
           if (strncmp(receivedChars,"3L", 2) == 0) {digitalWrite(3, LOW);}
           
           if (strncmp(receivedChars,"4H", 2) == 0) {digitalWrite(4, HIGH);}
           if (strncmp(receivedChars,"4L", 2) == 0) {digitalWrite(4, LOW);}
  
           if (strncmp(receivedChars,"5H", 2) == 0) {digitalWrite(5, HIGH);}
           if (strncmp(receivedChars,"5L", 2) == 0) {digitalWrite(5, LOW);}

           
            Serial.println("output: " + String(receivedChars));
          }

        end:
        newData = false;
    }
}

so...when I have it in this form:

    if (newData == true) 
    {
          //this line is only used for C# internal comunication
          if (strncmp(receivedChars,"Pause", 2) == 0) {Serial.println("-P-"); goto end; }//
   
          
          if (strncmp(receivedChars,"",1) == 0)//if is an empty "" string, is a input reading request
          {
                      //read the Input pin # from Arduino
          input1 = digitalRead(6);

            if (input1 == HIGH)Serial.println("input: 1");
            else Serial.println("input: 0");
            
          }

is running continuously, indifferent of the freq of my input oscillator.
But if Im adding the "counter" variable in the last if, it is running like 010 and it stops, counting 3 or 4 times, sometimes 0 times, not showing anything. Hmmm
I dont get it.



Please click on the image to enlarge it and to see better the text in it !
That -P- means when I press the Pause/Play button and how many times it counted and then stopped.
Sometimes no input, sometimes 1 and 0 and then stop, and it spit it at once.
-I want a 1 when input is High and a 0 when input is Low, at the speed it is actually running. Very slow for the moment.


-but when is in this form:

          input1 = digitalRead(6);

            if (input1 == HIGH)Serial.println("input: 1");
            else Serial.println("input: 0");

it flows like water - continuously and without timing, some internal update timing only he knows what it is.

I believe .... reading an input from arduino will update as the input changes (exactly what I want); but here in this case with serial COM ... is doing some repetitive readings that I can not put my finger where is the cause to make it read only once per changing.

hi @horace
I made another program, a little more complicated than this one until here.
You can check the --other-- code here How to drive manually HT1621B LCD driver IC?
I managed to adapt only a fragment of the code from this other code, into our code. And it is working ! Is supposed to lit up some segments on a LCD. That's all this code is doing.
I also simplified your code a tiny bit with this occasion.

          • the problem:
            You see those Thread.Sleep(100); lines from time to time.
            I had to include them, for the code to work correctly.
            Without them, I get a lot of [Very Random] errors !
            Here and there, and is messing up the output result (on my LCD).

            image
            image

So my question to you, is like this:
If arduino can transmit the same data and in even greater quantity than my test code here, why my test code is so slow to send? Or it is another detail that we should implement for faster speeds? or is not 'the speed' but something else that is influencing this data transmission 'speed' ? Or explain to me in detail what the hell is going on, on the arduino side, then on C# side, then in serial COM side, because I start to believe these 3 have different 'speeds' ? maybe? but what is the limit for each?
-How can you solve this problem, please, and thank you.

Im using this C# code to actually drive another IC.
I also had to declare some new functions for this DataBits() to work.
This is C# code, not arduino. It is arduino code inside C#, adapted code. Ok?


        void DataBits()
        {
                     //ADR   DATA
            //sendData(0,  0b0011);  //-,c,b,
            Thread.Sleep(100);
            digitalWrite(_pin_cs, LOW);
         

            //shiftOutBits(3, 0b101);  //Start 101
            //val = (bit(x - 1) & value) != 0;
            //0
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 1);
            digitalWrite(_pin_wr, HIGH);
            //1
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 0);
            digitalWrite(_pin_wr, HIGH);
            //2
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 1);
            digitalWrite(_pin_wr, HIGH);
            Thread.Sleep(100);



            //shiftOutBits(6, address);  //where address=0
            //1
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 0);
            digitalWrite(_pin_wr, HIGH);
            //2
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 0);
            digitalWrite(_pin_wr, HIGH);
            //3
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 0);
            digitalWrite(_pin_wr, HIGH);
            //4
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 0);
            digitalWrite(_pin_wr, HIGH);
            //5
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 0);
            digitalWrite(_pin_wr, HIGH);
            //6
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 0);
            digitalWrite(_pin_wr, HIGH);
            Thread.Sleep(100);

            //shiftOutBits(4, value);   //where value=0b0011
            //1
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 0);   //null
            digitalWrite(_pin_wr, HIGH);
            //2
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 1);   //c
            digitalWrite(_pin_wr, HIGH);
            //3
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 1);   //b
            digitalWrite(_pin_wr, HIGH);
            //4
            digitalWrite(_pin_wr, LOW);
            digitalWrite(_pin_data, 1);   //a
            digitalWrite(_pin_wr, HIGH);
            Thread.Sleep(100);

            digitalWrite(_pin_cs, HIGH);
            //END of DataBits()  
        }
 

sounds like your having problems passing data between threads, e.g. serial receive to a TextBox, and are loosing some data
try executing the C# code without debug (I generally run without debug which slows things down)

1 Like

you probably refer to not display anything on the textbox because thats the more likely to be the cause, right? I thought of that too.
This is what I did in the meantime and it worked... without any other problems.

        void digitalWrite(int pin, int value)
        {
            if (serialPort1.IsOpen)
            {
                Thread.Sleep(10);  //<<<<<<<<<<<<<<<<<<<<<<<<<<< here
                if (value == 0) //"LOW"
                {
                    serialPort1.Write("<" + pin + "L>"); //2L = digitalWrite(2,LOW);
                }
                if (value == 1) //"HIGH"
                {
                    serialPort1.Write("<" + pin + "H>"); //2H = digitalWrite(2,HIGH);
                }
            }
        }

and that entire void DataBits() is using the delay from inside this digitalWrite function.
I can tweak the "speed" of the program from this delay. Sometimes it works even with 1ms, but generally is ok with 10ms as shown.
I'll put in practice your answer, in the very end of this program. Is my thought.
Thank you though !

when experimenting I have written serial data received by the event handler direct to a TextBox, e.g.

// data received from serial port
private: System::Void serialPort1_DataReceived(System::Object^  sender, System::IO::Ports::SerialDataReceivedEventArgs^  e) {
	textBox1->AppendText(serialPort1->ReadExisting());
}

generally works if run without debug - with debug it will crash with thread accessing error
I don't recommend it for end user code though

1 Like