Mede tweakers,
Ik probeer eigenlijk iets heel simpels te doen, en dat is een servo 1 kant op laten draaien. Helaas wil hij niet echt meewerken. Als ik mijn servo aansluit op het onderstaande schema, dan draait die een heel klein stukje, maar daarna hoor je hem ergens binnenin zachtjes tikken, en draait die niet. Het klinkt echt alsof die het er ergens heel erg moeilijk mee heeft.
Het schema:

Zoals je ziet gebruik ik een atTiny44 om het geheel aan te sturen, en daar draait de volgende code op:
Het is echt heel weinig code, en volgens mij moet het kloppen, want bovenstaande code stelt alleen de hardware PWM van de AVR in op 'Frequency and Phase Correct mode'.
COM1A1 in TCCR1A wordt op 1 gezet, wat ervoor zorgt dat de OCA1 pin op 0V wordt gezet als er een 'Compare match' gebeurt tijdens het optellen, en wordt op 5V gezet als er een 'Compare match' gebeurt tijdens het aftellen.
In TCCR1B wordt WGM13 en CS10 gezet. Het eerste zorgt ervoor dat Frequency and Phase correct PWM wordt aangezet, met ICR1 als TOP waarde. ICR1 bepaalt nu dus eigenlijk de PWM frequentie. CS10 zorgt ervoor dat we de hardware clock zonder prescaler gebruiken om te tellen.
OCR1A wordt gebruikt voor de pulsbreedte. Hoe kom ik bij die getallen? Standaard gebruikt een AVR de interne 8MHz oscillator met een clockdivider van 8, dus resulterende clock is 1Mhz. Dat betekent 1000000 counts per seconde.
Op internet staat overal dat je 50 Hz als PWM frequentie moet gebruiken voor je servo, dus dat is een periode tijd van 1/50 = 0.02 s. Dat betekent dus na 20000 'counts' is er 20ms verstreken. In frequency and phase correct PWM telt de hardware van 0 tot TOP en dan weer terug tot 0, dus we delen dat getal door 2. ICR1 wordt dus 10000.
OCR1A bepaalt de pulsbreedte, en die pulsbreedte moet 2ms zijn om een bepaalde kant op te draaien. Dat betekent 2*10^(-3) * 1000000 = 2000 'counts'. Zoals eerder gezegd wordt tijdens het optellen de pin gereset als er een match optreed, en tijdens het aftellen wordt die weer gezet als er een match optreed. Dus ook hier moet je de waarde door 2 delen om de juiste pulsbreedte te krijgen (zie plaatje).

Als ik met mijn multimeter de spanning op de control pin meet, komt er ook mooi 0.5V uit. Dat is logisch want: 2 ms (pulsbreedte) / 20 ms (periodetijd) = 0.1. 0.1 * 5 (spanning uit de AVR) = 0.5V.
Wat gaat er dan fout? Is mijn schema niet goed? Is de servo kapot (wat ik raar zou vinden wat ik heb hem niet nieuw binnen)? Alvast bedankt.
Ik probeer eigenlijk iets heel simpels te doen, en dat is een servo 1 kant op laten draaien. Helaas wil hij niet echt meewerken. Als ik mijn servo aansluit op het onderstaande schema, dan draait die een heel klein stukje, maar daarna hoor je hem ergens binnenin zachtjes tikken, en draait die niet. Het klinkt echt alsof die het er ergens heel erg moeilijk mee heeft.
Het schema:

Zoals je ziet gebruik ik een atTiny44 om het geheel aan te sturen, en daar draait de volgende code op:
C:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ /* * main.c - Auto-generated by Anjuta's Makefile project wizard * */ #ifndef F_CPU #define F_CPU 1000000L #endif #include <avr/io.h> #include <avr/interrupt.h> #include <stdint.h> #define SERVO_PWM_TOP 10000UL // 50 Hz PWM #define SERVO_PWM_VALUE_STOP 750UL // Capture value to stop the servo (pulse width 1.5ms) #define SERVO_PWM_VALUE_TURN 1000UL // Capture value to turn the servo (pulse width 2ms) int main(void) { // Setup ports and timers DDRA = 0xFF; // All output // Configure timer/counter1 as phase and frequency PWM mode TCNT1 = 0; TCCR1A = (1 << COM1A1); TCCR1B = (1 << WGM13) | (1 << CS10); ICR1 = SERVO_PWM_TOP; OCR1A = SERVO_PWM_VALUE_TURN; sei(); while(1) { } } |
Het is echt heel weinig code, en volgens mij moet het kloppen, want bovenstaande code stelt alleen de hardware PWM van de AVR in op 'Frequency and Phase Correct mode'.
COM1A1 in TCCR1A wordt op 1 gezet, wat ervoor zorgt dat de OCA1 pin op 0V wordt gezet als er een 'Compare match' gebeurt tijdens het optellen, en wordt op 5V gezet als er een 'Compare match' gebeurt tijdens het aftellen.
In TCCR1B wordt WGM13 en CS10 gezet. Het eerste zorgt ervoor dat Frequency and Phase correct PWM wordt aangezet, met ICR1 als TOP waarde. ICR1 bepaalt nu dus eigenlijk de PWM frequentie. CS10 zorgt ervoor dat we de hardware clock zonder prescaler gebruiken om te tellen.
OCR1A wordt gebruikt voor de pulsbreedte. Hoe kom ik bij die getallen? Standaard gebruikt een AVR de interne 8MHz oscillator met een clockdivider van 8, dus resulterende clock is 1Mhz. Dat betekent 1000000 counts per seconde.
Op internet staat overal dat je 50 Hz als PWM frequentie moet gebruiken voor je servo, dus dat is een periode tijd van 1/50 = 0.02 s. Dat betekent dus na 20000 'counts' is er 20ms verstreken. In frequency and phase correct PWM telt de hardware van 0 tot TOP en dan weer terug tot 0, dus we delen dat getal door 2. ICR1 wordt dus 10000.
OCR1A bepaalt de pulsbreedte, en die pulsbreedte moet 2ms zijn om een bepaalde kant op te draaien. Dat betekent 2*10^(-3) * 1000000 = 2000 'counts'. Zoals eerder gezegd wordt tijdens het optellen de pin gereset als er een match optreed, en tijdens het aftellen wordt die weer gezet als er een match optreed. Dus ook hier moet je de waarde door 2 delen om de juiste pulsbreedte te krijgen (zie plaatje).

Als ik met mijn multimeter de spanning op de control pin meet, komt er ook mooi 0.5V uit. Dat is logisch want: 2 ms (pulsbreedte) / 20 ms (periodetijd) = 0.1. 0.1 * 5 (spanning uit de AVR) = 0.5V.
Wat gaat er dan fout? Is mijn schema niet goed? Is de servo kapot (wat ik raar zou vinden wat ik heb hem niet nieuw binnen)? Alvast bedankt.