- Akku Tests und Balkonkraftwerk Speicher         
Ergebnis 1 bis 5 von 5

Thema: Bahnsteuerung für Schrittmotor auf Mega128 macht Probleme

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    06.04.2008
    Beiträge
    18

    Bahnsteuerung für Schrittmotor auf Mega128 macht Probleme

    Anzeige

    Powerstation Test
    Brauche Hilfe !
    Mein Code macht undefinierbare Probleme - er läuft zwar stabil, doch die Bahn/Rampe wird nicht ordnungsgemäß mit Geschwindigkeit 0 beendet.

    Eigentlich soll per CTC-Mode eine Frequenz für eine Schrittmotorendstufe erzeugt werden um bei gegebener Strecke auf ein Speedlimit zu beschneunigen und rechtzeitig vor ende der Strecke auf "Null" abgebremst zu haben.
    Ich habe einer Timer auf 200Hz eingestellt um eine Interruptroutine in gleichbleibenden Zeitabständen die Berechnungen durchführen zu lassen.
    Im Hauptprogramm wird eigentlich nur ein neuer Durchlauf gestartet und die Ausgabe auf dem Display gemacht.

    Problem 1:
    ich lasse mir bei jedem Timerereigniss einen Interrupt auslösen, damit ich
    die ausgegebenen Pulse genau zählen kann.
    Ich lasse eine Variable bei 0 beginnen und hochzählen und am Display anzeigen, die andere Variable zählt von vorgegebener Strecke ( 8000 ) herunter.
    In einer If Abfrage wird der Timer gestoppt, wenn auf Null heruntergezählt wurde -> so wünsche ich es mir - aber er macht es nicht !

    Es kommt manchmal vor, dass die Routine auf unergründliche Weise viel
    früher zum ende kommt, die eine Variable ist nicht bis auf Null runter gekommen , und die andere nicht bei 8000 angekommen - Noch viel dubioser : nicht einmal mit einer rechnerisch erklärbaren Differenz!
    Obwohl die beiden Variablen genau untereinander runter/hochgezählt werden , scheint eine von beiden Zeilen manchmal nicht bearbeitet zu werden, da z.B. die eine Variable bei 8000 angekommen ist, die andere aber noch bei weitem nicht bei Null angekommen ist , sie steht z.b. bei 50

    Gibt es Jemanden in dieser Gemeinde, der mir das erklären kann ??


    Problem 2:
    Ich beobachte aber in aller Regel eine große Geschwindigkeit beim ende der Strecke - manchmal bremst er auch zu früh und läuft mit einer minimalen Geschwindigkeit( meine Vorgabe ) zum ende der Strecke.


    Code:
    $hwstack = 192
    $swstack = 192
    $framesize = 128
    'you might need to raise these numbers if your code grows !!!!!!! (unexpected behaviour of the program often results of too small stacks)
    
    '----------------------------------------------------------------------------------------------------------------------------------
    
    $regfile = "m128def.dat"
    $crystal = 16000000                                         'enter the used clock of your actual microcontroller
    
    Declare Sub Geschwindigkeit
    Declare Sub Rampe
    Declare Sub Timerladen
    
    Const Frq = 16000000                                        '# hier muss die Prozessorfrequenz nochmal rein !!!!
    Const T3prescale = 64                                       '# Timer3 Vorteiler
    Const T0prescale = 1024                                     '# Timer3 Vorteiler
    Const True = 1
    Const False = 0
    Const Time0 = 78                                            ' für 200Hz Wiederholrate
    '##############
    '#  A/D Port  #
    '##############
    Config Adc = Single , Prescaler = Auto , Reference = Internal
    '########### FrequenzGenerator mittels Timer0    ###############
    Config Timer0 = Timer , Prescale = T0prescale               '###### Interrupr für die Wiederholrate / sekunde
    Load Timer0 , Time0
    On Ovf0 Timer0_ovf
    Enable Timer0
    Start Timer0
    '########### PWM Generator mittels Timer3, Porta ###############
    Stop Timer3
    Config Timer3 = Timer , Prescale = T3prescale , Clear Timer = 1 , Compare A = Toggle       ' 1. Achse
    On Compare3a Compare_3a_int                                 ' When Timer3 = Compare3A register
    Compare3a = 55000                                           ' Load the TimerLimit value into the Compare1A (OCR1A) register
    
    Disable Compare3a
    
    
    Config Porte.3 = Output
    '###############################################################
                                                                'Now we need to select Port B as to an output port (data output to the display)
    Ddrb = &B11111111                                           'DDR = Data direction register; All 8 ports switched to output (1)
    
    Ddra = &B00000000                                           'switch all 8 Ports of Port A to input (0), Pin (PA.0 - PA.7)
    Porta = &B11111111                                          'All port pins have individually selectable pull-up resistors. Here we enable these pull-up-resisitors, so these Pins are always at logical 1
                                                                'You need to pull these Pins against ground (GND)
    Ddrc = &B00000000                                           'switch all Ports of Port C to input
    Portc = &B11111111
    
    Ddrd = &B00000000                                           'switch all Ports of Port D to input
    Portd = &B11111111                                          'all pull-up-Resistors turned on
    
    'Ddre = &B00000000                                           'switch all Ports of Port E to input
    'Porte = &B11111111                                          'all pull-up-Resistors turned on
    
    Ddrf = &B00000000                                           'switch all Ports of Port F to input
    Portf = &B11111111                                          'all pull-up-Resistors turned on
    
    Ddrg = &B00000000                                           'switch all Ports of Port G to input
    Portg = &B11111111                                          'all pull-up-Resistors turned on
                                             'all pull-up-Resistors turned on
    
    Debug0 Alias Porta.0
    Debug1 Alias Porta.1
    Debug2 Alias Porta.2
    Debug3 Alias Porta.3
    Debug4 Alias Porta.4
    Debug5 Alias Porta.5
    Debug6 Alias Porta.6
    Debug7 Alias Porta.7
    
    
    '##### Variablen #############################################
    Dim Problem As Bit
    Dim Menudraw As Bit
    Dim Init As Bit
    Dim Modus As Bit
    Dim Continus As Bit
    Dim Port As String * 14
    Dim Timer3reload As Word
    Dim Schrittzaehler As Long
    Dim T3basis As Long
    Dim T0basis As Long
    Dim Wunschspeedlong As Long
    Dim Speedakt As Single
    Dim Speedquadrat As Single                                  ' Speedakt zum Quadrat
    Dim Wiederholrate As Single
    Dim Gesamtschritte As Long
    Dim Halbschritte As Long
    Dim Beschleunischritte As Long
    Dim Schritte As Long
    Dim Umin As Long                                            ' so viele Schritte sing vom Weg noch übrig
    Dim Uminmax As Long
    Dim Beschleunigung As Single
    Dim Speedlimit As Single
    Dim Zeitincrement As Single
    Dim Wunschspeed As Single
    Dim Minspeed As Single
    Dim Tick As Single
    Const Fertig = 1
    Const Nichtfertig = 0
    Dim Schleife As Byte
    Dim Untersetzung As Integer
    Dim Schritteproumdrehung As Integer
    Dim Acc As Single
    Dim Speed As Single
    Dim Timecount As Long
    Dim Count As Long
    Dim Sek As Single
    
    
     Enable Interrupts
    Menudraw = 1
    Wunschspeed = 1
    Schrittzaehler = 0
    Beschleunigung = 30
    Speedlimit = 30
    Minspeed = 10
    Modus = 1
    Init = 0
    Gesamtschritte = 4000
    '############################################################################################
    '4 - Definition of used ports and pull up resistors
    $include Init21_display3000.bas                             'At our boards we are using Port B for the SPI-communication to the LCD.
    
       Orientation = Portrait                                   ' fürs Display
       Graphics_mode = 65k_uncompressed                         'select the needed color mode, here 65.536 colors
       Call Lcd_cls
    
    '##################################################################
    Start Adc
    
    
    '##################################################################
    
    
    T3basis = Frq / T3prescale                                  ' berechnung der Grundgeschwindigkeit aus Frq und Teiler
    T0basis = Frq / T0prescale
    Wiederholrate = T0basis / Time0
    Tick = 1 / Wiederholrate
    
    Do                                                          ' Schleife Hauptprogramm  - eigentlich nur zum anzeigen der Variablen aus dem Display
      Toggle Debug1
    
      If Schleife = Fertig Then                                 ' Wenn eine Rampe komplett ist
         Waitms 700                                             ' Variablen neu bestücken
         Schleife = Nichtfertig                                 ' um neuen Durchlauf nach Wartezeit starten
         Schrittzaehler = 0
         Gesamtschritte = 8000
         Beschleunigung = Beschleunigung + 100
         Speedlimit = Speedlimit + 200
         Init = 0
         Modus = 1
         Halbschritte = Gesamtschritte / 2
         Uminmax = 0
       End If
    
    
    '#### Anzeige auf dem LCD zur Kontrolle #########################
    
       If Menudraw = 1 Then
    
           Port = "Gesamtschritte"
           Call Lcd_print(port , 8 , 32 , 1 , 1 , 1 , White , Black)
    
           Port = "Speedakt "
           Call Lcd_print(port , 8 , 45 , 1 , 1 , 1 , White , Black)
    
           Port = "Schrittzaehl"
           Call Lcd_print(port , 8 , 100 , 1 , 1 , 1 , White , Black)
    
           Port = "Umin"
           Call Lcd_print(port , 8 , 120 , 1 , 1 , 1 , Green , Black)
    
           Port = "Modus"
           Call Lcd_print(port , 8 , 130 , 1 , 1 , 1 , Green , Black)
    
           Port = "sek"
           Call Lcd_print(port , 8 , 150 , 1 , 1 , 1 , Green , Black)
    
    
       Menudraw = 0
      End If
    
    
       Port = Str(gesamtschritte)
       Port = Format(port , "0000000")
       If Len(port) < 8 Then
        Call Lcd_print(port , 85 , 32 , 1 , 1 , 1 , Green , Black)
       End If
    
       Port = Fusing(speed , "####.#")
       Port = Format(port , "0000000")
       If Len(port) < 8 Then
        Call Lcd_print(port , 85 , 45 , 1 , 1 , 1 , Blue , Black)
       End If
    
      Port = Str(schrittzaehler)
       Port = Format(port , "0000000")
       If Len(port) < 8 Then
        Call Lcd_print(port , 85 , 100 , 1 , 1 , 1 , White , Black)
       End If
    
      Port = Str(uminmax)
       Port = Format(port , "00000.0")
       If Len(port) < 8 Then
        Call Lcd_print(port , 85 , 120 , 1 , 1 , 1 , White , Black)
       End If
    
      Port = Str(modus)
        Call Lcd_print(port , 85 , 130 , 1 , 1 , 1 , White , Black)
    
       Port = Fusing(sek , "####.##")
       Port = Format(port , "000000")
       If Len(port) < 8 Then
        Call Lcd_print(port , 85 , 150 , 1 , 1 , 1 , White , Black)
       End If
    
      Acc = Beschleunigung * Tick                               ' Berechnung der Beschleunigungsrate
    Loop
    
    End
    
    
    
    '#########################################
    '# Timerinterruptrutine       alle 5ms   #
    '#########################################
    Timer0_ovf:
      Load Timer0 , Time0
       Debug0 = 1
          Incr Count
          Enable Interrupts
    
      Call Geschwindigkeit                                      ' Gteschwindigkeitsberechnung
          If Init = 0 Then
             Start Timer3
             Enable Compare3a
             Init = 1
          End If
    
      Call Rampe                                                ' berechnung der Wunschgeschwindigkeit für die Rampe
    
      Call Timerladen
      Debug0 = 0                                                ' Timer mit Sollwert bestücken
      Return
    
    
    
    '################################
    '# Compare Interrupt Timer3a    #
    '################################
    Compare_3a_int:
      If Timer3 < Timer3reload And Problem = True Then Compare3a = Timer3reload       'bei Problemen Timer hier neu laden
      Toggle Porta.6
       Incr Schrittzaehler                                      ' Schrittzaehler hochzählen
       Decr Gesamtschritte                                      ' Gesamtschritte runterzählen
    
       If Gesamtschritte <= 0 Then                              ' wenn Gesamtschritte auf Null > keine Pulse mehr
             Stop Timer3
             Disable Compare3a
          Schleife = Fertig
          Timecount = Count                                     ' Zeit eines Ablaufes speichern
          Count = 0
        End If
    
    Return
    
    
    '###################################
    '# Sub Geschwindigkeitsberechnung  #
    '###################################
    Sub Geschwindigkeit
          Speedakt = T3basis / Compare3a                        '#  Frequenzbasis / PWM WERT
          Speed = Speedakt / 2                                  '   / 2   da 2 Interrupte für eine Periode benötigt werden
    End Sub
    
    '###################################
    '# Sub Beschleunigungsrampe  #
    '###################################
    Sub Rampe
          Umin = Speedakt * 6                                   '  60 für 1 Min
          Umin = Umin / 8                                       '800  Schritte pro umin &
                                                                ' > zum Anzeigen mit 2 Kommastellen nur durch 8
          If Umin > Uminmax Then                                ' zum Speichern der max. U/min
            Uminmax = Umin
          End If
    
        If Modus = 1 Then                                       ' wenn beschleunigt wird :
             If Wunschspeed > 0 Then                            ' wenn gefahren werden soll
                 If Wunschspeed < Speedlimit Then               ' wenn Speedlimit noch nicht erreicht
                    Wunschspeed = Wunschspeed + Acc             ' Berechnung der beschleunigung
                    If Schrittzaehler > Halbschritte Then       ' noch in der beschleunigungsphase darf nur die hälfte der Strecke beschleunigt werden
                       Modus = 0
                       Continus = 0
                    End If
                 Else
                    If Continus = 0 Then
                       Beschleunischritte = Schrittzaehler
                       Continus = 1
                    End If
                    If Beschleunischritte > Gesamtschritte Then
                       Modus = 0
                    End If
                 End If
             Else
               Wunschspeed = 1
             End If
        Else                                                    ' Bremsung einleiten !!
            If Wunschspeed > 0 Then
              Wunschspeed = Wunschspeed - Acc                   ' Beschleunigungsfaktor abziehen
            Else
              Wunschspeed = 0
            End If
        End If
         Sek = Timecount / Wiederholrate                        ' wie lange hat eine Rampe gesauert
    End Sub
    
    
    
    Sub Timerladen:                                             ' Timerwert aus "Wunschspeed" errechnen
       If Wunschspeed > 0 Then
            Wunschspeedlong = Wunschspeed
         Timer3reload = T3basis / Wunschspeedlong
       Else
         Timer3reload = 30000
       End If
         If Timer3reload > 30000 Then Timer3reload = 30000      ' Grenzen für den erlaubte werde für die Geschwindigkeit
         If Timer3reload < 10 Then Timer3reload = 10
         If Timer3 < Timer3reload Then
            Compare3a = Timer3reload
            Problem = False
         Else
            Problem = True
         End If
    End Sub
    
    $include Glcd21_display3000.bas
    
    $include Glcd21_fonts.bas
    'Dummy Data um Fehlermeldungen bei der Kompilierung der Standardroutinen zu vermeiden
    'Die Tabelle wird dann bei Nutzung eines indizierten Grafikdatei mit "echten" Daten ausgetauscht
       Colortable:
       Data 0
    kann mal bitte jemand sie meinen Code anschauen und konstruktive Kritik
    üben - ich bitte darum - ich komme hier nicht weiter - habe schon die berechnung der Bahnsteuerung mit Gleichnungen aus dem Physik-Buch gemacht und da hab ich auch die selben Ergebnisse bekommen.

    Ich Programmiere mit der neusten Bascom Version und setzte
    einen AT Mega 128 auf einer Platine von Display3000 (D071)ein.


    vielen Dank.

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von Vitis
    Registriert seit
    06.01.2005
    Ort
    Südpfalz
    Alter
    50
    Beiträge
    2.253
    hmmm ... verzwickt,
    denkbare Szenarios gibts viele ...
    zum Einen verwendeste Variablennamen, die eventuell
    in Deinen includeten Programmteilen verwendet werden
    könnten ... z.B. "speed"
    dann haste in Deiner Interruptroutine nen
    "enable interrupts" ... int in int, das kann Verwirrung stiften
    wozu brauchste das?
    Vor den Erfolg haben die Götter den Schweiß gesetzt

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    06.04.2008
    Beiträge
    18

    Re: hmmm ... verzwickt,

    Hallo Vitis, das mit den Variablen werd ich mir anschauen.

    Zitat Zitat von Vitis
    hmmm ... verzwickt,
    dann haste in Deiner Interruptroutine nen
    "enable interrupts" ... int in int, das kann Verwirrung stiften
    wozu brauchste das?
    Da ich jeden Timerinterrupt zählen möchte, muss ich auch in meinem Timerinterrupt ( 200 Hz ) wieder weitere interrupte freigeben.
    Mir haben zwar viele Leute gesagt, dass kann zu Problemen führen, doch 1. hab ich noch keine andere Lösung gefunden.
    2. 200 Hz ..... da bin ich alle mal mit der Routine durch,sodass allein durch die Codelänge verhindert wird, dass die gleiche Routine ineinander mehrfach aufgerufen wird. Das funktioniert eigentlich gut , hab mir es mit dem Oszi angeschaut.

    gruß olby2

  4. #4
    Erfahrener Benutzer Robotik Einstein Avatar von Vitis
    Registriert seit
    06.01.2005
    Ort
    Südpfalz
    Alter
    50
    Beiträge
    2.253
    eben drum, Deine Interruptroutine ist "schnell" sollte auch ohne den
    SEI ohne Probleme gehen
    Vor den Erfolg haben die Götter den Schweiß gesetzt

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    06.04.2008
    Beiträge
    18
    Leider nicht ,
    das habe ich mir mit dem Oszi schon angeschaut, wenn ich in meiner Timerroutine nicht weitere Interrupte erlaube, werden Timerereignisse in dieser Zeit nicht gezählt.

    Ich muss das aus jetziger sicht also machen - ich glaube aber nicht das in den geschachtelten IRQ´s das Problem zu finden ist , doch ich habe mir auch schon überlegt mit einem weiteren Timer einfach zu zählen was im CTC Mode bei Ocr3a alles so raus kommt


    gruß olby2

Berechtigungen

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

12V Akku bauen