Flux RS485

Salut à tous,
Je travaille sur Mega 2560 avec un module RS485.

En face, j'ai un système qui crache une page de 128kio ou encore 131072 caractères en 115200 bauds.
Mon problème c'est que je n'arrive pas à lire la totalité de la page ni même les deux derniers caractères soit NULL NULL. j'ai l'impression que le buffer d'entrèe n'arrive pas à suivre
Voici mon code:

// Lecture zone
  Serial3.flush();
  Send_Read_DM[0] = 0x02;
  Send_Read_DM[1] = pFirstPageToRead; // 0x01
  Send_Read_DM[2] = pNbPageToRead; // 0x01
  Serial3.write(Send_Read_DM, 3);

  while(pasFini){
    
    // Le Sleep sert à avoir un timeout à 5000ms environ
    delay(10);
    
    // Lecture des données
    while((queueLen = Serial3.available()) > 0){
      cptTimeOut = 0;
      
      for(int i = 0; i < queueLen; i++){ // Tant qu'on a pas lu les caractères attendus
        fichier.print(char(Serial3.read()));
        nbReceivedByte ++;
      }
    }

    Serial.print("nbReceivedByte: ");
    Serial.println(nbReceivedByte);
        
    cptTimeOut ++;

    if(cptTimeOut > RS485_TIME_OUT){ // RS485_TIME_OUT à 50ms, donc Timeout = 5000ms environ
      
      timeout = true;

      break;
    }
  
    if(nbReceivedByte >= nbByteToRead)
      pasFini = false;
  }

Question: lorsque je regarde la valeur de queueLen, elle ne dépasse jamais les 60, le buffer d'entrée est semble t'il limité à 64 ou 128 octets suivant les doc, est-ce qu'avec une telle limitation je risque de perdre des données?
Ensuite, le Serial3.read(), ne lit que octet par octet est-ce que ça ne risque pas non plus de ralentir tout ça??

Merci pour votre aide
Pilou

Salut,
Merci pour ta lumière.... C'est vrai que ailleurs dans mon programme j'utilise millis pour faire mes time out...
Bref, c'est nettement mieux, mais pas encore ça... lol. J'obtiens 127634 caractères sur les 131072 attendus... Par contre, j'obtiens bien mes deux caractères de fin de page NULL NULL

Voic le code optimiser, si tu vois mieux, dis-moi car je suis certain maintenant que c'est une question de vitesse.... Est-ce qu'on peut utiliser un time out interne, j'ai cru voir ça à un endroit et est-ce que ça optimiserai encore plus l'algo?

// Ouverture du fichier
  if(!(fichier = SD.open(String(pDirName) + pFileName, FILE_WRITE)))
    return false;

  currentmillis = millis();
  
  // Lecture zone
  Serial3.flush();
  Send_Read_DM[0] = 0x02;
  Send_Read_DM[1] = pFirstPageToRead;
  Send_Read_DM[2] = pNbPageToRead;
  Serial3.write(Send_Read_DM, 3);

  // Lancement de la lecture des données
  while(1){
    
    // Lecture des données
    while((queueLen = Serial3.available()) > 0){
      
      for(int i = 0; i < queueLen; i++){ // Tant qu'on a pas lu les caractères attendus
        fichier.print(char(Serial3.read()));
      }
    }
        
    if(timeOut = ( millis() - currentmillis >= RS485_TIME_OUT))
      break;
  }

  // Fermeture du fichier
  fichier.close();

  if(timeOut)
    return false;

Avec un autre code, j'essaye de lire et d'enregistrer par block, mais c'est sensiblement la même chose en terme de résultat...

while(1){
    
    // Lecture des données
    while((queueLen = Serial3.available()) > 0){

      readBuf = calloc(queueLen, sizeof(char));
      
      Serial3.readBytes(readBuf, queueLen);
      
      fichier.write(readBuf, queueLen);
      
      free(readBuf);
    }
        
    if(timeOut = ( millis() - currentmillis >= RS485_TIME_OUT))
      break;
  }

Mince, avec ce que tu me dis là, j'ai bien l'impression d'être dans une impasse....
T'as une idée de ou je pourrai trouver du code optimiser?

ok, ça me semble bien compliqué....
Merci

Ok, avec ce code, j'obtiens bien test = 131072, ce qui veut dire que c'est bien l'écriture sur la carte SD qui pose porblème et doit ralentir le systus, si quelqu'un a une solution, je suis preneur...
Je suis ouvert à l'utilisation d'autre chose qu'une carte SD, mais le système complet sera dans un boitier, donc pas de PC...

while(1){ // Tant qu'on a pas lu les caractères attendus
    
    // Lecture des données
    while((queueLen = Serial3.available()) > 0)      
      for(int i = 0; i < queueLen; i++){ 
        test++;
        toto = Serial3.read();
        //fichier.write(char(Serial3.read()));
      }
        
    if(timeOut = ( (millis() - currentmillis) >= timeOutVal))
      break;
  }

Une carte raspberry pi. Si tu utilises une Raspberry Pi Zero tu seras plus petit que l'arduino. La consommation sera un peu plus élevée qu'avec l'arduino par contre. Pour le coût c'est sensiblement la même chose.

yep, si je passe sur Raspberry, il faut que je recommence tout.....
Mais j'y ai pensé...
Merci

un système qui crache une page de 128kio

Bonjour,
par hasard, ce dispositif (secret ?) ne dispose pas d'une gestion de flux ?

Re-Salut,
Alors pour le système secret, ça ne l'ai pas trop, lol....
En fait c'est un appareil qui se trouvera dans la nature et autonome, si cet appareil ne fonctionne plus, nous avons besoin d'envoyer une personne du SAV à travers le monde juste pour récupérer les données de cet appareil et faire reset dessus avant qu'il ne soit renvoyer en France.
Donc l'idée c'est de faire plein de boîtier (poiur environ 300€) que nous distribuerons à nos partenaires.
Il enregistre les donnée sur carte SD qui sera ensuite soit envoyer en France, soit lu sur Pc et ils nous enverrons les données.... Ensuite ils font un reset de l'appareil qui peut ensuite voyager de façon sécure--> ça ça marche, via des carte de 8 et 4 relais...

Quand aux données, j'en ai deux type:

  • via RS232, je récupère certaines données que je mets dans un fichier CSV --> ça ça marche aussi très bien via Rx2...
  • Via RS485 (j'ai un module pour envoyer une demande à l'appareil et un module pour écouter l'appareil), je récupère 81 page de 128kio chacune soit un eeu moins de 10Mio de données...
    Sans compter que je dois normalement crypter tout ça.... lol

Entre chaque page, j'ai le temps que je veux, je décide. Par contre, je dois récupérer par zone, par exemple:

  • Zone 1 --> Page 1 soit 128kio, actuellement, je perds 3kio...
  • Zone 2 --> Page 2 à 7 soit 768Kio, actuellemnt je perds une 30kio environ...
  • Et ainsi de suite jusqu'à une zone 5 de 50 page (mais je peux les récupérer une à une)...
    je ne peux pas intervenire sur l'appareil en dehors de ces choses là, donc non modifiable et impossible de lui changer son soft pour l'adapter...
    Merci

ok,
alors +1 pour le pi zero

En fait, je vais tester demain de modifier la vitesse du bus SPI, j'ai mis un post sur le forum d'Adafruit (là ou j'ai acheter le module SD card), ils me proposent de changer cette vitesse.
Aparrement, par défaut, la vitesse du bus SPI est divisée par 4, on peut la diviser juste par deux, ou bien faire un SPI.setting( vitesse du bus.....)...
et aussi

Qu'est-ce qu'il a de mieux le pi zéro?

Qu'est-ce qu'il a de mieux le pi zéro ?

Bonjour,
vaste question, les utilisateurs y répondront,
juste pour l'anecdote, il a 256 000 fois la capacité en ram de l'arduino uno

pilou007:
Qu'est-ce qu'il a de mieux le pi zéro?

Cela dépend du critère que tu attaches à mieux.
Le Pi Zero est petit et il consomme relativement peu par contre il n'a qu'un port USB. Prix un peu moins de 5£ (je les achète en Grande Bretagne (chez ThePiHut ou bien Pimoroni) où il y a plus de disponibilité) .
Le Pi Zero W est petit et il consomme un peu plus que le précédent, il n'a qu'un port USB mais il propose le Wifi et le Bluetooth (utile si tu veux récupérer tes fichiers par le net par exemple). Prix légèrement en-dessous de 10£.
Les autres Raspi sont plus puissants mais vu ton application je ne pense pas qu'ils soient intéressant.

Yep, merci pour toutes ces info.
En fait si je n'y arrive en changeant les vitesse du bus SPI, il faudra certainement que j'envisage de changer de système et donc de passer sur Raspberry...
Merci, je vous tiens au courant.

Ok, alors bon, là j'ai tout testé.... lol
J'ai mis une carte SD class10 avec une valeur de 30MByte/s en écriture... C'est mieux, il ne me manque plus que 300 octets, c'est mieux que 2kio.....

Par contre, je teste un nouveau code mais qui utilise la mémoire dynamique, mais je bloque à la lecture.
Voici mon code:

#include <avr/pgmspace.h>

PROGMEM unsigned char readBuf[131076] = {'\0'}; // Enregistre le tableau en flash
unsigned char temp;

while(1){

    // Lecture des données
    while((queueLen = Serial3.available()) > 0)
      for(int i = 0; i < queueLen; i++)
        readBuf[test++] = char(Serial3.read());

    if(timeOut = ( millis() - currentmillis >= maxTimeOut))
      break;
  }

  Serial.print("test: ");
  Serial.println(test);
  
  /*unsigned char temp;
  for(int i = 0; i < 131076; i++){
    temp = pgm_read_byte(readBuf + i);
    fichier.write(temp);
  }*/

si je laisse le code comme ça, la variable test affiche bien la valeur de 131076, mais dés que je mets le for en route le système crash....
Des idées??

Ok, j'ai fait le gros boulet là.... Désolé...

Bon, je suis passé sur un long, mais ça ne marche toujours pas, apparemment il n'est pas possible d'écrire dans la flash de façon dynamique....

Je crois que je n'ai plus de solution là.... Peut être passer sur un Due pour avoir une fréquence d'horloge plus rapide... et espérer avoir mes 250 octets manquant.... Mais rien de sur....

apparemment il n'est pas possible d'écrire dans la flash de façon dynamique....

Bonjour,
il faudrait savoir ce que tu entends par "écrire dans la flash de façon dynamique" ?

les écritures en flash sont rarement abordées dans le forum, je n'ai moi même pas pratiqué, donc me contente de quelques évidences :

  • écrire en flash est risqué car il faut s'assurer de ne pas écraser des choses utiles
  • le nombre de cycles d'écriture est limité, donc une opération en boucle mal maîtrisée peut rapidement mener à la destruction de la flash
  • avec un avr, il est souvent sportif d'écrire au-delà des fameux 64k, il faut s'assurer que les bibliothèques gèrent correctement les passages entre blocs

Salut,
En fait je voulais utiliser la Flash un peu comme de la ram.
Dans mon prog, j'ai une entete de fichier CSV qui fait environ 10kio, et pour pouvoir l'utiliser, je fais:

// F(....) permet de mettre une chaine et uniquement une chaine en flash, sinon il faut utiliser PROGMEM
  fichier.println(F("Time;"
                  "UFD_STATE;"......));

Et ça marche très bien, je pensais essayer de faire un truc un peu similaire, mais en dynamique... Mais bon je vais passer sur un Due dés lundi, et sinon, je vais essayer un module l'EEPROM qui devrait être plus rapide et j'irai écrire sur ma carte à partir de l'EEPROM....

Salut à tous,
Je suis passé sous l'Arduino Due.

Je n'ai pas encore réussi à faire les test car j'ai un gros souci avec les interruptions.
Sous Méga 2560, mon code qui fonctionnait parfaitement:

volatile bool recordRunning = false;
volatile bool resetRunning = false;
volatile bool supportPres = true;

// IHM Boutons
#define BT_RECORD               2
#define BT_RESET                  3
#define SD_DETECT_CARTE         18


void setup() {
    
  Serial.begin(9600);
    
  // Interruptions
  attachInterrupt( digitalPinToInterrupt(BT_RECORD), intRecord, RISING);
  attachInterrupt( digitalPinToInterrupt(BT_RESET), intReset, RISING);  
  attachInterrupt( digitalPinToInterrupt(SD_DETECT_CARTE), intSupportState, CHANGE);
...
}

void loop() {
      
    // Présence support
    if(!supportPres)
      recordState(LED_ON, LED_OFF);
     
    /********************************************************************************************************************
     *                                                      RECORD                                                      *
     ********************************************************************************************************************/
    if(supportPres && recordRunning){
       ....
    }
}


void intRecord(void){
  
  if(!resetRunning && supportPres && !recordRunning)
    recordRunning = true;
}

/*
 * Interruption bouton reset
 */
void intReset(void){

  if(!recordRunning && !resetRunning)
    resetRunning = true;
}

/*
 * Interruption perte support d'écriture
 */
void intSupportState(void){

  if(digitalRead(SD_DETECT_CARTE)){
    supportPres = true;
    recordState(LED_OFF, LED_OFF);
  }else{
    supportPres = false;
    recordState(LED_ON, LED_OFF);
  }
    
   // arrêt du programme
   if(recordRunning)
      recordRunning = false;
}

Question: devrais-je ouvrir un autre post pour ça?

Mon interruption sur la pin 18, fonctionne toujours très bien, mais celle sur les Pin 2&3 ne fonctionne plus du tout. J'ai essayé de les passer en pin 42&43, idem....
Et le pin, c'est que suite à l'attachInterrupt.... mes boolléens change d'état et donc mon progr démarre sans action extérieure....
Merci