Forum: Compiler & IDEs HILFE ATmega164P Timerfrage


von Sebastian S. (sebastian_s25)


Lesenswert?

Hi Leute

ich bin grad richtig ueberfordert...

Und zwar geht es um folgendes Problem. Ich will eine Relais-Modulebox 
bauen, die:

- 4 Relais mit PWM ansteuern kann

- min. einen Timer hat, mit dem ich alle 40 ms verschiedene Pins 
abfragen kann (abfrage soll 20 ms lang sein, da ich ein signal von 230 V 
bekomme (Optokoppler))

- und der UART sollte auch noch funktionieren, aber nur wenn ein 
bestimmter Modus aktiviert ist (wird da ueberhaupt ein extra timer 
benoetigt?)

So erst hab ichs versucht mitm ATmaga32, da die Pinabfrage noch nicht da 
war...
Jetzt will ich die auch noch haben und schon geht nix mehr.. :(

Der ATmega164P haette zwar auch nur 3 Timer, aber dafuer 6 PWM und die 
gleiche Pinbelegung. Die Pinbelegung ist wichtig, da das Layout schon 
steht... :(

Kann ich den wirkich so hernehmen wie ich will? Ich muesste dann den 
OC2B als Compareunit verwenden, da die anderen Pins dann schon alle 
belegt sind... oder doch noch mal das Layout aendern, und den Timer 1 
freimachen und die Relaysansteuerung auf den OC2B legen?

Und kann ich den PWMs dann unterschiedliche frequenzen geben?

Sorry das sind wirklich doofe fragen, aber wie gesagt, ich bin grad 
ueberfodert und die entscheidung sollte bad moeglichst statt finden...

mfg
Sebastian

von Karl H. (kbuchegg)


Lesenswert?

Sebastian S. schrieb:

> - 4 Relais mit PWM ansteuern kann

Wozu braucht man bei einem Relais PWM?
Halb angezogene Relais gibt es nicht.

> - min. einen Timer hat, mit dem ich alle 40 ms verschiedene Pins
> abfragen kann (abfrage soll 20 ms lang sein, da ich ein signal von 230 V
> bekomme (Optokoppler))

Sample und Holdstufe in Form eines Kondensators ist schon erfunden.

> - und der UART sollte auch noch funktionieren, aber nur wenn ein
> bestimmter Modus aktiviert ist (wird da ueberhaupt ein extra timer
> benoetigt?)

Nein

> So erst hab ichs versucht mitm ATmaga32, da die Pinabfrage noch nicht da
> war...
> Jetzt will ich die auch noch haben und schon geht nix mehr.. :(

von Sebastian S. (sebastian_s25)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Sebastian S. schrieb:
>
>> - 4 Relais mit PWM ansteuern kann
>
> Wozu braucht man bei einem Relais PWM?
> Halb angezogene Relais gibt es nicht.

Die PWM nehm ich her um Strom zu sparen! Die Relays Abfallspannung liegt 
bei einem 24V Relay bei ca. 3 V und der Strom geht da von 33mA auf ca. 
5mA zurueck...

Das ist schon einiges!!

>
>> - min. einen Timer hat, mit dem ich alle 40 ms verschiedene Pins
>> abfragen kann (abfrage soll 20 ms lang sein, da ich ein signal von 230 V
>> bekomme (Optokoppler))
>
> Sample und Holdstufe in Form eines Kondensators ist schon erfunden.

Trotzdem muss ich da eine Abfrage starten koennen und dazu brauch ich 
einen timer.

>
>> - und der UART sollte auch noch funktionieren, aber nur wenn ein
>> bestimmter Modus aktiviert ist (wird da ueberhaupt ein extra timer
>> benoetigt?)
>
> Nein

Das is schon mal gut zu hoeren..

>
>> So erst hab ichs versucht mitm ATmaga32, da die Pinabfrage noch nicht da
>> war...
>> Jetzt will ich die auch noch haben und schon geht nix mehr.. :(

von Karl H. (kbuchegg)


Lesenswert?

Sebastian S. schrieb:

>>> - min. einen Timer hat, mit dem ich alle 40 ms verschiedene Pins
>>> abfragen kann (abfrage soll 20 ms lang sein, da ich ein signal von 230 V
>>> bekomme (Optokoppler))
>>
>> Sample und Holdstufe in Form eines Kondensators ist schon erfunden.
>
> Trotzdem muss ich da eine Abfrage starten koennen und dazu brauch ich
> einen timer.

Niemand sagt, dass ein Timer, der hardwaremässig eine PWM bedient nicht 
auch noch einen regelmässigen Interrupt auslösen darf.

Die Anregung mit dem Kondi bezoge sich auf das "abfrage soll 20 ms lang 
sein". Wenn du die 230V gleichrichtest und mit einem Kondi glättest, 
musst du keine Angst mehr haben, dass du ausgerechnet im 0-Durchgang der 
230V auf den Portpin schaust und so fälschlich ein Abschalten der 230V 
detektierst.

von Sebastian S. (sebastian_s25)


Lesenswert?

Hi

Des is aber ein wenig doof, weil ich die PWM mit 46kHz laufen lasse um 
auch geraeuschfrei zu werden.

und um 20ms zu bekommen muesste ich einen teiler von 1024 also 45Hz. 
Damit bekomm ich dann nur einen Interrupt alle 20ms.

ich bekomm von den 230V nur einen kleinen Puls alle 20 ms, das ist zu 
wenig um einen kondensator zu laden.

Das dass so ist, kommt vom optokoppler, da der nur ab 323 V durchlaesst, 
um ihn nicht zu schiessen...

von Karl H. (kbuchegg)


Lesenswert?

Sebastian S. schrieb:
> Hi
>
> Des is aber ein wenig doof, weil ich die PWM mit 46kHz laufen lasse um
> auch geraeuschfrei zu werden.

Ok.

> und um 20ms zu bekommen muesste ich einen teiler von 1024 also 45Hz.
> Damit bekomm ich dann nur einen Interrupt alle 20ms.
>
> ich bekomm von den 230V nur einen kleinen Puls alle 20 ms, das ist zu
> wenig um einen kondensator zu laden.

Was bedeutet 'klein'?
Wenn man nur oft genug nachsieht, ist auch 'klein' kein Thema mehr. Die 
Frage ist also: Wie oft ist ausreichend?

> Das dass so ist, kommt vom optokoppler, da der nur ab 323 V durchlaesst,
> um ihn nicht zu schiessen...

Hä?

von Sebastian S. (sebastian_s25)


Lesenswert?

Hi

Da durch die Optokopplerdiode ja nur ein gewisser strom fließen darf und 
die Leistung durch die Vorwiderstände (SMD) nicht zu gross sein soll, 
hab ich mir die Maximalspannung ausgerechnet, die an der diode anliegen 
darf. D.h. 323V ((230V*sqrt(2))-2V) müssen am Vorwiderstand abfallen.

Dass heißt aber auch wieder, dass ich nur für die kurze Zeit, in der die 
Spannung über 323V ist, ein signal auf der anderen seite bekomme!

Und ich vermute mal, dass die 1ms oder weniger nicht ausreicht, einen 
Kondensator so zu laden, dass meine 3,3V min 20ms am eingang anliegen, 
da ich ja hier auch noch einen widerstand zu GND benötige, dass sich der 
Kondensator bei nichtanliegenden Signal so schnell wie möglich wieder 
entlädt....

Also will ich es ausnutzen, dass der uC viel schneller ist als mein 
Signal. Sobald ich also meinen 20ms Zyklus starte, soller immer wieder 
nur die Pins abfragen. Und wenn jetzt der Impuls kommt, "läuft" er 
einige male drüber und ich kanns mir über eine variable merken und 
danach verarbeiten...

Ich hoffe ich habs einigermassen verständlich erklärt... Wenn nicht 
bitte sag es, ich muss das üben.... ;)

mfg
Bastian

von Karl H. (kbuchegg)


Lesenswert?

Sebastian S. schrieb:
> Hi
>
> Da durch die Optokopplerdiode ja nur ein gewisser strom fließen darf und
> die Leistung durch die Vorwiderstände (SMD) nicht zu gross sein soll,
> hab ich mir die Maximalspannung ausgerechnet, die an der diode anliegen
> darf. D.h. 323V ((230V*sqrt(2))-2V) müssen am Vorwiderstand abfallen.
>
> Dass heißt aber auch wieder, dass ich nur für die kurze Zeit, in der die
> Spannung über 323V ist, ein signal auf der anderen seite bekomme!

Äh.
Nein.
Eine LED leuchtet auch bei geringeren Stromstärken schon ganz 
ordentlich.

Sinkt die Spannung, dann bleibt der Spannungsanteil der LED nahezu 
gleich. Allerdings sinkt der Spannungsanteil der über dem Widerstand 
abfällt. Geringerer Spannungsabfall am Widerstand bedeutet, es fliesst 
weniger Strom durch den Widerstand und damit auch durch die LED. Die LED 
wird dunkler. Sie wird solange dunkler, bis dann irgendwann ihre 
Helligkeit nicht mehr ausreicht, den im OK mit eingebauten 
Phototransistor durchzusteuern. D.h. da entsteht keineswegs eine 
ultrakurzer Impuls auf der Ausgangsseite.


Ausserdem kann man ja auch schon vor dem Optokoppler gleichrichten und 
mit einem Elko die Spannung stabilisieren.

>
> Und ich vermute mal, dass die 1ms oder weniger nicht ausreicht, einen
> Kondensator so zu laden, dass meine 3,3V min 20ms am eingang anliegen,

Was hast du immer mit deinen 20ms.
20ms sind für einen µC eine halbe Ewigkeit. Wenn er in diesem 20ms 40 
mal auf den Eingangspin schielt, ob sich da was tut, dann wird das ja 
wohl reichen (musst du nachrechnen wie lange deine Pulse wirklich sind). 
Und wenn 40 mal nicht reichen, dann eben 80 mal.

von Sebastian S. (sebastian_s25)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Sebastian S. schrieb:
>> Hi
>>
>> Da durch die Optokopplerdiode ja nur ein gewisser strom fließen darf und
>> die Leistung durch die Vorwiderstände (SMD) nicht zu gross sein soll,
>> hab ich mir die Maximalspannung ausgerechnet, die an der diode anliegen
>> darf. D.h. 323V ((230V*sqrt(2))-2V) müssen am Vorwiderstand abfallen.
>>
>> Dass heißt aber auch wieder, dass ich nur für die kurze Zeit, in der die
>> Spannung über 323V ist, ein signal auf der anderen seite bekomme!
>
> Äh.
> Nein.
> Eine LED leuchtet auch bei geringeren Stromstärken schon ganz
> ordentlich.
>
> Sinkt die Spannung, dann bleibt der Spannungsanteil der LED nahezu
> gleich. Allerdings sinkt der Spannungsanteil der über dem Widerstand
> abfällt. Geringerer Spannungsabfall am Widerstand bedeutet, es fliesst
> weniger Strom durch den Widerstand und damit auch durch die LED. Die LED
> wird dunkler. Sie wird solange dunkler, bis dann irgendwann ihre
> Helligkeit nicht mehr ausreicht, den im OK mit eingebauten
> Phototransistor durchzusteuern. D.h. da entsteht keineswegs eine
> ultrakurzer Impuls auf der Ausgangsseite.
>
Stimmt, da hast du recht, da hab ich nen denkfehler gehabt... Wie der 
Impuls wirklich ausschaut, muss ich aber erst testen, da bei der max. 
Spitze nur 1mA fliesst...
>
> Ausserdem kann man ja auch schon vor dem Optokoppler gleichrichten und
> mit einem Elko die Spannung stabilisieren.
>
Das ist fuer mein Layout aber leider nicht machbar. Ich habe so schon 
nicht genuegend platz und ich verwende 0603er Pads....
>>
>> Und ich vermute mal, dass die 1ms oder weniger nicht ausreicht, einen
>> Kondensator so zu laden, dass meine 3,3V min 20ms am eingang anliegen,
>
> Was hast du immer mit deinen 20ms.
> 20ms sind für einen µC eine halbe Ewigkeit. Wenn er in diesem 20ms 40
> mal auf den Eingangspin schielt, ob sich da was tut, dann wird das ja
> wohl reichen (musst du nachrechnen wie lange deine Pulse wirklich sind).
> Und wenn 40 mal nicht reichen, dann eben 80 mal.

ja da hast du vollkommen recht!! Nur bin ich der Meinung, dass ich immer 
ueber eine gwisse Periode auf die Eingangspins schauen muss.

Ich stells mir so vor. Wenn ich es mit den 40 mal nachschaun mache....

Ich bekomme von einer Sinuswelle innerhalb einer Halbperiode einen Puls 
(laenger oder kuerzer sei jetzt mal dahingestellt). Jetzt schaut mein uC 
alle 500us auf den Pin und sieht 35 mal nichts und 5 mal ein Signal....

Ok ich glaub ich hab grad verstanden was du meinst... Ich kanns ja auch 
ueber eine Zahelvariable machen. D.h. alle 500us oder 250us nen 
interrupt, nachschaun was Sache ist und eine Variable hochzaehlen. Wenn 
ich dann 40 oder 80 erreicht hab dann auswaerten. Vorteil: mein uC is 
immer nur kurz belegt und nicht fuer eine ganze Periode...

Meintest du es so?? Hoff ich mal... ;)

von Karl H. (kbuchegg)


Lesenswert?

Sebastian S. schrieb:

> Ok ich glaub ich hab grad verstanden was du meinst... Ich kanns ja auch
> ueber eine Zahelvariable machen. D.h. alle 500us oder 250us nen
> interrupt, nachschaun was Sache ist und eine Variable hochzaehlen. Wenn
> ich dann 40 oder 80 erreicht hab dann auswaerten. Vorteil: mein uC is
> immer nur kurz belegt und nicht fuer eine ganze Periode...

Ich denke, jetzt hast du's.

Nur würde ich es anders rum machen.

Der µC schielt regelmässig (timergetrieben) auf den Pin.
Zusätzlich gibt es noch eine statische Variable - einen Zähler.
Der zählt aber nicht rauf, sondern runter!
Und zwar so:
1
#define TIMEOUT  80
2
uint16_t lastSeen_1;
3
4
ISR( Timer_Interrupt )
5
{
6
  if ( Eingangspin_1 == 1 ) {     // liegt der 230V Puls an?
7
    lastSeen_1 = TIMEOUT;         // Pulscounter zurücksetzen
8
9
    schalten oder was es auch immer beim "Kanal 1" zu tun gibt
10
    wenn die 230V VORHANDEN sind.
11
  }
12
  else {
13
    if ( lastSeen_1 > 0 ) {       // nix zu sehen von einem Puls
14
      lastSeen_1--;               // registrieren, dass nix zu sehen war
15
16
      if ( lastSeen_1 == 0 )      // ist die 'Timeout'-Uhr abgelaufen?
17
        schalten oder was es auch immer beim "Kanal 1" zu tun gibt
18
        wenn die 230V WEG sind.
19
    }
20
  }
21
}

in vielen Fällen ergibt runterzählen die einfachere Lösung als 
raufzählen. Im Grunde realisierst du eine "Countdownuhr", die von einem 
Puls am Eingang immer wieder auf die Wartezeit zurückgesetzt wird. 
Schafft es die Uhr, bis 0 zu zählen, dann war offenbar im gesammten 
Zeitraum nix von einem Puls zu sehen.
(Das ganze verallgemeinert natürlich jetzt auch schön auf n Eingänge. 
Einfach alles entsprechend oft duplizieren)

Wie schnell und wie lange diese 'Countdown' Uhr zählen muss, hängt jetzt 
natürlich davon ab, wie breit der Puls ist. Deine Countdown Uhr muss auf 
jeden Fall so oft nachsehen, dass es auf jeden Fall mindestens einmal 
Pin-Nachsehen in diesen Puls reinfällt. Das wiederrum hängt aber von der 
Breite des Pulses ab. Drum bin ich weiter oben auch immer so auf 
konkreten Daten zu den Pulsbreiten rumgeritten.

Zu oft kannst du nicht abtasten. Wenn der Interrupt entsprechend oft 
kommt, heißt das einfach nur, dass der Vorgabewert für den Countdown 
entsprechend hoch sein muss, damit er eine Schwingungsperiode der 50Hz 
Netzspannung runterzählen kann ohne abzulaufen.

So. Jetzt hast du einen Timer, der eine 42kHz PWM erzeugt. D.h. an 
diesen Timer kannst du ganz leicht eine ISR anhängen, die den Eingang 
dann ebenfalls mit 42kHz abtastet. Rein aus dem Bauch raus (ohne 
gerechnet zu haben), denke ich, dass das locker ausreicht, so dass du 
mit dieser Frequenz den Eingangspin mit Sicherheit irgendwann bei einer 
1 erwischt, wenn die 230V anliegen. Wenn du den Zähler von 20000 aus 
runterzählen lässt und der schafft es tatsächlich bis 0, dann bedeutet 
das dann, dass du 25 Netzperioden (50Hz) lang keinen einzigen 1-Puls am 
Eingang gesehen hast -> die 230V werden wohl abgeschaltet sein.

von Sebastian S. (sebastian_s25)


Lesenswert?

Hi

Herzlichen Dank fuer deine Erklaerung und Hilfe!!!

Ich werds auch fast so machen wie dus beschieben hast, is wirklich 
einfacher als das was ich gezaubert habe...
1
ISR(TIMER0_COMPA_vect)
2
{
3
  static unsigned char Switch_act = 0x00;
4
  
5
  static uint8_t SensCount = 0x00;
6
7
  if(Switch_PIN & (1<<Switch1))
8
  {
9
    if((Switch & 0x01) == 0x01)
10
    {
11
      Switch_act |= 0x01;       // keine Aenderung, aber Relais ein
12
    }
13
    else
14
    {
15
      Switch_act |= 0x11;       // Aenderung, und Relays ein
16
    }
17
  }
18
  if(Switch_PIN & (1<<Switch2))
19
  {
20
    if((Switch & 0x02) == 0x02)
21
    {
22
      Switch_act |= 0x02;
23
    }
24
    else
25
    {
26
      Switch_act |= 0x22;
27
    }
28
  }
29
  if(Switch_PIN & (1<<Switch3))
30
  {
31
    if((Switch & 0x04) == 0x04)
32
    {
33
      Switch_act |= 0x04;
34
    }
35
    else
36
    {
37
      Switch_act |= 0x44;
38
    }
39
  }
40
  if(Switch_PIN & (1<<Switch4))
41
  {
42
    if((Switch & 0x08) == 0x08)
43
    {
44
      Switch_act |= 0x08;
45
    }
46
    else
47
    {
48
      Switch_act |= 0x88;
49
    }
50
  }
51
52
  SensCount++;
53
54
  if(SensCount == 40)
55
  {
56
    Switch = Switch_act;         // ersten 4 Bit zeigen die geaenderten Pins an, 2. 4 Bit, den allgemeinen Status der Pins
57
58
    SensCount = 0;
59
  }
60
}

muss aber die Werte abspeichern, da ich diese noch ueber Funk an eine 
Steuerung weitergeben muss, dass die auch aktuell bleibt...

Das mit der PWM, die ich verwende is so ne Sache. Dafuer muesste immer 
ein Relais eingeschaltet sein, dass ich dieses Signal auch wirklich 
habe...

Ich nehme jetzt den ATmega164P und nehm den Timer/Counter0 her, da meine 
Relais alle auf Timer/counter1 und 2 passen...

Danke nochmal fuer deine Muehen!!! War bestimmt nicht leich mir das klar 
zu machen :D

von Karl H. (kbuchegg)


Lesenswert?

Sebastian S. schrieb:

> Danke nochmal fuer deine Muehen!!! War bestimmt nicht leich mir das klar
> zu machen :D

Wurscht.
Wichtig ist, dass du das Prinzip verstanden hast.

in deinem Urposting hatte ich den Eindruck, du suchst nach einer Lösung, 
bei der der µC 20ms nichts anderes tut, als dauernd den Eingangspin zu 
überwachen. Also irgendwas mit einer Schleife, die 20ms lang läuft oder 
so.

Und genau das ist auf einem µC praktisch immer der falsche Denkansatz. 
Du musst aufhören in Zeitschleifen zu denken sondern in Einheiten von: 
Mein Programm tastet sich von einem Zeitpunkt zum nächsten Zeitpunkt 
vor. Beim nächsten Zeitpunkt sieht es sich die Situation an, vergleicht 
eventuell mit Variablen, die noch vom letzten Zeitpunkt stammen und 
entscheidet dann, was zu tun ist.
Im Grunde so, wie ein Schachspieler der x Schachpartieen simultan 
spielt. Er geht zu einem Brett, sieht sich die Sache an, macht seinen 
Zug und geht zum nächsten Brett. Immer reihum, bis er irgendwann wieder 
bei diesem Brett ist. Und auch dann macht er wieder dasselbe: Situation 
ansehen, entscheiden, Zug machen - nächstes Brett. Auf die Art spielen 
30 Leute "gleichzeitig" gegen Garri Kasparov. Und das ist ganz was 
anderes, als wie wenn er erst mal auf dem ersten Brett die Partie zu 
Ende spielt, dann auf dem zweiten Brett, etc. etc.

Die Kunst besteht jetzt auf einem µC darin, eine derartige Systematik zu 
finden. Und wenn irgendwelche Zeiten im Spiel sind, dann läuft die 
Lösung praktisch immer über eine ISR, die regelmässig von einem Timer 
ausgelöst wird. Das ist dein Zeittakt und du musst jetzt eine Lösung 
finden, die darauf hinausläuft, dass du alle x Zeiteinheiten in ein 
Zimmer reingehst, dich umsiehst und aus dem, was du JETZT siehst (und 
was du dir auf einem Zettel notiert hast - das sind deine Variablen), 
deine Entscheidungen ableitest.

von Sebastian S. (sebastian_s25)


Lesenswert?

Danke nochmal!!

Ab jetzt werd ich wohl auch mehr interrupts hernehmen!!

Koennte man vielleicht die Ueberschrift aendern, damit andere diesen 
Thread ueber die Suche besser finden koennen? Das hat ja jetzt mehr mit 
Interruptgesteuerter Pinabfrage oder 230V mit uC richtig Abfragen zu 
tun, als mit dem ATmega164P.

Ich hab schon gesehen, ich hab da noch sehr viel zu lernen!!

Aber ich bin ja noch jung und ATMEL gibts noch laenger. :D

mfg

Sebastian

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.