Hallo,
ich habe eine Servosteuerung programmiert die nicht so recht laufen
will.
Um daher erstmal zu testen ob Servo etc. funktionieren, habe ich
folgendes absolut simpele Programm geschrieben, welches NUR den Servo
ungefähr in Mittelstellung setzen soll. Es ist so kurz dass ich es
direkt hier posten kann:
==========
DDRB |= (1 << PB1_SERVOOUT); // definiere PB1 als output
// Aktiviere timer0 mit prescaler 64 (CS02,CS01,CS00) = (0,1,1)
// Der Prozessortakt ist 8 MHz, entspricht 8000 Takten in 1ms.
// Bei Prescaler 64 entspricht ein Zählerstand 125 genau 1ms
TCCR0B |= (1 << CS01) | (1 << CS00);
while(1){
PORTB |= (1 << PB1_SERVOOUT); // setze Bit PB1
TCNT0 = 0x00;
while(TCNT0<(1504/8)); // warte ca. 1,5ms
PORTB &= ~(1 << PB1_SERVOOUT); // lösche Bit PB1
// warte 10ms (ist ja nur ein Experiment!)
TCNT0 = 0x00;
while(TCNT0<(2000/8)); // wait 2ms
TCNT0 = 0x00;
while(TCNT0<(2000/8)); // wait 2ms
TCNT0 = 0x00;
while(TCNT0<(2000/8)); // wait 2ms
TCNT0 = 0x00;
while(TCNT0<(2000/8)); // wait 2ms
TCNT0 = 0x00;
while(TCNT0<(2000/8)); // wait 2ms
}
==========
Ich weiss dass das Programm alles andere als elegant ist. Aber das Ziel
war einfach das ganze simpel und schnell zu machen.
Es klappt trotzdem nicht. Der Servo wandert in schnellen kleinen
Schritten zum vollen Ausschlag, und "tickt" dort dann stetig gegen den
Anschlag.
Ich habe alles x-mal gecheckt, das timing nachgerechnet (Taktfrequenz
ist 8 MHz), die Schaltung überprüft, ...
Leider habe ich kein Oszilloskop um das Signal zu checken.
Habe ich in obigem Code einen doofen Fehler den ich nach 3 Stunden nun
nicht mehr sehe? Hat jemand eine Idee woran es sonst liegen könnte?
Bin schier am verzweifeln, ich muss Tomaten auf den Augen haben...
Danke,
groki
Ergänzung:
Ziel-uC ist (noch) ein ATMEGA88,
das Signal was ich erzeugen will ist:
- 1,5ms Puls
- 10ms Pause
- 1,5ms Puls
- 10ms Pause
- ...
und so weiter. Später soll es mal mit der PWM-Funktion des Timers
laufen. So hatte ich es auch zuerst, aber da es nicht lief wollte ich
diese Fehlerquelle zunächst "ausschalten"...!
Hallo Lasse,
wie kann der Compiler das einfach wegoptimieren? Gibt es eine andere
Möglichkeit eine Pause zu implementieren?
Ist mein erstes Posting hier gewesen, hab die Code-tags nicht gesehen
(ich sag's ja, Tomaten auf den Augen...). Werde ich nächstes Mal
natürlich benutzen!
Danke,
groki
Danke, ich sehe es im Tutorial!
Im Debugger lief's wie gewünscht, da wird's ja auch vorher compiliert.
Und es wurde nicht wegoptimiert... Kann es sein dass es einen
Unterschied macht ob ich debugge oder auf dem AVR laufen lasse?
Ich probier's mal mit der _dela_ms() Funktion.
Hm, ich hab jetzt mal eine LED statt Servo angeschlossen, und folgenden
einfachen Code:
1
#define F_CPU 8000000UL // 8 MHz
2
3
...
4
5
while(1){
6
PORTB |= (1 << PB1_SERVOOUT);
7
_delay_ms(1000);
8
PORTB &= ~(1 << PB1_SERVOOUT);
9
_delay_ms(1000);
10
11
}
Das sollte ja die LED im 1s-Takt blinken lassen. Stattdessen scheint
_delay_ms(1000) jedoch 5-6 Sekunden zu dauern.
Stimmt etwas an der Taktfrequenz nicht? Ich habe die Fuse-Settings
angesehen, dort ist konfiguriert:
SUT_CKSEL: Int. RC Osc 8MHz, Start-up Ttime PWRDWN/RESET: 6CK/14CK + 65
Ich muss gestehen ich verstehe noch nicht ganz was das bedeutet? Mir
siehts nach 8MHz Taktfrequenz aus?
Danke,
groki
...ich rate kurz ins blaue:
der controller läuft noch auf 1Mhz mit dem internen taktoszillator
wenn das so ist, würde der controller auch ohne externen quarz laufen
(test!)
du müßtest in dem fall die entsprechenden fuse-bits setzen, um den
externen oszi einzuschalten (vorsicht, nichts falsches einstellen, sonst
läuft der controller nicht mehr an!)
Bevor ich als AVR-Amateur anfange die Fuse-Bits zu verpfuschen: Das
AVR-Studio sagt ja
SUT_CKSEL: Int. RC Osc 8MHz, Start-up Ttime PWRDWN/RESET: 6CK/14CK + 65
heisst das nicht das er mit 8MHz läuft? Wenn ich recht ans Datenblatt
erinnere werden die ATMEGA88 auch mit 8MHz ausgeliefert, oder? Die sind
brandneu.
Der AVR steckt im STK500 Board, ohne Quartz...
Ich werd's mal mit 1MHz versuchen, danke!
Ich glaube Du hast recht, mit 1MHz scheint es zu klappen.
Oh mann! Ich habe irgendwo gelesen 8MHz sei Standard bei
Auslieferung...muss das mal checken.
Werd nun mal nachlesen wie man 8MHz einstellt, falls jemand ne gute
Referenz hat wär ich dankbar!
(Bin ich auch jetzt schon, DANKE fürs helfen!!)
Lasse S. schrieb:> Er kann das einfach wegoptimieren, weil du nichts tust. Der Compiler> erkennt, dass die Schleife für den Programmablauf sinnlos ist.
Nein darf er nicht, alle AVR Register sind als volatile definiert. Da
eine Leseoperation auf TCNT0 gemacht wird, darf hier nicht wegoptimiert
werden.