Forum: Compiler & IDEs Attiny22 Zeitschaltung 6 Std aus und 10 Minuten an.(anfängerfragen)


von Kai Bruhns (Gast)


Lesenswert?

Hi ich komme aus dem Linux berreich und habe kaum Ahnung von C.
Skripten kann ich wie ein großer! schleifen for ++ alles nix neues im 
grunde habe ich damit auch nicht das Problem.

Das ich über C noch einiges nachlesen muß weiß ich.
Warum ein Attiny22?
Weil ich den noch rumliegen habe von einem IR einschlalter.
Und eigentlich ist es garnicht so schlecht es so zu machen.
Dan bin ich gezwungen mal ins dateblatt zu schauen und mich damit auch 
auseinander zu setzen

Nun muß ich noch wissen was ich machen will das ist meist das 
schwierigste.
Ich könnte eine relaysteuerung brauchen (24 Volt)
Als schonmal keine Baumarktlösung möglich.
Runter mit den 24 V und 5 V davon gemacht.
anstatt eine Relay erstmal eine LED angeschlossen.
Und blinken lassen funkt gut.
Da der ATtiny22 einen internen Timer hat will ich den auch nehmen.
Die tolleranz ist OK.
Ich versuche mir einen Timer einzurichten der
der 6 Stunden wartet und dann ein Relay für 10  Minuten anzieht im Loop.
Ich habe in Netz schon viel gefunden aber einmal ist es basecom
oder asm.
Da ich aber mehr darüber lernen will ist es wohl besser bei einer 
Sprache zu bleiben.Also C (wurde mir empfohlen).

Ich habe in dem code noch überflüssige dringelassen weil ich es später 
weite aufbauen und experementieren will und vielleicht noch ein schalter 
und eine programmierung einbauen will.
z.B. eimal drücken für 1 Std wartezeit 2 mal .... usw.
Aber das erstmal nicht.

Mein code läst sich nicht übersetzen weil die Timer aktivirung nicht 
stimmt.
Wie müßte es aussehen und wo hätte ich die infos herkriegen können?
Vielleicht beispiele die bei den ATtiny22 auch funktioniern
http://attiny.com/software/ATtiny22.pdf
Beruflich habe ich nix mit Computer oder Elektonik oder so zu tun.
Das ist nur Hobby.
1
# include <avr/io.h>
2
# include <avr/interrupt.h>
3
 
4
//Variablen für die Zeit
5
volatile unsigned int  millisekunden=0;
6
volatile unsigned int  sekunde=0;
7
volatile unsigned int  minute=0;
8
volatile unsigned int  stunde=0;
9
10
void warte_ein (void) {
11
   unsigned int i; // Schleifenvariablen erstmal 3 sekunden an
12
   for( i = 0; i < 3; i++ ) {
13
      while ( millisekunden = 1000 )
14
   }
15
}
16
17
void warte_aus (void) {
18
   unsigned int i; // Schleifenvariablen erstmal 15 sekunden aus
19
   for( i = 0; i < 15; i++ ) {
20
      while ( millisekunden = 1000 )
21
   }
22
}
23
24
int main(void) {
25
   DDRB = 0xFF;         // Durch diese Anweisung werden alle Pin's von PORTB auf " Ausgabe " gesetzt
26
   PORTB = 0;           // Hiermit wird PORTB auf 0 gesetzt
27
   //Timer 0 konfigurieren
28
   TCCR0 =(1<<CS00) |(1<<CS01);
29
   OCR0=125;
30
 
31
   //Compare Interrupt aktivieren 
32
   TIMSK|=(1<<OCIE0);
33
   //Globale Interrupts aktivieren
34
   sei();
35
//Der Compare Interrupt Handler
36
//Wird aufgerufen wenn TCNT0 = 125
37
//brauch ich das überhaupt?Ist das richtig so?
38
//oder wie anders?
39
 ISR(TIMER0_OVF0_vect) {
40
   millisekunden++;
41
   if(millisekunden==1000)
42
   {
43
      sekunde++;
44
      millisekunden=0;
45
      if(sekunde==60)
46
      {
47
         minute++;
48
         sekunde=0;
49
      }
50
      if(minute==60)
51
      {
52
        stunde++;
53
        minute=0;
54
      }
55
   }
56
}
57
//
58
   while (1) {
59
  PORTB = ~PORTB;
60
  warte_ein ();       // Funktionsaufruf
61
  PORTB = ~PORTB;
62
  warte_aus ();
63
}
64
}

von Karl H. (kbuchegg)


Lesenswert?

Kai Bruhns schrieb:

> Mein code läst sich nicht übersetzen weil die Timer aktivirung nicht
> stimmt.
> Wie müßte es aussehen und wo hätte ich die infos herkriegen können?

Die Info kriegst du aus dem Datenblatt für deinen Prozessor.
Und das wiederrum kriegst du bei Atmel.

von Karl H. (kbuchegg)


Lesenswert?

> Mein code läst sich nicht übersetzen weil die Timer aktivirung
> nicht stimmt.
> Wie müßte es aussehen

Wenn du jetzt noch die Fehlermeldung des Compilers angeben würdest und 
auf welche Zeile sie sich bezieht, dann müssten nicht 20 Leute deinen 
Code auf Verdacht durchsuchen und nach etwas suchen von dem sie nicht 
wissen wie es aussieht.

von Karl H. (kbuchegg)


Lesenswert?

1
int main(void) {
2
   DDRB = 0xFF;         // Durch diese Anweisung werden alle Pin's von PORTB auf " Ausgabe " gesetzt
3
   PORTB = 0;           // Hiermit wird PORTB auf 0 gesetzt
4
   //Timer 0 konfigurieren
5
   TCCR0 =(1<<CS00) |(1<<CS01);
6
   OCR0=125;
7
 
8
   //Compare Interrupt aktivieren 
9
   TIMSK|=(1<<OCIE0);
10
   //Globale Interrupts aktivieren
11
   sei();
12
//Der Compare Interrupt Handler
13
//Wird aufgerufen wenn TCNT0 = 125
14
//brauch ich das überhaupt?Ist das richtig so?
15
//oder wie anders?
16
 ISR(TIMER0_OVF0_vect) {
17
   millisekunden++;
18
   if(millisekunden==1000)
19
   {
20
      sekunde++;
21
      millisekunden=0;
22
      if(sekunde==60)
23
      {
24
         minute++;
25
         sekunde=0;
26
      }
27
      if(minute==60)
28
      {
29
        stunde++;
30
        minute=0;
31
      }
32
   }
33
}

In C werden Funktionen nicht in andere Funktionen eingebettet.
Eine ISR ist eine Funktion für sich und steht daher auch für sich.
1
ISR( TIMER0_OVF0_vect )
2
{
3
  millisekunden++;
4
  if(millisekunden==1000)
5
  {
6
    sekunde++;
7
    millisekunden=0;
8
    if(sekunde==60)
9
    {
10
      minute++;
11
      sekunde=0;
12
    }
13
    if(minute==60)
14
    {
15
      stunde++;
16
      minute=0;
17
    }
18
  }
19
}
20
21
int main(void)
22
{
23
   DDRB = 0xFF;         // Durch diese Anweisung werden alle Pin's von PORTB auf " Ausgabe " gesetzt
24
   PORTB = 0;           // Hiermit wird PORTB auf 0 gesetzt
25
26
   //Timer 0 konfigurieren
27
   TCCR0 =(1<<CS00) |(1<<CS01);
28
   OCR0=125;
29
 
30
   //Compare Interrupt aktivieren 
31
   TIMSK|=(1<<OCIE0);
32
   //Globale Interrupts aktivieren
33
   sei();
34
35
   while( 1 )
36
   {
37
   }
38
}

von bartsch (Gast)


Lesenswert?

Zuweisungen (while ( millisekunden = 1000 )) in den while-Schleifen 
(warte_ein und warte_aus)? Ist das Absicht?

von bartsch (Gast)


Lesenswert?

s/while-Schleifen/Funktionen/

von Kai Bruhns (Gast)


Lesenswert?

eigentlich ja
for( i = 0; i < 15; i++ ) {
      while ( millisekunden = 1000 )
   }
er soll i auf 0 setzen und einmal bis die variable millisekunden 1000 
warten.
dann ein dazuzählen bis 1 15 ist und ende.
Dan wird der port umgeschaltet.
(anfänger denken.)

Hier der geänderte Code und die Fehlermeldung

# include <avr/io.h>
# include <avr/interrupt.h>

//Variablen für die Zeit
volatile unsigned int  millisekunden=0;
volatile unsigned int  sekunde=0;
volatile unsigned int  minute=0;
volatile unsigned int  stunde=0;

void warte_ein (void) {
   unsigned int i; // Schleifenvariablen erstmal 3 sekunden an
   for( i = 0; i < 3; i++ ) {
      while ( millisekunden = 1000 )
   }
}

void warte_aus (void) {
   unsigned int i; // Schleifenvariablen erstmal 15 sekunden aus
   for( i = 0; i < 15; i++ ) {
      while ( millisekunden = 1000 )
   }
}

//Der Compare Interrupt Handler
//Wird aufgerufen wenn TCNT0 = 125
//brauch ich das überhaupt?Ist das richtig so?
//oder wie anders?
 ISR(TIMER0_OVF0_vect) {
   millisekunden++;
   if(millisekunden==1000)
   {
      sekunde++;
      millisekunden=0;
      if(sekunde==60)
      {
         minute++;
         sekunde=0;
      }
      if(minute==60)
      {
        stunde++;
        minute=0;
      }
   }
}

int main(void) {
   DDRB = 0xFF;         // Durch diese Anweisung werden alle Pin's von 
PORTB auf " Ausgabe " gesetzt
   PORTB = 0;           // Hiermit wird PORTB auf 0 gesetzt
   //Timer 0 konfigurieren
   TCCR0 =(1<<CS00) |(1<<CS01);
   OCR0=125;

   //Compare Interrupt aktivieren
   TIMSK|=(1<<OCIE0);
   //Globale Interrupts aktivieren
   sei();

//
   while (1) {
  PORTB = ~PORTB;
  warte_ein ();       // Funktionsaufruf
  PORTB = ~PORTB;
  warte_aus ();
}
}

///////////////

kai@debian:~/Desktop/avr$ avr-gcc -O0 -mmcu=attiny22 blink.c -o foo.elf
blink.c: In function ‘warte_ein’:
blink.c:14: error: expected expression before ‘}’ token
blink.c: In function ‘warte_aus’:
blink.c:21: error: expected expression before ‘}’ token
blink.c: In function ‘main’:
blink.c:52: error: ‘OCR0’ undeclared (first use in this function)
blink.c:52: error: (Each undeclared identifier is reported only once
blink.c:52: error: for each function it appears in.)
blink.c:55: error: ‘OCIE0’ undeclared (first use in this function)
kai@debian:~/Desktop/avr$

von Kai Bruhns (Gast)


Lesenswert?

oder hätte das if( millisekunden = 1000 ) heißen müssen?

von dummi (Gast)


Lesenswert?

while ( millisekunden == 1000 );

Syntax ist so besser aber Sinn nicht.

von ... .. (docean) Benutzerseite


Lesenswert?

while (milisekunden!=1000); ist noch viel besser

von Kai Bruhns (Gast)


Lesenswert?

Arg Immer diese ;;;;;;

nu iss es nur noch
kai@debian:~/Desktop/avr$ avr-gcc -O0 -mmcu=attiny22 blink.c -o foo.elf
blink.c: In function ‘main’:
blink.c:52: error: ‘OCR0’ undeclared (first use in this function)
blink.c:52: error: (Each undeclared identifier is reported only once
blink.c:52: error: for each function it appears in.)
blink.c:55: error: ‘OCIE0’ undeclared (first use in this function)
kai@debian:~/Desktop/avr$

von Karl H. (kbuchegg)


Lesenswert?

Kai Bruhns schrieb:
> Arg Immer diese ;;;;;;
>
> nu iss es nur noch
> kai@debian:~/Desktop/avr$ avr-gcc -O0 -mmcu=attiny22 blink.c -o foo.elf
> blink.c: In function ‘main’:
> blink.c:52: error: ‘OCR0’ undeclared (first use in this function)
> blink.c:52: error: (Each undeclared identifier is reported only once
> blink.c:52: error: for each function it appears in.)
> blink.c:55: error: ‘OCIE0’ undeclared (first use in this function)
> kai@debian:~/Desktop/avr$


Datenblatt lesen!
Ohne kommst du nicht weiter.


Der Tiny22 hat keine Output Compare Unit.
Im Abschnitt über den Timer 0 nachlesen, was der alles kann. Du gibt es 
keine Output Compare Unit.

OCR0   O_utput _C_ompare _R_egister  für Timer _0
OCIE0  O_utput _C_ompare _I_nterrupt _E_nable  für Timer _0

All das ist aber nicht vorhanden. Im Tiny22 kannst du nur den Overflow 
des Timers abhandeln.

von Kai Bruhns (Gast)


Lesenswert?

Ich verstehe das doch richtig das
Das der overflow den (ISR) anschubsen soll der dann einmal
Die sekunden setzt.
und den interupt muß ich aber aktivieren sonst geht es nicht
ich habe
Das in
Beitrag "Interupt bin am Verzweifeln"
neu TIMSK |= ( 1 << TOIE0 );
alt TIMSK|=(1<<OCIE0);
gefunden laut /usr/lib/avr/include/avr/iotn22.h
wird TOIE0 auf geführt
/* Timer/Counter0 Overflow */
#define TIMER0_OVF0_vect    _VECTOR(2)
#define SIG_OVERFLOW0      _VECTOR(2)

übersetzen geht
kai@debian:~/Desktop/avr$ avr-gcc -O0 -mmcu=attiny22 blink.c -o foo.elf
kai@debian:~/Desktop/avr$ avr-objcopy -O ihex -j .text -j .data foo.elf 
blink.hex
kai@debian:~/Desktop/avr$

chip geflasht und ich habe ein Dauerlicht.
Was heisen kann das die schleife oder das ISR nicht läuft.

Hat einer einen simplen test wie ich das testen kann?

von Karl H. (kbuchegg)


Lesenswert?

Kai Bruhns schrieb:

> Hat einer einen simplen test wie ich das testen kann?

Im AVR Studio gibt es einen Simulator. Zu finden unter "Debug"

von Karl H. (kbuchegg)


Lesenswert?

Ah und nochwas.

* Wenn du Fragen zu einem Programm hast, dann zeig das Programm. Es 
spielt dabei keine Rolle, ob du es vorher schon einmal gepostet hast 
oder nicht. Du hast das Programm jetzt verändert und daher ist es ein 
anderes Programm mit möglicherweise anderen Problemen.

* Falls du das noch drinnen hast
1
    while( millsekunden != 1000 )
2
      ;

dann muss ich dir leider sagen, dass dein Programm die Variable 
millisekunden niemals mit dem Wert 1000 vorfinden wird.

von Kai Bruhns (Gast)


Angehängte Dateien:

Lesenswert?

Ja du hast recht bei 1000 wird ja schon umgestellt.
ich hänge das prog mal an.
Moment mal ich habe was
wo ich so schreibe mit dauerleuchten auf der Testschaltung
Geht auf einmal die LED aus und sie fängt an in 18 sekundentakt zu 
blitzen.
Also 15 +3 sind 18 also geht das Timern und ich muß "nur" noch den code 
richtig zurechtfummeln....

von Karl H. (kbuchegg)


Lesenswert?

Überleg dir dafür
1
void warte_ein (void) {
2
   unsigned int i; // Schleifenvariablen erstmal 3 sekunden an
3
   for( i = 0; i < 3; i++ ) {
4
      while ( millisekunden!=999 );
5
   }
6
}

etwas anderes (selbiges für die andere Funktion)

wenn i 0 ist, wird in der while Schleife darauf gewartet, dass 
millisekunden den Wert 999 erreicht. Schön.
Dann gehts in der for-Schleife weiter, i kriegt den wert 1 und dann wird 
wieder gewartet, dass millisekunden 999 wird. Aber millisekunden wird 
noch immer den Wert 999 vom vorhergehenden Schleifendurchlauf haben. So 
schnell zählt dein Timer nicht, dass millisekunden auf 0 setzt, während 
hier gerade mal i um 1 erhöht wurde.

von Kai Bruhns (Gast)


Angehängte Dateien:

Lesenswert?

Ok ich glaube das ich es jetzt ansatzweise habe.
Ich habe
void warte_aus (void) {
   unsigned int i; // Schleifenvariablen erstmal 30 sekunden aus
   for( i = 0; i < 30; i++ ) {
     while( counter!=0 );
    while( counter!=1 );
   }
}

Ich habe festgestellt das ich wohl ein opfer des speed geworden bin.
TCCR0 =(1<<CS00); // das ist wohl das schnellste takt
So wie das jetzt funkt es schon mal ansatzweise.

Ich habe das invertiern jetzt mal direkt in der ISR eingebaut
komischer weise ist die LED 70 sekunden an und 95 Sekunden aus?
Kann ich die aufrufe auch direkt in der ISR machen.

Naja erst mal läuft der Timer ja ich werden mich mal weiter herrumlesen.
Wie man das am besten und verlust ärmsten software mäßig macht

von Karl H. (kbuchegg)


Lesenswert?

Kai Bruhns schrieb:

> Wie man das am besten und verlust ärmsten software mäßig macht

Entweder indem man die _delay_xx Funktionen benutzt, die die Library 
sowieso schon mitbringt.
Oder man wählt den anderen Ansatz:
Du hast ja in deiner ISR sowas wie eine Uhr implementiert, die sauber in 
Minuten und Sekunden zählt.
Am Anfang deiner Warterei kennst du die aktuelle Zeit. zb. 3 Minuten 28. 
Du weißt auch, wie lange du warten musst: 4 Minuten 34. Das heist deine 
Wartezeit ist dann zu Ende, wenn deine Uhr bis

     3  28
  +  4  34
   --------
     7  62    die Sekunden korrigiert  8  02

anzeigt. Wenn deine Uhr bei Beginn der Warterei 4' 34'' war und du in 
einer Schleife wartest, bis die Uhrzeit 8' 02'' ist, dann hast du 4' 
34'' gewartet. Alternativ könnte man natürlich in der ISR eine Uhr 
implementieren, die ganz einfach runterzählt :-)  Du gibst die Minuten 
und Sekunden vor, in der ISR wird das dann bis auf 0 heruntergezählt.

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.