Forum: Mikrocontroller und Digitale Elektronik Attiny13 erstes Programm. Hilfe gesucht !


von Steffen E. (steve9412)


Lesenswert?

Moin moin,
zuerst mal bin ich völliger Newbie in diesem Bereich und habe nicht 
wirklich viel Erfahrung im Bereich programmieren und würde mich über 
hilfreiche Beitrage die mich weiterbringen sehr freuen !

Ich möchte gerne über meinen Attiny13 2 Ausgangskarten(Pollin Bausatz) 
über einen Eingang(Taster) steuern, mit Folgender Funktion:

Wenn die Schaltung Spannung bekommt, soll als erstes Ausgangskarte 1 
einmal 5 Sekunden lang angesteuert werden. Wenn ich nun meinen Schalter 
betätige, soll Ausgangskarte 2 5 Sekunden angesteuert werden. Wenn ich 
nun meinen Schalter erneut betätige soll wiederum Ausgangskarte 1 5 
Sekunden angesteuert werden. Dies soll immer im Wechsel so weiter gehen. 
Wichtig ist, das die Steuerung beim Start immer mit der selben 
Ausgangskarte anfängt.

Ist dies einfach und mit einem Attiny13 zu realisieren ? Kann mir jemand 
bei dem Programm auf die Sprünge helfen ?

MFG Steve

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Steffen Ebeling schrieb:
> Kann mir jemand
> bei dem Programm auf die Sprünge helfen ?

Starte hier:
https://www.mikrocontroller.net/articles/AVR
und mach dann mit dem AVR Tutorial weiter. Wenn du eine LED blinken 
lassen kannst, bist du in der Lage Ausgangspins zu steuern. Weiterhin 
brauchst du für dein Projekt eine Art Uhr, die beim AVR Timer genannt 
wird. Und du musst Eingangspins lesen können.
Das ist erstmal die Grundlage. Feinheiten sind z.B. die Entprellung 
deines Schalters und das Speichern seines Zustandes, damit du die 
Bedingung deines Projekts erfüllst.

: Bearbeitet durch User
von Moby (Gast)


Lesenswert?

Steffen E. schrieb:
> zuerst mal bin ich völliger Newbie in diesem Bereich

Dann ist der Ratschlag meines Vorschreibers sehr zu beherzigen. Nutze 
die genannten Lernhilfen!

> Ist dies einfach und mit einem Attiny13 zu realisieren

Logo.

> Kann mir jemand
> bei dem Programm auf die Sprünge helfen ?

Jetzt ist die erste Frage: Welche Programmiersprache?
Ich empfehle da Assembler, da Du den Controller und dessen Möglichkeiten 
dann mit dem Tiny13 Datenblatt in der Hand gleich von grundauf 
kennenlernst.

> Wichtig ist, das die Steuerung beim Start immer mit der selben
> Ausgangskarte anfängt.

Das wird schon dadurch sichergestellt, daß Dein Programm immer von der 
gleichen Stelle aus anfängt und Du dann eben Deine vorgesehene Karte 
samt eines sogenannten Hardware-Timers aktivierst.

> einmal 5 Sekunden lang

Für sowas brauchst Du diesen Timer des Tiny13.
Der wird in Abhängigkeit von der Taktfrequenz des Controllers zum 
Beispiel so eingestellt, daß er nach Aktivierung durch die Tasterabfrage 
los- und bei 5 Sekunden "überläuft" und dabei was sinnvolles auslöst- 
wie eben das Deaktivieren der aktuellen Karte.

Die Tasterabfrage aktiviert neben dem Timer natürlich auch die nächste, 
richtige Karte. Du hast nur zwei, also kann man sich den aktuellen 
Zustand in einer binären Variable merken (beim Controllerstart auf 0 
gesetzt). Die wird bei Timerablauf einfach noch mit invertiert, damit 
die Tasterabfrage beim nächsten Auslösen wieder die andere Karte 
aktivieren kann.

So weit so einfach- der ganz grobe Ablauf.
Eine solche Taster-Anwendung enthält aber oft noch eine besondere 
Herausforderung: Mechanische Taster prellen. Das heißt, sie können in 
kürzester Zeit mehrfach auslösen. Mit Deinem gemächlichen Vorhaben hast 
Du aber Glück: Das muß Dich nicht interessieren. Die Tasterabfrage tut 
bei aktiviertem 5s-Timer einfach nix...

von oldmax (Gast)


Lesenswert?

Hi
Moin moin,
zuerst mal bin ich völliger Newbie in diesem Bereich und habe nicht
wirklich viel Erfahrung im Bereich programmieren und würde mich über
hilfreiche Beitrage die mich weiterbringen sehr freuen !
Nun, so allgemein wie du dein Anliegen vorbringst, liest sich das wie:" 
Ich brauch ein Programm, wer macht mir das". Das ist jetzt nicht bös 
gemeint, aber es wird ein weiter Weg, bis du ein Programm selbst 
schreiben kannst. Sicherlich hast du den bereits erwähnten Hinweis auf 
die Tutorials gesehen. Die sind gut verständlich und für Übungen bestens 
geeignet. So lernst du die Controller kennnen. Zur Sprache kann ich auch 
noch auf einen Beitrag im Forum von WWW.AVR-Praxis.de unter der Rubrik 
FAQ verweisen. Dort findest du u.A. im Beitrag "keine Angst vor 
Assembler" sicherlich alle benötigten Bausteine für deinen 
Programmwunsch ausführlich beschrieben.
Gruß oldmax

von F. F. (foldi)


Lesenswert?

Moby schrieb:
> Jetzt ist die erste Frage: Welche Programmiersprache?
> Ich empfehle da Assembler, da Du den Controller und dessen Möglichkeiten
> dann mit dem Tiny13 Datenblatt in der Hand gleich von grundauf
> kennenlernst.

Kommt drauf an wie weit du einsteigen willst.
Assembler ist schon eine Hausnummer mit der du dich gewaltig 
beschäftigen muss.
Schau mal nach "Arduino"!
Damit kannst du das nach zwei Tagen realisieren. Nimmst du jetzt noch 
einen "Arduino Nano", kannst du ihn nach bestandenen Tests in eine 
Schaltung auf Lochraster Platinen übernehmen. Wobei ich dir die 
Lochstreifenraster empfehle.
Wenn du mit C programmieren willst, bietet sich auch der ATmega328 an 
(der auf dem Nano ist), weil du z.B. dieses Programm dann locker auf 
einen ATtiny10 ohne große Änderungen laufen lassen kannst.
http://www.ebay.de/itm/Nano-V3-0-ATmega328-16M-5V-Micro-controller-CH340G-board-for-arduino-/371179047627?pt=LH_DefaultDomain_77&hash=item566bfecacb

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

foldi, der TE möchte das alles gerne mit dem ATTiny13 realisieren, was, 
wie wir uns schon einig waren, ohne jedes Problem möglich ist, sonst 
hätte ich auch gleich protestiert.
Das geht in Assembler oder in C, bei einem so überschaubaren Projekt ist 
ASM das simpelste und man lernt den MC richtig gut kennen.
Der Tiny10 ist schon wieder eine andere Liga, die TPI Programmierung 
kann nicht jeder Programmer und man muss mit den Pins ganz schön 
haushalten. Hier würde es gerade reichen...
Da wir nichts darüber wissen, was der TE für Tools hat, nehmen ich mal 
an, das der Tiny13 gerade da ist und programmiert werden kann.

von Ingo L. (corrtexx)


Lesenswert?

Ich hab da grad mal Bock drauf:
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define KARTE1    PB0
5
#define KARTE2    PB1
6
#define TASTER    PB2
7
8
9
10
int main(void)
11
{
12
  // Timer
13
  TCCR0A |= (1<<WGM00) | (1<<WGM01);    // CTC
14
  OCR0A = 149;              // 9,6MHz / ((149+1) * 64) = 1KHz
15
  TIMSK0 |= (1<<OCIE0A);          // Capture Interrupt
16
  TCCR0B |= (1<<CS00) | (1<<CS01);    // Prescaler 64
17
  
18
  // IOs
19
  PORTB = 0;
20
  DDRB |= (1<<KARTE1) | (1<<KARTE2);
21
  PORTB |= (1<<TASTER);          // Pull-up enable
22
  
23
  // global Interrupt enable
24
  sei();
25
  
26
  
27
    while(1){;
28
        //Nothing to Do 
29
    }
30
}
31
32
/* 1kHz */
33
ISR (TIM0_COMPA_vect)
34
{
35
  static uint16_t debounce = 0;
36
  static uint16_t OnTime = 5000;
37
  static uint8_t Kartenwahl = 0;
38
  
39
  if (debounce) debounce--;
40
  
41
  if (!(PINB & (1<<TASTER)) && !debounce){
42
    debounce = 100;
43
    OnTime = 5000;
44
    Kartenwahl++;
45
  }
46
  
47
  if (OnTime){
48
    switch (Kartenwahl%2){
49
    case 0: PORTB |= (1<<KARTE1); break;
50
    case 1: PORTB |= (1<<KARTE2); break;
51
    default: break;
52
  }else{
53
    PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) );
54
  }
55
}
Viel Spass damit

von Ulrich F. (Gast)


Lesenswert?

Ingo Less schrieb:
> OnTime = 5000
OnTime ist, und bleibt, 5000.
Oder habe ich was übersehen?

von Ingo L. (corrtexx)


Lesenswert?

Ulrich F. schrieb:
> OnTime ist, und bleibt, 5000.
> Oder habe ich was übersehen?
Warum? Wird einmal auf 5000 initialisiert und wird dann decrementiert.
Erst bei erneutem drücken des Tasters wird die Variable wieder auf 5000 
gesetzt. Stichwort static


Edit:
Ja sorry, das Decrement fehlt :(
1
 if (OnTime) OnTime--;

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Da ist es aber nicht egal, wie der Schalter beim Start steht.
Es soll ja in jedem Fall erst Karte 1 laufen, und beim Umschalten dann 
Karte 2. Man sollte also den Startzustand des Schalters in einem Flag 
speichern und den Schalter damit vergleichen. Wenn gleich, dann Karte 1, 
bei Unterschied dann Karte 2.

von F. F. (foldi)


Lesenswert?

Matthias Sch. schrieb:
> foldi, der TE möchte das alles gerne mit dem ATTiny13 realisieren,

Hast recht.

von Karl H. (kbuchegg)


Lesenswert?

Ingo Less schrieb:

> Edit:
> Ja sorry, das Decrement fehlt :(
>
>
1
>  if (OnTime) OnTime--;
2
>

Einen hab ich noch.
Ich hoff, ich hab mich da jetzt nicht vertan.

Wenn während der 5 Sekunden der Taster erneut betätigt wird, kann es 
sein, dass beide Karten angesteuert werden.

Obwohl: der TO hat ja nicht verraten, was in diesem Fall die korrekte 
Reaktion wäre.
Genauso wie er nicht verraten hat, ab wann die Zeit laufen soll. Ab 
niederdrücken oder ab loslassen. Kann man durch gedrückt halten des 
Tasters die 5 Sekunden verlängern oder nicht?

: Bearbeitet durch User
von Steffen E. (steve9412)


Lesenswert?

Moin,
vielen Dank erst mal für die vielen Kommentare ! :)

Matthias Sch. schrieb:
> Starte hier:
> https://www.mikrocontroller.net/articles/AVR
> und mach dann mit dem AVR Tutorial weiter. Wenn du eine LED blinken
> lassen kannst, bist du in der Lage Ausgangspins zu steuern. Weiterhin
> brauchst du für dein Projekt eine Art Uhr, die beim AVR Timer genannt
> wird. Und du musst Eingangspins lesen können.

Ja habe mich auch schon eine Weile mit den Ganzen Grundlagen beschäftig. 
Da das alles für mich Neuland ist, finde ich das es sehr viele 
Informationen auf einmal sind.

Ingo Less schrieb:
> Ich hab da grad mal Bock drauf:#include <avr/io.h>
> #include <avr/interrupt.h>
>
> #define KARTE1    PB0
> #define KARTE2    PB1
> #define TASTER    PB2
>
> int main(void)
> {
>   // Timer
>   TCCR0A |= (1<<WGM00) | (1<<WGM01);    // CTC
>   OCR0A = 149;              // 9,6MHz / ((149+1) * 64) = 1KHz
>   TIMSK0 |= (1<<OCIE0A);          // Capture Interrupt
>   TCCR0B |= (1<<CS00) | (1<<CS01);    // Prescaler 64
>
>   // IOs
>   PORTB = 0;
>   DDRB |= (1<<KARTE1) | (1<<KARTE2);
>   PORTB |= (1<<TASTER);          // Pull-up enable
>
>   // global Interrupt enable
>   sei();
>
>
>     while(1){;
>         //Nothing to Do
>     }
> }
>
> /* 1kHz */
> ISR (TIM0_COMPA_vect)
> {
>   static uint16_t debounce = 0;
>   static uint16_t OnTime = 5000;
>   static uint8_t Kartenwahl = 0;
>
>   if (debounce) debounce--;
>
>   if (!(PINB & (1<<TASTER)) && !debounce){
>     debounce = 100;
>     OnTime = 5000;
>     Kartenwahl++;
>   }
>
>   if (OnTime){
>     switch (Kartenwahl%2){
>     case 0: PORTB |= (1<<KARTE1); break;
>     case 1: PORTB |= (1<<KARTE2); break;
>     default: break;
>   }else{
>     PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) );
>   }
> }

Vielen dank! Könntest du eventuell die einzelnen Programmzeilen mal ein 
wenig erklären, was mit welchen Befehlen genau gemacht wird und wie nun 
mein gewünschter Ablauf entsteht ? Ich kann aus dem Programm nämlich 
nicht genau die Zusammenhänge untereinander deuten. Ich würde das 
Programm gerne verstehen wollen.

MFG

von Steffen E. (steve9412)


Lesenswert?

Karl Heinz schrieb:
> Wenn während der 5 Sekunden der Taster erneut betätigt wird, kann es
> sein, dass beide Karten angesteuert werden.
>
> Obwohl: der TO hat ja nicht verraten, was in diesem Fall die korrekte
> Reaktion wäre.
> Genauso wie er nicht verraten hat, ab wann die Zeit laufen soll. Ab
> niederdrücken oder ab loslassen. Kann man durch gedrückt halten des
> Tasters die 5 Sekunden verlängern oder nicht?

Das Ansteuern beider Karten gleichzeitig, würde in meinem fall keinen 
Fehler und Fehlfunktion in meiner Schaltung hervorrufen.

Beim Auslösen des Schalters wäre eine steigende Flanke besser.


MFG

: Bearbeitet durch User
von oldmax (Gast)


Lesenswert?

Hi
Steffen E. schrieb:
> Beim Auslösen des Schalters wäre eine steigende Flanke besser.

In der Regel ist ein Eingang mit einem internen Pullup Widerstand 
verschaltet. Das bedeutet für deine Schaltung, wenn du keinen externen 
PullDown verwenden willst, das dein Schalter/ Taster genau anders herum 
schaltet. Also, eine steigende Flanke bekommst du dann beim Loslassen.
 Gruß oldmax

von Karl H. (kbuchegg)


Lesenswert?

Steffen E. schrieb:

> Vielen dank! Könntest du eventuell die einzelnen Programmzeilen mal ein
> wenig erklären,

Das würde bedeuten, das Tutorial hier genau noch einmal hinzuschreiben.

> mein gewünschter Ablauf entsteht ? Ich kann aus dem Programm nämlich
> nicht genau die Zusammenhänge untereinander deuten. Ich würde das
> Programm gerne verstehen wollen.

Dann bleibt dir nichts anderes übrig als die Dinge zu lernen. Hier wird 
dir keiner eine 12 Seiten Abhandlung schreiben, die alles im Detail 
erläutert.
Arbeite das Tutorial durch, mach Übungen zu den einzelnen Themenkreisen. 
Das ist der Weg, wie man Dinge lernt.
Schriftsteller zu werden lernt man auch nicht dadurch, dass einem ein 
anderer Schriftsteller seinen Roman Wort für Wort auseinanderklaubt.

Ganz wichtig ist: Das Tutorial nur zu lesen ist zu wenig. Das ist wie 
beim Radfahren. Du kannst hunderte Bücher über radfahren lesen. Solange 
du dich nicht selbst in den Sattel setzt, wirst du dich nicht auf dem 
Rad halten können.

Soviel kann man aber sagen:
zentrales Element ist ein Timer, der durch seine Einstellung einen 
regelmässigen Basistakt (und damit eine definierte Zeitreferenz) 
erzeugt. In genau diesem Takt wird die ISR aufgerufen. Der Rest ist dann 
nur noch: Wenn ich 5 Sekunden benötige, und eine 'Uhr' zur Verfügung 
habe, die mir jede zb Zehntelsekunde einen Beep gibt, dann muss ich 50 
Beeps abzählen, bis 5 Sekunden beisammen sind. Die ISR ist so 
eingestellt, dass sie jede 1 Millisekunde feuert, also muss ich 5000 
derartige 'Feuerungen' abzählen (entweder von 0 bis 5000, oder von 5000 
runter bis 0) um eine Zeit von 5 Sekunden abzumessen.

zusätzlich zum Tutorial:
FAQ: Timer
Aber Timer ist schon etwas für fortgeschrittene Anfänger, auch wenn kaum 
ein Programm ohne sie auskommt. Mit einem Timer umgehen muss man können, 
weil sie praktisch überall vorkommen. Nur ist das (noch) kein Thema, 
wenn man bei 0 einsteigt. Da müssen zuerst andere Dinge verstanden 
worden sein.

: Bearbeitet durch User
von Ingo L. (corrtexx)


Lesenswert?

Karl Heinz schrieb:
> Wenn während der 5 Sekunden der Taster erneut betätigt wird, kann es
> sein, dass beide Karten angesteuert werden.
Ja das stimmt, das kann man ja aber abfangen wenn man will indem man 
einfach die Tasterabfrage blockiert so lange noch eine Karte aktiv is.
1
 if (!(PINB & (1<<TASTER)) && !debounce && !OnTime){
2
 ...
3
 }

von oldmax (Gast)


Lesenswert?

Hi
Karl Heinz schrieb:
> Dann bleibt dir nichts anderes übrig als die Dinge zu lernen. Hier wird
> dir keiner eine 12 Seiten Abhandlung schreiben, die alles im Detail
> erläutert.

Doch Karl Heinz. Im von mir angesprochenem Beitrag der AVR-Praxis 
Gemeinde hab ich das mal gemacht. Nur lesen muss das jeder, der sich 
dafür interessiert, schon selber. Und jetzt noch mal einzelne Auszüge 
davon mundgerecht zu präsentieren, dazu hab ich natürlich keine Lust.
Gruß oldmax

von Ingo L. (corrtexx)


Lesenswert?

oldmax schrieb:
>> Dann bleibt dir nichts anderes übrig als die Dinge zu lernen. Hier wird
>> dir keiner eine 12 Seiten Abhandlung schreiben, die alles im Detail
>> erläutert.

oldmax schrieb:
> Doch Karl Heinz. Im von mir angesprochenem Beitrag der AVR-Praxis
> Gemeinde hab ich das mal gemacht.

Ich glaube Karl-Heinz meint, dass sich jetzt niemand hinsetzt und mein 
kleines Programm beschreibt!

Ich hätte natürlich jede Zeile kommentieren können, aber da war ich zu 
faul zu...

von Karl H. (kbuchegg)


Lesenswert?

Ingo Less schrieb:

> Ich hätte natürlich jede Zeile kommentieren können, aber da war ich zu
> faul zu...

Das ist auch nicht sinnvoll.
Denn Dinge wie
* Wie wird ein Bit gesetzt
* Wie wird es gelöscht"
* Wie fragt man einen Eingang ab
die müssen einfach im Schlaf sitzen, ehe man überhaupt daran denken 
kann, ein Real-World Programm zu schreiben.

Damit ist aber noch lange nicht die Logik, die Idee die im Programm 
steckt, beschrieben. Die Idee hab ich versucht kurz zu skizzieren. Damit 
und mit ein wenig spielen mit Papier und Bleistift und verfolgen wie 
sich die einzelnen Werte ändern, sollte es eigentlich möglich sein, zu 
verfolgen wie sich daraus die gewünschte Funktionalität ergibt. Rein 
durch hinsehen wird ein Anfänger die einzelnen Bestandteile und welche 
Idee sie verkörpern nicht identifizieren, das ist mir schon klar. Aber 
der beste Weg ist immer noch, sich da durchzu'quälen', auch wenn das 
jetzt hart klingt. Hilft aber nichts, da musste jeder mal durch. Und mit 
der Zeit wird man ja auch besser, weil man Dinge, bestimmte Konstrukte, 
wiedererkennt.
Ist wie beim Schachspielen. Die Regeln sind schnell erklärt, aber in 
einem realen Schachspiel steckt mehr als nur die Anwendung der Regeln. 
Als Anfänger kannst du einem Hr. Pfleger stundenlang zu hören, du wirst 
trotzdem nicht verstehen wovon er da redet, bzw. wie er darauf kommt. 
Erst nach einiger Spielpraxis erschliesst sich vieles davon.

: Bearbeitet durch User
von Ingo L. (corrtexx)


Lesenswert?

Karl Heinz schrieb:
> Das ist auch nicht sinnvoll.
Macht meiner Meinung hier auch keinen Sinn, da das Programm genau das 
verkörpert, was er wollte. Somit hat er seine Programmbeschreibung 
selber geschrieben. Nur das "Wo passiert was" muss er sich halt selber 
raus suchen. Ich denke aber, dass ist bei den paar Zeilen kein Ding der 
Unmöglichkeit.

von Greg (Gast)


Lesenswert?

Ich hab da grad mal Bock drauf: // Ich auch, Dank an Ingo Less
1
// Aus der C Bibliothek Funktionsdateien laden
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
// Definition welcher Portpin zu welchen Anschluss gehören soll.
6
#define KARTE1    PB0
7
#define KARTE2    PB1
8
#define TASTER    PB2
9
10
11
// C Programm Hauptschleife
12
int main(void)
13
{
14
  // Timer Inbetriebsetzen hier auf 1khz stellen Wenn abgelaufen löst der Timer einen Interrupt aus.
15
  TCCR0A |= (1<<WGM00) | (1<<WGM01);    // CTC
16
  OCR0A = 149;              // 9,6MHz / ((149+1) * 64) = 1KHz //Vergleichsregister
17
  TIMSK0 |= (1<<OCIE0A);          // Capture Interrupt Vergleichsinterrupt einschalten
18
  TCCR0B |= (1<<CS00) | (1<<CS01);    // Prescaler 64 Vorteiler des Timers siehe Datenblatt vom Tiny
19
  
20
  // IOs  Ein und Ausgänge vorbereiten
21
  PORTB = 0; //Portausgänge alle auf 0 setzen
22
  DDRB |= (1<<KARTE1) | (1<<KARTE2); // 2 Portpinne als Ausgänge machen 
23
  PORTB |= (1<<TASTER);          // Pull-up enable Der Eingangspin mit einem Pullup Widerstand beschalten.
24
  
25
  // global Interrupt enable Freigabe der Interrupt Funktion allgemein
26
  sei();
27
  
28
  
29
    while(1){;  // Hauptschleife ist fertig Mach nichts mehr. Das Programm lebt jetzt nur noch vom Interrupt
30
        //Nothing to Do 
31
    }
32
}
33
34
/* 1kHz */
35
// Programmteil das bei einer Interrupt Auslösung abarbeitet wird.
36
ISR (TIM0_COMPA_vect)
37
{
38
  static uint16_t debounce = 0; // Variable debounce deklarieren 16bit ohne Vorzeichen und wird auf 0 gesetzt
39
  static uint16_t OnTime = 5000;// Variable OnTime 16bit ohne Vorzeichen wird auf 5000 gesetzt.
40
  static uint8_t Kartenwahl = 0;// Variable Kartenwahl 8bit ohne Vorzeichen wird auf 0 gesetzt.
41
  
42
  if (debounce) debounce--;
43
  
44
  if (!(PINB & (1<<TASTER)) && !debounce){ // Tasterabfrage wenn Eingangspin auf 1 ist dann
45
    debounce = 100;// Variable debounce auf 100 stellen
46
    OnTime = 5000;// OnTime auf 5000 stellen
47
    Kartenwahl++;// Zähler Kartenwahl um 1 addieren (Increment)
48
  }
49
  
50
  if (OnTime){// Wenn ONTime abgelaufen? (Bin selber Anfänger)
51
    switch (Kartenwahl%2){// switchanweisung  siehe Grundlagen
52
    case 0: PORTB |= (1<<KARTE1); break;// Wenn Kartenwahl 0 ist dann Portausgang für Karte1 setzen
53
    case 1: PORTB |= (1<<KARTE2); break;// Wenn Kartenwahl 1 ist dann Portausgang für Karte2 setzen
54
    default: break;// Breakanweiseung auch hier bitte die switch Grundlagen lesen
55
  }else{ // Falls weder 0 noch 1 ist dann Portausgänge der beiden Karten auf 0 setzen
56
    PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) );
57
  }
58
}
Viel Spass damit // auch von mir
Ich schliesse mich meinen Vorschreibern an, bitte die Grundlagen 
durchackern. Hier gab es ja schon viele Links

Gruß Greg

von Ingo L. (corrtexx)


Lesenswert?

Greg schrieb:
> if (OnTime){// Wenn ONTime abgelaufen? (Bin selber Anfänger)
1
if (debounce) debounce--; // Taster mit 100ms Entprellen
2
3
if (OnTime){// Während OnTime Karten schalten
4
...
5
}else{ // Falls OnTime abgelaufen, alle Karten deaktivieren
6
    PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) );
7
}

: Bearbeitet durch User
von Ingo L. (corrtexx)


Lesenswert?

Greg schrieb:
> debounce = 100;// Variable debounce auf 100 stellen
Ganau diese Art von Kommentar hilft garnicht.
Hier hätte es heißen müssen "Entprellzeit 100ms".

von Thomas E. (thomase)


Lesenswert?

Ingo Less schrieb:
> Ganau diese Art von Kommentar hilft garnicht.

Ja.

Und wenn, dann sollte er wenigstens richtig sein:

Greg schrieb:
1
IMSK0 |= (1<<OCIE0A);          // Capture Interrupt Vergleichsinterrupt einschalten

mfg.

von Steffen E. (steve9412)


Lesenswert?

Moin Leute,
das Programm läuft wie es oben geschrieben wurde nicht wirklich. 
Ausgangskarte 1 läuft immer dauerhaft und Ausgangskarte 2 geht an wenn 
man den Taster drückt und wenn man Ihn 5 Sekunden hält und wieder los 
lässt, geht Ausgangskarte 2 wieder aus aber auch nur dann.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Steffen E. schrieb:
> Moin Leute,
> das Programm läuft wie es oben geschrieben wurde nicht wirklich.

Welche Version?
Hast du auch die nachträglichen Änderungen noch eingepflegt?

Zum Rest:
Eigentlich ist das Programm so einfach, dass man auch einem Anfänger 
zumuten kann zu analysieren, wie das ganze arbeitet.

Dreh und Angelpunkt ist die Erkentnis, dass die ISR-Funktion jede 1 
Millisekunde aufgerufen wird. Das funktioniert also wie ein Wecker, der 
alle x Zeiteinheiten läutet. Der Benutzer wacht auf, sieht sich um, 
entscheidet was er zu tun hat (anhand seiner Umgebung) und macht die 
entsprechenden Aktionen.

Mit dieser Vorgabe, einem Blatt Papier und Bleistift sollte es 
eigentlich nicht mehr schwer sein, die Funktionalität nachvollziehen zu 
können, bzw. zu ergründen, warum etwas nicht funktioniert.

von Karl H. (kbuchegg)


Lesenswert?

Ingo Less schrieb:
> Greg schrieb:
>> debounce = 100;// Variable debounce auf 100 stellen
> Ganau diese Art von Kommentar hilft garnicht.
> Hier hätte es heißen müssen "Entprellzeit 100ms".

Und um das klar zu stellen: Das ist nur ein willkürlich 
herausgegriffenes Beispiel für sinnlose Kommentierung.
Der Rest der Kommentierung (die nicht von Ingo stammen) ist vom genau 
gleichen Kaliber: sinnlos
Sorry Greg. Aber du hast dir eine Menge Arbeit für nichts gemacht.

: Bearbeitet durch User
von Ingo L. (corrtexx)


Lesenswert?

Steffen E. schrieb:
> das Programm läuft wie es oben geschrieben wurde nicht wirklich.
> Ausgangskarte 1 läuft immer dauerhaft und Ausgangskarte 2 geht an wenn
> man den Taster drückt und wenn man Ihn 5 Sekunden hält und wieder los
> lässt, geht Ausgangskarte 2 wieder aus aber auch nur dann.
Wie hast du deinen Taster angebunden? Wenn du alle Nachträge ins 
Programm eingepflegt hast, dann sollte es funktionieren. Sofern der 
Taster richtig angeschlossen ist.

Aber wie K.-H. schon schrieb. Das Programm ist überschaubar einfach. Es 
soll dich ja auch dazu ermuntern es zu verstehen. Copy&Paste 
funktioniert meist eh nicht auf Anhieb.

von Steffen E. (steve9412)


Lesenswert?

Da ich hier einen Internen Pull-up Widerstand benutze, ist von PB2 auf 
den Taster und von dort auf 0V angeschlossen.

ich habe das Decrement noch eingefügt, bin mir aber auch nicht sicher ob 
das an der richtigen Stelle war. Sonst habe ich nichts mehr eingepflegt.
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
4
#define KARTE1    PB0
5
#define KARTE2    PB1
6
#define TASTER    PB2
7
8
9
10
int main(void)
11
{
12
// Timer
13
TCCR0A |= (1<<WGM00) | (1<<WGM01);    // CTC
14
OCR0A = 149;              // 9,6MHz / ((149+1) * 64) = 1KHz
15
TIMSK0 |= (1<<OCIE0A);          // Capture Interrupt
16
TCCR0B |= (1<<CS00) | (1<<CS01);    // Prescaler 64
17
18
// IOs
19
PORTB = 0;
20
DDRB |= (1<<KARTE1) | (1<<KARTE2);
21
PORTB |= (1<<TASTER);          // Pull-up enable
22
23
// global Interrupt enable
24
sei();
25
26
27
while(1){
28
//Nothing to Do
29
}
30
}
31
32
/* 1kHz */
33
ISR (TIM0_COMPA_vect)
34
{
35
static uint16_t debounce = 0;
36
static uint16_t OnTime = 5000;
37
static uint8_t Kartenwahl = 0;
38
39
if (debounce) debounce--;
40
41
42
if (!(PINB & (1<<TASTER)) && !debounce){
43
debounce = 100;
44
OnTime = 5000;
45
Kartenwahl++;
46
}
47
if (OnTime) OnTime--;
48
49
if (OnTime){
50
switch (Kartenwahl%2){
51
case 0: PORTB |= (1<<KARTE1); break;
52
case 1: PORTB |= (1<<KARTE2); break;
53
default: break;
54
}}else{
55
PORTB &= ~( (1<<KARTE2) | (1<<KARTE1) );
56
}
57
}

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Hast du eigentlich an den Fuses des AtTiny rumgemacht?

Denn wenn du da nichts getan hast, dann stimmt die Zeitberechnung im 
Programm nicht. Der Timer ist so eingerichtet, dass die Zeiten bei 
9.6Mhz Taktfrequenz stimmen. Hast du an den Fuses nichts gemacht, dann 
läuft der Tiny aber nicht mit 9.6Mhz sondern mit 1.2Mhz.

Also Folge davon sind alle Zeiten real dann 8 mal so lang. Aus deinen 5 
Sekunden werden ca. 40 Sekunden. Und die können laaaang sein, wenn man 
vor einem Gerät sitzt und darauf wartet, dass etwas passiert.

Ich hätte hier
1
    switch (Kartenwahl%2) {
2
      case 0: PORTB |= (1<<KARTE1);
3
              PORTB &= ~(1<<KARTE2);
4
              break;
5
6
      case 1: PORTB |= (1<<KARTE2);
7
              PORTB &= ~(1<<KARTE1);
8
              break;
9
10
      default: break;
11
    }
ja dafür gesorgt, dass die Ausgänge mit Sicherheit immer wechselseitig 
geschaltet sind.

: Bearbeitet durch User
von Ingo L. (corrtexx)


Lesenswert?

Karl Heinz schrieb:
> ja dafür gesorgt, dass die Ausgänge mit Sicherheit immer wechselseitig
> geschaltet sind.
Ja, auch sinnvoll... Das kommt davon wenn man solch ein Progrämmchen mit 
heißer Nadel schreibt. :)

von Thomas E. (thomase)


Lesenswert?

Karl Heinz schrieb:
> Hast du an den Fuses nichts gemacht, dann
> läuft der Tiny aber nicht mit 9.6Mhz sondern mit 1.2Mhz.

Wenn es nur um die CKDIV8-Fuse geht, bevor das im Übereifer fehlschlägt:
1
#include <avr/power.h>
2
3
int main(void)
4
{
5
 clock_prescale_set(clock_div_1);
6
.
7
.
8
.

mfg.

von F. F. (foldi)


Lesenswert?

Thomas Eckmann schrieb:
> Wenn es nur um die CKDIV8-Fuse geht, bevor das im Übereifer fehlschlägt:
> #include <avr/power.h>
>
> int main(void)
> {
>  clock_prescale_set(clock_div_1);
> .
> .
> .
>
> mfg.

Ich habe das noch nie verwendet. Wie genau ist das?

von Thomas E. (thomase)


Lesenswert?

F. Fo schrieb:
> Ich habe das noch nie verwendet. Wie genau ist das?

100%.

Damit stellt man den Clock Prescaler ein. Mit dieser Funktion lässt sich 
der Takt auf 1, 1/2, 1/4 und 1/8 einstellen. Unabhängig von der 
Fuse-Voreinstellung.

Das ist alles auch nichts Neues und setzt lediglich ein paar Bits im 
CLKPR. Dieses Register muss aber in einer Timed Sequence beschrieben 
werden, ähnlich dem Watchdog. Das Timing nimmt einem die Funktion ab.

Die berühmt-berüchtigte Fuse macht lediglich die Startvorgabe auf 1/8 
oder 1. Also nicht "festverdrahtet" wie die Einstellung der Taktquelle.

mfg.

: Bearbeitet durch User
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.