Pages: [1]   Go Down
Author Topic: Delay when receive data from Arduino Nano in first time plug USB cable  (Read 833 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Dear all!
I have a problem. Help me please.
Please look at my code.
+ Arduino code:
Code:
#include <FreqMeasure.h>
void setup() {
  Serial.begin(9600);
  FreqMeasure.begin();
}
double frequency=0;
int timeSetZeroFreq=0;
void loop() {
  if(Serial.available()>0)
  {
    switch(Serial.read())
    {
      case 0xA1:
            Serial.write(0xB1);
            delay(10);
            break;
      case 0xA4:
        {
            readFreq();
            byte *frequencyArray = (byte *) &frequency;
            Serial.write(0xB4);
            delay(10);
            Serial.write(frequencyArray[0]);
            delay(10);
            Serial.write(frequencyArray[1]);
            delay(10);
            Serial.write(frequencyArray[2]);
            delay(10);
            Serial.write(frequencyArray[3]);   
            delay(10);
            //Serial.write(frequencyArray,4);     
        }
            break;
      case 0xA8:
        {
            int voltage = analogRead(A0);
            byte * voltageArray = (byte *) &voltage;
            Serial.write(0xB8);
            delay(10);
            Serial.write(voltageArray[0]);
            delay(10);
            Serial.write(voltageArray[1]);
            delay(10);
            //Serial.write(voltageArray,2);
        }
            break;
      default:
            Serial.write(0xC1);
            break;
    }
  }
}
float readFreq()
{
  if (FreqMeasure.available())
      {
        double f = FreqMeasure.read();
        frequency = F_CPU / f;
      }
  else
  {
    timeSetZeroFreq = timeSetZeroFreq + 1;
    if(timeSetZeroFreq>50)
    {
      frequency = 0;
      timeSetZeroFreq = 0;
    }
  }
  return frequency;
}
+ Code in my project (written in C++ use SerialPort Class of Microsoft)
Code:
int main()
{
//initial serial port
SerialPort ^portSerial = gcnew SerialPort();
portSerial->BaudRate = L"COM3";
portSerial->Parity = Parity::None;
portSerial->StopBits = StopBits::Two;
portSerial->DataBits = 8;
portSerial->Handshake = Handshake::None;
portSerial->ReadTimeout = 500;
portSerial->WriteTimeout = 500;
portSerial->Open();
//send request
array<unsigned char>^request={0xA1};
while(1)
{
try
{
portSerial->Write(request,0,1);
//Read respond
       portSerial->ReadByte();
}
catch (System::Exception ^ex)
{
Console::WriteLine("Send Request Error: {0}",ex->Message);
}
}
}
-->My problem: In first time plug USB cable, function portSerial->ReadByte() error TimeOutException. After sending request in the 3rd (use while(1)), data received is true. More detail:
portSerial->Write(request,0,1) in the first time -> portSerial->ReadByte() error timeout
portSerial->Write(request,0,1) in the secondtime -> portSerial->ReadByte() error timeout
portSerial->Write(request,0,1) in the third time -> portSerial->ReadByte() = B1 ->right

But my problem occurs the first time you plug the USB cable. If do not disconnect the USB cable, then everything works normally.
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

When the serial port is opened the Arduino will usually reset. When the Arduino starts up, the bootloader runs and waits for a moment in case you are about to upload a new sketch. It is only after the bootloader has timed out that your sketch gets to run. Because the sketch is not running when your 'C' program sends the command, it does not send a response hence the timeout. I recommend you put a delay of a second or two after opening the port before you start sending commands.

You code does not seem to make any provision for the Arduino being disconnected while the program is running - if you want it to run long term, it would need to handle serial port failures and re-open the port as necessary.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you!
At first I think so. But when I use Serial Monitor to send command (on Arduino soft) at In first time plug USB cable --> Board reply immediately
Then I open the my project and send command --> it still fails time out as I said.
As you say, I have set portSerial->ReadTimeOut = 5000 (5s) but it still fails.
But my problem occurs the first time you plug the USB cable.
 
Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you!
At first I think so. But when I use Serial Monitor to send command (on Arduino soft) at In first time plug USB cable --> Board reply immediately
Then I open the my project and send command --> it still fails time out as I said.
As you say, I have set portSerial->ReadTimeOut = 5000 (5s) but it still fails.
But my problem occurs the first time you plug the USB cable.
 

When you open the Arduino serial monitor the board will reset. By the time you have typed the command sequence in to the serial monitor, the reset will be complete and the Arduino will be ready to respond.

Your application does the same thing but without any delay between opening the serial port (and making the Arduino reset as a result) and sending the first command. It doesn't matter how long you set the timeout; that first command was never received and the Arduino is never going to respond to it. Watch the Arduino and see how long it takes to complete a reset and begin running your sketch. Put in a delay a bit longer than that in your application, between opening the serial port and sending the first command.
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank! you're right. I'm put Sleep(2000) between opening the serial port and sending the first command ->it works normally
In case, I scan the COM port on the computer to find out portName of Arduino
Assuming my PC has the following ports
+ COM1
+ COM2
+ COM3
+ COM4 (Arduino)
I want to find the COM port of the Arduino. I will send the command to all COM ports, then receive respond
Check if respond properly to the value set under Arduino ->port Aruino found.
Code:
SerialPort ^portSerial = gcnew SerialPort();
portSerial->BaudRate = 9600;
portSerial->Parity = Parity::None;
portSerial->StopBits = StopBits::Two;
portSerial->DataBits = 8;
portSerial->Handshake = Handshake::None;
portSerial->ReadTimeout = 500;
portSerial->WriteTimeout = 500;
array<unsigned char>^request={0xA1};//respond will 0xB1 from arduino
listSerialPorts = portSerial->GetPortNames();
for each(String^ port in listSerialPorts)
{
portSerial->portSerial->PortName = port;
portSerial->Open();
Sleep(2000);
portSerial->Write(request,0,1);
rspFromBoard = portSerial->ReadByte();
if(rspFromBoard == 0xB1)
{
Console::WriteLine("Port Arduino Found");
}
}
->>>So happens in case of Sleep (2000) was repeated. It will create big delay in my app
In this case, how do I do?
« Last Edit: January 22, 2013, 08:17:55 pm by nhatnam06dt1 » Logged

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The delay only happens once, at startup. Is that a problem?

If it is, you could change your code so that it opens all the serial ports, wait 2 seconds and then sends a command to each one in turn - that way you would only have to wait for one delay.
« Last Edit: January 23, 2013, 09:32:32 am by PeterH » Logged

I only provide help via the forum - please do not contact me for private consultancy.

Offline Offline
Newbie
*
Karma: 0
Posts: 13
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, thank you very much.
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 644
Posts: 50500
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you want to talk to any Arduino (such as the Leonardo), you'll need to add
Code:
portSerial->DtrEnable = true;
to the C++ code.
Logged

Pages: [1]   Go Up
Jump to: