Forum: Mikrocontroller und Digitale Elektronik Atmega328PB Servo-Winkel mttels Taster verstellen


von Marco S. (marco_elec)


Lesenswert?

Guten Abend an alle,
es geht darum, einen Reely S0008 servo über einen Atmega 328PB zu 
steuern.
Der Servo wird über eine PWM, welche mittels TIMER1 CTC mode erfolgt, 
angesteuert.
Steuerung klappt wunderbar. Das habe ich mit einem Oszilloskop getestet.

Allerdings habe ich folgendes Problem:

Ich möchte mit einem Taster (an PD3) bei Tastendruck den Servo um ca. 5° 
weiterdrehen, ausgehend von einer beliebigen Ausgangsstellung. Für jeden 
Tastendruck soll der Servo also quasi um 5° weiterfahren bis er eine 
Endstellung x erreicht hat.
Das Problem ist, dass bei Tastendruck teilweise zufällig Schritte 
übersprungen werden. Statt einmal zu incrementieren, incrementiert er 
teilweise 2 oder dreimal. Manchmal klappt es aber auch. Leider habe ich 
nicht direkt rausgefunden an was dies liegt. Ich arbeite hier mit einem 
externen Interrupt. Auch eine delay im interrupt bringt keine Abhilfe.

Vielleicht hat jemand von euch hier einen Tipp, was das Problem ist. Am 
Oszilloskop sieht man sehr schön, wie er teilweise einfach doppelt 
incrementiert. Anbei noch der Code.

Ich danke euch schon mal im Voraus.
1
#define F_CPU 16000000UL //define CPU frequency 16Mhz
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
#include <util/delay.h>
5
6
7
int main(void)
8
{
9
  DDRD |= (1<<PORTD5); //set PD5 to output
10
  DDRD &=~(1>>PORTD3); //set PD3 to input to increment OCR1A value for servo movement
11
  PORTD |= (1<<PORTD3); //activate internal pull-up resistance 
12
  TCCR1A = 0; //no OCnx value is used
13
  TCCR1B |= (1<< WGM12) | (1<<CS11); //set CTC mode and prescaler to 8;
14
  TIMSK1 |= (1<< OCIE1A); //enable compare match at OCR1A
15
  EIMSK |= (1<<INT1); //activate external interrupt INT1 at PD3
16
  EICRA |= (1<<ISC11); //activate external interrupt in case of falling edge
17
  OCR1A = 2000; //set OCR1A to get the selected positive pulse width
18
  sei();
19
    
20
    while (1) 
21
    {
22
    
23
    
24
    }
25
}
26
ISR(INT1_vect)
27
{  
28
  OCR1A += 111; //increase OCR1A to get a movement of about 5°
29
  
30
}
31
ISR(TIMER1_COMPA_vect)
32
{
33
  PORTD ^= (1<< PORTD5); //toggle PD5 to create CTC PWM at PD5
34
}

von Thomas E. (thomase)


Lesenswert?


von Marco S. (marco_elec)


Lesenswert?

Hallo Thomas,

danke für die Antwort. Der Link ist top.

Die Entprellung selbst schreibe ich dann in die while Schleife der Main?

Bin mir gerade nicht ganz sicher, wie ich das mit der ISR(INT1_vec) 
verknüpfen kann

von Carl D. (jcw2)


Lesenswert?

Marco S. schrieb:
> Hallo Thomas,
>
> danke für die Antwort. Der Link ist top.
>
> Die Entprellung selbst schreibe ich dann in die while Schleife der Main?
>
> Bin mir gerade nicht ganz sicher, wie ich das mit der ISR(INT1_vec)
> verknüpfen kann

Mit Timer0 einen 10..20ms Interrupt auslösen und darin "debounce".

von Falk B. (falk)


Lesenswert?

Marco S. schrieb:
> Hallo Thomas,
>
> danke für die Antwort. Der Link ist top.

Dann muss man den Inhalt "nur" noch verstehen.

> Die Entprellung selbst schreibe ich dann in die while Schleife der Main?

Nö, in die Timer-ISR.

> Bin mir gerade nicht ganz sicher, wie ich das mit der ISR(INT1_vec)
> verknüpfen kann

Gar nicht. Denn Taster die prellen klemmt man nicht an einen externen 
Interrupt, sondern liest sie periodisch in einer Timer-ISR aus und 
filtert nochmal in Software.

In deine While(1) Schleife kommt nur periodisch die Abfrage über 
get_key_press() und im Falle einer positiven Antwort eine Erhöhung des 
PWM-Werts.

Mach mal und stell dein Ergebnis hier vor, dann kann man ggf. weitere 
Tipps geben.

von Marco S. (marco_elec)


Lesenswert?

Guten Morgen,

es hat sich mittlerweile erledigt.
Der Fehler war, dass ich (mal wieder) active low und active high nicht 
auseinandergehalten habe. Zweitens lag es an der fehlenden Entprellung.

Danke nochmals. Ich würde den Thread vielleicht noch offen lassen, da 
ich noch ein paar Sachen mit dem Servo vorhabe vorhabe und vielleicht 
nochmals auf euch zukommen muss.


Mal noch eine zweite Frage:
Ich suche einen guten Servo bzw. Schrittmotor für 360° Bewegungen.
Kklar man kann die normalen "tunen" aber ich hätte schon gerne ein 
"originales" Modell.
Habt ihr Empfehlungen, die ihr ausstellen könnt?

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.