Go Down

Topic: [Projet] Montage de mesure de stabilité (Read 22720 times) previous topic - next topic

Jean-François

Bon...J'arrive à lire les valeurs de mes accéleros et à les écrire sur la SD.
Maintenant il m'arrive un "truc" étrange (je pense à un overflow avec mes arrays), lorsque j'approche les 20 km/h l'arduino fait un reset.
L'écran lcd s'efface et le texte qui se trouve dans le setup s'affiche à nouveau....
J'ai fait un test en mettant mes capteurs sur une autre alim et le résultat est similaire.

Est-ce bien ce que je pense qui me provoque ça ?
Y a t'il un moyens de faire cela d'une autre manière ?

Code: [Select]
#include <SdFat.h>
#include <TinyGPS.h>
#include <LiquidCrystal.h> // Inclusion de la librairie pour afficheur LCD

SdFat sd;
SdFile myFile;
// Change the value of chipSelect if your hardware does
// not use the default value, SS_PIN.  Common values are:
// Arduino Ethernet shield: pin 4
// Sparkfun SD shield: pin 8
// Adafruit SD shields and modules: pin 10
const uint8_t chipSelect = SS_PIN;

const int RS=2; //declaration constante de broche
const int E=3; //declaration constante de broche
const int D4=4; //declaration constante de broche
const int D5=5; //declaration constante de broche
const int D6=6; //declaration constante de broche
const int D7=7; //declaration constante de broche

LiquidCrystal lcd(RS, E, D4, D5, D6, D7);// Création d'un objet LiquidCrystal = initialisation LCD en mode 4 bits

const int inX= 1 ;
const int inY= 0 ;
const int inZ= 2 ;

int AxeX [100];  // 625
int AxeY [100];  // 625
int AxeZ [100];  // 625

float Speed = 0;           
float FilteredSpeed = 0;
float filterVal = 0.9;
unsigned long TimeOldSpeed;
unsigned int rpm = 0;
int rpmcount = 0;
unsigned long timeold = 0;

int top = 0;
float SpeedVal [100]; // 625
unsigned long oldMillis=0;
unsigned long timeTop [100];  // 625

TinyGPS gps;

void gpsdump(TinyGPS &gps);
bool feedgps();
void printFloat(double f, int digits = 2);

void setup()
{
  Serial.begin(115200);
  Serial3.begin(9600);

  // Initialize SdFat or print a detailed error message and halt
  // Use half speed like the native library.
  // change to SPI_FULL_SPEED for more performance.
  //if (!sd.init(SPI_HALF_SPEED, chipSelect)) sd.initErrorHalt();
  if (!sd.init(SPI_FULL_SPEED, chipSelect)) sd.initErrorHalt();

  lcd.begin(20,2);
  lcd.setCursor(0, 0) ;
  delay(10);
 
  lcd.print("LCD OK") ;
  delay(2000);

  lcd.setCursor(0, 0) ;
  lcd.print("                   ") ;
  lcd.setCursor(0, 1) ;
  lcd.print("                   ") ;
  lcd.setCursor(0, 0) ;
  lcd.print("No Sat") ;

    Serial.print("Testing TinyGPS library v. ");
  Serial.println(TinyGPS::library_version());
  Serial.println("by Mikal Hart");
  Serial.println();
  Serial.print("Sizeof(gpsobject) = ");
  Serial.println(sizeof(TinyGPS));
  Serial.println();

  attachInterrupt(4, rpm_fun, FALLING);
}


void loop()
{
  if (millis() - timeold > 500 && FilteredSpeed > 0){
    FilteredSpeed=0;
  }

  if (rpmcount >= 6) {
    //Update RPM every 20 counts, increase this for better RPM resolution,
    //decrease for faster update

    // Speed = 10*1000/(millis() - timeold)*rpmcount/60*2.018;
    Speed = 0.002018/36/(millis() - timeold)*rpmcount*1000*3600;
    if (Speed > FilteredSpeed + 10 || Speed < FilteredSpeed - 10 )
    {
      Speed=FilteredSpeed;
    }

    FilteredSpeed= lpfilter(Speed*.9+(FilteredSpeed*.1), filterVal , FilteredSpeed);
   
    timeold = millis();
    rpmcount = 0;
   // Serial.print ("vitesse ");
   // Serial.println(FilteredSpeed,DEC);

  }

  if (millis()-TimeOldSpeed >100)
  {

    lcd.setCursor(14, 1) ;
    lcd.print("    ") ;
    lcd.setCursor(10, 1) ; // 13ème col - 4ème ligne - positionne le curseur à l'endroit voulu (colonne, ligne) (1ère=0 !)
    //lcd.print(gps.f_speed_kmph()) ; // affiche la chaîne texte - message de test
    lcd.print(FilteredSpeed) ;
    TimeOldSpeed=millis();
  }

  bool newdata = false;
  unsigned long start = millis();

  // Every 5 seconds we print an update
  while (millis() - start < 100)
  {
    if (feedgps())
      newdata = true;
  }
  //if (newdata== false){lcd.clear();} // // efface écran et met le curseur en haut à gauche

    if (newdata)
  {
    Serial.println("Acquired Data");
    Serial.println("-------------");
    gpsdump(gps);
    Serial.println("-------------");
    Serial.println();
  }
}

void printFloat(double number, int digits)
{
  // Handle negative numbers
  if (number < 0.0)
  {
    Serial.print('-');
    number = -number;
  }

  // Round correctly so that print(1.999, 2) prints as "2.00"
  double rounding = 0.5;
  for (uint8_t i=0; i<digits; ++i)
    rounding /= 10.0;

  number += rounding;

  // Extract the integer part of the number and print it
  unsigned long int_part = (unsigned long)number;
  double remainder = number - (double)int_part;
  Serial.print(int_part);

  // Print the decimal point, but only if there are digits beyond
  if (digits > 0)
    Serial.print(".");

  // Extract digits from the remainder one at a time
  while (digits-- > 0)
  {
    remainder *= 10.0;
    int toPrint = int(remainder);
    Serial.print(toPrint);
    remainder -= toPrint;
  }
}

void gpsdump(TinyGPS &gps)
{
  long lat, lon;
  float flat, flon;
  unsigned long age, date, time, chars;
  int year;
  byte month, day, hour, minute, second, hundredths;
  unsigned short sentences, failed;

  gps.get_position(&lat, &lon, &age);

  feedgps();

  gps.f_get_position(&flat, &flon, &age);

  feedgps();

  gps.get_datetime(&date, &time, &age);

  feedgps();

  gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);

  feedgps();

  lcd.setCursor(0, 0) ;
  lcd.print("                   ") ;
  lcd.setCursor(0, 1) ;
  lcd.print("                   ") ;
  lcd.setCursor(0, 0) ;
  lcd.print(flat,5) ;
  lcd.setCursor(0, 1) ;
  lcd.print(flon,5) ;
  lcd.setCursor(10, 0) ;
  lcd.print(second,DEC) ;
  lcd.setCursor(13, 0) ;
  lcd.print(int(gps.f_course())) ;
  lcd.setCursor(14, 1) ;
  lcd.print("    ") ;
  lcd.setCursor(10, 1) ;
  lcd.print(FilteredSpeed) ;

  if (!myFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)) {
    sd.errorHalt("opening test.txt for write failed");
  }

  // if the file opened okay, write to it:
  //  Serial.print("Writing to test.txt...");
  myFile.print(year);
  myFile.print("/");
  myFile.print(static_cast<int>(month));
  myFile.print("/");
  myFile.print(static_cast<int>(day));
  myFile.print(",");
  myFile.print(static_cast<int>(hour));
  myFile.print(":");
  myFile.print(static_cast<int>(minute));
  myFile.print(":");
  myFile.print(static_cast<int>(second));
  myFile.print(".");
  myFile.print(static_cast<int>(hundredths));
  myFile.print(",");
  myFile.print(flat,5);
  myFile.print(",");
  myFile.print(flon,5);
  myFile.print(",");
  myFile.print(int(gps.f_course()));
  myFile.print(",");
  myFile.println(FilteredSpeed);
 
   for (int i=0;i<=top-1;i++){
   myFile.print (timeTop [i]);
   myFile.print(",");
   myFile.print (SpeedVal [i]);
  //*
   myFile.print(",");
   myFile.print(AxeX[i]);
   myFile.print(",");
   myFile.print(AxeY[i]);
   myFile.print(",");
   myFile.println (AxeZ[i]);
   //*/
   }
   
  // close the file:
  myFile.close();
  //  Serial.println("done.");
  oldMillis=millis();
  top=0;
}

bool feedgps()
{
  while (Serial3.available())
  {
    if (gps.encode(Serial3.read()))
      return true;
  }
  return false;
}

void rpm_fun()
{
  rpmcount++;
  Top();
  top++;
}

float lpfilter(float data, float filterVal, float filteredVal){

  if (filterVal > 1){
    filterVal = .99;
  }
  else if (filterVal <= 0){
    filterVal = 0;
  }

  filteredVal = (data * (1 - filterVal)) + (filteredVal * filterVal);

  return filteredVal;
}

void Top(){
 
  SpeedVal[top]=FilteredSpeed;
  timeTop[top]=millis()-oldMillis;
  //*
AxeX[top] = analogRead(inX);
AxeY[top] = analogRead(inY);
AxeZ[top] = analogRead(inZ);
  //*/
}
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Artouste


Bon...J'arrive à lire les valeurs de mes accéleros et à les écrire sur la SD.
Maintenant il m'arrive un "truc" étrange (je pense à un overflow avec mes arrays), lorsque j'approche les 20 km/h l'arduino fait un reset.
L'écran lcd s'efface et le texte qui se trouve dans le setup s'affiche à nouveau....
J'ai fait un test en mettant mes capteurs sur une autre alim et le résultat est similaire.

Est-ce bien ce que je pense qui me provoque ça ?
Y a t'il un moyens de faire cela d'une autre manière ?



ta vitesse est derivée du top des rayons ?
peut etre un probleme d'interruption trop récurrente ?
tu a un générateur de fonction ?
si oui ce serait bien de le mettre en entrée en simulation/remplacement du phototrans et de voir à quelle frequence ça decroche

Jean-François

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Artouste


Voici mon générateur de "top" :



ok
grosso modo là tu a un rapport cyclique de 50%
si tu n'a pas de GBF , je suppose que tu a un autre arduino ?
essaye simplement en simulation l'exemple analog input tu injecte la sorte led13 sur ton entrée phototrans et regarde si ça decroche vers les même valeur de vitesse

Jean-François


ok
grosso modo là tu a un rapport cyclique de 50%
si tu n'a pas de GBF , je suppose que tu a un autre arduino ?
essaye simplement en simulation l'exemple analog input tu injecte la sorte led13 sur ton entrée phototrans et regarde si ça decroche vers les même valeur de vitesse


J'avais pas pensé à ça  :smiley-mr-green:, je pense que je dois mettre les gnd en commun ?
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Artouste



ok
grosso modo là tu a un rapport cyclique de 50%
si tu n'a pas de GBF , je suppose que tu a un autre arduino ?
essaye simplement en simulation l'exemple analog input tu injecte la sorte led13 sur ton entrée phototrans et regarde si ça decroche vers les même valeur de vitesse


J'avais pas pensé à ça  :smiley-mr-green:, je pense que je dois mettre les gnd en commun ?

rhooo  8)

Jean-François

Bôôôô... c'était à tout hasard  :smiley-mr-green:
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Jean-François

Alors, typiquement lorsque je dépasse 20 km/h ça foire (je ne peux pas être plus précis avec le potard que j'ai).

20 km/h>>  ~100 tops

Ce qui est bizarre c'est que lorsque le GPS n'est pas en fix, les tableau ne sont pas mis à contribution, ça foire vers 6-7 km/h  :smiley-roll-blue:
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Artouste

#248
Mar 03, 2012, 09:17 pm Last Edit: Mar 03, 2012, 09:27 pm by Artouste Reason: 1

Alors, typiquement lorsque je dépasse 20 km/h ça foire (je ne peux pas être plus précis avec le potard que j'ai).

20 km/h>>  ~100 tops

Ce qui est bizarre c'est que lorsque le GPS n'est pas en fix, les tableau ne sont pas mis à contribution, ça foire vers 6-7 km/h  :smiley-roll-blue:

peut être voir du coté de l'occupation temporelle globale, vers 100 top (20Km/H)  trop d'interruptions qui empêchent le traitement des autres processus ?
Ce qui semble à priori étonnant c'est le reset (automatique) de l'arduino (ça ressemble à un phénomène de watchdog interne) , un plantage (plus rien) ou données affichées incohérentes me semblerait plus "naturel".

Là je ne vais pouvoir t'aider plus sur ce probleme, je n'ai pas de mega

peut etre un test à faire : diminuer le taux de rafraichissement/clacul des info sur le lcd pour voir si le "reset" intervient à vitesse plus élevée

Jean-François

#249
Mar 03, 2012, 10:30 pm Last Edit: Mar 03, 2012, 10:41 pm by Jean-François Reason: 1
Sur les conseils de Skywodd (merci  ;), si tu veux bien poster ton explication), j'ai modifié ça de cette façon :

Code: [Select]
void rpm_fun()
{
 rpmcount++;
 Top();
 top++;
 if( top >= 100){top=100-1;}
}


Le débordement des tableaux est limité avec un if.

Maintenant, cela fonctionne jusqu'à 30 km/h... il faut que je trouve un moyen de simuler une plus grande vitesse.
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Artouste


Sur les conseils de Skywodd (merci  ;), si tu veux bien poster ton explication), j'ai modifié ça de cette façon :

Code: [Select]
void rpm_fun()
{
 rpmcount++;
 Top();
 top++;
 if( top >= 100){top=100-1;}
}


Le débordement des tableaux est limité avec un if.

Maintenant, cela fonctionne jusqu'à 30 km/h... il faut que je trouve un moyen de simuler une plus grande vitesse.

oui,  pas sympa skywodd de faire des cachoteries  :smiley-mr-green:
ça fonctionne jusqu'à 30 et ça reset ensuite pareil ou tu ne peux pas simuler des tops qui renvoie une V > 30 Kmh ?

Jean-François

Je peux aller à une vitesse affichée de 30 km/h, mais je ne sais pas si l'info est traitée sur la SD... c'est ce que je suis en train de tester.
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

skywodd


Sur les conseils de Skywodd (merci  ;), si tu veux bien poster ton explication),

Ouaip !

Donc voila toute l'histoire ...

J'ai tout d'abord pensé à un manque de ram, du coup j'ai fait quelques stats :
J'ai compté :
-  312 int (soit 624 octets)
- 104 float (soit 832 octets)
- 104 long (soit 416 octets)
- 193 char (soit 193 octets)
Soit un total de 1615 octets de ram utilisé statiquement.

Ajouté à cela la pile d'appel pour les fonctions, les buffers des ports séries (96 octets), les instances d'objets (LiquidCrystal, Gps, ...) et SdFat (~1.5Ko) on approche des 4Ko de ram consommé.
Mais vu que la mega2560 a 8Ko de ram ça ne devrait pas être la cause du probléme.

J'ai donc regardé de plus prés le code et j'ai remarqué que les tableaux :
AxeX[], AxeY[], AxeZ[], SpeedVal[], et timeTop[]
Pouvait être sujet à un buffer overflow, car top est incrémenté (ligne 285) dans rpm_fun() sans jamais faire le moindre test de dépassement.

En croisant ce point avec le fait que les tableaux couvrent 50% de la ram, il est trés fortement probable que le bug soit causé par un buffer overflow venant écrire dans des zones mémoires qui ne devraient jamais être bidouillées.
Quand la mémoire ram par en sucette le cpu redémarre au vecteur de reset, ça ressemble donc très fortement aux symptômes.

Quote
oui,  pas sympa skywodd de faire des cachoteries

C'est J-F qui est venu me chercher par MP :smiley-mr-green:
Enfin, il a bien fait, j'avais complétement décroché du topic :smiley-red:

Quote
ça fonctionne jusqu'à 30 et ça reset ensuite pareil ou tu ne peux pas simuler des tops qui renvoie une V > 30 Kmh ?

J'espère pas, si ça reset à V > 30Km ça voudrai dire qu'il y a encore un buffer overflow quelques pars :smiley-sweat:
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

churchill


J'espère pas, si ça reset à V > 30Km ça voudrai dire qu'il y a encore un buffer overflow quelques pars :smiley-sweat:

Et qu'en plus JF serait cantonné à faire du tricycle exclusivement dans les zones 30 km/h....

Jean-François

J'ai mis mes tableaux à 250 (histoire d'avoir la possibilité de monter à 50 tout de même  :smiley-mr-green:).... et à partir de 24 km/h la vitesse inscrite sur la SD est de 0, alors que les valeurs de l'accéléro est toujours dans les 250 à 350 (posé sur la table).
On dirait que le traitement de la vitesse ne se fait plus déjà avant de faire un overflow.
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Go Up