Forum: Mikrocontroller und Digitale Elektronik Einfacher DMX Regler mit ATTiny


von Moritz B. (busti)


Lesenswert?

Hallo,
Ich habe vor einiger Zeit einen DMX RGB Strahler der Marke MCCrypt 
gekauft und wollte ihn in meiner Wohnung verwenden. Man kann daran 
leider allerdings nur 6 verschiedene Festfarben einstellen, die alle 
mehr oder weniger ungeeignet sind geschweige denn einen weichen 
Frárbwechsel. Allerdings hat er einen DMX Eingang und deshalb habe ich 
mir gedacht, dass ich einen ATTiny45 verwenden könnte um die Farbe zu 
regeln.
Um dies zu erreichen habe ich den DMX + Anschluss des Strahlers mit Pin 
0 des Tinys verbunden und an die Analogen Pins Potentiometer 
angeschlossen, die die ersten 3 Byte des DMX Signals steuern. Ich habe 
diesen Code bei 8MHz auf den Tiny geladen unter Verwendung der Arduino 
IDE:
1
#include "pins_arduino.h";
2
#define sig 0                 // DMX signal output pin
3
4
void setup () {
5
  pinMode(sig, OUTPUT);
6
  digitalWrite(sig, HIGH);
7
  pinMode(A1, INPUT);
8
  pinMode(A2, INPUT);
9
  pinMode(A3, INPUT);
10
}
11
12
void loop(){
13
  //delay(10);
14
  digitalWrite(sig, LOW);  
15
  delay(10);     
16
  shiftDmxOut(sig, 0);
17
  shiftDmxOut(sig, analogRead(A1)/8);
18
  shiftDmxOut(sig, analogRead(A2)/8);
19
  shiftDmxOut(sig, analogRead(A3)/8);
20
  //for (int count = 1; count <= 512; count++){
21
  //  shiftDmxOut(sig, 0);
22
  //}
23
}
24
25
void shiftDmxOut(int pin, int theByte){
26
  int port_to_output[] = { NOT_A_PORT, NOT_A_PORT, _SFR_IO_ADDR(PORTB)};
27
  int portNumber = port_to_output[digitalPinToPort(pin)];
28
  int pinMask = digitalPinToBitMask(pin);
29
  _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;
30
  //delayMicroseconds(10);
31
  cli();  
32
  _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask;   
33
  fourUSdelay();  
34
  for (int i = 0; i < 8; i++){
35
    if (theByte & 01){
36
      _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask; 
37
    }
38
    else { 
39
      _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask; 
40
    }
41
    fourUSdelay();
42
    theByte >>= 1;
43
  }
44
  _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;  
45
  sei();  
46
}
47
48
void fourUSdelay(void) {
49
    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
50
    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
51
}
Allerdings verhält sich das licht sehr "komisch"...
Ist nur ein Poti aufgedreht so wird immer die Farbe Blau dargestellt und 
zwischendurch beginnt das licht manchmal zu blinken / flackern, 
allerdings nur bei bestimmten Einstellungen.

Vielleicht habe ich etwas übersehen.
Vielen Dank für eure Hilfe,
Moritz Bust

von Dödel (Gast)


Lesenswert?

Moritz Bust schrieb:
> Um dies zu erreichen habe ich den DMX + Anschluss des Strahlers mit Pin
> 0 des Tinys verbunden

Dann mach dich zuerst mal schlau, wie ein DMX Bus elektrisch aufgebaut 
ist.

Moritz Bust schrieb:
> Allerdings verhält sich das licht sehr "komisch"...
> Ist nur ein Poti aufgedreht so wird immer die Farbe Blau dargestellt und
> zwischendurch beginnt das licht manchmal zu blinken / flackern,
> allerdings nur bei bestimmten Einstellungen.

Ist zu erwarten, so wie du Lampe angeschlossen hast...

von blubber (Gast)


Lesenswert?

Moritz Bust schrieb:
> Um dies zu erreichen habe ich den DMX + Anschluss des Strahlers mit Pin
> 0 des Tinys verbunden und an die Analogen Pins Potentiometer

Ohne mir deinen Code angesehen zu haben:

Bau das mal richtig auf!
So wird das nie sicher funktionieren sondern von Tempereatur, 
Luftfeuchtigkeit und Mondphase abhängig sein ....

Ein MAX485 oder SN76176 sollte noch drin sitzen.

Was du machst hat den selben Effekt, als wenn man beim Auto mit leerem 
Tank das Motorsteuergerät umprogrammiert ...

von Lichttechniker (Gast)


Lesenswert?

Moritz Bust schrieb:
> Um dies zu erreichen habe ich den DMX + Anschluss des Strahlers mit Pin
> 0 des Tinys verbunden

DMX ist im Prinzip RS485, also ein differentielles Signal. Normalerweise 
nimmt man dazu einen Treiber IC. Ohne wirds schwierig:
Beitrag "RS485 ohne Treiber-IC unmöglich?"

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Es kann sein, dass der Anschluss der China-Scheinwerfer auch mit 
nicht-normgerechten Pegeln klarkommt, aber das Protololl als solches 
musst du unter allen Umständen einhalten. Dazu gehört z.B., dass ein 
solcher RGB-Scheinwerfer die Helligkeitswerte auf je einem DMX-Kanal 
erwartet, d.h. du musst die Packets entsprechend aufbauen und im 
richtigen Timing senden.

: Bearbeitet durch User
von Lichttechniker (Gast)


Lesenswert?

Also: Nimm besser einen ATMega mit UART und hänge einen MAX485 dran.

von Moritz B. (busti)


Lesenswert?

Ok, wenn ich einen MAX485 nehme macht es immernoch genau das selbe.
Ich habe etwas ähnliches in dem selben Setup schon einmal vor ein Paar 
Monaten zum laufen bekommen finde den Code aber nicht mehr. :(

von Jürgen B. (hicom)


Lesenswert?


von Moritz B. (busti)


Lesenswert?

Hallo,
Vielen Dank für eure Mithilfe. Ich habe das Problem jetzt gelöst. Den 
Max485 benötige ich nicht es scheint mit nur einem Strahler auch ohne zu 
gehen.. Es geht auch ohne. Das Hauptproblem war Das Timing. Ich habe 
dieses jedoch jetzt mit meinem Oszilloskop korrigiert. Für alle die so 
etwas auch mal machen wollen hier der code:
1
#include "pins_arduino.h";
2
#define sig 0                 // DMX signal output pin
3
4
void setup () {
5
  pinMode(sig, OUTPUT);
6
  digitalWrite(sig, HIGH);
7
  pinMode(A1, INPUT);
8
  pinMode(A2, INPUT);
9
  pinMode(A3, INPUT);
10
}
11
12
void loop(){
13
  uint8_t red   = analogRead(A1)/8;
14
  uint8_t green = analogRead(A2)/8;
15
  uint8_t blue  = analogRead(A3)/8;
16
  digitalWrite(sig, LOW);
17
  delayMicroseconds(40);
18
  shiftDmxOut(sig, 0);
19
  shiftDmxOut(sig, red);
20
  shiftDmxOut(sig, green);
21
  shiftDmxOut(sig, blue);
22
}
23
24
void shiftDmxOut(int pin, int theByte){
25
  int port_to_output[] = { NOT_A_PORT, NOT_A_PORT, _SFR_IO_ADDR(PORTB)};
26
  int portNumber = port_to_output[digitalPinToPort(pin)];
27
  int pinMask = digitalPinToBitMask(pin);
28
  _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;
29
  cli();  
30
  _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask;   
31
  fourUSdelay();  
32
  for (int i = 0; i < 8; i++){
33
    if (theByte & 01){
34
      _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask; 
35
    }
36
    else { 
37
      _SFR_BYTE(_SFR_IO8(portNumber)) &= ~pinMask; 
38
    }
39
    fourUSdelay();
40
    theByte >>= 1;
41
  }
42
  _SFR_BYTE(_SFR_IO8(portNumber)) |= pinMask;  
43
  sei();  
44
}
45
46
void fourUSdelay(void) {
47
    asm("nop\n nop\n nop\n nop\n nop\n nop\n nop\n nop\n");
48
    asm("nop\n nop\n nop\n");
49
}

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.