Mit Servosignal & uC schalten

Gast #2337430
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!
Gast #2337465
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
Gast #2337488
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.
Gast #2337538
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?!
Gast #2337548
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.
Gast #2337560
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.
#2337563
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...
Gast #2337573
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.
#2337583
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.
#2337594
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?
Gast #2337634
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!
Gast #2337655
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.
Gast #2337683
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.
#2337684
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...
Gast #2337731
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.
Gast #2338642
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!

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