mikrocontroller.net

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


Autor: Kai Bruhns (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.
# 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 )
   }
}

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();
//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;
      }
   }
}
//
   while (1) {
  PORTB = ~PORTB;
  warte_ein ();       // Funktionsaufruf
  PORTB = ~PORTB;
  warte_aus ();
}
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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();
//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;
      }
   }
}

In C werden Funktionen nicht in andere Funktionen eingebettet.
Eine ISR ist eine Funktion für sich und steht daher auch für sich.
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 )
   {
   }
}

Autor: bartsch (Gast)
Datum:

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

Autor: bartsch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
s/while-Schleifen/Funktionen/

Autor: Kai Bruhns (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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$

Autor: Kai Bruhns (Gast)
Datum:

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

Autor: dummi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
while ( millisekunden == 1000 );

Syntax ist so besser aber Sinn nicht.

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
while (milisekunden!=1000); ist noch viel besser

Autor: Kai Bruhns (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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$

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Kai Bruhns (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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"

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
    while( millsekunden != 1000 )
      ;

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

Autor: Kai Bruhns (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Überleg dir dafür
void warte_ein (void) {
   unsigned int i; // Schleifenvariablen erstmal 3 sekunden an
   for( i = 0; i < 3; i++ ) {
      while ( millisekunden!=999 );
   }
}

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.

Autor: Kai Bruhns (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.