PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Drucker mit AVR ansteuern?



CapSob
08.06.2006, 23:13
Hallo Leute!

Hab grad ein kleines Projekt im Kopf, folgendes:

Da ich in einer Firma arbeite, wo Laserdrucker der Firma Kyocera repariert werden und ich vor jeder Wartung einen kleines Test von Laptop aus auf den Drucker über die Parallele Schnittstelle schicken muss.

Ich starte erstmal den Laptop und (hab mir eine Dos-Batch-Datei geschrieben) schicke folgendes an den Drucker:

c:\>echo !R! STAT1; EXIT; > lpt1:

c:\>echo !R! FRPO I1, 1; EXIT; > lpt1:

c:\>echo !R! ELOG; EXIT; > lpt1:

So, da mir es irgendwie zu blöd ist, jedesmal den alten LAptop anzuwerfen, dachte ich mir, da es ja nur die Parallele Schnittstelle ist, sollte es doch relativ einfach sein mit einem uC (z.B. ATMega 8 ) die oben genannten "Daten" an den Drucker zu übertragen.

Hat da jemand schon irgendwie Erfahrung oder weiß jemand, wie ich die Parallele Schnittstelle eines Druckers ansteuere?

Pls Hlp!

cap.

izaseba
08.06.2006, 23:51
Hallo,
Ich habe es selber noch nicht gemacht, aber ich kenne da jemanden, der das gemacht hat,
schaue mal hier (http://www.mehto.roboterbastler.de/?Projekte:Drucker_ansteuern)
nach, vielleicht hilft es Dir

Gruß Sebastian

Vitis
09.06.2006, 09:10
Klar kannste das mit dem Mega8, Die Centronics
Schnittstelle des Druckers ist auch nur 8 Bit breit und
n paar kleine Zusätze

* Datenleitungen:
o Data0 (2) – Datenbit 0
o ...
o Data7 (9) – Datenbit 7
* Steuer- oder Handshake-Pins:
o Strobe (1) – zeigt dem Empfänger an, dass ein gültiges Datum anliegt
o Busy (11) – zeigt die Bereitschaft des Druckers zur Datenübernahme an
o Ack (10) – Acknowledge, Bestätigung der Datenübernahme durch den Drucker
* Melde-, Status- oder Kontrolleitungen:
o PE (12) – „Papierende“, zeigt an, dass kein Papier mehr vorhanden ist
o Select (13) – zeigt an, ob der Drucker On- oder Offline ist
o Autofeed (14) – veranlasst den Drucker, nach jedem Carriage-Return (CR) ein Line-Feed (LF) auszuführen
o Error (32) – zeigt das Auftreten eines Fehlers an
o Init (31) – veranlasst einen Drucker-Reset
o SelectIn (36) – teilt dem Drucker mit, dass er angesprochen wird

Die Datenübertragung erfolgt nach folgendem Protokoll:

1. Der Sender überprüft anhand der Busy-Leitung, ob der Empfänger bereit ist. Falls ja, wird das Datenbyte auf die Datenleitungen gelegt.
2. Durch Aktivierung des Strobe-Signals (mind. 1 bis max. 50 Mikrosekunden) wird dem Empfänger die Gültigkeit des Datums mitgeteilt.
3. Durch Aktivierung von Busy signalisiert der Empfänger, dass er mit der Verarbeitung der Daten beschäftigt ist.
4. Der erfolgreiche Empfang und Verarbeitung des Datenbytes wird vom Endgerät durch das Acknowledge-Signal bestätigt.


Wenn der Drucker unter DOS geht geht er auch unter AVR.
Knifflig wirds bei Druckern die selbst keinen Zeichensatz mehr haben
und nicht ohne Treiber laufen, also auch nicht unter DOS, die
bekommste nicht so einfach unter AVR in Gang

CapSob
11.07.2006, 13:46
Ok, danke erstmal an euch!

also brauch ich ja bloß 11 leitungen.

- 8 datenleitungen
- 1 busy zum abfragen
- 1 init zum initialisieren
- 1 strobe zum bestätigen

wie leg ich denn z.B. ein "!" an den PortD in bascom? muss ich es dann binär ausgeben, oder kann ich den kompletten "Text" anlegen?, so als eine art routine dass er nach jedem zeichen ein strobe setzt?

irgendwie einer eine ahnung, wie bissl quelltext aussehen kann?

mfg,
cap.

Mehto
11.07.2006, 13:58
Benutz doch einfach meine Assembler Routine, oder schau von der ab. Das ganze ist wirklich sehr einfach.



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Druck-Routinen ;;
;; ============ ;;
;; (c)Sven Lissel (svenlissel@web.de) ;;
;; www.Mehto.de.vu ;;
;; 23.07.2005 ;;
;; ;;
;; Parallel-Interface ;;
;; DB0-DB7: PD0-PD7 ;;
;; Strobe: PB0 ;;
;; Busy: PC1 ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Druck-Routine zum Drucken über ein Paralleles Kabel
;
; Achtung! Folgendes muss eingerichtet sein:

;-Stackpointer
;-PortD als Ausgang Pin0- Pin7
;-PortB als Ausgang Pin0- Pin1
;-PortC als Eingang Pin1

;Wenn der Drucker zum empfangen nicht bereit ist wird gewarten und Pin1
;an PortB wird auf high geschaltet.(Kann auch weggelassen werden)

;Register r16 und r17 werden verwendet. r17 wird aber gesichert und wieder hergestellt.

;Das zu druckende Zeichen (oder Befehl) in r16 laden und mit "rcall drucken" routine aufrufen.





;;;;;;;;;;;;;;;;;;;;;;Befehle;;;;;;;;;;;;;;;;;;

;;;;Initalisieren:
; Muss vor dem Drucken aufgerufen werden
; aufrufen mit: "rcall drucken_init"



;;;;;Erweiterter Grafiksatz aktivieren;;;;;
; kann aufgerufen werden um erweiterte Zeichen drucken zu können
; aufrufen mit: "rcall drucken_grafiksatz"



;;;;;Puffer Drucken;;;;;
; muss aufgerufen werden wenn die gesendeten zeichen gedruckt werden sollen
; aufrufen mit: "rcall drucken_puffer"



;;;;;Blatt ausgeben;;;;;
; Muss aufgerufen werden wenn das bedruckte Blatt ausgegeben werden soll.
; aufrufen mit: "rcall drucken_ausgeben"



;;;;;;Farbe aussuchen;;;
; Kann aufgerufen werden um die Textfarbe zu ändern
;
;;;;Farben:
;Farben werden mit Hex nummern angegeben
;
;0x00 Schwarz
;0x01 Magenta
;0x02 Cyan
;0x03 Violett
;0x04 Gelb
;0x05 Rot
;0x06 Grün

; Zuerst muss die ausgesuchte Farbe nach r17 geladen werden.
; z.B.: ldi r17, 0x02

;Und dann nur noch "rcall drucken_farben" aufrufen



;;;;;Neue zeile;;;;
;; geht in die nächste Zeile.
;; Aufrufen mit: "rcall drucken_zeile"



;;;;;;;Routine;;;;;;;

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Drucken ;;;;;;;;;;;;;
drucken:
push r17

;;;;;;;;;;;;;;;;
drucken_wait: ;warten is der Drucker bereit ist

sbi PortB, 1 ;LED anschalten um mitzuteilen das auf den Drucker gewartet wird

sbic PinC, 1
rjmp drucken_wait

cbi PortB, 1 ;LED wieder abschalten
;;;;;;;;;;;;;;;



out PORTD, r16 ;Daten an PortD anlegen

cbi PortB, 0 ;Daten an PortD übernehmen (fallende Flanke)

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Impulsdauer zum Daten übernehmen
;Mindestens 0,5 µs höchstens 50µs
;Bei 1Mhz r17=1 , bei 16 Mhz = 16 usw.

ldi r17, 2 ;bei 1Mhz r17=2 ca. 6µs

loop12:
dec r17
brne loop12
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

sbi PortB, 0 ;Daten an PortD übernehmen ende (high setzen)


pop r17
reti
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;; Initalisieren ;;;;;;;;
drucken_init:

ldi r16, 0x1B
rcall drucken

ldi r16, 0x40
rcall drucken

reti
;;;;;;;;;;;;;;;;;


;;;;;;;;;;;;;;;;;Erweiterter Grafiksatz aktivieren;;;;;;;;;;
drucken_grafiksatz:

ldi r16, 0x1b
rcall drucken
ldi r16, 0x36
rcall drucken

reti
;;;;;;;;;;;;;;;;;



;;;;;;;;;;;;;;Puffer Drucken;;;
drucken_puffer:

ldi r16, 0x0A
rcall drucken

reti
;;;;;;;;;;;;;;


;;;;;;;;;;;;;;Blatt ausgeben;;;
drucken_ausgeben:

ldi r16, 0x0c
rcall drucken

reti
;;;;;;;;;;;;;;



;;;;;;;;;;;;;;Farbe wechseln;;;
drucken_farbe:

ldi r16, 0x1B
rcall drucken

ldi r16, 0x72
rcall drucken

mov r16, r17
rcall drucken

reti
;;;;;;;;;;;;;;


;;;;;;;;;;;;; Neue zeile ;;;;;;;;;
drucken_zeile:

ldi r16, 0x0A ;Neue Zeile
rcall drucken

reti
;;;;;;;;;;;;;



Gruß,
Mehto

Vitis
11.07.2006, 15:48
Die kommunikation ist im Prinzip recht einfach.

Man nehme einen Port des AVR oder PIC, der 8 Bit hat.
Die Zeichen die Du sendest sind nix anderes als Binäre werte,
die 8 Bit lang sind, also Beispiel A = Dezimal 65, Binär
1000001. Woher ich das Weiß ?
Schau mal unter ASCII im Netz nach, da sind dann genau die
Codes aufgelistet.
Nun mußt Du nur och die Binärwerte der zu übertragenden Zeichen
an Deinen Port geben (der sollte als Ausgang definiert sein) und
dann den Strobe hochziehen, damit der Drucker weiß, aha hier
kommt ein neues Zeichen.
Beispiel:
STAT1; EXIT;
S = 83 = 1010011
T = 84 = 1010100
A = 65 = 1000001
T = 84 = 1010100
; = 59 = 0111011
etc. etc.

http://de.wikipedia.org/wiki/ASCII-Tabelle
1 entspricht dann Pin auf 5V, 0 entspricht Pin auf GND.

In Bascom würds in etwa so aussehen,
PortA=65 (für A)

Mehto
11.07.2006, 17:42
Das steht übrigens auch alles hier.....
http://www.mehto.roboterbastler.de/?Projekte:Drucker_ansteuern


Gruß,
Mehto

CapSob
11.07.2006, 17:54
Thx @ Vitis: Hört sich logisch an. Aber jedes zeichen einzeln übergeben ist halt schon ein bisschen stark aufwändig! muss mal mehtos-routine angucken.

Thx @ Mehto: Von deiner Seite hab ich die Infos zwecks Ansteuerung - schöne Seite! Die Assembler-File muss ich mir mal genauer anschauen - hab nicht wirklich Ahnung von ASM.


Hab mal meine kleine Projekt-Doku hinzugefügt. Mich würde es freuen, wenn íhr sie euch mal reinzieht, ob ich soweit alles richtig gemacht habe... thx.

mfg,
cap.

P.S.: Hardware steht schonmal. Jetzt gehts an coden!

Robby 8
11.07.2006, 17:58
hi
Sorry das ich hier jetzt von was ganz anderem rede ,aber bin neu hier un will en theme rein stellen ins Forum weis aber net wie ?
bitte um hilfe un danke im vorrau un noch ma sorry

PicNick
11.07.2006, 18:01
@Robby 8

Du gehst in die Forum-Übersicht, sucht ein Forum aus, und drückst auf "neues Thema"

Mehto
11.07.2006, 18:43
Ja, jedes Zeichen must du schon einzeln übertragen, glaub mir, das wäre besser als ein 128 bit Datenbus....
Aber das programmiert man sich einfach so das man einen String einfach nach und nach überträgt...

Bis jetzt schöne Doku, nur würde ich den Text von meine Seite nicht eins zu eins rein kopieren, änder ihn irgend wie noch ein wenig ab, so das man ihn nicht sofort wieder erkennt.

Wenn jemand dann mal auf meine Seite stoßen sollte und sich dann wieder an den Text erinnert macht sich das nicht so gut ;-)
Sonst denkt jemand womöglich noch ich hätte den Text auch schon irgendwo her kopiert, dabei hab ich mir so viel Mühe gegeben... 8-[
Veruche daher den Text bitte nochmal in eigene Worte zu fassen.


Gruß,
Mehto

CapSob
11.07.2006, 19:11
Ok, schade eigentlich. Muss ich halt jedes Zeichen einzeln übergeben... *heul*

@Mehto: Würde es dir was ausmachen, wenn ich deine Homepage als Quelle angebe, sodass ich den Text stehen lassen kann? Ich weiß schon, wieviel arbeit eine eigene Homepage ist... ;)

mfg,
cap.

Mehto
11.07.2006, 19:18
Ok, schade eigentlich. Muss ich halt jedes Zeichen einzeln übergeben... *heul*
Das ist doch selbst in Assembler kein Problem, und in Bascom dann doch drei mal nicht ;-)
Guck dir mal das an: (in Assembler)
http://www.mikrocontroller.net/tutorial/memory



@Mehto: Würde es dir was ausmachen, wenn ich deine Homepage als Quelle angebe, sodass ich den Text stehen lassen kann? Ich weiß schon, wieviel arbeit eine eigene Homepage ist... ;).
Ok, wenn du die Quelle angibst ist das von mir aus ok.
Aber was ich das letzte finde ist, wenn andere sich die Arbeit machen und einer kopiert sich das dann einfach zusammen und macht sein Geld damit.
Aber ich denke das ist bei dir ja nicht der Fall, Außerdem hast du ja schon etwas eigenes gemacht...

Viele Grüße,
Mehto

CapSob
11.07.2006, 19:25
Danke Mehto. Ich geb eigentlich immer ne Quelle an. Aber da ich vorher schnell schnell gemacht hab, dass ich die Datei online stellen kann, hab ich da wohl was übersehen. Keine Angst. Geld damit machen werde ich nicht. Falls das Projekt nachher funktioniert, werde ich 3 - 4 Stück noch für meine Kollegen machen, und das wars.


@ all: Melde mich, wenn ich weiter gekommen bin!

CapSob
12.07.2006, 00:57
Also, hab mich grad bissl hingesetzt und den ersten Programmteil geschrieben. Nun würde ich gerne von euch wissen, ob dies so passt.

Verbesserungsvorschläge sind gewünscht!

peace,
cap.

Vitis
12.07.2006, 07:44
ok, das Prinzip wurde erkannt, es sollte so in etwa funktionieren,
aber ... es gibt immer ein aber ... viel zu kompliziert ;)



dim textstring as string * 20
dim buchstabe as string *1
dim y as byte
dim x as byte

textstring="STAT1; EXIT; "
textlaenge=len(textstring)
for x=1 to textlaenge step 1
buchstabe=mid(textstring,x,1)
y=chr(buchstabe)
Portd=y
gosub Drucker_senden
next x


man verwendet gosub, weil man dann an genau die gleiche stelle
über return zurückspringt ... ist schöner als goto.
so in etwa könnts laufen und der Text ist viel flotter änderbar.
man sehe, die Bytes werden einer nach dem andern an den Drucker
geschickt, aber man kann das auch in ner Schleife unterbringen ;)

oder andere Variante:


dim textstring as string * 20
dim bytewerte(20) as byte at textstring overlay
dim x as byte
dim y as byte

textstring="STAT1; EXIT; "
y=len(textstring)
for x = 1 to y step 1
Portd=bytewerte(x)
gosub Drucker_senden
next x

CapSob
13.07.2006, 11:33
Ja Servus!

Hab grad die Elektronik fertig gebastelt, Billig-Programmer schnell gebaut, Software war ja schon fertig.

Jetzt schnell Datei rüberschieben und testen - und? Blöd... (S+c+h+e+i+s+s+e wurde zensiert...)

Probleme:
1. Hab ihm programmiert, dass er beim einschalten beide LEDs für 1 sek. anmacht, so als funktionstest der LEDs sozusagen. Aber die LEDs leuchten so locker 3-4 sek. Timing-Problem. Fuses? Externer Quarz mit 2 Kondis sind dran.

2. Ich starte, nachdem der DST "gebootet" hat, das Programm 1. OK, Status-LED Grün geht aus, dafür die Rote an. Passt. Aber kommt was am Drucker raus? Nein.

Hier mal die Software:

$regfile = "m8def.dat"
$crystal = 16000000

Ddrb = &B00000000 'Port B komplett als Eingang
Ddrc = &B00001111 'Am Port C PC0 bis PC3 Ausgang, Rest Eingang
Ddrd = &B11111111 'Port D komplett als Ausgang

Portb = &B00011110 'Pullup für PB1 bis PB4 aktivieren (Taster)
Portc = &B00001111 'Beim starten auf 0 setzen
Portd = &B00000000 'Beim starten auf 0 setzen

Portc.0 = 0 'LED Grün an
Portc.1 = 0 'LED Rot an

Wait 1 'Test, ob beide LEDs funktionieren

Portc.1 = 1 'LED Rot aus


Do
If Pinb.1 = 0 Then 'Taster 1 gedrückt
Gosub Dst1
End If
If Pinb.2 = 0 Then 'Taster 2 gedrückt
Gosub Dst2
End If
If Pinb.3 = 0 Then 'Taster 3 gedrückt
Gosub Dst3
End If
If Pinb.4 = 0 Then 'Taster 4 gedrückt
Gosub Dst4
End If
Loop


Dst1: 'Programm 1: Statusseite 1 und 2
Portc.0 = 1 'Grüne LED aus
Portc.1 = 0 'Rote LED an
Gosub Drucker_init
Portd = 33 '!
Gosub Drucker_senden
Portd = 82 'R
Gosub Drucker_senden
Portd = 33 '!
Gosub Drucker_senden
Portd = 32 'Leerzeichen
Gosub Drucker_senden
Portd = 83 'S
Gosub Drucker_senden
Portd = 84 'T
Gosub Drucker_senden
Portd = 65 'A
Gosub Drucker_senden
Portd = 84 'T
Gosub Drucker_senden
Portd = 59 ';
Gosub Drucker_senden
Portd = 83 'S
Gosub Drucker_senden
Portd = 84 'T
Gosub Drucker_senden
Portd = 65 'A
Gosub Drucker_senden
Portd = 84 'T
Gosub Drucker_senden
Portd = 49 '1
Gosub Drucker_senden
Portd = 59 ';
Gosub Drucker_senden
Portd = 69 'E
Gosub Drucker_senden
Portd = 88 'X
Gosub Drucker_senden
Portd = 73 'I
Gosub Drucker_senden
Portd = 84 'T
Gosub Drucker_senden
Portd = 59 ';
Gosub Drucker_senden
Portd = 12 'Form Feed
Gosub Drucker_senden
Portc.0 = 0 'Grüne LED an
Portc.1 = 1 'Rote LED aus
Return


Dst2:
Return


Dst3:
Return


Dst4:
Return


Drucker_senden:
Portc.3 = 1 'Stobe aktivieren
Waitus 10 '10 mikrosekunden warten
Portc.3 = 0 'Daten übernommen
Return


Drucker_init:
Portc.2 = 0 'Init-Signal auf Low zum initialisieren
Waitus 50 '50 mikrosekunden warten
Portc.2 = 1 'Drucker ist initialisiert
Return


End

Im Anhang gibts auch nochmal das Programm zum downloaden.

BITTE HELFT MIR ! ! !

mfg,
cap.


EDIT:
Mir ist grad aufgefallen, dass ich zwar BUSY angeschlossen habe, aber ich irgendwie in meiner programmierung nicht auftaucht. Kann das ein/das Problem sein?

Wegen Fuses setzen hab ich bissl Angst, davor mir den uC zu schießen. Ich benutz zum "brennen" PonyProg. Bitte helft mit da, das mein erstes richtiges AVR Projekt ist. Hatte bis jetzt noch keine wirklichen Erfolge mitm AVR, will das endlich mal ein AVR-Projekt klappt!

EDIT2:
Wie sieht des eigentlich aus wegen dem Strobe-Signal? High oder Low? In meiner Programmierung gebe ich auf das Strobe-Signal 10 usek. ein High-Signal, nach dem ersten Byte - usw... Kann es auch daran liegen?

Vitis
13.07.2006, 18:19
bei den Fuses brauchste Dir keinen kopf machen,
die kannste übrigens auch in Bascom setzen,
änderst auf Crystal = 1000000 also 1 MHz und schon ist die
Sache gut. Für die Anwendung brauchste eh keine 16MHz
und der AVR läuft vom Werk aus mit 1MHz.

Aber auf alle Fälle würd ich den Programmer von Bascom
verwenden, der kann die Fuses prima und deutlich
einfacher als Pony ("wieher") ;)

Der Busy sollte schon mit rein, währ sinnvoll und kann durchaus
die Quelle sein. Der Busy ist ja für die Flusssteuerung
wichtig.

also, du hast da "Wait 1" und "$crystal = 16000000",
wenn du die Fuses nicht auf extern stehen hast läft Dein Mega auf 1MHz.
Das weiß aber Bascom nicht, ergo baut es ne Warteschleife, die um
den 16-Fachen Wert zu lange ist in Dein Programm.
Abhilfe, wie gesagt, "$Crystal = 1000000"

hab mal kurz gebastelt, probiers mal so: (Datei im Anhang)

CapSob
14.07.2006, 05:42
@ vitis:

Wow, danke erstmal!

Hab aber da 1 Fehler:


Dim Bytewerte(30) As Byte At Textstring Overlay

Da bringt er mir nen Error: Adress out of bounds / Error 90

und mir ist folgendes aufgefallen:


Declare Sub Senddata(byval Nutzdaten As String)

Dim Textstring As String * 30

Müsste da eigentlich nich statt Nutzdaten, Textstring stehen?

mfg,
cap.


EDIT:
Ämm... ich hab gar kein ACKN. Laut Mehto´s Dokumentation auf seiner Seite braucht man das nicht, da man sich irgendwie ans Busy-Signal orientiert...?

Vitis
15.07.2006, 11:38
Ok, dann ohne Ackn, so genau hab ich mir mehtos Seite nicht
angesehen.

Der Textstring ist Dein "Kontainer" in den Du den zu übertragenden
Befehl reinspeicherst.

Die Nutzdaten sind die an die Subprozedur zu übergebenen Daten,
die dann in der Sub verarbeitet werden sollen. Im Prinzip
kannste die gleichsetzen, aber ich finds von der Logik her
schöner wenn man da 2 Paar Schuhe verwendet.

War auch nur so mal schnell in 5 MInuten zusammengeklickt,
also wenig Ansprüche auf Perfektion ;)

Bei mir lässt sich das Progrämmchen ohne Beanstandungen
von Bascom Compilieren, welche Version verwendest Du ?

Ach so, schau mal in den Compiler Einstellungen nach Stack Frame usw.,
da sollten evtl. auch n paar Werte rein

Dann eben anders:

CapSob
16.07.2006, 22:16
Ich gebs glaub auf. es klappt nicht. zumindestens mit der programmierung von vitis. er druckt noch kagge aus, aber nich des was er sollte.

@vitis:
hab deinen code mal 1:1 auf den uC geschickt - ohne erfolg. dann hab ich gemerkt, dass du strobe 50 ms!, statt 50 us! gecodet hast. hab das mal geändert - aber auch ohne erfolg.

mal schauen, ob ich noch lust hab, daran mal weiter zu arbeiten...

@all:
danke, dass ihr euch so um mich bemüht habt! rn is krass!