Forum: Mikrocontroller und Digitale Elektronik AVR ATtiny2313 mit Timer-Interrupt (CTC-Mode) und Piezo-Summer


von Marcel P. (souko_h)


Lesenswert?

Hallo Profis,

ich bräuchte mal ein bischen hilfe bem denken, da ich nicht soo viel
erfahrung mit AVR's habe und noch beim lernen bin ;-) !

Ich habe von einem Freund eine Platine mit einem Tiny2313, an dem ein
Display im 4 bit-Modus, ein Drehgeber (2-bit Gray-Code gg. Masse -
Auswertung ohne Interrupt) ein Taster (gg. Masse) und einem
Piezo-Schallwandler über BC547 (also Lautsprecher, kein Summer) und
einem Relais über BC547 hängen.

Das ganze soll eine Zeitschaltuhr sein.

Über Drehgeber wird eine Zeit vorgewählt, welche bei Tastendruck anfängt
runter zu zählen. Während die Zeit herunter zählt, soll das Relais
anziehen und bei 0 Sekunden wieder abfallen.

Soweit kein Thema. ABER, ich möchte gerne den Piezo als Summer
verwenden, der kurz piepsen soll, wenn man die Zeit Startet (kurzes
piepen) und eben drei mal piept, wenn die Zeit abgelaufen ist. (So wie
eine Eieruhr)

Wenn ich nun aber die Sekundenzeit über den Timer im CTC-Modus
realisiere, wie bekomme ich dann noch eine PWM hin, um dem Piezo das
piepsen bei zu bringen ?

Der AVR hat keinen externen Oszi oder Quarz. Würde ihn also auf internen
Oszi laufen lassen (8Mhz mit Div8 -> 1Mhz)
Der Summer hängt auf PD2 (INT0).

Irgendwie hängt mein Kopf gerade, und ich brauche mal eine Schubs, wo
ich weiter nach einer Lösung suchen muss.

Grüße, Souko

von c-hater (Gast)


Lesenswert?

Marcel Peterkau schrieb:

> Wenn ich nun aber die Sekundenzeit über den Timer im CTC-Modus
> realisiere, wie bekomme ich dann noch eine PWM hin, um dem Piezo das
> piepsen bei zu bringen ?
>
> Irgendwie hängt mein Kopf gerade, und ich brauche mal eine Schubs, wo
> ich weiter nach einer Lösung suchen muss.

Im Datenblatt. Darin steht u.a., dass der 2313 über ZWEI Timer verfügt.

von Falk B. (falk)


Lesenswert?

@ Marcel Peterkau (souko_h)

>Wenn ich nun aber die Sekundenzeit über den Timer im CTC-Modus
>realisiere, wie bekomme ich dann noch eine PWM hin, um dem Piezo das
>piepsen bei zu bringen ?

Hier ist es ausnahmsweise mal einfach, mit einer Warteschleife zu 
arbeiten.
Also Piepser ON, xx us warten, Piepser aus, xx us warten, das Ganze N 
mal.

>Der AVR hat keinen externen Oszi oder Quarz. Würde ihn also auf internen
>Oszi laufen lassen (8Mhz mit Div8 -> 1Mhz)

Wenn es nur eine grobe EIeruhr werden soll für vielleicht 1 Stunde, dann 
ist das OK.

>Der Summer hängt auf PD2 (INT0).

Dort kommt man so oder so nur per Software ran.

von Marcel P. (souko_h)


Lesenswert?

c-hater schrieb:
> Im Datenblatt. Darin steht u.a., dass der 2313 über ZWEI Timer verfügt.

Ja, nur leider ist die Platine vorgefertigt, und so wie ich das 
verstanden habe, kann ich den PWM des Timers1 nicht auf den PD2 
umbiegen, oder ?

Falk Brunner schrieb:
> Wenn es nur eine grobe EIeruhr werden soll für vielleicht 1 Stunde, dann
> ist das OK.

Es handelt sich eher um Zeitbereiche zwischen 20 bis 300 Sekunden.
Aber eben mit der Genauigkeit einer mechanischen Eieruhr ^^

Falk Brunner schrieb:
> Hier ist es ausnahmsweise mal einfach, mit einer Warteschleife zu
> arbeiten.
> Also Piepser ON, xx us warten, Piepser aus, xx us warten, das Ganze N
> mal.

Hm, das klingt nach Quick&Dirty, aber wäre eine Idee, die ich so 
garnicht gesehen habe. Jaja, der Wald und die Bäume ^^

also grob so (beep einfach so lange auf true, wie es piepsen soll)?
1
if(beep == true)
2
{
3
        PORTD ^= ( 1 << PD2 );   //Pin umschalten
4
        _delay_us(125);          //halbe Periodendauer von 4kHz
5
6
}
7
else
8
{
9
  PORTD &= ~(1<<PD2)             //sei leise wenn beep == false
10
}

von c-hater (Gast)


Lesenswert?

Marcel Peterkau schrieb:

> Ja, nur leider ist die Platine vorgefertigt, und so wie ich das
> verstanden habe, kann ich den PWM des Timers1 nicht auf den PD2
> umbiegen, oder ?

Per Software schon. Zwei Mini-ISRs, von denen eine den Pin einschaltet 
und die andere aus und der Drops ist gelutscht.

Eine Alternative wäre, halt den Sekundentakt mit dem anderen Timer zu 
erzeugen. Prescaler auf 256 und er kann genausoweit zählen wie der 
16Bit-Timer, bloß halt nicht so genau. Aber bei internem Taktgenerator 
als Quelle spielt das wohl keine große Rolle. Notfalls kann man ja per 
OSCCAL tunen, bis es paßt.

Und eine weitere Alternative wäre, die Leiterplatte einfach ein wenig 
umzuarbeiten. Das werden ja keine Tausende sein, sondern eine 
einstellige Stückzahl. Da kann man sowas schonmal machen.

von Marcel P. (souko_h)


Lesenswert?

c-hater schrieb:
> Marcel Peterkau schrieb:
>
>> Ja, nur leider ist die Platine vorgefertigt, und so wie ich das
>> verstanden habe, kann ich den PWM des Timers1 nicht auf den PD2
>> umbiegen, oder ?
>
> Per Software schon. Zwei Mini-ISRs, von denen eine den Pin einschaltet
> und die andere aus und der Drops ist gelutscht.
>
> Eine Alternative wäre, halt den Sekundentakt mit dem anderen Timer zu
> erzeugen. Prescaler auf 256 und er kann genausoweit zählen wie der
> 16Bit-Timer, bloß halt nicht so genau. Aber bei internem Taktgenerator
> als Quelle spielt das wohl keine große Rolle. Notfalls kann man ja per
> OSCCAL tunen, bis es paßt.
>
> Und eine weitere Alternative wäre, die Leiterplatte einfach ein wenig
> umzuarbeiten. Das werden ja keine Tausende sein, sondern eine
> einstellige Stückzahl. Da kann man sowas schonmal machen.

Hm... umarbeiten kommt wohl nicht in Frage, da die Platine ein fertiges 
Teil ist, und er die Software mehrfach verwenden will.

Wenn ich deine Lösung richtig verstehe, schalte ich den Pin ein und 
wieder aus, und das wars.

Ich muss ja aber eine Frequenz irgendwo um die 2-5 kHz erzeugen, damit 
der Piezo nen Ton von sich gibt.

Ich habe von einem anderen bekannten den Hinweis bekomm "nimm doch 
Soft-PWM" - da brauch ich dann doch aber auch einen Timer, oder ?
Geht das dann mit dem Timer1 ?

von Karl H. (kbuchegg)


Lesenswert?

Marcel Peterkau schrieb:

> Wenn ich deine Lösung richtig verstehe, schalte ich den Pin ein und
> wieder aus, und das wars.
>
> Ich muss ja aber eine Frequenz irgendwo um die 2-5 kHz erzeugen, damit
> der Piezo nen Ton von sich gibt.

und da der Timer läuft und läuft und läuft, treten die Timer-Interrupts 
wieder und wieder auf und jedesmal wird die ISR aufgerufen und bei jedem 
Aufruf wird der Pin umgeschaltet und daher .... toggelt dann der Pin.

> Ich habe von einem anderen bekannten den Hinweis bekomm "nimm doch
> Soft-PWM" - da brauch ich dann doch aber auch einen Timer, oder ?
> Geht das dann mit dem Timer1 ?

Lass doch endlich mal den Begriff PWM aus dem Spiel.
Du musst einfach nur einen Pin 0/1 schalten. Quasi eine blinkende LED, 
nur eben ein wenig schneller. Ist doch für einen Timer, der eine ISR 
aufruft überhaupt kein Problem.

von Marcel P. (souko_h)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Lass doch endlich mal den Begriff PWM aus dem Spiel.
> Du musst einfach nur einen Pin 0/1 schalten. Quasi eine blinkende LED,
> nur eben ein wenig schneller. Ist doch für einen Timer, der eine ISR
> aufruft überhaupt kein Problem.

Ja, stimmt... ich brauche ja nur on/off und kein Varviables 
Tastverhältniss !

Ich werde das mal probieren, und dann berichten.
Danke an alle, die mir bisher Anstösse für Lösungen geliefert haben !

von Karl H. (kbuchegg)


Lesenswert?

Marcel Peterkau schrieb:

> Ich werde das mal probieren, und dann berichten.
> Danke an alle, die mir bisher Anstösse für Lösungen geliefert haben !

Aber bitte nicht so, dass du da wieder dauern mit Timer Vorteiler 
ein/aus rummachst.

Mach dir eine golable volatile Variable, die steuert ob in der Timer ISR 
der Pin getoggelt werden soll oder nicht
1
volatile uint8_t buzzerOn;
2
3
ISR( .... Timer 2 ... )
4
{
5
  if( buzzerOn )
6
    PORTD ^= ( 1 << PD2 );
7
}

und um den µC dann laut geben zu lassen, setzt du einfach buzzerOn auf 1 
bzw 0 zum abschalten. Das kann dann nämlich zb in der anderen ISR 
passieren, die sich um die Sekunden kümmert, damit der Buzzer am Ende 
der Zeit im Sekundentakt 3 mal buzzert. Einfach im Sekundentakt buzzerOn 
auf 1 bzw. 0 setzen und gut ists. :-)

von Route_66 (Gast)


Lesenswert?

Hallo!
Das ganze geht natürlich auch mit nur einem Timer. Es hindert dich ja 
niemand, einen 250 µs Interrupt auch für die Sekundenzählung oder den 
Drehgeber mit zu benutzen. In der Main wird für den Piepser einfach 
beep=1 gesetzt, gewartet und dann wieder beep=0. In der Timer ISR wird 
der Pin nur getoggelt, wenn beep==1. Schon sind 2 kHz ferdsch!

von Marcel P. (souko_h)


Angehängte Dateien:

Lesenswert?

Sooo,

ich habe im Anhang mal meinen Sourcecode mit gepostet.
Ja, es ist einige Dinge, welche Copy & Paste aus Tutorials sind grins 
aber wieso das Rad neu erfinden.

Habe das mit dem Piepser jetzt über den 2. Timer mit CTC-Modus gelösst, 
der mir immer wieder den Pin toggelt.

Das ganze einfach in eine if-Schleife verpackt und über eine 
volatile-Variable gesteuert.

Dann habe ich den Encoder doch mit in den Interrupt gehängt.

als nächstes muss ich mir noch überlegen, wie ich das Ding dazu bekomme 
nicht Dauer zu piepsen, sondern im Takt, aber das dürfte kein Problem 
werden.

Danke für die Denkanstösse, manchmal sieht man den Wald vor lauter 
Bäumen nicht ^^

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.