Hey Leute! Ich habe mir ein STK500 zugelegt und habe schon etwas Erfahrung mit Bascom bin aber noch Anfänger. Ich möchte einen Servo ansteuern, aber der macht nicht das, was ich will, ich nehme stark an, das an meinem Code etwas falsch ist, leider weiß ich nicht was. Ich habe abundzu noch mit der Syntax etwas Probleme bzw. damit, dem uC zu sagen, was er machen soll. Mein Vorhaben sah wie folgt aus: Ich wollte über den Timer0 alle 20ms aus dem Hauptprogramm (ich lass dort nur eine LED blinken) in eine ISR springen, die wiederum 1ms läuft. Dann wollte ich dem Servo 1ms ein Signal geben, das heißt er musste dann ganz nach links fahren. Tut er aber nicht, sondern zittert wenn überhaut ein bisschen, ich bin am verzweifeln. Kann mir jemand weiterhelfen? Ich habe zwar gelesen, dass es auch mit dem Timer1 geht, aber ich habe nicht ganz verstanden, wie ich die Comparewerte nutzen soll, um die Zeitdauer anzugeben, wie breit das Signal seien soll. Für Hilfe bin ich sehr dankbar, weil ich nicht weiß, wo mein Denkfehler ist. (Ich habe doch richtig verstanden, dass ein Servo alle 20ms ein Signal bekommt, welches 1ms - 2ms lang ist, oder? 1ms wäre ganz links, 1,5 Mittelstellung, 2ms ganz rechts) Den Servo (der von Conrad für 2,95€) habe ich an VTG/GND von Portd und das gelbe Kabel an Portd.5 angeschlossen. Anbei der Code: '----------------------------------------------------------------------- --' $regfile = "m16def.dat" $crystal = 8000000 $baud = 19200 $hwstack = 32 $swstack = 8 $framesize = 24 Dim K As Byte K = 131 Config Portb = Output Config Portd = Output Config Timer0 = Timer , Prescale = 1024 Enable Interrupts Enable Timer0 On Timer0 Isr_von_timer0 Timer0 = 99 Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Down , Prescale = 1 Enable Timer1 Start Timer1 Do Toggle Portb.0 Waitms 100 Loop End Isr_von_timer0: Config Timer0 = Timer , Timer0 = K , Prescale = 64 Compare1a = 1 Return '----------------------------------------------------------------------- -' Gruß Bascompasstschon
SChon mal die BASCOM Doku gelesen? BASCOM kann aus dem STand heraus Servos ansteuern. siehe zb http://halvar.at/elektronik/servo_mit_bascom_avr/
Ja, das habe ich gesehen. Aber kann ich einen Servo nicht auch über einen Timer mit Comparewerten steuern? Das wollte ich gerne hinbekommen. Gruß Bascompasstschon
Kann man. Aber wenn ich mir dein Machwerk so ansehe, bist du mit den vorgefertigten Routinen besser bedient. Aber seis drum: Ist zwar nicht BASCOM, aber die Idee kann man sich holen Modellbauservo Ansteuerung
Oh super, vielen Dank! :-))) Das habe ich gar nicht gesehen! :-) Ich wollte ganz gerne eine Lageregelung machen, das ist mein Ziel. Ich habe einen Gyro als Sensor (ADXRS610) und die Werte die ich einlese sind auch ganz in Ordnung, natürlich nicht perfekt, aber einigermaßen gut. Der Drift hält sich in Grenzen. Bei diesen Routinen verstehe ich nicht ganz, was sich hinter dem Reload verbirgt. Ich wollte das so machen, dass ich die Werte einlese und dann daraus einen Winkel bestimme. Aus diesem Winkel muss ich nun eine Signallänge bestimmen (z.B +180 = 2ms) und dem Motor dann je nach Lage x ms ein Signal (zwischen 1 - 2 ms) geben (alle 20 ms). So hatte ich mir das gedacht. Mein Problem bei der Routine ist, dass ich nicht genau weiß, was der Reload ist (in Bascom). Gruß Bascompasstschon
Bascompasstschon schrieb: > Bei diesen Routinen verstehe ich nicht ganz, was sich hinter dem Reload > verbirgt. Welchem Relaod? Wieviele Servos hast du? Eines? Dann nimm dir den Timer 1, setz den Prescaler so, dass du damit 2 Millisekunden gut in einem Timerwert abbilden kannst. Dann setzt du den Timer in einem PWM Modus auf. Der PWM Wert ist dann die Länge des Pulses, den der Timer erzeugt. Sprich: Deine gewünschte Zeit bildet sich in einem bestimmten Wert für das Vergleichsregister ab. Den Wert rechnest du im Programm aus und setzt ihn im Vergleichsregister. Fertig. Den Rest macht die Hardware-PWM > bestimmen (z.B +180 = 2ms) und dem Motor dann je nach Lage x ms ein > Signal (zwischen 1 - 2 ms) geben richtig > (alle 20 ms). Vergiss die 20ms. Die sind nicht wichtig. Ob der Puls alle 10 oder alle 15 oder alle 20 oder alle 25ms kommt, ist dem Servo herzlich egal. Das ist keine Zeit, auf die du dein Augenmerk richten musst. Du konzentrierst dich jetzt erst mal ausschlisslich darauf, einen Puls mit Pulslängen von 1 bis 2 ms zu generieren. Und zwar in Hardware mit der PWM. Wenn dann hinter dem Puls noch Zeit übrig bleibt, bis der Timer überläuft und den nächsten Puls anfängt, dann passt das schon.
Erst einmal, herzlichen Dank, dass du mir hilfst! :-) Ok, das werde ich versuchen, ich würde es so machen: '----------------------------------------------------------------------- --' 'Timer1 = 16Bit-Timer 'X_Takte: CPU[Hz]*Anzeit[ms]/1000 = X_Takte; 'Prescaler: Prescaler > X_Takte/65536 'Timer1_Anzahl_der_Takte: X_Takte/Prescaler = Timer_Anzahl_der_Takte 'Timer1 = 65536 - Timer_Anzahl_der_Takte '----------------------------------------------------------------------- --' Wenn ich die Anzeit[ms] auf 2ms setze bekomme ich für den Prescaler 256 (> 244,14). Wenn ich dann z.B. COMPARE1A = 2 eingebe, heißt das, dass der Servo dann ein Signal von 2ms bekommt und dann nach rechts fährt? Hier mein Programm: $regfile = "m16def.dat" $crystal = 8000000 $baud = 19200 $hwstack = 32 $swstack = 8 $framesize = 24 Config Portd = Output Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Down , Prescale = 256 Do Compare1a = 2 Loop End Was bedeutet Pwm = 8? Was würde passieren wenn ich den auf 9 oder 10 stelle? Vielen Dank für die Hilfe! Tut mir Leid, wenn ich noch etwas länger auf der Leitung stehe! Viele Grüße
Ich glaube ich habe schon einen Fehler entdeckt, so müsste es sein, oder? Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Down , Prescale = 256 Enable Timer Start Timer
Warum eigentlich "dringend" ? Das Problem, das sich mit einer PWM ergibt, ist daß bei PWM 8Bit nur 256 Stufen zur Verfügung stehen, und davon soll auch noch etwas die Pause übrig sein. Also ist nur ein Teil der 256 Schritte für das Servosignal nutzbar. Eine reine Hardware PWM hat lediglich den Vorteil, daß sie keinerlei Prozessorressourcen beansprucht. Ich würd' einen anderen Ansatz nehmen, den Timer auf CLEAR TIMER = 1 konfigurieren, dann eine Compare-ISR aufsetzen und darin den Compare1A-Wert abwechselnd auf die Puls- oder die Pause-Zeit setzen und dabei den Servo-Pin entsprechend umschalten. Das geht auch quasi im Hintergrund und schont die zur Verfügung stehende Rechenleistung, braucht vielleicht 0.5% davon. Solltest Du Deinen Hardware PWM Ansatz weiterverfolgen wollen, so wäre die Rechnung bei 8MHz: Servopuls 1-2ms, PWM 10Bit, Prescaler 64 = 8µs pro PWM-Stufe, ergibt für 1-2ms Werte von 62 - 128, mit einer Pulswiederholrate von 16,4ms. Wichtig dabei ist zu wissen daß Bascom die Phase Correct PWM verwendet, und die braucht doppelt so lange wie die Fast PWM, da sie rauf und runterzählt, also bei PWM 10Bit von 0 bis 1023 und von 1023 bis 0.
Hey, vielen Dank, das werde ich mal probieren. Allerdings weiß ich nicht genau, wie man das in einem Code schreiben kann, kannst du mir da evtl. helfen? Muss ich dann das nehmen: Config Timer1 = Counter , Edge = Falling , Compare A = Set , Compare B = Toggle , Clear Timer = 1 ? Würde das dann so aussehen? Ich habe noch mit der Syntax Probleme. :-( Config Portd = Output Condig Portb = Output Config Timer1 = Counter , Edge = Falling , Compare A = Set , Compare B = Toggle , Clear Timer = 1 Enable Timer1 Start Timer1 On Timer1 Isr_von_timer1 Do Toggle Portb.0 Loop End Isr_von_timer1: Compare1a = 2 Gruß Bascompasstschon
Wenn Du = Counter schreibst, dann wird der Prescaler abgeschaltet und der Zähler erwartet das was er zählen soll am Pin, sollte T1 sein, aber das willst Du sicher nicht. Du braucht bei Clear Timer überhaupt keinen PWM Mode angeben, Clear Timer arbeitet so, daß bei Eerreichen des Compare-Wertes der Zähler auf 0 gesetzt wird und wenn man es erlaubt hat, wird die Compare ISR anesprungen. In dieser ISR kann man dann den neuen Comparewert setzen. Syntax sollte in etwa so sein: Config Timer1 = Timer, Prescale = 64, Clear Timer = 1 On Compare1A Comp1_ISR Enable Compare1A Enable Interrupts ... Compare1A = 200 ' Wert, bei dem der Zähler rücksetzt und die ISR aufgerufen wird ... Comp1_ISR: ' Compare1A abwechselnd neu laden, usw. Return Ohne Gewähr, müsste es selbst testen. Versuch' doch mal, ob Du es so hinbekommst, lass erst mal in der ISR 'ne Led blinken, nimm 'nen höheren Prescaler, damit du's auch blinken siehst. Wenn das dann hinhaut, kannst Du in der ISR beginnen den Comparewert abwechselnd neu zu laden. Wenn das dann geht, hast Du Dein Ziel eigentlich schon erreicht.
Oh klasse, vielen Dank für die Hilfe! :-) Das werde ich dann so probieren! :-)
Hallo! Hier ein Auszug aus meinem Servotester mit 3 Tasten.
1 | $regfile = "m88def.dat" |
2 | $crystal = 16000000 |
3 | $hwstack = 48 |
4 | $swstack = 32 |
5 | $framesize = 32 |
6 | |
7 | Ddrb = &B00000001 'Portb.0 Ausgang für Servo |
8 | Portb = &B11111110 'Pullups Portb |
9 | |
10 | Dim Comp_b As Word |
11 | Dim Count As Word |
12 | |
13 | |
14 | Config Timer1 = Timer , Prescale = 8 , Compare A = Disconnect , Compare B = Disconnect , Clear Timer = 1 |
15 | |
16 | |
17 | Enable Oc1a |
18 | On Oc1a Testa |
19 | |
20 | Enable Oc1b |
21 | On Oc1b Testb |
22 | |
23 | Compare1a = 39999 '20ms |
24 | Compare1b = 2499 '449=linker Anschlag_4999=rechter Anschlag_2499=Mitte |
25 | |
26 | Enable Interrupts |
27 | |
28 | Do |
29 | |
30 | If Pinb.5 = 0 Then |
31 | Compare1b = 449 |
32 | End If |
33 | |
34 | If Pinb.4 = 0 Then |
35 | Compare1b = 4999 |
36 | End If |
37 | |
38 | If Pinb.3 = 0 Then |
39 | Compare1b = 2499 |
40 | End If |
41 | |
42 | Loop |
43 | End |
44 | |
45 | Testa: |
46 | |
47 | Portb.0 = 1 |
48 | |
49 | Return |
50 | |
51 | Testb: |
52 | |
53 | Portb.0 = 0 |
54 | |
55 | Return |
Code dient nur zur Funktionserklärung. Die Werte müssen natürlich an das verwendete Servo angepasst werden. MfG
Hallo Gerk! Vielen Dank für deinen Code! Ich werde ihn morgen gleich ausprobieren und werde versuchen alles zu verstehen! :-) Heute bin ich leider nicht dazu gekommen, etwas zu machen! Also, einen schönen Restsonntag! :-) Bis dann! Gruß Bascompasstschon
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.