Forum: Mikrocontroller und Digitale Elektronik Barcodescanner mit UART auf LCD (C)


von Patrick F. (paz)



Lesenswert?

Hardware

+ myAVR Board MK2 (AtmelMega8)
    http://shop.myavr.de/Systemboards/myAVR%20Board%20MK2,%20best%C3%BCckt.htm?sp=article.sp.php&artID=40

+ myAVR LCD V2.4
    http://shop.myavr.de/index.php?sp=article.sp.php&artID=15

+ XL1035 Scanner Module (Anhang)



Software

+ UART library by Peter Fleury

+ LCD library for HD44870 based LCD's by Peter Fleury
    http://homepage.hispeed.ch/peterfleury/avr-software.html#libs



Problemstellung

Das Ziel des Programms soll sein die Charakter des Barcodes (Anhang) 
über das LCD auszugeben. Bisher zeigt das LCD lediglich nicht bekannte 
x,x(quer) und Leerzeilen chars an (Anhang).
Wie lässt sich dieses Problem lösen?

Vielen Dank für jede Hilfe



C-Programm
1
#ifndef F_CPU
2
#define F_CPU 1000000UL
3
#endif
4
5
#include <avr/io.h>
6
#include <avr/interrupt.h>
7
#include <util/delay.h>
8
#include <stdlib.h>
9
#include "uart.h"
10
#include "lcd.h"
11
12
#define UART_BAUD_RATE      9600            // SCANNER Baud Rate
13
#define NODATA 0x01
14
#define OVERFLOW 0x02
15
16
17
//****************************  MAIN  *********************************
18
19
int main(void)
20
{  
21
  DDRB = 0xff;                    // define DATADirection PORT B
22
  
23
    uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU));  //INITIALIZE UART
24
  
25
    sei();                        //set enable Interrupts <-- UART
26
      
27
  lcd_init(LCD_DISP_ON_BLINK);            //initialisation of LCD
28
  lcd_clrscr();
29
  lcd_home();
30
  
31
  int scanning = 1;
32
  char buffer[33];
33
  
34
  unsigned int index = 0;
35
  unsigned int is_reading = 0;            //getting data from uart ring buffer --> buffer
36
  
37
  while (scanning)
38
  {
39
    unsigned int raw = uart_getc();          // for example 0F45 
40
    char data = (raw & 0xFF);            // data byte: 45 from 0F45
41
    char stat = (raw / 256);            // stat byte: 0F from 0F45
42
    
43
    if (stat == OVERFLOW)              //OVERFLOW ERROR HANDLER
44
    {
45
      PORTB |= (1<<PB5);              //Turn on red LED
46
      while(uart_getc() != UART_NO_DATA) {}    //clearing ring buffer
47
    }
48
    
49
    if (stat != NODATA && is_reading)
50
    {
51
      buffer[index] = data;
52
      index++;
53
    }
54
    
55
    if (NODATA && !is_reading)
56
    {
57
      lcd_clrscr();
58
      lcd_home();
59
      lcd_puts("no data");
60
      _delay_ms(500);
61
    }
62
    
63
    if (stat == NODATA && is_reading)
64
    {
65
      lcd_clrscr();
66
      lcd_home();
67
      lcd_puts(buffer);
68
      _delay_ms(10000);
69
      index = 0;
70
      is_reading = 0;
71
      PORTB &= ~(1<<PB4);
72
      
73
      for (int i = 0; i<33; i++)
74
      {
75
        buffer[i] = "";
76
      }
77
    }
78
    
79
    if (stat != NODATA && !is_reading)
80
    {
81
      buffer[index] = data;
82
      index++;
83
      is_reading = 1;
84
      PORTB |= (1<<PB4);                //Turn on yellow LED
85
    }
86
  }    
87
}
88
//**************************  END MAIN  *******************************

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Dein Buffer ist nicht terminiert (letztes Zeichen muss ein 0x00 sein).

Patrick Fuchs schrieb:
> if (NODATA && !is_reading)

Du meinst doch sicherlich "stat == NODATA", da NODATA mit 0x01 immer 
wahr ist.

Patrick Fuchs schrieb:
> for (int i = 0; i<33; i++)
>       {
>         buffer[i] = "";
>       }

buffer[i] ist ein char. "" ist ein char*. Das geht so nicht.
Du willst wohl folgendes haben:
buffer[i] = 0x00;

Du machst auch keine Prüfung auf einen Bufferüberlauf.
Was passiert wohl, wenn index plötzlich über die 33 rausläuft?

Wo und wie hast Du den Scanner angeschlossen?
Laut Datenblatt gibt es zwei Modi: Keyboard und Serial.

Das mal so auf die Schnelle.

von Peter K. (peterka2000)


Lesenswert?

Wo hast du denn das Scanner-Modul her?

von Patrick F. (paz)


Lesenswert?

Der Scanner ist laut Datenblatt Serial angeschlossen.

von lol (Gast)


Lesenswert?

Peter K. schrieb:
> Wo hast du denn das Scanner-Modul her?

das würde ich auch gerne wissen

von Karl H. (kbuchegg)


Lesenswert?

Ich würde mir erst mal das Modul mit einem RS232/USB Umsetzer (oder 
einem MAX232, wenn ich noch eine echte serielle Schnittstelle am PC 
habe) erst mal an den PC hängen und dort in einem Terminalprogramm 
nachsehen ob und was das Scanner-Modul so von sich gibt.

So wie das momentan ist, ist das ein Stochern im Nebel. Du weißt nicht, 
ob das Modul was vernünftiges von sich gibt bzw. du weißt nicht, ob in 
deinem µC alles korrekt gemacht ist. die 1Mhz für F_CPU lassen in mir 
den Verdacht aufkommen, dass der auf internem Oszillator läuft, was ein 
Problem mit der Baudrate bedeuten kann. D.h. auch das würde ich mal 
testen, indem ich den µC etwas ausgeben lasse, was ich mir am PC im 
Terminalprogramm ansehe.

Die x bzw x-quer bzw. Leerezeichen lassen eigentlich nicht auf 'bekannt 
oder nicht bekannt' schliessen (nichts dergleichen steht im Datenblatt 
vom Scanner), sondern die würde ich erst mal als Indiz werten, dass da 
mit der Baudrate was nicht stimmt. Höchst wahrscheinlich ist das Problem 
im µC zu lokalisieren. Gerade deshalb ist es so wichtig, dass man erst 
mal eine Komponente (den Scanner), durch etwas ersetzt, dessen 
funktionieren ausser Zweifel steht (ein PC mit Terminalprogramm) und 
dort mal die UART Verbindung durchtestet.
Es hat sich auf lange Sicht bewährt, wenn man in einem System immer nur 
eine Komponente hat, von der man nicht weiß, ob sie sauber funktioniert. 
Je mehr ungetestete und unbekannte Komponenten man hat, desto 
schwieriger wird die Fehlersuche. Daher führt der schnellste Weg, auch 
wenn es zunächst nicht so aussieht, meistens darüber erst mal alles bis 
auf 1 einzige unbekannte und ungetestete Komponente durch etwas ausser 
Frage stehendes zu ersetzen. Und in den meisten Fällen muss dann eben 
ein PC als 'Lückenbüsser' herhalten. Was in diesem Fall besonders 
einfach geht, da die Kommunikation über UART abläuft und ein PC das aus 
dem Stand kann. Damit kann man Scanner und µC erst mal unabhängig 
voneinander auf korrekte Funktion testen UND hat auch noch den Vorteil, 
dass man im Terminalprogramm sogar sieht, was sich auf der Schnittstelle 
abspielt.

von Patrick F. (paz)


Lesenswert?

Scanner gekauft bei http://www.szhcct.com/en/gyhz.asp

Wäre ein externer Oszillator für den IC eine Möglichkeit?
In PuTTy bekam ich bereits eine ca. 12 Byte lange (Ergebnisse liegen 
zuhause) Hex-Schlange.
Es muss also entweder an der falschen Konversion --> Display liegen oder 
an - wie von kbuchegg bereits erwähnt - der falschen Baudrate. Wie 
kann ich die Baudrate überprüfen bzw. richtig stellen? Oder ist der 
interne Oszillator einfach zu ungenau?

Danke vielmals für die hilfreichen Antworten!

Liebe Grüße,
Patrick

von Karl H. (kbuchegg)


Lesenswert?

Patrick Fuchs schrieb:


> In PuTTy bekam ich bereits eine ca. 12 Byte lange (Ergebnisse liegen
> zuhause) Hex-Schlange.

Das ergibt keinen Sinn.
Das Gescannte vom Barcode kommt ziemlich sicher im ASCII-Klartext raus. 
Höchst wahrscheinlich auch noch mit einem abschliessenden \n, so dass 
man ihn einfach und problemlos in bestehende Programme integrieren kann.

Wenn also auf deinem Etikett steht
"Klo-Beleg"
und im Terminal taucht dieser Text nicht auf, dann ist was oberfaul(*)

Alles andere wäre nämlich ziemlicher Schwachsinn, ohne das dieser 
irgendetwas bringen würde.


(*) dir ist schon klar, dass es verschiedene Barcode-Systeme gibt?
http://de.wikipedia.org/wiki/Strichcode

von J. T. (chaoskind)


Lesenswert?

> #define UART_BAUD_RATE      9600            // SCANNER Baud Rate

da stellst du deine baudrate ein. Ansonsten such im Forum nach Baudrate 
einstellen. Da gibs n kleinen Schnippsel Code wo du dein Taktrate und 
deine Baudrate eingibst, doch ich denke #define UART_BAUD_RATE genau das 
macht, nur schon weiß welchen Prozesseortakt du fährst.
Das Codeschnippselchen gibs definitiv in ASM doch ich glaub da gibs auch 
ne Variante für C für. In C arbeite ich mich übrigens auch gerade erst 
ein, daher kann ich da nicht wirklich viel zu sagen. Ich weiß nicht, wie 
deine UART_INIT aussieht.

von Ingo (Gast)


Lesenswert?

Du könntest statt dem Barcode-Scanner mal den PC anschliessen.
Putty (wie gehabt auf 9600), dann etwas vom uC zum PC senden,
z.B. ein 'A' im Sekundentakt.
Wenn dies geht, dann kannst Du RxD an den Scanner hängen.
Hat den Vorteil, dass du etwas vom Barcode-Scanner empfangen
und Debug-Ausgaben zum PC senden kannst.
(Beachtet aber mögliche Spannungsunterschiede der Schnittstellen,
TTL <-> ~ +/-12V RS232)

Kannst du mal ein Beispiel posten, was auf (unter) dem Barcode steht und
was Putty dir anzeigt, wenn du den Scanner direkt am PC angeschlossen
hast? Kommen immer die gleichen Zeichen, wenn du den gleichen
Barcode mehrmals darueber ziehst?

von Patrick F. (paz)


Lesenswert?

Hallo Freunde!

Dem Vorschlag mit PuTTY bin ich gefolgt --> nach einer 
Baudratenanpassung durch den Vergrößerungsfaktor 4 stimmten die Zeichen.

Ich vermute, dass das an der fehlerhaften Delay.h Header liegt, die in 
der meinen Version delays 4 mal so schnell wie normal ausführt.

Die Arbeiten gehen weiter, danke für alle Antworten!

Lg,
Paz

von Patrick F. (paz)


Lesenswert?

Patrick Fuchs schrieb:
> Ich vermute, dass das an der fehlerhaften Delay.h Header liegt, die in
> der meinen Version delays 4 mal so schnell wie normal ausführt.

Muss mich korrigieren:
    Was ich nicht wusste: dass das myavr Board den mega8 mit einem 
externen Oszillator
    (3686400 Hz) auf Trab hält.
    Mein Lehrer meinte immer dass die Delay.h in dieser Version 
inkompatibel zum Board
    wäre.

Lösung: einfach die richtige Frequenz einstellen --> 3686400 und schon 
kann mit allem normal und wie geplant gearbeitet werden.

Nochmals vielen Dank für die Ideen und Anregungen,
Lg, Paz

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.