Jump to content
Usertreffen 2024: 29.5.-2.6. | Anmelden bitte bis 30.4. ×
Schiffsmodell.net

arduino als Lichtsteuerung


Guest

Recommended Posts

Über das Kostenproblem haben sich schon verschiedene Leute Gedanken gemacht.

 

Je nach Projekt reichen nur wenige externen Bauelemente aus, um mit dem ATMega (dem "Hirn" des Arduino) eine funktionsfähige Schaltung zu bekommen. Stichwort bei Google ist "arduino barebone".

Oder hier ist ein ganz guter Einstieg: http://todbot.com/blog/2009/05/26/minimal-arduino-with-atmega8/

 

Einzelne ATMegaX bekommt man auch schon ab 1,50 Euro, mit Bootloader kosten sie dann etwas mehr (5 Euro). Du kannst also das komfortable Arduino-Board verwenden, um dein Projekt zu testen und dann später auf eine feste Minimalvariante mit passenden externe Beschaltung (für LED z.B. mit Widerständen) umsteigen. Die lässt sich dann auch auf Lochraster aufbauen.

 

Und noch zwei passende Links zum Abschluss:

Minimalboard (allerdings noch in der Entwicklung):

Lösung ganz ohne Board: http://www.geocities.jp/arduino_diecimila/obaka/project-2/index_en.html

 

Gruß, Kai

Edited by lab
Link to comment
  • Replies 58
  • Created
  • Last Reply

Top Posters In This Topic

  • Kessl

    9

  • hoppppla

    6

  • lab

    4

Top Posters In This Topic

Posted Images

Guest willie
Ja, interrupts sind fraglos schöner, sie können aber mehr Probleme verursachen als lösen wenn man nicht wirklich genau weiß was sie machen. Wird bei Signalfalttern während eines interrupts ein weiterer aufgerufen und noch noch bevor der abgehandelt wurde der nächste ist irgendwann schluss und der mc wird nur noch ein rotes Lichtchen zeigen. Wer mit Interrupts umgeht sollte schon wissen wie er während eines interrupt handels weitere interrupts verhindert und er sollte auch wissen das diese handles kurz sein müssen und das sich z.B. andere Funktionen nicht ohne weiteres aus einem Handler heraus aufrufen lassen usw. usf.

 

Für Schiffe halte ich max. 40 ms Auszeit, selbst für die Steuerung, allemal für vertretbar und der Code ist definitiv übersichtlicher als ein interrupthandler, weil einfach linear. Wer das aber in schön sehen will darf mal einen Blick in die Software des Multiwii werfen. Die lesen die Kanäle (inzwischen) auch mit interrupts aus und das lässt sich praktisch 1:1 kopieren wenn daran interesse besteht. Es ging mir auch eigentlich nur darum zu sagen: Es funktioniert auch mir pulsein und es gibt einen Unterschied zwischen micro- und millisekunden. Aber ja, es geht eleganter.

Na soviel umständlicher ist es nun nicht. s. mein Quelltext weiter oben.

Da arbeite ich genau mit dem Interrupt. Richtig ist, man muss wissen was man da tut. Das mit dem Interrupt sperren haste recht. Geht aber auch einfach:

void RcIntHandler() {
 cli();
 static unsigned long RcTemp = 0;
 if ( digitalRead(2) ) { 
   RcTemp = micros(); 
 } 
 else {
   RcValue = micros() - RcTemp; 
 }
 sei();
}

Mit den Hardware Interrupts geht nur auf Pin 2 und 3 (INT0, INT1). Es gibt aber eine Lib mit dem man auf fast jeden Pin einen ChangeInterrupt bekommen kann. Ich empfehle einfach mal das hier:

http://arduino.cc/playground/Code/Interrupts

Link to comment

Ich habe nie gesagt das es schwer ist, nur das Interrupts durchaus eine beliebte Fehlerquelle sein können, wenn man sich nicht halbwegs im klaren ist was in diesem Moment mit der Hardware passiert. Für dein Beispiel sollte rcvalue z.B. als volatile deklariert werden, macht man dies nicht kann es zu wirklich lustigen Ergebnissen führen.

 

Auch wäre es noch etwas schöner wenn die Berechnung außerhalb des Handlers durchgeführt werden würde, der Handler selbst also nur die Zeit speichert zu der das Signal gefallen oder gestiegen ist. micros() fängt nach grob einer Stunde wieder bei 0 an, will sagen die uint32 läuft über. Im schlimmsten Fall reagiert das Boot dann nach 60 min einfach nicht mehr auf Steuerbefehle. Wie ich c++ kenne wird er RcValue = micros() - RcTemp; auch dann ausführen wenn micros() - RcTemp negativ wird und rcvalue eine uint ist, dennoch gehört es zum sauberen programmieren diesen Fehler abzufangen und spätestens jetzt wird der Code deutlich aufwendiger als mit pulsein. Und bitte nicht falsch verstehen, ich will nicht sagen das du nicht mit interrupts umgehen kannst, aber derjenige der diesen Thread gestartet hat hat glaube ich vor 4 Jahren das letzte mal programmiert und sich vor einigen Tagen seinen ersten Microcontroller bestellt. Manchmal ist weniger mehr, und wir sind hier in einem Forum für Schiffe, selbst wenn das auslesen der RC Signale 0,5 sec dauern würde, ich glaube selbst das würde man bei den trägen Servos die "wir" meist verbauen und bei den Beschleunigungen die Schiffe (besonders wenn sie 30 Lichter über 3 Masten verteilt haben) so an den Tag legen kaum auffallen.

Link to comment

Äh - es ging ja eh nicht um Servofunktionen, wo eine evtl. zeitkritische Steuerreaktion erfolgen muß, sondern um Lichsteuerung.

Läuft ja für mich fast schon in Richtung Multiswitch-Modul.

 

Übrigens habe ich irgendwann mal im RC-Line ein nettes Tutorial zum AVR

und Servoansteuerung gesehen. Wollte ich mir mal antun, habe es aus Zeitgründen noch nicht geschafft. Schau'n wir mal....

 

viele Grüße

Holger

Link to comment
Guest willie

das volatile ist irgendwie nicht hier im Code gelandet, steht aber im original davor.

 

Die Berechnung geht sehr schnell. Ja der Überlauf tritt nach ca. 70Min ein, da aber hier ein Impuls von 1-2ms gemessen wird, müßte der Überlauf genau in diesen Bereich fallen. Und selbst wenn ein Rollover passiert, wird die Dauer trotzdem richtig berechnet. (unsigned ...)

Beispiel: (ich nehm mal byte weil kürzer) (S Startzeit, D Dauer, A aktuelle Zeit) Der Impuls ist 15 wasauchimmer lang.

S = 15, D = A - S = 30 -15 = 15. Korrekt

S = 250, D = A - S = 9 - 250 = -241 -> 15 (256- 241) Also auch korrekt.

Trick ist, der Überlauf in micros wird durch den Überlauf in der Berechnung aufgehoben. Wichtig ist aber das alles unsigned in der Berechnung ist, sonst geht's nicht...

 

Beim PulsIn haste dafür andere Probleme. Die Genauigkeit ist nämlich recht "empirisch".

wiring_pulse.c
...
return clockCyclesToMicroseconds(width * 21 + 16)

Macht sich in der Praxis beim Messen von RC Impulsen kaum bemerkbar.

Und auch beim PulsIn mußt du den Wert auf Plausibilität prüfen, auch da können Störimpulse, Ausfall und sonstiges mit einwirken. Der Aufwand ist da ungefähr gleich.

 

Es gilt für beide Varianten:

Für Motor/Rudersteuerungen müßte man eh deutlich mehr Aufwand in die Überprüfung des Signales selber stecken. Vor allem würde ich da auf Plausibilität prüfen. Und zwar auch zeitlich, damit kurze Störimpulse unterdrückt werden können. Beispiel, erst nach 5 geänderten gleichen Impulsen (mit Jitter) wird die Änderung an die eigentliche Steuerlogik übertragen. Sowas eben. Für eine einfache Lichtsteuerung würd ich den Aufwand nicht machen...

 

Ich denke übrigens der Threadersteller ist längst abgetaucht.

Link to comment

...

Übrigens habe ich irgendwann mal im RC-Line ein nettes Tutorial zum AVR

und Servoansteuerung gesehen.

...

 

Ja, genau - siehe Link von Hellmut ein paar Beiträge weiter oben.

Das habe ich vor einigen Jahren dort erstellt. Vielleicht nicht mehr top-aktuell, aber auch heute noch brauchbar.

 

...

Ich denke übrigens der Threadersteller ist längst abgetaucht.

...

 

Das befürchte ich auch. Und wenn man die Experten-Beiträge hier mal mit Einsteigeraugen liest, fällt mir dazu auch der ein oder andere Grund ein... ;)

 

Ihr kennt euch fraglos hervorragend mit yC´s aus (sicher auch besser als ich!), aber es wäre in diesem Fall halt angebracht, sein Wissen einmal noob-verständlich rüberzubringen und solche "Experten-Diskussionen" zu vermeiden. Die versteht eh kaum einer... :keineIdee:

 

Ja, die Beiträge sind "On-Topic", aber leider für den TO ziemlich nutzlos, wie ich vermute... wir wissen nicht einmal, ob er überhaupt "C" kann.

 

Und noch einmal kurz zur Erläuterung für die Einsteiger, alle gezeigten Codes werden wohl funktionieren, egal, ob auf einem Arduino oder direkt im nackten Chip.

 

Atmel bleibt Atmel...

 

Grüße

 

Torsten

Link to comment
es wäre in diesem Fall halt angebracht, sein Wissen einmal noob-verständlich rüberzubringen

Wenn du eine bestimmte Frage hast, nur raus damit. Ich bin zwar sicher kein Experte, aber den einen oder andere Fehler habe ich sicher schon gemacht und kann davor warnen ;). Was das mit dem noob-verständlich angeht gibt es aber stellenweise kleinere Probleme. Was genau ein Interrupt ist, was er macht und vor allem was die CPU macht wenn er ausgelöst wird ist nämlich nicht wirklich leicht zu erklären und erfordert schon einiges an Einsicht in die interne Funktionsweise von Computern. Auf der anderen Seite ist das relativ unnötig weil es noch immer die bewährte Version: Trial & error gibt. Und sollte selbst das schief gehen kann man klauen, das WIICopter Projekt ist Source-offen und geht es nur ums auslesen der Fernsteuerung, die Jungs haben den Quelltext für Summensignalempfänger, für normale Mehrkanalempfänger und sogar für S-Bus. Und sind wir mal ehrlich, es geht hier um Modelle. Selbst wenn man einen Fehler macht, das worst-case Szenario liegt irgendwo zwischen einer Delle im Rumpf und rausschwimmen weil sich nichts mehr bewegt. Wägt man das ab gegen die Möglichkeiten die sich eröffnen, z.B. selbstgebaute Mehrkanalschalter, Lichter die blinken und die bei Dunkelheit automatisch anschalten, Sensoren die Temperatur, Spannung und sogar Wassereinbruch messen, Potentiell einem Autopiloten der, mittels GPS und Kompass, eingelernte Routen 2h am Stück abfährt, Y-Mischer für 2 und mehr Motoren, zwei Servos für die 2 Ruder auf einem Kanal und damit Potentiell eine Bremse oder der Test des Lursson? Effekts, ... ich glaube das Risiko wird allemal von den Vorteilen aufgefangen. Natürlich sollte die Sache mit dem Autopilot nicht das zweite Projekt nach dem blinken-lassen einer LED sein, aber die Möglichkeiten die sich eröffnen sind enorm und es war nie leichter als heute.

Link to comment

Da bin ich vollkommen bei Dir, und wenn man einmal angefangen hat, sich mit den Käfern zu beschäftigen, ist der Suchtfaktor schon ziemlich groß! :mrgreen:

 

Es ging mir bei meiner Ansage nur darum, den TO und ein paar andere mitlesende Neulinge nicht gleich mit Fachdiskussionen plattzuwalzen.

Wenn man sich nicht auskennt, sind solche Beiträge eher kontraproduktiv, weil sie nur unnötig abschrecken.

 

"Trial & Error" ist das Stichwort - einfach mal einfach anfangen, ausprobieren, erste Erfolgserlebnisse geniessen... kompliziert wird´s dann meist von alleine. :mrgreen:

 

Aber keine Sorge, ich versteh euch schon einigermaßen... ;)

 

Grüße

 

Torsten

Link to comment

Danke erstmal für eure rege Diskussion. Ich habe mir inzwischen den Arduino Uno Rev 3 zugelegt und auch schon ein wenig damit rumgespielt. Sicher können die Profis unter euch eine Lichtsteuerung "für'n Appel und 'n Ei" "herstellen". Andere wiederum geben sehr viel mehr Geld aus als diese 20€.

 

Nun, von Lichtsteuerung habe ich nicht wirklich viel Ahnung und ich habe auch nicht vor darin Profi zu werden. Ich möchte einfach nur das Ziel erreichen, die ca. 60 LEDs auf meinem Schiff so zu schalten wie ich das gerne hätte.

 

Also: Programmcode - kein Problem. Zusatzmodul (Shield) habe ich irgendwie kein brauchbares für mich gefunden. Muß ich mir wohl selber löten. (Die Ausgänge können max. 20mA schalten, bei mir sollen aber bis zu 20 LEDs an einen Ausgang -> Transistor)

Und auch wenn die Frage nach wie vor blöd klingt... wie zum Geier schließe ich die 3 Kabel vom Empfänger (+ - und Impuls) an den Arduino an? Ich habe mich schon ca. 5h durch diverse Foren geprügelt aber kein anschauliches Material bzw. ein Anschlußmuster gefunden...

 

Für einen sachlichen Hinweis wäre ich daher sehr dankbar!

 

Kleiner Nachtrag noch: Ich wollte hier keine Fachdiskussion auslösen, es ging lediglich darum ob jemand mit arduino in Schiffsprojekten Erfahrung hat. ;)

Link to comment
Guest willie

Anschliessen ist auch einfach.

+ und GND vom RC-Kabel gehen auf +5V und Gnd vom Arduino. (Powerleiste neben der Analogleiste.)

Jetzt kommt es darauf an, ob du mit pulseIn oder attachINterupt arbeitest.

Bei pulsIn schliesst du das Datenkabel vom Empfänger an einen beliebigen D oder auch A Pin vom Arduino an.

2-12 (0,1 würd ich auch nicht nehmen,da geht die serielle SChnittstelle drüber, 13 ist die Board-LED, die würd ich dafür auch nicht nehmen) sind die Pins auf den langen Leisten (in den offiziellen Bildern oben)

A0-A5 (wenn als digital Eingang oder Ausgang verwendet heißen die 14-19) sind die A Pins neben der Versorgungsleiste. (in den offiziellen Bildern unten)

 

Im setup() dann ein

pinMode(X, INPUT); // Pin als Eingang
digitalWrite(x,HIGH); // Interner Pullup eingeschaltet

X ist der verwendete Pin.

Im loop kannst dann per

RcValue = pulseIn(X, HIGH, 1000); 

die Pulslänge messen.

 

Wie's mit dem Interrupt funktioniert hab ich weiter oben im Thread gepostet. Allerdings würd ich in deinem Fall beim pulsIn bleiben.

 

Zum Treiben: Es gibt Bustreiber die können evt. sogar deine Last direkt treiben. Aber eine einfache BC547-Treiber sollte bis 100mA auch reichen. Falls es mal knapp wird mit dem Ausgängen, das hier hilft:

http://arduino.cc/en/Tutorial/ShiftOut

Link to comment
Anschliessen ist auch einfach.

+ und GND vom RC-Kabel gehen auf +5V und Gnd vom Arduino. (Powerleiste neben der Analogleiste.)[/url]

Sollte dein Empfänger den Strom von einem BEC bekommen würde ich dringend davon abraten das + Kabel zu verbinden und lediglich die Masse und das Signal verbinden.

 

Was Treiber angeht: Nimm gleich den da. Das Teil kostet nur unwesentlich mehr als gar nichts und du schaltest damit gleich 8x 500 ma und er lässt sich ziemlich einfach auf Cu Platinen löten und auf breadboards nutzen.

Link to comment
Guest willie

Da niergends was davon steht, daß der Arduino von woanders seine Spannung bezieht, bin ich davon ausgegangen, das er seine Spannung mit aus dem Empfänger kommt.

Haste aber recht, wenn der Arduino direkt aus einem Akku gespeist wird, dann sollte man + nicht verbinden.

 

@Kessl: Genau den suchte ich, hab ihn aber nicht gefunden...

Link to comment
Guest willie

Hupps,

hab's gestern abend noch mal schnell ausprobiert. Dabei ist mir ein kleiner Fehler aufgefallen.

RcValue = pulseIn(X, HIGH, 1000[color=Red][b]00[/b][/color]);

muss es heissen. Das wären dann 100ms max. Wartezeit. 1000 is zu wenig, schliesslich sendet der Empfänger nur alle 20ms...

Link to comment
Da niergends was davon steht, daß der Arduino von woanders seine Spannung bezieht, bin ich davon ausgegangen, das er seine Spannung mit aus dem Empfänger kommt.

Der 5V pin ist als Stromquelle gedacht, um also z.B. den Empfänger (oder ein shield/einen Servo oder was immer) mit Strom zu versorgen, nicht als Eingang. Direkt daneben gibt es einen Vin Pin der als Eingang gedacht ist und direkt zum großen AC Anschluss an der Front durchgeschleift ist, hier lässt sich also auch die Versorgungsspannung (Bordspannung) am Arduino abgreifen wenn der Arduino über den AC an der Front gespeist wird. Als Stromquelle für den Arduino empfehle ich den großen an der Front neben dem USB. Über diesen Eingang verträgt der Arduino Spannungen zwischen 5 und 18V und kann damit (meist) problemlos direkt an die Bordspannung. Unter 7V Versorgungsspannung sollte man aber an der 5V Leitung nichts abgreifen.

Link to comment

kleine Ergänzung: der Arduino bekommt seine Spannung direkt aus dem 12V Akku. Erste Tests waren gestern erfolgreich.. Ich habe ein kleines Programm geschrieben mit dem ich zwischen 4 mini-programmen hin- und herschalten konnte. Testweise hatte ich dazu an Pin 12 und 13 jeweils eine LED angeschlossen. Den RC-Eingang (Impuls) hatte ich auf Pin 7 zu liegen, die Masse vom RC-Empfänger auf GND. Das Programm selber hat zwar so einige Macken, aber fürs erste hat es seinen Zweck erfüllt:

 

const int LED13 = 13;
const int LED11 = 11;
int rc_pin_1 = 7;
int wert_1;
int zl = 1;
int wartezeit = 200000;
unsigned long currentMillis = 0;
void setup()
{
 pinMode(LED13, OUTPUT);
 pinMode(LED11, OUTPUT);
 pinMode(rc_pin_1, INPUT);
}
void blinken(int thePin, int dauer) {
 digitalWrite(thePin, HIGH);
 delay(dauer);
 digitalWrite(thePin, LOW);
 delay(dauer);
}
void setled(int thPin, int stat) {
  digitalWrite(thPin, stat); 
}
void prg(int prog) {
switch (prog) {
 case 1:
  prg1();
  break;
 case 2:
  // do something when var equals 2
  prg2();
  break;
 case 3:
  prg3();
  break;
 default:
  prg4();
} 
}
// Programm 1 - Fahrbetrieb
void prg1() {
setled(13,HIGH);
setled(11,HIGH);
}
// Programm 2 - Notfall
void prg2() {
setled(13,LOW);
setled(11,HIGH);
}
// Programm 3 - Ankern
void prg3() {
setled(13,HIGH);
setled(11,LOW);
}
// Programm 4 - Alles Aus
void prg4() {
setled(13,LOW); 
setled(11,LOW);
}
void loop()
{

 wert_1 = pulseIn(rc_pin_1, HIGH, 20000);
 if(wert_1 > 1900) {
   if (currentMillis == 0) {
    currentMillis = millis();
   }

   if(millis() - currentMillis > wartezeit) {

     // wenn Hebel gedrückt wird, Programmzähler zl nach 2 Sekunden um 1 erhöhen
     if(zl > 4) { zl = 1; }    // Programmzähler auf den Anfang setzen, wenn das max. an Programmen erreicht wurde
     prg(zl);                  // das entsprechende Programm aufrufen
     zl++;                     // Programmzähler für den nächsten Aufruf um eins erhöhen
     currentMillis = 0;        // Zeitstempel zurücksetzen
   }
 }
}

 

Heute habe ich das Programm komplett überarbeitet, kann es aber erst heute Abend testen. Wie gesagt: ich bin kein Programmierkünstler! Es soll nur funktionieren :D

 

Für Vorschläge und Verbesserungen bin ich jederzeit offen!

 

// Programm zur Lichtsteuerung des FSB Seeadler
// Stand: 16.08.2012
// Programme:
//  1 - Aus
//  2 - normale Fahrt
//  3 - Manövrierbehindert
//  4 - Einsatz
//  5 - Schiff vor Anker
//  6 - Schleppvorgang
//  7 - Test
// Lampenauflistung:
//        Bezeichnung         Farbe       Anz./Position                              I/O bei Programm                    Pin
//                                                                             1    2    3    4    5    6    7
// ----------------------------------------------------------------------------------------------------------------------------------
//   1  - Topplicht           weiß        1x Signalmast, 1x Bug                O    I    O    I    O    I    I            3
//   2  - Ankerlicht          weiß        1x Bug, 1x Heck                      O    O    O    O    I    O    I            4
//   3  - Hecklaterne         weiß        1x Heck                              O    I    I    I    O    I    I            5
//   4  - Seitenlaterne Stb   grün        1x Stb am Deckshaus                  O    I    I    I    O    I    I            5
//   5  - Seitenlaterne Bb    rot         1x Bb am Deckshaus                   O    I    I    I    O    I    I            5
//   6  - Heckschlepplicht    gelb        1x Heck                              O    O    O    O    O    I    I            6
//   7  - Signallicht         rot         4x Signalmaast                       O    O    I    O    O    O    I            7
//   8  - Signallicht         weiß        2x Signalmast                        O    O    I    O    O    O    I            7
//   9  - Heck Zolllaterne    weiß        1x Heck                              O    O    O    I    O    O    I            8
//  10  - Steuerlicht         blau        1x Bug                               O    O    O    O    O    O    I
//  11  - NOK Freifahrerlicht gelb        1x Bug                               O    O    O    O    O    O    I
//  12  - Blinklicht          blau        1x Signalmast                        O    O    O    I    O    O    I            8
//  13  - Manöversignal       weiß        1x Signalmast                        O    O    O    O    O    O    I
//  14  - Schlepplicht        weiß        2x Bug                               O    O    O    O    O    I    I            6
//  15  - Hubschr.Abwinschfl. gelb       12x Hubschrauberabwinschfläche        O    O    O    O    I    O    I            9
//  16  - Decksbeleuchtung    weiß       16x div. Decks                        O    O    O    O    I    O    I            9
//  17  - Innenbeleuchtung    gelb/grün  16x div. Decks                        O    O    O    O    I    O    I            9
//  18  - Blinklicht          gelb        1x Signalmast                        O    O    O    O    O    O    I
//  11 ist nur Formhalber installiert, 18 (Fährbetrieb?) wird vorerst ignoriert
//  10 & 13 muß ich noch herausfinden bei welchem Programm sie geschaltet werden

int rc_pin = 2;                  // RC-Empfänger Puls-Leitung an Pin 2
const int LED3 = 3;
const int LED4 = 4;
const int LED5 = 5;
const int LED6 = 6;
const int LED7 = 7;
const int LED8 = 8;
const int LED9 = 9;

// hier werden die Programme definiert
int prg1[] = {0,0,0,0,0,0,0};
int prg2[] = {1,0,1,0,0,0,0};
int prg3[] = {0,0,1,0,1,0,0};
int prg4[] = {1,0,1,0,0,1,0};
int prg5[] = {0,1,0,0,0,0,1};
int prg6[] = {1,0,1,1,0,0,0};
int prg7[] = {1,1,1,1,1,1,1};
int rc_signal;                       // Wert der vom Empfänger übermittelt wird
int z1 = 1;                          // aktuelles Programm , Start mit 1
int wartezeit = 2000;              // Signaldauer bis das nächsten Programm geschaltet wird, aktuell 2 sek
unsigned long zeitstempel = 0;
int programmpause = 250;             // Verzögerung der loop-Schleife, aktuell 250ms

void setup()
{
 pinMode(rc_pin, INPUT);
 pinMode(LED3, OUTPUT);
 pinMode(LED4, OUTPUT);
 pinMode(LED5, OUTPUT);
 pinMode(LED6, OUTPUT);
 pinMode(LED7, OUTPUT);
 pinMode(LED8, OUTPUT);
 pinMode(LED9, OUTPUT);
}

// Funktion um RC-Kanal auszulesen
int rcStatus()
{
 int rc_in = pulseIn(rc_pin, HIGH, 100000);
 return rc_in;
}

// Programm wechseln
void prgwechsel(int prgNr) {
 String programmnummer = String("prg" + prgNr);      // Programmnummer aus prg und übergebenem Wert erstellen
 int schaltpin = 3;                                  // erster Pin an dem eine LED angeschlossen ist
 for(int i=0;i<7;i++) {                              // 7 Durchläufe der FOR-Schleife weil 7 Ausgänge geschaltet werden sollen
   if(programmnummer[i] == 1) {                      // wenn Wert = 1
     digitalWrite(schaltpin,HIGH);                   // LED anschalten
   } else {                                          // sonst
     digitalWrite(schaltpin,LOW);                    // LED ausschalten
   }
   schaltpin++;                                       // für den nächsten For-Durchlauf den Pin um 1 erhöhen
 }
}

void loop()
{
 // Anfangsstatus -> alles Aus, Start mit Programm 1 (von z1 übergeben)

 rc_signal = rcStatus();                       // aktuellen RC-Wert abfragen
 if(rc_signal < 1700) {                        // wenn kein Signal anliegt
   zeitstempel = millis();                     // Zeitstempel auf aktuellen Zeitpunkt setzen
 } else {                                      // Signal liegt an
   if(millis() - zeitstempel >= wartezeit) {    // liegt das Signal bereits 2 Sek an?
    z1++;                                      // Programmzähler um 1 erhöhen für den nächsten gültigen Aufruf
    zeitstempel = millis();                    // und zeitstempel zurücksetzen      
     if(z1 == 8) {                             // wenn Programm NR. 8 erreicht ist, welches ja nicht existiert
       z1 = 1;                                 // Programm auf 1 zurücksetzen => alles Aus
     }
    prgwechsel(z1);                            // geändertes Programm aktivieren
   } else {                                    // sonst
     zeitstempel = zeitstempel + programmpause;   // zeitstempel erhöhen
   }
 }

 delay(programmpause);                         // Pause
}

Link to comment

Man hört diese Musik und denkt: Salieri ;)

 

Spaß, aber an so 1-2 Stellen könnte man etwas aufräumen. Fangen wir mal oben an:

 

const int LED[] = {3, 4, 5, 6, 7, 8, 9};
//warum machst du die LEDs const, prg aber nicht?
int prg[7][7] = 
{0,0,0,0,0,0,0},
{1,0,1,0,0,0,0},
{0,0,1,0,1,0,0},
{1,0,1,0,0,1,0},
{0,1,0,0,0,0,1},
{1,0,1,1,0,0,0},
{1,1,1,1,1,1,1};
void prgwechsel(int prgNr) {
 for(int i=0;i<7;i++) {  // 7 Durchläufe der FOR-Schleife weil 7 Ausgänge geschaltet werden sollen
     digitalWrite(led[i],prg[prgNr][i]); //HIGH und LOW sind nichts anderes als 1 und 0 und die stehen schon in prg[x][y] drin
 }
}

 

Empfinde ich irgendwie als eleganter. Auch müssen die LED Pins nicht nacheinander kommen und die Reihenfolge spielt keine Rolle mehr da sie in LED[] definiert wird. Die 2 Zeilen da oben machen aber genau das selbe wie die 8 bei dir, falsch war es also nicht.

 

Dann würde ich noch folgendes tun:

rc_lesen_ok = false //globale variable
int rcStatus() //status klingt für mich nicht, lieber rc_read oder so
{
 int rc_in = pulseIn(rc_pin, HIGH, 100000);
 if(rc_in > 2200 || rc_in < 900) { //wenn rc_in > 2200 oder < 900
   rc_lesen_ok = false //globale variable die feststellt das das auslesen nicht funktioniert hat, in diesem Fall nicht schalten
   return 0;
 }
 else{
 rc_lesen_ok = true;
 return rc_in;
}

in der loop dann natürlich rc_lesen_ok abfragen, z.B.
void loop(){
 rc_signal = rcStatus();                       // aktuellen RC-Wert abfragen
 if(rc_lesen_ok){
    //hier der Rest deiner loop wie sie im moment ist
 }
 else{
   delay(1000);}

Bei deinem Code würde er alle Nase lang die Programme wechseln wenn der Sender ausgeschaltet würde, weil er vermutlich 0 zurückgeben würde.... müsste man mal testen. Die main schaue ich mir evtl. mal später an, die prog wechsel hat mich nur geradezu angesprungen.

Edited by Kessl
Link to comment
Guest willie

Glückwunsch zum 1. Programm. Sieht doch gut aus. Ein paar kleinere Tipps hätt ich noch.

 

1. versuch soviel wie möglich als const zu definieren. Alles was sich während der Laufzeit nicht ändert, kann man als const definieren.

2. Du hast nur 2 Schaltzustände für die LED's an oder aus, dein Programmarray kann ja dann auch als boolean definiert sein. Spart Platz und Zeit. (int sind 2 Byte, boolean ist ein Bit...)

const boolean prgX[] = {

3. Du kannst auch ein offenes Array definieren:

Beispiel offenes Array: Liste deine Ausgänge:

const byte LED_AUSGAENGE[] = { 3, 4, 5, 6, 7, 8, 9};

So kannst du später ohne dein Programm zu ändern einfach einen Ausgang hinzufügen. Durchinterieren kannste dann mit:

void setup()
{
 pinMode(rc_pin, INPUT);

 for (int i =0; i< sizeof(LED_AUSGAENGE); i++) {
   pinMode(LED_AUSGAENGE[i], OUTPUT);
 }
...
}

Du kannst natürlich auch 2 dimensionale Arrays verwenden. Innere Dimmensionen dürfen nicht offen sein, die äußerste schon.

 

Hier deine Programme:

const boolean programme[][7] = {
 {0, 0, 0, 0, 0, 0, 0  },
 {1, 0, 1, 0, 0, 0, 0  },
 {0, 0, 1, 0, 1, 0, 0  },
 {1, 0, 1, 0, 0, 1, 0  },
 {0, 1, 0, 0, 0, 0, 1  },
 {1, 0, 1, 1, 0, 0, 0  },
 {1, 1, 1, 1, 1, 1, 1  }};

Programmwechsel:

// Programm wechseln
void prgwechsel(int prgNr) {
 for(int i=0;i<sizeof(LED_AUSGAENGE);i++) {
     digitalWrite(LED_AUSGAENGE[i],programme[i][prgNr]);
 }
}

BTW: Du kannst auch die Analogen Eingänge als Digitale Ein- und Ausgänge verwenden, haben dann die Nummern 14-19.

 

 

4. Eine Funktion mit nur 1 Zeile Code (int rcStatus()) macht natürlich keinen Sinn. Da wird zuviel Code zum hin und herspringen erzeugt. Nicht immer kann der Optimierer das erkennen. Also das Auslesen des Pulses ruhig in den Hauptteil, oder besser, die Funktion z.B. mit der Prüfung des Signales ausbauen. BTW.: der Wert, der da vom pulseIn kommt ist ein unsigned long. Kann zu unangenehmen Folgen führen, wenn man den auf einen int zuweist.

 

5. Versuch das Signal vom Empfänger etwas besser zu kontrollieren. z.B. in dem du den Impuls nur in einem bestimmten Bereich zuläßt. z.B. kannst du testen ob der Puls zwischen 1000 und 2000 liegt, dann ist der OK. bei fehlerhaften Werten ignorierst du den Impuls. Das mit der Wartezeit ist schon gut, besser fände ich, zu testen ob 3 mal der gleiche Wert (natürlich in einem Bereich z.B. von 1600-1800) anliegt. Erst dann wird der Wert verarbeitet. Gerade wenn man z.B. mit der Reichtweite nahe an der Grenze liegt, oder wenn die Akkus schwach werden, kann der Empfänger sehr merkwürdige Werte auspucken. Und da wäre es schon komisch, wenn dann plötzlich das Schiff Flackerlicht macht...:mrgreen: (Obwohl, so würdest du wenigsten mitbekommen, das was nicht i.O. ist...:keineIdee:)

 

Die Idee, das, wenn du den Hebel legst, die Programm im 2 Sekundentakt durchgewechselt werden, find ich richtig gut.

Du könntest z.B. auch noch auf das Zurücklegen des Hebels reagieren. (1000-1500ms) z.B. mit einem speziellen Programm oder mit einem Reset auf das Nullprogramm.

 

12V ist gut, dann bitte nicht den Empfänger mit dem Plus verbinden. (Zumindest nicht, wenn der Empfänger noch von woanders Strom kriegt.)

 

PS.: Meine Codefragmente oben, hab ich nur gegen den Compiler getestet. Evt. muss man da noch ein paar kleinere Änderungen vornehmen. Soll ja auch nur als Hinweise dienen.

Link to comment

Danke erstmal für eure Hilfe. Ich habe den Code jetzt angepaßt bzw. ergänzt. Das mit dem 2 Sekunden warten bevor das nächste Programm gestartet wird, habe ich jetzt durch eine Pause im Programmwechsel gelöst. Finde ich einfacher. Auch sind noch 2 Ports dazu gekommen. Hier also der aktuelle Quelltext:

 

// Programm zur Lichtsteuerung des FSB Seeadler
// Stand: 16.08.2012
// Programme:
//  0 - Aus
//  1 - normale Fahrt
//  2 - Manövrierbehindert
//  3 - Einsatz
//  4 - Schiff vor Anker
//  5 - Schleppvorgang
//  6 - Test

// Lampenauflistung:
//        Bezeichnung         Farbe       Anz./Position                              I/O bei Programm                    Pin
//                                                                             1    2    3    4    5    6    7
// ----------------------------------------------------------------------------------------------------------------------------------
//   1  - Topplicht           weiß        1x Signalmast, 1x Bug                O    I    O    I    O    I    I            3
//   2  - Ankerlicht          weiß        1x Bug, 1x Heck                      O    O    O    O    I    O    I            4
//   3  - Hecklaterne         weiß        1x Heck                              O    I    I    I    O    I    I            5
//   4  - Seitenlaterne Stb   grün        1x Stb am Deckshaus                  O    I    I    I    O    I    I            5
//   5  - Seitenlaterne Bb    rot         1x Bb am Deckshaus                   O    I    I    I    O    I    I            5
//   6  - Heckschlepplicht    gelb        1x Heck                              O    O    O    O    O    I    I            6
//   7  - Signallicht         rot         4x Signalmast                        O    O    I    O    O    O    I            7
//   8  - Signallicht         weiß        2x Signalmast                        O    O    I    O    O    O    I            7
//   9  - Heck Zolllaterne    weiß        1x Heck                              O    O    O    I    O    O    I            8
//  10  - Steuerlicht         blau        1x Bug                               O    O    O    O    O    O    I
//  11  - NOK Freifahrerlicht gelb        1x Bug                               O    O    O    O    O    O    I
//  12  - Blinklicht          blau        1x Signalmast                        O    O    O    I    O    O    I            10
//  13  - Manöversignal       weiß        1x Signalmast                        O    O    O    O    O    O    I
//  14  - Schlepplicht        weiß        2x Bug                               O    O    O    O    O    I    I            6
//  15  - Hubschr.Abwinschfl. gelb       12x Hubschrauberabwinschfläche        O    O    O    O    I    O    I            9
//  16  - Decksbeleuchtung    weiß       16x div. Decks                        O    O    O    O    I    O    I            9
//  17  - Innenbeleuchtung    gelb/grün  16x div. Decks                        O    O    O    O    I    O    I            11
//  18  - Blinklicht          gelb        1x Signalmast                        O    O    O    O    O    O    I

//  11 ist nur Formhalber installiert, 18 (Fährbetrieb?) wird vorerst ignoriert
//  10 & 13 muß ich noch herausfinden bei welchem Programm sie geschaltet werden

int rc_pin = 2;                  // RC-Empfänger Puls-Leitung an Pin 2

const byte LED_AUSGAENGE[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11};

// hier werden die Programme definiert
const boolean programme[][9] = {
 {0, 0, 0, 0, 0, 0, 0, 0, 0  },
 {1, 0, 1, 0, 0, 0, 0, 0, 0  },
 {0, 0, 1, 0, 1, 0, 0, 0, 0  },
 {1, 0, 1, 0, 0, 1, 0, 1, 0  },
 {0, 1, 0, 0, 0, 0, 1, 0, 0  },
 {1, 0, 1, 1, 0, 0, 0, 0, 0  },
 {1, 1, 1, 1, 1, 1, 1, 1, 1  }};

int rc_signal;                       // Wert der vom Empfänger übermittelt wird
int z1 = 0;                          // aktuelles Programm
int programmpause = 250;             // Verzögerung der loop-Schleife, aktuell 250ms

void setup()
{
 pinMode(rc_pin, INPUT);
 for (int i =0; i< sizeof(LED_AUSGAENGE); i++) {
   pinMode(LED_AUSGAENGE[i], OUTPUT);
 }
 Serial.begin(9600);
}

// Funktion um RC-Kanal auszulesen
int rc_read()
{
 int rc_in = pulseIn(rc_pin, HIGH, 100000);
  return rc_in;
}

// Programm wechseln
void prgwechsel(int prgNr) {
 for(int i=0;i<sizeof(LED_AUSGAENGE);i++) {                
     digitalWrite(LED_AUSGAENGE[i],programme[i][prgNr]);   // LED schalten
     Serial.print(programme[i][prgNr]);
 }
 delay(2000);
 Serial.println("");
}

void loop()
{
 // Anfangsstatus -> alles Aus

 rc_signal = rc_read();                       // aktuellen RC-Wert abfragen
//  Serial.println(rc_signal);

 if(rc_signal > 1850) {                        // wenn kein Signal anliegt
    z1++;
    if(z1 > 6) {                               // wenn Programm NR. 7 erreicht ist
       z1 = 0;                                 // Programm auf 0 zurücksetzen => alles Aus
     }
    prgwechsel(z1);                            // geändertes Programm aktivieren
    Serial.println(z1);
  } else if (rc_signal < 1150) {               // wenn Steuerknüppel nach unten
   z1 = 0;                                     // aktuelles Programm resetten und
   prgwechsel(z1);                             // alles ausschalten (programm 0)
   Serial.println(z1);
 } else {
   // do nothing
 }
 delay(programmpause);                         // Pause
}

Habe am Arduino bisher nur eine LED zum testen angeschlossen.

Daher habe ich zu Kontrollzwecken den LED-Status auf den Monitor geben lassen. Dies sieht wie folgt aus:

 

00001010106
1
011101104
2
0000011074
3
00100011654
4
00010014147
5
0000101614
6
010101104
0
00001010106
1

oben die Ausgabe der Ports, darunter die Programmnummer. Eigentlich sollten da nur 1 und 0 stehen. Also hat sich noch irgendwo ein Fehler eingeschlichen...

Link to comment

Also um dir nicht den ganzen Spaß zu nehmen gebe ich dir einen Tipp:

 

Du hast ein Array mit 8x9 und kannst dir nicht erklären warum die Zahlen komisch sind die ausgegeben werden. hmmm, eigentlich müsste Z1 doch 0 sein, die erste Zeile müsste theoretisch doch 0 0 0 0 0 0 0 0 0 heißen, oder?

 

Jetzt steht da aber 0 1 0 1 0 1 1 x.

 

Wenn du nicht drauf kommst steht hier die Lösung etwas versteckt:

array[x][y] ist nicht das selbe wie array[y][x]

 

/edit: Ach ja, ich würde an Deiner Stelle noch folgendes tun:

1. Wenn du schon Serial.Write benutzt um dein Programm zu überprüfen, dann immer sauber und lass dir ausgeben was da gerade zu sehen ist und was zu sehen sein sollte. Was dich in 2 sec auf die Lösung deines Problems gebracht hätte wäre (99% sicher) ein:

Serial.print(programme[prgNr]);

Serial.print(" ");

2. Ich würde aus dem z1++, if z1>7 usw. eine extra Funktion machen, das wirkt übersichtlicher.

3. Der Wertebereich für das auslesen der Funke liegt zwischen 1000 und 2000 (+/- 'n bissi was), ein Wert von 1850 ist nicht kein Signal, bestenfalls Steuerknüppel oben. Gar kein Signal würde ich aber auch noch abfangen, z.B. durch if(rc_signal < 900 || rc_signal > 2200) [die || sind ein logisches oder, das if wird in diesem fall ausgeführt wenn eine der beiden wahr ist, das signal also fehlerhaft ist]

Edited by Kessl
Link to comment
Guest willie

Ja,

 

ich hab die beiden Indizes verwechselt.

Da beide aber 7 lang waren, ist das beim compilieren nicht aufgefallen:

 

Definition:

const boolean programme[][sizeof(LED_AUSGAENGE)] = {
...

 

im Code dann:

 for(int i=0;i<sizeof(LED_AUSGAENGE);i++) {                
     digitalWrite(LED_AUSGAENGE[i],programme[prgNr][i]);   // LED schalten
     Serial.print(programme[prgNr][i]);
 }

programme [prgNr] und nicht umgekehrt.

Mea culpa.

Link to comment

ich hab die beiden Indizes verwechselt.

Da beide aber 7 lang waren, ist das beim compilieren nicht aufgefallen:

 

das ist mir jetzt auch aufgefallen... war schon spät gestern Abend ;)

Die "Tabelle" wurde quasi vertikal und nicht horizontal ausgelesen.

 

mein RC-in habe ich mir auch per serial ausgeben lassen. Er liegt bei max-Ausschlag nach unten bei 12xx und oben bei 1912. Daher habe ich bisher nur abgefragt, ob der Steuerknüppel quasi oben oder unten ist. Wenn kein Signal anliegt oder bei ca. 1550 in der Mitte passiert nix. Klar können noch ein paar Feinheiten angepaßt werden! So soll z.B. die LED 12 2x/s blinken. Das wollte ich aber erst anpassen, wenn der Signalmast angeschlossen ist...

 

Zum endgültigen Testen muß ich mir jetzt erstmal eine Leiterplatte entwerfen um die ganzen LEDs anschließen zu können.

 

Nochmal zum Wertebereich:

if(rc_signal > 1850) { // wenn rc_signal größer als 1850
- 1. Möglichkeit, das Signal ist höher als 1850

 

} else if (rc_signal < 1150) { // wenn Steuerknüppel nach unten

z1 = 0; // aktuelles Programm resetten und

prgwechsel(z1); // alles ausschalten (programm 0)

2. Möglichkeit, das Signal ist niedriger als 1150. Das schließt auch mit ein, daß KEIN Signal anliegt, also 0 übergeben wird. In diesem Fall wird Programm 0 gestartet => Alles Aus

 

} else {

// do nothing

3. Möglichkeit, ein Signal zwischen 1151 & 1849. Nix machen

 

 

also vielen Dank nochmal für eure Hilfe, der Grundstein ist gelegt! :)

Edited by matze777
Link to comment
Guest willie

Richtig. Du wirst sehen, mit der Anwendung kommen auch noch weitere Wünsche und auch Fehler hoch. Meine GT-2 macht z.b. 950 - 1900 Ausschlag. Weiterhin ist da ja auch noch der Trimm. Auch der beeinflusst natürlich das Signal. Da ist jede Funke anders. Zum Glück musst du dich nur erst mal u. Deine Funke kümmern. Prof. Produkte müssen alle Varianten können, deswegen ist das nochmal etwas komplexer, so mit einstellbarem Null- und Schaltpunkt.

Bin sehr gespannt, wie du den Arduino in dein Boot integrierst.

Link to comment

Ich vermute mal du hast einen 3-wege schalter/taster an deiner Funke mit der du die Lichter steuern möchtest, oder? Dein erster Ansatz, die Zeit zu messen, hat mir sehr viel besser gefallen als das delay(2000) das du im Moment benutzt. Aus vielen Gründen ist das einfach nur hässlich, auch weil du so für 2 sec deine Beleuchtung nicht ausschalten kannst. Der folgende Code schaltet sofort, aber er schaltet nur 1x und wartet dann bis der Schalter 1x in der Mitte war. Gerade wenn dein Schalter eigentlich ein Taster ist kannst du so deutlich schneller schalten. Da unten kannst du alles mit Zeitstempen und schalten_nach übrigens auch löschen, wenn du keinen delay beim schalten benötigst, und eigentlich ist das unnötig. Ach ja, und schmeiß den delay(wartezeit) aus der loop, der ist wirklich total unnötig.

boolean geschaltet = false;
unsigned long zeitstempel = 0;
unsigned long schalten_nach = 0;

void schalten(){
 z1++;
 if(z1 >= 6) { // >= ist zwar unnötig, aber meistens trotzdem besser ^^
   z1 = 0;
 }
 prgwechsel(z1);
 geschaltet = true;
}
void allesaus(){
 z1=0;
 progwechsel(z1);
}

void loop(){
 if(rc_signal < 900 || rc_signal > 2100) allesaus(); //fehlerhaftes Signal, nichts tun
 else if(rc_signal > 1850 && millis() >= zeitstempel + schalten_nach && |geschaltet) {
   schalten();
 }
 else if(rc_signal < 1150){
   allesaus();
 }
 else{
   zeitstempel = millis();
   geschaltet = false;
 }
}

Link to comment
  • 3 weeks later...

ich benutze den rechten vor-zurück knüppel an der Fernsteuerung. Mit dem Programm funktioniert das soweit ganz gut! Habe mir eine Leiterplatte gebastelt um die Signale an die entsprechenden LEDs weiterzuleiten.

 

(1. Bild)

 

soweit so gut... nun habe ich das ganze noch etwas umgelötet da ich die Elektronik in einem Kasten verstauen möchte. Außen sind SUB-D Stecker angebracht so daß ich den Kasten jederzeit ausbauen kann.

 

(2. Bild Vorder- und 3. Bild die Rückseite)

 

Jetzt habe ich auf einmal das Problem, daß alle LEDs dauerhaft leuchten, obwohl ich am Aufbau der Platine nichts geändert habe. Ich habe lediglich die Stecker entfernt und durch Kabel ersetzt. Der Arduino ist nicht angeschlossen, es liegt an den Transistoren also kein Signal an. Lediglich 12V + und - sind an der Platine angeschlossen. Ich habe auch schon kontrolliert ob es irgenwo einen Kurzschluss gibt, habe aber nichts auffälliges bemerkt. Normalerweise bräuchte ich doch 9 Signale, damit alle 9 Transistoren schalten... Irgendwie komme ich derzeit nicht weiter! Vielleicht habt ihr einen Tip für mich!?

post-6678-1419862264,2835_thumb.jpg

post-6678-1419862264,3889_thumb.jpg

post-6678-1419862264,4868_thumb.jpg

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.