Forum: Mikrocontroller und Digitale Elektronik Mit Servosignal & uC schalten


von Sefco (Gast)


Lesenswert?

HeyHo!

Ich versuche seit längerer Zeit, mit einem Servo Signal, was ich am 
Empfänger meine RC-Porsches abgreife, einfach etwas zu schalten. Sprich 
einen Blinker oder einfach nur LEDs.
Ich habe bereits im Tutorial gelesen, dass ein Servo Signal ca. 20 ms 
lang ist und aus kurzen Peaks von ca. 2ms besteht. Ich dachte mir, dass 
es ja einfach wäre, dieses Signal an einen Eingang von meinem uC zu 
legen und sobald ein High detektiert wird, soll etwas geschaltet werden. 
Allerdings klappt es einfach nicht. Hier mein Code:

1
#include <avr/io.h>          
2
#include "util/delay.h"
3
 
4
int main (void) 
5
{            
6
7
  DDRD = (0 << DDB0);
8
  DDRB = (1 << DDB0);
9
   PORTB = (1 << 0);
10
11
    while(1) 
12
  {    
13
               
14
    if (PIND & (1 << PD0))
15
    {
16
      PORTB = (0 << 0);
17
      _delay_ms(2000);
18
    }
19
    else
20
    {
21
      PORTB = (1 << 0);
22
      _delay_ms(2000);
23
    }
24
25
26
  }
27
28
   return 0;                 
29
}





Mach ich irgendwo einen Denkfehler? Ist das Signal zu schnell für den 
ATMEGA 8, den ich nutze, oder müsste das eigenltich so klappen?

Danke!

von Lala (Gast)


Lesenswert?

Mhm....

versuchs lieber mit einem Interrupt auf dem entsprechenden pin

von Sefco (Gast)


Lesenswert?

Wieso sollte das besser klappen meinst du?

von Mutti (Gast)


Lesenswert?


von Sefco (Gast)


Lesenswert?

Ja ich weiß wie ein Interrupt klappt, aber wieso funktioniert es auf 
meine Art nicht?

von Martin (Gast)


Lesenswert?


von Michael (Gast)


Lesenswert?

Hallo,

ich würde stark behaupten mit deinem Polling-Ansatz verpasst du schlicht 
und einfach das Signal.
Ablauf:
Kein High ->
PortB.0 auf  setzen
2 sek warten
-> neuer Durchlauf der Schleife
-> Abfrage auf High

Wenn an dieser Stelle gerade nicht High ist, verpasst du für weitere 2 
sek jegliche Flanke. Das High müsste als zufällig genau bei der Abfrage 
anliegen, was vermutlich so in deinen Tests nicht vorkommt.
Da du das programm mit dem Delay außerdem blockierst, ist es entweder 
sowieso nur für diesen Einsatz gedacht, dann würde sich statt dem µC 
aber auch ein Monoflop eignen, oder aber du solltest auf 
Interruptbetrieb umstellen, wenn schon nicht das Signal über 
Interrupteingang, so doch zumindest die Wartezeit, um ein blockieren des 
restlichen Programmes zu verhindern.

MFG

von Sefco (Gast)


Lesenswert?

Vielen Dank für den Link Martin!

Michael, ich glaube du hast recht. Ich habe die Pause nur eingeführt, 
weil ich Angst hatte das ich die LED nicht sehe weil das alles zu 
schnell geht.

Ich teste mal!

von Sefco (Gast)


Lesenswert?

So, dumme Pause rausgenommen. Sieht jez so aus:
1
#include <avr/io.h>          
2
#include "util/delay.h"
3
 
4
int main (void) 
5
{            
6
7
  DDRD = (0 << DDB0);
8
  DDRB = (1 << DDB0);
9
   PORTB = (1 << 0);
10
11
    while(1) 
12
  {    
13
               
14
    if (PIND & (1 << PD0))
15
    {
16
      PORTB = (0 << 0);
17
      _delay_ms(2000);
18
      PORTB = (1 << 0);
19
    }
20
21
  }
22
23
   return 0;                 
24
}



Leider klappt es immer noch nicht. Ich schalte im Moment zu Testzwecken 
nur eine LED an, die ja dann nach kurzer Zeit wieder von alleine 
ausgeht. Egal auf welchen Kanal ich mich mit PD0 stecke, die LED bleibt 
aus. Allerdings geht sie jedesmal an, wenn ich Gas gebe. Irgendwie sehr 
komisch. Vielleicht sollte ich es doch mal mit dem Interrupt versuchen.

von Sefco (Gast)


Lesenswert?

So, auch mit Interrupt klappt es nicht. Interrupt reagiert auf steigende 
Flanke.
1
#include <avr/io.h>          
2
#include "util/delay.h"
3
#include <avr/interrupt.h>
4
5
6
int main()
7
{
8
9
  DDRB = 0b11111111; //PORTB auf Ausgang schalten
10
  PORTB = 0b11111111;
11
12
  GICR = (1 << INT0); //INT0-Interrupt aktivieren
13
14
  MCUCR = (1 << ISC01)|(1 << ISC00); //Aktiviere Sensitivität auf steigende Flanke
15
16
  sei(); //Generell Interrupts aktivieren
17
18
19
  while (1) //Hauptschleife
20
  {
21
    
22
  }
23
24
  return 0;
25
26
}
27
28
ISR(INT0_vect) //Interruptfunktion: Hier wird hingesprungen, wenn ein Interrupt ausgelöst werden soll.
29
{
30
  PORTB =~ PORTB; 
31
}



Togglet dann einfach meine LED. Klappt auch, wenn ich den Interrupt mit 
zwei Messspitzen auslösen. Am Empfänger macht das Ding einfach garnicht, 
außer ich gebe Gas. Ich versteh garnich was das Gas geben auf einem 
anderen Kanal damit zu tun hat.

Habt ihr eine Idee, was hier vor sich geht?!

von Martin (Gast)


Lesenswert?

Wenn du Pollen möchtest, solltest du z.B. deinen Eingang jede ms einmal 
abtasten ist dein Signal länger als 5 Abtastungen 1 dann sendet dein 
Sender ein Signal >50%.

von Sefco (Gast)


Lesenswert?

Kannst du mir erklären, wass "Pollen" ist? Ich versteh deinen letzten 
Beitrag leider garnicht.

von Martin (Gast)


Lesenswert?

Die Timer der Renesas Controller haben einen Puls-Lenght-Messure Modus. 
Dabei startet der Timer mit der steigenden Flanke und stoppt bei der 
fallenden Flanke. Gleichzeitig wird ein Interrupt ausgelöst. Ich muss 
dann in der Interrupt Routine nur noch den Timer auslesen und auswerten. 
Wie es bei einem AVR geht weiß ich nicht.

von Martin (Gast)


Lesenswert?

Pollen ist im Programm regelmäßig den Portpin abfragen. Im Gegensatz 
dazu steht Interrupt, wo das Programm durch ein Ereignis unterbrochen 
wird.

von Martin (Gast)


Lesenswert?

Sefco schrieb:
> Kannst du mir erklären, wass "Pollen" ist? Ich versteh deinen letzten
> Beitrag leider garnicht.

Jede Millisekunde schaust du welchen Pegel dein Portpin hat. Ist dein 
Portpin zum ersten mal 1 dann zählst du einen Zähler hoch. Nach einer 
weiteren ms schaust du wieder ob dein Portpin immernoch 1 ist wenn ja, 
zählst du deinen Zähler hoch. Wenn nein schaust du dir den Wert des 
Zähler an. Ist der > 10 ist dein Servo Impuls länger als 10ms, also 
scxhaltest du dein Licht im Modell ein. Ist dein Zähler kleiner als 10 
schaltest du dein Licht aus.

von Sefco (Gast)


Lesenswert?

OK, aber ich mach es ja jetzt mit einem Interrupt. Es passiert aber 
einfach nichts, die LED geht nicht an. Was mach ich nur falsch...

von X. H. (shadow0815)


Lesenswert?

Pollen ist ständiges Nachfragen:

Sind wir schon da? NEIN! Sind wir schon da? NEIN! Sind wir schon da? 
NEIN! Sind wir schon da? NEIN! Sind wir schon da? NEIN! Sind wir schon 
da? NEIN! Sind wir schon da? NEIN! Sind wir schon da? NEIN! Sind wir 
schon da? NEIN! Sind wir schon da? NEIN! Sind wir schon da? NEIN! Sind 
wir schon da? NEIN! Sind wir schon da? NEIN! Sind wir schon da? JA!  --> 
Führe Aktion Aussteigen durch...

Interruptgesteuert: Kind spielt GameBoy. Eltern sind angekommen und 
interrupten das Kind mit: Wir sind da, tu mal kurz aussteigen!

Interruptgesteuert hat das Kind mehr Zeit für andere Dinge, weil es 
nicht ständig fragen muss, es wird automatisch unterbrochen wenn es 
soweit ist...

von Martin (Gast)


Lesenswert?

Ich habe auf meiner Seite auch folgende Seite verlinkt:
http://www.rn-wissen.de/index.php/Servos

von Martin (Gast)


Lesenswert?

Sorry, ich hatte das Servosignal falsch im Kopf. Das Prinzip bleibt aber 
das gleiche. Du musst die Zeit messen, wie lange das Signal High ist. 
Das Servo Signal ist zwischen 1ms und 2ms lang High. Beim Pollen taste 
das Signal also alle 0,1ms ab. Ist der Zähler > 15 dann LED ein und bei 
< 15 LED aus.

von Martin (Gast)


Lesenswert?

@X.H.
nette Erklärung ;)

Wie soll man auch in ruhe Game Boy spielen wenn man alle 2 Minuten 
fragen muss ob man schon da ist.

von Klaus W. (mfgkw)


Lesenswert?

Sefco schrieb:
> So, auch mit Interrupt klappt es nicht.

Erstens ist das eine abgrundtief miese Fehlerbeschreibung.

Zweitens: Hast du dir schn mal die Grundlagen angeeignet, z.B. das 
AVR-gcc-Tutorial?

Drittens hast du dort auch gefunden, wie Modellbauservos funktionieren?

Eher nicht, sonst würdest du sowas nicht schreiben:
Sefco schrieb:
> ISR(INT0_vect) //Interruptfunktion: Hier wird hingesprungen, wenn ein Interrupt 
ausgelöst werden soll.
> {
>   PORTB =~ PORTB;
> }

Warum sollte man den Port toggeln, wenn ein Interrupt eintritt?
Das "auch mit Interrupt klappt es nicht" ist dann auch nicht 
verwunderlich.

Mach dich doch bitte erstmal schlau, wie das Servosignal funktioniert.
Sonst hat es keinen Sinn, dich hier mit Infos zu füttern und dabei
nur die Luft sinnlos umzurühren.

Und nein, es reicht nicht, nur auf den Interrupt zu warten.

von Michael (Gast)


Lesenswert?

Sefco schrieb:
> Allerdings klappt es einfach nicht.

Kannst du das genauer beschreiben? Die Pulse des Servosignals sind immer 
da, was soll also bei deiner Methode passieren.

von Klaus W. (mfgkw)


Lesenswert?

Sefco schrieb:
> Ich dachte mir, dass
> es ja einfach wäre, dieses Signal an einen Eingang von meinem uC zu
> legen und sobald ein High detektiert wird, soll etwas geschaltet werden.

Das Signal kommt doch regelmäßig, egal welcher Wert beim Sender 
eingestellt ist.

Du musst den Unterschied herausfinden zwischen der einen Stellung am 
Sender und der anderen, und dann darauf reagieren, um deinen Schalter 
auf der Empfängerseite zu betätigen.

Also: wie unterscheidet sich das Signal zwischen dem einen und dem 
anderen Zustand?

von Martin (Gast)


Lesenswert?

Und wenn Junior zwischenduch mal sagt "Ich habe hunger" kann er nicht 
gleichzeit fragen "sind wir schon da" und somit muss er dies mit einer 
kleinen Verzögerung fragen.

von Sefco (Gast)


Lesenswert?

OK, der Link von RN wissen hat sehr geholfen. Ich hatte garnicht 
verstanden, dass der Impuls permanent kommt. Ich dachte er würde nur 
kommen, wenn ich den Hebel an der Fernssteuerung bewege.

>Erstens ist das eine abgrundtief miese Fehlerbeschreibung.

Ich habe meinen Fehler oben bereits beschrieben. Die LED bleibt aus, 
egal was für einen Kanal ich nehme. Sie geht allerdings immer an, wenn 
ich Gas geben.


>Warum sollte man den Port toggeln, wenn ein Interrupt eintritt?
>Das "auch mit Interrupt klappt es nicht" ist dann auch nicht
>verwunderlich.

Wieso nicht? Es geht hier ums Schalten. Was ich schalte oder beim 
Interrupt mache ist doch egal oder nicht?


Also mach ich jetzt folgendes: Ich nutze einen Timer, um zu messen, wie 
breit der Impuls ist. Ist der Impuls bei 1,5 ms bin ich in der Mitte. 
Ist der Impuls größer als 1,5ms lenke ich nach oben aus, ist er kleiner 
als 1,5 ms nach unten. Daran kann ich dann erkennen, was ich am Sender 
mache.

Da ich damit noch keine Erfahrung habe, insbesondere nicht mit Timern, 
werde ich das jetzt mal probieren und mich sicher später nochmal melden 
wenn ich Probleme habe.

Danke euch!

von Mutti (Gast)


Lesenswert?

<IRONIE_AUS>
  Super !!!
</IRONIE_AUS>

von uwe (Gast)


Lesenswert?

Das ist der richtige Ansazt und sollte so funktionieren. Aber die Mitte 
brauch noch eine Totzohne in der nichts passiert (denn das Potentiometer 
in dem Sender wird toleranzen und Umkehrspiel haben und nicht jedesmal 
genau zur Mittelstellung zurückkehren) Also muß getestet werden ob der 
Impuls 1,5ms +-0.01ms lang ist, wenn nicht gucken ob kleiner oder größer 
und etsprechend schalten.

von Sefco (Gast)


Lesenswert?

Alles klar bin dran! Wie gesagt, ich habe keine Ahnung von Timer. Lese 
da gerade erstmal im Tut.

von uwe (Gast)


Lesenswert?

ein Fahrtenregler lernt zum Beispiel die Mittelstellung (und den 
Vollausschlag). Also man läßt den Knüppel in Mittelstellung und drückt 
auf "lerne Mittelstellung" und der Fahrtenregler guckt sich das Signal 
an und merkt sich z.B. Aha 1,6ms ist also Mitte , man drückt den Knüppel 
maximal hoch und drückt auf "lerne Maximum" und er sieht (das es gut 
war) 2,4ms und  speichert dies als Maximum, man drückt den Hebel bis zum 
Anschlag runter und drückt wieder die Taste und er guckt sich das Signal 
an und sieht 0,95ms und nimmt dies als minimum.
Natürlich nimmt man nicht drei Tasten dafür sonder beim erstenmal 
drücken wird Wert 1 gespeichert, beim zweiten der zweite usw. und damit 
man die Taste auch für andere Sachen benutzen kann muss man erst in den 
Konfigurationsmodus kommen. Dies macht man indem man die Taste 3 
Sekunden lang drückt. Tasten Entprellen muß man auch noch. Ausserdem ist 
An und Ausaschalten langweilig. Also steuer lieber die LED mit PWM an um 
die Helligkeit zu regulieren. Mach Später ne Vollbrücke dran und klemm 
nen Motor ran. Dann haste nene Digitalen Fahtenregler.

von Klaus W. (mfgkw)


Lesenswert?

Ich hatte auch mal einen Empfänger ausgelesen.

Da habe ich es so gemacht, daß ich erstens einen Timer laufen lasse, und 
zweitens erst den INT0 so konfiguriere, daß er auf steigende Flanke 
reagiert. In der Int0_vect wird dieser Fall erkannt an einem 1-Wert des 
Pins und dabei wird der ISR0 gleich wieder so umkonfiguriert, daß er ab 
jetzt auf fallende Flanke reagiert. Außerdem wird bei 1 am Datenpin in 
der ISR0_vect gleich der Zählerwert des Timers zu 0 gesetzt.

Ist in der ISR0_vect dagegen der Datenpin 0, dann ist es offensichtlich 
der ISR0 mit der fallenden Flanke. Dann wird er erstens wieder auf 
steigende Flanke umgemodelt für den nächsten Impuls, und zweitens der 
aktuelle Timerwert hergenommen, der ja bei der steigenden Flanke zu 0 
gesetzt wurde und in der Zwischenzeit etwas hoch lief.
Der Wert des Timers ist ein Maß dafür, wie lange das Signal high war.

Es gibt sicher auch andere Wege, vielleicht einfachere. Deshalb nur als 
Vorschlag...

von uwe (Gast)


Lesenswert?

Wenn du das durch hast, dann hast du das Kapitel Timer,PWM,Input Capture 
und output compare verstanden.

von ziegenpeter (Gast)


Lesenswert?

Also wenn der Controller nichts anderes machen muss, würd ich das ganz 
trivial so lösen, dass ich erst mal auf die steigende Flanke warte.

while (isPinLow()) {}

Wenn ab 1,5 ms ausgelöst werden soll, dann wart ich ab jetzt diese Zeit 
(delayMs(15) oder so ähnlich) und wenn danach wieder low ist, wird nicht 
geschaltet, wenn immer noch high, dann wird geschaltet.
Und das ganze in eine Endlosschleife.

von Sefco (Gast)


Lesenswert?

ziegenpeter schrieb:
>Also wenn der Controller nichts anderes machen muss, würd ich das ganz
>trivial so lösen, dass ich erst mal auf die steigende Flanke warte.
>
>while (isPinLow()) {}
>
>Wenn ab 1,5 ms ausgelöst werden soll, dann wart ich ab jetzt diese Zeit
>(delayMs(15) oder so ähnlich) und wenn danach wieder low ist, wird nicht
>geschaltet, wenn immer noch high, dann wird geschaltet.
>Und das ganze in eine Endlosschleife.


Vielen Vielen Dank für die Idee. Damit klappt es super. Mir geht es ja 
wirklich nur ums schalten. Von daher kann ich mir den Timer komplett 
sparen. Klasse Idee! Danke!

Gruß & Gute Nacht!

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.