- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Ergebnis 1 bis 10 von 13

Thema: TIME funktioniert nicht beim ATtiny44, wie kann ich das Problem lösen?

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    37
    Beiträge
    5.093
    Ich meinte nicht das du nur 1ms misst.

    In der Hauptschleife fügst du ein delay von 1ms ein (somit hast du einen Schleifendurchlauf von Programmablauf + 1ms).
    Wenn die Lichtschranke ein Fahrzeug erkennt (und vorher noch keines erkannt wurde) setzt du einen Merker (=Fahrzeug erkannt).
    Gleichzeitig setzt du einen Counter auf 0.
    Wenn du ein Fahrzeug erkannt hast (Merker) zählst du in jedem Schleifendurchlauf den Counter hoch.
    Wenn der Counter z.B. 50 erreicht hat (entspricht mindestens 50ms), dann gibst du die die Fahrzeugerkennung wieder frei (Merker "Fahrzeug erkannt" wieder auf "0" setzen).


    Ich hoffe das du es jetzt besser verstanden hast was ich meine.

    Edit: Den Merker benötigst du natürlich für jede Spur ein mal.

    MfG Hannes

  2. #2
    Neuer Benutzer Öfters hier
    Registriert seit
    12.02.2025
    Beiträge
    7
    Hi,

    wenn ich es richtig verstanden habe sollte es so aussehen:

    Code:
            waitms 1
            if Spur_1 = 1 then
              Durchfahrt_1 = 1 : Zeit_1 = 0
            end if
            if Durchfahrt_1 = 1 then
              incr Zeit_1
            end if
            if Zeit_1 = 50 then
              Ampel_1 = 1 : locate 2,1 : lcd "- * -"
              incr Runde_Spur_1 : Z_formatiert = str(Runde_Spur_1)
              locate 3,19 : lcd ; format(Z_formatiert , "  ")
              Ampel_1 = 0 : locate 2,1 : lcd "-----"
            end if
            if Zeit_1 > 1000 then
              Durchfahrt_1 = 0 : Zeit_1 = 0
            end if
    es funktioniert wie meine Version:

    Code:
            if Spur_1 = 1 or Spur_1PZ <> 0 then
              if Spur_1PZ = 0 then
                Ampel_1 = 1 : locate 2,1 : lcd "- * -"
                incr Runde_Spur_1 : Z_formatiert = str(Runde_Spur_1)
                locate 3,19 : lcd ; format(Z_formatiert , "  ")
                Ist_1 = 0 : Soll_1 = 222 : Spur_1PZ = 1
                enable timer0
                Ampel_1 = 0 : locate 2,1 : lcd "-----"
              else
                if Spur_1PZ > 120 then
                  disable timer0
                  Spur_1PZ = 0
                end if
              end if
            end if
    Grüßle, Hermann

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.715
    Blog-Einträge
    133
    Hallo Hermann,

    ich verfolge den thread auch schon einige Tage. Ich denke, eine richtige Entprellung wie für prellende Tasten ist bei Dir nicht nötig. Sobald eine Lichtschranke von einem Auto getriggert wurde, könnte schon eine Runde gezählt werden. Wegen der Lücken im Auto dann einfach die Zählung der entsprechenden Spur für eine notwendige Zeit unterbinden um die Mehrfachzählung bei einer Durchfahrt zu verhindern.

    Das hast Du ja im Prinzip mit der Prellzeit etc. schon verwirklicht.

    Ich schlage dazu, ich nenne es mal "Monoflop" vor:

    Programm:
    Der Timer 0 erzeugt alle etwa 10ms einen compare0a Interrupt
    In der Interruptserviceroutine wird der Ablauf der Monoflops realisiert.
    In der Hauptschleife werden die Lichtschranken abgefragt. (bei Autodurchfahrt werden sie "0")
    Ist eine Lichtschranke "0" und das entsprechende Monoflop = "0" wird die Runde gezählt und die Monoflop Zeit "aufgezogen"
    Der Timer0 hat nach der Ablaufzeit das Monoflop wieder scharf geschaltet. Das Auto ist durch, die Lichtschranke auf "1" und somit bereit für die nächste Durchfahrt.

    Code:
    $regfile = "ATtiny44.DAT"
    $framesize = 24
    $swstack = 20
    $hwstack = 34
    $crystal = 8000000
    
    const deadtime = 100                                        '100 * 10ms of copmare0a interrupt
    
    opto_1 alias pina.1                                         'light barrier track 1
    opto_2 alias pina.2                                         'light barrier track 2
    
    porta.1 = 1                                                 'pullup opto_1
    porta.2 = 1                                                 'pullup opto_2
    
    ocr0a = 78
    config timer0 = timer , prescale = 1024 , CLEAR_TIMER = 1   'about 10 milliseconds compare0A interrupt
    on compare0a isr_deadtime
    enable COMPARE0A
    enable interrupts
    
    
    dim monoflop_1 as byte
    dim monoflop_2 as byte
    dim round_1 as byte                                         'round counter
    dim round_2 as byte                                         'round counter
    
    
    do
      if opto_1 = 0 and monoflop_1 = 0 then
        incr round_1
        monoflop_1 = deadtime
      endif
    
      if opto_2 = 0 and monoflop_2 = 0 then
        incr round_2
        monoflop_2 = deadtime
      endif
    loop
    
    
    isr_deadtime:
      if monoflop_1 > 0 then decr monoflop_1
      if monoflop_2 > 0 then decr monoflop_2
    return
    
    
    end                                                         'end program

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    12.02.2025
    Beiträge
    7
    Hi Searcher,

    das gefällt mir, weniger Zeilen und damit auch übersichtlicher . Es funktioniert mit einer kleinen Änderung, da ich an den Foto-LEDs mit einem Transistor die Polung invertiere bedarf es eine 1 bei "opto_1 = 0..." oder die Transistoren wieder entfernen. Die Namen der Variablen werde ich im fertigen Programm so umbennenen das ich sie in X Jahren noch wiedererkenne .

    Was ich noch nicht verstehe:
    * ocr0a = 78 --- Wer oder was ist das?
    * compare0a --- Wer oder was ist das, warum nicht timer0?

    Das kleine Testprogramm sieht dann so aus:
    Code:
    ' --- Mikrocontroler Daten... ----------------------------------------------------------------------------------
    
    $regfile   = "attiny44.dat"
    $crystal   = 8000000
    $hwstack   = 40							' $hwstack   = 34
    $swstack   = 40							' $swstack   = 20
    $framesize = 40							' $framesize = 24
    
    ' --- Deklarationen... -----------------------------------------------------------------------------------------
    
    enable interrupts
    
    ocr0a = 78
    config timer0 = timer , prescale = 1024 , CLEAR_TIMER = 1	' about 10 milliseconds compare0A interrupt
    on compare0a isr_deadtime					' 
    enable COMPARE0A
    
    config porta  = output
    config portb  = input
    
    config lcdpin = pin , Db4 = porta.2 , Db5 = porta.3 , Db6 = porta.4 , Db7 = porta.5 , E = porta.0 , Rs = porta.1
    config lcd    = 20 * 4
    cursor off    : cls
    
    opto_1 alias pinb.1										' light barrier track 1
    opto_2 alias pinb.2										' light barrier track 2
    
    ' --- Variablen... ---------------------------------------------------------------------------------------------
    
    const deadtime   = 100									' 100 * 10ms of copmare0a interrupt
    
    dim monoflop_1   as byte
    dim monoflop_2   as byte
    dim round_1      as byte									' round counter
    dim round_2      as byte									' round counter
    dim Z_formatiert as string * 2 : Z_formatiert =  ""				' Zahlen rechtsbündige formatieren
    
    ' --- Programm Anfang ------------------------------------------------------------------------------------------
    
    locate 1,1 : lcd "Formel X   20 Runden"
    locate 2,1 : lcd "--------------------"
    locate 3,1 : lcd "Spur 1 ---- Runde  0"
    locate 4,1 : lcd "Spur 2 ---- Runde  0"
    
    do
    
      if opto_1 = 1 and monoflop_1 = 0 then
        incr round_1
        Z_formatiert = str(round_1)
        locate 3,1 : lcd "Spur 1 ---- Runde" ; format(Z_formatiert , "   ")
        monoflop_1 = deadtime
      endif
    
      if opto_2 = 1 and monoflop_2 = 0 then
        incr round_2
        Z_formatiert = str(round_2)
        locate 4,1 : lcd "Spur 1 ---- Runde" ; format(Z_formatiert , "   ")
        monoflop_2 = deadtime
      endif
    
    loop
    
    ' --- Prozeduren, Funktionen... --------------------------------------------------------------------------------
    
    isr_deadtime:
      if monoflop_1 > 0 then decr monoflop_1
      if monoflop_2 > 0 then decr monoflop_2
    return
    
    ' --- Programm Ende --------------------------------------------------------------------------------------------
    
    end
    Grüßle, Hermann

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.715
    Blog-Einträge
    133
    Zitat Zitat von Naubaddi Beitrag anzeigen
    Was ich noch nicht verstehe:
    * ocr0a = 78 --- Wer oder was ist das?
    * compare0a --- Wer oder was ist das, warum nicht timer0?
    Hi,
    der Timer0 ist so konfiguriert, daß er bei einem Vergleichswert zurückgesetzt wird und nicht erst bei seinem Maximalwert von 255.
    Das ist das CLEAR_TIMER = 1 bei der Timerconfiguration. Der Vergleichswert steht in dem Register OCR0A mit dem Wert 78.
    Wenn der Timer bis 78 gezählt hat wird er zurückgesetzt und NICHT das Timer0/Overflow0 Interrupt Flag gesetzt, sondern das Compare0a Interrupt Flag.
    Der Timer hat ja nicht seinen Maximalwert erreicht.

    Der µC läuft mit 8MHz. Timer Prescale ist 1024. Der Timer läuft also mit 7812,5Hz. Pro Timerstep also 1/7812,5Hz = 0,128ms. Von 0 bis zum Wert 78 im OCR0A Register braucht er also 0,128ms * 78 = 9,984ms und noch einen Step zurück auf 0 für eine komplette Timerrunde (10,112ms). Richtiger wäre also OCR0A = 77 (komplette Timerrunde in 0,009984s) weil man dann genauer an die gewollten 10ms Abstände des Interrupts herankommt.

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  6. #6
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.715
    Blog-Einträge
    133
    Es gäbe noch weitere Verbesserungen, die man implementieren könnte.

    Wenn in der Hauptschleife die Lichtschranken abgefragt werden, könnte es passieren, daß ein Auto mal nicht erfaßt wird. Das ist abhängig von der Laufzeit der Hauptschleife. Je länger die läuft, desto wahrscheinlicher ist es, daß ein Auto durchrutscht, ohne daß die Lichtschrankenabfrage gerade dran ist.

    Könnte man zB mit Interrupts verhindern. Ich würde PCINT0 und PCINT1 dafür hernehmen. Da diese aber einmal von allen Pins des ganzen PortA und zum anderen von allen Pins des PortB ausgelöst werden können, könnte man eine Lichtschranke an den PortB umverkabeln. Das macht den Code kleiner, da man sonst extra Code zur Feststellung des auslösenden Pins eines Ports benötigt. Damit bekommt man auch wieder eine weiter ganz kleine Unsicherheit, da zwischen Interrupt und Pinbestimmung Zeit vergeht.

    Wenn also ein PCINT ausgelöst wurde setzt man in der ISR ein Flag und disabled den PCINT. Das Flag wird in der in der Haupschleife abgefragt, bei abgelaufenem Monoflop die Runde gezählt und das Flag zurücksetzt. Nach Ablauf des Monoflops muß das PCINT-Flag gelöscht werden, da durch die Mehfachauslösung der Lichtschranke noch ein Interruptflag stehen könnte, daß dann ungewollt die PCINT ISR nochmal auslöst. Und dann der PCINT wieder freigeben.

    So sollte das Risiko einer Fehlzählung ziemlichh minimiert sein.

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    12.02.2025
    Beiträge
    7
    Hi,

    die Fragen:
    * ocr0a = 78 --- Wer oder was ist das?
    * compare0a --- Wer oder was ist das, warum nicht timer0?
    sind gut beantwortet, habe die Antwort aufgeschrieben bei den vielen gesammelten Infos zu BASCOM.

    Das ein Fahrzeug nicht erkannt wird ist auszuscließen, 1 mal haben beide Spuren gewonnen als die Lichtschranken synchron unterbrochen wurden. Das Problem war die mehrfach Zählung weil die Abfrage so irre schnell ist.

    Klicke auf die Grafik für eine größere Ansicht

Name:	Lichtschranke syncron.jpg
Hits:	6
Größe:	75,0 KB
ID:	36050

    Grüßle, Hermann
    Geändert von Naubaddi (19.02.2025 um 16:43 Uhr) Grund: Schreibfehler

Ähnliche Themen

  1. 2-Timerprobleme kann ich nicht lösen(Attiny13 o.ä)
    Von oderlachs im Forum Microcontroller allgemeine Fragen/Andere Microcontroller
    Antworten: 9
    Letzter Beitrag: 17.02.2014, 15:05
  2. PCF8574 funktioniert nur nicht beim Lesen, warum?
    Von madangdive im Forum C - Programmierung (GCC u.a.)
    Antworten: 2
    Letzter Beitrag: 06.01.2010, 11:43
  3. ATtiny44 ADC will nicht
    Von Schokohoernl im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 07.07.2007, 13:51
  4. URXC1 Interrupt beim Atmega 128 funktioniert nicht
    Von tobuc0 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 0
    Letzter Beitrag: 24.06.2007, 09:23
  5. kann Uref beim Roboterboard V1.2 nicht messen
    Von Marvin im Forum Bauanleitungen, Schaltungen & Software nach RoboterNetz-Standard
    Antworten: 2
    Letzter Beitrag: 30.04.2004, 22:43

Berechtigungen

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

Solar Speicher und Akkus Tests