Forum: Mikrocontroller und Digitale Elektronik Arduino frage zu Serial.print


von Bert S. (kautschuck)


Lesenswert?

Hi,

Was passiert eigentlich, wenn ich einen Arduino Uno extern versorge und 
trotzdem Serial.print() verwende, ohne angeschlossenes Serial Interface? 
Der Arduino verwendet ja den Interrupt zum senden und somit werden die 
Daten alle in einen Buffer geschrieben. Ist dies überhaupt ein Ring 
Buffer, oder was passiert wenn dieser voll ist? Ich habe nämlich ein 
Problem mit einem Arduino Uno, der sich nach etwa 3 Wochen aufhängt, 
wobei ich festgestellt habe, dass ich ein Serial.print("...") vergessen 
habe, wo aber nur ein paar mal am Tag aufgerufen wird.

: Bearbeitet durch User
Beitrag #5415357 wurde von einem Moderator gelöscht.
von yesitsme (Gast)


Lesenswert?

Die Serielle Schnittstelle hat keine Empfangsquitierung. Dein 
Serial.print() sollte ungehört verhallen und sich nichts irgendwo 
ansammeln.

von Dr. Sommer (Gast)


Lesenswert?

yesitsme schrieb:
> Die Serielle Schnittstelle hat keine Empfangsquitierung. Dein
> Serial.print() sollte ungehört verhallen und sich nichts irgendwo
> ansammeln.

Gilt aber nur wenn das keine USB-Serielle ist, also USBSerial oder wie 
das hieß. Die wartet sehr wohl auf Bestätigung/Abholung...

P.Loetmichel schrieb im Beitrag #5415357:
> Ich würde ja BASCOM nehmen.
Schön für dich; es gibt Leute die können nicht nur solche Baby-Sprachen.

> Da funktioniert die serielle immer!
Das hat nichts mit der Programmiersprache zu tun.

von c-hater (Gast)


Lesenswert?

Bert S. schrieb:

> Was passiert eigentlich, wenn ich einen Arduino Uno extern versorge und
> trotzdem Serial.print() verwende, ohne angeschlossenes Serial Interface?

Vermutlich nix besonderes, die Daten werden einfach in's Nirvana 
gesendet, erscheinen also ganz normal am Ausgangspin, nur halt ohne, 
dass sich irgendwer dafür interessiert...

Irgendwas anderes käme überhaupt nur im Falle eines aktiven 
Handshake-Mechanismus in Frage.

von Christopher J. (christopher_j23)


Lesenswert?

Wenn der TX-Buffer voll ist, dann blockt HardwareSerial::write() (und 
damit auch Serial.print() ) so lange, bis genug Platz ist um die Daten 
in den Buffer zu schreiben. Für Details siehe auch 
https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp#L213


P.Loetmichel schrieb im Beitrag #5415357:
> Ich würde ja BASCOM nehmen.
>
> Da funktioniert die serielle immer!

Deine ständige Schleichwerbung für BASCOM ist mittlerweile einfach nur 
noch lächerlich.

von Bert S. (kautschuck)


Lesenswert?

Christopher J. schrieb:
> Wenn der TX-Buffer voll ist, dann blockt HardwareSerial::write() (und
> damit auch Serial.print() ) so lange, bis genug Platz ist um die Daten
> in den Buffer zu schreiben. Für Details siehe auch
> 
https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/HardwareSerial.cpp#L213

Dr. Sommer schrieb:
> Gilt aber nur wenn das keine USB-Serielle ist, also USBSerial oder wie
> das hieß. Die wartet sehr wohl auf Bestätigung/Abholung...

Ok, danke, dann liegt das in der Tat daran, dass ich auf die USB-Serial 
schreibe.

: Bearbeitet durch User
von yesitsme (Gast)


Lesenswert?

Dr. Sommer schrieb:
> also USBSerial

Hat der Arduino Uno das?

von DAVID B. (bastler-david)


Lesenswert?

meine Erfahrungen sind so das es egal ist ob was angeschlossen ist oder 
nicht.
Da es keinen warte befehl gibt.
Der arduino sendet es einfach egal ob die gegen stelle bereit ist oder 
nicht.
ich frage zb mit einen 2560 alle 40 ms eine Spannung ab und sende sie an 
einen PC.
Und das auch mal 10 stunden lang.
Es spielt dabei aber keine rolle ob der PC läuft oder nicht die Daten 
werden gesendet und fertig.

von Frank (Gast)


Lesenswert?


von Einer K. (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Gilt aber nur wenn das keine USB-Serielle ist, also USBSerial oder wie
> das hieß. Die wartet sehr wohl auf Bestätigung/Abholung...
Nicht soweit mir bekannt....

Oder anders gesagt:
Meine tun das nicht.
Und ich werde ihnen auch nicht sagen, dass sie es tun sollen.

Die gesendeten Daten landen im Nirvana!
So wie beim 328P, als auch beim 32U4

Wenn man sie nicht im Nirvana haben möchte, sollte man (beim 32U4) eine 
Blockade einführen.

while(!Serial);
Blockiert den 32U4 solange, bis vom PC ein Port geöffnet wird.

von Einer K. (Gast)


Lesenswert?

Frank schrieb:
> Nein. Ein Fdti an RX-TX:
> https://www.arduino.cc/en/uploads/Main/arduino-uno-schematic.pdf

Nöö..
Ein ATMega16U2. (oder ganz alt, ein 8U2)
Es gibt einige UNO kompatible mit anderen Serial Wandlern.
Aber mit FTDI ist mir keiner bekannt.

von Michael U. (amiga)


Lesenswert?

Hallo,

es ist egal was man da sendet, der AVR schiebt es ben zum TX raus und 
damit ist das Thema für ihn erledigt. Hier laufen auch Sachen, wo ich 
einfach vergessen habe, meine Debug-Ausgaben abzuschalten und da wird 
dann noch einges mehr an Daten ins Nichts geschickt. Die Ausgaben 
bremsen natürlich den Programmablauf etwas, wenn sie erfolgen. Da ich 
allerdings die Serielle ohnehin immer auf 115200 setze ist auch die 
Wartezeit auf Platz im seriellen Buffer gering falls es mal mehr als die 
64 Byte Buffer sind.

Solche Aufhänger sehen immer nach knapp werdendem Ram aus oder falscher 
Arraygröße, wo nur selten über die Grenze geschrieben wird, oder...

Gruß aus Berlin
Michael

: Bearbeitet durch User
von Manfred (Gast)


Lesenswert?

Bert S. schrieb:
> Was passiert eigentlich, wenn ich einen Arduino Uno extern versorge und
> trotzdem Serial.print() verwende, ohne angeschlossenes Serial Interface?

Man sieht die Tx-LED flackern, weiter nichts, es läuft einfach.

Gedanken habe ich mir gemacht, einen ProMini möglichst schnell wieder 
schlafen zu legen, da frage ich einen Pin ab (Brückenstecker) und sende 
nur, wenn dieser auf "Debugmode" gesteckt ist.

Arduino F. schrieb:
> Ein ATMega16U2. (oder ganz alt, ein 8U2)
> Es gibt einige UNO kompatible mit anderen Serial Wandlern.
> Aber mit FTDI ist mir keiner bekannt.

Natürlich nicht, weil FTDI unverschämte Preise nimmt und sich damit der 
ChinUNO preislich verdreifachen würde. Mit FTDI ist mir nur der 
Gravitech-Nano bekannt, den ich nicht bereit bin, zu bezahlen.

von P.Loetmichel (Gast)


Lesenswert?

Mit BASCOM täte es auch ein ganz normaler ATMEGA8!

von Joschua K. (cimera)


Lesenswert?

Hast du vielleicht irgendwas im Code wie:

//mach alle paar Millisekunden irgendwas
if (millis() > last + x){
   //mach irgendwas
   last = millis();
}

Das kann beim Überlauf von millis() (etwa nach 50 Tagen) dazu führen das 
der Code im if-Statement nicht mehr ausgeführt wird. Falls du dann noch 
für dein millis in einem long statt unsigned long zwischenspeicherst 
o.Ä. würde das sogar mit deinen drei Wochen etwa hinkommen.

Das Problem wird auch hier beschrieben: 
https://forum.arduino.cc/index.php?topic=285280.0

Lösung:
if (millis() - last > x)

: Bearbeitet durch User
von Wolfgang (Gast)


Lesenswert?

Bert S. schrieb:
> Ist dies überhaupt ein Ring Buffer, oder was passiert
> wenn dieser voll ist? Ich habe nämlich ein Problem mit
> einem Arduino Uno, der sich nach etwa 3 Wochen aufhängt,
> wobei ich festgestellt habe, dass ich ein Serial.print("...")
> vergessen habe, wo aber nur ein paar mal am Tag aufgerufen wird.

Warum sollte ein Buffer voll laufen. Solange die 
Schnittstellengeschwindigkeit höher als deine mittlere Datenrate ist, 
klötern die Bits schneller am TX raus, als du sie rein schreibst. Der 
ATmega328 des Arduino Uno weiss nicht, was hinter seinem TX Ausgang 
kommt und ob sich jemand für die gesendeten Inhalte interessiert. Guck 
mal mit einem Oszi/LA auf TX (DIO1). Da kommen die Bits rausgepurzelt, 
egal wie du den Uno versorgst.
https://www.arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf

von Dr. Sommer (Gast)


Lesenswert?

Arduino F. schrieb:
> Nicht soweit mir bekannt....

Kann sein dass sich meine Erinnerung hier auf die STM32 Arduino 
Implementation bezieht... Es ist natürlich schon so dass ein Controller 
der direkt an die "echte" USB Schnittstelle angeschlossen ist merkt wenn 
Daten vom USB aus abgefragt werden. Ob er bei Nicht-Abfragen blockiert 
oder Daten löscht ist eine Implementations Frage...

von Bert S. (kautschuck)


Lesenswert?

Joschua K. schrieb:
> Hast du vielleicht irgendwas im Code wie:
>
> //mach alle paar Millisekunden irgendwas
> if (millis() > last + x){
>    //mach irgendwas
>    last = millis();
> }
>
> Das kann beim Überlauf von millis() (etwa nach 50 Tagen) dazu führen das
> der Code im if-Statement nicht mehr ausgeführt wird. Falls du dann noch
> für dein millis in einem long statt unsigned long zwischenspeicherst
> o.Ä. würde das sogar mit deinen drei Wochen etwa hinkommen.
>
> Das Problem wird auch hier beschrieben:
> https://forum.arduino.cc/index.php?topic=285280.0
>
> Lösung:
> if (millis() - last > x)

Sehr gut das du das erwähnst. Ich verwende eine Timer library namens 
"TimerObject.h".

https://playground.arduino.cc/Code/ArduinoTimerObject

Im Code ist da sehr viel mit millis():
1
#include "TimerObject.h"
2
3
TimerObject::TimerObject(unsigned long int ms){
4
  Create(ms, NULL, false);
5
}
6
7
TimerObject::TimerObject(unsigned long int ms, CallBackType callback){
8
  Create(ms, callback, false);
9
}
10
11
TimerObject::TimerObject(unsigned long int ms, CallBackType callback, bool isSingle){
12
  Create(ms, callback, isSingle);
13
}
14
15
void TimerObject::Create(unsigned long int ms, CallBackType callback, bool isSingle){
16
  setInterval(ms);
17
  setEnabled(false);
18
  setSingleShot(isSingle);
19
  setOnTimer(callback);
20
  LastTime = 0;
21
}
22
23
void TimerObject::setInterval(unsigned long int ms){
24
  msInterval = (ms > 0) ? ms : 0;
25
}
26
27
void TimerObject::setEnabled(bool Enabled){
28
  blEnabled = Enabled;
29
}
30
31
void TimerObject::setSingleShot(bool isSingle){
32
  blSingleShot = isSingle;
33
}
34
35
void TimerObject::setOnTimer(CallBackType callback){
36
  onRun = callback;
37
}
38
39
void TimerObject::Start(){
40
  LastTime = millis();
41
  setEnabled(true);
42
}
43
44
void TimerObject::Resume(){
45
  LastTime = millis() - DiffTime;
46
  setEnabled(true);
47
}
48
49
void TimerObject::Stop(){
50
  setEnabled(false);
51
52
}
53
54
void TimerObject::Pause(){
55
  DiffTime = millis() - LastTime;
56
  setEnabled(false);
57
58
}
59
60
void TimerObject::Update(){
61
  if(Tick())
62
    onRun();
63
}
64
65
bool TimerObject::Tick(){
66
  if(!blEnabled)
67
    return false;
68
  if(LastTime > millis()*2)//millis restarted
69
    LastTime = 0;
70
  if ((unsigned long int)(millis() - LastTime) >= msInterval) {
71
    LastTime = millis();
72
    if(isSingleShot())
73
      setEnabled(false);
74
      return true;
75
  }
76
  return false;
77
}
78
79
80
unsigned long int TimerObject::getInterval(){
81
  return msInterval;
82
}
83
84
unsigned long int TimerObject::getCurrentTime(){
85
  return (unsigned long int)(millis() - LastTime);
86
}
87
CallBackType TimerObject::getOnTimerCallback(){
88
  return onRun;
89
}
90
91
bool TimerObject::isEnabled(){
92
  return blEnabled;
93
}
94
95
bool TimerObject::isSingleShot(){
96
  return blSingleShot;
97
}

von Einer K. (Gast)


Lesenswert?

Soweit ich das auf die schnelle überblicken kann, sollte die Timer 
Klasse funktionieren.
Du verwendest eine veraltetete Version.
Aber auch das ist kein Drama.

Mir gefallen die "unsigned long" da nicht.
Das ist für AVR, angemessen, aber auf 32 Bit Modellen dürfte das dann 
unnötiger Weise 64 Bit nutzen.


Schlussendlich, dürfte die Klasse ok sein.
Und nicht deinen Fehler verursachen.

Die Serielle Ausgabe ist nicht dein Problem.

---------
Auch wenn du es nicht hören möchtest:
Aus meiner Sicht hast du ein anderes Problem im Code!

von Christopher J. (christopher_j23)


Lesenswert?

Arduino F. schrieb:
> Auch wenn du es nicht hören möchtest:
> Aus meiner Sicht hast du ein anderes Problem im Code!

Sehe ich genauso. Drei Wochen sind auch deutlich weniger als 49 Tage. Da 
ist was anderes Faul.

von Dr. Sommer (Gast)


Lesenswert?

Arduino F. schrieb:
> Mir gefallen die "unsigned long" da nicht.
> Das ist für AVR, angemessen, aber auf 32 Bit Modellen dürfte das dann
> unnötiger Weise 64 Bit nutzen.

long ist auf den meisten Plattformen 32 bit... So ein Ratespiel 
vermeidet man durch Nutzung von uint32_t & Konsorten.

von Bratarrat (Gast)


Angehängte Dateien:

Lesenswert?

Hatte mir die tage das zurecht Geklöppelt.

Zwar nicht schön, aber erfüllt seinen Zweck. Wenn D2 nicht mit GND 
gebrückt, gibt es keine/kaum Serielle Ausgabe.

von Stefan F. (Gast)


Lesenswert?

> Mir gefallen die "unsigned long" da nicht.
> Das ist für AVR, angemessen, aber auf 32 Bit Modellen dürfte das
> dann unnötiger Weise 64 Bit nutzen.

Zumindest beim ARM ist unsigned long ebenfalls 32bit.

von Stefan F. (Gast)


Lesenswert?

> Wenn D2 nicht mit GND gebrückt, gibt es keine/kaum Serielle Ausgabe.

Für solche Zwecke benutze ich manchmal einen Jumper, den ich mitten auf 
den 6 Poligen ISP Anschluss stecke.

von Manfred (Gast)


Lesenswert?

Stefanus F. schrieb:
>> Wenn D2 nicht mit GND gebrückt, gibt es keine/kaum Serielle Ausgabe.
>
> Für solche Zwecke benutze ich manchmal einen Jumper, den ich mitten auf
> den 6 Poligen ISP Anschluss stecke.

Und wozu? Ich habe mindestens drei Anwendungen, wo serial.print aktiv, 
aber nichts angeschlossen ist, es passiert genau garnichts!

Ich teile diese Ansicht:
yesitsme schrieb:
> sollte ungehört verhallen

Ich habe eine Anwendung mit dem ProMini, wo ich Strom sparen will, da 
gibt es einen Brückenstecker (aka Jumper) "debug". Diesen frage ich ab 
und gebe nur serielle Daten aus, wenn er gesetzt ist, damit ich im 
Regelbetrieb schnell wieder in den Schlaf komme.

von Stefan F. (Gast)


Lesenswert?

> Und wozu?

Um die Zeit zu sparen, die Debug Ausgaben kosten. Wenn das für die 
Anwendung irrelevant ist, dann braucht man natürlich auch keinen Jumper.

> Ich habe eine Anwendung mit dem ProMini, wo ich Strom sparen will, da
> gibt es einen Brückenstecker (aka Jumper) "debug". Diesen frage ich ab
> und gebe nur serielle Daten aus, wenn er gesetzt ist, damit ich im
> Regelbetrieb schnell wieder in den Schlaf komme.

Das wäre mein Grund Nr 2 gewesen. Ich bin verwirrt, das du nach einem 
Grund gefragt hast und direkt danach selbst einen geliefert hast. Irgend 
etwas muss ich da missverstanden haben.

von Stefan F. (Gast)


Lesenswert?

Bei meinem indischen Motorrad hat sich der Hersteller was interessantes 
ausgedacht:
1
Tx o---[===]---------o-+
2
                       |
3
Gnd o----------------o-+

Und zwar hat es einen seriellen Ausgang, wo man eine LED anschließen 
kann. Diese gibt dann allerlei Diagnose-Infos als eine Art Morsecode 
aus. Fahren kann man in diesem Zustand nicht.

Im Fahrbetrieb zieht man die LED ab und steckt einen Brückenstecker auf. 
Dadurch wird die Ausgabe der Diagnosemeldungen deaktiviert.

von npn (Gast)


Lesenswert?

Stefanus F. schrieb:
> Bei meinem indischen Motorrad hat sich der Hersteller was
> interessantes
> ausgedacht:Tx o---[===]---------o-+
>                        |
> Gnd o----------------o-+
>
> Und zwar hat es einen seriellen Ausgang, wo man eine LED anschließen
> kann. Diese gibt dann allerlei Diagnose-Infos als eine Art Morsecode
> aus. Fahren kann man in diesem Zustand nicht.
>
> Im Fahrbetrieb zieht man die LED ab und steckt einen Brückenstecker auf.
> Dadurch wird die Ausgabe der Diagnosemeldungen deaktiviert.

Und der Kurzschluss von TX nach GND stört nicht?

von npn (Gast)


Lesenswert?

npn schrieb:
> Und der Kurzschluss von TX nach GND stört nicht?

Ich seh gerade, das ist wohl ein Widerstand in der TX-Leitung?
Dann hat sich meine Frage erledigt. Sorry :-)

von Eric B. (beric)


Lesenswert?

Stefanus F. schrieb:
>> Und wozu?
>
> Um die Zeit zu sparen, die Debug Ausgaben kosten.

Wozu? Für gesparte Clockticks gibt's kein Geld zurück ;-)

von Stefan F. (Gast)


Lesenswert?

> Wozu? Für gesparte Clockticks gibt's kein Geld zurück

Wie gesagt, der Motor meines Motorrades kann zum Beispiel nicht laufen, 
wenn diese Debug Meldungen des Steuermoduls aktiviert sind.

Wenn die Ausgaben in der konkreten Anwendung nicht stören, würde ich 
auch auf eine Deaktivierung verzichten.

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.