Go Down

Topic: Problems in TX/RX data between C# and Arduino (Read 5091 times) previous topic - next topic

PaulS

Quote
Now i only need to work on the buffer allocation

You are telling the SerialPort class to allocate a receive buffer. I don't see that you have anything more to do.

Quote
and properly writing to the file.

Is there a problem with this? Have you confirmed that you are getting all the data to the C# application?

Quote
Is it possible to program arduino's chip and take it out of the board and use it dirrectly from a bread board?

With a few extra pieces, yes. "standalone" is the search term you want.

Quote
Will the ADC still work?

But, of course.

Reynal74

By echoing the data I confirmed that Arduino is giving me all the values that I request, however, I have not manage to get all the data in the files created. Is there any better approach to writing the data into a file? I'm using the following C#
Code: [Select]
       private void StartArduinoButton_Click(object sender, EventArgs e)
       {
           if (serialPort1.IsOpen == true)//checking if any port is open in order to close it
           {
               //creating output file
               string ArduinoLogName = @"" + desktopPath + "\\" + "ArduinoData_" + DateTime.Now.ToString("MMM-d-yyyy") + ".txt";//creates the log file
               FileStream ArduinoLogFile = new FileStream(ArduinoLogName, FileMode.Create);//creates a new file or overwrites a previous file created
               StreamWriter writer = new StreamWriter(ArduinoLogFile);//variable to write

               serialPort1.Write("<TX>");//Sending arduino the transmitting command
               int NumberOfReadings = int.Parse(SelNumberOfReading.SelectedItem.ToString());//converting the selected number of readings from string to ints

               for (int count = 0; count <= NumberOfReadings; count++)
               {
                   try
                   {
                       RxData = serialPort1.ReadLine();//reading data from the port
                       writer.WriteLine(RxData);//writing the transmitted data
                       Console.WriteLine(RxData);
                   }
                   catch (Exception RzData)
                   {
                       RxData = RzData.ToString();
                       writer.WriteLine(RxData);//writing the transmitted data
                       Console.WriteLine(RxData);
                   }
               }

               MessageBox.Show("The Transmission from Arduino has ended.");
               ArduinoLogFile.Close();//Closing the data file
           }
           else
           {
               MessageBox.Show("There is no Serial Ports open.");//message box telling user that there is not ports open
               StartArduinoButton.Enabled = false;//disabling the start arduino button
           }

           serialPort1.Close();//closing the serial port
           this.Refresh();
           this.Close();//closing the application
       }//end of StartArduinoButton


Also, even though I close the port and the C# application, I still face the problem of needing to open the Serial Monitor for the Arduino to be reset. Is it manageable to have a function or something do that? would I experience the same problem if i use the ATmega328 as standalone?
If you think you have it, you don't. If you think you don't have it, you still don't.

PaulS

#17
Nov 28, 2010, 01:08 pm Last Edit: Nov 28, 2010, 01:11 pm by PaulS Reason: 1
Go back and look at your Arduino code. How many lines is it sending if you request one reading? 2, by my count.

How many lines does it send if you request 5 readings. 10, by my count.

How many lines are you reading in the C# application using serialPort1.read(), after requesting 1 reading? 2, by my count (count == 0 and count == 1).

How many lines are you reading in the C# application using serialPort1.read(), after requesting 5 readings? 6, by my count (count == 0, count == 1, count ==2, count ==3, count == 4, and count == 5).

Also, notice that you open a file, and get a stream writer object from the file. After writing some stuff (buffered), you close the file, without closing the streams into that file. The streams might automatically be flushed and closed, but I never rely on that happening. Flush the streams and close them, before closing the file.

Reynal74

I did not manage to understand the comment below. I took care of the stream writer ( flush it and close it ), yet I do not manage to write all the data into the file. When I echo it, I see every point requested by the C# command.

Quote
Go back and look at your Arduino code. How many lines is it sending if you request one reading? 2, by my count.

How many lines does it send if you request 5 readings. 10, by my count.

How many lines are you reading in the C# application using serialPort1.read(), after requesting 1 reading? 2, by my count (count == 0 and count == 1).

How many lines are you reading in the C# application using serialPort1.read(), after requesting 5 readings? 6, by my count (count == 0, count == 1, count ==2, count ==3, count == 4, and count == 5).


This is how the reading part of C# is looking like, can some comments be done?
Code: [Select]

       //settings for the button that starts arduino serial transmission
       private void StartArduinoButton_Click(object sender, EventArgs e)
       {
           if (serialPort1.IsOpen == true)//checking if any port is open in order to close it
           {
               //creating output file
               string ArduinoLogName = @"" + desktopPath + "\\" + "ArduinoData_" + DateTime.Now.ToString("MMM-d-yyyy") + ".txt";//creates the log file
               FileStream ArduinoLogFile = new FileStream(ArduinoLogName, FileMode.Create);//creates a new file or overwrites a previous file created
               StreamWriter writer = new StreamWriter(ArduinoLogFile);//variable to write

               serialPort1.Write("<TX>");//Sending arduino the transmitting command
               int NumberOfReadings;

               if (SelNumberOfReading.SelectedItem == null)
               {
                   NumberOfReadings = 50;//default number of readings
               }
               else
               {
                   NumberOfReadings = int.Parse(SelNumberOfReading.SelectedItem.ToString());//converting the selected number of readings from string to ints
               }

               for (int count = 0; count <= NumberOfReadings; count++)
               {
                   try
                   {
                       RxData = serialPort1.ReadLine();//reading data from the port
                       writer.WriteLine(RxData);//writing the transmitted data
                       Console.WriteLine(RxData);
                   }
                   catch (Exception RzData)
                   {
                      RxData = RzData.ToString();
                      writer.WriteLine(RxData);//writing the transmitted data
                      Console.WriteLine(RxData);
                   }
               }

               MessageBox.Show("The Transmission from Arduino has ended.");
               writer.Flush();//flush the streams
               writer.Close();//close the streams
               ArduinoLogFile.Close();//Closing the data file
           }
           else
           {
               MessageBox.Show("There is no Serial Ports open.");//message box telling user that there is not ports open
               StartArduinoButton.Enabled = false;//disabling the start arduino button
           }

           serialPort1.Close();//closing the serial port
           this.Refresh();
           this.Close();//closing the application
       }//end of StartArduinoButton


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

PaulS

Your Arduino code contains:
Code: [Select]
     Serial.print("======================");
     Serial.print(atoiHolder);Serial.print("    ");Serial.print(N);
     Serial.println("======================");

     if(N == atoiHolder)
     {
               Serial.print("IM AT THE END OF COM");
           Serial.end(); // Presumably, this has been removed.
     }

<snip>

     Serial.print(N);Serial.print(';');
     Serial.print(Input0_Data,8);Serial.print(';');
     Serial.print(Input1_Data,8);Serial.print(';');
     Serial.print(Input2_Data,8);Serial.print(';');
     Serial.print(Input3_Data,8);Serial.println(';');

If one reading is requested, there will be 3 lines of output (not two as I suggested earlier).

If ten readings are requested, there will be 21 lines of output (not 20 as I suggested earlier.

Your C# code has this:
Code: [Select]
   for (int count = 0; count <= NumberOfReadings; count++)
If one reading is requested, NumberOfReadings will be 1, and the loop will execute when count = 0 and when count = 1, reading 2 of the three lines.

If ten readings are requested, NumberOfReadings will be 10, and the loop will execite when count = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, and 10, reading 11 of the 21 lines sent.

Reynal74

I just changed that part of my Arduino code to avoid getting confused, now I have the code below. However, the problem remains. When I echo this with C#, all the points requested appear on the console.


Code: [Select]
     //-------------- Executing C# Commands --------------
     if(started && ended)
     {  
           if(buffer[0] == 'N')
           {
                 buffer[0] = '0';//replaces N by '0' and now buffer holds '0','X','X','X','X'
                 atoiHolder = atoi(buffer);//atoiHolder now holds XXXX (number of reads decided by user)
           }
           if(buffer[0] == 'T' && buffer[1] == 'X')//indication from C# to TX data
           {
                 while(N <= atoiHolder)
                 {
                       //ADC OPERATION
                       Input0_Data  = analogRead(Input0);//Reading inputs from analog inputs
                       Input1_Data  = analogRead(Input1);
                       Input2_Data  = analogRead(Input2);
                       Input3_Data  = analogRead(Input3);

                       Input0_Data = Input0_Data * ToAnalogCoefficient; //converting ASCII-encoded decimal back to Analog
                       Input1_Data = Input1_Data * ToAnalogCoefficient;
                       Input2_Data = Input2_Data * ToAnalogCoefficient;
                       Input3_Data = Input3_Data * ToAnalogCoefficient;

                       Serial.print(N);Serial.print(';');//Packaging the data to be outputted to the computer
                       Serial.print(Input0_Data,3);Serial.print(';');//The selected format  N;Input0_Data;Input1_Data;Input2_Data;Input3_Data;
                       Serial.print(Input1_Data,3);Serial.print(';');
                       Serial.print(Input2_Data,3);Serial.print(';');
                       Serial.print(Input3_Data,3);Serial.println(';');
                       N = N + 1; //Incrementing the N-Domain
                       delay(10);//delay of 10ms to let ADC recover ( SEARCH IF NECESSARY )
                 }
                       
           }//end of transmitting section

           serialIn = 0;//resetting serialIn
           buffer[serialIn] = '\0';//Null the buffer array
           started = false; //reset to false
           ended = false; //reset to false

     }//end of Executing C# Commands

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

Reynal74

I was messing around with the board and I noticed that if I press the reset button everything works fine, all the data is copied into the file created by the C# application. Is there a way of making that automatic?  ;D
If you think you have it, you don't. If you think you don't have it, you still don't.

PaulS

Pressing the reset button on the Arduino has no impact on the code running on your PC. If you are seeing all of the data appear in the console window, and it all appears correct, the problem is with how you are writing that data to the file on the PC.

Resetting the Arduino causes the serial port connection to close. What is YOUR application doing when that happens?

Reynal74

When I press the reset button my application is not doing nothing ( not even open ). does closing the port by resetting the Arduino (pressing the button) means Serial.end() ?
If you think you have it, you don't. If you think you don't have it, you still don't.

Reynal74

Quote
Resetting the Arduino causes the serial port connection to close.

I tried ending the port connection from the Arduino code and nothing good came out of it. Is it possible to do it within the code? I haven't found a command or a way to do the reset from the code. If I place the code into the chip (permanently??), would it get damage if I have some external way to do this reset (the reset will be made many times)? Also, does Arduino's chip have some minimum time requirement for the ADC to recover?

I'm doing the following:
Code: [Select]
void loop()
{
Serial.begin();
     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

     //-------------- Executing C# Commands --------------
     if(started && ended)
     {  
           if(buffer[0] == 'N')
           {
                 buffer[0] = '0';//replaces N by '0' and now buffer holds '0','X','X','X','X'
                 atoiHolder = atoi(buffer);//atoiHolder now holds XXXX (number of reads decided by user)
           }
           if(buffer[0] == 'T' && buffer[1] == 'X')//indication from C# to TX data
           {
                 while(N <= atoiHolder)
                 {
                       //ADC OPERATION
                       Input0_Data  = analogRead(Input0);//Reading inputs from analog inputs
                       Input1_Data  = analogRead(Input1);
                       Input2_Data  = analogRead(Input2);
                       Input3_Data  = analogRead(Input3);

                       Input0_Data = Input0_Data * ToAnalogCoefficient; //converting ASCII-encoded decimal back to Analog
                       Input1_Data = Input1_Data * ToAnalogCoefficient;
                       Input2_Data = Input2_Data * ToAnalogCoefficient;
                       Input3_Data = Input3_Data * ToAnalogCoefficient;

                       Serial.print(N);Serial.print(';');//Packaging the data to be outputted to the computer
                       Serial.print(Input0_Data,3);Serial.print(';');//The selected format  N;Input0_Data;Input1_Data;Input2_Data;Input3_Data;
                       Serial.print(Input1_Data,3);Serial.print(';');
                       Serial.print(Input2_Data,3);Serial.print(';');
                       Serial.print(Input3_Data,3);Serial.println(';');
                       N = N + 1; //Incrementing the N-Domain
                       delay(10);//delay of 10ms to let ADC recover ( SEARCH IF NECESSARY )
                 }
             
           }//end of transmitting section
Serial.end();
           serialIn = 0;//resetting serialIn
           buffer[serialIn] = '\0';//Null the buffer array
           started = false; //reset to false
           ended = false; //reset to false

     }//end of Executing C# Commands
}//end of loop
If you think you have it, you don't. If you think you don't have it, you still don't.

PaulS

Your problem is on the PC side and how you are handling the data there, not on the Arduino. Closing the serial port on the Arduino side will effectively take it off-line, and your PC application will not be able to talk to it again (until it is reset).

Quote
I haven't found a command or a way to do the reset from the code.

There isn't one. There are some methods to cause the Arduino to appear to reset, but they are not supported, and the side effects depend on the method. I'm not going to comment further on how to do it, because it is NOT what you need to do.

Quote
Also, does Arduino's chip have some minimum time requirement for the ADC to recover?

Yes. You can check the Atmel data sheet for particulars. Somewhere between 10 and 100 milliseconds generally works, depending on what is being measured.

Reynal74

Reset problem solved. Now i just need to make the code a bit more fault tolerant. thanks a lot for your help PaulS  :)

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

PaulS

Quote
Reset problem solved.

That's great. What was the problem?

Reynal74

I just needed to set N = 0 before the while loop.
If you think you have it, you don't. If you think you don't have it, you still don't.

PaulS

Quote
I just needed to set N = 0 before the while loop.

Ah, yes. The little things that trip you up.

Go Up