[RESOLU] DUEMINALOVE + OPENLOG

Bonsoir à tous,

J'ai fait l'acquisition dernièrement d'un Openlog avec lequel j'ai fait les tests de base trouvés sur le Net : tout fonctionnait.

Aujourd'hui, je cherche à placer cet OpenLog dans un projet pour enregistrer quelques informations et là, plus moyen de le faire fonctionner!!!

Lorsqu'une carte SD vierge est insérée, il créé le fichier CONFIG.TXT :

57600,26,3,0,1,1

baud,escape,esc#,mode,verb,echo

Voici le code que je teste :

/*
  Software serial test
 
 Receives from the hardware serial, sends to software serial.
 
 The circuit:
 * RX is digital pin 10 (connect to TX of other device)
 * TX is digital pin 11 (connect to RX of other device)
 
 Note:
 Not all pins on the Mega and Mega 2560 support change interrupts,
 so only the following can be used for RX:
 10, 11, 12, 13, 50, 51, 52, 53, 62, 63, 64, 65, 66, 67, 68, 69
 
 Not all pins on the Leonardo support change interrupts,
 so only the following can be used for RX:
 8, 9, 10, 11, 14 (MISO), 15 (SCK), 16 (MOSI).
*/

#include <SoftwareSerial.h>

SoftwareSerial mySerial(8, 9); // RX, TX

void setup()  
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
//  while (!Serial) {
//    ; // wait for serial port to connect. Needed for Leonardo only
//  }

  Serial.println("Hardware Serial init : OK");

  // set the data rate for the SoftwareSerial port
  mySerial.begin(57600);
  delay(500);
  Serial.println("Software Serial init : OK");

  Serial.println("Go...");

}

void loop() // run over and over
{
//  if (mySerial.available())
//    Serial.write(mySerial.read());
  if (Serial.available()) {
    char x = Serial.read();
    mySerial.print(x);
    Serial.println(x);
  }
}

Tout ce qui est saisi sur le Moniteur devrait être écrit sur la carte SD, seulement tous les fichiers créés sont vides!

Alors, à force de jongler avec les différents tests, je me suis aperçu que la configuration ARDUINO + SoftwareSerial + IDE023 ne fonctionne pas

J'ai testé le même code avec l'IDE 1.0.3, ça marche!! Sauf que le reste du projet est avec l'IDE023...

Ma question : est-ce qu'il y a une possibilité de faire fonctionner correctement SoftwareSerial avec l'IDE023?....

Merci pour vos suggestions
Olivier

Bonjour,

Bernardino:
Ma question : est-ce qu'il y a une possibilité de faire fonctionner correctement SoftwareSerial avec l'IDE023?....

Avant 1.0.x la librairie SoftwareSerial n'était pas codé par la même personne, et la version fourni était buggé à mort ...

Avant 1.0.1 la librairie SoftwareSerial telle qu'on la connait s'appelait "NewSoftSerial" :
http://arduiniana.org/libraries/newsoftserial/

Bonsoir,

Merci skywodd pour cette information.

Je suis en cours de test et voici mes résultats :
Mon sketch avec IDE023 + DUEMINALOVE + OPENLOG + NewSoftSerial fonctionne à 9600 bauds, au delà, j'obtiens n'importe quoi dans les fichiers.

Maintenant je cherche à intégrer NewSoftSerial dans le sketch définitif et là je coince sur une erreur de compilation :

NewSoftSerial\NewSoftSerial.cpp.o: In function `__vector_5':
C:\Program Files\arduino-0023\libraries\NewSoftSerial/NewSoftSerial.cpp:318: multiple definition of `__vector_5'
RC_Log_PortD_OpenLogSoftSerial.cpp.o:C:\Users\Olivier\AppData\Local\Temp\build2069600562732123190.tmp/RC_Log_PortD_OpenLogSoftSerial.cpp:171: first defined here

Si quelqu'un a une idée sur la résolution de ce problème, elle est la bien venue.

J'ai mis le code complet ici :
http://bernard.o.perso.neuf.fr/Electronic/RC_Log_PortD_OpenLogSoftSerial.zip

Merci d'avance.
Olivier

9600 bauds c'est le maximum que peut fournir NewSoftSerial / SoftwareSerial il me semble (c'est de l'émulation de port série, faut pas trop en demander).

Si tu veut vraiment aller plus haut dans l'échelle des bauds regarde du côté de AltSoftSerial (57600 bauds max) :
http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html

C'est à peu prés la même chose que NewSoftSerial mais sans latence.
Par contre tu ne choisis pas les broches du port série "virtuel", ni le nombre de port (1 port et pas plus).

Bonsoir,

@skywodd
Si je peux me permettre, ;), (tout étonné de devoir te corriger :blush:)
mais dans la bible d'Arduino, "ils disent" que SoftwareSerial, ça peut aller jusqu'à 115200...

"The SoftwareSerial library has been developed to allow serial communication on other digital pins of the Arduino, using software to replicate the functionality (hence the name "SoftwareSerial"). It is possible to have multiple software serial ports with speeds up to 115200 bps. A parameter enables inverted signaling for devices which require that protocol. "

Je teste dès que possible cette nouvelle librairie (ce soir donc, boulot oblige...).

Par contre, est-ce que vous auriez une explication sur l'erreur à la compilation suivante :

NewSoftSerial\NewSoftSerial.cpp.o: In function `__vector_5':
C:\Program Files\arduino-0023\libraries\NewSoftSerial/NewSoftSerial.cpp:318: multiple definition of `__vector_5'
RC_Log_PortD_OpenLogSoftSerial.cpp.o:C:\Users\Olivier\AppData\Local\Temp\build2069600562732123190.tmp/RC_Log_PortD_OpenLogSoftSerial.cpp:171: first defined here

Est-ce dû à une incompatibilité entre la librairie et mon sketch principal?
Comment résoudre ce problème?

Au lieu d'attendre bêtement une réponse, j'ai essayé de comprendre ce qui se passe...
On trouve dans la libraire fournie (NewSoftSerial) des interruptions :

#if defined(PCINT0_vect)
ISR(PCINT0_vect)
{
  NewSoftSerial::handle_interrupt();
}
#endif

#if defined(PCINT1_vect)
ISR(PCINT1_vect)
{
  NewSoftSerial::handle_interrupt();
}
#endif

#if defined(PCINT2_vect)
ISR(PCINT2_vect)
{
  NewSoftSerial::handle_interrupt();
}
#endif

#if defined(PCINT3_vect)
ISR(PCINT3_vect)
{
  NewSoftSerial::handle_interrupt();
}
#endif

Or je définis aussi de mon côté une interruption :

ISR(PCINT2_vect) { //this ISR is common to every receiver channel, it is call everytime a change state occurs on a digital pin [D2-D7]
  uint8_t mask;
  uint8_t pin;
  uint16_t cTime,dTime;
  static uint16_t edgeTime[8];
  static uint8_t PCintLast;

  pin = PIND;             // PIND indicates the state of each PIN for the arduino port dealing with [D0-D7] digital pins (8 bits variable)

  mask = pin ^ PCintLast;   // doing a ^ between the current interruption and the last one indicates wich pin changed
  sei();                    // re enable other interrupts at this point, the rest of this interrupt is not so time critical and can be interr  pted safely
  PCintLast = pin;          // we memorize the current state of all PINs [D0-D7]

  cTime = micros();         // micros() return a uint32_t, but it is not usefull to keep the whole bits => we keep only 16 bits

  // mask is pins [D0-D7] that have changed
  // chan = pin sequence of the port. chan begins at D0 and ends at D7
  if (mask & 1<<0)           //indicates the bit 0 of the arduino port [D0-D7], that is to say digital pin 2, if 1 => this pin has just changed
    if (!(pin & 1<<0)) {     //indicates if the bit 0 of the arduino port [D0-D7] is not at a high state (so that we match here only descending PPM pulse)
      dTime = cTime-edgeTime[0]; 
      if (900<dTime && dTime<2200) rcPinValue[0] = dTime; // just a verification: the value must be in the range [1000;2000] + some margin
    } 
    else edgeTime[0] = cTime;    // if the bit 0 of the arduino port [D0-D7] is at a high state (ascending PPM pulse), we memorize the time

...

Est-cela qui pose problème? Oui, puisque lorsque je supprime cette routine, la compilation passe. Seulement j'ai besoin des 2...
Comment faire en sorte que les 2 interruptions soient compatibles?...

Questions plus basique : quelle shield utilisez-vous pour vos datalogger (enregistrement sur carte SD)? J'ai choisi OpenLog car il ne consomme que 2 pins.

Merci pour vos réponses.
Olivier

papybricol:
Si je peux me permettre, ;), (tout étonné de devoir te corriger :blush:)
mais dans la bible d'Arduino, "ils disent" que SoftwareSerial, ça peut aller jusqu'à 115200...

J'ai vu l'information sur le site de PJRC.
Ils ont peut être amélioré les timings avec l'intégration dans le core arduino, ou la doc officielle/PJRC ou moi avons raté un truc quelque pars :grin:

Bernardino:
Par contre, est-ce que vous auriez une explication sur l'erreur à la compilation suivante :
(...)
Est-ce dû à une incompatibilité entre la librairie et mon sketch principal?
Comment résoudre ce problème?

Cette erreur est typique d'une double déclaration d'une d'interruption (deux ou plus ISR(...) avec le même vecteur).

Bernardino:
Est-cela qui pose problème? Oui, puisque lorsque je supprime cette routine, la compilation passe. Seulement j'ai besoin des 2...
Comment faire en sorte que les 2 interruptions soient compatibles?...

Les interruptions PCINT sont toutes catchés par NewSoftSerial pour gérer le(s) port(s) série virtuel.
Si tu utilises une PCINT et que le port série virtuel se trouve sur la même PCINT tu seras bloqué.

Choisi des broches qui permettent d'avoir deux PCINTs indépendantes et commente la PCINT qui bloque dans le code de la librairie.
N'oublie pas de faire ton initialisation de ta PCINT après le NewSoftSerial::begin().

Sinon utilise AltSoftSerial, cette librairie utilise uniquement des interruptions de type "Capture" et "Comparator".

Bernardino:
Questions plus basique : quelle shield utilisez-vous pour vos datalogger (enregistrement sur carte SD)? J'ai choisi OpenLog car il ne consomme que 2 pins.

J'ai aussi un module OpenLog (mais pas pour faire du datalogging :grin:).
Tout dépend de l'application, datalogging en local, par internet, ...

Je viens de tester la librairie AltSoftSerial. Les tests de base sont bien plus concluant.

Malheureusement, maintenant je tombe d'autre soucis sur ma fonction de log :

Les tous premiers essais de log avait été réalisés avec ce module :
http://www.cooking-hacks.com/index.php/shop/arduino/microsd-2gb-module-for-arduino.html

Et pour écrire sur la carte SD, j'avais cette routine qui donnait satisfaction :

  // Enregistrement sur carte SD
  if (currentTime > (sdTime + 20000) ) { // 50Hz (20000)
      char dataString[ ] = "0000000000;000;000;000;000;000;000";
        unsigned long valRC = sdTime/1000;
        for(int i = 0; valRC > 0 && i < 10; i++){
          int val = valRC % 10;
          // ne pas oublier que les tableaux commencent à l'indice 0!!!
          dataString[9 - i] = 48 + val;
          valRC /= 10;
        }

    for (int voieRC=0;voieRC<6;voieRC++){
      //Serial.print(map(rcData[voieRC], 900, 2200, 0, 179));
        int valRC = map(rcData[voieRC], 900, 2200, 0, 179);
        for(int i = 0; valRC > 0 && i < 3; i++){
          int val = valRC % 10;
          // ne pas oublier que les tableaux commencent à l'indice 0!!!
          dataString[13 + voieRC * 4 - i] = 48 + val;
          valRC /= 10;
        }
    }

    File dataFile = SD.open(stringFile, FILE_WRITE);
  
    // if the file is available, write to it:
    if (dataFile) {
      dataFile.println(dataString);
      dataFile.close();
    }  
    // if the file isn't open, pop up an error:
    else {
      Serial.println("error opening datalog.txt");
    }
    sdTime = currentTime;
  }
  currentTime = micros();
}

Maintenant que je suis passé sur OpenLog, la routine est la même sauf pour la partie finale :

void writeSD(){
  if (currentTime > (sdTime + 100000) ) { // 50Hz (20000)
    char dataString[ ] = "0000000000;000;000;000;000;000;000";
    
    // Log le temps
    unsigned long valRC = sdTime/1000;
    for(int i = 0; valRC > 0 && i < 10; i++){
      int val = valRC % 10;
      // ne pas oublier que les tableaux commencent à l'indice 0!!!
      dataString[9 - i] = 48 + val;
      valRC /= 10;
    }

    // Log les données RC
    for (int voieRC=0;voieRC<6;voieRC++){
      //Serial.print(map(rcData[voieRC], 900, 2200, 0, 179));
        int valRC = map(rcData[voieRC], 900, 2200, 0, 179);
        for(int i = 0; valRC > 0 && i < 3; i++){
          int val = valRC % 10;
          // ne pas oublier que les tableaux commencent à l'indice 0!!!
          dataString[13 + voieRC * 4 - i] = 48 + val;
          valRC /= 10;
        }
    }

    // Envoi des données à OpenLog
    String currentDataString = dataString;
    mySerial.println(currentDataString);
    Serial.println(currentDataString);
    
    sdTime = currentTime;
  }
}

Les données reçues via le moniteur sont cohérentes :

...
0000010201;085;085;126;085;021;082
0000010301;085;084;126;085;022;082
0000010401;085;085;125;085;021;082
0000010501;085;086;126;085;020;082
0000010601;085;086;126;085;020;082
0000010701;085;085;125;085;021;082
0000010801;085;084;126;085;021;082
0000010901;085;085;125;085;021;082
0000011001;086;084;126;085;022;082
...

Par contre les données enregistrées sur la cart SD sont illisibles avec des caractères NULL à ne plus en finir... J'ai changé la fréquence d'enregistrement sans succès.

Même ce code ne marche pas :

  #define versionOpenLog "Rc_Log_20130127"

  #include <AltSoftSerial.h>
  AltSoftSerial mySerial; // RX=pin8, TX=pin9

  #define SOFTSERIAL_COM_SPEED 57600  // Faire correspondre avec le contenu du fichier CONFIG.TXT de la carte SD

...
  mySerial.begin(9600);
  mySerial.println("Essai");
  mySerial.println(versionOpenLog);

J'ai repris les codes qui fonctionnait, j'ai donc essayé ça (au cas où les string soient mal traitées) :

    // Envoi des données à OpenLog
    //mySerial.println(dataString); Ne fonctionne pas!!
    for (int i = 0; i < sizeof(dataString) - 1; i++) mySerial.print(dataString[i]);
    Serial.println(dataString);

Et là, encore une fois, je sèche... =(

Est-ce qu'il y a encore une incompatibilité avec le reste du code?....
Faut-il repasser en Serial Hardware avec les pins D0 et D1? J'ai cru comprendre qu'il fallait les laisser libre pour la communication PC. Sachant que ce projet n'est pas destiné à être connecté à un PC, quels sont les risques?...

Merci pour votre aide...
Olivier

Cherche l'erreur :

  #define SOFTSERIAL_COM_SPEED 57600
...
  mySerial.begin(9600);

Moi je verrai plutôt :

mySerial.begin(SOFTSERIAL_COM_SPEED);

Sinon n'oublie pas de croiser Rx et Tx (Tx arduino -> Rx openLog, ...) :wink:

Voilà : c'est ce qu'on appelle une boulette :blush:
Ce n'était pas la première, ça ne sera certainement pas la dernière! En espérant que cela ne se reproduise pas...
Merci pour ton aide.
Olivier