Hallo , ich bin leider noch neu auf diesem Gebiet und versuch schon seit Tagen eine normales Graupner Servo C577 mit dem Attiny 13 zu steuern. 1,2 MHz Habe schon viel in den Foren gelesen, doch leider tauchen immer neue Fragen. Habe ein Problem die funktion der Register mir vorzustellen. Um eine Rudermaschine mit einem PWM Signal von 20 ms und dann noch ein Signal von 1 bis 2 ms zu bekommen. Gibt es Register in die man high und low schreibt ? TCCR0A,A ;für high ? TCCR0B,A ;für low ? Oder müssen ich Warteschleifen schreiben die auf den Takt des Controllers abgestimmt werden ? Wie bekomme ich beim Attiny 13 den Modus CTC hin. Besteht die Möglichkeit das ich einen Quellcode bekomme. An dem ich die Funktion ausprobieren kann. Vielen Dank für Eure Hilfe!!!!!!
Versuche es mal mit Timer, das ist besser und genauer als Warteschleifen. Codebeispiele habe ich mal bei www.hanneslux.de gesehen, war aber glaube nicht für Tiny13. KH
Danke für den Tipp mit dem Timer, doch leider komme ich immer noch an meine Grenzen. Das Servo dreht voll auf Anschlag. Kennst Du Dich Assembler aus ? Könntest Du bitte eine Blick auf meinen Code werfen. Habe den CTC Modus genommen mit den Pin 0 zur Ausgabe Mein Attiny13 ist mit 1,2 MHz getacktet. Bin mir nicht sicher mit der Umsetzung der Schleifen für die 20ms und 1,5ms für die Mitte. Ob es überhaupt so funktionieren kann ,wenn ich die richtigen Werte einsetze. Auch mit dem Teiler stehe ich noch auf dem Schlauch, ob das alles so richtig ist ;) 1,2MHz (255/1200000) = 0,0002125µs = 0,2125 milli sec. dann müssten 20ms = 94 und 1,5ms = 7 Danke im Voraus Joachim
Naja, der Tiny13 hat nur einen 8-Bit-Timer, da passen beide Zeiten (20 ms und 1-2 ms) nicht bei erträglicher Auflösung rein. Daher ist Hardware-PWM kein guter Ansatz. CTC ist erst recht keine gute Idee. Beim Tiny15 bietet sich an, Timer1 mit Vorteiler 16 laufen zu lassen, das macht bei 16 MHz eine Auflösung von 10 µs, also Zahlenwerte von 100 bis 200 für 1 bis 2 ms. Der Tiny13 hat aber keinen feinstufigen Vorteiler, er hat nur Vorteiler durch 1, 8, 64, 256 oder 1024. Dafür kann man mittels CLKPR die Taktfrequenz in feineren Schritten verändern. Um nun in einer Timer-Runde (256 Schritte) die Zeiten von 1-2 ms abbilden zu können, bietet sich eine Taktfrequenz von 4,8 MHz und ein Vorteiler von 64 an. Eine Timer-Runde dauert demnach 3,4 ms, was Zahlenwerte von 75 und 150 für die beiden Endwerte (1 ms, 2 ms) ergibt und 112 für die Mitte (1,5 ms). Das ist zwar nicht so schön wie beim Tiny15, aber besser als gar nichts. Somit wäre also geklärt, wie die Impulsbreite erzeugt (bemessen) werden kann. Nun zur Impulspause. Die 20 ms passen in dieser Einstellung nicht in den Timer rein. Man könnte jetzt den Vorteiler umschalten und wechselweise beide Zeiten messen, es geht aber auch einfacher. Im Overflow-Interrupt des Timers wird eine Variable heruntergezählt, diese bestimmt die Impuls-Pause von etwa 20 ms. Als Startwert wird 6 festgelegt (6 x 3,4 ms = 20,4 ms), bei Erreichen von 0 wird sie wieder auf Startwert gesetzt, der Impulspin auf H geschaltet und die gewünschte Impulsbreite in das OCR0A-Register geschrieben, sozusagen als Termin für den Compare0A-Interrupt. Im Compare0A-Interrupt wird dann lediglich der Impuls-Portpin wieder auf L gesetzt. Bis zum nächsten Ablauf des Impulspausenzählers tritt der COM0A-Interrupt zwar öfters auf, aber ein bereits auf L gesetzter Portpin bleibt beim weiteren Setzen auf L auch nur L, es lohnt sich also nicht, diese Interrupts zu unterdrücken. Wenn es sein muss, kann der COM0A-Interrupt auch mehrere verschiedene Servoimpulse an mehreren Port-Pins erzeugen, die, wie bei einer RC-Fernsteuerung, nacheinander erfolgen. Das Hauptprogramm kann dann die Impulsbreite(n) als Zahlenwert bereitstellen, also die Servoposition, die angefahren werden soll. Dies kann z.B. durch Einlesen eines Potis per ADC erfolgen, oder durch Auswahl aus einer Liste mittels Up/Down-Taster, dann wäre aber noch eine Tastenentprellung einzubinden bzw. die ADC-Abfrage. Bisher hast Du Dich ja noch nicht dazu geäußert, wo der Sollwert (Stellposition) herkommen soll. KH
>Beim Tiny15 bietet sich an, Timer1 mit Vorteiler 16 laufen zu lassen, >das macht bei 16 MHz eine Auflösung von 10 µs, also Zahlenwerte von 100 >bis 200 für 1 bis 2 ms. Bei mir ergibt 16MHz durch 16 geteilt 1MHz, was eine Periodendauer von 1µs darstellt...
R..., Du hast (wie immer) recht, da fehlt ein Komma. Ich meinte natürlich 1,6 MHz. Ich danke Dir für diesen Hinweis. Beste Grüße in den hohen Norden, KH
Hallo Heinz, möchte mich bei Dir bei Dir für die ausfühlichen Zeilen bedanken. Habe versuch die Interrupts wie in Deinen Zeilen umzusetzen. bis auf die neue Taktfrequenz . Dieses hat den Grund weil ich den Uploader von meinem Franzis Lernpacket benutze möchte. Auf die Stellgenauigkeit kommt es in meinem Anwendungsfall nicht so sehr an. Möchte auf meinem Geburtstag Dia´s vorführen, doch mein Projektor hat keinen Timer. Diesen wollte ich gerne mit der Rudermaschine machen die in ca 20 sec auf die Fernbedienung drückt und somit das nächste Dia aufruft. Das erste Geburtstagsgeschenk wäre schon mal wenn die Rudermaschine nicht immer auf Anschlag fahren würde und zuckt. Du hattest geschrieben das ich keine Impulsbreite (n) angegeben hätte. Wie ist der Name von dem Register ,das ich mit der Impulsbreite laden muß ? Ist der normale PWM Modus geeignet ? Dürfte ich Dich nochmal bitten, meinen Code anzusehen. Vielleicht könntest Du mir noch einmal einen guten Tipp geben. vielen Dank vom Anfänger Joachim
Taktfrequenz... Ich hatte nicht von den Fuses gesprochen, sondern vom Clock-Vorteiler CLKPR (siehe Datenblatt Seite 25). Dieser lässt sich vom Programm, also per Software einstellen. Damit wird die Einstellung erst wirksam, wenn das Programm gestartet wird, Dein Bootloader (oder was immer Du mit Franzis-Uploader meinst) findet also den normalen Takt vor. Das ist also kein Problem. Stellgenauigkeit... Nunja, etwas Auflösung bzw. Wiederholgenauigkeit brauchst Du schon, auch wenn Du nur eine Taste der Fernbedienung betätigen willst. Denn sonst presst das Servo unter Umständen das Mohnöl aus der Fernbedienung... ;-) Alle 20 Sekunden... Das heißt also, Du brauchst noch eine Uhr, zumindest eine halbwegs genaue Zeitzählung. Der Tiny13 hat nur einen Timer, es geht aber trotzdem einzubauen. Mit CompareB lässt sich alle 1 oder 2 Millisekunden ein weiterer Interrupt erzeugen, in dem die Zeit hochgezählt werden kann. Es geht auch mit dem Overflow-Interrupt, aber das werden recht krumme Werte. Impulsbreite... Du möchtest das Servo zwischen zwei Positionen hin und her fahren. Demnach musst Du 2 Impulsbreiten als Konstanten definieren, für jede Position eine. Die Uhr schaltet dann nach jeweils 19 Sekunden auf Position 2 und nach 1 Sekunde wieder auf Position 1 zurück. Register-Name für Impulsbreitenwert... Das kommt darauf an, welchen Interrupt man verwendet. Ich sprach von CompareA des Timer0, also heißt das Register OCR0A (Datenblatt Seite 72). PWM-Modus... Der Timer läuft nicht im PWM-Modus, da die PWM-Modi des 8-Bit-Timers dazu ungeeignet sind. Der Timer läuft einfach nur frei durch, er wird nirgends angehalten und auch nirgends manipuliert. Also weder auf 0 gesetzt, noch auf irgend einen Startwert. Der Timer zählt einfach nur aufwärts und läuft bei 255 -> 256 über, also 256 ist schon wieder 0. Nun nochmal zum logischen Aufbau des Programms. Der Timer rennt durch und löst drei verschiedene Interrupts aus: - Overflow-Interrupt (beim Überlauf von 255 auf 0) alle 3,4 ms In diesem Interrupt wird die Impulspause herab gezählt (6...0). Ist die Impulspause abgelaufen (0), wird der Impulspin per Programm ( also durch die Anweisung *sbi portb,servopin* ) auf H-Pegel gesetzt und der Impulspausenzähler wieder auf 6 gesetzt. Weiterhin wird der gerade gültige (von der Zeitzählung bereitgestellte) Impulsbreitenwert in das Vergleichsregister OCR0A geschrieben, damit COM0A-Interrupt exakt zu dem Termin ausgelöst wird, wenn der Impuls abgeschaltet werden soll. - Compare-Interrupt A (Timer hat denselben Zählerstand erreicht, wie in OCR0A steht) In diesem Interrupt wird lediglich der Impuls-Ausgang wieder auf L-Pegel geschaltet ( *cbi portb,sercopin* ). - Compare-Interrupt B (Timer erreicht den Wert von OCR0B) Hier wird die Zeit gezählt. Damit der nächste COM0B-Int. in einem fest definierten Zeitabstand (Intervall) erfolgt, muss der Vergleichs- Wert bei jedem Interrupt aktualisiert werden. Dazu liest man OCR0B ein, addiert das Intervall (150 für 2 ms) dazu, und schreibt das Ergebnis nach OCR0B zurück. Nun weiß der Timer den nächsten Termin zum Auslösen eines COM0B-Interruptes. Jetzt muss aber noch die eigentliche Arbeit gemacht werden, das Zählen der Zeit. Dazu erhöht man einen Zähler (ein Register) in jedem Durchlauf um 1. Alle 256 Durchläufe hat das Register den Wert 0. 256 mal 2 ms ergibt 512 ms, also eine gute halbe Sekunde, wobei die 6 Runden zuviel nachher noch korregiert werden. Der Zählerstand 0 ist also der Indikator, dass eine halbe Sekunde vergangen ist. Die Auswertung wird das Hauptprogramm übernehmen, damit die Interrupt-Service-Routinen (ISRs) sehr kurz bleiben und sich nicht gegenseitig blockieren. - Es soll noch erwähnt werden, dass jede ISR noch das SREG sichern muss, damit sie dem Hauptprogramm nicht die Flags unterm Hintern verändert. Denn das hätte böse Folgen (logisch falsches Rechnen und springen). - Hauptprogramm (Hauptschleife) Die Mainloop muss nun die Zeit (in Schritten zu 0,5 s) zählen. Dazu wird ständig der Zeitvorteiler auf 0 geprüft (TST zvt). Ist er 0, wird zu einer Routine gesprungen, die folgendes tut: - Zeitvorteiler um 6 erhöhen, das korregiert den Fehler 256 / 250 und sorgt dafür, dass diese Routine nicht nochmal aufgerufen wird, denn zvt ist ja nun nicht mehr 0. - Zeitzähler herunterzählen und auf 2 Werte (Konstanten) prüfen: - bei Zählerstand 2 wird Position 2 in das Positionsregister geladen - bei Zählerstand 0 wird wieder Position 1 geladen und der Zähler auf den Startwert (40 für 20 Sekunden) gesetzt. - Reset-Routine: Hier wird der Controllertakt auf 4,8 MHz eingestellt (CLKPR), es werden alle I/Os initialisiert, es wird der Timer mit Vorteiler 64 gestartet, es werden die Interrupts für Ovf, ComA und ComB freigegeben und die Startwerte für alle Zähler (und OCR0x-Register) eingestellt. Deinen Quelltext habe ich mir aus Zeitgründen noch nicht angesehen, mal sehen, ob ich nachher noch Zeit dazu finde. KH
@Husky: Probiere mal das Programm im Anhang. Das Servo kommt an Pin 5 (PB0). ...
@Hannes, habe dein Programm auf den Chip aufgespielt und es hat leider nicht funktioniert. Das Servo ist in die Endlage gefahren und hat immer gezuckt. Ich möchte mich bei allen bedanken die viel Zeit aufgebracht haben um mir beim umsetzen dieses Problemes zu helfen. Mein Wissen ist leider zur Zeit noch nicht so weit, das ich alle Euren guten Tipps umsetzen kann. (ich arbeite daran) Ich werde das Problem aus Zeitgründen "mechanisch" lösen. Und möchte Eure Zeit nicht unnötig in anspruch nehmen. @KH, danke für den lehrreichen Text. Wenn ich wieder mehr Zeit habe , werde ich mit Hilfe Deiner Zeilen versuchen es doch noch umzusetzen. Danke!
Joachim H. wrote: > @Hannes, > > habe dein Programm auf den Chip aufgespielt und es hat leider nicht > funktioniert. Das Servo ist in die Endlage gefahren und hat immer > gezuckt. Also bei mir hat das Servo (0815-Billig-Servo) wunderbar funktioniert. Wenn es bei Dir nicht funktioniert, dann läuft Dein Tiny13 vermutlich nicht mit der Werkseinstellung (9,6 MHz, CKDIV8 aktiv). Überprüfe mal Deine Fusebits, vielleicht ist er ja auf 4,8 MHz Takt eingestellt. Noch besserer Vorschlag: Klemme mal das Servo ab, lege Spannung an den Tiny13 und miss mal die Frequenz an Pin 5 (PB0). Diese muss etwa 50 Hz betragen. Falls Du keine Frequenz messen kannst, könntest Du im Quelltext mal den Taktvorteiler mit anderen Werten füttern. Lass das Servo aber nicht zu oft und zu lange auf Anschlag fahren, es geht davon irgendwann kaputt. Als weitere Ursache kommt in Frage, dass Du vielleicht den Abblock-Kondensator (100 nF Keramik) am AVR vergessen hast und Servo und AVR aus der gleichen Betriebsspannung ohne Entkopplung betreibst. Dann löst jeder Störimpuls einen Reset im AVR aus. > > Ich möchte mich bei allen bedanken die viel Zeit aufgebracht haben um > mir beim umsetzen dieses Problemes zu helfen. > > Mein Wissen ist leider zur Zeit noch nicht so weit, das ich alle Euren > guten Tipps umsetzen kann. (ich arbeite daran) Jou, mach, wir haben alle mal angefangen. > > Ich werde das Problem aus Zeitgründen "mechanisch" lösen. Ich glaube, dass ist nicht nötig. Mit einem Tiny13 im (ATMEL-) Auslieferungszustand und einem Standard-Servo funktioniert das Programm bestens. > Und möchte Eure Zeit nicht unnötig in anspruch nehmen. > > @KH, > > danke für den lehrreichen Text. > Wenn ich wieder mehr Zeit habe , werde ich mit Hilfe Deiner Zeilen > versuchen es doch noch umzusetzen. Danke! Mein Programm ist eine Umsetzung dieser Gedanken. ...
Hallo Hannes, an welcher Schraube in Deinem Programm muß ich drehen damit es mit 1,2 MHz arbeitet. In dem Heft vom Lernpaket steht. Das Bootprogramm und das Interface Programm verwenden die serielle Schnittstelle mit einer definierten Übertragungsrate von 9600Baud. Dazu ist es erfordelich ,das der Controller mit einer definierten Taktfrequenz arbeitet. Der ATiny13 besitzt drei interne RC Oszillatoren mit 128 kHz, 4,8MHz und 9,6MHz. Außerdem kann der Takt geachtelt werden. Das Lernpaket arbeitet mit dem 9,6 MHz Oszillator und dem Teiler, sodass der Prozessortakt 1,2 MHz beträgt. Joachim
Joachim H. wrote: > Hallo Hannes, > > an welcher Schraube in Deinem Programm muß ich drehen damit es mit > 1,2 MHz arbeitet. Das Programm möchte den Tiny13 auf 9,6 MHz mit halbiertem Takt nutzen, also mit 4,8 MHz. > > In dem Heft vom Lernpaket steht. > > Das Bootprogramm und das Interface Programm verwenden die serielle > Schnittstelle mit einer definierten Übertragungsrate von 9600Baud. > Dazu ist es erfordelich ,das der Controller mit einer definierten > Taktfrequenz arbeitet. Der ATiny13 besitzt drei interne RC Oszillatoren > mit 128 kHz, 4,8MHz und 9,6MHz. > Außerdem kann der Takt geachtelt werden. Das Programm geht davon aus, dass der Tiny13 mit dem RC-Oszillator mit 9,6MHz arbeitet und interessiert sich nicht dafür, ob der Takt geachtelt wird. Es schaltet den Takt-Teiler CLKPR auf Halbieren (statt Achteln) und erreicht damit einen Takt von 4,8 MHz. Eingestellt wird das mit dem Wert: .equ clk_val=1<<clkps0 ;Wert Taktvorteiler 1 zu 2 (4,8 MHz) in der Reset-Routine: ldi wl,clk_ss ;Konstanten für Taktumschaltung ldi wh,clk_val ;vorladen out clkpr,wl ;Schreibschutz der Taktumschaltung aufheben out clkpr,wh ;Takt umschalten nop ;Zeit zum Einschwingen geben > > Das Lernpaket arbeitet mit dem 9,6 MHz Oszillator und dem Teiler, sodass > der Prozessortakt 1,2 MHz beträgt. Wenn dem so ist, dann muss das Programm auch funktionieren. Ich habe es auf dem Steckbrett mit einem werksneuen Tiny13 (ohne Änderung der Fusebits) und einem Conrad-Billig-Servo laufen. Ich würde an Deiner Stelle trotzdem mal die Fusebits auslesen und notieren und anhand des Datenblattes ermitteln, ob der Tiny13 noch original gefust ist. Ich weiß z.B., dass die zum Lernpaket von myAVR mitgelieferten Mega8 nicht dem ATMEL-Auslieferungszustand entsprechen. Daher halte ich es für möglich, dass auch der Franzis-Tiny13 verstellt sein kann. Der einfachste Test ist das Messen der Frequenz an Pin5 ohne angeschlossenem Servo. Diese muss etwa 50 Hz betragen. Aus dem tatsächlichen Wert kann man dann ermitteln, ob der AVR schneller oder langsamer läuft als er sollte. > > Joachim ...
Hallo Hannes, habe versucht Deinen Quellcode in das AVRStudie mit dem Modus für ATtiny13 zu compelieren. Das Programm hat zwei Fehlermedlungen angezeigt. Vielleicht kannst Du etwas damit anfangen. (Zeile 4) .equ servopin=pb0 ;Pin, an dem das Servo angeschlossen ist (Zeile 114) subi xl,-h_sek ;Intervall aufaddieren (n?ste Int-Termin) Building project... AVRASM: AVR macro assembler version 1.76.4 (Aug 6 2004 07:02:13) Copyright (C) 1995-2004 ATMEL Corporation Creating 'C:\zwischenablage\servo4.eep' Creating 'C:\zwischenablage\servo4.hex' Creating 'C:\zwischenablage\servo4.obj' Creating 'C:\zwischenablage\servo4.map' Assembling 'C:\zwischenablage\servo4.asm' Including 'C:\Programme\Atmel\AVR Tools\AvrAssembler\Appnotes\tn13def.inc' C:\zwischenablage\servo4.asm(4) : warning : Undefined variable referenced C:\zwischenablage\servo4.asm(4) : error : Undefined variable referenced C:\zwischenablage\servo4.asm(114) : warning: Immediate byte operand out of range Assembly complete with 1 error Deleting 'C:\zwischenablage\servo4.eep' Deleting 'C:\zwischenablage\servo4.obj' Deleting 'C:\zwischenablage\servo4.hex' Deleting 'C:\zwischenablage\servo4.map' vielen Danke im Voraus joachim
Wenn Du mit relativ neuen AVRs arbeiten willst, solltest Du Dein AVR-Studio schon mal auf AVR-Assembler 2 umschalten. Ich hoffe, Du hast eine halbwegs aktuelle Version des AVR-Studios und wurschtelst nicht mehr mit einer 3.5x er Version herum. ...
Also ich bekomme beim Assemblieren diese Meldung:
1 | AVRASM: AVR macro assembler 2.1.9 (build 90 Jul 5 2006 11:06:16) |
2 | Copyright (C) 1995-2006 ATMEL Corporation |
3 | |
4 | E:\AVR\FORUM\t13servo\t13serv1.asm(15): Including file 'C:\Programme\Atmel\AVR Tools\AvrAssembler2\Appnotes\tn13def.inc' |
5 | E:\AVR\FORUM\t13servo\t13serv1.asm(135): No EEPROM data, deleting E:\AVR\FORUM\t13servo\t13servo1.eep |
6 | |
7 | ATtiny13 memory use summary [bytes]: |
8 | Segment Begin End Code Data Used Size Use% |
9 | --------------------------------------------------------------- |
10 | [.cseg] 0x000000 0x00007e 126 0 126 1024 12.3% |
11 | [.dseg] 0x000060 0x000060 0 0 0 64 0.0% |
12 | [.eseg] 0x000000 0x000000 0 0 0 64 0.0% |
13 | |
14 | Assembly complete, 0 errors. 0 warnings |
Zum Vergleich, Du nutzt Assembler Version 1:
1 | AVRASM: AVR macro assembler version 1.76.4 (Aug 6 2004 07:02:13) |
und ich Version 2:
1 | AVRASM: AVR macro assembler 2.1.9 (build 90 Jul 5 2006 11:06:16) |
Die Version (1 oder 2) kann man per Menü auswählen: Menü/Project/Assembler-versions (siehe Anhang) Ich nutze AVR-Studio Version 4.12 mit Service-Pack 4 Build 498. Eine Nachfolger-Version lief bei einem Bekannten nicht, ich hatte sie aber nicht probiert, da ich auch nicht ohne zwingenden Grund hinter jeder neuen Version hinterher bin wie der Teufel hinter der Seele. Ich denke, es genügt, wenn Du per Menü die Assembler-Version 2 auswählst. ...
Hallo Hannes, entschuldige das ich erst jetzt schreibe. War im Urlaub . Vielen Dank, jetzt geht es ! schöne Grüße Joachim
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.