Hallo zusammen,
gestartet im Hauptthread folge ich nun Jürgens Empfehlung ein eigenes Thema für DMX - RF24 - Raumlichtsteuerung aufzumachen.
Aufgabenstellung: Meine Lampen an der Decke, die mit RGBW-LED ausgerüstet sind, kann ich nicht mit der MLL verkabeln. Die LED werden über einen Nano angesteuert. Anfangs habe ich eine Übertragung mittels IR eingebaut, das ist aber fehleranfällig wenn jemand oder etwas im Weg steht. Die nRF24L01-Module sollten den Job besser erledigen. Dazu muss ich das Signal der MLL von der Hauptplatine zu einem Nano bekommen, der dann über ein nRF24L01 die Daten an die beiden Lampen schickt. Jürgens Vorschlag war die DMX-Schnittstelle zu verwenden, um die Zahlenwerte in digitlaer Form von der Hauptplatine zu bekommen.
Umsetzung: Ich hatte MAX485-IC hier und habe die RS485-Module fast 1:1 nachgebaut. Änderungen beim DMX-Sender R3 durch Brücke ersetzt, um RS485 in den Sendemodus zu versetzen, ist elektrisch wie auf der [URL=https://wiki.mobaledlib.de/anleitungen/spezial/dmx512/dmx_adapter_herstellen?s[]=dmx]MLL-Wiki DMX512 Adapter[/URL] umgesetzt. Die LED für die Spannungsanzeige habe ich weggelassen.
DMX-Empfänger: RE und DE werden auf Masse gezogen für den Empfangsmodus. Leitung zwischen den beiden DMX-Modulen ist eine 8 m Chinch-Audioleitung. Daten werden an den Arduino auf den serielle RX geführt. Ich habe das mal versucht darzustellen.
Aufbau
Die Verbindung zwischen Hauptplatine und RS485-Sendemodul per 10 cm Flachbandleitung, zwischen RS485-Empfängermodul und DMX-RF24-Brücke 10 cm Kabel. Ich brauche in meinem Fall eine lange Leitung, da ich an den Nano noch für was anderes anschließen will, dazu später mehr. Wer nur das DMX-Signal an einen Arduino übergeben will und mit 10 cm auskommt kann beide DMX-Modul weglassen und DI mit dem RX-Pin des Arduino verbinden.
Das zwischenzeitlich geplante I2C-Display ist wieder entfernt, da Störungen zwischen Display- und DMX-Library auftraten.
Schaltun der Lampen:
Firmware
Von der MLL werden drei Werte übergeben:
R: 1=Nacht, 2=Sonnenaufgang, 3=Tag, 4=Sonnenuntergang
G: 0 oder 1 für Gewitterblitze bei Nacht
B: 0-255 für die Geschwindigkeit der Farbänderungen
Die DMX-Brücke liest permanent die Werte von der MLL ein, sendet selbst aber nur per RF24 an die Lampen wenn die Werte sich geändert haben. Das 2,4 GHz-Netz, welches auch für WLAN in Gebrauch ist muss ja nicht unötig geflutet werden.
#include <DMXSerial.h>
byte aktuellModus = 0; /*
0 = undefined
1 = Nacht
2 = Sonnenaufgang
3 = Tag
4 = Sonnenuntergang */
byte aktuellBlitze = 0;
byte aktuellSpeed = 50;
// RF24-Definition
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";
void setup() {
DMXSerial.init(DMXReceiver);
pinMode(LED_BUILTIN, OUTPUT);
radio.begin();
radio.openWritingPipe(address);
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MIN / LOW / HIGH / MAX
radio.stopListening();
}
void loop() {
struct Data_Package {
byte Modus = DMXSerial.read(1);
byte Blitze = DMXSerial.read(2);
byte Speed = DMXSerial.read(3);
};
Data_Package data; // Create a variable with the above structure
if (aktuellModus != data.Modus || aktuellBlitze != data.Blitze || aktuellSpeed != data.Speed){ // wenn ein Parameter geändert ist sende Daten an Lampe
digitalWrite(LED_BUILTIN, HIGH); //signalisiere das Senden via RF24
radio.write(&data, sizeof(Data_Package));
aktuellModus = data.Modus;
aktuellBlitze = data.Blitze;
aktuellSpeed = data.Speed;
delay(500);
digitalWrite(LED_BUILTIN, LOW);
}
}
In der Lampe sind die Zielfarben hinterlegt und die Berechnung der Übergänge läuft dort ab.
Die Nanos der beiden Lampen haben keinen Bootloader, dadurch leuchten sie nach Einschalten fast sofort.
* 2 separate Lampen mit weissen und RGB-LED-Streifen werden beim Einschalten des Stromes voll weiss leuchten (Standardmodus)
* Beim Betrieb der Modellbahn werden die Beleuchtungsszenarien über 2,4 GHz Funkmodul empfangen und die Lampen geschaltet
* Code zur LED-Ansteuerung basiert auf Beispiel von Philipp Gahtow https://pgahtow.de
*/
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";
//Beleuchtungssteuerung:
int mode = 0;
/*
0 = undefined
1 = Nacht
2 = Sonnenaufgang
3 = Tag
4 = Sonnenuntergang
5 = Gewitter, nur bei Nacht
*/
unsigned long time = 0;
//Pins:
int BluePin = 5;
int RedPin = 6;
int GreenPin = 9;
int WhitePin = 10;
struct Data_Package {
byte Modus = 0;
byte Blitze = 0;
byte Tempo = 4000;
};
Data_Package data;
int lightsoll = 255; //Helligkeit
int temposoll = 4000; //Geschwindigkeit der Änderungen - Maximalbereich 50000
int blauist = 0;
int blausoll = 0;
int rotist = 200;
int rotsoll = 200;
int gruenist = 0;
int gruensoll = 0;
int weissist = 150;
int weisssoll = 150;
boolean modechange = false; // im Falle von Änderungen langsam an den Zielwert angleichen
boolean gewitter = false; //nur in der Nacht
int gcount = 0;
void setup()
{
radio.begin();
radio.openReadingPipe(0, address);
radio.setPALevel(RF24_PA_LOW); // RF24_PA_MIN / LOW / HIGH / MAX
radio.startListening();
pinMode(RedPin, OUTPUT);
pinMode(GreenPin, OUTPUT);
pinMode(BluePin, OUTPUT);
pinMode(WhitePin, OUTPUT);
analogWrite(WhitePin,weissist);
}
void loop()
{
time++;
if (modechange == true) { // Tageszeiten direkt anspringen
switch (mode) {
case 1: blausoll = 255; // Nacht
rotsoll = 0;
gruensoll = 0;
weisssoll = 0;
modechange = false;
break;
case 2: blausoll = 0; // Sonnenaufgang
rotsoll = 255;
gruensoll = 95;
weisssoll = 0;
modechange = false;
break;
case 3: blausoll = 0; // Tag
rotsoll = 200;
gruensoll = 0;
weisssoll = 255;
modechange = false;
break;
case 4: blausoll = 0; // Sonnenuntergang
rotsoll = 255;
gruensoll = 40;
weisssoll = 0;
modechange = false;
break;
}
}
if (radio.available()) { // Änderungen via nRF24L01 empfangen
radio.read(&data, sizeof(Data_Package));
if (data.Modus == 1) { // 1 = Nacht
mode = 1;
modechange = true;
}
if (data.Modus == 2) { // 2 = Sonnenuntergang
mode = 2;
modechange = true;
}
if (data.Modus == 3) { // 3 = Tag
mode = 3;
modechange = true;
}
if (data.Modus == 4) { // 4 = Sonnenaufgang
mode = 4;
modechange = true;
}
if (data.Blitze == 1 && mode == 1 ) { // Blitze = Gewitterblitze, nur bei Nacht
gewitter = true;
}
temposoll = map(data.Tempo, 0, 255, 50000, 1000);
}
if (time >= temposoll) {
time = 0;
setRGB(weisssoll, blausoll, rotsoll, gruensoll);
if (gewitter == true) { // Nacht, Gewitter berechnen
gcount++;
if ((gcount % 2 == 1 && gcount > 20 && gcount < 24)) //doppelt
blitz(true, 0);
if ((gcount % 2 == 1 && gcount > 35 && gcount < 40)) //doppelt
blitz(true, 0);
if ((gcount % 2 == 1 && gcount > 55 && gcount < 58)) //einfach
blitz(true, 0);
if ((gcount % 2 == 1 && gcount > 76 && gcount < 82) || gcount == 89) //doppelt, einfach
blitz(true, 1);
if ((gcount % 2 == 1 && gcount > 126 && gcount < 130)) //doppelt
blitz(true, 0);
if ((gcount % 2 == 1 && gcount > 172 && gcount < 174)) //einzel
blitz(true, 1);
if (gcount % 2 == 0)
blitz(false, 0);
if (gcount > 180) { //deaktivieren
gewitter = false;
gcount = 0;
}
}
}
} // Ende Loop
void setRGB(int weisss, int blaus, int rots, int gruens) { // Schreiben der PWM-Werte auf die Pins
if (weisss > weissist)
weissist++;
if (weisss < weissist)
weissist--;
if (map(blaus,0,255,0,lightsoll) > blauist)
blauist++;
if (map(blaus,0,255,0,lightsoll) < blauist)
blauist--;
if (map(rots,0,255,0,lightsoll) > rotist)
rotist++;
if (map(rots,0,255,0,lightsoll) < rotist)
rotist--;
if (map(gruens,0,255,0,lightsoll) > gruenist)
gruenist++;
if (map(gruens,0,255,0,lightsoll) < gruenist)
gruenist--;
analogWrite(BluePin,blauist); //blau
analogWrite(RedPin,rotist); //rot
analogWrite(GreenPin,gruenist); //grün
analogWrite(WhitePin,weissist); //warm-weiß
}
void blitz(boolean aktiv, int farbe) { // Blitz
if (aktiv == true) {
if (farbe == 1)
analogWrite(BluePin,255); //blau
else
analogWrite(RedPin,255); //rot
analogWrite(GreenPin,255); //grün
analogWrite(WhitePin,255); //warm-weiß
}
else {
analogWrite(RedPin,0); //rot
analogWrite(GreenPin,0); //grün
analogWrite(WhitePin,0); //warm-weiß
}
}
Jetzt muss ich mich mit der Logik in der MLL beschäftigen aber dafür gibt es ja Hardis-PDF zur Pushbuttonplatine
Viele Grüße,
Holger