Forum: Mikrocontroller und Digitale Elektronik Servoansteuerung, finde den Fehler nicht.


von Felix (Gast)


Lesenswert?

Hallo Leute,
versuche gerade mit einem atmega88 einen Servo anzusteuern. Der Servo 
soll nacheinander verschiedene Positionen anfahren. Es soll eine von mir 
festgelegte Wartezeit ("i") zwischen den Positionen geben.

Was funktioniert:
 - PWM mittels Timer. Periodendauer stimmt (Oszi), Positionsänderungen 
durch manuelles setzen der "posi"-Variable macht der Servo.
 - die debounce Funktion funktioniert auch, die Variable "schalter" gibt 
an, ob Kippschalter an oder aus ist. Geprüft mit LED.
 - Es gibt keine Fehler beim kompilieren, nix raucht^^

Wo es hängt:
Wenn ich den µC mit Schalterstellung "aus" programmiere, fährt der Servo 
in die Stellung 1500. Schalte ich den Schalter ein, fährt der Servo in 
die erste Position vom Ablaufprogramm und bleibt dort für immer.
Warum will er nicht weiter?

Ist mein erstes µC-Projekt, wenn euch also irgendwelche "don'ts" 
auffallen, bitte sagen.

Vielen Dank, mfG

1
#define F_CPU 8000000UL
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <util/delay.h>
6
7
static int pressed_confidlvl=0;
8
static int released_confidlvl=0;
9
static volatile unsigned int i=0;
10
static volatile int posi=1500; 
11
static volatile unsigned int schrittnr=4;
12
13
int debounce(int a);
14
void ablauf(int n);
15
16
int main(void)
17
{
18
  //Timer1 (16bit) für PWM einstellen
19
  DDRC |= (1 << PC0);                      //Servopin als Ausgang
20
  TCCR1A |= (1 << WGM11);                    //siehe eine Zeile weiter unten
21
  TCCR1B |= (1 << CS11) | (1 << WGM12) | (1 << WGM13);    //prescaler auf clk/8 & fastpwm mode mit ICR1 als TOP
22
  TIMSK1 |= (1 << TOIE1);                    //Overflow Interrupt einschalten
23
  ICR1 = 19999;                        //Neues TOP-ende des Zählers festgelegt. Insgesamt 20 000 entspricht bei F_CPU 8MHz, prescaler clk/8, einer dauer von 20ms oder 50Hz
24
  sei();
25
26
  DDRC &= ~(1 << PC2);   //Pin für Schalter auf Eingang setzen & Pullup aktivieren
27
  PORTC |= (1 << PC2);
28
  DDRC |= (1 << PC3);                      //SchalterkontrollLED-pin auf Ausgang setzen
29
30
  int schalter=0;                        //Gibt an ob Schalter an=1 oder aus=0. Wird durch debounce-Funktion gesetzt.
31
  
32
  while(1)
33
  {
34
    schalter=debounce(schalter);
35
    
36
    if (schalter == 1)
37
    {
38
      PORTC |= (1 << PC3);      //wenn schalter 1 dann LED an
39
      ablauf(1);
40
    }
41
    else
42
    {
43
      PORTC &= ~(1 << PC3);      // wenn schalter 0 dann LED aus
44
      i=0; 
45
    }
46
    
47
//PWM für Servo  
48
    if (TCNT1 >= 500 && TCNT1 <= 3000)  //Zeitabschnitt Pegel=1 von PWM   //außerdem einschränkung der abfragezeit durch max und minimale servoposition
49
    {
50
      if (TCNT1 >= posi && bit_is_set(PORTC, PINC0))
51
      {
52
        PORTC &= ~(1 << PC0);    //Pegel zurück auf 0 setzen
53
      }
54
    }
55
    if (TCNT1 < 500 || TCNT1 > 3000)  //Zeitabschnitt Pegel=0 von PWM
56
    {
57
    }
58
  }  
59
}
60
61
ISR(TIMER1_OVF_vect)            //wird alle 20ms aufgerufen, da 
62
{
63
  PORTC |= (1 << PC0);
64
  
65
  if (i > 0)
66
  {
67
    i--;            //alle 20ms i um eins dekrementieren bis 0 erreicht
68
    
69
    if ((i == 0) && (schrittnr > 0))
70
    {
71
      schrittnr--;      //am Ende der durch i definierten Wartezeit: schrittnr erniedrigen
72
    }
73
  }
74
}
75
76
77
int debounce(int a)
78
{
79
  int pressed=a;
80
81
  if (bit_is_clear(PINC,PC2))
82
  {
83
    pressed_confidlvl++;
84
    if (pressed_confidlvl >= 10000 && pressed == 0)          //Grenze für confidencelevel noch nicht sinnvoll überlegt.
85
    {
86
      pressed_confidlvl = 0;
87
                pressed = 1;
88
    }
89
  }
90
  if (bit_is_set(PINC, PC2))
91
  {
92
    released_confidlvl++;
93
    if (released_confidlvl >= 10000 && pressed == 1)
94
    {
95
      released_confidlvl = 0;
96
                 pressed = 0;
97
    }
98
  }
99
  return pressed;
100
}
101
102
void ablauf(int n)                            //n gibt die Nummer des Programms an, welches in der if abfrage danach definiert wird
103
{
104
  if (n == 1)
105
  {
106
    if (schrittnr == 4)
107
    {
108
      posi = 800;
109
      i = 100;                          // i = 100 entspricht 2 sek Wartezeit
110
    }
111
    if (schrittnr == 3)
112
    {
113
      posi = 1400;
114
      i = 100;
115
    }
116
    if (schrittnr == 2)
117
    {
118
      posi = 2000;
119
      i = 100;
120
    }
121
    if (schrittnr == 1)
122
    {
123
      posi = 1000;
124
      i = 100;
125
    }
126
    if (schrittnr == 0)
127
    {
128
      posi = 800;
129
      i = 100;
130
    }
131
  }
132
}

von Felix (Gast)


Lesenswert?

OK Fehler ist gefunden. i wird bei jedem durchlauf durch "ablauf" wieder 
auf 100 gesetzt.

von EGS_TI (Gast)


Lesenswert?

Ein schönes Bespiel für einen Seiteneffekt.

von Rechtschreibpolizei (Gast)


Lesenswert?

Felix schrieb:
> manuelles setzen

Fehler gefunden:

"Setzen" wird hier groß geschrieben!

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
Noch kein Account? Hier anmelden.