-         
Seite 2 von 8 ErsteErste 1234 ... LetzteLetzte
Ergebnis 11 bis 20 von 73

Thema: Mehrere RC Signale einlesen und mehrere Servos ausgeben

  1. #11
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.649
    Blog-Einträge
    133
    Anzeige

    LiFePo4 Akku selber bauen
    Hallo Robert,
    wenn es in Bascom zeitkritisch wird, kann man es mit Inlineassembler versuchen.

    Ich habe nix weiter gemacht als in Deinem letzten geposteten Programm versucht, die Impulsmeß-ISRs mit ASM zu ersetzten mit manuellem Registersichern (On interrupt label Nosave) und hoffe keinen Bug eingebaut zu haben.
    Die max. Ausführungszeit einer ISR sollte von ca. 17µs auf ca. knapp 5µs gesunken sein. Vielleicht bessert es das Verhalten.

    Ungetestet und ohne Gewähr

    Gruß
    Searcher

    Code:
    '===============================================================================
    'RC Eingang 1 an Pin 3 (PB1, PCINT9)
    'RC Eingang 2 an Pin 7 (PA7, PCINT7)
    'RC Eingang 3 an Pin 5 (PB2, INT0)
    'Servo 1 an Pin 13 (PA0)
    'Servo 2 an Pin 12 (PA1)
    'Servo 3 an Pin 11 (PA2)
    'Servo 4 an Pin 10 (PA3)
    '===============================================================================
    
    $regfile = "attiny24.dat"
    $crystal = 8000000                                          'FuseBit CKDIV8 deaktivieren
    
    $hwstack = 32
    $swstack = 20
    $framesize = 40
    
    
    '-------------------------------------------------------------------------------------------------
    'Timer und konfigurieren
    '-------------------------------------------------------------------------------------------------
    
    Config Timer1 = Timer , Prescale = 8                        'Timer für Einlesen RC Signale
    Start Timer1
    
    Config Timer0 = Timer , Prescale = 64                       'Timer für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms
    Enable Timer0
    On Timer0 Servoausgabe
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Variablen definieren
    '-------------------------------------------------------------------------------------------------------------
    
    'Variablen fürs RC Einlesen
    Dim Rc_signal_1_start As Word
    Dim Rc_signal_2_start As Word
    Dim Rc_signal_3_start As Word
    
    Dim Impulslaenge_1 As Word
    Dim Impulslaenge_2 As Word
    Dim Impulslaenge_3 As Word
    
    
    
    'Variablen für Berechnungen
    Dim Berechnung_1 As Word
    Dim Berechnung_2 As Word
    
    
    
    'Variablen für Servoausgabe
    Dim Kanal As Byte
    Dim Servoausgabe_1 As Byte
    Dim Servoausgabe_2 As Byte
    Dim Servoausgabe_3 As Byte
    Dim Servoausgabe_4 As Byte
    Dim Pausen_variable As Byte
    
    
    '-------------------------------------------------------------------------------------------------
    'Einigen Variablen Werte zuweisen
    '-------------------------------------------------------------------------------------------------
    
    Kanal = 1
    Pausen_variable = 0
    
    '-------------------------------------------------------------------------------------------------------------
    'Ein- und Ausgang festlegen
    '-------------------------------------------------------------------------------------------------------------
    
    Ddra = &B00001111                                           'PA0 - PA3 werden Ausgänge
    Ddrb = &B00000000                                           'PortB bleibt Eingang
    
    
    '-------------------------------------------------------------------------------------------------
    'Interrupt-Service-Routinen konfigurieren und freigeben
    '-------------------------------------------------------------------------------------------------
    
    'Info:
    'Alle Porta Pinchangeinterrupts sind in Bascom "PCINT0" zugeordnet.
    'Alle Portb Pinchangeinterrupts sind in Bascom "PCINT1" zugeordnet.
    
    
    Pcmsk1.pcint9 = 1                                           'beim Flankenwechsel an PB1/PCINT9 (RC Eingang 1) Pinchangeinterrupt1 auslösen und in die Subroutine springen
    Enable Pcint1                                               'Pinchangeinterrupt1 (1 weil auf PortB) zulassen
    On Pcint1 Rc_eingang_1 Nosave           'Register werden manuel in der ISR gesichert
    
    
    Pcmsk0.pcint7 = 1                                           'beim Flankenwechsel an PA7/PCINT6 (RC Eingang 2) Pinchangeinterrupt0 auslösen und in die Subroutine springen
    Enable Pcint0                                               'Pinchangeinterrupt0 (0 weil auf PortA) zulassen
    On Pcint0 Rc_eingang_2 Nosave           'Register werden manuel in der ISR gesichert
    
    
    Config Int0 = Change                                        'beim Flankenwechsel an PB2/INT0 (RC Eingang 3) Int0 auslösen und in die Subroutine springen
    Enable Int0
    On Int0 Rc_eingang_3 Nosave             'Register werden manuel in der ISR gesichert
    
    Enable Interrupts
    
    
    
    '======================================================
    'Hauptprogramm
    '======================================================
    
    Do
    
    
    'Umrechnung erstes RC Signal auf 8-Bit
    Berechnung_1 = Impulslaenge_1 / 8                           'ergibt Werte zwischen 125 und 250
    
    If Berechnung_1 > 255 Then                                  'zu hohe Werte abfangen
       Berechnung_1 = 255
    End If
    
    If Berechnung_1 < 120 Then                                  'zu kleine Werte abfangen
       Berechnung_1 = 120
    End If
    
    
    'Umrechnung zweites RC Signal auf 8-Bit
    Berechnung_2 = Impulslaenge_2 / 8                           'ergibt Werte zwischen 125 und 250
    
    If Berechnung_2 > 255 Then                                  'zu hohe Werte abfangen
       Berechnung_2 = 255
    End If
    
    If Berechnung_2 < 120 Then                                  'zu kleine Werte abfangen
       Berechnung_2 = 120
    End If
    
    
    
    Servoausgabe_1 = Berechnung_1
    Servoausgabe_2 = Berechnung_2
    Servoausgabe_3 = 190
    Servoausgabe_4 = 190
    
    
    Loop
    
    
    
    '======================================================
    'ISR
    '======================================================
    
    
    'Rc_eingang_1:
    '   If Pinb.1 = 1 Then
    '   Rc_signal_1_start = Timer1
    '   Else
    '   Impulslaenge_1 = Timer1 - Rc_signal_1_start
    '   End If
    'Return
    
    Rc_eingang_1:
     $asm
       push r16                             'Register auf Stack sichern
       in r16,sreg                          'Statusregister holen und halten
       push r17                             'Register auf Stack sichern
       push r18                             'Register auf Stack sichern
       sbis pinb , 1                        'Skip next Instr if PINBx = 1
       rjmp pulslaenge1                     'Spring zur Berechnung von Impulslaenge
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_1_start} , r17        'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_1_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal high Byte
       rjmp ende1                           'Springe zum Ende
      Pulslaenge1:
       in r17 , tcnt1l                      'Timer1 low Byte holen
       lds r18 , {Rc_signal_1_start}        'Hole Rc_signal low Byte
       Sub R17 , R18                        'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_1} , r17           'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       lds r18 , {Rc_signal_1_start} + 1    'Hole Rc_signal high Byte
       sbc r17 , r18                        'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_1} + 1 , r17       'Speichere Resultat high Byte nach Impulslaenge high Byte
      Ende1:
       pop r18                              'Register vom Stack zurückholen
       pop r17                              'Register vom Stack zurückholen
       Out Sreg , R16                       'Statusregister zurückspeichern
       pop r16                              'Register vom Stack zurückholen
     $end Asm
    Return
    
    'Rc_eingang_2:
    '   If Pina.7 = 1 Then
    '   Rc_signal_2_start = Timer1
    '   Else
    '   Impulslaenge_2 = Timer1 - Rc_signal_2_start
    '   End If
    'Return
    
    Rc_eingang_2:
     $asm
       push r16                             'Register auf Stack sichern
       in r16,sreg                          'Statusregister holen und halten
       push r17                             'Register auf Stack sichern
       push r18                             'Register auf Stack sichern
       sbis pina , 7                        'Skip next Instr if PINBx = 1
       rjmp pulslaenge2                     'Spring zur Berechnung von Impulslaenge
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_2_start} , r17        'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_2_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal high Byte
       rjmp ende2                           'Springe zum Ende
      Pulslaenge2:
       in r17 , tcnt1l                      'Timer1 low Byte holen
       lds r18 , {Rc_signal_2_start}        'Hole Rc_signal low Byte
       Sub R17 , R18                        'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_2} , r17           'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       lds r18 , {Rc_signal_2_start} + 1    'Hole Rc_signal high Byte
       sbc r17 , r18                        'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_2} + 1 , r17       'Speichere Resultat high Byte nach Impulslaenge high Byte
      Ende2:
       pop r18                              'Register vom Stack zurückholen
       pop r17                              'Register vom Stack zurückholen
       Out Sreg , R16                       'Statusregister zurückspeichern
       pop r16                              'Register vom Stack zurückholen
     $end Asm
    Return
    
    'Rc_eingang_3:
    '   If Pinb.2 = 1 Then
    '   Rc_signal_3_start = Timer1
    '   Else
    '   Impulslaenge_3 = Timer1 - Rc_signal_3_start
    '   End If
    'Return
    
    Rc_eingang_3:
     $asm
       push r16                             'Register auf Stack sichern
       in r16,sreg                          'Statusregister holen und halten
       push r17                             'Register auf Stack sichern
       push r18                             'Register auf Stack sichern
       sbis pinb , 2                        'Skip next Instr if PINBx = 1
       rjmp pulslaenge3                     'Spring zur Berechnung von Impulslaenge
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_3_start} , r17        'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_3_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal high Byte
       rjmp ende3                           'Springe zum Ende
      Pulslaenge3:
       in r17 , tcnt1l                      'Timer1 low Byte holen
       lds r18 , {Rc_signal_3_start}        'Hole Rc_signal low Byte
       Sub R17 , R18                        'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_3} , r17           'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       lds r18 , {Rc_signal_3_start} + 1    'Hole Rc_signal high Byte
       sbc r17 , r18                        'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_3} + 1 , r17       'Speichere Resultat high Byte nach Impulslaenge high Byte
      Ende3:
       pop r18                              'Register vom Stack zurückholen
       pop r17                              'Register vom Stack zurückholen
       Out Sreg , R16                       'Statusregister zurückspeichern
       pop r16                              'Register vom Stack zurückholen
     $end Asm
    Return
    
    
    
    Servoausgabe:
    
    If Kanal = 1 Then
       If Porta.0 = 0 Then                                      'wenn der Ausgangspin aus ist
          Load Timer0 , Servoausgabe_1                          'wird der Timer0 mit dem Wert der Variable "Servoausgabe_1" vorgeladen
          Porta.0 = 1                                           'und der Ausgangspin eingeschaltet
       Else                                                     'erst beim nächsten Timer0 Überlauf landen wir hier
          Porta.0 = 0                                           'Ausgangspin wird wieder ausgeschaltet
          Incr Kanal                                            'und der nächsten Kanal bearbeitet
       End If
    End If
    
    
    If Kanal = 2 Then
       If Porta.1 = 0 Then
          Load Timer0 , Servoausgabe_2
          Porta.1 = 1
       Else
          Porta.1 = 0
          Incr Kanal
       End If
    End If
    
    
    If Kanal = 3 Then
       If Porta.2 = 0 Then
          Load Timer0 , Servoausgabe_3
          Porta.2 = 1
       Else
          Porta.2 = 0
          Incr Kanal
       End If
    End If
    
    
    If Kanal = 4 Then
       If Porta.3 = 0 Then
          Load Timer0 , Servoausgabe_4
          Porta.3 = 1
       Else
          Porta.3 = 0
          Incr Kanal
       End If
    End If
    
    
    
    'Pausenauffüllung
    
    
    If Kanal = 5 Then
      Timer0 = 0                                                '8-Bit Timer auf 0, Überlauf alle 2,048ms
      If Pausen_variable < 7 Then                               '2,048ms * 6 = 12,288ms Pausenfüllzeit
      Incr Pausen_variable
      Else
      Pausen_variable = 0
      Kanal = 1
      End If
    End If
    
    
    Return
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  2. #12
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    58
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Mit "ähnlich gut" meine ich, dass ein geringes, aber deutlich sichtbares Servozucken an den Servos vorhanden ist, welche mit den eingelesenen RC-Signalen versorgt werden. Servos, denen ich im Programm einen Festwert zuweise, zucken nicht.
    Die Verwendung des (NoSave-) Pinchange-Interrupts zum Einlesen halte ich auch für richtig, ich war nur zu faul es umzusetzen.

    Was ihr weder in der Bascom- noch in der ASM-Version beachtet ist der Überlauf des Timers während der Impulsmessung. Hier schlummert möglicherweise auch mein Denkfehler:

    Code:
    '-------------------------------------------------------------------------------------------------------------
    'Hauptprogramm starten
    '-------------------------------------------------------------------------------------------------------------
    
    Do
    
    If Pina.7 = 1 And Empfangskanal_temp_ein(1) = 0 Then
       Empfangskanal_temp_ein(1) = Timer1
    End If
    
    If Pina.7 = 0 And Empfangskanal_temp_ein(1) <> 0 Then
          Empfangskanal_temp_aus(1) = Timer1
          If Empfangskanal_temp_aus(1) > Empfangskanal_temp_ein(1) Then       ' Wert nur gültig wenn kein Timerüberlauf
             Empfangskanal(1) = Empfangskanal_temp_aus(1) - Empfangskanal_temp_ein(1)
          End If
          Empfangskanal_temp_ein(1) = 0
    End If
    
    If Empfangskanal(1) <> 0 Then Servo(1) = Empfangskanal(1) End If
    
    Loop
    
    End
    Gruß

    mic

    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  3. #13
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Zitat Zitat von radbruch Beitrag anzeigen
    Was ihr weder in der Bascom- noch in der ASM-Version beachtet ist der Überlauf des Timers während der Impulsmessung.
    Inder Bascom Version funktioniert dies auch bei Timer Überlauf, solange Impulslaenge_1 nicht überläuft. Da hier nur Werte bis max 2000 kommen dürften, geht das auch so:

    Rc_eingang_1:
    If Pinb.1 = 1 Then
    Rc_signal_1_start = Timer1
    Else
    Impulslaenge_1 = Timer1 - Rc_signal_1_start
    End If
    Return

    Du brauchst also keine Vorkehrungen zu treffen, ob der aktuelle Wert größer als der vorherige ist
    If Empfangskanal_temp_aus(1) > Empfangskanal_temp_ein(1) Then ' Wert nur gültig wenn kein Timerüberlauf
    Ob searcher das in ASM auch so umgesetzt hat, kann ich leider nicht beurteilen.

  4. #14
    Neuer Benutzer Öfters hier
    Registriert seit
    12.12.2013
    Alter
    47
    Beiträge
    22
    Hallo zusammen,

    ich habe mir gerade die Zeiten angesehen, die Ihr für die Ausführung der ISR vermutet. Als Anfänger und Laie weiß ich natürlich nicht, wie lange so ein Sprung in die ISR und wieder zurück dauert. Aber selbst wenn ich von rund 20 µs ausgehen, sind das "nur" 2% der Gesamtmessdauer bei einem 1ms Signal (bei 2ms wäre es nur noch 1 % Abweichung). Da die Ausgabewerte durch die Verwendung des 8-Bit-Timers dann auch noch durch 8 geteilt werden, "scheinen" mir die Sprungzeiten kaum noch relevant, oder rechne ich da falsch . Ist wie gesagt nur eine Vermutung.

    mfg
    Robert

  5. #15
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Hallo Robert,
    rechne mal so:
    Du hast auf der Ausgabeseite eine Auflösung von 125 Schritten für die Spanne zwischen 1ms und 2ms, also für 1ms. D.h. ein Schritt hat die Dauer von 8µs. Da machen 20µs natürlich schon einen Unterschied.

  6. #16
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.649
    Blog-Einträge
    133
    Zitat Zitat von for_ro Beitrag anzeigen
    Du brauchst also keine Vorkehrungen zu treffen, ob der aktuelle Wert größer als der vorherige ist
    If Empfangskanal_temp_aus(1) > Empfangskanal_temp_ein(1) Then ' Wert nur gültig wenn kein Timerüberlauf
    Ob searcher das in ASM auch so umgesetzt hat, kann ich leider nicht beurteilen.
    Hallo, die ASM Teile sollen eine 1:1 Umsetzung der entsprechenden Bascom ISRs sein; also keine Gültigkeitsüberprüfung. Falls der Timer überläuft würde das Ergebnis der Subtraktion negativ sein. Die Impulslaenge Variable ist vom Typ Word mit 16Bit wie auch TCNT1 16Bit, kann keine negativen Zahlen enthalten, "läuft mit über" und enthält dann den gewollten Abstand von Rc_signal_start und aktuellem Timerstand. Soll auch so in der ASM funktionieren.

    @radbruch: Hab noch keine Zeit gefunden, mich in Deine Version reinzudenken.

    Die ASM Teile könnten noch etwas optimiert werden, wenn die Push und Pop nur da stehen, wo sie wirklich gebraucht werden. Falls PIN high ist, spart man an der Stelle fast nochmal ca 1µs.

    Mit der "Servoausgabe ISR" hab ich mich auch noch nicht beschäftigt

    Gerade überlege ich, ob man nicht ein Polling in einer einzigen ISR zum Pulsmessen durchführen könnte.
    Also irgendeiner der drei Interrupts tritt auf und in der einzigen ISR, die allen drei Interrupts zugeordnet ist werden dann alle drei Eingänge auf ihren Zustand gepollt und über Flagsteuerung Falschberechnungen verhindert werden. Keine Ahnung, ob das schneller werden könnte ...

    Gruß
    Searcher
    Code:
    Rc_eingang_1:
     $asm
       sbis pinb , 1                        'Skip next Instr if PINBx = 1
       rjmp pulslaenge1                     'Spring zur Berechnung von Impulslaenge
        push r17                             'Register auf Stack sichern
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_1_start} , r17        'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_1_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal high Byte
       pop r17                              'Register vom Stack zurückholen
       rjmp ende1                           'Springe zum Ende
      Pulslaenge1:
       push r16                             'Register auf Stack sichern
       in r16,sreg                          'Statusregister holen und halten
       push r17                             'Register auf Stack sichern
       push r18                             'Register auf Stack sichern
       in r17 , tcnt1l                      'Timer1 low Byte holen
       lds r18 , {Rc_signal_1_start}        'Hole Rc_signal low Byte
       Sub R17 , R18                        'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_1} , r17           'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       lds r18 , {Rc_signal_1_start} + 1    'Hole Rc_signal high Byte
       sbc r17 , r18                        'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_1} + 1 , r17       'Speichere Resultat high Byte nach Impulslaenge high Byte
       pop r18                              'Register vom Stack zurückholen
       pop r17                              'Register vom Stack zurückholen
       Out Sreg , R16                       'Statusregister zurückspeichern
       pop r16                              'Register vom Stack zurückholen
      Ende1:
     $end Asm
    Return
    Geändert von Searcher (22.12.2013 um 12:09 Uhr)
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  7. #17
    Neuer Benutzer Öfters hier
    Registriert seit
    12.12.2013
    Alter
    47
    Beiträge
    22
    @Searcher
    Nach dem ganzen "Weihnachts- und Familienfeierstreß" habe ich mich wieder dem Programmieren zugewand. Ich habe Deinen ASM-Code mal drauf gespielt. Ist schwer zu sagen, ob es gewirkt hat: Die Servos haben vorher leicht gezuckt, und zucken hinterher auch leicht (subjektiv etwas weniger). Ich denke es liegt daran, dass wir bisher "nur" bei den 3 ISRs vom RC-Signal Einlesen Zeit gespart haben. Bei der Ausgabe wird allerding viel öfter in die ISR gesprungen (alleine 6-7 mal nur für die Pausenzeit).

    Ich habe die letzten Stunden damit verbacht, Deinen ASM Code zu verstehen. Meine Güte, wer hat sich den sowas ausgedacht Obwohl ich versucht habe, mich auch hier http://www.avr-asm-tutorial.net/avr_de/index.html einzulesen, gebe ich nun offen und ehrlich zu: ASM werd ich wohl nie kapieren

    Ich habe den neuen Code nochmal angehängt. Deinen Code, der die Register nur im Bedarfsfall sichert/holt, konnte ich anpassen und einfügen (war nach Deiner tollen Vorarbeit auch nicht so schwer).
    Nur die Ausgabe ISR habe ich nicht realisieren können

    mfg
    Robert

    Code:
    '===============================================================================
    'RC Eingang 1 an Pin 3 (PB1, PCINT9)
    'RC Eingang 2 an Pin 6 (PA7, PCINT7)
    'RC Eingang 3 an Pin 5 (PB2, INT0)
    'Servo 1 an Pin 13 (PA0)
    'Servo 2 an Pin 12 (PA1)
    'Servo 3 an Pin 11 (PA2)
    'Servo 4 an Pin 10 (PA3)
    '===============================================================================
    
    $regfile = "attiny84.dat"
    $crystal = 8000000                                          'FuseBit CKDIV8 deaktivieren
    
    $hwstack = 50
    $swstack = 50
    $framesize = 50
    
    
    '-------------------------------------------------------------------------------------------------
    'Timer und konfigurieren
    '-------------------------------------------------------------------------------------------------
    
    Config Timer1 = Timer , Prescale = 8                        'Timer für Einlesen RC Signale
    Start Timer1
    
    Config Timer0 = Timer , Prescale = 64                       'Timer für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms
    Enable Timer0
    On Timer0 Servoausgabe
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Variablen definieren
    '-------------------------------------------------------------------------------------------------------------
    
    'Variablen fürs RC Einlesen
    Dim Rc_signal_1_start As Word
    Dim Rc_signal_2_start As Word
    Dim Rc_signal_3_start As Word
    
    Dim Impulslaenge_1 As Word
    Dim Impulslaenge_2 As Word
    Dim Impulslaenge_3 As Word
    
    
    
    'Variablen für Berechnungen
    Dim Berechnung_1 As Word
    Dim Berechnung_2 As Word
    
    
    
    'Variablen für Servoausgabe
    Dim Kanal As Byte
    Dim Servoausgabe_1 As Byte
    Dim Servoausgabe_2 As Byte
    Dim Servoausgabe_3 As Byte
    Dim Servoausgabe_4 As Byte
    Dim Pausen_variable As Byte
    
    
    '-------------------------------------------------------------------------------------------------
    'Einigen Variablen Werte zuweisen
    '-------------------------------------------------------------------------------------------------
    
    Kanal = 1
    Pausen_variable = 0
    
    '-------------------------------------------------------------------------------------------------------------
    'Ein- und Ausgang festlegen
    '-------------------------------------------------------------------------------------------------------------
    
    Ddra = &B00001111                                           'PA0 - PA3 werden Ausgänge
    Ddrb = &B00000000                                           'PortB bleibt Eingang
    
    
    '-------------------------------------------------------------------------------------------------
    'Interrupt-Service-Routinen konfigurieren und freigeben
    '-------------------------------------------------------------------------------------------------
    
    'Info:
    'Alle Porta Pinchangeinterrupts sind in Bascom "PCINT0" zugeordnet.
    'Alle Portb Pinchangeinterrupts sind in Bascom "PCINT1" zugeordnet.
    
    
    Pcmsk1.pcint9 = 1                                           'beim Flankenwechsel an PB1/PCINT9 (RC Eingang 1) Pinchangeinterrupt1 auslösen und in die Subroutine springen
    Enable Pcint1                                               'Pinchangeinterrupt1 (1 weil auf PortB) zulassen
    On Pcint1 Rc_eingang_1 Nosave           'Register werden manuel in der ISR gesichert
    
    
    Pcmsk0.pcint7 = 1                                           'beim Flankenwechsel an PA7/PCINT6 (RC Eingang 2) Pinchangeinterrupt0 auslösen und in die Subroutine springen
    Enable Pcint0                                               'Pinchangeinterrupt0 (0 weil auf PortA) zulassen
    On Pcint0 Rc_eingang_2 Nosave           'Register werden manuel in der ISR gesichert
    
    
    Config Int0 = Change                                        'beim Flankenwechsel an PB2/INT0 (RC Eingang 3) Int0 auslösen und in die Subroutine springen
    Enable Int0
    On Int0 Rc_eingang_3 Nosave             'Register werden manuel in der ISR gesichert
    
    Enable Interrupts
    
    
    
    '======================================================
    'Hauptprogramm
    '======================================================
    
    Do
    
    
    'Umrechnung erstes RC Signal auf 8-Bit
    Berechnung_1 = Impulslaenge_1 / 8                           'ergibt Werte zwischen 125 und 250
    
    If Berechnung_1 > 255 Then                                  'zu hohe Werte abfangen
       Berechnung_1 = 255
    End If
    
    If Berechnung_1 < 120 Then                                  'zu kleine Werte abfangen
       Berechnung_1 = 120
    End If
    
    
    'Umrechnung zweites RC Signal auf 8-Bit
    Berechnung_2 = Impulslaenge_2 / 8                           'ergibt Werte zwischen 125 und 250
    
    If Berechnung_2 > 255 Then                                  'zu hohe Werte abfangen
       Berechnung_2 = 255
    End If
    
    If Berechnung_2 < 120 Then                                  'zu kleine Werte abfangen
       Berechnung_2 = 120
    End If
    
    
    
    Servoausgabe_1 = Berechnung_1
    Servoausgabe_2 = Berechnung_2
    Servoausgabe_3 = 190
    Servoausgabe_4 = 190
    
    
    Loop
    
    
    
    '======================================================
    'ISR
    '======================================================
    
    
    'Rc_eingang_1:
    '   If Pinb.1 = 1 Then
    '   Rc_signal_1_start = Timer1
    '   Else
    '   Impulslaenge_1 = Timer1 - Rc_signal_1_start
    '   End If
    'Return
    
    Rc_eingang_1:
     $asm
       sbis pinb , 1                        'Skip next Instr if PINBx = 1
       rjmp pulslaenge1                     'Spring zur Berechnung von Impulslaenge
       push r17                                                 'Register auf Stack sichern
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_1_start} , r17        'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_1_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal high Byte
       pop r17                              'Register vom Stack zurückholen
       rjmp ende1                           'Springe zum Ende
      Pulslaenge1:
       push r16                             'Register auf Stack sichern
       in r16,sreg                          'Statusregister holen und halten
       push r17                             'Register auf Stack sichern
       push r18                             'Register auf Stack sichern
       in r17 , tcnt1l                      'Timer1 low Byte holen
       lds r18 , {Rc_signal_1_start}        'Hole Rc_signal low Byte
       Sub R17 , R18                        'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_1} , r17           'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       lds r18 , {Rc_signal_1_start} + 1    'Hole Rc_signal high Byte
       sbc r17 , r18                        'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_1} + 1 , r17       'Speichere Resultat high Byte nach Impulslaenge high Byte
       pop r18                              'Register vom Stack zurückholen
       pop r17                              'Register vom Stack zurückholen
       Out Sreg , R16                       'Statusregister zurückspeichern
       pop r16                              'Register vom Stack zurückholen
      Ende1:
     $end Asm
    Return
    
    'Rc_eingang_2:
    '   If Pina.7 = 1 Then
    '   Rc_signal_2_start = Timer1
    '   Else
    '   Impulslaenge_2 = Timer1 - Rc_signal_2_start
    '   End If
    'Return
    
    Rc_eingang_2:
     $asm
       sbis pinA , 7                                            'Skip next Instr if PINBx = 1
       rjmp pulslaenge2                                         'Spring zur Berechnung von Impulslaenge
       push r17                                                 'Register auf Stack sichern
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_2_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_2_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal high Byte
       pop r17                                                  'Register vom Stack zurückholen
       rjmp ende2                                               'Springe zum Ende
      Pulslaenge2:
       push r16                                                 'Register auf Stack sichern
       in r16,sreg                                              'Statusregister holen und halten
       push r17                                                 'Register auf Stack sichern
       push r18                                                 'Register auf Stack sichern
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       lds r18 , {Rc_signal_2_start}                            'Hole Rc_signal low Byte
       Sub R17 , R18                                            'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_2} , r17                               'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       lds r18 , {Rc_signal_2_start} + 1                        'Hole Rc_signal high Byte
       sbc r17 , r18                                            'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_2} + 1 , r17                           'Speichere Resultat high Byte nach Impulslaenge high Byte
       pop r18                                                  'Register vom Stack zurückholen
       pop r17                                                  'Register vom Stack zurückholen
       Out Sreg , R16                                           'Statusregister zurückspeichern
       pop r16                                                  'Register vom Stack zurückholen
      Ende2:
     $end Asm
    Return
    
    'Rc_eingang_3:
    '   If Pinb.2 = 1 Then
    '   Rc_signal_3_start = Timer1
    '   Else
    '   Impulslaenge_3 = Timer1 - Rc_signal_3_start
    '   End If
    'Return
    
    Rc_eingang_3:
    $asm
       sbis pinb , 2                                            'Skip next Instr if PINBx = 1
       rjmp pulslaenge3                                         'Spring zur Berechnung von Impulslaenge
       push r17                                                 'Register auf Stack sichern
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_3_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_3_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal high Byte
       pop r17                                                  'Register vom Stack zurückholen
       rjmp ende3                                               'Springe zum Ende
      Pulslaenge3:
       push r16                                                 'Register auf Stack sichern
       in r16,sreg                                              'Statusregister holen und halten
       push r17                                                 'Register auf Stack sichern
       push r18                                                 'Register auf Stack sichern
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       lds r18 , {Rc_signal_3_start}                            'Hole Rc_signal low Byte
       Sub R17 , R18                                            'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_3} , r17                               'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       lds r18 , {Rc_signal_3_start} + 1                        'Hole Rc_signal high Byte
       sbc r17 , r18                                            'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_3} + 1 , r17                           'Speichere Resultat high Byte nach Impulslaenge high Byte
       pop r18                                                  'Register vom Stack zurückholen
       pop r17                                                  'Register vom Stack zurückholen
       Out Sreg , R16                                           'Statusregister zurückspeichern
       pop r16                                                  'Register vom Stack zurückholen
      Ende3:
     $end Asm
    Return
    
    
    
    Servoausgabe:
    
    If Kanal = 1 Then
       If Porta.0 = 0 Then                                      'wenn der Ausgangspin aus ist
          Load Timer0 , Servoausgabe_1                          'wird der Timer0 mit dem Wert der Variable "Servoausgabe_1" vorgeladen
          Porta.0 = 1                                           'und der Ausgangspin eingeschaltet
       Else                                                     'erst beim nächsten Timer0 Überlauf landen wir hier
          Porta.0 = 0                                           'Ausgangspin wird wieder ausgeschaltet
          Incr Kanal                                            'und der nächsten Kanal bearbeitet
       End If
    End If
    
    
    If Kanal = 2 Then
       If Porta.1 = 0 Then
          Load Timer0 , Servoausgabe_2
          Porta.1 = 1
       Else
          Porta.1 = 0
          Incr Kanal
       End If
    End If
    
    
    If Kanal = 3 Then
       If Porta.2 = 0 Then
          Load Timer0 , Servoausgabe_3
          Porta.2 = 1
       Else
          Porta.2 = 0
          Incr Kanal
       End If
    End If
    
    
    If Kanal = 4 Then
       If Porta.3 = 0 Then
          Load Timer0 , Servoausgabe_4
          Porta.3 = 1
       Else
          Porta.3 = 0
          Incr Kanal
       End If
    End If
    
    
    
    'Pausenauffüllung
    
    
    If Kanal = 5 Then
      Timer0 = 0                                                '8-Bit Timer auf 0, Überlauf alle 2,048ms
      If Pausen_variable < 7 Then                               '2,048ms * 6 = 12,288ms Pausenfüllzeit
      Incr Pausen_variable
      Else
      Pausen_variable = 0
      Kanal = 1
      End If
    End If
    
    
    Return

  8. #18
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.649
    Blog-Einträge
    133
    Hallo,

    ich nutze ASM auch nur, wenn es zeitkritisch wird. Die Anfänge sind eigentlich nicht so schwer aber um ASM richtig auszunutzen bedarf es schon einiger Praxis (die mir auch noch fehlt).

    Ich habe im Augenblick nicht die Ruhe mich eingehend mit der Aufgabe zu beschäftigen aber trotzdem noch ein paar Gedanken, weil ich bisher nur auf die 1:1 Umsetzung der ISR nach ASM geschaut habe:

    Die ASM-ISRs zum Messen der Impulse dauern im ungünstigen Fall 5µs. Liegen die asynchron ankommenden Impulse zeitmäßig ungünstig (alle drei fallende Flanken zum gleichen Zeitpunk) wird die letzte ISR schon mit 10µs Verzögerung aufgerufen, da ja die ersten beiden Flanken abgearbeitet werden. Die 10µs Ungenauigkeit (Jitter in der Pulsweite) veranlassen die meisten Servos schon zu einer Bewegung ohne die Ausgaberoutine genauer unter die Lupe genommen zu haben.

    Neue Idee ist nun, den Puls an einem Eingang komplett zu messen und eventuell weitere Pulse an den anderen Eingängen erstmal zu ignorieren. Der gemessene Eingang wird "gesperrt" um den nächsten Eingang zu komplett zu messen. Das Spiel geht weiter, bis der letzte Pulseingang gemessen wurde und dann kann mit dem ersten wieder begonnen werden.

    Vorteil ist erstmal eine genaue Pulslängenmessung. Die Pulse treffen ja alle 20ms ein. Im schlechten Fall würden also 3 oder 4 aufeinander folgende Impulse eines Einganges nicht gemessen, also 60ms bis 80ms würde keine Veränderung in der Pulsweite eines Eingangs festgestellt werden - würd ich als vernachlässigbar bei der Baggersteuerung ansehen!?

    Wahrscheinlich vielleicht käme man dann auch ohne ASM aus.

    In der Zeit, in der die Pulseeingänge nacheinander gemessen werden, müssen natürlich alle 20ms die Servos mit den Steuerimpulsen versorgt werden. Kann auch, da die Meßergebnisse zwischengespeichert werden und wenn ein Eingang mit Messen dran ist, aktualisiert wird. - Wie gesagt, soweit bin ich noch nicht - Vielleicht läßt sich radbruchs Methode verwenden oder Deine? Wird halt eine weitere Aufgabe...


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

  9. #19
    Neuer Benutzer Öfters hier
    Registriert seit
    12.12.2013
    Alter
    47
    Beiträge
    22
    Zitat Zitat von Searcher Beitrag anzeigen
    Neue Idee ist nun, den Puls an einem Eingang komplett zu messen und eventuell weitere Pulse an den anderen Eingängen erstmal zu ignorieren. Der gemessene Eingang wird "gesperrt" um den nächsten Eingang komplett zu messen.
    Sowas habe ich bereits versucht umzusetzen, indem ich entsprechende Interrupts disabled und das entsprechende Flag im Timer/Counter Interrupt Flag Register unmittelbar vor Verlassen der Einlese-ISR gesetzt habe. Dadurch wurden (EINLESE-)Interrupts, die wärend des Einlesens eines Kanals aufgetreten sind, gelöscht. Die einzelnen Eingänge sind dann nacheinander eingelesen worden. Dass ich dafür länger brauche, bis alle Daten der 3 Eingänge aktualisiert sind, ist kein Problem.

    Ich durfte dabei aber nicht die Flags der Ausgabe ISR löschen, da sich sonst die Servos überschlugen (war ja auch zu erwarten). Ich denke, dass nur noch eine Beschleunigung der (zeitaufwendigen) Springerei in die Ausgabe ISR etwas vom Servozitten nehmen kann. Mit meinem ASM-Kenntnissen (Gesamtlerndauer 10 Stunden, am Stück, heute) komme ich aber defenitiv nicht weiter.

    Könnte mir jemand Schritt für Schritt erklären, wie ich einen passenden ASM Code basteln kann, ohne dafür 3 Jahre an die Uni zu müssen?

    Schönes Wochenende noch,
    Robert

  10. #20
    Erfahrener Benutzer Robotik Einstein Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.649
    Blog-Einträge
    133
    Zitat Zitat von R2D2 Bastler Beitrag anzeigen
    Sowas habe ich bereits versucht umzusetzen, ....
    Gut, doch keine neue Idee Egal, dann hab ich was zum Testen für Dich. Eine Übersetzung der Ausgabe ISR nach ASM. Ohne Gewähr (wie immer) da ich außer Kompilieren nicht getestet habe.
    Ist wieder nichts weiter als eine fast 1:1 Übersetzung von der Funktion her. In der Bascom ISR wird mit "Load Timer" gearbeitet. Das hab ich zur "Servoausgabe_x" Berechnung in der Hauptschleife vorweggenommen und nicht weiter überprüft, ob das so hinhauen kann. Sollte eigentlich nach der Bascom Hilfe zu LOAD. - nosave - bei der ON Timer0 label Anweisung. Viel Muße bei der Durchsicht

    Könnte mir jemand Schritt für Schritt erklären, wie ich einen passenden ASM Code basteln kann, ohne dafür 3 Jahre an die Uni zu müssen?
    Das wär zu viel für mich Hab versucht gut zu kommentieren.

    Gruß
    Searcher

    Code:
    '===============================================================================
    'RC Eingang 1 an Pin 3 (PB1, PCINT9)
    'RC Eingang 2 an Pin 6 (PA7, PCINT7)
    'RC Eingang 3 an Pin 5 (PB2, INT0)
    'Servo 1 an Pin 13 (PA0)
    'Servo 2 an Pin 12 (PA1)
    'Servo 3 an Pin 11 (PA2)
    'Servo 4 an Pin 10 (PA3)
    '===============================================================================
    
    $regfile = "attiny84.dat"
    $crystal = 8000000                                          'FuseBit CKDIV8 deaktivieren
    
    $hwstack = 50
    $swstack = 50
    $framesize = 50
    
    
    '-------------------------------------------------------------------------------------------------
    'Timer und konfigurieren
    '-------------------------------------------------------------------------------------------------
    
    Config Timer1 = Timer , Prescale = 8                        'Timer für Einlesen RC Signale
    Start Timer1
    
    Config Timer0 = Timer , Prescale = 64                       'Timer für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms
    Enable Timer0
    On Timer0 Servoausgabe Nosave           'Register werden manuell in der ISR gesichert
    
    
    '-------------------------------------------------------------------------------------------------------------
    'Variablen definieren
    '-------------------------------------------------------------------------------------------------------------
    
    'Variablen fürs RC Einlesen
    Dim Rc_signal_1_start As Word
    Dim Rc_signal_2_start As Word
    Dim Rc_signal_3_start As Word
    
    Dim Impulslaenge_1 As Word
    Dim Impulslaenge_2 As Word
    Dim Impulslaenge_3 As Word
    
    
    
    'Variablen für Berechnungen
    Dim Berechnung_1 As Word
    Dim Berechnung_2 As Word
    
    
    
    'Variablen für Servoausgabe
    Dim Kanal As Byte
    Dim Servoausgabe_1 As Byte
    Dim Servoausgabe_2 As Byte
    Dim Servoausgabe_3 As Byte
    Dim Servoausgabe_4 As Byte
    Dim Pausen_variable As Byte
    
    
    '-------------------------------------------------------------------------------------------------
    'Einigen Variablen Werte zuweisen
    '-------------------------------------------------------------------------------------------------
    
    Kanal = 1
    Pausen_variable = 0
    
    '-------------------------------------------------------------------------------------------------------------
    'Ein- und Ausgang festlegen
    '-------------------------------------------------------------------------------------------------------------
    
    Ddra = &B00001111                                           'PA0 - PA3 werden Ausgänge
    Ddrb = &B00000000                                           'PortB bleibt Eingang
    
    
    '-------------------------------------------------------------------------------------------------
    'Interrupt-Service-Routinen konfigurieren und freigeben
    '-------------------------------------------------------------------------------------------------
    
    'Info:
    'Alle Porta Pinchangeinterrupts sind in Bascom "PCINT0" zugeordnet.
    'Alle Portb Pinchangeinterrupts sind in Bascom "PCINT1" zugeordnet.
    
    
    Pcmsk1.pcint9 = 1                                           'beim Flankenwechsel an PB1/PCINT9 (RC Eingang 1) Pinchangeinterrupt1 auslösen und in die Subroutine springen
    Enable Pcint1                                               'Pinchangeinterrupt1 (1 weil auf PortB) zulassen
    On Pcint1 Rc_eingang_1 Nosave           'Register werden manuel in der ISR gesichert
    
    
    Pcmsk0.pcint7 = 1                                           'beim Flankenwechsel an PA7/PCINT6 (RC Eingang 2) Pinchangeinterrupt0 auslösen und in die Subroutine springen
    Enable Pcint0                                               'Pinchangeinterrupt0 (0 weil auf PortA) zulassen
    On Pcint0 Rc_eingang_2 Nosave           'Register werden manuel in der ISR gesichert
    
    
    Config Int0 = Change                                        'beim Flankenwechsel an PB2/INT0 (RC Eingang 3) Int0 auslösen und in die Subroutine springen
    Enable Int0
    On Int0 Rc_eingang_3 Nosave             'Register werden manuel in der ISR gesichert
    
    Enable Interrupts
    
    
    
    '======================================================
    'Hauptprogramm
    '======================================================
    
    Do
    
    
    'Umrechnung erstes RC Signal auf 8-Bit
    Berechnung_1 = Impulslaenge_1 / 8                           'ergibt Werte zwischen 125 und 250
    
    If Berechnung_1 > 255 Then                                  'zu hohe Werte abfangen
       Berechnung_1 = 255
    End If
    
    If Berechnung_1 < 120 Then                                  'zu kleine Werte abfangen
       Berechnung_1 = 120
    End If
    
    
    'Umrechnung zweites RC Signal auf 8-Bit
    Berechnung_2 = Impulslaenge_2 / 8                           'ergibt Werte zwischen 125 und 250
    
    If Berechnung_2 > 255 Then                                  'zu hohe Werte abfangen
       Berechnung_2 = 255
    End If
    
    If Berechnung_2 < 120 Then                                  'zu kleine Werte abfangen
       Berechnung_2 = 120
    End If
    
    
    
    Servoausgabe_1 = 256 - Berechnung_1     'Servoausgabe_ zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
    Servoausgabe_2 = 256 - Berechnung_2     'Servoausgabe_ zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen)
    Servoausgabe_3 = 190
    Servoausgabe_4 = 190
    
    
    Loop
    
    
    
    '======================================================
    'ISR
    '======================================================
    
    
    'Rc_eingang_1:
    '   If Pinb.1 = 1 Then
    '   Rc_signal_1_start = Timer1
    '   Else
    '   Impulslaenge_1 = Timer1 - Rc_signal_1_start
    '   End If
    'Return
    
    Rc_eingang_1:
     $asm
       sbis pinb , 1                        'Skip next Instr if PINBx = 1
       rjmp pulslaenge1                     'Spring zur Berechnung von Impulslaenge
       push r17                                                 'Register auf Stack sichern
       in r17 , tcnt1l                      'Timer1 low Byte holen
       sts {Rc_signal_1_start} , r17        'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       sts {Rc_signal_1_start} + 1 , r17    'Speichere Timer1 high Byte nach Rc_signal high Byte
       pop r17                              'Register vom Stack zurückholen
       rjmp ende1                           'Springe zum Ende
      Pulslaenge1:
       push r16                             'Register auf Stack sichern
       in r16,sreg                          'Statusregister holen und halten
       push r17                             'Register auf Stack sichern
       push r18                             'Register auf Stack sichern
       in r17 , tcnt1l                      'Timer1 low Byte holen
       lds r18 , {Rc_signal_1_start}        'Hole Rc_signal low Byte
       Sub R17 , R18                        'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_1} , r17           'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                      'Timer1 high Byte holen
       lds r18 , {Rc_signal_1_start} + 1    'Hole Rc_signal high Byte
       sbc r17 , r18                        'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_1} + 1 , r17       'Speichere Resultat high Byte nach Impulslaenge high Byte
       pop r18                              'Register vom Stack zurückholen
       pop r17                              'Register vom Stack zurückholen
       Out Sreg , R16                       'Statusregister zurückspeichern
       pop r16                              'Register vom Stack zurückholen
      Ende1:
     $end Asm
    Return
    
    'Rc_eingang_2:
    '   If Pina.7 = 1 Then
    '   Rc_signal_2_start = Timer1
    '   Else
    '   Impulslaenge_2 = Timer1 - Rc_signal_2_start
    '   End If
    'Return
    
    Rc_eingang_2:
     $asm
       sbis pinA , 7                                            'Skip next Instr if PINBx = 1
       rjmp pulslaenge2                                         'Spring zur Berechnung von Impulslaenge
       push r17                                                 'Register auf Stack sichern
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_2_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_2_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal high Byte
       pop r17                                                  'Register vom Stack zurückholen
       rjmp ende2                                               'Springe zum Ende
      Pulslaenge2:
       push r16                                                 'Register auf Stack sichern
       in r16,sreg                                              'Statusregister holen und halten
       push r17                                                 'Register auf Stack sichern
       push r18                                                 'Register auf Stack sichern
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       lds r18 , {Rc_signal_2_start}                            'Hole Rc_signal low Byte
       Sub R17 , R18                                            'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_2} , r17                               'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       lds r18 , {Rc_signal_2_start} + 1                        'Hole Rc_signal high Byte
       sbc r17 , r18                                            'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_2} + 1 , r17                           'Speichere Resultat high Byte nach Impulslaenge high Byte
       pop r18                                                  'Register vom Stack zurückholen
       pop r17                                                  'Register vom Stack zurückholen
       Out Sreg , R16                                           'Statusregister zurückspeichern
       pop r16                                                  'Register vom Stack zurückholen
      Ende2:
     $end Asm
    Return
    
    'Rc_eingang_3:
    '   If Pinb.2 = 1 Then
    '   Rc_signal_3_start = Timer1
    '   Else
    '   Impulslaenge_3 = Timer1 - Rc_signal_3_start
    '   End If
    'Return
    
    Rc_eingang_3:
    $asm
       sbis pinb , 2                                            'Skip next Instr if PINBx = 1
       rjmp pulslaenge3                                         'Spring zur Berechnung von Impulslaenge
       push r17                                                 'Register auf Stack sichern
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       sts {Rc_signal_3_start} , r17                            'Speichere Timer1 low Byte nach Rc_signal low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       sts {Rc_signal_3_start} + 1 , r17                        'Speichere Timer1 high Byte nach Rc_signal high Byte
       pop r17                                                  'Register vom Stack zurückholen
       rjmp ende3                                               'Springe zum Ende
      Pulslaenge3:
       push r16                                                 'Register auf Stack sichern
       in r16,sreg                                              'Statusregister holen und halten
       push r17                                                 'Register auf Stack sichern
       push r18                                                 'Register auf Stack sichern
       in r17 , tcnt1l                                          'Timer1 low Byte holen
       lds r18 , {Rc_signal_3_start}                            'Hole Rc_signal low Byte
       Sub R17 , R18                                            'Subtrahiere Rc_signal low Byte von Timer1 low Byte
       sts {Impulslaenge_3} , r17                               'Speichere Resultat low Byte nach Impulslaenge low Byte
       in r17 , tcnt1h                                          'Timer1 high Byte holen
       lds r18 , {Rc_signal_3_start} + 1                        'Hole Rc_signal high Byte
       sbc r17 , r18                                            'Subtrahiere Rc_signal high Byte von Timer1 high Byte
       sts {Impulslaenge_3} + 1 , r17                           'Speichere Resultat high Byte nach Impulslaenge high Byte
       pop r18                                                  'Register vom Stack zurückholen
       pop r17                                                  'Register vom Stack zurückholen
       Out Sreg , R16                                           'Statusregister zurückspeichern
       pop r16                                                  'Register vom Stack zurückholen
      Ende3:
     $end Asm
    Return
    
    
    
    Servoausgabe:
    
    'If Kanal = 1 Then
    '   If Porta.0 = 0 Then                                      'wenn der Ausgangspin aus ist
    '      Load Timer0 , Servoausgabe_1                          'wird der Timer0 mit dem Wert der Variable "Servoausgabe_1" vorgeladen
    '      Porta.0 = 1                                           'und der Ausgangspin eingeschaltet
    '   Else                                                     'erst beim nächsten Timer0 Überlauf landen wir hier
    '      Porta.0 = 0                                           'Ausgangspin wird wieder ausgeschaltet
    '      Incr Kanal                                            'und der nächsten Kanal bearbeitet
    '   End If
    'End If
    
    
     $asm
       push r16                             'Register auf Stack sichern
       in r16,sreg                          'Statusregister holen und halten
       push r17                             'Register auf Stack sichern
       push r18                             'Register auf Stack sichern
       lds r17 , {kanal}                    'hole Kanalnummer
       cpi r17 , 1                          'check Kanal und ...
       brne LABEL_KANAL_2                   '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 0                       'Skip next instr. wenn PORTA.0 = 0 ist
       rjmp label_1                         'Springe zum LOW-setzen des Servosignals
       lds r18 , {Servoausgabe_1}           'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R18                      'Setze Timer0 mit Pulslängenwert
       sbi porta , 0                        'Setze Servosignal HIGH
       rjmp Ende_isr                        'Springe zum Ende der ISR
      Label_1:
       cbi porta , 0                        'Setze Servosignal nach LOW
       inc r17                              'Erhöhe Kanalnummer
       sts {kanal} , r17                    'Sichere Kanalnummer
    
    'If Kanal = 2 Then
    '   If Porta.1 = 0 Then
    '      Load Timer0 , Servoausgabe_2
    '      Porta.1 = 1
    '   Else
    '      Porta.1 = 0
    '      Incr Kanal
    '   End If
    'End If
    
      Label_kanal_2:                        'Bearbeitung von Kanal 2
       cpi r17 , 2                          'check Kanal und ...
       brne LABEL_KANAL_3                   '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 1                       'Skip next instr. wenn PORTA.1 = 0 ist
       rjmp label_2                         'Springe zum LOW-setzen des Servosignals
       lds r18 , {Servoausgabe_2}           'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R18                      'Setze Timer0 mit Pulslängenwert
       sbi porta , 1                        'Setze Servosignal HIGH
       rjmp Ende_isr                        'Springe zum Ende der ISR
      Label_2:
       cbi porta , 1                        'Setze Servosignal nach LOW
       inc r17                              'Erhöhe Kanalnummer
       sts {kanal} , r17                    'Sichere Kanalnummer
    
    'If Kanal = 3 Then
    '   If Porta.2 = 0 Then
    '      Load Timer0 , Servoausgabe_3
    '      Porta.2 = 1
    '   Else
    '      Porta.2 = 0
    '      Incr Kanal
    '   End If
    'End If
    
      Label_kanal_3:                        'Bearbeitung von Kanal 3
       cpi r17 , 3                          'check Kanal und ...
       brne LABEL_KANAL_4                   '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 2                       'Skip next instr. wenn PORTA.2 = 0 ist
       rjmp label_3                         'Springe zum LOW-setzen des Servosignals
       lds r18 , {Servoausgabe_3}           'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R18                      'Setze Timer0 mit Pulslängenwert
       sbi porta , 2                        'Setze Servosignal HIGH
       rjmp Ende_isr                        'Springe zum Ende der ISR
      Label_3:
       cbi porta , 2                        'Setze Servosignal nach LOW
       inc r17                              'Erhöhe Kanalnummer
       sts {kanal} , r17                    'Sichere Kanalnummer
    
    'If Kanal = 4 Then
    '   If Porta.3 = 0 Then
    '      Load Timer0 , Servoausgabe_4
    '      Porta.3 = 1
    '   Else
    '      Porta.3 = 0
    '      Incr Kanal
    '   End If
    'End If
    
      Label_kanal_4:                        'Bearbeitung von Kanal 4
       cpi r17 , 4                          'check Kanal und ...
       brne LABEL_KANAL_5                   '... "wenn nicht gleich" verzweige zum nächsten Kanal
       sbic porta , 3                       'Skip next instr. wenn PORTA.3 = 0 ist
       rjmp label_4                         'Springe zum LOW-setzen des Servosignals
       lds r18 , {Servoausgabe_4}           'Hole aufbereiteten Pulslängenwert für Timer0
       Out Tcnt0 , R18                      'Setze Timer0 mit Pulslängenwert
       sbi porta , 3                        'Setze Servosignal HIGH
       rjmp Ende_isr                        'Springe zum Ende der ISR
      Label_4:
       cbi porta , 3                        'Setze Servosignal nach LOW
       inc r17                              'Erhöhe Kanalnummer
       sts {kanal} , r17                    'Sichere Kanalnummer
    
    'Pausenauffüllung
    
    'If Kanal = 5 Then
    '  Timer0 = 0                                                '8-Bit Timer auf 0, Überlauf alle 2,048ms
    '  If Pausen_variable < 7 Then                               '2,048ms * 6 = 12,288ms Pausenfüllzeit
    '  Incr Pausen_variable
    '  Else
    '  Pausen_variable = 0
    '  Kanal = 1
    '  End If
    'End If
    
      Label_kanal_5:                        'Bearbeitung von Kanal 5
       cpi r17 , 5                          'check Kanal und ...
       brne Ende_isr                        '... "wenn nicht gleich" verzweige zum Ende der ISR
       clr r18                              'Setze r18 auf 0
       Out Tcnt0 , R18                      'Setze Timer0 auf 0
       lds r18 , {pausen_variable}          'Hole Pausenvariable
       cpi r18 , 7                          'Vergleiche mit 7
       brlo label_incr_pause                'Ist Pausenvariable (r18) kleiner 7 verzweige
       clr r18                              'Setze r18 auf 0
       sts {pausen_variable} , r18          'Setze Pausenvariable auf 0
       ldi r17 , 1                          'Setze r17 auf 1
       sts {kanal} , r17                    'Setze Kanal auf 1 (Speichere r17 nach Kanal)
       rjmp ende_isr                        'Springe
      Label_incr_pause:
       inc r18                              'Erhöhe r18 um 1
       sts {pausen_variable} , r18          'Speichere r18 nach Pausenvariable
      Ende_isr:
       pop r18                              'Register vom Stack zurückholen
       pop r17                              'Register vom Stack zurückholen
       Out Sreg , R16                       'Statusregister zurückspeichern
       pop r16                              'Register vom Stack zurückholen
     $end Asm
    Return
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

Seite 2 von 8 ErsteErste 1234 ... LetzteLetzte

Ähnliche Themen

  1. Mehrere analoge Werte über ein ADC einlesen möglich?
    Von HeXPloreR im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 07.08.2012, 17:18
  2. Schaltkreis für mehrere Servos
    Von Sebbokalypse im Forum Elektronik
    Antworten: 9
    Letzter Beitrag: 12.11.2009, 18:46
  3. Mehrere Signale umschalten
    Von flexxo im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 25.02.2007, 13:56
  4. Antworten: 9
    Letzter Beitrag: 02.04.2006, 17:53
  5. Mehrere Signale über einen Interrupt erkennen
    Von Minifriese im Forum Elektronik
    Antworten: 22
    Letzter Beitrag: 04.06.2004, 08:31

Berechtigungen

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