Keine Reaktion auf Eingabe

#2917867
Lesenswert?

Servus,

hatte vor ein kleines Projekt zum Lernen zu bauen. Das zieht sich 
inzwischen schon seit ein paar Wochen, dem ein oder anderen dürfte die 
Schaltung bekannt vorkommen.

Da die Schaltung mit dieser Community entwickelt wurde, nehme ich 
einfach an, dass sie soweit stimmen müsste (was nicht im Bild ist, ist 
auch nicht angeschlossen). Es muss also an dem Programm liegen; wenn ich 
die Batterie anschließe läuft die Uhrzeit normal ab und die Namen werden 
richtig angezeigt. Wenn ich einen der Schalter drücke, passiert aber 
nichts (die Uhr läuft aber weiter), es wird nicht einmal das '+' 
angezeigt, was ich ich zum Test (Zeile 141) reinschreibe, wenn irgendein 
Input existiert.

LCD wird angesteuert mit der Fleury-Lib (funktioniert auch, sonst wären 
die Ausgaben ja nicht da)

Vielen Dank im Voraus für Hilfe.

Grüße
Michael
Angehängte Dateien:
#2917897
Lesenswert?

Michael W. schrieb:
> Servus,
>
> hatte vor ein kleines Projekt zum Lernen zu bauen. Das zieht sich
> inzwischen schon seit ein paar Wochen, dem ein oder anderen dürfte die
> Schaltung bekannt vorkommen.
>
> Da die Schaltung mit dieser Community entwickelt wurde, nehme ich
> einfach an, dass sie soweit stimmen müsste (was nicht im Bild ist, ist
> auch nicht angeschlossen).

Bitte zeig ALLES.

Da du den ADC Port benutzt: Hast du an AVcc die Spannungsversorgung 
angeschlossen?
#2917913
Lesenswert?

Die Uhrenweiterschaltung sollte als ganzes in die ISR

Dafür solltest du dir als Ausgleich mal ein paar LCD Ausgabefunktionen 
machen, damit du die Ausgaben in der Hauptschleife vernünftig erledigen 
kannst, ohne gleich mal eine halbe Bildschirmseite Code in der 
Hauptschleife dafür zu brauchen.
#2917928
Lesenswert?

>       if(((*BUTTON_PORT)&BUTTON_MASK_ADJUST)


Eingaben von aussen, zb Tasten, werden abgefragt, indem man das PIN (!) 
Register ausliest und nicht das PORT Register!


An dieser Stelle hör ich auf. das hat keinen Sinn.
Lies das Tutorial und mach ein paar Vorübungen.
Den ganzen Code müsste man nehmen, wegschmeissen und nochmal von vorne 
anfangen. Da ist kaum Struktur drinnen, der ganze Code ist verworren und 
unübersichtlich.
#2917937
Lesenswert?

>     // U-Umlaut senden
>     lcd_command(0x48); // CG-RAM 1-0

Kann denn dein LCD keine Umlaute anzeigen?
Mag ich kaum glauben.
Gut im regulären ASCII Datensatz sind sie nicht drinnen, aber in der 
Erweiterung der Zeichen mit gesetztem Bit 7 sind neben einem ganzen 
Haufen anderer Zeichen sicher auch Umlaute mit drinn, die vom LCD 
angezeigt werden ohne dass man dafür die benutzerdefinierten Zeichen 
angreifen muss.
#2917952
Lesenswert?

Probier mal dieses Programm
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "lcd.h"
4

5
#define KEY_DDR   DDRC
6
#define KEY_PORT  PORTC
7
#define KEY_PIN   PINC
8

9
#define KEY_ADJUST 1
10
#define KEY_DISP   0
11

12
int main()
13
{
14
  uint8_t keysPrev;
15
  uint8_t keysNow;
16

17
  lcd_init(LCD_DISP_ON_CURSOR);
18

19
  KEY_DDR &= ~(( 1 << KEY_ADJUST ) | ( 1 << KEY_DISP ));
20
  KEY_PORT |= ( 1 << KEY_ADJUST ) | ( 1 << KEY_DISP );
21

22
  keysPrev = ~KEY_PIN;   // das bewirkt, dass beim ersten Vergleich
23
                         // mit der aktuellen Tastenstellung auf jeden
24
                         // Fall ein Unterschied festgestellt wird und damit
25
                         // beim Programmstart der erste Update des LCD
26
                         // erzwungen wird.
27

28
  while(1) {
29

30
    keysNow = KEY_PIN;
31

32
    if( keysNow != keysPrev ) {
33
      keysNow = keysPrev;
34

35
      lcd_gotoxy( 0, 0 );
36

37
      if( keysNow & ( 1 << KEY_ADJUST ) )
38
        lcd_puts( "Adjust gedrueckt" );
39

40
      else if( keysNow & ( 1 << KEY_DISP ) )
41
        lcd_puts( "Disp   gedrueckt" );
42

43
      else
44
        lcd_puts( "nichts gedrueckt" );
45
    }
46
  }
47
}

Bei Tastendruck muss sich was auf deinem LCD tun.
#2917990
Lesenswert?

Michael W. schrieb:
> OK, ich schreib mal um, ihr habt Recht: der Code ist echt
> unübersichtlich. Wenn ich fertig bin, probiere ich und schreib dann
> nochmal.

Ne. Du sollst zuerst den Code probieren, damit man hier mal weiß ob 
deine Verschaltung grundsätzlich funktioniert.
Denn ich bau die nächsten Beispiele nicht auf ungetester Hardware auf. 
Erst mal will ich wissen, ob das da funktioniert, ehe ich dir Programme 
für einen µC gebe, den ich nicht vor mir liegen habe und den ich blind 
programmieren muss ohne eine Chance zu haben, die Programme zu testen, 
ehe du sie zu Gesicht bekommst.
#2918130
Lesenswert?

Habe mal deinen Code geflasht: es scheint doch an der Schaltung zu 
liegen. Mir ist aufgefallen, dass etwa 1,8V permanent am Anschluss 
anliegen, kann das an dem Poti in Kombination mit dem/den 
22K-Widerständen liegen?

(Ausgabe ist übrigens "Adjust gedrueckt")
Habe mal dein Programm modifiziert und einen Fall eingeführt, wenn beide 
Taster gedrückt sind: Beide sind 1.

Was tun?
#2918399
Lesenswert?

Oops.
Reiss die Schalter runter. Die sind schlecht verdrahtet.
Du hängst sie so an


    µC-Pin  -------------+
                         |
                       \
                        \
                         |
                         |
                    -----+---- GND

Also einfach nur den Schalter dazu benutzen, den µC Pin bei Tastendruck 
mit GND zu verbinden. Nicht mehr. Den Rest macht die Software.

Und dann änderst du noch
1
 .....
2

3
     if( !( keysNow & ( 1 << KEY_ADJUST ) ) )
4
        lcd_puts( "Adjust gedrueckt" );
5

6
     else if( !( keysNow & ( 1 << KEY_DISP ) ) )
7
....
#2919206
Lesenswert?

Arrgh.
Mein Fehler

Das ist falsch
1
    if( keysNow != keysPrev ) {
2
      keysNow = keysPrev;

so ist es richtig
1
    if( keysNow != keysPrev ) {
2
      keysPrev = keysNow;


Im ganzen Satz :-)
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "lcd.h"
4

5
#define KEY_DDR   DDRC
6
#define KEY_PORT  PORTC
7
#define KEY_PIN   PINC
8

9
#define KEY_ADJUST 1
10
#define KEY_DISP   0
11

12
int main()
13
{
14
  uint8_t keysPrev;
15
  uint8_t keysNow;
16

17
  lcd_init(LCD_DISP_ON_CURSOR);
18

19
  KEY_DDR &= ~(( 1 << KEY_ADJUST ) | ( 1 << KEY_DISP ));
20
  KEY_PORT |= ( 1 << KEY_ADJUST ) | ( 1 << KEY_DISP );
21

22
  keysPrev = ~KEY_PIN;   // das bewirkt, dass beim ersten Vergleich
23
                         // mit der aktuellen Tastenstellung auf jeden
24
                         // Fall ein Unterschied festgestellt wird und damit
25
                         // beim Programmstart der erste Update des LCD
26
                         // erzwungen wird.
27

28
  while(1) {
29

30
    keysNow = KEY_PIN;
31

32
    if( keysNow != keysPrev ) {
33
      keysPrev = keysNow;
34

35
      lcd_gotoxy( 0, 0 );
36

37
     if( !( keysNow & ( 1 << KEY_ADJUST ) ) )
38
        lcd_puts( "Adjust gedrueckt" );
39

40
     else if( !( keysNow & ( 1 << KEY_DISP ) ) )
41
        lcd_puts( "Disp   gedrueckt" );
42

43
      else
44
        lcd_puts( "nichts gedrueckt" );
45
    }
46
  }
47
}


(Es gibt eben nichts was so einfach wäre, dass man es doch verbocken 
kann)
#2919424
Lesenswert?

Michael W. schrieb:

> Frage noch: Warum funktioniert die Schaltung auf dem Pollin-Board; bzw.
> Warum kann ich dort über PORTD (angeschlossen an den Schaltern auf dem
> Pollin-Board) nicht-invertiert lesen?

Weil auf dem Pollin-Board die Schalter anders rum angeschlossen sind.
Das hat aber Nachteile. Unter anderem den, dass du nicht die eingebauten 
Pullup-Widerstände des µC benutzen kannst.

Wozu externe Pull-Down Widerstände verbauen, wenn der µC Pullup mithat?

(Zudem hat das Pollin Board noch ein anderes Problem, was letzten Endes 
dazu führt, dass man die Taster sowieso auf die hier benutzte 
Standard-Konfiguration umbaut)
#2919443
Lesenswert?

Probier mal.
Bei Druck auf den DISP Taster müsste die Anzeige von Uhrzeit auf 
Wochentag/Woche umwechseln
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "lcd.h"
4

5
#ifndef TRUE
6
#define TRUE 1
7
#define FALSE 0
8
#endif
9

10

11
#define KEY_DDR   DDRC
12
#define KEY_PORT  PORTC
13
#define KEY_PIN   PINC
14

15
#define KEY_ADJUST 1
16
#define KEY_DISP   0
17

18
struct time
19
{
20
  uint8_t week_;
21
  uint8_t day_;
22
  uint8_t hour_;
23
  uint8_t min_;
24
  uint8_t sec_;
25
};
26

27
volatile uint8_t timeTick;      // wird nach jeder Sekunde TRUE
28
volatile struct time actTime;   // die aktuelle Zeit
29

30

31
char* dayString[] = { "Mo", "Di", "Mi", "Do", "Fr", "Sa", "So" };
32

33
int main()
34
{
35
  uint8_t keysPrev;
36
  uint8_t keysNow;
37
  uint8_t dispMode = 0;
38

39
  lcd_init(LCD_DISP_ON_CURSOR);
40

41
  //
42
  // Timer 1
43
  //   CTC Modus
44
  //   Prescaler + OCR1A   -> 1 ms
45
  OCR1A = (1000*(CPU_FREQ/1000000))-1; // Timer löst alle 1000 Counts aus
46
  TCCR1A = 0x00; // CTC-Modus
47
  TCCR1B = (1<<WGM12)|(1<<CS10); // Prescaler 1 -> (1.000.000/1)/1000 = 1000 mal pro Sekunde
48
  TIMSK = (1<<OCIE1A);
49

50
  // Tasten 
51
  KEY_DDR &= ~(( 1 << KEY_ADJUST ) | ( 1 << KEY_DISP ));
52
  KEY_PORT |= ( 1 << KEY_ADJUST ) | ( 1 << KEY_DISP );
53

54
  keysPrev = ~KEY_PIN;   // das bewirkt, dass beim ersten Vergleich
55
                         // mit der aktuellen Tastenstellung auf jeden
56
                         // Fall ein Unterschied festgestellt wird und damit
57
                         // beim Programmstart der erste Update des LCD
58
                         // erzwungen wird.
59

60
  while(1) {
61

62
    keysNow = KEY_PIN;
63

64
    if( keysNow != keysPrev ) {
65
      keysPrev = keysNow;
66

67
      if( !( keysNow & ( 1 << KEY_DISP ) ) )
68
        mode = 1;
69
      else
70
        mode = 0;
71
    }
72
    
73
    if( mode == 0 )
74
      lcd_time( 0, 0, &actTime );
75
    else
76
      lcd_date( 0, 0, &actTime );
77
  }
78
}
79

80
void lcd_time( uint8_t x, uint8_t y, struct time* tim )
81
{
82
  char buf[20];
83
  
84
  sprintf( buf, "%2d:%02d:%02d", (int)tim->hour_, (int)tim->min_, (int)tim->sec_ );
85
  lcd_gotoxy( x, y );
86
  lcd_puts( buf );
87
}
88

89
void lcd_date( uint8_t x, uint8_t y, struct time* tim )
90
{
91
  char buf[20];
92
  
93
  sprintf( buf, "%02d - %s  ", (int)tim->week_, dayString[tim->day_] );
94
  lcd_gotoxy( x, y );
95
  lcd_puts( buf );
96
}
97

98
ISR(TIMER1_COMPA_vect)
99
{
100
  static uint16_t milliSec;
101
  
102
  milliSec++;
103
  if( milliSec == 1000 ) {  
104
    milliSec = 0;
105
    timeTick = TRUE;
106

107
    actTime.sec_++;
108
    if( actTime.sec_ == 60 ) {
109
      actTime.sec_ = 0;
110
      
111
      actTime.min_++;
112
      if( actTime.min_ == 60 ) {
113
        actTime.min_ = 0;
114
        
115
        actTime.hour_++;
116
        if( actTime.hour_ == 24 ) {
117
          actTime.hour_ = 0;
118
          
119
          actTime.day_++;
120
          if( actTime.day_ == 7 ) {
121
            actTime.day_ = 0;
122
            
123
            actTime.week_++;
124
          }
125
        }
126
      }
127
    }
128
  }
129
}
#2919974
Lesenswert?

So, hab ich jetzt noch einmal Komplett neu geschrieben. Habe übrigens im 
Datenblatt des Displays nachgesehen: es gibt kein "ü" in der 
Code-Tabelle. Es ist angeblich aber trotzdem ein HD47780.

Mal der jetzige Code im Anhang.

XTAL ist in der Fleury-Lib definiert und das gleiche wie CPU_FREQ.

Habe noch folgende Beobachtung in der letzten Stunde gemacht: die Uhr 
läuft zu langsam. Ich werd mich mal dran machen und einen 
Korrekturfaktor einbauen (also OCR1A veränderbar machen).

Vielleicht wird der dann im EEPROM gespeichert, würde zumindest nicht 
schaden. (Der Wert wird im Idealfall ja nur ein paar mal geschrieben)

Grüße
Michael
Angehängte Dateien:
#2920064
Lesenswert?

Michael W. schrieb:

> Warum legst du für die einzelnen Elemente der Zeit extra eine Struktur
> anlegen, wenn das ganze Projekt im Prinzip eine erweiterte Uhr ist?

Weil es erstens nichts kostet
ich zweitens dann die Uhrzeit wie im Beispiel in einfacher Art und Weise 
an Funktionen übergeben kann
drittens du selber sagst, dass es eine erweiterte Uhr ist, da also noch 
Dinge dazu kommen
von denen ich viertens denke, dass da irgendwann mal zusätzliche 
einstellbare Zeiten dazu kommen werden

Aber der Hauptpunkt ist: weil es mich nichts kostet und ich so die Dinge 
beisammen halte, die zusammen gehören. Eine Uhrzeit besteht nun mal aus 
diesen Dingen.
#2920068
Lesenswert?

Michael W. schrieb:
> So, hab ich jetzt noch einmal Komplett neu geschrieben. Habe übrigens im
> Datenblatt des Displays nachgesehen: es gibt kein "ü" in der
> Code-Tabelle. Es ist angeblich aber trotzdem ein HD47780.

Interessant.
Es gibt da verschiedene Versionen.
Normalerweise hat man UMlaute. Allerdings nur in Form von 
Kleinbuchstaben. Für Grossbuchstaben mit Umlaut reicht der Platz nicht.

http://de.wikipedia.org/w/index.php?title=Datei:Charset.gif&filetimestamp=20090712201008


> Habe noch folgende Beobachtung in der letzten Stunde gemacht: die Uhr
> läuft zu langsam.

:-)
Die 1Mhz sind bei dir vom internen RC-Oszillator?
Dann allerdings darfst du dich nicht wundern. Der ist so genau wie der 
Wasserstand der Donau.
FÜr eine Uhr brauchst du einen Quarz. Ohne wird das nichts.
Und diesen Quarz musst du auch ausmessen. Denn selbst wenn am Quarz 4MHz 
druafsteht, bedeutet das nicht, das er exakt 4000000 Schwingungen in der 
Sekunde macht.

AVR - Die genaue Sekunde / RTC
#2920119
Lesenswert?

Karl Heinz Buchegger schrieb:
>> Datenblatt des Displays nachgesehen: es gibt kein "ü" in der
>> Code-Tabelle. Es ist angeblich aber trotzdem ein HD47780.
>
> Interessant.
> Es gibt da verschiedene Versionen.
> Normalerweise hat man UMlaute. Allerdings nur in Form von
> Kleinbuchstaben.

Probier mal das Zeichen 0xf5. Das ist in allen mir vorliegenden 
Datenblättern das kleine "ü".
#2920158
Lesenswert?

Georg G. schrieb:
> Karl Heinz Buchegger schrieb:
>>> Datenblatt des Displays nachgesehen: es gibt kein "ü" in der
>>> Code-Tabelle. Es ist angeblich aber trotzdem ein HD47780.
>>
>> Interessant.
>> Es gibt da verschiedene Versionen.
>> Normalerweise hat man UMlaute. Allerdings nur in Form von
>> Kleinbuchstaben.
>
> Probier mal das Zeichen 0xf5. Das ist in allen mir vorliegenden
> Datenblättern das kleine "ü".

Hab irgendwann mal probiert (nicht jetzt), da kommt irgenwas anderes 
raus, ich weiß jetzt aber nicht mehr was. Habe auch nach anderen 
HD47780-Datenblättern geschaut, hat aber alles nichts geracht. Naja, 
dann hab ich halt das "ü" selbst rein geschrieben.

Ja, ist mir klar, dass das auf gar keinen Fall annähernd genau ist. Da 
die Schaltung auf der Platine aber schon mehr oder weniger den gesamten 
Platz einnimmt und ich dann isolierte Drahtbrücken bräuchte (wäre dann 
3. Ebene), möchte ich lieber nur den Korrekturfaktor verwenden. Aber 
fürs nächste Projekt (was auch immer das sein wird) weiß ich ja jetzt 
Bescheid.

Das mit dem Korrektur-Faktor dürfte in diesem speziellen Fall auch 
funktionieren, da Quarze ja bekanntlich von der Temperatur abhängig sind 
- und die ist im Einsatzraum ziemlich konstant 21°C. Und wenn die Uhr 
mal ein Paar Minuten falsch geht, ist das kein Problem, ich kann sie ja 
nachstellen.

Beim nächsten Projekt werde ich auch einen Programmier-Anschluss (ISP) 
anlöten; Erstens muss man beim raus-hebeln sehr vorsichtig sein und 
zweitens geht es deutlich schneller (mit ISP-Anschluss), wenn man 
einfach was probieren möchte. Kann ich den direkt an die Ports hängen 
(siehe Pollin-Board) oder muss ich etwas zwischendran hängen (weil das 
Pollin-Board in dem Punkt ebenfalls nicht ganz stimmt)?

Grüße
Michael
#2920357
Lesenswert?

Michael W. schrieb:

> Hab irgendwann mal probiert (nicht jetzt), da kommt irgenwas anderes
> raus, ich weiß jetzt aber nicht mehr was. Habe auch nach anderen
> HD47780-Datenblättern geschaut, hat aber alles nichts geracht. Naja,
> dann hab ich halt das "ü" selbst rein geschrieben.

Im Zweifelsfall hilft immer das Experiment weiter.
Es ist relativ trivial, sich ein Programm zu schreiben, welches 
nacheinander zb jeweils 16 Zeichen mit aufsteigenden Codes auf dem LCD 
ausgibt.
Im AVR-Tutorial ist zb ein derartiges Programm in einer etwas anderen 
Form, aber mit der gleichen Funktionalität in Assembler geschrieben 
(allerdings im Zusammenhang mit der Erklärung, wie man fachgerecht 
Tastendrücke erkennt).

> Ja, ist mir klar, dass das auf gar keinen Fall annähernd genau ist. Da
> die Schaltung auf der Platine aber schon mehr oder weniger den gesamten
> Platz einnimmt und ich dann isolierte Drahtbrücken bräuchte

Welche Drahtbrücken.
Du scheinst da etwas misszuverstehen: Der Quarz muss sowieso dicht an 
den µC herangesetzt werden. Und das du diesen Platz nicht mehr hast, 
kann ich ehrlich gesagt kaum glauben.

> 3. Ebene), möchte ich lieber nur den Korrekturfaktor verwenden.

Tja.
Dann wird deine Uhr immer nur eine nette (und durchaus lehrreiche) 
Spielerei bleiben, die für praktische Zwecke nicht zu gebrauchen ist.
Solange du damit leben kannst, ist das ok.


> Das mit dem Korrektur-Faktor dürfte in diesem speziellen Fall auch
> funktionieren, da Quarze ja bekanntlich von der Temperatur abhängig sind

Langsam. Quarze sind temperaturabhängig. Ja.
Aber die Frage ist: um welche Größenordnungen geht es!

Dein RC-Schwingkreis hat Abweichungen, die sind um einige Größenordnung 
größer als das, was dir selbst der grindigste Quarz auf Anhieb bietet.
#2920457
Lesenswert?

OK. Die Tastenentprellung von Herrn Dannegger ist relativ interressant 
gelöst.

> Tja.
> Dann wird deine Uhr immer nur eine nette (und durchaus lehrreiche)
> Spielerei bleiben, die für praktische Zwecke nicht zu gebrauchen ist.
> Solange du damit leben kannst, ist das ok.

Mehr sollte es auch nicht sein (der Putzplan könnte für uns drei hier 
auch locker auf ner A4-Seite stehen, was er noch tut).
Leider habe ich auf der Lochrasterplatine zwischen Controller (Auf der 
Seite wo XTAL1 und 2 liegen) und Ende der Platine 6 Löcher im 3-Punkt. 
Davon sind aber zwei nebeneinander nicht benutzbar (liegen schon 
Brücken) und Masse ist relativ weit entfernt und nicht eingeplant war. 
Das hängt auch damit zusammen, dass ich die Platine bestimmt fünf mal 
umgelötet habe.
Wie gesagt: fürs nächste mal weiß ich Bescheid. Hätte aber auch nicht 
gedacht, dass der interne Oszillator/Taktgeber so schwankt.

Vielen Dank für deine Hilfe!

Grüße
Michael

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