Atmega88 Servo mit Poti steuern

Gast #3588837
Lesenswert?

Hallo zusammen,

ich hab mal wieder ne Frage.
Ich möchte einen Servomotor über ein Poti an meinem Atmega88 steuern.
Momentan habe ich ein Programm geschrieben, das über den Ausgang OC1A 
den Servomotor vom Linksanschlag zum Rechtsanschlag und zurück fahren 
lässt. Der Servo wird mit einem 50Hz Signal angesteuert. Jetzt wollte 
ich den Ausgang OC1A so lassen und den OC1B so programmieren, dass er 
ich den Motor über ein Poti steuern kann.
Nur leider bewegt sich der Servo nicht, wenn ich ihn an den OC1B Ausgang 
anschließe. Ich weis aber nicht warum.
Mein Atmega88 läuft mit 8MHz und der Timer1 wird mit 8fach Prescaler 
betrieben.
Der Wert ADC_C0 ist eine 16Bit Variable in der der Wert vom ADC 
gespeichert wird. Der ADC teil funktioniert, und der Wert wird mir auch 
auf einem LCD ausgegeben.

Hier mein Code:
1
int main(){
2

3
DDRB |= 1<<PINB1 | 1<<PINB2;
4

5
  TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0 | 1<<COM1B0 | 1<<COM1B1;
6
  TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS11;
7
  ICR1 = 19999;
8

9

10
while(1){
11
  OCR1A = ICR1 - 1000;
12
  OCR1B = ICR1 - (850 + (ADC_C0 * 1,26));
13
  _delay_ms(500);
14
  OCR1A = ICR1 -2000;
15
  OCR1B = ICR1 - (850 + (ADC_C0 * 1,26));
16
  _delay_ms(500);
17
}
18

19
}
Gast #3588887
Lesenswert?

1
uint16_t ADC_C0;
2

3

4

5

6
ADMUX &= ~(1<<MUX0);
7
  ADCSRA |= (1<<ADSC);
8
  while (ADCSRA & (1<<ADSC)){}
9
    ADCL_C0 = ADCL;
10
    ADCH_C0 = ADCH;
11
  
12
  ADMUX |= (1<<MUX0);
13
  ADCSRA |= (1<<ADSC);
14
  while (ADCSRA & (1<<ADSC)){}
15
    ADCL_C1 = ADCL;
16
    ADCH_C1 = ADCH;
17
  
18
  ADC_C0 = ADCL_C0 + (ADCH_C0 * 256);
19
  ADC_C1 = ADCL_C1 + (ADCH_C1 * 256);
Gast #3588912
Lesenswert?

Hier mal der ganze Code:
1
#define F_CPU 8000000
2

3

4
#include <avr/io.h>
5
#include <util/delay.h>
6
#include <lcd-routines.h>
7
#include <lcd-routines.c>
8
#include <stdint.h>
9

10

11

12

13
uint16_t ADC_C0;
14
uint16_t ADC_C1;
15
uint8_t ADCL_C0;
16
uint8_t ADCH_C0;
17
uint8_t ADCL_C1;
18
uint8_t ADCH_C1;
19
char ADC_StringC0 [16];
20
char ADC_StringC1 [16];
21

22

23

24
void ADC_Init (void)
25
{
26
  
27
  ADMUX |= (1<<REFS0);
28
  ADCSRA |= (1<<ADPS2) | (1<<ADPS1) | (1<<ADEN) | (1<<ADSC);
29
  
30
  while (ADCSRA & (1<<ADSC));
31
  ADCL_C0 = ADCL;
32
  ADCH_C0 = ADCH;
33
  
34
}
35

36

37
void ADC_Read (void)
38
{
39
  
40
  ADMUX &= ~(1<<MUX0);
41
  ADCSRA |= (1<<ADSC);
42
  while (ADCSRA & (1<<ADSC)){}
43
    ADCL_C0 = ADCL;
44
    ADCH_C0 = ADCH;
45
  
46
  ADMUX |= (1<<MUX0);
47
  ADCSRA |= (1<<ADSC);
48
  while (ADCSRA & (1<<ADSC)){}
49
    ADCL_C1 = ADCL;
50
    ADCH_C1 = ADCH;
51
  
52
  ADC_C0 = ADCL_C0 + (ADCH_C0 * 256);
53
  ADC_C1 = ADCL_C1 + (ADCH_C1 * 256);
54
  
55
}
56

57

58

59
void LCD_Write (void)
60
{
61
  lcd_clear();
62
  
63
  itoa (ADC_C0, ADC_StringC0, 10);
64
  itoa (ADC_C1, ADC_StringC1, 10);
65
  
66
  lcd_setcursor(0,1);
67
  lcd_string("ADC0      ADC1");
68
  lcd_setcursor(0,2);
69
  lcd_string(ADC_StringC0);
70
  lcd_setcursor(9,2);
71
  lcd_string(ADC_StringC1);
72
  
73
  
74
  
75
  
76
}
77

78

79
void AVR_init (void)
80
{
81
  DDRC |= 1<<PINC4 | 1<<PINC5;
82
  PORTC |= 1<<PINC2 | 1<<PINC3;
83
  DDRB |= 1<<PINB1 | 1<<PINB2;
84
  
85
}
86

87

88
void PWM_init (void)
89
{
90

91
  TCCR1A |= 1<<WGM11 | 1<<COM1A1 | 1<<COM1A0 | 1<<COM1B0 | 1<<COM1B1;
92
  TCCR1B |= 1<<WGM12 | 1<<WGM13 | 1<<CS11;
93
  ICR1 = 19999;
94
  
95
  
96
}
97

98

99
void PWM_Funktion (void)
100
{
101
  OCR1A = ICR1 - 1000;
102
  OCR1B = ICR1 - (850 + (ADC_C0 * 1.26));
103
  _delay_ms(500);
104
  OCR1A = ICR1 -2000;
105
  OCR1B = ICR1 - (850 + (ADC_C0 * 1.26));
106
  _delay_ms(500);
107
  
108
  
109
}
110

111

112
int main(void)
113
{  
114
  AVR_init();
115
  ADC_Init();
116
  lcd_init();
117
  PWM_init();
118
   
119
  
120
  
121
  
122
    while(1)
123
    {
124
        ADC_Read();
125
    LCD_Write();
126
    PWM_Funktion();
127
    
128
      
129
    
130
    
131
    }
132
}
Gast #3588921
Lesenswert?

Christian schrieb:
> Ich habe mal ausprobiert mit einen normalen C++ compiler eine
> Berechnung
> mit einer int Variable zu machen. Es hat funktioniert. Allerdings nur
> wenn der Multiplikator so geschrieben wird 1.26 und nicht 1,26. Also
> müsste es so auch funktionieren.
> OCR1B = ICR1 - (850 + (ADC_C0 * 1.26));

Beim AVR GCC ist der Default für die Berechnung ein Integer, damit wird 
sich das so verhalten, wie von mir oben beschrieben.

Im AVR-Studio kannst Du Deinen Code auch simulieren und die Variablen 
untersuchen, stell dafür auf keine Optimierung, -O0.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren