Forum: Mikrocontroller und Digitale Elektronik Arduinio Software Serial - wie synchronisiert man 2 Software Ports bei Datenempfang


von Tbd (ids2001)


Lesenswert?

Hallo Leute,

ich habe folgendes Problem.
Ich muss 2 Geräte auswerten ( Xbee, Kompass Modul ) welche im 
Sekundentakt Daten ( beide senden Ascii Strings mit CR am Ende ) senden.
Ich verwende die IDE 1.0.3.

Bei der Softwareserial Lib kann ja nur immer ein Port der aktive sein.
Deshalb setze ich diesen bevor ich ihn abhöre auf myPort.listen() aktiv. 
Jedoch ist hier das Problem gegeben, dass keine Daten wie beim Hardware 
Port gebuffert werden.
D.h es kann Datenverlust bestehen ?! oder?


Jetzt habe ich es so gelöst, dass ich wenn ich einen Port auf aktiv 
setze, diesen für eine bestimmte Zeit mit einer while Schleife für eine 
Sekunde lang abhöre bzw warte dass er aktiv wird, wenn nicht wird die 
Schleife abgebrochen. Dass ich nun nicht eine Sekunde unnötig warte, 
wenn die Daten schon empfangen wurden ( CR empfangen ), frage ich 
innerhalb der Schleife das CR Zeichen ab, und habe es in meiner 
Schleifenbedingung als Abbruch definiert.


Es funktioniert zwar, ich finde es aber nicht ganz so elegant.
Gibt es keine Möglichkeit, Daten zu buffern und somit kein unnötiges 
"Warten" in den Programmablauf einbauen zu müssen?

Oder wäre es in meinem Fall der beste Weg,auf externe Hardware UART 
Bausteine auszuweichen, falls diese Daten buffern können und dann 
einfach wieder mit der SoftwareSerial Lib den UART auslese?( keine 
Ahnung, eventl kann man die UARTs ja auch mit I2C auslesen.... )


hier mal einpaar Code Ausschnitte von meinem Sketch
1
void setup()
2
{
3
  Serial.begin(19200);
4
  Kompass.begin(19200);
5
  XBee.begin(19200);
6
  XBee.listen();
7
  Serial.println("Test Serial");
8
  XBee.println("Test XBee");
9
  Kompass.println("Test Kompass");
10
}
1
void loop()
2
{
3
  if(XBee.isListening())
4
    checkXbee();
5
  else
6
    Serial.println("Xbee not available");
7
    
8
  if(Kompass.isListening())
9
    checkKomp();
10
  else
11
    Serial.println("Kompass not available");
12
    
13
}
14
15
16
void checkXbee()
17
{
18
  long time = micros();
19
  boolean bCancle = false;
20
  while((micros()-time) < 1000000 && !bCancle)
21
  {
22
    // if(XBee.available()>0)
23
      // Serial.println("Lese ankommende Daten von XBee ein: ");
24
    while(XBee.available()>0&& !bCancle)
25
    {
26
      char c = XBee.read();
27
      Serial.write(c);
28
      if(c == '\r' || c == '\n')
29
      {
30
        bCancle =true;
31
        Serial.println("");
32
      }
33
    }
34
    Kompass.listen();
35
  }
36
}
37
38
39
void checkKompass() 
40
{
41
  long time = micros();
42
  boolean bCancle = false;
43
  while((micros()-time) < 1000000 && !bCancle)
44
  {
45
    // if(Scada.available()>0)
46
      // Serial.println("Lese ankommende Daten von Kompass ein: ");
47
    while(Kompass.available()>0 && !bCancle)
48
    {  
49
      char c = Kompass.read();
50
      Serial.write(c);
51
      if(c == '\r' || c == '\n')
52
      {
53
        bCancle =true;
54
        Serial.println("");
55
      }
56
    }
57
  }
58
  XBee.listen();
59
60
}

Der Output im Terminal sieht so aus.
1
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
2
1213,,,,,,,,,,
3
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
4
1213,,,,,,,,,,
5
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
6
1213,,,,,,,,,,
7
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
8
1213,,,,,,,,,,
9
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
10
1213,,,,,,,,,,
11
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
12
1213,,,,,,,,,,
13
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
14
1213,,,,,,,,,,
15
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
16
1213,,,,,,,,,,
17
H,1,1,1637604,4786467,24410,6,53,4985,124578,no Error
18
1213,,,,,,,,,,


Der String beginnend mit "H" kommt vom Xbee und die untere Zeile kommt 
vom Kompass ( bitte die vielen ,,,, wegdenken - da dieser String von 
einem externen selbstgeschriebenen C# Simulator stammt, mit dem ich mir 
GPS Strings zusammenbastle ..... )


Ich wäre euch sehr dankbar, wenn ihr mir hier tolle Tipps und Hilfe 
geben könnts.

lg
Dieter

von Stefan (Gast)


Lesenswert?

An welche Ports hast Du die beiden Sensoren angeschlossen? Sind das 
beides UART's?

Wenn die Arduino Libraries nicht ausrecihen oder Du mit ihnen nicht klar 
kommst, hindert Dich niemand daran (back to the roots) selbst zu 
programmieren.

IMHO verleitet das Arduino System dazu, die Beschäftigung mit den 
Grundlagen zu überspringen, was schnell in Sackgassen führt.

Hier gibt es viele Leute, die einiges mit AVR Mikrocontrollern gemacht 
haben. Aber Arduino spezifische Fragen bleiben sehr oft unbeantwortet. 
Trenne Dich von den Arduino Libraries, dann kommst Du besser voran.

von EGS (Gast)


Lesenswert?

@ Stefan:

um die Arduino Libs kommt er nicht herum, er kann diese aber erweitern 
oder eine eigene schreiben.

In diesem Fall geht er dann aber nicht back to the roots sondern muss 
sich dann wieder mit der HW-nahen Programmierung auseinander setzen.

b2t:

Wenn die Lib keinen Buffer vorsieht, gibt es keinen. Die richtige 
serielle Schnittstelle, hat ja die Serial.Available Funktion, die prüft 
ob Daten empfangen werden und diese dann in einen Buffer schreibt.

Hast du die SoftwareSerial oder die NewSoftwareSerial Lib?

von Tbd (ids2001)


Lesenswert?

EGS schrieb:
> Hast du die SoftwareSerial oder die NewSoftwareSerial Lib?

Hi,

ich verwende die Arduino 1.0.3 und dort ist die SoftwareSerial enthalten 
von arduiniana.org. ( ehem NewSoftSerial )

News: NewSoftSerial is in the core!  Starting with Arduino 1.0 
(December, 2011), NewSoftSerial has replaced the old SoftwareSerial 
library as the officially supported software serial library.  This means 
that if you have 1.0 or later, you should not download this library.  To 
port your code to 1.0, simply change all NewSoftSerial references to 
SoftwareSerial.



lg

Dieter

@Stefan: die beiden Sensoren habe ich nicht an UARTS angeschlossen, weil 
ansonsten würde ich nicht einen SoftwareUART verwenden.

von Peter D. (peda)


Lesenswert?

Dieter Sch schrieb:
> Bei der Softwareserial Lib

Was erwartest Du bei einer Nachbildung in SW?
Der AVR ist damit zu 100% ausgelastet.

Nimm 2 HW-Uarts.
Oder eine HW-UART und eine SW-UART über ICP und Timer.

von Tbd (ids2001)


Lesenswert?

Peter Dannegger schrieb:
> Nimm 2 HW-Uarts.

welche kannst du mir empfehlen?

Wieso ich die SoftwareSerial Lib verwenden will - na ganz einfach um zu 
sehen ob es meinen Anforderungen entspricht, wenn nicht muss ich mich um 
was neues umsehen.... wie zb zusätzliche HW Uarts.

Kennst du Projekte wo mit Arduinos auf externe HW Uarts zugegriffen 
wird?

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

16C552
16C752 (hat größeren FIFO)

gibt es von vielen Firmen. (16Cx54 = Quad UART)

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Alternativ: Nimm einen STM32 der hat schon bis zu 8 UARTS drin. Der 
STM32F407 hat 6.

von Tbd (ids2001)


Lesenswert?

ich kenne mich mit externen HardwareUart Bausteinen nicht so aus.
Eine kurze Frage.

Buffert der die Daten auch?

D.h ich könnte dann sequenziell die einzelnen Uarts am Baustein 
nacheinander abfragen?

von Peter D. (peda)


Lesenswert?

Dieter Sch schrieb:
> Kennst du Projekte wo mit Arduinos auf externe HW Uarts zugegriffen
> wird?

Was gefällt Dir an den internen UARTs nicht?
Z.B. der ATmega164 hat 2 UARTs, der ATmega2560 hat 4 UARTs.

Externe UARTs sind sehr teuer.
Da kann man besser einen ATtiny2313 als UART programmieren und per I2C 
anbinden. Und da der nichts weiter zu tun hat, ginge noch ne 2. UART in 
SW per T1 mit ICP.

von Karl (Gast)


Lesenswert?

Peter Dannegger schrieb:
> der ATmega2560 hat 4 UARTs

Und den gibt's auchn och als Arduino Mega.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.