Bascom attiny13 Timer 2 mal nutzen

Matthiasab64

Mitglied
21. Feb. 2012
82
0
6
Brandenburg an der Havel, de
Sprachen
  1. BascomAVR
Hallo,

Ist es möglich den Timer im tiny13 zwei mal zu nutzen?

Gewünscht ist das ein pin abgefragt wird ob er 1 ist oder war - Bewegungsmelder einstellbar 0.2 - 18 s
Wenn eine Bewegung erfasst wurde dann soll eine PWM meinen ausgang ein dimmen und bei 100% bleiben für 30 s
Wenn in den 30 s wieder eine Bewegung erfasst wird fangen die 30 s immer wieder von vorn an wenn nicht dimmt das licht nach ablauf der 30 s aus.

Die Schaltung funktioniert schon so ähnlich, Problem ist nur das erst nach ablauf der 30 s bzw beim ausdimmen neu erfasst werden kann mir fehlt irgendwie die Möglichkeit ein interupt auszulösen

hier mal der code:
Code:
$regfile = "Attiny13.dat"
 $crystal = 1200000
 $hwstack = 10
 $framesize = 17
 $swstack = 0




 Dim An As Byte
 Dim Aus As Byte
 Dim Pwm As Byte





 Config Portb.0 = Output

 Config Pinb.2 = Input

 Tccr0a = &B11110001 : Tccr0b = &B00000010 : Ocr0b = 255

 Ocr0a = 255                                                'Portb.2 = 1

An = 0 : Pwm = 255







Do
   If Pinb.2 = 1 And An = 0 Then

      Do
           Decr Pwm : Ocr0a = Pwm : Waitms 10
            An = 1
         Loop Until Pwm = 0
        Wait 3



      Elseif Pinb.2 = 1 And An = 1 Then


      Elseif Pinb.2 = 0 And An = 1 Then

         Do
           Incr Pwm : Ocr0a = Pwm : Waitms 10
           An = 0
         Loop Until Pwm = 255 Or Pinb.2 = 1


   End If


 Loop

Danke schon mal im vorraus

(ja ich habe schon die suche verwendet aber es gibt zu viele variablen den jeder beschreibt sein Problem anders, vllt such ich auch falsch weil sich mein Problem anders lösen lässt als ichs mir vorstelle)
 
Du hast sicher ein (hochsprachenbasiertes) falsches Bild des Timers. Stell Dir den Timer wie 'ne Uhr vor, die Du programmunabhängig vollständig im Hintergrund laufen lassen kannst.
Dein Programm kann das Laufverhalten der Uhr starten, stoppen, Geschwindigkeit usw beinflussen - Du kannst jederzeit auch einen Blick auf die "Uhr" werfen, oder sie umstellen...

Ansonsten läuft die einfach so im Hintergrund vor sich hin.

Ferner kannst Du ggf (auch komplett in Hardware) ein oder mehrere Pins als PWM laufen lassen.

Und: Der Timer besitzt ggf mehrere Möglichkeiten, bei bestimmten Zuständen Dein (im Vordergrund laufendes) Programm zu unterbrechen (Interrupt), um bestimmte Subroutinen/Unterprogrammes auszuführen, und danach wieder zum Hauptprogramm zurückzukehren.

Es ist also alles nur eine Sache Deines Programmes...
 
Guten Morgen,

Danke Lotadac

Hab mir heut in der Nachtschicht nochmal den Kopf zerbrochen, und siehe da es geht, ist sicher nicht der kürzeste und eleganteste Weg, aber ich bin ja in der Lernphase, ich würde zu gern wieder auf Assambler umsteigen aber im Moment fehlt mir die Zeit, ich weis von früher das man da sehr viel effektiver arbeiten kann.

Hier kurz nochmal der funktionierende Code - Kritik erwünscht, bzw Hinweise für eine bessere Lösung :)

Code:
$regfile = "Attiny13.dat"
 $crystal = 1200000
 $hwstack = 10
 $framesize = 17
 $swstack = 0




 Dim An As Bit
 Dim X As Bit
 Dim Pwm As Byte





 Config Portb.0 = Output
 Config Portb.3 = Output
 Config Pinb.2 = Input

 Tccr0a = &B11110001 : Tccr0b = &B00000010 : Ocr0b = 255

 Ocr0a = 255                                                'Portb.2 = 1

' Interrupts
On Pcint0 Pcint0_isr                                        ' zu ISR springen wenn PCINT2
Enable Pcint0
Pcmsk.2 = 1                                                 'enable PCINT2

'
Enable Interrupts





An = 0 : Pwm = 255







Do

   If An = 0 And X = 1 Then

         Do
           Decr Pwm : Ocr0a = Pwm : Waitms 10
            An = 1
         Loop Until Pwm = 0


        Elseif An = 1 And X = 1 Then
           Reset X
          Wait 3
             Portb.3 = X
         End If

    If Pinb.2 = 0 And An = 1 And X = 0 Then

         Do
           Incr Pwm : Ocr0a = Pwm : Waitms 2
             An = 0
         Loop Until Pwm = 255 Or X = 1

    End If



 Loop

 Pcint0_isr:

    Set X

 Return


Portb.3 hatte mir nur zur Kontrolle der Hilfs Variable gedient, kommt dann noch raus....

gruss Matthias
 
Wenn das ganze wie gewünscht läuft, bist Du ja eigentlich fertig.
Da Du aber trotzdem konstruktive Kritik erbeten hattest, schreib ich mal noch ein paar Sachen dazu.

Was uns hier die Hilfe etwas schwerer macht ist, daß Du uns das Konzept, Deine Lösungsidee nicht vorher mitteilst. Dazu kommt dann noch, daß auch Dein Code nicht übermäßig kommentiert ist. Da muß man sich dann erstmal irgendwie hineindenken. Wenn dann auch keine klingenden Variablen verwendet wurden, machts das auch nicht grade leichter.

Zu Deinem Programm:
Du verwendest als Signaleingang den Interrupt eines Pins. In der ISR setzt Du ein Flag, welches Du im Hauptprogramm pollst. Du könntest genausogut den Pin selbst im Hauptprogramm pollen, wenn das Signal lange genug anliegt (wovon ich mal ausgehe).
Du verwendest Warteschleifen.

Zu Deinem Problem:
Du willst über einen Ausgang ein PWM-Signal ausgeben können.
Auslöser soll ein Flankenwechsel eines Pin sein.
Die Pulsweite soll dann erst langsam hochgefahren werden.
Eine Zeit lang auf max bleiben.
Langsam runtergefahren werden (und dann abgeschaltet?).
Ein erneutes Triggern während der PWM (hoch, an, runter) soll möglich sein, und das ganze zurücksetzen.

Konzeptvorschlag:
Die PWM wird naheliegend als HardwarePWM durch den einen Timer erzeugt.
Du hast folgende Status: Auszustand (PWM-Erzeugung über den CompareOutputMode deaktiviert), steigende Phase, Wartezeit, fallende Phase. Diese Status würde ich in einer Statusvariable festhalten, welche man auch bei Bedarf abfragen kann.
Der Timer erzeugt nebenbei mit seinen Überläufen eine Zeitbasis, welche im Hauptprogramm gepollt wird, und (entsprechend der aktiven Phase) nötige "Veränderungen" vornimmt.
 
Hallo,

Sorry ja stimmt in der eile hab ich gar nichts kommentiert.

Ja hab ich ganz zu Anfang vllt n bissel unübersichtlich erklärt.

Also:

In der Küche unterm Schrank kommt eine weisse Led-stripe, die wird über ein Logiglevel mosfet direkt am Pinb.0 betrieben.
Den Eingang pinb.2 schaltet ein Bewegungsmelder (aber kein standart)http://www.google.de/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&ved=0CCwQFjAA&url=http%3A%2F%2Fwww.mpja.com%2Fdownload%2F31227sc.pdf&ei=K60NU7WnFIeJ7AbLhYHgCA&usg=AFQjCNELdcZfKHaZhM4NlzFmhzu2_fOHwg

Ich möchte das wenn der Bewegungsmelder ein Signal gibt, das die LED´s ein gedimmt werden, wenn jetzt die nächsten 30s kein Signal mehr kommt wird wieder ausgedimmt.
Sollte in den 30s bzw während des ausdimmens ein neues Signal kommen, dann beginnen die 30s wieder von vorn, sollte er schon abgedimmt haben wird von dort wo die PWM gerade war wieder eingedimmt.

Warum nicht mit normalen Bewegungsmeldern? weil die nicht Retriggerbar sind und auch nicht dimmen. Und n haufen Geld kosten die auch, die oben genannten unter dem Namen tk0523 ab 1,50$ zu haben

Das Signal liegt 0.2 - 0.5 s an, würde ich es länger anliegen lassen zB 30s , dann würde der Bewegungsmelder erst nach dieser Zeit neu erfassen.

soweit der Stand als ich das Prog zum laufen hatte

jetzt hab ich im Datenblatt des PIR herausgefunden das der PIR mittels Jumper auf retriggerbar umgestellt werden kann, das würde im Prinzip die Warteschleife und das Pollen ersetzen (glaub ich)

Gruss Matthias
 
Zum Konzeptvorschlag

ist das so gemeint das ich für jede Phase ein Unterprogramm habe?
Das mit dem Timer als Zeitbasis im Hauptprogramm gefällt mir , mir fällts immer noch schwer das alles auseinander zu halten.

Weil da bin ich noch nicht ganz erleuchtet wie wie die Pwm arbeitet (was pwm ist weiss ich schon) nur eben Hardware oder Software und trotz des einen Timers ne Hardware-PWM und den Timer noch für die Zeitfunktion zu nutzen

Gruß Matthias
 
Wenn Du so willst, schon. Was ist denn ein Unterprogramm? Ein Stück des Codes, der von irgendwo aus aufgerufen werden kann, und von dem wieder zurückgekehrt wird.
Ein in sich geschlossener Code-Block. Wo der nun konkret im Programm erscheint, ist relativ egal.
Ob der Block direkt in einem then-Block einer If-Abfrage steht, oder von dort aus aufgerufen wird (call subroutine/Gosub/...), macht für den Controller keinen großen Unterschied.

Dir (und uns) erleichtert es aber ggf die Lesbarkeit des Programmes.

Nochmal was zum Timer:
Für den Mega8 hatte ich in diesem Thread mal umfangreich über die Register des dort verwendeten 16bit-Timers "ausgelassen", und insbesondere später (#27) eine Übersicht der Operationsmodi des Timers zusammengestellt.

Der 8bit-Timer Deines Tiny13 ist ohne InputCaptureUnit und nur 6 Operationsmodi wesentlich weniger potent, im wesentlichen ist das aber trotzdem ähnlich.
Hier stehen Dir nonPWM, singleSlope-PWM und dualSlope-PWM zur Verfügung, wobei jeweils die Reichweite entweder 0xFF sein kann, oder durch OCR0A begrenzt werden kann (eben die 6 Modi).

Weiter mit dem Konzept:
Du willst LEDs gedimmt leuchten lassen, der Controller läuft mit 9,6MHz/MainPrescaler 8 = 1,2MHz, korrekt?
Gehen wir also mal von Mode3 (fastPWM bis 0xFF - singleSlope, beide PWM-Kanäle verwendbar) aus
(mal etwas mit meiner Clock-Calculator-App rumgespielt)
ok...
Wenn der Timer mit einem Prescaler von 64 am effektiven Systemtakt von 1,2MHz hängt läuft er ca alle 13,5ms über. Oder andersrum gesagt: die PWM-Frequenz beträgt dann etwas über 73Hz - sollte also eigentlich hinreichend flimmerfrei sein.
Den gewünschten CompareOutputMode des/der gewünschte/n Kanales/Kanäle kannst Du im entsprechenden Timer-Control-Register einstellen UND jederzeit bei bedarf auch umstellen -> um eben in Deinen Status den PWM komplett an- oder ausschalten zu können, ohne den Timer selbst anhalten zu müssen.
Die LED-Helligkeit kannst Du jederzeit durch Manipulation der entsprechenden OCR-Register verändern.
Soweit erstmal klar.

Unabhängig von diesen PWM-Verhalten kannst Du trotzdem den Überlauf-Interrupt verwenden, wie Du das ja bereits getan hattest...
jetzt eben ca alle 13,5ms.
Wir können aber auch gleich das Interrupt-Anforderungsflag nutzen.
Da Dein Sensor-Signal wesentlich länger anliegt, reicht es auch aus, nur alle 13,5ms "danach zu schauen" (pollen). Also:
Im Haupptprogramm prüfen (if...), ob der Timer übergelaufen ist (Flag)
Wenn ja:
Flag zurücksetzen
prüfen ob das Sensor-Signal anliegt
wenn ja:
Status auf "hochdimmen" schalten
PWM-Output aktivieren (Compare Output Mode)​
aktuellen Status abfragen, und in ein entsprechendes Unterprogramm springen (hochdimmen, an, runterdimmen... aus braucht logischerweise kein Unterprogramm)​
Ende-If-Flag

Im "hochdimmen-Unterprogramm" wird einfach nur der Wert des Compare-Registers erhöht, bis das Maximum erreicht ist, dann wird der Status auf "an" umgeschaltet.
Im "runterdimmen" wird analog dazu dekrementiert bis min, dann wird der PWM-Output abgeschaltet (CompareOutputMode), und der Status auf aus gesetzt.
Im "an" zählst Du einfach 'ne vorgegebene Anzahl an Überläufen (also 13,5ms-Abschnitten), bevor Du auf "runterdimmen" schaltest.
Wenn das Compare-Register so durch alle 256 Möglichkeiten geht, dauert das dimmen je ca 3,5s.
Für den "an-Zähler" brauchst Du also dann mehr als ein Byte. Außerdem muß er beim Umschalten von "hochdimmen" auf "an" zurückgesetzt werden.

Soweit meine erste Idee... man könnte natürlich die PWM- und Überlauffrequenz (=Zeitbasis) erhöhen, und dann auch das hoch-/runterdimmen variabler gestalten (analog zum "an-Zähler") - aber das ist Deine Geschichte...

Grüße
LotadaC

Nachtrag:
Wie gesagt können die Unterprogramme stattdessen auch direkt bei der Statusabfrage stehen (sinnigerweise ist diese als case-of-Konstrukt zu gestalten) - aber separate Unterprogramme sind sicher übersichtlicher.
 
Hallo,

ich sehe schon das mir noch sehr viel Verständnis in Sachen Timer und co fehlt.

Also hab ich mich entschieden die Sache erst mal so wie sie jetzt funktioniert zu verbauen(hab in der Schaltung ne SPI Schnittstelle vorgesehen)
klicht1.JPG



und mich dann mal eingehend mit den Timern beschäftigen.

Gibt es einen guten Ansatz mit dem man das ganze verhalten der Timer überwachen kann? Der Simulator wäre eine Option oder?

Stell mir das so vor das man einen Timer parametriert und dann jedes Register und alle Flags im überblick hat und versteht was bei Überläufen usw geschieht.


Zu der Sache mit dem Takt(9,6MHz) eigentlich bin ich mit der Geschichte durch und hab sie gut verstanden...... aber der Tiny13 :fie:

Gefust auf 9,6MHz mit einem vorteiler von 8 , sollte eigentlich 1,2MHz ergeben
aber wenn ich im oben genannten Prog wait auf 30 s hab , vergeht 1min, also irgendwas geht sich da nicht aus :confused:


Danke für deine Mühe Lotadac

Gruss Matthias
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)