• Die Forumsregeln und Nutzungsbedingungen findet ihr in der Navbar unter Impressum !
    Bitte unbedingt beachten!
    Wie überall im Leben gibt es Spielregeln, so auch hier!
    Die Datenschutzerklärung zum DSGVO findet ihr ebenfalls in der Navbar unter Datenschutzerklärung !
    Hinweis nach DSGVO :
    Es ist hier keinerlei Angabe erforderlich. Alle Angaben in diesem Bereich sind öffentlich sichtbar und werden freiwillig gemacht. Mit einem Eintrag in diesem Bereich erkenne ich dieses an, und bestätige die Datenschutzerklärung zur DSGVO für das Forum gelesen zu haben.

    Danke
  • Hallo Gast, beschränke dich hier bitte auf den Bereich der Elektronik. Die Fahrzeuge oder Gebäude, wo diese Elektronik eingebaut wird bitte in dem passenden Fachbereiich behandeln. Auch wenn Teile des Projektes dadurch im Forum doppelt vorhanden sind! Danke.

Arduino Hilfe bei Arduino RC-Empfänger auslesen und motor mit PWM Steuern

Pat12-6

New member
Registriert
14.03.2015
Beiträge
7
Hallo Leute hat jemand von euch Erfahrung mit dem auslesen und Verarbeiten von Empfänger Signalen mit einem Arduino?


Wenn ja bitte ich um Hilfe und Tipps =)

Lg Patrick =)
 
Moin Patrick,

Jepp, habe ich.

Es gibt eine blockierende Variante per pulseIn() Funktion oder nicht blockierend per Interrupt.

Erzähl doch mal was du machen möchtest.
 
Moin Patrick,

Jepp, habe ich.

Es gibt eine blockierende Variante per pulseIn() Funktion oder nicht blockierend per Interrupt.

Erzähl doch mal was du machen möchtest.

danke für die schnelle Antwort,

also ich hab eine Funke mit 10 Kanäle und will einen Kran steuern, welcher mit Spindelhubzylindern betrieben wird.

ich habe es jetzt mal geschafft die 10 Kanäle auszulesen mit pulseln aber mehr auch nicht^^

was die Schaltung von den Motoren angeht die hab ich auch schon ich will ein 2 Wechsel Relais und ein Mostet mit PWM...#


Mein Problem ist eben das ich ned vom Auslesen des Kanals zum Ansteuern von egal welchen dingen komme^^

ich habe einen Code von der Seite http://www.rcarduino.tk nämlich den:

Code:
#include <debug.h>
#include <makros.h>
#include <RCReceive.h>

/*
  RC_Template.ino - Template for RC Receiver enabled programs - Version 0.2
  Copyright (c) 2012 Wilfried Klaas.  All right reserved.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

const byte PIN_RC = 2; 

// Der Empfänger
RCReceive rcReceiver;

void setup() {
  rcReceiver.attach(PIN_RC);

  // put your setup code here, to run once:
}

void loop() {
  // Aktuellen RC-Wert lesen
  rcReceiver.poll();

  // Nullpunktsbestimmung ?
  if (rcReceiver.hasNP() && !rcReceiver.hasError()) {
    doWork();
  } else if (rcReceiver.hasError()) {
    // Fehlerbehandlung failsafe oder sowas...
  }
}

void doWork() {
  byte value = rcReceiver.getValue();

  // put your main code here, to run repeatedly: 

}


Lg und danke schon mal =)
 
Also was das anzeigen mit dem Serial monitor angeht hab ich jetzt mal hinbekommen,

jetzt komm ich zu dem Punkt verarbeiten^^

Code:
#include <debug.h>
#include <makros.h>
#include <RCReceive.h>

/*
  RC_Template.ino - Template for RC Receiver enabled programs - Version 0.2
  Copyright (c) 2012 Wilfried Klaas.  All right reserved.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

const byte PIN_RC = 24; 

// Der Empfänger
RCReceive rcReceiver;

void setup() 
{
  Serial.begin(9600);
  rcReceiver.attach(PIN_RC);

  // put your setup code here, to run once:
}

void loop() {
  // Aktuellen RC-Wert lesen
  rcReceiver.poll();

  // Nullpunktsbestimmung ?
  if (rcReceiver.hasNP() && !rcReceiver.hasError()) {
    doWork();
  } else if (rcReceiver.hasError()) {
    // Fehlerbehandlung failsafe oder sowas...
  }
}

void doWork() {
  byte value = rcReceiver.getValue();

  // put your main code here, to run repeatedly: 
Serial.println(value);
}
 
Geschafft =)

Code:
#include <debug.h>
#include <makros.h>
#include <RCReceive.h>

/*
  RC_Template.ino - Template for RC Receiver enabled programs - Version 0.2
  Copyright (c) 2012 Wilfried Klaas.  All right reserved.

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

const byte PIN_RC = 24; //Signalanschluss
const int Motor1 = 2; //PWM-Motoranschluss
const int Rel1 = 25; //Relais 1 zum Umschalten zwischen Drehrichtungen

int Mot1 = 0;

// Der Empfänger
RCReceive rcReceiver;

void setup() 
{
  pinMode(Rel1,OUTPUT);
  Serial.begin(9600);
  rcReceiver.attach(PIN_RC);

  // put your setup code here, to run once:
}

void loop() 
{
  // Aktuellen RC-Wert lesen
  rcReceiver.poll();

  // Nullpunktsbestimmung ?
  if (rcReceiver.hasNP() && !rcReceiver.hasError()) {
    doWork();
  } else if (rcReceiver.hasError()) {
    // Fehlerbehandlung failsafe oder sowas...
  }
}

void doWork() 
{
  byte value = rcReceiver.getValue();

  // put your main code here, to run repeatedly: 
Serial.println(value);


  
  if (value > 122)
  {
    Mot1 =map(value,122,243,0,255);
    analogWrite(Motor1,Mot1);
  }
  if (value < 117)
  {
    Mot1 =map(value,117,0,0,255);
    analogWrite(Motor1,Mot1);
    digitalWrite(Rel1,HIGH);
  }
  else 
  {
    digitalWrite(Rel1,LOW);
  }
}
 
Moin Patrick,

grundsätzlich versuche ich ohne externe Libs aus zu kommen, da nie ganz klar ist was sie wie tun. Die Empfängerkanäle lese ich grundsätzlich selbst per Interrupt aus. So wird mein Programm nicht geblockt und ich habe die Kontrolle was passiert.

Das Auslesen per Interrupt ist eigentlich sehr einfach. Du legst einen Interrupt auf einen Pin der auslöst wenn ein Signalwechsel erfolgt. Du merkst Dir immer die micros() bei jedem IRQ. Von diesem Wert ziehst du die micros des letzten IRQ ab. Nun prüfst Du die Differenz. Ist diese kleiner 2500 Mikrosekunden handelt es sich um das auszuwertende HIGH Signal ist es größer ist es der LOW Bereich, der ist uninteressant.

Zusätzlich empfehle ich über die letzten 4 Werte einen Mittelwert zu bilden, so kannst Du den Wert glätten und ggf. auftretende Messfehler glatt bügeln.

Aus dieser Glättung geht ein Wert zur weiteren Verarbeitung hervor. Den packst Du in eine volatile Variable und kannst ihn dann in der loop() Funktion bearbeiten.

Sobald du mehrere Kanäle auslesen willst musst Du auf Interrupts gehen, da die pulseIn Funktion blockt und so Signale anderer Kanäle ungelesen bleiben während du einen bestimmten Kanal liest.
 
Ich glaub ich verstehe was du meinst aber geht das mit interupt nicht nur auf bestimmten Pins?

ich mein ich prüf die Programme jetzt am Mega, da hab ich ja eh praktisch unendlich pins aber ich will das dann mit dem Nano oder nanos machen aus Platzgründen.

was rätst du mir da zu tun?

danke schon mal für die Hilfe =)
 
Moin Patrick,

ich habe hier mal ein Minimalprojekt gebastelt zum Auslesen eines Kanals mit Ausgabe auf einen Servo.

Las es einfach mal auf Dich wirken.... ;)

Code:
#include <Servo.h>

			Servo		SpeedServo;

volatile	uint8_t		LastInterruptState					= PIND;

//	Variablen fuer die Geschwindigkeit
volatile	uint16_t	ReceivedSpeedValues[4]				= {1500, 1500, 1500, 1500};
volatile	uint16_t	ReceivedSpeedValuesSum				= 6000;
volatile	uint8_t		ReceivedSpeedValuesIndex			= 0;

volatile	uint32_t	LastSpeedChange						= micros();
volatile	uint16_t	LastSpeedValue						= 0;

#define                 PinSpeedServo		6			//	Servo Ausgang fuer die Geschwindigkeit		

void SpeedPositionInterrupt() 
{
	uint32_t    nMicros		= micros();
	uint16_t    nDifference  = (uint16_t)(nMicros - LastSpeedChange);

	if ( (nDifference > 900) && ( nDifference < 2100))
	{
		ReceivedSpeedValuesSum							-= ReceivedSpeedValues[ReceivedSpeedValuesIndex];
		ReceivedSpeedValues[ReceivedSpeedValuesIndex]	 = nDifference;
		ReceivedSpeedValuesSum							+= nDifference;
		ReceivedSpeedValuesIndex						 = ( ( ReceivedSpeedValuesIndex + 1 ) & 0x03 );	//	Index erhoehen und ggf. von 4 auf 0 springen
		nDifference										 = ( ReceivedSpeedValuesSum >> 2 );	//	durch 4 teilen

		LastSpeedValue  = nDifference;
	}
	LastSpeedChange	= nMicros;
}

ISR(PCINT2_vect)
{
	uint8_t	PinState	= PIND;
	uint8_t	PinChanges	= PinState ^ LastInterruptState;

	if (PinChanges & (1<<PCINT18))
		SpeedPositionInterrupt();

	LastInterruptState	= PinState;
}

void setup() 
{
	SpeedServo.attach( PinSpeedServo );

	PCICR |= (1 << PCIE2);
	PCMSK2 |= ( ( 1<<PCINT18) | (1<<PCINT19) | (1<<PCINT20) | (1<<PCINT21));

	sei();
}


void loop() 
{
	uint16_t	nServoValue = LastSpeedValue;

	//	do something with Servo value...

	SpeedServo.writeMicroseconds(nServoValue);
	delay (20);
}
 
Hehe Super danke =)

ich werd mir das morgen in der Arbeit durchlesen jetzt hab ich keinen Kopf mehr dazu^^


aber echt nett von dir Danke =)

Gruß und Schönen Abend Patrick
 
Also ich hab das ganze (meine Version) jetzt versucht für mehrere Kanäle zu schreiben.....

Ja und da merk ich genau warum ma da das Interrupt nehmen soll^^

is extrem Träge wegen der nullpunktbestimmung =(

muss ich mir dann morgen anschauen, ich hab gehofft ich komm drum rum^^
 
Moin Patrick,

Von einer Nullpunktbestimmung am Anfang habe ich Abstand genommen. Wenn die Trigger mal aus Versehen verstellt sind oder Schalter in der falschen Position stehen geht das ganze grandios schief.

Daher habe ich mich bei meinen Lösungen für einen expliziten Einlernmodus entschieden. Due Daten werden danach gespeichert. So bootet das Element sehr schnell da nur Parameter geladen werden müssen.

Da man ja nicht ständig die Funke oder den Empfänger ändert muss das Einlernen ja nur einmalig gemacht werden.
 
Ich klinke mich hier mal ein.

Habe gleiches vor, allerdings mit einer Zusatzfunktion.. ich möchte über einen Kipptaster Gangstufen simulieren die den Motor begrenzen sollen...
1. Stufe 0-20%
2. Stufe 0-40%
3. Stufe 0-60%
4. Stufe 0-80%
5. Stufe 0-100%

Ist das mit der "nicht blockierenden" Variante möglich? bis jetzt hatte ich beim Arduino nur Code Beispiele verwendet.. das Multitasking im Programmieren viel mir bis jetzt immer sehr schwer. (Früher Pocketviewer Programmiert mit OWbasic aber auch nur Ablaufprogramme.. nie Multitasking.)

Werde mir auf jedenfall das obrige Programm zur Brust nehmen und etwas probieren. ;(
 
Hallo Marc,
hast du dir schon Gedanken gemacht, wie du die Gangstufen dem Motor vermitteln möchtest.
Der Arduino kann ja deinen Motor nicht ansteuern. So viel Strom kann der nicht ab.
Oder willst du den normalen Fahrtregler benutzen und ihn nur bei den entsprechenden % blockieren, damit man dann nicht schneller fahren kann?
Den wirklichen Sinn, kann ich darin noch nicht erkennen, da ja auch das Motorgräuch vom Soundmodul nicht angepasst wird.
Das müsste ja bei jeder Gangstufe auch wieder ganz unten anfangen.
 
Ja der Fahrtenregler soll das dann übernehmen.

Das Beier Soundmodul kann die Schaltstufen genau nach dem Arduino übernehmen.. heißt das dass Soundmodul im 1. Gang zb. 0-20% geht und AB 20% 2. Gang. wie ein Manuelles Getriebe sozusagen.. durch den Taster blockiere ich ja die Fahrstufen sodass der Motor im 1. Gang nur 20% Maximalleistung hat.. das ist die Schwelle für das beier Soundmodul.. sobald ich hochschalte und schneller werde Schaltet das Soundmodul ja in den nächsten Gang.

Sollte eig. funktionieren..
 
JA, ok.
Aber trotzdem ist das ja genau das Gegenteil von dem was man von einem Getriebe erwartet.
Im Ersten Gang soll ja die durch die Untersetzung die Kraft erhöht werden mit dem Nebeneffekt, dass die Drehahl absinkt.
Du produzierst ja genaus das Gegenteil du reduzierst die Leistung im 1. Gang auf 20%. Wenn der einen steilen Berg rauf will musst du ja hochschalten, damit du den hochkommst. :mama
 
Genau deswegen hab ich ja ein Motorgetriebe gesucht was eine gute Höchstgeschwindigkeit und Kraft unten rum hat. Dadurch kann man ja egal in welcher Stufe den Berg hoch fahren. Die Stufen begrenzen sich ja nicht untenrum (noch nicht). Vielleicht kommt da auch noch was, wenn es denn erstmal funktioniert.
 
wenn du eine Leistungsmodul anstatt des Fahrtenreglers nimmst kann man den Strom mitmessen. Durch den Arduino kann dann der volle Motorstrom zugelassen werden. Die Abregelung müsste dann über den PWM erfolgen. Nach Messung der Motordrehzahl kann man das über einen PI Regler hinbekommen.

Nichts desto trotz ist ein Getriebe aber besser :)
 

Servonaut
Zurück
Oben Unten