Go Down

Topic: RS485 troubles (Read 394 times) previous topic - next topic

pilou007

Sep 06, 2017, 10:44 am Last Edit: Sep 06, 2017, 10:54 am by pilou007
Hi everybody,
I work with Mega 2560 and with RS485 module.

On the other side, a device that transmit one page of 128kio or 131072 chars using115200 bauds speed.
My problem is that I cannot read the whole page as if the system is not fast enough, not even the last 2 chars which are NULL NULL. It looks like the incomming buffer cannot get everything

here is my code:
Code: [Select]

  // 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: queueLen never gets more than 60, according to different doc, it could get 64 or 128 chars is that enough to get my whole page?

Then Serial3.read(), read only char by char is that fast enought??

Thanks for your help
Pilou

pilou007

Hey guys,
I optimise the code and it works better but it's not enought... I got 127634 chars on 131072 expected chars

Could you help to find better?

Code: [Select]

// 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;

pilou007

I also tried this to work by block but it's nearly the same...
Code: [Select]

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;
  }

pilou007

ok guys,
Withe that code, I can proove that the problem comes from the writting on the SD card which slow down the system....

I am open to any other solution, even to replace the SD card with another device, but my project should be autonomous, so no computer...
Code: [Select]

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;
  }

pylon

Code: [Select]
    // Le Sleep sert à avoir un timeout à 5000ms environ
    delay(10);


Having delays in the code is a bad idea in most situations.

Regarding the rest of the code: Post complete code, excepts often don't show the real problem.
http://snippets-r-us.com/

pilou007

Ok, thank you.
If you look at my last post I changed it...

Now..
I changed the SD card for a Class10 writting at 30MBytes/s, I add this

Code: [Select]

SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));

With both it's really better I only lose 250 bytes instead of 2kiB.
And now I tried this
Code: [Select]

PROGMEM unsigned char readBuf[131076] = {'\0'}; // Enregistre le tableau en flash
  unsigned char temp = '\0';
 
 
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);
 
  for(int i = 0; i < 131076; i++){
    temp = pgm_read_byte(readBuf + i);
    fichier.write(temp);
  }

But it crashes down when I tried to read the buffer in the for loop....

Any idea?
Thanks

pylon

Quote
PROGMEM unsigned char readBuf[131076] = {'\0'};
Flash memory is read-only from the sketch. You cannot use it like RAM.

Quote
I changed the SD card for a Class10 writting at 30MBytes/s,
In the code you posted there is no SD card!


pilou007

Ok, I tried.... lol
But apparently it does not work...
First I am i big jerk, because in my loop "for(int i = 0; i < 131076; i++)... i sloud be a long, not an int....

But it does not work neither.

For the SD card, I put this
Code: [Select]

  SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE0));
 
  if (!SD.begin(SD_CS_PIN))
    initOk = false;

pylon

Did you read my last answer? Forget to use the flash (PROGMEM) as RAM, it won't work. You don't need the for loop because it won't write out what you read from the Serial3 interface.

And you still did not post complete code.

pilou007

Hello,
Ok, I tried....

The complete code is about 1000 lines split in 18 files (.h & .cpp), so I will not put the entire code...

The function doing the reading of the RS485 and the writting on the SD card contains only that code....
And the SD card initialization is in the setup....
I tried to take off the for loop, but it does not work....

i'm going tu use a Due on monday to check out if with a higher cpu clock speed it would be better or not.
Else I will try with a 2048kBytes (or at least a 128KBytes but it would just as the page I get is 131072 so 128K) EEPROM...

Thank you

pylon

Quote
i'm going tu use a Due on monday to check out if with a higher cpu clock speed it would be better or not.
Else I will try with a 2048kBytes (or at least a 128KBytes but it would just as the page I get is 131072 so 128K) EEPROM...
If you really need to read that much data, use a controller able to handle that amount. The Mega2560 is definitely not able to handle it, an EEPROM will wear out very fast, so you would have to add some SRAM externally which is definitely out of scope.
Have you thought about changing the platform? A Raspberry Pi would be able to handle that stuff and has and SD card built in.

Go Up