Go Down

Topic: SerialEvent() & Serial.read() mehr als 64Bytes (Read 896 times) previous topic - next topic

arduinofish

Hallo,

gibt es eine Möglichkeit über die Console mehr 64Bytes einzulesen, wenn man serialEvent() benutzt?


Danke
Peter

uwefed

So wie ich die Funktion SerialEvent() verstanden habe ist das eine Interruptfunktion die auf den eingang von daten auf der seriellen Schnittstelle reagiert. In dieser Funktion kannst Du dann die Daten aus der seriellen Schnittstelle auslesen. So ergibt sich nie das Problem des Bufferüberlaufs des Eingangsbuffers.

Grüße Uwe

arduinofish

Sorry, mein Fehler. Es ging um Serial.available() (im Zusammenhang mit SerialEvent)
das kann halt nur 64Byte lesen. Ich bräuchte es aber so, dass ich ca 300 Bytes einlesen kann.

uwefed

Nach meiner Erklärung verstehe ich Deine Frage nicht.
Grüße Uwe

arduinofish

Das Problem ist das Serial.available() nur die ersten 64 Byte einer Konsoleneingabe lesen kann.
Für meine Zwecke sollten es aber deutlich mehr sein,..300 ca.


Ich habe folgenden Code:


Code: [Select]

String inputString = "";         // a string to hold incoming data
boolean stringComplete = false;  // whether the string is complete


void setup()
{
  inputString.reserve(800);
  Serial.begin(38400);
  setupBlueToothConnection();

}

void loop()
{
  if (stringComplete) {
    Serial.println(inputString);
    // clear the string:
    inputString = "";
    stringComplete = false;
  }
}

void setupBlueToothConnection()
{
  Serial.print("Setting up Bluetooth link");
  Serial2.begin(38400);
  delay(1000);
  sendBlueToothCommand("\r\n+STWMOD=0\r\n");
  sendBlueToothCommand("\r\n+STNA=modem\r\n");
  sendBlueToothCommand("\r\n+STAUTO=0\r\n");
  sendBlueToothCommand("\r\n+STOAUT=1\r\n");
  sendBlueToothCommand("\r\n+STPIN=0000\r\n");
  delay(2000); // This delay is required.
  Serial2.print("\r\n+INQ=1\r\n");
  delay(2000); // This delay is required.
  Serial.print("Setup complete");

}

void sendBlueToothCommand(char command[])
{
  char a;
  Serial2.print(command);
}

void serialEvent2() {
  while (Serial2.available()) {
    // get the new byte:
    char inChar = (char)Serial2.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline, set a flag
    // so the main loop can do something about it:
    if (inChar == ';') {
      stringComplete = true;
      //Serial.println(inputString);
    }
  }
}

madworm

#5
May 22, 2012, 11:35 pm Last Edit: May 22, 2012, 11:58 pm by madworm Reason: 1
Wo ist das problem?

Der input buffer der seriellen ports sollte eigentlich nur ein kleiner zwischenspeicher sein, so dass kein datenverlust auftritt wenn die daten nicht _sofort_ aus dem datenregister ausgelesen UND verarbeitet werden koennen. Das kopieren erledigt ein interrupt. Er ist nicht dafuer gedacht ein komplettes datenpacket fuer die _bearbeitung_ vorzuhalten.

In der regel ist die verarbeitungsgeschwindigkeit wesentlich hoeher als der eingehende datenstrom. Daher ist es ueberhaupt kein problem daten aus dem seriellen buffer in einen 2ten groesseren buffer zu kopieren. Sobald der dann voll ist kann er bearbeitet werden.

Also:

* daten im seriellen buffer ? --> in den grossen hineinkopieren (array) und index hochzaehlen
* bearbeitungsbuffer voll ? --> auswerten

Es ist auch sinnvol den begin und das ende eines datenpaketes durch geeignete marker erkennbar zu machen.

---

Noch etwas zu SerialEvent()...

Wenn man sich die 'main.cpp' anschaut, dann sieht das so aus:

Code: [Select]
int main(void)
{
        init();
#if defined(USBCON)
        USBDevice.attach();
#endif
        setup();
        for (;;) {
                loop();
                if (serialEventRun) serialEventRun();
        }
        return 0;
}


und in 'HardwareSerial.cpp'

Code: [Select]
void serialEventRun(void)
{
#ifdef serialEvent_implemented
  if (Serial.available()) serialEvent();
#endif
#ifdef serialEvent1_implemented
  if (Serial1.available()) serialEvent1();
#endif
#ifdef serialEvent2_implemented
  if (Serial2.available()) serialEvent2();
#endif
#ifdef serialEvent3_implemented
  if (Serial3.available()) serialEvent3();
#endif
}


Durch etwas linker-trickserei ist das so hingebogen, dass es nur ausgefuehrt wird, wenn die funtion auch vom benutzer implementiert worden ist. Sonst wird das wegoptimiert. Interrupts spielen da nicht hinein. Es wird somit erzwungen, dass nach der normalen loop() auch 1x diese funktion aufgerufen wird. Persoenlich finde ich das konstrukt unnoetig.

Das ganze ist 100% aequivalent zu:

Code: [Select]
void loop(void) {
  // irgendwas start
  //
  // irgendwas ende

  if(Serial.available()) {
    // mach irgendwas anderes
  }
}



• Upload doesn't work? Do a loop-back test.
• There's absolutely NO excuse for not having an ISP!
• Your AVR needs a brain surgery? Use the online FUSE calculator.
My projects: RGB LED matrix, RGB LED ring, various ATtiny gadgets...
• Microsoft is not the answer. It is the question, and the answer is NO!

uwefed

madworm, könnte das Problem daher kommen, daß er mit Strings arbeitet und nicht mit char und einem Array?
Grüße Uwe

madworm

#7
May 23, 2012, 12:46 am Last Edit: May 23, 2012, 12:53 am by madworm Reason: 1
Auch moeglich ;-)

Wenn er

Code: [Select]
Serial.println(inputString.reserve(800));

verwendet, dann sollte als rueckgabewert eine "1" kommen, wenn es erfolgreich war. Ist der angeforderte platz zu gross, dann einen "0". Mit einem ATmega168 klappt es mit "800" jedenfalls nicht mehr. Da ein 328er 2k RAM hat, sollte das noch tun.
• Upload doesn't work? Do a loop-back test.
• There's absolutely NO excuse for not having an ISP!
• Your AVR needs a brain surgery? Use the online FUSE calculator.
My projects: RGB LED matrix, RGB LED ring, various ATtiny gadgets...
• Microsoft is not the answer. It is the question, and the answer is NO!

arduinofish

Vielen Dank, dass ihr für mich eure Nacht zum Tag gemacht habt :)
Ich habe einen Mega 2560, so sollten die 800 Zeichen kein Problem sein. Ich werde heute abend oder am Wochenende noch ein bisschen probieren und das Ergebnis mitteilen.



Go Up