Arduino frage zu Serial.print

#5415339
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.
Beitrag #5415357 wurde von einem Moderator gelöscht.
Gast #5415369
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.
Gast #5415378
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.
#5415385
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.
#5415387
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.
#5415416
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.
Gast #5415422
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.
#5415438
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
Gast #5415587
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.
#5415717
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)
Gast #5415731
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
Gast #5415740
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...
#5415796
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
}
Gast #5416016
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!
Gast #5506006
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.
Gast #5506222
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.
Gast #5506228
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.
Gast #5506283
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren