- LiFePO4 Speicher Test         
Ergebnis 1 bis 8 von 8

Thema: Problem: ATTiny13 mit RC-Servosignal/WS2803 LED-Treiber

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2012
    Beiträge
    5

    Problem: ATTiny13 mit RC-Servosignal/WS2803 LED-Treiber

    Anzeige

    Praxistest und DIY Projekte
    Hallo,

    nachdem ich nun selber nicht mehr weiter komme, versuche ich nun einen barmherzigen Bascom-Helfer zu finden, der mir vielleicht weiter helfen kann.

    Ich habe ein ATMega8-Programm welches mir abhängig von einem durch einen Interrupt ausgelöstes Event (Servo-Signal aus einem RC-Empfänger), Lichtspielereien an einem WS2803 LED-Treiber ermöglicht.

    Soweit funktioniert auch mit dem Mega8 alles wie ich es möchte. Allerdings wollte ich aufgrund von Platzersparnis nun einen ATTiny13 verwenden. Dieser hat allerdings nur einen 8-bit-Timer. Aber ich glaube mein portiertes Programm hat schon mit dem Interrupt Probleme. Hier der Quellcode in Bascom:

    Code:
    $regfile = "ATtiny13.dat"                                   'es handelt sich um einen ATTiny13
    $crystal = 9600000                                          'der eingebauter RC-Oszillator läuft mit 9,6 Mhz
    $hwstack = 32
    $swstack = 10
    $framesize = 10
    
    
    Config Portb = Output                                       'Alle IO-Pins als Ausgang
    Ddrb.1 = 0                                                  'B1 = Interrupt also Eingang
    
    Dim I As Byte
    Dim J As Byte
    Dim K As Byte
    
    Dim Reading As Bit
    Dim Timer_wert As Byte
    Dim Error As Bit
    
    Clk1 Alias Portb.0
    Data1 Alias Portb.2
    
    'Timer1 konfigurieren
    Config Timer0 = Timer , Prescale = 1024
    
    'Interrupt Int0 auf wechselndes Signal konfigurieren
    Config Int0 = Change
    
    
    '======================================================
    'Initialisierungen
    '======================================================
    
    'Zuweisung der Interrupt-Service-Routinen
    On Int0 On_int0
    On Timer0 On_timer0
    
    'Timer-Freigabe
    Enable Timer0
    Stop Timer0
    
    'Freigabe der Interrupt-Routinen
    Enable Int0
    Enable Interrupts
    
    '======================================================
    'Hauptprogramm - Lauflicht mit 5 LEDs an einem WS2803
    '======================================================
    
    Do
          If Timer_wert < 200 Then
    
          K = 1
          Do
    
          Gosub Reset_ws2803
    
          For J = 1 To 18
             For I = 1 To 8
                If J = K Then Data1 = 1 Else Data1 = 0
                Gosub Clk_ws2803
             Next I
          Next J
          Waitms 7
    
          K = K + 1
    
          Loop Until K > 5
    
          End If
    
    Loop
    End
    
    
    '======================================================
    'Unterprogramme
    '======================================================
    
    On_int0:                                                    'Interrupt
       'Den Timer starten mit steigender Flanke
       If Reading = 0 Then
          Start Timer0
          Reading = 1
       'Den Timer stoppen mit fallender Flanke
       Else
          Stop Timer0
          Timer_wert = Timer0
          Timer0 = 0
          Reading = 0
       End If
       'Error-Bit rücksetzen
       Error = 0
    Return
    
    
    On_timer0:                                                  'Timer
       'Error-Bit stzen
       Error = 1
       Reading = 0
       Stop Timer0
       Timer_wert = 0
    Return
    
    
    'WS2803 LED-Treiber resetten
    Reset_ws2803:
       Clk1 = 0
       Waitus 600
    Return
    
    'WS2803 alle LEDs aus
    Clear_ws2803:
       For J = 1 To 18
          For I = 1 To 8
             Data1 = 0
             Gosub Clk_ws2803
          Next I
       Next J
    Return
    
    'WS2803 Clocksignal
    Clk_ws2803:
       Clk1 = 0
       Waitus 1
       Clk1 = 1
       Waitus 1
    Return
    Sobald ich die Fernsteuerung einschalte, blinken die LEDs undefiniert. Ansonsten laufen sie anständig durch. Ich habe den Timer auch zum Test mal herausgenommen und das Timer-Unterprogramm "On_timer0" komplett geleert aber immer der gleiche Müll. Ich denke der Interrupt vermurkst mir das Timing für den WS2803 aber auf dem Mega8 lief es ja einwandfrei. Ich weiss ehrlich keinen Rat mehr. Hat von euch vielleicht jemand eine Idee?

    P.S.:
    R/C-Signal ist mit 50 Hz PWM moduliert und variiert je nach Reglerstellung zwischen 1-2 ms. Der Interrupt-Pin ist mit diesem Signal verbunden. Bei steigender Flanke wird der Timer gestartet und mit fallender Flanke wieder gestoppt.

    Der WS2803 wird seriell mit Graustufen für 18 LEDs befüllt. Ich beschränke mich auf "volle Helligkeit". D.h. ich schiebe 18 x 8bit für die Graustufen in den Chip, hier 18 x den Binärwert für 256. Die Ansteuerung funktioniert wie gesagt soweit, bis ich eben den R/C-Sender einschalte und der Interrupt-Pin dann seine Signalwechsel bekommt.

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Hallo Poettie,
    ich glaube nicht, dass du 18 mal den Wert 256 rausschickst, maximal gehen 255 in 8 Bit. Tatsächlich schickt deine Schleife aufgrund der Abfrage J=K wahrscheinlich das hier raus:
    255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    0 0 0 0 255 0 0 0 0 0 0 0 0 0 0 0 0 0

    Wieso der Int dazwischenfunken soll, sehe ich noch nicht.
    Jedenfalls würde ich die Synchronisierung uber das Bit Reading anders machen. Wenn dies einmal aus dem Tritt kommt, passt das nicht mehr. Daher würde ich dir empfehlen, den Wert des Eingangs abzufragen.
    If PinB.1 = 1 Then 'dann war es eine steigende Flanke
    Zeige doch mal dein funktionierendes Programm für den M8.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2012
    Beiträge
    5
    Hallo for_ro, danke für deine Antwort. Ja, 255 meinte ich ...

    Hier der komplette Code für den Mega8

    Code:
    
    $regfile = "M8adef.dat"                                     'es handelt sich um einen ATmega8a
    $crystal = 8000000                                          'der eingebauter RC-Oszillator läuft mit 8 Mhz
    $hwstack = 100                                              'im Speicher werden für den Hardware-Stack 100 Byte reserviert
    $swstack = 100                                              'im Speicher werden für den Software-Stack 100 Byte reserviert
    $framesize = 100                                            'im Speicher werden für den Frame 100 Byte reserviert
                                                                   'PC0 ist Clockausgang, PC1 ist Datenausgang. Rest Eingänge
    Config Portd = Input
    Config Portc = Output
    Config Portb = Output
    
    Dim I As Byte
    Dim J As Byte
    Dim K As Byte
    Dim Kk As Byte
    Dim L As Byte
    Dim Ll As Byte
    Dim Flashen As Byte
    Dim Ogrenzetimer As Integer
    
    Dim Greyscale As Byte
    
    
    Dim Reading As Bit
    Dim Timer_wert As Word
    Dim Error As Bit
    
    Clk1 Alias Portc.0
    Data1 Alias Portc.1
    
    
    'Timer1 konfigurieren
    Config Timer1 = Timer , Prescale = 1
    
    'Interrupt Int0 auf wechselndes Signal konfigurieren
    Config Int0 = Change
    
    Enable Timer1
    Stop Timer1
    
    Enable Int0
    Enable Interrupts
    
    
    
    
    
    '======================================================
    'Initialisierungen
    '======================================================
    
    'Zuweisung der Interrupt-Service-Routinen
    On Int0 On_int0
    On Timer1 On_timer1
    
    'Timer-Freigabe
    Enable Timer1
    Stop Timer1
    
    'Freigabe der Interrupt-Routinen
    Enable Int0
    Enable Interrupts
    
    Ogrenzetimer = 15350
    
    
    '======================================================
    'Hauptprogramm
    '======================================================
    
    Do
    
                'Alles ausschalten
                If Timer_wert > 1 And Timer_wert < 11749 Or Timer_wert > Ogrenzetimer Then
    
                Gosub Reset_ws2803
    
                Gosub Clear_ws2803
    
                Portb.0 = 0
                Portb.1 = 0
                Portb.2 = 0
                Portb.3 = 0
                Portb.4 = 0
                Flashen = 0
                End If
    
    
                If Timer_wert > 11750 And Timer_wert < 12151 Then
                  Gosub Reset_ws2803
                  Gosub Clear_ws2803
    
                     Portb.0 = 1
                     Portb.1 = 1
                     Portb.2 = 1
                     Portb.3 = 1
                     'Portb.4 = 1
                     Portb.4 = 0
                End If
    
    
                If Timer_wert > 12150 And Timer_wert < 12551 Then
                  Gosub Reset_ws2803
                  Gosub Clear_ws2803
                  Do
                     Portb.0 = 0
                     Portb.1 = 0
                     Portb.2 = 0
                     Portb.3 = 0
                     Portb.4 = 0
    
                     Waitms 4
    
                     Portb.0 = 1
                     Portb.1 = 1
                     Portb.2 = 1
                     Portb.3 = 1
                     'Portb.4 = 1
    
                     Waitms 1
    
                  Loop Until Timer_wert < 12551 Or Timer_wert > 12950
                End If
    
    
                If Timer_wert > 12550 And Timer_wert < 12951 Then
                  Gosub Reset_ws2803
                  Gosub Clear_ws2803
                  Do
                     Portb.0 = 0
                     Portb.1 = 0
                     Portb.2 = 0
                     Portb.3 = 0
                     Portb.4 = 0
    
                     Waitms 8
    
                     Portb.0 = 1
                     Portb.1 = 1
                     Portb.2 = 1
                     Portb.3 = 1
                     'Portb.4 = 1
    
                     Waitms 1
    
                  Loop Until Timer_wert < 12551 Or Timer_wert > 12950
                End If
    
                If Timer_wert > 12950 And Timer_wert < 13351 Then
                  Gosub Reset_ws2803
                  Gosub Clear_ws2803
                  Do
                     Portb.0 = 0
                     Portb.1 = 0
                     Portb.2 = 0
                     Portb.3 = 0
                     Portb.4 = 0
    
                     Waitms 16
    
                     Portb.0 = 1
                     Portb.1 = 1
                     Portb.2 = 1
                     Portb.3 = 1
                     'Portb.4 = 1
    
                     Waitms 1
    
                  Loop Until Timer_wert < 12951 Or Timer_wert > 13350
                End If
    
                If Timer_wert > 13350 And Timer_wert < 13751 Then
                  Gosub Reset_ws2803
                  Gosub Clear_ws2803
                  Do
                     Portb.0 = 0
                     Portb.1 = 0
                     Portb.2 = 0
                     Portb.3 = 0
                     Portb.4 = 0
    
                     Waitus 320
    
                     Portb.0 = 1
                     Portb.1 = 1
                     Portb.2 = 1
                     Portb.3 = 1
                     'Portb.4 = 1
    
                     Waitus 10
    
                  Loop Until Timer_wert < 13351 Or Timer_wert > 13750
                End If
    
    
                If Timer_wert > 13750 And Timer_wert < 14151 Then
    
                Gosub Reset_ws2803
    
                Gosub Clear_ws2803
    
                Portb.0 = 0
                Portb.1 = 0
                Portb.2 = 0
                Portb.3 = 0
                Portb.4 = 0
                Flashen = 0
    
                Waitms 50
    
                Portb.0 = 1
                Portb.1 = 1
                Portb.2 = 1
                Portb.3 = 1
                Portb.4 = 1
    
                Gosub Reset_ws2803
                For J = 1 To 36
                   For I = 1 To 8
                      Data1 = 1
                      Gosub Clk_ws2803
                   Next I
                Next J
    
                Waitms 10
    
                End If
    
    
                If Timer_wert > 14150 And Timer_wert < 14551 Then
    
                Gosub Reset_ws2803
    
                Gosub Clear_ws2803
    
                Portb.0 = 0
                Portb.1 = 0
                Portb.2 = 0
                Portb.3 = 0
                Portb.4 = 0
                Flashen = 0
    
                Waitms 500
    
                Portb.0 = 1
                Portb.1 = 1
                Portb.2 = 1
                Portb.3 = 1
                Portb.4 = 1
    
                Gosub Reset_ws2803
                For J = 1 To 36
                   For I = 1 To 8
                      Data1 = 1
                      Gosub Clk_ws2803
                   Next I
                Next J
    
                Waitms 50
    
                End If
    
    
    
                'Lauflicht entgegen gesetzt
                If Timer_wert > 14550 And Timer_wert < 14951 Then
    
                Portb.0 = 0
                Portb.1 = 0
                Portb.2 = 1
                Portb.3 = 1
    
                Do
    
                   K = 1 : L = 36
                   Do
    
                      Gosub Reset_ws2803
                      For I = 1 To 18
                         For J = 1 To 8
                            If I = K Then Data1 = 1 Else Data1 = 0
                            Gosub Clk_ws2803
                         Next J
                      Next I
                      K = K + 1
    
                      For I = 19 To 36
                         For J = 1 To 8
                            If I = L Then Data1 = 1 Else Data1 = 0
                            Gosub Clk_ws2803
                         Next J
                      Next I
                      L = L - 1
                      Waitms 15
                      Portb.4 = 0
    
                   Loop Until L < 18 Or Timer_wert < 14550 Or Timer_wert > 14951
    
                   K = 18 : L = 19
                   Do
                      Gosub Reset_ws2803
                      For I = 1 To 18
                         For J = 1 To 8
                            If I = K Then Data1 = 1 Else Data1 = 0
                            Gosub Clk_ws2803
                         Next J
                      Next I
                      K = K - 1
    
                      For I = 19 To 36
                         For J = 1 To 8
                            If I = L Then Data1 = 1 Else Data1 = 0
                            Gosub Clk_ws2803
                         Next J
                      Next I
                      L = L + 1
                      Waitms 15
                      Portb.4 = 0
    
                   Loop Until L > 36 Or Timer_wert < 14550 Or Timer_wert > 14951
    
                Loop Until Timer_wert < 14550 Or Timer_wert > 14949
    
                End If
    
    
                'Dimmen aller LEDs
                If Timer_wert > 14950 And Timer_wert < Ogrenzetimer Then
                Portb.2 = 1
                Portb.3 = 1
                      Greyscale = 250
    
                      Do
    
                      Gosub Reset_ws2803
    
                      For J = 1 To 36
                         For I = 1 To 8
                            L = 8 - I
                            If J > 0 And J < 37 Then Data1 = Greyscale.l Else Data1 = 0
                            Gosub Clk_ws2803
                         Next I
                      Next J
                      If Greyscale < 125 Then Waitms 1
                      If Greyscale < 64 Then Waitms 1
                      If Greyscale < 32 Then Waitms 1
                      If Greyscale < 16 Then Waitms 1
                      Greyscale = Greyscale - 2
                      Portb.4 = 0
                      Loop Until Greyscale < 2 Or Timer_wert < 14950 Or Timer_wert > Ogrenzetimer
    
                      Greyscale = 1
    
                      Do
    
                      Gosub Reset_ws2803
    
                      For J = 1 To 36
                         For I = 1 To 8
                            L = 8 - I
                            If J > 0 And J < 37 Then Data1 = Greyscale.l Else Data1 = 0
                            Gosub Clk_ws2803
                         Next I
                      Next J
                      If Greyscale < 125 Then Waitms 1
                      If Greyscale < 64 Then Waitms 1
                      If Greyscale < 32 Then Waitms 1
                      If Greyscale < 16 Then Waitms 1
                      Greyscale = Greyscale + 2
                      Portb.4 = 0
                      Loop Until Greyscale > 254 Or Timer_wert < 14950 Or Timer_wert > Ogrenzetimer
                End If
    
    
    Loop
    End
    
    
    '======================================================
    'Unterprogramme
    '======================================================
    
    
    
    On_int0:                                                    'Interrupt
       'Den Timer starten mit steigender Flanke
       If Reading = 0 Then
          Start Timer1
          Reading = 1
          If Flashen = 25 Then Portb.4 = 1
          If Flashen < 26 Then Flashen = Flashen + 1 Else Flashen = 0
       'Den Timer stoppen mit fallender Flanke
       Else
          Stop Timer1
          Timer_wert = Timer1
          Timer1 = 0
          Reading = 0
       End If
       'Error-Bit rücksetzen
       Error = 0
    Return
    
    On_timer1:                                                  'Timer
       'Error-Bit setzen
       Error = 1
       Reading = 0
       Stop Timer1
       Timer_wert = 0
    Return
    
    Reset_ws2803:
       Clk1 = 0
       Waitus 600
    Return
    
    Clear_ws2803:
       For J = 1 To 36
          For I = 1 To 8
             Data1 = 0
             Gosub Clk_ws2803
          Next I
       Next J
    Return
    
    
    Clk_ws2803:
       Clk1 = 0
       Waitus 1
       Clk1 = 1
       Waitus 1
    Return
    Zur Erläuterung:
    Ich habe ein Modellflugzeug mit 36 LEDs in den Tragflächen. Diese werden über zwei WS2803 LED-Treiber angesteuert. Die Treiber sind in Reihe geschaltet.
    Des Weiteren habe ich fünf 1 - 3 Watt LEDs, die ich über einen Transistor, gesteuert durch den Mega8, ansteuere.
    Über meine R/C-Anlage schicke ich über einen freien Kanal ein PWM-Signal wie oben beschrieben an den Interrupt-Pin des Mega8. Dieser Startet bei steigender Flanke des PWM Signals den 16-bit Timer und stoppt ihn bei fallender Flanke.
    Über den Timer Wert wird das "Lichtprogramm" bestimmt, welches gewählt wird. D.h. in Abhängigkeit von der Position des Stellers auf meiner R/C-Anlage variiert das PWM-Signal. Dies nutze ich für die Programmwahl.

    Portc.0 = Clock-Eingang der WS2803 (zwei in Reihe)
    Portc.1 = Dateneingang der WS2803 (zwei in Reihe)
    Portb.0-Portb.4=Ausgang für 1-3W LED-Treiber (Transistorschaltung)

    Das funktioniert auch alles Prima. Allerdings läuft das Ganze auf dem Tiny13 nicht so wie gewollt. Ich habe erstmal nur das Lauflicht mit 5 LEDs programmiert. Das hat auf dem Tiny funktioniert.

    - - - Aktualisiert - - -

    Achso, If PinB.1 = 1 abzufragen geht leider nicht. Damit würde ich meine Lichtshow unterbrechen Daher muss es schon über den Interrupt sein. Du siehst ja wie verwurschtelt das Hauptprogramm ist. Das sind einige Lichtprogramme die abhängig vom Timerwert durchlaufen werden. Wenn ich jetzt die PinB.1 = 1 IF-Abfrage da reinbauen würde, dann würde das ganze Timing nicht mehr passen. Und mit dem Interrupt beim Mega8 funktioniert es ja bestens. Ich verstehe halt nicht warum der Tiny13 da jetzt so rumzickt -.-
    Geändert von Poettie (25.11.2012 um 22:15 Uhr)

  4. #4
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Zitat Zitat von Poettie Beitrag anzeigen
    Achso, If PinB.1 = 1 abzufragen geht leider nicht. Damit würde ich meine Lichtshow unterbrechen Daher muss es schon über den Interrupt sein. Du siehst ja wie verwurschtelt das Hauptprogramm ist. Das sind einige Lichtprogramme die abhängig vom Timerwert durchlaufen werden. Wenn ich jetzt die PinB.1 = 1 IF-Abfrage da reinbauen würde, dann würde das ganze Timing nicht mehr passen. Und mit dem Interrupt beim Mega8 funktioniert es ja bestens. Ich verstehe halt nicht warum der Tiny13 da jetzt so rumzickt -.-
    Ich meinte dies hier:
    Code:
    On_int0:                                                    'Interrupt
       'Den Timer starten mit steigender Flanke
       If Reading = 0 Then
    Ich verstehe das so, dass du dir über die Variable Reading merkst, welche Flanke du gerade hast. Wenn du eine Flanke verpasst, ist die Synchronisation futsch.
    Daher würde ich dir raten, es so zu machen
    Code:
    On_int0:                                                    'Interrupt
       'Den Timer starten mit steigender Flanke
       If PinB.1 = 1 Then
    Das wird immer stimmen. Mit Timing und so hat das nichts zu tun.

    Edit: Wenn du den Timer genau so konfigurieren möchtest, wie beim M8 dann musst du den Prescale auf 256 setzen.

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2012
    Beiträge
    5
    Hallo for_ro,

    danke für deinen Tipp. Ich habe das so getestet aber sobald der Interrupt auslöst, habe ich das gleiche unkontrollierte Verhalten.

    Ich habe die Interruptroutine testweise auch mal leer gelassen also:

    Code:
    On_int0:                                                    'Interrupt
    Return
    Sobald ich am Interruptpin meinen RC-Empfänger anschließe, habe ich willkürliches blinken meiner LEDs. Sobald ich den Stöpsel ziehe, habe ich wieder mein Lauflicht ordentlich am Laufen.

    Eigentlich darf das nicht sein. Wenn ich alles richtig verstanden habe, dann sollte der Tiny doch bei steigender und fallender Flanke am PINB.1 in die Interruptroutine "On_Int0" hüpfen und dann gleich zum letzten Programmschritt zurück springen, oder?

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    36
    Beiträge
    5.070
    Ich kenne mich zwar nicht so genau mit Empfängern aus, aber könnte es sein das du noch einen Pullupwiderstand brauchst? Versuche einfach einmal einen Pullup von ca. 10k einbauen.

    MfG Hannes

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2012
    Beiträge
    5
    Leider hilft weder ein Pull-Up noch ein Pull-Down. Der Empfänger ist ein Graupner GR-12 Hott.

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    25.11.2012
    Beiträge
    5
    Ok, Fehler gefunden. Ich habe mir ein Soundkartenoszilloskop gebastelt und heraus gefunden das der Empfänger an dem Kanal kein vernünftiges Signal ausgibt -.-


    An einem anderen Kanal lief das Programm dann auch. Trotzdem danke für eure Antworten.

Ähnliche Themen

  1. [ERLEDIGT] ATtiny13: Problem mit ADC Abfrage!
    Von bnitram im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 23.05.2011, 20:23
  2. ATtiny13 Problem mit PWM
    Von stefan8010 im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 3
    Letzter Beitrag: 21.05.2011, 09:25
  3. Suche 3.3V RGB-LED-Treiber mit integriertem Step-Up
    Von Goblin im Forum Suche bestimmtes Bauteil bzw. Empfehlung
    Antworten: 4
    Letzter Beitrag: 24.04.2010, 15:26
  4. Problem ASURO-LIB I2C mit SAA1064 LED-Treiber
    Von mmittler im Forum Asuro
    Antworten: 0
    Letzter Beitrag: 01.10.2008, 05:26
  5. [gelöst]Problem mit Interrupt Attiny13
    Von OEP im Forum Assembler-Programmierung
    Antworten: 2
    Letzter Beitrag: 19.04.2007, 09:47

Berechtigungen

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

Solar Speicher und Akkus Tests