Serial communication with pc

Hello!

I have a problem with serial communication. I briefly describe my setup:

Arduino is running a server-like program which waits for serial input signals which will trigger various event.
On the other side, on the pc, I have a client-like program, written in C++ which sends out commands via serial to arduino.

Everything works fine only after I open the arduino IDE serial monitor and send the first command by hand.
If I try to start directly with my C++ program it would not work

My doubt is that there is something wrong in the initialization of serial communication; so I paste my PC client-like initialization code:

serialHandle = CreateFile("\\\\.\\COM11", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    DCB serialParams = { 0 };  // Do some basic settings
    serialParams.DCBlength = sizeof(serialParams);

    GetCommState(serialHandle, &serialParams);
    serialParams.BaudRate = 9600;
    serialParams.ByteSize = 8;
    serialParams.StopBits = ONESTOPBIT;
    serialParams.Parity = NOPARITY;
    GetCommState(serialHandle, &serialParams);

    COMMTIMEOUTS timeout = { 0 };   // Set timeouts
    timeout.ReadIntervalTimeout = 50;
    timeout.ReadTotalTimeoutConstant = 50;
    timeout.ReadTotalTimeoutMultiplier = 50;
    timeout.WriteTotalTimeoutConstant = 50;
    timeout.WriteTotalTimeoutMultiplier = 10;
    SetCommTimeouts(serialHandle, &timeout);

and also my put char routine:

void SerialPutc(HANDLE *hCom, char txchar) {
  BOOL bWriteRC;
  static DWORD iBytesWritten;
  bWriteRC = WriteFile(*hCom, &txchar, 1, &iBytesWritten,NULL);
  return;
}

on the arduino side I have:

void loop() { 
  int inByte;
  if (Serial.available() > 0) {
    inByte = Serial.read();
    switch (inByte) {
      case 'a' :      //muovi a sinistra
        digitalWrite(sx, HIGH); is_moving=true;
        break;
      case 'b' :      //muovi a destra
        digitalWrite(dx, HIGH); is_moving=true;
        break;
      case 'c' :      //stop
        digitalWrite(sx, LOW); digitalWrite(dx, LOW); is_moving=false;
        break;
…

Any advise?

Posting snippets of code isn't any help.

My first guess is that your PC code doesn't allow time for the Arduino to reset when the PC code opens the serial port.

Another common problem in newbies' PC programs is that they close the port and reopen it. This is no problem for a PC application but it just doesn't work with an Arduino because it will reset every time the port is reopened.

A simple way to deal with the reset is to have the Arduino send a short message from setup() and for the PC program to wait until it receives that before proceeding.

The Python and Arduino code here illustrates this.

...R

Long time has passed, but I still can't figure out how to solve my problem.

I do actually open and close the serial communication. I have a button to open it when I need it and to close it when I don't need it anymore.
I can't put anything in the setup() function of arduino because it would be executed only once, then the arduino stays on "forever".

I think I'll paste the whole code: arduino side and pc side, so maybe you have some more details.
I recap my problem: serial communication works only after I open arduino IDE serial monitor and send the first command by hand.

Here is the PC source code:

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Choice.H>
#include <windows.h>
#include <stdio.h>

HANDLE serialHandle;
bool connesso=0, aperto=0, motoi=0;
int gradimovi=0, tempoi=0;
Fl_Window *form;
Fl_Input  *gradimov;
Fl_Button *connetti, *sconnetti, *destra, *sinistra, *stop, *apri, *chiudi, *moto, *panic;
Fl_Choice *veloc;

char SerialGetc(HANDLE *hCom);
void SerialPutc(HANDLE *hCom, char txchar);
void connetticb(Fl_Widget* obj);
void destracb(Fl_Widget* obj);
void sinistracb(Fl_Widget* obj);
void stopcb(Fl_Widget* obj);
void motocb(Fl_Widget*);
void apricb(Fl_Widget* obj);
void chiudicb(Fl_Widget* obj);
void paniccb(Fl_Widget*);
void veloccb(Fl_Widget*);


int main(int argc, char *argv[]){
   form = new Fl_Window(440,190,"AUTODOME Museo del Bali");
   connetti = new Fl_Button(20,20,80,30, "Connetti");     
   connetti->callback(connetticb);
   connetti->color(FL_RED);
   gradimov = new Fl_Input(160,25,50,20, "Gradi: ");
   gradimov->value("0");
   gradimov->deactivate();                                          
   destra = new Fl_Button(350,20,60,30, "&Destra");     
   destra->callback(destracb);
   destra->deactivate();
   stop = new Fl_Button(290,20,50,30, "STOP");        
   stop->callback(stopcb);
   stop->deactivate();
   sinistra = new Fl_Button(220,20,60,30, "&Sinistra");   
   sinistra->callback(sinistracb);
   sinistra->deactivate();
   moto = new Fl_Button(350,60,60,30, "Moto");        
   moto->callback(motocb);
   moto->deactivate();
   apri = new Fl_Button(220,100,90,30, "&Apri");      
   apri->callback(apricb);
   apri->deactivate();
   chiudi = new Fl_Button(320,100,90,30, "Chiuso");     
   chiudi->callback(chiudicb);
   chiudi->color(FL_RED);
   chiudi->deactivate();
   panic = new Fl_Button(220,140,190,30, "&PANIC");    
   panic->callback(paniccb);
   panic->deactivate();
   veloc = new Fl_Choice (280,65,60,20, "Velocit‡ cupola: ");
   veloc->add("0|1|2|3|4");
   veloc->value(0);
   veloc->deactivate();
   veloc->callback(veloccb);
   form->end();
   form->show(argc, argv);
   return Fl::run();
}

char SerialGetc(HANDLE *hCom) {
  char rxchar;
  BOOL bReadRC;
  static DWORD iBytesRead;
  bReadRC = ReadFile(*hCom, &rxchar, 1, &iBytesRead, NULL);
  return rxchar;
}

void SerialPutc(HANDLE *hCom, char txchar) {
  BOOL bWriteRC;
  static DWORD iBytesWritten;
  bWriteRC = WriteFile(*hCom, &txchar, 1, &iBytesWritten,NULL);
  return;
}

void connetticb(Fl_Widget* obj){
  if (connesso==0) {
    serialHandle = CreateFile("\\\\.\\COM11", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
    DCB serialParams = { 0 };  // Do some basic settings
    serialParams.DCBlength = sizeof(serialParams);

    GetCommState(serialHandle, &serialParams);
    serialParams.BaudRate = 9600;
    serialParams.ByteSize = 8;
    serialParams.StopBits = ONESTOPBIT;
    serialParams.Parity = NOPARITY;
    GetCommState(serialHandle, &serialParams);

    COMMTIMEOUTS timeout = { 0 };   // Set timeouts
    timeout.ReadIntervalTimeout = 50;
    timeout.ReadTotalTimeoutConstant = 50;
    timeout.ReadTotalTimeoutMultiplier = 50;
    timeout.WriteTotalTimeoutConstant = 50;
    timeout.WriteTotalTimeoutMultiplier = 10;
    SetCommTimeouts(serialHandle, &timeout);
    obj->label("Sconnetti");
    obj->color(FL_GREEN);
    obj->redraw();
    apri->activate();
    destra->activate();
    sinistra->activate();
    gradimov->activate();
    panic->activate();
    veloc->activate();
    connesso=1;
  }
  else if (connesso==1) {
    CloseHandle(serialHandle);
    if (aperto==1) chiudicb(chiudi);
    stopcb(stop);
    obj->label("Connetti");
    obj->color(FL_RED);
    obj->redraw();
    apri->deactivate();
    destra->deactivate();
    sinistra->deactivate();
    veloc->deactivate();
    gradimov->value("0"); gradimovi=0;
    gradimov->deactivate();
    panic->deactivate();
    connesso=0;
  }
}

void veloccb(Fl_Widget* obj) {
  moto->activate();
}

void destracb(Fl_Widget* obj){
  gradimovi=atoi(gradimov->value());
  if (gradimovi==0){
    SerialPutc(&serialHandle, 'b');
    obj->color(FL_GREEN);
    obj->deactivate();
    obj->redraw();
    sinistra->deactivate();
    stop->activate();
  }
  if (gradimovi>0) {
    SerialPutc(&serialHandle, 'b');
    Sleep(gradimovi*2000);
    SerialPutc(&serialHandle, 'c');
    gradimov->value("0"); gradimovi=0;
  }
}

void sinistracb(Fl_Widget* obj){
  gradimovi=atoi(gradimov->value());
  if (gradimovi==0){
    SerialPutc(&serialHandle, 'a');
    obj->color(FL_GREEN);
    obj->deactivate();
    obj->redraw();
    destra->deactivate();
    stop->activate();
  }
  if (gradimovi>0) {
    SerialPutc(&serialHandle, 'a');
    Sleep(gradimovi*2000);
    SerialPutc(&serialHandle, 'c');
    gradimov->value("0"); gradimovi=0;
  }
}

void stopcb(Fl_Widget* obj){
  SerialPutc(&serialHandle, 'c');
  destra->color(FL_BACKGROUND_COLOR);
  destra->activate();
  destra->redraw();
  sinistra->color(FL_BACKGROUND_COLOR);
  sinistra->activate();
  sinistra->redraw();
  obj->deactivate();
  if (motoi) {
    veloc->value(0);
    motoi=0;
    tempoi=0;
  }
}

void motocb(Fl_Widget*){
  DWORD dwBytesWritten;
  stop->activate();
  destra->deactivate();
  sinistra->deactivate();
  tempoi=veloc->value();
  motoi=1;
  switch(tempoi) {
    case 1: WriteFile(serialHandle, "g1.16", 4,&dwBytesWritten, NULL);
    case 2: WriteFile(serialHandle, "g1.8", 4,&dwBytesWritten, NULL);
    case 3: WriteFile(serialHandle, "g1.4", 4,&dwBytesWritten, NULL);
    case 4: WriteFile(serialHandle, "g1.2", 4,&dwBytesWritten, NULL);
    default: ;
  }
}

void apricb(Fl_Widget* obj){
    SerialPutc(&serialHandle, 'd');
    obj->label("Aperto");
    obj->color(FL_GREEN);
    obj->deactivate();
    obj->redraw();
    chiudi->label("&Chiudi");
    chiudi->color(FL_BACKGROUND_COLOR);
    chiudi->activate();
    chiudi->redraw();
    aperto=1;
}

void chiudicb(Fl_Widget* obj){
  SerialPutc(&serialHandle, 'e');
  obj->label("Chiuso");
  obj->color(FL_RED);
  obj->deactivate();
  obj->redraw();
  apri->label("&Apri");
  apri->color(FL_BACKGROUND_COLOR);
  apri->activate();
  apri->redraw();
  aperto=0;
}

void paniccb(Fl_Widget*){
  SerialPutc(&serialHandle, 'f');
}

And here is the arduino source code:

#define TOPCLO 24000

boolean is_moving=false;
boolean is_open=false;
int tempo=0;
int gradi=0;

byte sx = 8;
byte dx = 9;
byte op = 7;
byte cl = 6;
byte panic = 5;

void checksensors (){
  ;
}

void setup() { 
  Serial.begin(9600);
  pinMode(sx, OUTPUT);
  pinMode(dx, OUTPUT);
  pinMode(op, OUTPUT);
  pinMode(cl, OUTPUT);
  pinMode(panic, OUTPUT);
  digitalWrite(op, HIGH);
  digitalWrite(cl, HIGH);
  digitalWrite(panic, HIGH);
}

void loop() { 
  int inByte;
  if (Serial.available() > 0) {
    inByte = Serial.read();
    switch (inByte) {
      case 'a' :      //muovi a sinistra
        digitalWrite(sx, HIGH); is_moving=true;
        break;
      case 'b' :      //muovi a destra
        digitalWrite(dx, HIGH); is_moving=true;
        break;
      case 'c' :      //stop
        digitalWrite(sx, LOW); digitalWrite(dx, LOW); is_moving=false;
        break;
      case 'd' :      //apri 
        digitalWrite(op, LOW); delay(TOPCLO); digitalWrite(op, HIGH); is_open=true;
        break;
      case 'e' :      //chiudi 
        digitalWrite(cl, LOW); delay(TOPCLO); digitalWrite(cl, HIGH); is_open=false;
        break;
      case 'f' :      //panic 
        digitalWrite(panic, LOW); delay(500); digitalWrite(panic, HIGH);
        break;
      case 'g' :      //automotion 
        gradi = Serial.parseInt();
        tempo = Serial.parseInt();
        while(Serial.read() != 'c') {
          digitalWrite(dx, HIGH);
          delay(gradi*2000);
          digitalWrite(dx, LOW);
          delay(tempo*1000);
          checksensors();
        }
        break;
      default:
        break;
    }
    checksensors();
  }
}
  static DWORD iBytesWritten;
  bWriteRC = WriteFile(*hCom, &txchar, 1, &iBytesWritten,NULL);

Why is iBytesWritten static?

If I try to start directly with my C++ program it would not work

Shitcan that C++ code. Write an app using C#. Open the port in a callback. Wait an appropriate length of time, then send any data you want. Close the port when you are done. There is a sample C# application attached that should get you started.

CommunicateWithArduino.zip (54 KB)

Tensore79:
I do actually open and close the serial communication. I have a button to open it when I need it and to close it when I don't need it anymore.
I can't put anything in the setup() function of arduino because it would be executed only once, then the arduino stays on "forever".

Opening and closing the serial port on the PC "when you don't need it" is not an option. Open it, and leave it open until you are finished using the Arduino.

Lot's of folk put stuff goes in setup() precisely because it only needs to happen once. The stuff that needs to happen lots of times goes into, or is called from loop().

Did you try the example I posted. Do you understand how it works? If not I will try to explain.

...R