So, hier nochmal der Code für ein einzelnes Servo auf dem kleineren Attiny45. Die Berechnung der Servogeschwindigkeit musste nochmals komplett überarbeitet werden, da beim Attiny45 nur 8-Bit Timer zur Verfügung stehen. Da sich der Kleine nicht mit mehreren RC Signalen rumschlagen muss, war es (fast) kein Problem, die entsprechende Berechnung umzugestalten.
mfg
Robert
Code:'=============================================================================== 'Single Baggerarmsteuerung V3 ' 'RC Eingang 1 an Pin 7 (PB2, INT0) 'Poti 1a an Pin 2 (PB3, ADC3) 'Poti 1b an Pin 3 (PB4, ADC2) 'Servo 1 an Pin 6 (PB1) Baggerarmservo '=============================================================================== $regfile = "attiny45.dat" $crystal = 8000000 'FuseBit CKDIV8 deaktivieren $hwstack = 40 $swstack = 40 $framesize = 50 '------------------------------------------------------------------------------------------------- 'Timer konfigurieren '------------------------------------------------------------------------------------------------- Tccr1 = &B00000111 'Timer1 für RC-Signal Einlesung wird gestartet (Prescale 64) (geht beim Attiny45 nicht mit "Config"!) Config Timer0 = Timer , Prescale = 64 'Timer0 für Servoausgabe, Wert 125 entspricht 1ms, Wert 250 entspricht 2ms On Timer0 Servoausgabe Nosave 'Register werden manuel in der ISR gesichert Enable Timer0 '------------------------------------------------------------------------------------------------- 'Interrupt-Service-Routinen konfigurieren und freigeben '------------------------------------------------------------------------------------------------- Config Int0 = Change 'beim Flankenwechsel an PB2/INT0 (RC Eingang) Int0 auslösen und in die Subroutine springen Enable Int0 On Int0 Rc_eingang_1 Nosave 'Register werden manuel in der ISR gesichert Enable Interrupts '------------------------------------------------------------------------------------------------- 'Poti-Eingänge konfigurieren '------------------------------------------------------------------------------------------------- Config Adc = Single , Prescaler = Auto Start Adc '------------------------------------------------------------------------------------------------------------- 'Konstanten definieren '------------------------------------------------------------------------------------------------------------- Const Jitterausgleich = 2 'Wert in µs um den sich gemessene Impulslaenge aendern darf/muss, bevor Servo gestellt wird Const Rc_min = 122 'Minimaler RC-Wert für die Berechnungen (Werte zwischen 120 - 125 sinvoll) Const Rc_max = 253 'Maximaler RC-Wert für die Berechnungen (Werte zwischen 250 - 255 sinvoll) '------------------------------------------------------------------------------------------------------------- 'Variablen definieren '------------------------------------------------------------------------------------------------------------- Dim Rc_signal_1_start As Byte Dim Rc_signal_1_stop As Byte Dim Rc_signal_1_stop_flag As Byte Dim Impulslaenge_1 As Byte Dim Impulslaenge_1_alt As Byte Dim Impulslaengenaenderung As Integer 'wird nur einmal gebraucht, da nur Hilfswariable 'Variablen für Servowegsbegrenzung Dim Poti_1a As Word Dim Poti_1b As Word Dim Limit_1a As Byte Dim Limit_1b As Byte 'Variablen für Berechnungen Dim Berechnung_1 As Byte Dim Berechnung_1a As Byte Dim Servospeed As Byte Dim Zeit_1 As Byte Dim Zeit_2 As Word 'Variablen für Servoausgabe Dim Kanal As Byte Dim Servoausgabe_1 As Byte '------------------------------------------------------------------------------------------------- 'Einigen Variablen Werte zuweisen '------------------------------------------------------------------------------------------------- Kanal = 1 Berechnung_1a = 187 'Servo erst mal auf Mittelstellung '------------------------------------------------------------------------------------------------------------- 'Ein- und Ausgang festlegen '------------------------------------------------------------------------------------------------------------- Ddrb = &B00000010 'PB1 wird Ausgang, restlicher PortB bleibt Eingang '====================================================== 'Hauptprogramm '====================================================== Do 'RC Impulslänge berechnen und Grenzwerte festlegen If Rc_signal_1_stop_flag = 1 Then 'Bearbeitung nur, wenn ISR Pulsende gefunden hat Disable Int0 'Mögliche Korruption durch ISR vorbeugen Impulslaenge_1 = Rc_signal_1_stop - Rc_signal_1_start Enable Int0 Rc_signal_1_stop_flag = 0 Impulslaengenaenderung = Impulslaenge_1_alt - Impulslaenge_1 'SW-Hysterese If Abs(impulslaengenaenderung) >= Jitterausgleich Then Impulslaenge_1_alt = Impulslaenge_1 Berechnung_1 = Impulslaenge_1 If Berechnung_1 > Rc_max Then Berechnung_1 = Rc_max If Berechnung_1 < Rc_min Then Berechnung_1 = Rc_min End If End If 'Berechnung der Servogeschwindigkeit und Servostellung If Berechnung_1 < 182 And Berechnung_1a > Rc_min Then Servospeed = Berechnung_1 - Rc_min 'ergibt Werte zwischen 0 (schnell) und 61 (langsam) Zeit_1 = 61 - Servospeed 'inventieren (0=langsam, 61=schnell) Zeit_2 = Zeit_2 + Zeit_1 If Zeit_2 > 200 Then Decr Berechnung_1a Zeit_2 = 0 End If End If If Berechnung_1 > 193 And Berechnung_1a < Rc_max Then Servospeed = Rc_max - Berechnung_1 Zeit_1 = 61 - Servospeed 'inventieren Zeit_2 = Zeit_2 + Zeit_1 If Zeit_2 > 200 Then Incr Berechnung_1a Zeit_2 = 0 End If End If 'Potis abfragen und Werte für Servolimits berechnen Poti_1a = Getadc(3) Poti_1a = Poti_1a / 25 '1024 / 25 = 41, ergibt ca 30% Wegbegrenzung Limit_1a = 255 - Poti_1a Poti_1b = Getadc(2) Poti_1b = Poti_1b / 25 Limit_1b = 120 + Poti_1b 'RC Signal auf Limitwerte begrenzen If Berechnung_1a > Limit_1a Then 'zu hohe Werte abfangen Berechnung_1a = Limit_1a End If If Berechnung_1a < Limit_1b Then 'zu kleine Werte abfangen Berechnung_1a = Limit_1b End If 'Finale Berechnungen an Servoausgabe übergeben, Servoausgabe_x zum direkten Laden in TCNT0 vorbereiten (Cmd Load umgangen) Servoausgabe_1 = 256 - Berechnung_1a 'Baggerarmservo Loop '====================================================== 'ISR '====================================================== Rc_eingang_1: $asm push r17 'Register auf Stack sichern sbis pinb , 2 'Skip next Instr if PINBx = 1 rjmp Puls_ende1 'Springe Puls_ende in r17 , tcnt1 'Timer1 Wert holen sts {Rc_signal_1_start} , r17 'Speichere Timer1 nach Rc_signal_1_start rjmp ende1 'Springe zum Ende Puls_ende1: in r17 , tcnt1 'Timer1 Wert holen sts {Rc_signal_1_stop} , r17 'Speichere Timer1 nach Rc_signal_1_stop ldi r17 , 1 sts {Rc_signal_1_stop_flag} , r17 'Setze Flag zur Bearbeitung von Impulslaenge in Hauptschleife Ende1: pop r17 'Register vom Stack zurückholen $end Asm Return Servoausgabe: $asm push r16 'Register auf Stack sichern in r16,sreg 'Statusregister holen und halten push r17 '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 portB , 1 'Skip next instr. wenn PORTA.0 = 0 ist rjmp label_1 'Springe zum LOW-setzen des Servosignals sts {kanal} , r17 'Sichere Kanalnummer lds r17 , {Servoausgabe_1} 'Hole aufbereiteten Pulslängenwert für Timer0 Out Tcnt0 , R17 'Setze Timer0 mit Pulslängenwert sbi portB , 1 'Setze Servosignal HIGH rjmp Ende_isr 'Springe zum Ende der ISR Label_1: cbi portB , 1 'Setze Servosignal nach LOW inc r17 'Erhöhe Kanalnummer 'Pausenauffüllung 'Pausenanfang sts {kanal} , r17 'Sichere Kanalnummer ldi r17 , &B00000101 'CS00 und CS02 für prescaler 1024 in Timer0 vorbereiten Out Tccr0b , R17 'Timer0 läuft mit 128µs Auflösung ldi r17 , 162 'Wert für ca 12ms bis zum nächsten OVF (162=256-94) bei prescaler 1024 Out Tcnt0 , R17 rjmp Ende_isr 'Springe zum Ende der ISR 'Pausenende Label_kanal_2: 'Bearbeitung von Kanal 2 (Pausenende) ldi r17 , &B00000011 'CS00 und CS01 für prescaler 64 in Timer0 vorbereiten Out Tccr0b , R17 'Timer0 läuft wieder mit 8µs Auflösung ldi r17 , 1 'Kanalnummer auf 1 setzen sts {kanal} , r17 'Sichere Kanalnummer Ende_isr: 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
Zitieren

Lesezeichen