Go Down

Topic: Wierd problem when using SoftwareSerial (Read 929 times) previous topic - next topic

Randam

hello.

i am using an arduinoMega 2560.

it has 4 hardware serial ports, but i need 1 more.

so i included a software serial-port.

at first i was only using the 4 hardware ports.
i was reading bytes from 3 and sending them with the 4th.

now i wanted to send them over the software port.

here my code with the hardware port:
Code: [Select]
if (Serial3.available()) {

    Serial3.setTimeout(45);                           
    Serial3.readBytes(comein_3, 11);                         


     if ( puffer[4] != (byte) comein_3[9] ){    // here i check if there is new data
      for( int i=5; i<10; i++ ){
        puffer[ i-5 ] = comein_3[ i ];                 
      }



  // ************************ here i do some things with the bytes  *********************************************

      // in the end the bytes that were in the "puffer"-array are now in "fertig_daten"
     

      Serial.print( (char*) fertig_daten);              // here i send them over the hardware port
                                                                  // this works just fine

      serial_out.print( (char*) fertig_daten);        // here i try to send my data over the software serial port
                                                                   
    }
  }


my problem now is, when i try to use the software port, my controll-function if the bytes read from serial3 are new doesnt work anymore.
here:
Code: [Select]
if ( puffer[4] != (byte) comein_3[9] ){    // here i check if there is new data
      for( int i=5; i<10; i++ ){
        puffer[ i-5 ] = comein_3[ i ];                 
      }


when i use the hardware port, send the date it works fine.
i am reading data from a RFID-Reader and if the Transponders is held into the antenna-field, the reader sends the transponder-number over and over again.
but i only need it once, so i use the controll-function to check if the data, which i read is different from the data i read the last time.
and for some reasons, when i try to use the software serial port that doesnt work anymore.

pylon

Post complete code!

You know that interrupts are disabled during the whole transfer of a byte using the SoftwareSerial class, don't you? If you use SoftwareSerial you generally shouldn't expect that anything other is going on on that Arduino during that use, at least not in a timely manner.

Randam

the complete code is very long and has a lot of stuff, that has nothing to do with the part, that is causing the problem.

should i post it anyway?

and yeah i know that.

it seems like, when i send stuff with the software serial it screws with the buffer of serial3.(could that be?)
changes some bytes for what ever reason, which causes the if( puffer[4] != (byte) comein_3[9] ) to become true, despite the fact that the some transponder is beeing read.

pylon

Quote
should i post it anyway?


Showing us just excerpts of your code doesn't allow us to find the parts that may interfere. For example you don't show how the serials are initialized or how the buffers are defined.
Ideally you minimize your sketch to the smallest size still showing the problem you described. Then post that code.

Quote
it seems like, when i send stuff with the software serial it screws with the buffer of serial3.(could that be?)


I don't think so. It's more probable that you miss some characters if the interrupts are disabled for a too long time because the serial buffers are filled within interrupt service routines. If you have 4 serial interfaces receiving data and sending that data out using a SoftwareSerial chances are quite high that the SoftwareSerial code is using so much processor time (with interrupts disabled) that the serial receiving is not reliable anymore.

Randam

okay, here is the code.

there is also an if (Serial1.available()) and if (Serial2.available()) construct which does the same as the if (Serial3.available()).
had to cut it, because of the 9500 character limit.
Code: [Select]


#include <LiquidCrystal.h>
#include "Wire.h"
#include <SoftwareSerial.h>
#include <EEPROM.h>

SoftwareSerial serial_out(10, 11); // RX, TX

// here was a lot of variable declaration

void setup(){

 
 // Initialisieren der seriellen Schnittstellen
 Serial.begin (2400);                          // Serial 0 mit einer Baud-Rate von 2400 initialisieren
 Serial1.begin(9600, SERIAL_8E1);              // Serial 1 mit 9600 Baud und Even-Parity initialisieren
 Serial2.begin(9600, SERIAL_8E1);              // Serial 2 mit 9600 Baud und Even-Parity initialisieren
 Serial3.begin(9600, SERIAL_8E1);              // Serial 3 mit 9600 Baud und Even-Parity initialisieren

 // Software-Port initialisieren mit 2400 Baud
 serial_out.begin(2400);

}

//*********************************************************************
//*********************************************************************  ==> MAIN BEGIN <==

void loop()
{

 // ************************************* Print Serial with Time-Stamp (Serial_3)  

 // when characters arrive over the serial port...
 if (Serial3.available()) {

   Serial3.setTimeout(45);                            // 45 ms fürs Datenholen
   Serial3.readBytes(comein_3, 11);                   // 11 Bytes einlesen          


    if ( puffer[4] != (byte) comein_3[9] ){
     for( int i=5; i<10; i++ ){
       puffer[ i-5 ] = comein_3[ i ];                // 5 benötigeten Bytes in Puffer ablegen  
     }



 // here i put the bytes from puffer into fertig_daten

     for( int i=0; i<=9; i++ ){                                              // Daten in Speicher ablegen zur Anzeige auf LCD
       EEPROM.write( count  + i, fertig_daten[ i ]);
     }

     EEPROM.write( count + 10, ';');      // Zeit ebenfalls in Speicher ablegen
     EEPROM.write( count + 11, stunde_1);
     EEPROM.write( count + 12, minute_1);
     EEPROM.write( count + 13, minute_2);
     EEPROM.write( count + 14, sekunde_1);
     EEPROM.write( count + 15, sekunde_2);
     EEPROM.write( count + 16, millisekunde_1);
     EEPROM.write( count + 17, millisekunde_2);
     EEPROM.write( count + 18, '#');

     show = count;                                     // Platzierung merken
     count = count + 19;                               // Speicherstelle erhöhen
     // ************************************** Speicherstelle in EEPROM speicher ****************************
     val[3]=count % 10;                                 // aufteilen auf 3 stellen
     delay(10);
     val[2]=(count % 100)/ 10;
     delay(10);
     val[1]=(count % 1000) / 100;
     delay(10);



     EEPROM.write(1, val[1]);                            // speichern der 3 stellen
     delay(10);
     EEPROM.write(2, val[2]);
     delay(10);
     EEPROM.write(3, val[3]);
     delay(10);
     // ********************************************************************************************

     fertig_daten[ 10 ] = ';';                                               // Trennzeichen in Puffer ablegen
     fertig_daten[ 11 ] = stunde_1;                                          // Zeit in Übergabe-Array ablegen

     fertig_daten[ 12 ] = minute_1;
     fertig_daten[ 13 ] = minute_2;

     fertig_daten[ 14 ] = sekunde_1;
     fertig_daten[ 15 ] = sekunde_2;

     fertig_daten[ 16 ] = millisekunde_1;
     fertig_daten[ 17 ] = millisekunde_2;

     fertig_daten[ 18 ] = '#';                         // Abschlußzeichen in Puffer ablegen

     
     serial_out.print( (char*) fertig_daten);          // Datenübertragung an SK-System


     if (led_3_State == LOW) {
       //digitalWrite(led_3_Pin, HIGH);                                         // LED aneinschalten
       led_3_Millis = currentMillis;                                          // Zeitpunkt des Einschaltens von LED1
       led_3_State = HIGH;
     }
   }
 }




 //********************************************************************* Print chip
 if ( show != show_alt){                     // Nur neue Ausschrift, wenn neue Daten

   lcd.setCursor(0, 2);
   lcd.print("Platz ");

   if((show/19+1)<10){
     lcd.print("0");
   }
   lcd.print((show/19)+1);

   lcd.setCursor(8, 2);

   lcd.print(":");

   for(int b=0; b<=9;b++){
     lcd.write( EEPROM.read( show + b ) );
   }

   //********************************************************************* Print Memory

   lcd.setCursor(0, 3);
   lcd.print("Zeit: ");

   lcd.write( EEPROM.read( show + 11 ) );
   lcd.print(":");

   lcd.write( EEPROM.read( show + 12 ) );
   lcd.write( EEPROM.read( show + 13 ) );
   lcd.print(":");

   lcd.write( EEPROM.read( show + 14 ) );
   lcd.write( EEPROM.read( show + 15 ) );
   lcd.print(":");

   lcd.write( EEPROM.read( show + 16 ) );
   lcd.write( EEPROM.read( show + 17 ) );

   show_alt = show;                                              // Stelle merken, für Vergleich ob neue Daten da sind
 }

 //*********************************************************************  ==> MAIN END <==
 //*********************************************************************

}



pylon

Your serial_out connection has a baud rate of 2400. Sending of one byte needs about 4ms, during this time interrupts are disabled. The hardware of the 4 hardware serial interfaces can hold 1 Byte then an interrupt service routine has to copy that byte from the internal register to a buffer in the RAM. If this is not done until the next byte is completely received, that byte gets lost. During the 4ms of your SoftwareSerial transmission each of the 4 hardware serial interfaces can receive up to 4 characters, 3 of them are lost because the interrupt is disabled. Did you get the problem? Don't use SoftwareSerial in this setup!

Randam

okay, that makes sense.


could i solve the problem, if i would set the baud from my software serial up to 9600?
or should it be higher?

or doesnt it work at all, with the stuff i want to do?

pylon

Quote
could i solve the problem, if i would set the baud from my software serial up to 9600?
or should it be higher?


Driving the speed higher will not make you happy. The principal problem persists. You must eliminate the SoftwareSerial class.

I would give the AltSoftSerial library a try (http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html). It's fixed to two pins and it removes PWM from two pins but I guess in your case it's the most cost effective solution.

Randam

haha, thanks, it works now with the altSoftSerial.
thanks guys

Go Up