PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RC Empfänger auslesen



W-Lan Kabel
14.09.2009, 14:53
Hallo,

Wie kann ich einen Empfänger (3 Kanäle und Stromanschluss) auswerten?
kann der RP6 oder Die CCpro M128 drei PWM signal lesen und danach
einen servo (alleine geht das) und die beiden Motoren vom RP6 proportional steuern?

ich hab das mal in einem youtubevideo gesehen aber da sieht man nicht wo die dort zwei Kanäle angeschlossen sind und ob das auch mit drei geht.

Also wo sind die 3mal 3 kabel anzuschließen und wie liest man die aus?
Den strom für den Empfänger gibt ja der 5volt spannungsregeler vom Rp6 aus, den kann man ja benutzen.

vielen Dank

radbruch
14.09.2009, 17:17
Hallo

Das geht mit dem RP6 recht einfach. Ein möglicher Ansatz: Mit den selben Routinen mit denen man mit dem RP6 ein Servo ansteuern würde, kann man auch die Servo-Impulslängen eines RC-Empfängers messen:
https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=328950#328950

http://img.youtube.com/vi/A_GYUeFAgY8/2.jpg (http://www.youtube.com/watch?v=A_GYUeFAgY8)
http://www.youtube.com/watch?v=A_GYUeFAgY8

(Das einfache Programm dazu findet man ein paar Beiträge davor)

Gruß

mic

Virus
15.09.2009, 09:58
Kann der Timer auch drei lesen?
und wo müssen die Leitungen vom empfänger angeschlossen werden?

Die Stromversorgung ist klar ( GND und +5 Volt)
Aber dann kommen ja noch pro Kanal drei leitungen aus dem dem empfänger,
ich nehme an GND, +5 Volt und PWM?

Reicht es nicht nur PWM zu verwenden?
Und das kommt dann an entweder SCL, IT1 oder SDA?

radbruch
15.09.2009, 17:11
Hallo

Selbstverständlich kann der Mega32 auch drei (oder mehr) RC-Signale messen. Im oben erwähnten Thread habe ich weiter unten die Funktion nochmals näher beschrieben. Der eigentliche Messvorgang geschied in der ISR. Weil beim RP6 die Timer und ihre ISR schon alle belegt sind verwende ich in diesem Beispiel meine eigene abgespeckte Library (rblib (https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=329255#329255)). Man könnte auch die orginale Lib verwenden, dann muss man aber die ISR in RP6RobotBaseLib.c ändern. Aber dazu später mehr, erstmal die Grundlagen zum Impulslängenmessen:

Die Servoimpulse sollten zwischen 0,5 und 1,5ms lang sein (je nach Doku auch 1-2ms). Gehen wird mal von 1ms Impulslänge und 100 als gewünschten Positionswert für die Servomitte aus. (Ohne den Totpunkt des Servos zu beachten wäre das eine Auflösung von ca. 100 Schritten.) Dann muss eine Positionseinheit 1ms/100=10µs dauern. Deshalb muss die ISR alle 10µs aufgerufen werden, bei jedem Aufruf wird ein temporärer lokaler Zähler erhöht, solange der Impuls am Eingang erkannt wird. Wenn das Ende des Impulses erkannt wird, wird der Zählerinhalt in eine globale Variable kopiert und steht damit überall im Programm zur Verfügung. Der Zähler wird wieder auf 0 gesetzt und wartet auf den Start des nächten Impulses. Als Code für die ISR sieht diese Funktion bei mir so aus:

if (PINC & 1) rc_temp_dir++; else
if (rc_temp_dir) { rc_input_dir=rc_temp_dir-1; rc_temp_dir=0; }
if (PINC & 2) rc_temp_pwr++; else
if (rc_temp_pwr) { rc_input_pwr=rc_temp_pwr-1; rc_temp_pwr=0; }
if (PINA & 16) rc_temp_pwr++; else
if (rc_temp_pwr) { rc_input_pwr=rc_temp_pwr-1; rc_temp_pwr=0; }


Wenn am Eingang ein High anliegt wird der Zähler (rc_temp_xxx) erhöht . Ist der Eingang nicht gesetzt (else-Zweig) und der Zähler gleich 0 (rc_temp_xxx ist dann false) passiert nichts, weil wir auf den Impulsstart warten. Ist der Zähler allerdings ungleich 0 wurde etwas gezählt. Dann wird der Zähler in die globale Input-Variable (rc_input_xxx) kopiert und anschliesend gelöscht. Das ist dann der Status "warten auf Impulsstart".

Diese Beispiele verwenden die Pins SDA, SCL und E_INT1. Die sind alle direkt am XBUS verfügbar (Pin 8,10 und 12?). Vom RC-Empfänger müssen die PWM.Signale jeweils mit einem Mega32-Eingang verbunden sein, sicherheitshalber über einen Schutzwiderstand (ca. 1k?), zusätzlich müssen Vcc und GND vom RP6 und dem Empfänger verbunden sein. Man könnte aber auch andere Pins verwenden, ADC0/1 wäre noch günstig

Soweit alles klar? Jetzt wird's nämlich noch etwas komplizierter: Da bei meinem Beispiel mit meiner Lib der Timer0 frei ist sieht die ISR bei mir so aus:


ISR(TIMER0_COMP_vect)
{
if (PINC & 1) rc_temp_dir++; else
if (rc_temp_dir) { rc_input_dir=rc_temp_dir-1; rc_temp_dir=0; }
if (PINC & 2) rc_temp_pwr++; else
if (rc_temp_pwr) { rc_input_pwr=rc_temp_pwr-1; rc_temp_pwr=0; }
}


Der Timer wird im CTC-Mode betrieben. Das Timerzählregister wird mit jedem Timertakt erhöht und mit einem Grenzwert (OCR0) verglichen. Wenn Timerzählregister und der Grenzwert gleich groß ist wird das Timerzählregister auf 0 gesetzt und die ISR aufgerufen. (btw. wenn nun der Grenzwert erneut erreicht wird BEVOR die ISR beendet ist spricht man von einem Überlauf) Das Setup des Timers sieht dann so aus (weiter Infos im Datenblatt des Mega32):
TCCR0 = (0 << WGM00) | (1 << WGM01); // CTC-Mode
TCCR0 |= (0 << COM00) | (0 << COM01); // ohne OCR-Pin
TCCR0 |= (0 << CS02) | (1 << CS01) | (0 << CS00); // prescaler /8
TIMSK = (1 << OCIE0); // Interrupt ein
OCR0 = 10;
(eigentlich fehlt hier noch ein sei() ;)

Wichtig ist der Prescaler. Der Timer läuft nicht direkt mit dem Systemtakt des Microkontrollers, sein Takt errechnet sich aus dem Systemtakt geteilt durch den Prescaler, beim RP6 sind das 8MHz/8=1MHZ. Da nach zehn Timerzähltakten dann der Interrupt ausgelöst wird (OCR0=10) kommen wir so auf 1MHZ/10=100kHz oder eben 10µs zwischen den Interrupten.

In der RP6-Library wird der Timer aber mit OCR0=99 konfiguriert, das ergibt einen 10kHz-Takt und 100µs zwischen den Interupts. Wenn man nun die Lib-ISR einfach mit den RC-Zählfunktionen ergänzt würden die Messwerte um den Faktor 10 kleiner sein als bei meinem Beispiel:

ISR (TIMER0_COMP_vect)
{
if (PINC & 1) rc_temp_dir++; else
if (rc_temp_dir) { rc_input_dir=rc_temp_dir-1; rc_temp_dir=0; }

#ifdef POWER_ON_WARNING
(RC-Code in der Datei RP6RobotBaseLib.c einfügen)
Das würde immer noch eine Auflösung der Impulslängen in 10 Schritten ermöglichen.

Für eine höhere Auflösung müßte man in der RP6-Lib den OCR0-Wert verkleinern. Dadurch würden aber einige andere RP6-Funktionen beeinflußt werden, z.B. Sleep() und mSleep(), die Stopwatches und wasweisichnoch. Außerdem würde zehnmal mehr Interupts ausgelöst werden. das würde das System ausbremsen und da die ISR in der RP6-Lib recht lang ist würde dies auch zu einem Überlauf nach dem anderen führen.

Ächz. Der Beitrag ist doch etwas länger geworden.

Gruß

mic

Virus
15.09.2009, 20:48
vielen vielen Damk,
jetzt kapier ich idiod es auch mal!

zusätzlich müssen Vcc und GND vom RP6 und dem Empfänger
die bei jedem kanal sich ändern oder die die den Epfänger versorge?

radbruch
15.09.2009, 21:08
Naja, es auch nicht einfach, weil viele Dinge zusammenspielen müssen.

Vcc und GND (das sind schlicht + und - der Spannungsversorgung) sind für alle Kanäle gleich, ändern sich nicht und sind zugleich die Versorgung für den Empfänger. Die Impulse des Empfängers sind eigentlich nur Spannungen (high oder low) zwischen Impuls-Pin und GND, der Mega32 wertet dann die Pegel zwischen seinen Pins und GND aus. Deshalb reicht eine Verbindung zwischen RP6-GND zu Empfänger-GND, eine für RP6-Vcc zu Empfänger-Vcc und je eine Verbindung pro Kanal zwischen Impulsausgang des Empfängers und Eingangspin des Mega32.

Virus
16.09.2009, 08:10
ah,
soetwas hab ich mir schon gedacht,
jetzt kann ich mir sicher sein

vielen Dank