Forum: Mikrocontroller und Digitale Elektronik Klappensteuerung mit Modellbauservo


von Willi L (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,
Ich mache gerade für diverse Raumabsaugungen die Klappensteuerung mit 
Modellbauservo. Die Servoansteuerung erfolgt mit einem Attiny 45. Der 
Ausgang PB0 ist der Hardwareausgang vom PWM. Mit PB1 wird die 
Spannungsversorgung für den Servo geschalten (natürlich über 
Transistor). Zur Zeit als Simulation mit einer LED. An PB4 ist der 
Starteingang.
Programmablauf: PB4 wird auf L gelegt,die Impulslänge wird umgeschalten 
und danach ist PB1 für ca. 1sec. H (Impuls damit der Servo in die neue 
Position fährt). Für die Grundstellung wird PB1 wiederum Angesteuert, 
wenn Eingang PB4 wieder H ist. PWM funktioniert (Frequenz 20ms; 
Impulsdauer 1ms bzw. 2ms.)Das Problem ist, dass die PWM sporadisch im 
Interval von 1-5sec) selbst invertiert (s.Anhang)
Die Schaltung wird, wie schon gesagt als Simulation, mit LED und 
Batterie betrieben.
Ich bin noch neu mit MC und bitte daher um Hilfe

DANKE im Voraus

Willi
1
/*
2
 * Test_Timer_ATtiny45.c
3
 *
4
 */ 
5
#define F_CPU 8000000UL
6
#include <avr/io.h>
7
#include <avr/interrupt.h>
8
#include <util/delay.h>
9
10
#define Klappe_oeffnen      (!(PINB&(1<<PB4))) //Start von Steuerung
11
unsigned int servo_GS = 142;                   // Klappe zu
12
unsigned int servo_AS = 147;                   // Klappe auf
13
unsigned int power=0;                          // Spannung Servo ein
14
unsigned int power1=0;
15
16
ISR (TIMER0_COMPA_vect)
17
{    
18
    OCR0A=155-OCR0A;                      // Impulsbreite 20mS (50Hz)
19
}
20
 
21
int main(void)
22
{
23
  DDRB |= (1 << PB0)|(1<<PB1)|(1<<PB2);   // PB0, PB1 und PB2 als Ausgänge
24
                            
25
    
26
    
27
  TCCR0A = (1<<WGM01)|(1<<COM0A0);       // CTC Modus, Togle compare match
28
  TCCR0B =(1<<CS02)|(1<<CS00);           // Prescaler 1024                 
29
  TIMSK = (1 << OCIE0A);                 //Interrupt freigeben
30
 
31
  sei();                                                                  
32
33
  while(1) 
34
  {
35
    
36
   if (Klappe_oeffnen)            // warte auf startsignal
37
    {
38
     OCR0A=servo_AS;              // Klappe auf                      
39
     _delay_ms(300);
40
                  
41
     for (power; power <=2; power++ // Servo ca. 1sec. ein
42
    {
43
            PORTB |=(1<<PB1);           // Ausgang Spannung Servo EIN
44
     _delay_ms(300);
45
    }      
46
        
47
      
48
           PORTB &=~(1<<PB1);            // Ausgang Spannung Servo AUS
49
           power1=0;     
50
    }
51
    
52
     if (!(Klappe_oeffnen))
53
    {
54
      OCR0A=servo_GS;                  // Klappe zu
55
      _delay_ms(300);
56
      
57
           for (power1; power1 <=2; power1++)// Spannung Servo ca.1sec. ein
58
    {
59
                 PORTB |=(1<<PB1);           // Ausgang Spannung Servo EIN
60
    _delay_ms(300);
61
    }  
62
      
63
            PORTB &=~(1<<PB1);         // Ausgang Spannung Servo AUS
64
      power=0;
65
    }  
66
  }                                             
67
}

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Das ganze Verfahren ist keine gute Idee.

Wenn du alles auf dem CTC Modus mit Pin Toggeln aufbaust, musst du 
höllisch aufpassen, dass du die Zuweisungen an das OCR0A Register beim 
richtigen Timer Durchlauf machst.

Ich bin zwar dafür, gewisse Dinge mit dem Timer zu erledigen. Wenn es 
aber nur darum geht, ein Servo in eine bestimmte Position zu fahren, 
dann brauchst du es nicht mit so einem Verfahren machen. Denn genauer 
als mit 2 fixen _delay_us, die du (samt Pulspin-Umschaltung) in einer 
Schleife 150 mal wiederholst, wird das auch nicht. Das eine hängt von 
der Taktfrequenz genauso ab, wie das andere.

D.h. so
1
int main(void)
2
{
3
  DDRB |= (1 << PB0)|(1<<PB1)|(1<<PB2);   // PB0, PB1 und PB2 als Ausgänge
4
5
  isOffen = 0;
6
                            
7
  while(1) 
8
  {
9
    if (Klappe_oeffnen && !isOffen)            // warte auf startsignal
10
    {
11
      PORTB |=(1<<PB1);           // Ausgang Spannung Servo EIN
12
      for( i = 0; i < 150; ++i )
13
      {
14
        PORTB |= (1<<PB0);
15
        _delay_us( 1000 );
16
        PORTB &= ~(1<<PB0);
17
        _delay_ms(19);
18
      }
19
      PORTB &=~(1<<PB1);            // Ausgang Spannung Servo AUS
20
      isOffen = 1;
21
    }
22
23
    if (!Klappe_oeffnen && isOffen)
24
    {
25
      PORTB |=(1<<PB1);           // Ausgang Spannung Servo EIN
26
      for( i = 0; i < 150; ++i )
27
      {
28
        PORTB |= (1<<PB0);
29
        _delay_us( 2000 );
30
        PORTB &= ~(1<<PB0);
31
        _delay_ms(18);
32
      }
33
      PORTB &=~(1<<PB1);            // Ausgang Spannung Servo AUS
34
      isOffen = 0;
35
    }
36
  }
37
}

Wenn man nicht damit leben kann, dass die Steuerung nicht auf ein 
Schaltsignal reagiert, sondern dass das das Servo erst seine Endstellung 
erreichen muss, dann baut man das eben ein bischen um, so dass die 
for-Schleifen in Form eines Zählers in der Hauptschleife aufgehen. Ist 
nicht wirklich wahnsinnig schwierig, diese Transformation zu machen. Ist 
der Zähler ungleich 0, dann schaltet man die SPannungs Versorgung ein 
und entscheidet anhand des Steuereingangs, in welche Richtung verfahren 
werden soll, generiert 1 entsprechenden Puls und zählt den Zähler um 1 
runter. Ist der Zähler 0, so wird dem Servo der Saft abgedreht. Bleibt 
nur noch den Steuereingang zu überwachen und wenn sich da eine 
Veränderung ergibt, dann setzt man den Zähler auf 150.

: Bearbeitet durch User
von Thomas (Gast)


Lesenswert?

Nimm Bascom, da ist eine Servoansteuerung drin. Die kostenlose Version 
geht bis 4kB, reicht sogar für deinen Controller ;)

von Willi L (Gast)


Lesenswert?

Danke Karl Heinz, werde gleich ausprobieren.
Ich bin jetzt als Anfänger nur etwas verwirrt, weil alle Vorschläge im 
Forum eigentlich mit Timer aufgebaut sind und immer die Rede ist, dass 
man mit  "Delay"  eher geizig umgehen soll ;-).
LG
Willi

von Karl H. (kbuchegg)


Lesenswert?

Willi L schrieb:
> Danke Karl Heinz, werde gleich ausprobieren.
> Ich bin jetzt als Anfänger nur etwas verwirrt, weil alle Vorschläge im
> Forum eigentlich mit Timer aufgebaut sind und immer die Rede ist, dass
> man mit  "Delay"  eher geizig umgehen soll ;-).

Ja, ist auch grundsätzlich richtig.

Was ist das Problem:
Das Problem ist, dass man mittels delay keine vernünftigen Programme 
schreiben kann, so dass der µC scheinbar mehrere Dinge gleichzeitig 
machen kann.
Hast du diesen Fall?
Nicht wirklich. Dein Fall ist einfach gelagert: Wenn Input High dann 
Servo in die eine Endstellung. WEnn Input Low, dann in die andere 
Endstellung.
Und sonst nichts weiter.
Das geht mit delay genauso gut und ist für dich einfacher als eine 
Timerlösung, deren Probleme du nicht verstehst.

von Willi L (Gast)


Lesenswert?

Es funktioniert

vielen Dank noch mal

Willi

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.