Archiv verlassen und diese Seite im Standarddesign anzeigen : RP6 und RC
blenderkid
30.12.2007, 18:46
Hi,
ich habe auf meinen Robby einen RCEmpfänger draufgebaut und die PWM Stecker an die ADCs gesteckt.
Ich habe ein Programm geschrieben ,dass 200ms lang zählt wie oft der Strom an geht.
Hmm,jetzt habe ich beim Steuern des RP6 immer eine Verzögerung bis er reagiert.
Gibt es eine bessere Methode die Frequenz des PWM zu ermitteln?
DIV
Hi,
wenn du so ein Programm schreiben kannst, könntest du sicher auch darauf kommen, dass man so ohne alle weiteren Infos (Hardware: Was ist wo dran? Was soll das bewirken? Software: Stell dein Prog ein!) eine Glaskugel brauchen würde, um deine Frage zu beantworten.
Gruß Dirk
blenderkid
31.12.2007, 12:02
Hi, okay kann ich verstehen.
Ich finde keine Datenblätter zu dem Empfänder und der Fernsteuerung ( acoms AP-202/40 und AR-2/40 ), war auch keine Anleitung dabei :( .
Der Empfänder hat zwei Kanäle. Ich habe die PWM-Stecker, der beiden Kanäle, an ADC2 und ADC3 auf dem M32 gesteckt und die GNDs an die GNDs.
Wenn ich die ADCs auslese erhalte ich entweder 0 oder 655.
Jetzt möchte ich herausfinden wie die Frequenz der PWMs ist, um den RP6 mit der Fernsteuerung steuern zu können
roboterheld
31.12.2007, 13:29
....Jetzt möchte ich herausfinden wie die Frequenz der PWMs .......
kannste doch selber festlegen.
http://www.mikrocontroller.net/topic/87282#new
radbruch
31.12.2007, 13:51
Hallo blenderkid
Mit einfachen Bordmitteln des RP6:
// Auswerten eines 2-Kanal RC-Empfängers an PortC0 und PortC1 31.12.2007 mic
// Mit der RP6-Library, blockierend ähnlich wie sleep(), noch ohne timeout!!!
// Durch die Verwendung von SCL/SDA kann das Programm nicht angehalten werden,
// Nach einem Reset startet der ATMega32 sofort erneut.
// Besser ist ein Anschluß an ADC0/ADC1 (PortA0 und PortA1)
#include "RP6RobotBaseLib.h" // Library einbinden
#include "RP6uart.h" // Zum Debuggen, wir wollen ja was sehen,
#include "RP6uart.c" // auch wenn wir kein LCD besitzen
uint8_t read_rc(uint8_t kanal)
{
extern uint8_t delay_timer; // der sleep()-Timer aus RP6RobotBaseLib.c
if (kanal == 1) // Eingang Kanal 1 der RC-Fernbedienung (SCL xBus Pin10)
{
while (!(PINC & 1)); // Warten auf aufsteigende Flanke
sleep(1); // setzt den delay_timer auf 0
while (PINC & 1); // Warten auf absteigende Flanke
return (delay_timer); // Fertig, Rückgabewert in 0.1ms
}
if (kanal == 2) // Eingang Kanal 2 der RC-Fernbedienung (SDA xBus Pin12)
{
while (!(PINC & 2)); // Warten auf aufsteigende Flanke
sleep(1); // setzt den delay_timer auf 0
while (PINC & 2); // Warten auf absteigende Flanke
return (delay_timer); // Fertig, Rückgabewert in 0.1ms
}
return(0); // ungültiger Parameter übergeben
}
int main(void)
{
initRobotBase();
DDRC &= ~3; // Ports auf Eingang
PORTC &= ~3; // und PullUps aus
setLEDs(1); // Anzeige Programm gestartet
writeString_P("\n\n\r2-Kanal RC-Empfänger einlesen 31.12.07 mic\n\r");
while(1)
{
writeString_P("\n\r");
writeString_P("Kanal 1: ");
writeInteger(read_rc(1), 10);
writeString_P(" Kanal 2: ");
writeInteger(read_rc(2), 10);
mSleep(300);
}
return 0;
}
Die Ausgabe dazu:
[RP6BOOT]
[READY]
2-Kanal RC-Empfãnger einlesen 31.12.07 mic
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 13 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 13 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 15 Kanal 2: 13
Kanal 1: 15 Kanal 2: 13
Kanal 1: 15 Kanal 2: 13
Kanal 1: 16 Kanal 2: 13
Kanal 1: 16 Kanal 2: 14
Kanal 1: 17 Kanal 2: 14
Kanal 1: 18 Kanal 2: 14
Kanal 1: 18 Kanal 2: 14
Kanal 1: 18 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 12 Kanal 2: 14
Kanal 1: 9 Kanal 2: 14
Kanal 1: 10 Kanal 2: 14
Kanal 1: 10 Kanal 2: 14
Kanal 1: 10 Kanal 2: 13
Kanal 1: 10 Kanal 2: 13
Kanal 1: 12 Kanal 2: 13
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 11
Kanal 1: 14 Kanal 2: 10
Kanal 1: 14 Kanal 2: 10
Kanal 1: 14 Kanal 2: 10
Kanal 1: 14 Kanal 2: 10
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 15
Kanal 1: 14 Kanal 2: 18
Kanal 1: 14 Kanal 2: 18
Kanal 1: 14 Kanal 2: 18
Kanal 1: 14 Kanal 2: 18
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Kanal 1: 14 Kanal 2: 14
Da das Signal nur 0 oder 1 ist, benötigt man natürlich keinen ADC. Der Empfänger wird an Vcc und GND angeschlossen. Die Kanäle in dieser Version an SDA und SCL (PortC0/PortC1). Alle Anschlüsse sind am xBUS verfügbar.
Gruß
mic
[Edit]
Ich Depp, ich weiß doch, welche Ports verwendet werden sollten. Hier die Version für ADC2/3 (ungeprüft):
// Auswerten eines 2-Kanal RC-Empfängers an PortA2 und PortA3 31.12.2007 mic
// Version für blenderkid (nicht geprüft)
#include "RP6RobotBaseLib.h" // Library einbinden
#include "RP6uart.h" // Zum Debuggen, wir wollen ja was sehen,
#include "RP6uart.c" // auch wenn wir kein LCD besitzen
uint8_t read_rc(uint8_t kanal)
{
extern uint8_t delay_timer; // der sleep()-Timer aus RP6RobotBaseLib.c
if (kanal == 1) // Eingang Kanal 1 der RC-Fernbedienung (ADC2 PortA2)
{
while (!(PINA & 4)); // Warten auf aufsteigende Flanke
sleep(1); // setzt den delay_timer auf 0
while (PINA & 4); // Warten auf absteigende Flanke
return (delay_timer); // Fertig, Rückgabewert in 0.1ms
}
if (kanal == 2) // Eingang Kanal 2 der RC-Fernbedienung (ADC3 PortA3)
{
while (!(PINA & 8)); // Warten auf aufsteigende Flanke
sleep(1); // setzt den delay_timer auf 0
while (PINA & 8); // Warten auf absteigende Flanke
return (delay_timer); // Fertig, Rückgabewert in 0.1ms
}
return(0); // ungültiger Parameter übergeben
}
int main(void)
{
initRobotBase();
DDRA &= ~12; // Ports auf Eingang ADC2+3
PORTA &= ~12; // und PullUps aus
setLEDs(1); // Anzeige Programm gestartet
writeString_P("\n\n\r2-Kanal RC-Empfänger einlesen 31.12.07 mic\n\r");
while(1)
{
writeString_P("\n\r");
writeString_P("Kanal 1: ");
writeInteger(read_rc(1), 10);
writeString_P(" Kanal 2: ");
writeInteger(read_rc(2), 10);
mSleep(300);
}
return 0;
}
Noch ein [Edit]: Hab' doch glatt überlesen, dass es für ein M32 sein soll. Damit kann ich leider nicht dienen, weil mir das keiner schenken mag. *traurigkuck*
Hallo,
@mic:
Kleiner Hinweis dazu:
Seit Version 1.3 der RP6Lib vom 25.9 gibt es auch die 16Bit Variable "timer" die alle 100µs hochgezählt wird. Sowohl für die RP6BaseLib als auch die RP6ControlLib.
Damit könnte man es so schreiben:
// Hier wird der E_INT1 Pin an PORTA als Eingang verwendet...
while (!(PINA & E_INT1)); // Warten auf aufsteigende Flanke
timer=0;
while (PINA & E_INT1); // Warten auf absteigende Flanke
return (timer); // Fertig, Rückgabewert in 0.1ms
Auf delay_timer sollte man eigentlich gar keinen Zugriff haben (der Compiler sollte meckern ;) ) - hast Du an den Headern was verändert?
Den Bootloader interessiert zum Starten des Programms übrigens nur SDA.
ACHTUNG: Auf jeden Fall zur Sicherheit 1K Widerstände in Serie dazwischen schalten wenn man SDA oder SCL als Sensoreingänge verwenden möchte! Der Bootloader generiert beim Starten nämlich einen General Call auf dem I2C Bus, schaltet SDA und SCL also als Ausgänge und ganz kurz nach GND!
--> Für E_INT1 und die beiden freien ADC Anschlüsse braucht man natürlich keinen Widerstand.
An den freien I/Os vom RP6-M32 Modul sowieso nicht wenn man die Portrichtung auf Eingang schaltet.
--------------------------------------------------------------------
@blenderkid:
Für das RP6-M32 Erweiterungsmodul funktioniert es prinzipiell natürlich ganz ähnlich. Hier hast Du auch jede Menge freie I/O Pins.
Um nochmal auf die Ausgangsfrage einzugehen:
Gibt es eine bessere Methode die Frequenz des PWM zu ermitteln?
Ja - man misst statt der Anzahl der Pulse einfach die Dauer eines einzelnen Pulses! Wie in dem Programmbeispiel von mic.
MfG,
SlyD
radbruch
31.12.2007, 16:34
Hallo SlyD
Ich verwende die orginale Version 1.3 vom 25.9.07 Die Variable delay_timer habe so eingebunden:
extern uint8_t delay_timer;
Eine Fehlermeldung erhalte ich nicht beim Compilieren, ich lese die Variable auch nur aus.
Ich verwende delay_timer mit Absicht, weil weiterhin timer für eigene Anwendungen frei bleiben sollte. Weil meine Funktion blockierend ist, kann delay_timer von sleep() in dieser Zeit nicht verwendet/verändert werden. Ein weiterer Vorteil ist, dass ich mit sleep(0) (war noch ein Bug in der ersten Version) bequem schreibend auf delay_timer zugreifen kann, auch wenn der Aufruf theoretisch einen kleinen Messfehler verursacht.
Der Tipp mit dem SDA-Reset funktioniert wunderbar, ich habe nun den zweiten Kanal auf E-INT1 gelegt und kann das Programm deshalb auch wieder stoppen.
Das aktuelle Programm sieht nun so aus:
// Auswerten eines 2-Kanal RC-Empfängers an PortC0 und PortA4 31.12.2007 mic
// Mit der RP6-Library, blockierend wie sleep(), ohne timeout!!!
// Besser ist ein Anschluß an ADC0/ADC1 (PortA0 und PortA1)
#include "RP6RobotBaseLib.h" // Library einbinden
#include "RP6uart.h" // Zum Debuggen, wir wollen ja was sehen,
#include "RP6uart.c" // auch wenn wir kein LCD besitzen
uint8_t read_rc(uint8_t kanal)
{
extern uint8_t delay_timer; // der sleep()-Timer aus RP6RobotBaseLib.c
if (kanal == 1) // Eingang Kanal 1 der RC-Fernbedienung (SCL xBus Pin10)
{
while (!(PINC & 1)); // Warten auf aufsteigende Flanke
sleep(0); // setzt den delay_timer auf 0
while (PINC & 1); // Warten auf absteigende Flanke
return (delay_timer); // Fertig, Rückgabewert in 0.1ms
}
if (kanal == 2) // Eingang Kanal 2 der RC-Fernbedienung (E_INT1 xBus Pin8)
{
while (!(PINA & E_INT1)); // Warten auf aufsteigende Flanke
sleep(0); // setzt den delay_timer auf 0
while (PINA & E_INT1); // Warten auf absteigende Flanke
return (delay_timer); // Fertig, Rückgabewert in 0.1ms
}
return(0); // ungültiger Parameter übergeben
}
int main(void)
{
initRobotBase();
DDRC &= ~1; // Ports auf Eingang (SCL)
PORTC &= ~1; // und PullUps aus
extIntOFF(); // E_INT1 auf Eingang
setLEDs(1); // Anzeige Programm gestartet
writeString_P("\n\n\r2-Kanal RC-Empfänger einlesen 31.12.07 mic\n\r");
while(1)
{
writeString_P("\n\r");
writeString_P("Kanal 1: ");
writeInteger(read_rc(1), 10);
writeString_P(" Kanal 2: ");
writeInteger(read_rc(2), 10);
mSleep(300);
}
return 0;
}
Leider sind meine ADC0/1-Anschlüsse vorerst dauerhaft belegt, weil ich sie zur Servoansteuerung verwende um meinen RP6 mit einem 4-Radantrieb zu betreiben. Ich habe immer noch keine Alternative zu den orginalen Antriebseinheiten gefunden, deshalb muss ich wohl abwarten, bis mir die passenden Teile eines Schrott-RP6 in die Hände fallen oder arexx ein Getriebekit zum Nachrüsten anbietet.
Gruß
mic
blenderkid
01.01.2008, 18:11
Hi, muss man irgendetwas besonderes machen um den timer zu verwenden?
Bei mir sagt der immer 0.
ich habe mal probiert:
writeInteger(timer,10);
mSpleep(200);
writeInteger(timer,10);
und auch da sagt er zwei mal 0.
Die timer Variable gibt es wie gesagt erst seit der Version vom 25.9.2007 bzw. 28.9 der RP6Lib.
Hier die aktuelle Version:
http://www.arexx.com/rp6/downloads/RP6Examples_20071016.zip
Da muss man eigentlich nichts machen und kann die Variable direkt in allen eigenen Programmen verwenden.
Beispiel:
uint16_t t_end = 0;
uint16_t t_start = timer;
mSleep(100);
t_end = timer;
// Es ist besser die Ausgaben getrennt von den Messungen zu machen
// da die Ausgaben selbst auch Zeit benötigen.
writeString_P("# Start: ");
writeInteger(t_start,DEC);
writeString_P(" -> End: ");
writeInteger(t_end,DEC);
writeString_P(" -> Diff: ");
writeInteger(t_end - t_start,DEC);
writeChar('\n');
MfG,
SlyD
blenderkid
01.01.2008, 20:06
ich habe das hier geschrieben:
uint8_t RC(uint8_t kanal)
{
if (kanal == 1)
{
while((PINA&8));
timer=0;
while(!(PINA&8));
return (timer);
}
if (kanal == 2)
{
while(!(PINA&4));
timer=0;
while(PINA&4);
return (timer);
}
return(0);
}
und da sagt er immer 0.
blenderkid
01.01.2008, 20:11
uups, die Smilies sollen Achten sein.
radbruch
01.01.2008, 21:05
Hallo blenderkid
Poste doch mal dein komplettes Programm (möglichst aufs nötigste reduziert, möglichst kopiert und nicht nachgeschrieben wie "mSpleep(200); und in code-Tags), so dass man es im Umfeld betrachten kann. Erster Tipp: falsche (oder keine) Kanal-Nr. an RC() übergeben.
Man kann einen Eintrag hier im Forum auch editieren. Um die lästigen ;)-Smilies zu unterdrücken, kann man unten das Häckchen bei "Smilies in diesem Beitrag deaktivieren" reinmachen.
Gruß
mic
blenderkid
02.01.2008, 12:44
Ok hier also der Code aufs nötigste reduziert
uint8_t RC(uint8_t kanal)
{
if (kanal == 1)
{
while(!(PINA&8));
timer=0;
while(PINA&8);
return (timer);
}
if (kanal == 2)
{
while(!(PINA&4));
timer=0;
while(PINA&4);
return (timer);
}
return(0);
}
void moveCommand(behaviour_command_t * cmd)
{
RCcount=RC(1);
RCcount2=RC(2);
writeInteger(RCcount,10);
writeChar('\n');
}
int16_t main(void)
{
initRP6Control();
DDRA &= ~ADC3;
DDRA &= ~ADC2;
PORTA &= ~12;
startStopwatch6();
startStopwatch7();
writeInteger(timer,10);
mSleep(200);
writeInteger(timer,10);
while(true)
{
moveCommand(0);
}
return 0;
}
Hier kommt immer 0 heraus. :-(
mfg blenderkid
blenderkid
02.01.2008, 12:58
vielleicht wegen dem return(0); ?
radbruch
02.01.2008, 15:00
Hallo blenderkid
Was ich nun halt immer noch nicht weiß: Wie ist bei deinem Programm die Variable "timer" deklariert.
Egal, für einen schnellen Test kannst du folgendes ändern:
erstes timer=0; in timer=11;
zweites timer=0; in timer=22;
und das return(0); in return(33);
Bei 11 oder 22 stimmt etwas nicht mit dem timer, dann mal timer durch delay_timer ersetzen(beide sind gleichschnell 0,1ms!). 33 wird wohl nicht auftreten.
Gruß
mic
Wie ist bei deinem Programm die Variable "timer" deklariert.
Braucht er nicht zu deklarieren - ist im RP6Lib drin als
volatile uint16_t timer;
@Blenderkid: Du hast aber auch an ADC0 oder ADC1 was angeschlossen? Eventuell mal den anderen Kanal verwenden falls Du da was verwechselt hast beim anschließen?
Poste mal nach den Modifikationen die mic vorgeschlagen hat die komplette Ausgabe des Programms!
Und zusätzlich würde ich einfach an vielen Stellen (z.B. Beginn/Ende einer Funktion, in den If Bedingungen etc. ) mal probeweise
writeString_P("#1#\n");
...
writeString_P("#2#\n");
...
usw. hinschreiben immer mit anderen Nummern natürlich. Dann weisst Du genau an welche Stellen Dein Programm hinspringt und wo es hakt.
Evtl. noch ein mSleep(100) in die Hauptschleife reinmachen damit die Ausgaben nicht zu schnell erfolgen.
Sobald das Programm dann funktioniert, kannst Du die ganzen Ausgaben wieder entfernen.
MfG,
SlyD
EDIT:
PINA & 8 ist natürlich E_INT1.
PINA & 4 ist allerdings nicht ADC1...
Schreib das am besten immer so: PINA & ADC0, PINA & E_INT1, PINC & SCL etc. dann weiss man auch direkt welcher Pin gemeint ist.
Diese ganzen Definitionen findest Du in der Datei RP6RobotBase.h
blenderkid
02.01.2008, 15:16
diese includes benutze ich.
#include "RP6ControlLib.h"
#include "RP6I2CmasterTWI.h"
#include "RP6Control_I2CMasterLib.h"
sonst deklariere ich timer nicht.
Bei dem Test kommt immer 11 heraus.
Als ich delay_timer benutzt hab, sagte mir der Compiler: RP6Control_10_Move2.c:467: error: 'delay_timer' undeclared (first use in this function)
MfG
blenderkid
blenderkid
02.01.2008, 15:32
>>Diese ganzen Definitionen findest Du in der Datei RP6RobotBase.h<<
ich benutze aber den M32.
also RP6ControlLib.h
Ach - sorry - hab ich nicht mehr dran gedacht.
Natürlich ist es auch dafür sinnvoll die entsprechenden Definitionen aus "RP6Control.h" zu verwenden, also z.B. PINA & ADC2 usw. - dann weiss man direkt wo was angeschlossen ist.
blenderkid
02.01.2008, 15:37
Es wird oben von Verion 1.3 erzählt. In der Dateien aus dem Link oben:
http://www.arexx.com/rp6/downloads/RP6Examples_20071016.zip
Steht immer version 1.1
radbruch
02.01.2008, 15:40
Hallo
Die Pins sollten eigentlich richtig sein, sonst würde die Funktion RC() nie beendet werden (oder es sind zufällig irgendwelche Eingänge die wechseln).
Wenn 11 zurückgemeldet wird, läuft irgendwas mit dem Timer schief. Ich würde mal delay_timer einbinden (das hat bei mir funktioniert) und dann weiter entscheiden:
extern uint8_t delay_timer;
und timer=0; durch Sleep(0); ersetzen.
Gruß
mic
@blenderkid:
Ja - oben dachte ich auch noch Du sprichst von der Lib für das Mainboard - die hat Version 1.3 - die Lib für das RP6Control Modul ist 1.1 - da ist der Timer natürlich auch schon mit drin.
Die Versionsnummern laufen getrennt, damit man sehen kann in welchen Teilen der Lib sich was verändert hat.
Die sind nur in einem Archiv, weil einige Dateien gemeinsam verwendet werden (I2C und UART Funktionen)
MfG,
SlyD
PS:
Was ist denn die Ausgabe mit dem Code den ich oben gepostet habe:
https://www.roboternetz.de/phpBB2/viewtopic.php?p=339987#339987
?
blenderkid
02.01.2008, 15:49
Ahh, klasse der delay_timer funktioniert sehr gut.
Danke an Alle.
MfG
blenderkid
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.