Seite 9 von 9

#121 Re: Arduino im Modellbau

Verfasst: 11.05.2015 17:59:47
von helifan10
Asche auf mein Haupt! :oops:
Hatte ich vergessen anzupassen als ich GND und Vin getauscht habe.
Ist natürlich richtig, die LEDs müssen natürlich gedreht werden.

#122 Re: Arduino im Modellbau

Verfasst: 15.05.2015 22:30:43
von Husi
helifan10 hat geschrieben:also geplant sind mal drei Eingänge. Ich möchte eigentlich die Standardbibliothek nutzen.
Mittlerweile habe ich das Einlesen der Empfängerkanäle ohne externe Bibliothek versucht. Siehe da, es ist einfacher als gedacht. Allerdings habe ich gelesen, das bei gleichzeitiger Ausgabe mittels der Servo-Bibliothek ungleiche Zyklen entstehen könen. Schuld sollen die Interrupts sein, die die Abarbeitungszeit der Schleifen durcheinander wirbeln können.

Code: Alles auswählen

 // Empf�nger Kan�le auslesen und via Serial wieder ausgeben.

const int BAUD_RATE       = 9600;
const int PIN_RC_KANAL_01 = 3;  // Ausgangs Kanal am Empf�nger 01 wird an die PWM Leitung 3 angeschlossen.
const int PIN_RC_KANAL_02 = 4;  // Ausgangs Kanal am Empf�nger 02 wird an die PWM Leitung 4 angeschlossen.
const int PIN_RC_KANAL_03 = 5;  // Ausgangs Kanal am Empf�nger 03 wird an die PWM Leitung 5 angeschlossen.
const int DELTA           = 7;  // Rauschunterdr�ckung bei der Ausgabe auf Serial.

int Kanal_01;        // Variablen erzeugen, in denen der jeweilige Empf�nger-Kanal gespeichert wird.
int Kanal_02;
int Kanal_03;
int Kanal_01_alt;    // hier liegen dann die alten Werte, die zur Rauschunterdr�ckung auf Serial gebraucht werden.
int Kanal_02_alt;
int Kanal_03_alt;


void setup() {
  pinMode(PIN_RC_KANAL_01, INPUT);
  pinMode(PIN_RC_KANAL_02, INPUT);
  pinMode(PIN_RC_KANAL_03, INPUT);
  
  Serial.begin(BAUD_RATE);
  Serial.println("Mirkos Empfaenger Test 01");
}


void Werte_auf_Serial_ausgeben() {
  int diff;            // Differenz des neuen und alten Wertes zur Rauschunterdr�ckung bei der Serial Ausgabe
  int neu_schreiben;   // steuert, ob die Textausgabe erfolgen mu�, oder eben nicht
  
  neu_schreiben = 0;   // Null hei�t, die Werte sind noch gleich => keine neue Ausgabe
  
  diff = abs(Kanal_01 - Kanal_01_alt);      // Absolut Wert von der Differenz der alt und neu-Werte bilden.
  if (diff > DELTA) { neu_schreiben = 1; }  // Wenn Differenz gr��er als Raussperre, dann Text neu ausgeben.
  
  diff = abs(Kanal_02 - Kanal_02_alt);
  if (diff > DELTA) { neu_schreiben = 1; }
  
  diff = abs(Kanal_03 - Kanal_03_alt);
  if (diff > DELTA) { neu_schreiben = 1; }
  
  if (neu_schreiben == 1) {
    Serial.print("Kanal 01: ");
    Serial.println(Kanal_01);
    Serial.print("Kanal 02: ");
    Serial.println(Kanal_02);
    Serial.print("Kanal 03: ");
    Serial.println(Kanal_03);
    Serial.println();
  }
  
  Kanal_01_alt = Kanal_01;  // den aktuellen Wert in den alt Speicher schreiben, weil jetzt wieder neu eingelesen wird.
  Kanal_02_alt = Kanal_02;
  Kanal_03_alt = Kanal_03;
}

void loop() {
  Kanal_01 = pulseIn(PIN_RC_KANAL_01, HIGH, 25000);  // Empf�nger Kanal 01 einlesen.
  Kanal_02 = pulseIn(PIN_RC_KANAL_02, HIGH, 25000);  // Empf�nger Kanal 02 einlesen.
  Kanal_03 = pulseIn(PIN_RC_KANAL_03, HIGH, 25000);  // Empf�nger Kanal 03 einlesen.
  
  Werte_auf_Serial_ausgeben();
} 
Viele Grüße
Mirko

#123 Re: Arduino im Modellbau

Verfasst: 15.05.2015 22:45:49
von Crizz
Schau dir mal den Quellcode von MultiWii an, vielleicht hilft dir das weiter. Damit läßt sich auch ein PPM-Summensignal auf PWM-Einzelkanäle ausgeben ohne das du wirkliche Probleme zu erwarten hast, ist ne Grundfunktion die wegen der Gimbal-Ansteuerung mit drin ist.

#124 Re: Arduino im Modellbau

Verfasst: 15.05.2015 23:52:25
von Husi
Crizz hat geschrieben:Schau dir mal den Quellcode von MultiWii an, vielleicht hilft dir das weiter.
Das werde ich auch, wenn es so weit ist. Zuerst möchte ich (zumindest) alle Grundlagen von der Basis her einmal selbst im Texteditor geschrieben haben. Mir geht es zumindest so, das ich es dann wirklich verstanden habe.
Natürlich gibt es dabei (wie immer) verschiedene Herangehensweisen.
Mirko

#125 Re: Arduino im Modellbau

Verfasst: 16.05.2015 08:04:58
von the-fallen
Wenn die Servobibliothek Interrupts benutzt, dann vermute ich, dass sie selbst (per Software "BitBanging") ein PWM Signal erzeugt. Dabei könnte der Atmega328P auf 6 Pins ein PWM per Hardware erzeugen (die PWM Pins).

Die analogWrite() Funktion macht genau das. Will man die Frequenz verändern muss man allerdings ein paar Register einstellen (weg von den Default-Werten). Dann kann man übrigends auch unter gewissen Umständen feinere Abstufungen als 0-255 erzeugen wenn man muss.

Hier gibt es die ersten Infos dazu:
http://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM

Da das PWM Signal auf den PWM Pins im Chip und nicht in der Software erzeugt wird stört es nicht den Ablauf deines Programm es und wird andersherum natürlich auch nicht durch dein Programm gestört. Es liegt immer ein sauberes PWM an selbst wenn du in deinem Code selber ein Interrupt benutzt.

#126 Re: Arduino im Modellbau

Verfasst: 18.04.2016 21:34:52
von helifan10
Hallo zusammen,

habe nun endlich meine Schaltung von Post 110 in den Rumpf eingebaut.
Habe aber die Belegung der Pins was Funktionen und Beleuchtung betrifft noch einmal angepasst.
Habe jetzt ca. 3 Stunden probiert und Fehlersuche betrieben.
Bis ich darauf gekommen bin, das bei Ausgabe im seriellen Monitor die ersten beiden Pins belegt werden.
Die Auswertung der beiden Sendersignale wollte überhaupt nicht klappen. Im Monitor wurde nur Müll angezeigt.
Jetzt funzt es aber einwandfrei. Manchmal sind es kleine Dinge auf die man erst mal kommen muss :shock:

- Positionsbeleuchtung und Landescheinwerfer über normalen Schalter am Heli einschalten ( onkl. Servo fahren )
- Doppelblitz ACLs
- Wechsellicht Scheinwerfer am Bug
- Taster an Sender wählt auf MP3 Player nächsten Titel an
- Schalter an Sender (drei Stellungen) schaltet später Zusatzfunktionen Winde oder Wasserpumpe für Löschtank

Hier mal mein aktueller Scatch. Eventuell kann sich ja noch jemand was abkupfern.
Wobei Ihr beim Thema Arduino kompetenter seit als ich.

Programm Bell UH-1H RAVEN 3

#include <Servo.h>

Servo SERVO1;
Servo SERVO2;
Servo SERVO3;
int Kanal7;
int Kanal8;

void setup() {

pinMode(0, OUTPUT); // Legt OUT 0 als Ausgang Leiste Pin7 ACL Unten fest > Blinkfrequenz
pinMode(1, INPUT); // Eingang Kanal7 von Sender
pinMode(2, INPUT); // Eingang Kanal8 von Sender
pinMode(3, INPUT_PULLUP); // Legt IN 3 als Eingang Schalter Beleuchtung fest
pinMode(4, OUTPUT); // Legt OUT 4 als Ausgang Leiste Pin 6 ACL Oben fest > Blinkfrequenz
pinMode(5, OUTPUT); // Legt OUT 5 als Ausgang Leiste Pin 5 Scheinwerfer Unten rechts fest
pinMode(6, OUTPUT); // Legt OUT 6 als Ausgang Leiste Pin 4 Scheinwerfer Unten links fest
pinMode(7, OUTPUT); // Legt OUT 7 als Ausgang Leiste Pin 3 Landescheinwerfer und Positionslampen fest
pinMode(8, OUTPUT); // Legt OUT 8 als Ausgang Relais 1 fest > Motor Wasserpumpe Ein
SERVO1.attach(9); // Legt PWM OUT 9 für das Servo des Landescheinwerfers fest.
SERVO2.attach(10); // Legt PWM OUT 10 für das Servo des Lasthaken fest.
SERVO3.attach(11); // Legt PWM OUT 11 für das Servo des Winde fest.
pinMode(12, OUTPUT); // Legt OUT 12 als Ausgang Relais 2 fest > Vorwärts MP3 Player
pinMode(13, OUTPUT); // Legt OUT 13 als Ausgang Relais 3 fest > Play MP3 Player

//Serial.begin(9600); // Startet die Datenübertragung mit 9600 Baud
}

void loop() { // Loop starten// Positionsbeleuchtungen einschalten,

if (digitalRead(3) == LOW) { // Schalter am Input 3 auf Platine schaltet Beleuchtung ein
digitalWrite(7,HIGH); //Schaltet Landescheinwerfer und Positionslampen ein
}
else {
digitalWrite(7,LOW); //Schaltet Landescheinwerfer und Positionslampen aus
}

// Relais K1 9V Ausgang für Pumpe

if (digitalRead(3) == LOW) {
digitalWrite(8,HIGH); //Schaltet Relais K1 ein.
}
else {
digitalWrite(8,LOW); //Schaltet Relais K1 aus.
}

// MP3 Player vorwärts schalten Relais K2

Kanal7 = pulseIn(1, HIGH, 25000); //Ließt Eingangssignal am Input 1 an Platine ein Taster Ruhestellung ca.1100.
//Serial.print("RX-K7 (ms): ");
//Serial.println(Kanal7);
if (Kanal7 >=1600) { //Wenn Eingangssignal größer 1600 Signal ein Titel weiter
digitalWrite (12,HIGH); //Schaltet Relais K2 am Ausgang 12 Vorwärts am MP3 Player
}
if (Kanal7 <=1500){
digitalWrite (12,LOW);
}

// Schalten Relais K3

Kanal8 = pulseIn(2, HIGH, 25000); //Ließt Eingangssignal am Input 2 ein Stellung 1 ca.1100, Stellung 2 ca.1600, Stellung 3 ca.1900
if (Kanal8 >=1200) { //Wenn Eingangssignal
digitalWrite (13,HIGH); //Schaltet Relais K2 am Ausgang 13
}
if (Kanal8 <=1200){
digitalWrite (13,LOW);
}

// ACL einschalten und blinken lassen

unsigned long time = millis() % 2000; // Zeitachse zum schalten der ACL Beleuchtung

if (time <= 80 || time >=160 && time <=240) { // Schaltet zwischen zu den angegebenen Zeiten ACL Oben ein
digitalWrite(4, HIGH); // Ausgang ACL Oben ein
}
else {
digitalWrite(4, LOW);
}
if (time >= 1000 && time <= 1080 || time >=1160 && time <=1240) { // Schaltet zwischen zu den angegebenen Zeiten ACL Unten ein
digitalWrite(0, HIGH); // Ausgang ACL Unten ein
}
else {
digitalWrite(0, LOW);
}

// Bugscheinwerfer einschalten und blinken lassen
if (time <= 900) { // Schaltet innerhalb der ersten 900ms Bugscheinwerfer Links ein
digitalWrite(6, HIGH); // Ausgang Bugscheinwerfer Links
}
else {
digitalWrite(6, LOW);
}
if (time >= 1000 && time <=1900) { // Schaltet zwischen 1000ms und 1900ms Bugscheinwerfer Rechts ein
digitalWrite(5, HIGH); // Ausgang Bugscheinwerfer Rechts
}
else {
digitalWrite(5, LOW);
}

// Servo Landescheinwerfer ein/ausfahren und Landescheinwerfer ein/ausschalten

if (digitalRead(3) == LOW) { // Abfrage Schalter Input 3 auf Platine
SERVO1.write(140); // Servo fährt auf Position 140 Grad Landescheinwerfer ausfahren
delay(10); // Verzögerungszeit Landescheinwerfer einschalten
digitalWrite(6,HIGH); // Einschalten Landescheinwerfer am Ausgang 6
}
else
{
SERVO1.write(20); // Servo fährt auf Position 10 Grad Landescheinwerfer eingefahren
digitalWrite(6,LOW); // Ausschalten Landescheinwerfer am Ausgang 6
}

} //Programmende

#127 Re: Arduino im Modellbau

Verfasst: 20.04.2016 18:02:08
von Proto
Ich hab sowas ähnliches auch mal gebaut und dafür das SUMD von Graupner genutzt. Hab grad einen Listener via Optokoppler mit über ein T-Stück ans Datenkabel zum Stabi gehängt. Recht Simpel da es ein Standard UART mit 115200 boud im 8N1 ist. Bietet sich also quasi an einfach den Hardware UART RX zu nutzen. Hier hat es einer Entschlüsselt:


Programmausschnitte wie ich das damals genutzt hab:

Simple Abfrage ob Byte 1 Normal Boot oder Failsave ist und Byte 0 die Graupnerkennung. Somit bestimme ich den Anfang des Array rc_rawdata[]

Code: Alles auswählen

ISR(USART_RX_vect) 
{
	static unsigned char rc_byteposition;
	rc_rawdata[rc_byteposition]=UDR0;

	if((rc_rawdata[rc_byteposition]==0x81)|(rc_rawdata[rc_byteposition]==0x01)&&(rc_rawdata[rc_byteposition-1]==0xA8))
	{
		rc_rawdata[0]=rc_rawdata[rc_byteposition-1];
		rc_rawdata[1]=rc_rawdata[rc_byteposition];
		rc_byteposition=1;
		rc_newdata=1;
	}		
	rc_byteposition++;
}
Auswertung (noch ohne Checksum, die hab ich damals nicht fertig gestellt weil ich mir irgendwann dachte das es für ne LED Steuerung eigentlich egal ist. Hier hab ich die Rohdaten ins Format 0-100% umgerechnet.

Code: Alles auswählen

void uart_interpret(volatile unsigned char *last_channel_count, volatile unsigned char rc_rawdata[],unsigned int *rc_data, volatile unsigned char *rc_newdata)
{
	unsigned char data_ok=0;
	*last_channel_count=rc_rawdata[2];
	if (*last_channel_count<4)
		*last_channel_count=4;
	if(*rc_newdata==1)	
	{														//Nur wenn neue Daten vorhanden sind werden diese auch ausgewertet.
		data_ok=uart_check(rc_rawdata);
		if(data_ok==1)
		{
			for (unsigned char byte = 0; byte < *last_channel_count; byte++ )				//Wird so oft verrechnet wie der Empfänger uns über die Anzahl im letzten Telegram angegeben hat
				rc_data[byte] = (((unsigned long)(rc_rawdata[(byte << 1) + 3]) << 8) + rc_rawdata[(byte << 1) + 4]) / 38.4 - 187.5;		
/*
Zur einfacheren Weiterverarbeitung werden alle Werte vom ursprünglichen Wertebereich Dezimal 7200 (bei -150% in der Funke) über Dezimal 12000 (0% in der Funke) bis Dezimal 16800 (+150% in der Funke) in 0-255 umgerechnet.
Effektiver Wertebereich erstreckt sich von Dezimal 46 (bei -100% in der Funke) über Dezimal 127 (bei 0% in der Funke) bis Dezimal 209 (bei +100% in der Funke). Das ganze ist nicht sehr genau (Rundungsfehler) aber 
völlig ausreichend. Wer erkennt schon mehr als 200 verschiedene Stufen für die jeweilige Farbe. Wir Männer sehen höhstens 5 :-) 
Formel ergibt sich: (16800 - 7200) / 255 (neuer Bereich 0-100%) - 191 (Offset entfernen)			
rc_data Kanalzuordnung ist wie folgt:								
rc_data[0] == Kanal 1
rc_data[1] == Kanal 2
rc_data[n] == Kanal n
*/

			*rc_newdata=0;															//Falls neue Daten da waren wird dieser Indikator wieder abgearbeitet zurückgesetzt
		}
	}
}
Vielleicht kanns ja wer brauchen oder wills verbessern. Potential ist da genug, da ich auch nur Hobbybastler bin :-)

Grüße
Christian