Pages: [1]   Go Down
Author Topic: Problem reading serial port  (Read 507 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 42
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I need someone to open my eyes :o. I have a problem and just can't figure out what's wrong. The Arduino will get commands via the serial port (in fact an Xbee module) and execute the commands. This goes well. But this morning I changed the code to detect timeouts. The fisrt command is OK, but then it get a timeout on each caracter received.

This is what I wish to do:
  • each command ends with '#'
  • as sson as the fisrt character is received, I checked if receiving times out

Here is the code:

Quote
void setup()
{
int i;

#ifdef MEGA
  Serial.begin(57600);
#else
  Serial.begin(57600);
#endif

  strCmd[0] = '\0';  
  ptCmd = 0;
  fComp = false;
  Commande.Cmd = 255;
  for (i = 0; i < 5; i++)
    Commande.Par = 0;
  Commande.NbPar = 0;
  
  fProc = true;
  
  fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);

  // The uart is the standard output device STDOUT.
  stdout = &uartout;
  
}

void loop()
{
char  Car;  // un caractère
char nCmd[3];  // numéro de commande
char fStr[15];
long lStart;   // lecture au départ du compteur de timeout

// Pointeurs

int i;  // dans strCmd
int j;  // dans nCmd[] et strPar[]
int k;  // dans Commande.Par[]
char strPar[6];  // un paramètre (chaîne)

  //  1 - read serial port

  if (fProc == true)  // true the process characters
    {
     
    // If at least 1 char. received, check timeout
      
    if ((ptCmd > 0) && ((millis() - lStart) > 5000))  
      {

#ifdef MEGA
      printf("  pt = %d - tout ---\n   ", ptCmd);
      for (i = 0; i < ptCmd; ++i)
        printf("%c", strCmd);
      printf("\n");
#endif  
      ptCmd = 0;  
      strCmd[0] = '\0';

      }
    else      // carry on
      {
      if (Serial.available())  // at least one char. received
        {
        Car = (char)Serial.read();
        
        if (Car != FIN_CMD)  // '#' not received
          {
          strCmd[ptCmd++] = Car;
          lStart = millis();  // restart timeout counter        
          }
        else                // '#' received
          {
          fComp = true;    // Command complete
          strCmd[ptCmd] = '\0';
          ptCmd = 0;
          fProc = false;
          // Serial.flush();
          }
        }  // if caractère reçu        
      }  // else de if timeout  
    }   // if (fProc == true)

  // remining of loop cut, process command
}
  


One more information. At this time the software is develloped on a MEGA board, and I communicate with the board via serial monitor.

Thanks for your help
« Last Edit: September 21, 2010, 10:49:32 am by planteg » Logged

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 238
Posts: 24322
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It's better if you include ALL the sketch, and use the "#" icon, instead of the quote.
Logged

"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 42
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I changed the the part that reads the serial port, and still have problems. Please note that I was unable to publish the entire sketch because it was bigger than the maximum number of characters allowed. Sorry for the comments in French, this is my language.

I use the console to do the debugging (breakpoints would be nice  :-/), and here is what I get for the first command sent (10#):

Cmd = 10
Par[0] =  0.000
Par[1] =  0.000
Par[2] =  0.000
Par[3] =  0.000
Par[4] =  0.000
Nb de param. = 0
00#
  pt = 2 - tout ---
   10


The command executes OK (it returns 00#), but right after a timeout is declared (pt = 2 - tout ---).

Note this code:

  //  2 - Préparation de la commande dans la structure
  
 delay(20);    // needed but why ???

If this delay is not there, then it does not work at all. Here is what I get on the console:


Nothing at all  :-?. When the last character is received, I set fComp to true. Then this should execute:

  if (fComp == true)
    {
    ...
    }

But it does not without the call to delay().

I am quite puzzled:
  • the comands complete OK, but then there is a timeout. Note that the iidea is to strart timeout check only once a first character is received
  • when you have to insert delays, you're in big trouble  smiley-wink.
I have had strange problems with the other micro connected to an Xbee, a Rabbit module, because only the baud rate was set. With the Arduino, one can only set the baud rate. I have read on the site that everything else is set to 8, n, 1. But I wonder.

Here is the code:

Code:
#include <Servo.h>

#include <MsTimer2.h>
#include <stdio.h>
#include <stdlib.h>

#define MEGA  // Lorsque défini, indique que c'est un board MEGA
              // non défini, board FIO

// create a FILE structure to reference our UART output function

static FILE uartout = {0} ;

// create a output function
// This works because Serial.write, although of
// type virtual, already exists.
static int uart_putchar (char c, FILE *stream)
{
    Serial.write(c) ;
    return 0 ;
}

#define  VER 6    // La version

#define FIN_CMD '#'  // caractère de fin de commande
#define FIN_PAR ';'  // caractère de in de paramètre

typedef struct
  {
  int Cmd;     // la commande (son numéro)
  float Par[5];  // 5 paramètres
  int NbPar;   // nb de paramètres  
  } Cmd;
  
Cmd Commande;  // Structure qui contient le no de commande et les paramètres

typedef struct
  {
  int mini;     // largeur d'impulsion minimale
  int centre;   // largeur d'impulsion centre moteur continu
  int maxi;     // largeur d'impulsion maximale
  int cont;     // true, moteur continu
  float temps;  // temps en sec. pour atteindre 60 deg. moteur angulaire
  } SPar;
  
SPar ServoP;  // structure qui contient les paramètres  

typedef struct
  {
  int ang;              // angle où amener le bras
  float temps;          // temps pour y aller ou revenir
  unsigned char aller;  // true c'est un aller, false un retour
  int count;            // le nb de fois
  } aPulse;

aPulse angP;  // structure qui contient les paramètres

#define SERVO_PIN 9  // pin Arduino où est relié le moteur

// Les commandes

#define ATTACH_SERVO    1
#define SET_ANGLE       2
#define SET_ROTATION    3
#define DETACH_SERVO    4
#define RUN_CONT_MSEC   5
#define SERVO_ATT       6
#define RUN_ANG_NB      7
#define STOP_CONT       8
#define VERSION         9
#define PING           10

//  Les messages de retour

#define CMD_OK        "00#"
#define CMD_ER_PAR    "01#"  // erreur validation des paramètres
#define CMD_NB_PAR    "03#"  // nb. de paramètres incorrect
#define CMD_NO_ATT    "04#"  // pas de servo attaché

int fComp;  // true, alors commande complète
Servo Moteur;  // objet pour le servo
char strCmd[30];  // comamnde reçue à traiter
int ptCmd = 0;  // pointeur dans Cmd
int fProc;  // true, lire les caractères
long lTimeOut;

void SendResp(char Resp[]);
void StopCont(unsigned char);
void StopCont2();

void setup()
{
int i;

  fdev_setup_stream (&uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE);

  // The uart is the standard output device STDOUT.
  stdout = &uartout;

#ifdef MEGA
  Serial.begin(9600);
#else
  Serial.begin(57600);
#endif

  strCmd[0] = '\0';  
  ptCmd = 0;
  fComp = false;
  Commande.Cmd = 255;
  for (i = 0; i < 5; i++)
    Commande.Par[i] = 0;
  Commande.NbPar = 0;
  
  fProc = true;
  
  
  
}

void loop()
{
char  Car;  // un caractère
char nCmd[3];  // numéro de commande
char fStr[15];


// Pointeurs

int i;  // dans strCmd
int j;  // dans nCmd[] et strPar[]
int k;  // dans Commande.Par[]
char strPar[6];  // un paramètre (chaîne)

  //  1 - Lecture des caractères

  if (fProc == true)
    {
    
    if (ptCmd == 0)    // pas de car. reçu
      {
      if (Serial.available() > 0)  // car. reçu(s)
        {
        Car = (char)Serial.read(); // printf("  Recu %c\n", Car);
        strCmd[ptCmd++] = Car;
        lTimeOut = millis() + 1000;  // charge le compteur  
        }
      }
    else    // des car. déjà reçus
      {
      if (millis() > lTimeOut)  // oups timeout
        {
#ifdef MEGA
        printf("  pt = %d - tout ---\n   ", ptCmd);
        for (i = 0; i < ptCmd; ++i)
          printf("%c", strCmd[i]);
        printf("\n");
#endif  
        ptCmd = 0;  
        strCmd[0] = '\0';
        Serial.flush();          
        }  
      else  // pas de timeout
        {
        if (Serial.available() > 0)  // car. reçu(s)
          {
          Car = (char)Serial.read(); // printf("  Recu %c\n", Car);
          
          if (Car == '#')  // commande finie
            {
            fProc = false; // printf("  # recu\n");
            fComp = true; // printf("fComp = %d\n", fComp);
                        
            }
          else
            {
            strCmd[ptCmd++] = Car;
            lTimeOut = millis() + 1000;  // charge le compteur
            }  
          }          
        }  // if timeout  
      }    // des car. déjà reçus    
    }      if (fProc == true)  
        
  //  2 - Préparation de la commande dans la structure
  
  delay(20);    // needed but why ???
  
  if (fComp == true)
    {
    
    i = 0;
    
    nCmd[0] = strCmd[i++]; nCmd[1] = strCmd[i++]; nCmd[2] = 0;
    
    Commande.Cmd = atoi(nCmd);
    
    for (k = 0; k < 5; k++)
      Commande.Par[k] = 0;
      
    j = 0; k = 0;
    while (strCmd[i] != '\0')
      {
      Car = strCmd[i++];  
      
      if (Car != FIN_PAR)
        strPar[j++] = Car;
      else
        {
        strPar[j] = '\0';
        Commande.Par[k++] = atof(strPar);
        j = 0;
        }
      }
      
    Commande.NbPar = k;
  
  #ifdef MEGA
  
    // Imprime commande
    
    printf("Cmd = %d\n", Commande.Cmd);
    for ( i = 0; i < 5; ++i)
      {
      dtostrf(Commande.Par[i], 6, 3, fStr);
      printf("Par[%d] = %s\n", i, fStr);
      }
      
    printf("Nb de param. = %d\n", Commande.NbPar);
  
  #endif
  
    //  3 - Exécution de la commande
  
    switch (Commande.Cmd)
      {
        
      case ATTACH_SERVO:
        AttachServo();
        break;  
      case SET_ANGLE:
        SetAngle();
        break;  
      case SET_ROTATION:
        SetRotation();
        break;
      case DETACH_SERVO:
        DetachServo();
        break;  
      case RUN_CONT_MSEC:
        RunContMsec();
        break;
      case SERVO_ATT:
        ServoAtt();
        break;
      case RUN_ANG_NB:
        RunAngNb();
        break;
      case STOP_CONT:
        StopCont(true);
        break;
      case VERSION:
        Version();
        break;
      case PING:
        Ping();
        break;  
      }
  
    Serial.flush();
    fComp = false;
    fProc = true;
    }
}

// There is some more code, not relevant
// removed because the message was over maximum size

Thanks
« Last Edit: September 22, 2010, 11:25:42 am by planteg » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 42
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK,

that was a code 18  :-/. Now works fine.

When coding is OK, results are OK  ;D.
Logged

Pages: [1]   Go Up
Jump to: