AVR Project – Relay Timer with ATmega8 AVR MCU

OP #3314596
Lesenswert?

Guten Morgen liebe Forum Gemeinde,

ich habe mich an den vergangenen Tagen mal mit einem Projekt, welches 
ich im Internet gefunden habe auseinander gesetzt.

http://extremeelectronics.co.in/avr-projects/avr-project-relay-timer-with-atmega8-avr-mcu/

Dazu habe ich alle nötigen Daten heruntergeladen und im AVR Studio 
eingefügt, sowie die Schaltung auf meinen Steckbrettern 
zusammengesteckt. Siehe Foto.

Leider funktioniert es aber nicht. Ich habe aber darauf geachtet, die 
Fuses umzustellen.

Anschließend habe ich es versucht mit AVR Simulator IDE zu simulieren, 
auch ohne Erfolg. (Aber ohne die Fuses).

Kann mir jemand Tipps geben wie ich es zum laufen bekomme?

Hier der Code aus LCD_RELAY_TIMER.c:
1
/******************************************************
2

3
A Simple Device Timer project designed using ATmega8
4
AVR MVU. The Timer is usefull for keeping a device
5
"ON" for a specific period of time. After the set time
6
elapse the timer automatically turns the load off.
7

8
The Timer uses a standart 16x2 lcd module for user interface
9
UI. User can set the time using a 3 button keypad.
10

11
After that Timer is started. While count down is in 
12
progress, the time left is displayed on screen.
13

14
The program use our LCD driver library more details
15
of which can be found in Website.
16

17
Use avr-gcc + AVR Studio to compile.
18

19
Author: Avinash Gupta
20
E:Mail: me@avinashgupta.com
21
Web: www.eXtremeElectronics.co.in
22

23
*** THIS PROJECT IS PROVIDED FOR EDUCATION/HOBBY USE ONLY  ***
24

25
*** NO PROTION OF THIS WORK CAN BE USED IN COMMERIAL       ***
26
*** APPLICATION WITHOUT WRITTEN PERMISSION FROM THE AUTHOR ***
27

28
EVERYONE IS FREE TO POST/PUBLISH THIS ARTICLE IN
29
PRINTED OR ELECTRONIC FORM IN FREE/PAID WEBSITES/MAGAZINES/BOOKS
30
IF PROPER CREDIT TO ORIGINAL AUTHOR IS MENTIONED WITH LINKS TO
31
ORIGINAL ARTICLE 
32

33

34

35

36
Copyright (C) 2008-2009 eXtreme Electronics, India.
37

38
******************************************************/
39

40
#include <avr/io.h>
41
#include <avr/interrupt.h>
42

43
#include "lcd.h"
44

45
//Connection of Load
46
#define LOAD_DDR DDRC
47
#define LOAD_PORT PORTC
48
#define LOAD_POS PC0
49

50
//Global variable for the clock system
51
volatile unsigned int   clock_millisecond=0;
52
volatile char       clock_second=0;
53
volatile char       clock_minute=0;
54
volatile char       clock_hour=0;
55

56

57
void Wait(uint8_t n)
58
{
59

60
  uint8_t i,temp;
61
  temp=n*28;
62

63
  for(i=0;i<temp;i++)
64
    _delay_loop_2(0);
65
}
66

67
void LoadOn()
68
{
69
  LOAD_PORT|=(1<<LOAD_POS);
70
}
71

72
void LoadOff()
73
{
74
  LOAD_PORT&=(~(1<<LOAD_POS));
75
}
76
main()
77
{
78

79
  while(1)
80
  {
81
    LOAD_DDR|=(1<<LOAD_POS);
82

83
    LoadOff();
84

85
    //Enable Pullups on Keypad
86
    PORTB|=((1<<PB2)|(1<<PB1)|(1<<PB0));
87

88
    int8_t hr,min;  //Target Time
89
    hr=min=0;
90

91
    //Initialize the LCD Subsystem
92
    InitLCD(0);
93
    //Clear the display
94
    LCDClear();
95

96
    //Set up the timer1 as described in the
97
    //tutorial
98
    TCCR1B=(1<<WGM12)|(1<<CS11)|(1<<CS10);
99
    OCR1A=250;
100

101
    //Enable the Output Compare A interrupt
102
    TIMSK|=(1<<OCIE1A);
103

104
    //Enable interrupts globally
105
    sei();
106

107
    LCDClear();
108
    LCDWriteString("    Welcome     ");
109
    LCDWriteStringXY(0,1,"   Relay Timer  ");
110

111
    Wait(4);
112

113
    LCDClear();
114
    LCDWriteString("Set Time - 00:00");
115
    LCDWriteStringXY(0,1," Start     ^");
116

117
    uint8_t selection=1;
118
    uint8_t old_pinb=PINB;
119

120
    while(1)
121
    {
122
      while((PINB & 0b00000111) == (old_pinb & 0b00000111));
123
    
124
      //Input received
125

126

127
      if(!(PINB & (1<<PINB2)) && (old_pinb & (1<<PB2)))
128
      {
129
        //Selection key Pressed
130
        selection++;
131
        if(selection==3)
132
          selection =0;
133
      }
134

135
      if(!(PINB & (1<<PINB1)) && (old_pinb & (1<<PB1)))
136
      {
137
        //Up Key Pressed
138
        if(selection == 1)
139
        {
140
        
141
          //Hour is selected so increment it
142
          hr++;
143

144
          if(hr == 100)
145
            hr =0;
146
        }
147

148
        if(selection == 2)
149
        {
150

151
          //Min is selected so increment it
152
          min++;
153

154
          if(min == 60)
155
            min =0;
156
        }
157

158
        if(selection == 0)
159
        {
160
          //Start Selected
161
          break;
162
        }
163

164

165
      }
166

167
      if(!(PINB & (1<<PINB0)) && (old_pinb & (1<<PB0)))
168
      {
169
      //Down Key Pressed
170
        if(selection == 1)
171
        {
172

173
          //Hour is selected so decrement it
174
          hr--;
175

176
          if(hr == -1)
177
            hr =99;
178
        }
179

180
        if(selection == 2)
181
        {
182

183
          //Min is selected so decrement it
184
          min--;
185

186
          if(min == -1)
187
            min =59;
188
        }
189

190
        if(selection == 0)
191
        {
192
          //Start Selected
193
          break;
194
        }
195

196
      }
197

198
    
199
      old_pinb=PINB;
200

201
    
202

203
      //Update Display
204
      LCDClear();
205
      LCDWriteString("Set Time - 00:00");
206
      LCDWriteStringXY(0,1," Start    ");
207

208
      //Hour
209
      LCDWriteIntXY(11,0,hr,2);
210

211
      //Minute
212
      LCDWriteIntXY(14,0,min,2);
213

214
      if(selection == 0)
215
        LCDWriteStringXY(0,1,">");
216
    
217
      if(selection == 1)
218
        LCDWriteStringXY(11,1,"^");
219

220
      if(selection == 2)
221
        LCDWriteStringXY(14,1,"^");
222

223
      _delay_loop_2(0);
224
      _delay_loop_2(0);
225
      _delay_loop_2(0);
226
      _delay_loop_2(0);
227

228
      _delay_loop_2(0);
229
      _delay_loop_2(0);
230
      _delay_loop_2(0);
231
      _delay_loop_2(0);
232
    }
233

234
    //Start the Load
235
    LoadOn();
236

237
    //Now start the timer
238
    clock_hour = hr;
239
    clock_minute = min;
240
    clock_second =0;
241

242
    LCDClear();
243
    LCDWriteString("  Power Off In ");
244

245
    while(1)
246
    {
247
      LCDWriteIntXY(4,1,clock_hour,2);
248
      LCDWriteString(":");
249
      LCDWriteIntXY(7,1,clock_minute,2);
250
      LCDWriteString(":");
251
      LCDWriteIntXY(10,1,clock_second,2);
252

253
      if((clock_hour == 0) && (clock_minute == 0) && (clock_second == 0))
254
      {
255
        //Time Out
256
        LoadOff();
257

258
        LCDClear();
259
        LCDWriteString("Load Turned Off");
260
      
261
        while(1)
262
        {
263
          LCDWriteStringXY(0,1,"*Press Any Key*");
264

265
          Wait(1);
266

267
          LCDWriteStringXY(0,1,"                ");
268

269
          Wait(1);
270

271
          if((~PINB) & 0b00000111)
272
            break;
273

274
        }
275

276
        break;
277

278
      
279

280
      }
281

282
      _delay_loop_2(0);
283
      _delay_loop_2(0);
284
      _delay_loop_2(0);
285
      _delay_loop_2(0);
286
    }
287
  //Continue again
288
  }
289

290

291
}
292

293
//The output compate interrupt handler
294
//We set up the timer in such a way that
295
//this ISR is called exactly at 1ms interval
296
ISR(TIMER1_COMPA_vect)
297
{
298
  clock_millisecond++;
299
  if(clock_millisecond==1000)
300
  {
301
    clock_second--;
302
    clock_millisecond=0;
303
    if(clock_second==-1)
304
    {
305
      clock_minute--;
306
      clock_second=59;
307

308
      if(clock_minute==-1)
309
      {
310
        clock_hour--;
311
        clock_minute=59;
312
      }
313
    }
314
  }
315
}
Angehängte Dateien:
#3314619
Lesenswert?

Sebastian M. schrieb:

> Leider funktioniert es aber nicht.

Was heißt funktioniert nicht?

Fang mit was einfacherem an.
Steck mal eine LED an einen Port Pin und sieh nach, ob der µC überhaupt 
läuft, indem du die LED blinken lässt.
Im Moment sind da zu viele ungetestete Systeme im Spiel, so dass man 
nicht wirklich eine Aussage darüber treffen kann, was das Problem ist. 
Also muss man abspecken und mit einem möglichst einfachen Testprogramm 
System für System, Komponente für Komponente in Betrieb nehmen.
OP #3314718
Lesenswert?

wovon möchtest du ein Foto haben, von der Hardware?
1
/************************************************
2
  LCD CONNECTIONS
3
*************************************************/
4

5
#define LCD_DATA D  //Port PD0-PD3 are connected to D4-D7
6

7
#define LCD_E D //Enable OR strobe signal
8
#define LCD_E_POS PD4  //Position of enable in above port
9

10
#define LCD_RS D  
11
#define LCD_RS_POS PD6
12

13
#define LCD_RW D
14
#define LCD_RW_POS PD5
15

16

17
//************************************************
18

19
#define LS_BLINK 0B00000001
20
#define LS_ULINE 0B00000010
#3314737
Lesenswert?

Sebastian M. schrieb:
> Karl Heinz Buchegger schrieb:
>> Das kann nicht stimmen.
>>
>> Wenn am Port D die Datenbits auf den Pins PD4 bis PD7 liegen, dann kann
>> die RS Leitung nicht auf PD6 liegen
>
> Die Ports am Controller sind PD0 - PD3 das sind die Anschlüsse am
> LCD D4 - D7.

Ja, habs schon gemerkt.
In deinem Projekt ist eine etwas andere Version der LCD Routinen als 
die, die ich mir von der angegebenen Web-Site gezogen habe.
#3314768
Lesenswert?

Sebastian M. schrieb:
> Karl Heinz Buchegger schrieb:
>> In deinem Projekt ist eine etwas andere Version der LCD Routinen als
>> die, die ich mir von der angegebenen Web-Site gezogen habe.
>
> Wie meinst du das? Habe diese runtergeladen und eingebunden und
> eigentlich nichts verändert.

Die hier
http://extremeelectronics.co.in/avr-tutorials/using-lcd-module-with-avrs/

sind ein wenig anders gemacht.
OP #3315009
Lesenswert?

Ich bekomme jetzt im AVR Studio folgende Warnung nach dem start von 
Build Solution.
1
Warning  1  
2
return type defaults to 'int' [enabled by default]  ...RELAY_TIMER_DOWNLOAD\LCD_RELAY_TIMER.c  76  1  RELAY_TIMER_DOWNLOAD

Das ist dieser Codeabschnitt in der LCD_RELAY_TIMER.c der Fehler soll in 
der Zeile main() sein.:
1
...
2
void LoadOff()
3
{
4
  LOAD_PORT&=(~(1<<LOAD_POS));
5
}
6
main()
7
{
8

9
  while(1)
10
  {
11
    LOAD_DDR|=(1<<LOAD_POS);
12

13
    LoadOff();
14

15
    //Enable Pullups on Keypad
16
    PORTB|=((1<<PB2)|(1<<PB1)|(1<<PB0));
17

18
    int8_t hr,min;  //Target Time
19
    hr=min=0;
20
...
#3315033
Lesenswert?

Sebastian M. schrieb:
> cyblord ---- schrieb:
>> Ist auch kein Fehler, sondern eine Warnung.
>
> das klingt so einfach. Spielt es keine rolle, wie ich main() deklariere?
> Was schlägst du vor?

int

Deshalb sollte auch ans Ende der main() ein return 0.
So macht man das sauber. Auch wenns im Controller keine Rolle spielt.


Und Rückgabetyp weglassen ist nie gut. Wieso fehlt der überhaupt?
#3315051
Lesenswert?

Sebastian M. schrieb:
> cyblord ---- schrieb:
>> nt
>>
>> Deshalb sollte auch ans Ende der main() ein return 0.
>
> nur zum Verständnis, da ich den rückgabetyp nicht weiterverarbeite, ist
> es egal wie ich diesen Deklariere?

Nach irgendwelchen C Standards (die ich grade nicht genau benennen kann) 
sollte main() einen INT zurückgeben. Ich würde dabei bleiben. Auf einem 
Laufzeitsystem, ist das wichtig, damit ein programm einen errocode 
rückgeben kann. Darum auch return 0, da 0=kein fehler, <>0 = Fehler.
Du hast kein Laufzeitystem auf dem Controller, darum egal. Trotzdem 
würde ich mich bei C daran halten.
OP #3315056
Lesenswert?

cyblord ---- schrieb:
> Nach irgendwelchen C Standards (die ich grade nicht genau benennen kann)
> sollte main() einen INT zurückgeben. Ich würde dabei bleiben. Auf einem
> Laufzeitsystem, ist das wichtig, damit ein programm einen errocode
> rückgeben kann. Darum auch return 0, da 0=kein fehler, <>0 = Fehler.
> Du hast kein Laufzeitystem auf dem Controller, darum egal. Trotzdem
> würde ich mich bei C daran halten.

Ok, danke für den Tipp.

Ich werde jetzt die Schaltung im Keller erneut aufbauen. Mal schauen ob 
es mit den neuen Komponenten klappt.
#3315079
Lesenswert?

Sebastian M. schrieb:

> kann ich dir auch nicht sagen, dieses Projekt stammt von einer Homepage,
> ich versuche nur zur Übung das zum laufen zu bekommen.

Konzentrier dich erst mal nur auf das LCD und lass den Timer-Code weg.

Ein einfaches
1
int main()
2
{
3
  InitLCD(0);
4
  LCDWriteString("    Welcome     ");
5

6
  while( 1 )
7
    ;
8
}
reicht, um das LCD in Betrieb zu nehmen und den Funktionsnachweis zu 
erbringen.
Alles andere sind erst mal nur zusätzliche Möglichkeiten, Fehler zu 
machen.
Und so prickelnd gut ist der Code von diesem Timer dann auch wieder 
nicht geschrieben.
OP #3315311
Lesenswert?

So habe die Schaltung erneut zusammengesteckt, leider ohne Funktion. Als 
ich dann das Quarz gegen ein frisch geliefertes ausgetauscht habe, habe 
ich endlich eine Anzeige bekommen.

=> Quarz defekt <=

Nun gibt es aber ein neues Problem, welches dieses mal nicht an der 
Hardware liegen kann.

Nach dem Einschalten ist folgendes zu sehen:
("||||||||||||||||") = schwarze Rechtecke
("                ")

Nach dem Drücken von "Select" erscheint:
("    Welcome     ")
("   Relay Timer  ")

dann passiert nach 4 sek. nichts, erst durch drücken von
"select" oder "up" oder "down" für eine dauer von 3 sek. danach ist 
folgendes Bild:
("Set Time - 00:00")
(" Start     ^    ");

Jedes drücken einer Taste führt wieder zum Bild:
("    Welcome     ")
("   Relay Timer  ")



Karl Heinz Buchegger schrieb:
> Und so prickelnd gut ist der Code von diesem Timer dann auch wieder
> nicht geschrieben.

Leider bin ich aber nicht in der Lage, selbst einen Code zu schreiben. 
Somit bleibt mir nur noch die Möglichkeit, einen zu suchen, und diesen 
dann nach meinen Wünschen anzupassen.
#3315331
Lesenswert?

Sebastian M. schrieb:

> Leider bin ich aber nicht in der Lage, selbst einen Code zu schreiben.
> Somit bleibt mir nur noch die Möglichkeit, einen zu suchen, und diesen
> dann nach meinen Wünschen anzupassen.

Ich denke du willst üben?

Dann analysier den Anfang des Codes, sieh nach was passiert (die ganze 
Timer Sache lässt du erst mal weg), und analysiere wie die Sache mit den 
Tasten funktioniert.

Und dann schreibst du den ganzen Teil, der sich um LCD, Tasten und 
erhöhen/erniedrigen der einzelnen Zahlenwerte dreht neu und nach deinen 
Vorstellungen.

Eine bessere Übung gibt es nicht.

Wenn der Teil dann erst mal zufriedenstellend funktioniert, dann können 
wir uns über den Timer unterhalten, bzw. wie man dann die eingestellte 
Zeit tatsächlich ablaufen lässt. Aber erst mal hast du mit LCD, Tasten 
und deren Auswertung genug zu tun.

Sorry. Aber wer etwas selber bauen will, der muss auch selber ran. Das 
war schon immer die Maxime hier im Forum.
#3315351
Lesenswert?

Sebastian M. schrieb:
> Karl Heinz Buchegger schrieb:
>> Eine bessere Übung gibt es nicht.
>
> Hast du auch einen Vorschlag wie man dort am besten ran geht?

Sicher.
Ignorier erst mal die komplette Timer Sache.

Du hast 2 Variablen, die Stunden und die Minuten.
Und du hast 3 Tasten.
Mit einer Taste wählst du aus, welchen Zahlenwert (Stunden oder Minuten) 
du verändern willst und mit den anderen beiden erhöhst bzw. erniedrigst 
du den Wert. Und dann werden die neuen Werte wieder am LCD angezeigt.

Analysier den Code. Genau diese Funktionalität ist da im Grunde schon 
programmiert, wenn auch etwas ... seltsam und langatmig. D.h. du hast 
schon Code, an dem du dir ansehen kannst, wie man zb den Wert einer 
Variablen ausgibt. Du hast schon Code der, ähm, Tastenabfragen 
realisiert. Nur bitte nimm nicht diese besch.... delay Funktionen des 
Autors, sondern wenigstens die im AVR-GCC bereits vorhandenen.

Fürs erste reicht es ja auch, wenn du nach dem Drücken einer Taste erst 
mal 2 unterschiedliche Texte anzeigst
1
int main()
2
{
3
  lcd_init( 0 );
4

5
  PORTB |= ( 1 << PB0 );
6

7
  while( 1 )
8
  {
9
    if( PINB & ( 1 << PB0 ) )
10
    {
11
      LCDGotoXY( 0, 0 );
12
      LCDWriteString("Oben ");
13
    }
14
    else {
15
      LCDGotoXY( 0, 0 );
16
      LCDWriteString("Unten");
17
    }
18
  }
19
}

Dann gehts eben weiter. Nicht etwas tun solange eine Taste gedrückt ist, 
sondern eine gedrückte Taste nur einmal auswerten. Um beim Original zu 
beliben, zb so
1
int main()
2
{
3
  uint8_t oldPin;
4
  uint8_t newPin;
5

6
  uitn8_t cnt = 0;
7

8
  lcd_init( 0 );
9

10
  PORTB |= ( 1 << PB0 );
11

12
  oldPin = PINB & ( 1 << PB0 );
13

14
  LCDWriteIntXY( 4, 1, cnt, 2 );
15

16
  while( 1 )
17
  {
18
    newPin = PINB & ( 1 << PB0 );
19

20
    if( newPin != oldPin )   // gibts einen Unterschied zu 'vorher'
21
                             // wenn ja, dann ist die Taste entweder
22
    {                        // gedrückt oder losgelassen worden
23
      cnt++;
24
      LCDWriteIntXY( 4, 1, cnt, 2 );
25
    }
26
    oldPin = newPin;
27

28
    _delay_ms( 10 );
29
  }
30
}

(@Alle: Ja ich weiß, die Entprellung ist nicht gut gelöst. Aber bei den 
Voraussetzungen ist alles andere noch zu schwer für ihn.)


Und so geht das eben weiter. Eines führt zum anderen.
Als nächstes brauchst du dann eine zweite Taste, so dass du den Wert 
nicht nur erhöhen, sondern auch verringern kannst.
Klappt das, dann kommt eine 2-te Variable ins Spiel, die verändert wird.
Und du musst irgendwie zwischen den beiden umschalten, so dass du beide 
voneinander unabhängig erhöhen/erniedrigen kannst.
Dazu brauchst du eine weitere (3-te) Taste, die die Umschaltung macht. 
Und du musst deinem Benutzer irgendwie anzeigen, welche der beiden 
Zahlen er gerade verändert.

Aber Grundvoraussetzung ist es nun mal, dass du Tasten auswerten und 
Aktionen daran knüpfen kannst. Perfekt um das zu üben.
#3315393
Lesenswert?

Sebastian M. schrieb:
> Karl Heinz Buchegger schrieb:
>> lcd_init( 0 );
>
> das ist doch aber nicht der Aufruf der funktion in meinem Projekt oder?
> Hier lautet deiser Befehl InitLCD(0).

OK. Dann eben so.
Ich hab nicht bei jedem Aufruf der vorgefertigten Funktionen nachgesehen 
(*), ob sich die Funktion wirklich so schreibt. Dazu hast du ja die 
'Vorlage' mit dem Originalcode, in dem man schnell und einfach nachsehen 
kann.

(*) das ist von hier aus nämlich recht mühsam zu bewerkstelligen. Aber 
du hast ja den Code vor dir - sieh nach, wie die Funktion wirklich 
heißt. Aus dem Zusammenhang sollte klar sein, welche Funktion gemeint 
ist.
#3315452
Lesenswert?

Sebastian M. schrieb:
> Ehrlich gesagt, verstehe ich jetzt nicht was dass oben für
> Codeausschnitte sind? Der erste ist ja nur ein Test, knopf drücken =
> Anzeige.
>
> Aber sagt
>
1
> PORTB |= ( 1 << PB0 );
2
>
>
> nicht aus , dass der Ausgang auf logisch 1 gesetzt werden soll?


Nein, nicht nicht in diesem Fall.
Denn der Pin PB0 am Port B wurde ja nicht mittels DDRB auf Ausgang 
programmiert. Daher ist er nach wie vor ein Eingang und daher schaltet 
diese Anweisung den Pullup Widerstand für diesen Pin ein.

AVR-GCC-Tutorial

> Der erste ist ja nur ein Test
Aber offenbar einer, den du in seiner Einfachheit nicht komplett 
verstehst.
Üben!
Solche Dinge, wie die Zusammenhänge der DDRx, PORTx und PINx Register 
dürfen kein Problem sein. Sowas musst du einwandfrei erkennen können, 
wenn du es siehst.
Denn sonst unterhalten wir uns über eine einfache Blinddarmoperation, 
dessen ausführender Arzt Schwierigkeiten beim Aufkleben eines Pflasters 
hat. Keine guten Voraussetzungen.
OP #3315595
Lesenswert?

1
int main()
2
{
3
  uint8_t oldPin; // Variable deklarieren
4
  uint8_t newPin;// Variable deklarieren
5

6
  uitn8_t cnt = 0; //setzte cnt=00
7

8
  lcd_init( 0 ); // LCD initialisieren
9

10
  PORTB |= ( 1 << PB0 ); // Pin0 pull up ein
11

12
  oldPin = PINB & ( 1 << PB0 ); // oldPin ist =1 wenn pb0=1
13

14
  LCDWriteIntXY( 4, 1, cnt, 2 ); // schreibe an LCD zeile 1 spalte 4 
15
                                  //dem wert von cnt, zweistellig
16

17
  while( 1 )
18
  {
19
    newPin = PINB & ( 1 << PB0 );// newPin ist =1 wenn pb0=1
20

21
    if( newPin != oldPin )   // gibts einen Unterschied zu 'vorher'
22
                             // wenn ja, dann ist die Taste entweder
23
    {                        // gedrückt oder losgelassen worden
24
      cnt++;                 //erhöhe cnt um 1
25
      LCDWriteIntXY( 4, 1, cnt, 2 ); // schreibe an LCD zeile 1 spalte 4 
26
                                      //dem wert von cnt, zweistellig
27

28
    }
29
    oldPin = newPin;   // gleichsetzen
30
 
31
    _delay_ms( 10 );   // 10ms warten
32
  }
33
}

das ist ja alles schön und gut, aber weiterbringen tut mich das doch 
auch nicht. was bringt das? an welcher stelle ist das sinnvoll?
#3315627
Lesenswert?

Sagtest du nicht, du willst üben?

Dann übe! Und fang endlich an, nicht nur "malen nach Zahlen" zu 
betreiben, sondern deine Programme selbst zu entwickeln!
Den Grundstein hab ich dir gelegt um daraus das Programm zu entwickeln. 
Die weitere Entwicklung wirst du aber selber machen müssen. Denn letzten 
Endes willst DU ja dieses Projekt stemmen, nicht ich. Ich helfe dir 
nur, wenn du nicht mehr weiterkommst (und glaub mir, es wäre für mich 
wesentlich einfacher das Programm einfach zu schreiben als dich da durch 
die Entwicklung zu begleiten. Die 30 Minuten, die ich für das 
vollständige Programm brauchen würde, sind schon lange um)
OP #3316030
Lesenswert?

Guten Morgen,

ich habe mich mal um die taster gekümmert, bitte mal durchschauen.
Habs nochmal verbessert.

1
while(1)
2
    {
3
      // ### Zeit einstellen ###  
4

5
      
6
      
7
      
8
      // Select Key
9
      newPin = PINB & ( 1 << PB2 );    
10
      
11
      if (newPin != oldPin)
12
      {
13
        selection ++;
14
        
15
        if (selection ==3)
16
        {
17
          selection=0;
18
        }
19
          
20
      }
21

22
      // --- Up Key ---
23
      newPin = PINB & ( 1 << PB1 );
24
      
25
      if (newPin != oldPin)
26
      {
27
        
28
        if (selection ==1)      // Auswahl ist auf Stunden
29
        {
30
          hr++;
31
          if (hr==100)      // Wenn Stunde =100 setze wieder 0
32
          {
33
            hr=0;
34
          }
35
        }
36
        
37
        if (selection ==2)      // Auswahl ist auf Minuten
38
        {
39
          min++;
40
          if (min==60)      // Wenn Minute =60 setze wieder 0
41
          {
42
            min=0;
43
          }
44
        }
45
      
46
        
47
        if (selection ==0)
48
        {
49
          break;
50
        }
51
      }
52
        // --- --- ---
53
        
54

55
      // --- Down Key ---
56
      newPin = PINB & ( 1 << PB0 );
57
        
58
      if (newPin != oldPin)
59
      {
60
          
61
        if (selection ==1)      // Auswahl ist auf Stunden
62
        {
63
          hr--;
64
          if (hr==-1)      // Wenn Stunde =100 setze wieder 0
65
          {
66
              hr=99;
67
          }
68
        }
69
          
70
        if (selection ==2)      // Auswahl ist auf Minuten
71
        {
72
          min++;
73
          if (min==-1)      // Wenn Minute =60 setze wieder 0
74
          {
75
            min=59;
76
          }
77
        }
78
          
79
        if (selection ==0)
80
        {
81
          break;
82
        }
83
        // --- --- ---            
84
      }
85
        
86
        
87
    }
OP #3316261
Lesenswert?

So, habe jetzt auch noch, wie ich glaube,die LCD Aktualisierung ergänzt. 
Das siht dann für dem DOWN KEY exemplarisch so aus:

1
// --- Down Key ---
2
      newPin = PINB & ( 1 << PB0 );
3
        
4
      if (newPin != oldPin)
5
      {
6
          
7
        if (selection ==1)      // Auswahl ist auf Stunden
8
        {
9
          hr--;
10
          if (hr==-1)      // Wenn Stunde =100 setze wieder 0
11
          {
12
            hr=99;
13
          }
14
        LCDWriteIntXY(11,0,hr,2);
15
        }
16
          
17
        if (selection ==2)      // Auswahl ist auf Minuten
18
        {
19
          min++;
20
          if (min==-1)      // Wenn Minute =60 setze wieder 0
21
          {
22
            min=59;
23
          }
24
        LCDWriteIntXY(11,0,min,2);
25
        }
26
          
27
        if (selection ==0)
28
        {
29
          break;
30
        }
31
        // --- --- ---

Jetzt fehlen noch die Curserpositionen und die eigentliche 
Timerfunktion.
OP #3316944
Lesenswert?

Hey,

zur Info, ich habe jetzt zumindest den Ursprünglichen Code zum laufen 
bekommen. In der Schaltung von der Homepage fehlte die Verbindung von 
Pin 22 (AGND) zu GND und 21(AREF) zu +5V.

Wenn ich jetzt eine Zeit einstelle und starte:

2min eingestellt und gestartet:
1
Anzeige:
2
00:02:55
3
...
4
00:02:00
5
00:02:99
6
00:02:98
7
00:02:97
8
...
9
00:02:00
10
00:02:99
11
00:02:98
12

13
etc...

liegt das vielleicht an dem Timer dings?
1
ISR(TIMER1_COMPA_vect)
2
{
3
  clock_millisecond++;
4
  if(clock_millisecond==1000)
5
  {
6
    clock_second--;
7
    clock_millisecond=0;
8
    if(clock_second==-1) //-1
9
    {
10
      clock_minute--;
11
      clock_second=59;
12

13
      if(clock_minute==-1) //-1
14
      {
15
        clock_hour--;
16
        clock_minute=59;
17
      }
18
    }
19
  }
20
}
#3317235
Lesenswert?

Hier sitzt der Übeltäter
1
volatile char       clock_second=0;
2
volatile char       clock_minute=0;
3
volatile char       clock_hour=0;

hier ist nicht definiert ob ein char signed oder unsigned sein soll.
So wie die Vergleiche hier sind
1
...
2
    if(clock_second==-1) //-1
3
...

müssen das signed Werte sein.

Also
1
volatile signed char       clock_second=0;
2
volatile signed char       clock_minute=0;
3
volatile signed char       clock_hour=0;
Gast #3317324
Lesenswert?

Wahrscheinlich es liegt an die Timer Dinge, es ist die Timer
Funktionalität die Probleme gibt.

Es scheint dass das Problem ist das deine Sekunden Counter in eine
Variable ohne Vorzeichen gespeichert ist.

Also, im General jede Variable ist nur ein Sammlung von Bits die
irgendwo in den Arbeitsspeicher des Mikrocontroller liegen. Wie die Bits
interpretiert werden stellt man ein durch den Typ Deklaration.


Zum Beispiel:
1
char a = 0;  // 8 bit variable (mit oder ohne Vorzeichen abhängig von Kompilator/Plattform) und Anfangswert = 0 
2
unsigned char b = 0; // 8 bit variable ohne Vorzeichen und Anfangswert = 0 
3
signed char c = 0; // 8 bit variable mit Vorzeichen und Anfangswert = 0

was passiert wenn man eins subtrahiert:
1
a--;  // a hat jetzt ein Wert von -1 oder 255 (hängt von ob der Kompilator char als ein Typ mit oder ohne Vorzeichen nimnt  )  
2
b--; // b hat jetzt ein Wert von 255 ( Typ ohne Vorzeichen, 0 ist die Minimalwert)  
3
c--; // a hat jetzt ein Wert von -1 ( Typ mit Vorzeichen, -127 ist die Minimalvert. Analogisch zum der Fall mit Variable b, wenn b ein wert von -127 hätte und eins davon subtrahiert wird, dann würde c ein Wert von +127

Wieso sieht man 00:02:99 statt 00:02:255? Ich nehme an, dass wenn deine
Anzeige Funktion ein Wert mit Mehr Stellen als erwarten kriegt dann
Zeigt die die Maximale Wert die man mit die gewünschte Stellenmenge
anzeigen kann. Ich bin aber nicht sicher, ich hab fast kein Ehrfahrung
mit avr gcc und überall kein mit diese LCD Code.

Wenn du Englisch verstehen kannst (es ist sowieso extrem schwer
Programmieren zu Lernen ohne Englisch zu verstehen zu können) lies mal
den Artikel hier: https://en.wikipedia.org/wiki/C_data_types

Bisschen offtopic:

Ich weiss dass das ganze Ding an Anfang sehr verwirrend aussehen kann.
Man muss gleichzeitig auf Software und Hardware aufpassen: Dinge wie:
versorgt den Spannungsquelle eine gleiche Spannung? Auch under Last?
Sind die Kondensatoren für den Quarz die Richtige wert? Hab ich die
richtige Fuses am Kontroller programiert? Benutzt den Projektcode
irgendwelche nicht Standarte Erweiterungen und werden die von den
Kompilator die ich benutze Unterstützt? und viele viele mehr ähnliche
Fragen...

Wenn aber in die Ende man sein Projekt zu eine korrekt funktionierende
Zustand bringt alle diese Schwierigkeiten blenden in Vergangenheit aus.
Mindestens bis man genug zum Spielen mit seine neue Gadget hatte und ein
neues und mehr kompliziertes Projekt annimmt.
OP #3318378
Lesenswert?

wunder bar, danke euch beiden.

Bin gerade am rumspielen, klappt auch ganz gut.

aber ein problem bekomm ich nicht weg, und zwar ist das der blinkende 
Cursor.

Ich habe folgende Änderungen versucht:

LCD.h
1
...
2
#define LS_BLINK 0B00000001 //geändert auf 0B00000000
3
#define LS_ULINE 0B00000010 //geändert auf 0B00000000
4
...
5
#define LCDClear() LCDCmd(0b00000001)    //geändert auf 0b00000000
6
#define LCDHome() LCDCmd(0b00000010);    //geändert aud 0b00000000

ohne Erfolg.

LCD.c
1
...
2
//Now the LCD is in 4-bit mode
3

4
  LCDCmd(0b00001100|style);    //geändert auf ohne |style
5
  LCDCmd(0b00101000);      //function set 4-bit,2 line 5x7 dot format
6
...

ohne erfolg.

Ich habe sowohl alles einzeln, als auch in Kombination probiert.
Habt ihr noch eine Idee?

PS: Die Anweisungen habe ich von hier
http://www.mikrocontroller.net/articles/AVR-Tutorial:_LCD

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