- LiFePO4 Speicher Test         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 13

Thema: Timer, Zähler, zwei Frequenzen

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    20.11.2005
    Beiträge
    88

    Timer, Zähler, zwei Frequenzen

    Anzeige

    Praxistest und DIY Projekte
    Irgendwie stelle ich mir immer noch die Frage, wie realisiere ich z.B. zwei verschiedene Zeiten/Frequenzen bzw. zwei LEDs sollen unterschiedlich schnell blinken mit nur einem Timer. (Mit wait Zeiten im Programm wäre es ja einfach, hält ja aber alles nur auf.)

    Nehmen wir das Beispiel.

    LED 1 im 0,5Hz Takt = 2sec Takt
    LED 2 im 1 Hz Takt = 1sec Takt

    Vom Ansatz würde ich mir nun überlegen. Ich programmiere einen Timer auf 0,5 Hz, lass in der ISR eine Variable X zählen. Von 1 - 2, bei wert 2 fängt er wieder bei 1 an.
    In der Hauptschleife frage ich die Variable X mit einem If ab!

    Ist der Ansatz so richtig, oder löst man sowas anders ?

  2. #2
    Erfahrener Benutzer Robotik Visionär
    Registriert seit
    26.11.2005
    Ort
    bei Uelzen (Niedersachsen)
    Beiträge
    7.942
    Im Prinzip schon, nur gehen die wenigsten Timer so langsam.

  3. #3
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.842
    Umgekehrt. Timer immer die kleinste Einheit.
    Die zählst 1 Sekunde --> LED2
    jedes zweite mal ---> LED1

    Da 1 Sekunde für einen Timer ganzschön lang ist, ist es besser, z.B. 1mS einzustellen, also bei 1000->LED2 bei 2000 -> LED1 uns dann wieder von vorn.

    Durch das Frequenz-Verhältnis von 1:2 gibt es noch mehr Möglichkeiten, aber sei's drum
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    20.11.2005
    Beiträge
    88
    Supi, danke... Also war mein Ansatz ja nicht verkehrt Macht ja auch sinn dann mit 1ms (1khz).. Vielen Dank

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    28.02.2009
    Beiträge
    18
    etwas langsamere Frequenzen bekommst du mit nem Uhrenquarz, allerdings schwingt der immer noch relativ schnell.

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    20.11.2005
    Beiträge
    88
    Ich habe nun mal ein Code, der funktioniert. Aber selbst persönlich finde ich die Lösung nicht so gut. Vll habt ihr ja andere bessere Ideen:
    z.B man viel nun nicht 0,5sek sondern auf 0,2sec Ein/AUS... Dann müsste man mit meinm Prog alles wieder anpassen.

    Code:
    $eeprom
    $eepromhex
    $regfile = "m32def.dat"                                     ' Prozessortyp ATmega32
    $crystal = 16000000                                         ' Taktrate
    $hwstack = 32
    $swstack = 10
    $framesize = 40
    $baud = 4800
    
    
    Config Portb.2 = Output
    Led1 Alias Portb.2
    Config Portb.3 = Output
    Led2 Alias Portb.3
    
    
    Config Lcd = 20 * 2
     Config Lcdpin = Pin , Db4 = Porta.0 , Db5 = Porta.1 , Db6 = Porta.2 , Db7 = Porta.3 , E = Porta.5 , Rs = Porta.4
      Cls
      Cursor Off
    
    
    Config Timer0 = Timer , Prescale = 64
    On Timer0 Timer_irq
    Const Timervorgabe = 6
    Enable Timer0
    Enable Interrupts
    
    
    
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    Start Adc
    
    Dim W As Word
    Dim Taktzaehler As Integer
    Dim 05takt As Bit
    Dim 10takt As Bit
    Dim 20takt As Bit
    Dim Merker1 As Bit
    Dim Merker2 As Bit
    
    
    
    
    Do
    
    W = Getadc(7)
    
    Locate 2 , 15
    Lcd W ; " "
    Waitms 200
    
    If W >= 400 Then
    Merker1 = 1
    Else
    Merker1 = 0
    End If
    
    If W <= 400 Then
    Merker2 = 1
    Else
    Merker2 = 0
    End If
    
    
    
    
    
    Loop
    
    Timer_irq:
      Timer0 = Timervorgabe
    
      If Taktzaehler >= 4000 Then
      Taktzaehler = 0
      End If
    
      Taktzaehler = Taktzaehler + 1
    
    
      If Taktzaehler >= 0 And Taktzaehler <= 500 Then
         05takt = 1
         10takt = 1
      End If
    
      If Taktzaehler >= 500 And Taktzaehler <= 1000 Then
         05takt = 0
         10takt = 1
      End If
    
      If Taktzaehler >= 1000 And Taktzaehler <= 1500 Then
         05takt = 1
         10takt = 0
      End If
    
      If Taktzaehler >= 1500 And Taktzaehler <= 2000 Then
         05takt = 0
         10takt = 0
      End If
    
    
    If 05takt = 1 And Merker1 = 1 Then
    Led2 = 0
    Else
    Led2 = 1
    End If
    
    If 10takt = 1 And Merker2 = 1 Then
    Led1 = 0
    Else
    Led1 = 1
    End If
    
    Return
    End

  7. #7
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.01.2007
    Ort
    Göttingen
    Beiträge
    706
    Aber selbst persönlich finde ich die Lösung nicht so gut.
    Zwar führen viele Wege nach Rom, und Schönheit liegt ja bekanntlich im Auge des Betrachters ( ), aber eine grundsätzliche Regel sollte man konsequent befolgen:
    In Interrupt-Routinen sollte so wenig wie möglich Code stehen, damit die Hauptschleife nicht so lange unterbrochen wird. Während eines Interrupts sind nämlich die anderen Interrupts erstmal blockiert, und daraus können unübersichtliche Verschachtelungen entstehen. Am besten setzt man in der ISR nur ein Flag-Bit, das in der Hauptschleife abgefragt wird. Ist es 1, wird der dazugehörige Code ausgeführt und es anschließend wieder gelöscht - fertig.

    In Deinem speziellen Fall würde ich (...) den Timer z.B. alle 0,1 Sekunden überlaufen und in der ISR ein Flag setzen lassen.

    In der Hauptschleife wird dann das Flag abgefragt. Wenn es 1 ist, inkrementierst Du 2 Zähl-Variablen. Wenn die eine 2 bzw. die andere 5 erreicht hat (und Deine "Merker" gesetzt sind), wird der Status der dazugehörigen LED einfach getoggelt und die Zählvariable auf 0 zurückgesetzt.

    Wenn Du ein paar Zeilen Code brauchst, sag Bescheid. Aber selber schreiben ist viel schöner


    Gruß & Co

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    20.11.2005
    Beiträge
    88
    Hi, danke für die Antwort. Die hat schon viel geholfen Habe das Programm noch nicht testen können, aber ich denke so meinst du das? Meine ISR läuft nur alle 1ms über und somit auch 500ms, 200ms in der Zählervariable.

    Aber wenn ich nun z.B. das Display nur alle Sek bzw hier halbe Sekunde aktualisieren möchte, ist das doch in meinem Code falsch, dann würden die LED nicht mehr richtig blinken wg der Wartezeit oder?
    Wie um gehe ich nun sowas?
    Ich hatte mal gelesen, kontinuerliche LCD Routinen sind nicht vorteilhaft (wg Zykluszeit??)!

    Code:
    $eeprom
    $eepromhex
    $regfile = "m32def.dat"                                     ' Prozessortyp ATmega32
    $crystal = 16000000                                         ' Taktrate
    $hwstack = 32
    $swstack = 10
    $framesize = 40
    $baud = 4800
    
    
    Config Portb.2 = Output
    Led1 Alias Portb.2
    Config Portb.3 = Output
    Led2 Alias Portb.3
    
    
    Config Lcd = 20 * 2
     Config Lcdpin = Pin , Db4 = Porta.0 , Db5 = Porta.1 , Db6 = Porta.2 , Db7 = Porta.3 , E = Porta.5 , Rs = Porta.4
      Cls
      Cursor Off
    
    
    Config Timer0 = Timer , Prescale = 64
    On Timer0 Timer_irq
    Const Timervorgabe = 6
    Enable Timer0
    Enable Interrupts
    
    
    
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    Start Adc
    
    Dim W As Word
    Dim Taktzaehler02 As Integer
    Dim Taktzaehler05 As Integer
    Dim Timer0_flag As Bit
    Timer0_flag = 0
    
    
    Do
    
    W = Getadc(7)
    
    Locate 2 , 15
    Lcd W ; " "
    Waitms 500      'Was ist wenn hier die Zeit nun auf 500ms stehen würde?
    
    
    If Timer0_flag = 1 Then
    Taktzaehler02 = Taktzaehler02 + 1
    Taktzaehler05 = Taktzaehler05 + 1
    Timer0_flag = 0
    End If
    
    If Taktzaehler02 = 200 Then
    Toggle Led1
    Taktzaehler02 = 0
    End If
    
    If Taktzaehler05 = 500 Then
    Toggle Led2
    Taktzaehler05 = 0
    End If
    
    
    Loop
    
    Timer_irq:
      Timer0 = Timervorgabe
    
      Timer0_flag = 1
    
    Return
    End

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    20.11.2005
    Beiträge
    88
    Letztendlich sollte das doch auch so gehen mit der Wartezeit für das LCD ohne die main loop aufzuhalten ?

    Code:
    $eeprom
    $eepromhex
    $regfile = "m32def.dat"                                     ' Prozessortyp ATmega32
    $crystal = 16000000                                         ' Taktrate
    $hwstack = 32
    $swstack = 10
    $framesize = 40
    $baud = 4800
    
    
    Config Portb.2 = Output
    Led1 Alias Portb.2
    Config Portb.3 = Output
    Led2 Alias Portb.3
    
    
    Config Lcd = 20 * 2
     Config Lcdpin = Pin , Db4 = Porta.0 , Db5 = Porta.1 , Db6 = Porta.2 , Db7 = Porta.3 , E = Porta.5 , Rs = Porta.4
      Cls
      Cursor Off
    
    
    Config Timer0 = Timer , Prescale = 64
    On Timer0 Timer_irq
    Const Timervorgabe = 6
    Enable Timer0
    Enable Interrupts
    
    
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    Start Adc
    
    Dim W As Word
    Dim Taktzaehler02 As Integer
    Dim Taktzaehler05 As Integer
    Dim Taktzaehler1000 As Integer
    
    
    Do
    
    
    If Timer0_flag = 1 Then
    Taktzaehler02 = Taktzaehler02 + 1
    Taktzaehler05 = Taktzaehler05 + 1
    Taktzaehler1000 = Taktzaehler1000 + 1
    Timer0_flag = 0
    End If
    
    If Taktzaehler02 = 200 Then
    Toggle Led1
    Taktzaehler02 = 0
    End If
    
    If Taktzaehler05 = 500 Then
    Toggle Led2
    Taktzaehler05 = 0
    End If
    
    If Taktzaehler1000 = 1000 Then
    W = Getadc(7)
    Locate 2 , 15
    Lcd W ; " "
    Taktzaehler1000 = 0
    End If
    
    Loop
    
    
    Timer_irq:
      Timer0 = Timervorgabe
    
      Timer0_flag = 1
    
    Return
    End

  10. #10
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.01.2007
    Ort
    Göttingen
    Beiträge
    706
    Letztendlich sollte das doch auch so gehen mit der Wartezeit für das LCD ohne die main loop aufzuhalten ?
    Ganz genau! So ist es viel eleganter als mit waitms500, die das Programm halt für diese Zeit total lahmgelegt hätten. Und Du bekommst genauso alle 1 Sek. den aktuellen ADC-Wert angezeigt.

    Eigentlich müsste es mit diesem Code super laufen!

    Gruß,

    Daniel

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen