Forum: Mikrocontroller und Digitale Elektronik Daten für Thermodrucker aus Array korrupt?


von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich muss mit einem Arduino über SoftSerial einen Bon auf einem 
Kiosk-Thermodrucker ausgeben. Alle Textausgaben klappen problemlos, aber 
zuerst kommt ein Logo. Die Daten dafür liegen in einem Array of byte 
bzw. uint8_t im PROGMEM. Die Größe beträgt 2868 Bytes.

In zwei geschachtelten Loops (für 12 Zeilen zu je 239 Spalten) lese ich 
die Daten aus dem Array mit "pgm_read_byte(&logo[c])" und sende sie 
zeilenweise und mit der passenden ESC-Sequenz für den Grafikmode voran, 
zum Drucker. Da Softserial nur einen Puffer von 64 Bytes hat, mache ich 
zusätlich alle 32 Bytes eine Pause von 1000 Mikrosekunden (Drucker 
druckt mit 9600 Bit/s)...

Problem: Immer so ziemlich in der Mitte des Logos (was ja im Grafikmodus 
gedruckt wird), werden plötzlich anstelle des Grafikblocks für diese 
eine Zeile einige Buchstaben im Textmodus eingestreut, bevor der Rest 
des Logos wieder ordentlich gedruckt wird.

Das Argument für pgm_read_byte ist short, reicht also bis 32000, das 
kann es nicht sein. Gäbe es eine Größenbeschränkung für Arrays im 
PROGMEN, würde nach der "Störung" wohl nicht der Rest gedruckt ... was 
kann das sein?

Ich vermute noch einen Pufferüberlauf am Drucker, aber der gibt keine 
entsprechende Rückmeldung (XMODEM, kein XOFF).

Ideen, Tips? Danke.

: Bearbeitet durch User
von Bruno V. (bruno_v)


Lesenswert?

Frank E. schrieb:
> Da Softserial nur einen Puffer von 64 Bytes hat, mache ich
> zusätlich alle 32 Bytes eine Pause von 1000 Mikrosekunden (Drucker
> druckt mit 9600 Bit/s)...

Du sendest also 12 Zeilen je (239+n) Bytes, mit n ~ 3 oder so

Du sendest mit 9600 Baud (ist das so gemeint?), also ~1Byte pro ms. 
Zudem machst Du alle 32 Byte 1 ms Pause.

--> Der Funktionsaufruf muss damit "blockierend" sein, denn sonst hilft 
dir 1ms nicht wirklich.

Du sendest also 8 Blöcke pro Zeile, der letzte nur ~ 18 Byte.

--> ist sicher, dass die nächste Zeile korrekt neu beginnt? Oder gib es 
ein "Blockgrenzen" Problem?

--> Sind zwei Logos immer gleich kaputt? Oder "random"? Wenn immer 
gleich, finde die genau Position heraus (notfalls unter einer Lupe die 
Pixel auszählen).

: Bearbeitet durch User
von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Bruno V. schrieb:
> Frank E. schrieb:
>> Da Softserial nur einen Puffer von 64 Bytes hat, mache ich
>> zusätlich alle 32 Bytes eine Pause von 1000 Mikrosekunden (Drucker
>> druckt mit 9600 Bit/s)...
>
> Du sendest also 12 Zeilen je (239+n) Bytes, mit n ~ 3 oder so

ja, die ESC-Sequenz 27 '*' 3 239 0 kommt immer vorweg, dann folgen die 
239 Bytes

> Du sendest mit 9600 Baud (ist das so gemeint?), also ~1Byte pro ms.
> Zudem machst Du alle 32 Byte 1 ms Pause.
>
> --> Du sendest also 8 Blöcke pro Zeile, der letzte nur ~ 18 Byte.
ja, 239 (getestet mit der Bronbreite) ist leider eine Primzahl
>
> --> ist sicher, dass die nächste Zeile korrekt neu beginnt? Oder gib es
> ein "Blockgrenzen" Problem?

im Druckbild gibt es keine seitliche Verschiebung, ich verwende einen 
über alle Loops laufenden Zähler, der die Bytes im Array adressiert

> --> Sind zwei Logos immer gleich kaputt? Oder "random"? Wenn immer
> gleich, finde die genau Position heraus (notfalls unter einer Lupe die
> Pixel auszählen).

Ja, das Druckbild ist immer an der gleichen Stelle kaputt, es sind auch 
immer die gleichen Zeichen, und das im Textmodus.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich habe den Eindruck, dass der Drucker intern die Bilddaten komprimiert 
und bei zu vielen Details ins Stolpern kommt. Ich habe anstelle des 
Logos mal ein anderes Testbild erstellt (nur ein Rahmen mit einem Kreis 
und einige Zahlen), das wird problemlos ausgedruckt ...

Zur Erstellung des Soucecodes für das Progmem-Array verwende ich immer 
das gleiche Programm.

von Rahul D. (rahul)


Lesenswert?

Frank E. schrieb:
> Ideen, Tips? Danke.

Hast du mal testweise ein Hardware-UART verwendet?

von Harald K. (kirnbichler)


Lesenswert?

Frank E. schrieb:
> Da Softserial nur einen Puffer von 64 Bytes hat, mache ich
> zusätlich alle 32 Bytes eine Pause von 1000 Mikrosekunden (Drucker
> druckt mit 9600 Bit/s)...

Verlängere die Pause mal auf mehr als 32 Millisekunden ...

von Frank K. (fchk)


Lesenswert?

Frank E. schrieb:

> Ich vermute noch einen Pufferüberlauf am Drucker, aber der gibt keine
> entsprechende Rückmeldung (XMODEM, kein XOFF).
>
> Ideen, Tips? Danke.

1. Ist die Übertragung 8-bit clean? Heißt genau: kannst Du jeden 8 Bit 
Wert senden, und der wird vom Drucker auch korrekt interpretiert. Auch 
Nullbytes, XON (0x11), XOFF (0x13), CFR, LF etc? Hast Du das 
verifiziert?

2. Ist die Übertragung auf der Leitung fehlerfrei? Sind die Daten 
korrekt? Hast Du das mit einem Logicanalyzer verifiziert?

fchk

von Mario M. (thelonging)


Lesenswert?

Frank E. schrieb:
> Da Softserial nur einen Puffer von 64 Bytes hat, mache ich zusätlich
> alle 32 Bytes eine Pause

Der Puffer ist nur für den Empfang. Senden läuft ohne und ist immer 
blockierend.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Frank K. schrieb:
> Frank E. schrieb:
>
>> Ich vermute noch einen Pufferüberlauf am Drucker, aber der gibt keine
>> entsprechende Rückmeldung (XMODEM, kein XOFF).
>>
>> Ideen, Tips? Danke.
>
> 1. Ist die Übertragung 8-bit clean? Heißt genau: kannst Du jeden 8 Bit
> Wert senden, und der wird vom Drucker auch korrekt interpretiert. Auch
> Nullbytes, XON (0x11), XOFF (0x13), CFR, LF etc? Hast Du das
> verifiziert?

So lange der Drucker die im ESC-Befehl für den Grafikmodus angegebene 
Anzahl von Bytes nicht vollständig erhalten hat, ist er 8-bit-clean. Man 
muss schließlich jedes beliebige Bitmuster drucken können.

Ausserhalb des Grafikmodus reagiert er natürlich unterschiedlich auf 
Steuercodes. Das hab ich aber alles schon fertig, z.B. Font auswählen, 
Fett, Condensed, Vorschub, Rückzug, Abschneiden voll und halb ... läuft 
alles einwadfrei. Nur die Grafik macht Stress.

> 2. Ist die Übertragung auf der Leitung fehlerfrei? Sind die Daten
> korrekt? Hast Du das mit einem Logicanalyzer verifiziert?

Die Leitung vom Arduino Nano (5V!) zum Drucker ist ca. 30cm lang und 
führt über ein Max232-Modul (Breakout mit 9pol. Sub-D-Buchse) auf eine 
"echte" V24 am Drucker.

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Frank E. schrieb:

> Ich habe den Eindruck, dass der Drucker intern die Bilddaten komprimiert
> und bei zu vielen Details ins Stolpern kommt.

Wäre tatsächlich denkbar, dass er nicht genug Pufferspeicher hat, um das 
komplette Bild "raw" aufzubewahren, bis er es tatsächlich ausdrucken 
kann. Auch bei nur 9,6kBaud dürften die Daten weit schneller zu 
übertragen sein, als der Ducker sie ausdrucken kann.

Wenn es wirklich dieses Problem ist, dann liegt die Lösung klar auf der 
Hand: einfach langsamer senden. Also: zwar natürlich weiterhin mit 
9,6kBaud, aber dafür mit Pausen zwischen den einzelnen Bytes. Die Pausen 
erst mal sehr großzügig wählen und dann schrittweise verringern.

Mit diesem Ansatz kann man also auf jeden Fall erst mal herausfinden, ob 
das wirklich das Problem ist. Falls ja, kann man dann die Pausenlänge 
optimieren.

Falls nein, war es nicht dieses Problem.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Mario M. schrieb:
> Frank E. schrieb:
>> Da Softserial nur einen Puffer von 64 Bytes hat, mache ich zusätlich
>> alle 32 Bytes eine Pause
>
> Der Puffer ist nur für den Empfang. Senden läuft ohne und ist immer
> blockierend.

Das ist mir neu, wäre aber erfreulich, weil dann als Ursache 
auszuschließen.

Frage: Warum kennt SoftSerial dann die Methode "flash"? Laut Referenz 
wartet die (neuerdings), bis alle zu sendenden Bytes raus sind ... ?

von Mario M. (thelonging)


Lesenswert?

Frank E. schrieb:
> Frage: Warum kennt SoftSerial dann die Methode "flash"?

Welche Lib verwendest Du denn? Arduinos SoftwareSerial kennt kein 
"flush".

von Bruno V. (bruno_v)


Lesenswert?

Wie gehst Du mit Escapesequenzen in den Daten um?

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Mario M. schrieb:
> Arduinos SoftwareSerial kennt kein
> "flush".

Falsch...
Kennt es.
Macht zwar nix, aber kennt es.

https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SoftwareSerial/src/SoftwareSerial.cpp#L470

von Frank K. (fchk)


Lesenswert?

Frank E. schrieb:

>> 2. Ist die Übertragung auf der Leitung fehlerfrei? Sind die Daten
>> korrekt? Hast Du das mit einem Logicanalyzer verifiziert?
>
> Die Leitung vom Arduino Nano (5V!) zum Drucker ist ca. 30cm lang und
> führt über ein Max232-Modul (Breakout mit 9pol. Sub-D-Buchse) auf eine
> "echte" V24 am Drucker.

Und hast Du das messtechnisch verifiziert, dass da wirklich die Daten 
drüberlaufen, von denen Du glaubst, dass sie drüberlaufen? Ansonsten ist 
das alles nur Raterei.

Du kannst ja auch einen PC ans andere Ende hängen und die ankommenden 
Bytes mitprotokollieren und vergleichen. Und Du kannst die Daten auch 
vom PC an den Drucker schicken. Damit schließt Du den Arduino als 
Fehlerquelle aus.

fchk

von Harald K. (kirnbichler)


Lesenswert?

Schafft der Drucker es eigentlich, nach etwa 240 Millisekunden das 
Papier um eine ganze Zeile zu transportieren? Druckt das Ding vier 
(Graphik-) Zeilen pro Sekunde?

Wenn der Drucker ohne Handshake angesteuert wird, könnte bereits das 
ein Problem sein

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Harald K. schrieb:
> Schafft der Drucker es eigentlich, nach etwa 240 Millisekunden das
> Papier um eine ganze Zeile zu transportieren? Druckt das Ding vier
> (Graphik-) Zeilen pro Sekunde?
>
> Wenn der Drucker ohne Handshake angesteuert wird, könnte bereits das
> ein Problem sein

Ganz genau. Und wenn man zu doof/faul ist, das (vermutlich vorhandene 
Hardware-) Handshake zu benutzen, dann ist halt "Senden mit Pausen" 
angesagt.

von Harald K. (kirnbichler)


Lesenswert?

Ob S. schrieb:
> Und wenn man zu doof/faul ist

Versuch' das mal anders zu formulieren.

von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Harald K. schrieb:
> Ob S. schrieb:
>> Und wenn man zu doof/faul ist
>
> Versuch' das mal anders zu formulieren.

Mach' doch mal einen Vorschlag!

von Monk (roehrmond)


Lesenswert?

Ist das die Fortsetzung von deinem Problem von 2022?

Beitrag "Bondrucker mit Fehler im Druckbild"

Frank E. schrieb:
> Ich habe einfach nicht die Zeit, das Problem bis zur endgültigen Lösung
> zu lösen, muss erstmal so. Wird vermutlich niemandem ausser mir
> auffallen. Ist nicht schön, aber so ist das Leben ...

Scheiße schwimmt immer wieder hoch. Dieses mal solltest du dir die Zeit 
nehmen, das Problem vollständig zu analysieren, anstatt zu raten.

Ich plädiere immer noch dafür, die Stromversorgung zu kontrollieren.

: Bearbeitet durch User
von Ob S. (Firma: 1984now) (observer)


Lesenswert?

Monk schrieb:

> Ich plädiere immer noch dafür, die Stromversorgung zu kontrollieren.

Kontrolle kann natürlich nie schaden, aber meiner Meinung nach weist das 
beschriebene Fehlerbild kein bissel auf diesbezügliche Probleme hin.

von Bruno V. (bruno_v)


Lesenswert?

Frank E. schrieb:
> So lange der Drucker die im ESC-Befehl für den Grafikmodus angegebene
> Anzahl von Bytes nicht vollständig erhalten hat, ist er 8-bit-clean. Man
> muss schließlich jedes beliebige Bitmuster drucken können.

Es gibt keinen Code zum Abbrechen oder neu aufsetzen?

Prinzipiell kann man auch in Bitmuster Escapecodes einbauen. Mit einem 
speziellen Byte (z.B. 47), dass im Datenstrom verdoppelt wird, wenn es 
kein Escape-Code ist.

von Mario M. (thelonging)


Lesenswert?

Arduino F. schrieb:
> Mario M. schrieb:
>> Arduinos SoftwareSerial kennt kein
>> "flush".
>
> Falsch...
> Kennt es.
> Macht zwar nix, aber kennt es.

Gut, dann nehme ich meine Aussage zurück. Hatte in der Doku nichts 
gefunden.
https://docs.arduino.cc/learn/built-in-libraries/software-serial/

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.