Forum: Mikrocontroller und Digitale Elektronik Problem mit DMX


von Johny_D94 (Gast)


Lesenswert?

Moing

Ich "darf" für einen Kollegen ein DMX empfänger bastln, welcher je nach 
wert 2 Relay schaltet.

Regler wird nach unten geschoben => Relay 1 wird kurz erregt, fällt 
wider ab
Regler wird nach oben geschoben => Relay 2 wird kurz erregt, fällt 
wieder ab

Da ich DMX am anfang gar nicht kannte aber sah dass es sich eigentlich 
um UART handelt, habe ich zugesagt. Als "orientierung" habe ich diese 
Daten hier genommen:
Beitrag "DMX512 Empfänger mit Relaisansteuerung für 20 Kanäle"

Jetzt probiere ich seit letzten Freitag und kriege es nicht hin!

Kann jemand mal bitte meinen Code ansehen? Ich sehe einfach nicht mehr 
weiter :(
1
#define F_CPU 16000000
2
3
#include <avr/io.h>
4
#include <avr/interrupt.h>
5
#include <avr/sleep.h>
6
#include <util/delay.h>
7
8
9
10
uint8_t dmx_data;    // DMX data
11
uint8_t lastState;    //Last State of Port
12
uint8_t counter_T;    //Count the overflows of Timmer0
13
volatile uint8_t flag;        // new data available
14
15
16
int main(void) {
17
18
// init
19
20
  PORTB = 0xFF;    // all pull-ups ON
21
  DDRD  = 0x3F;    // PD0..5 outputs
22
  PORTD = 0x40;     //PullUp PD6
23
24
 
25
    UBRRH = 0;
26
    UBRRL = 3; //Vorteiler 3 @16Mhz = 250 Kbaud
27
    UCSRB = (1<<RXCIE) | (1<<RXEN);
28
29
  TCCR0B  |= (1<<CS00)|(1<<CS02); // Prescaler 1024 Timmer
30
31
//enable global Interrupt
32
  sei();   
33
34
// main loop
35
  while (1) {
36
    if (!flag) {
37
      set_sleep_mode(SLEEP_MODE_IDLE);
38
      sleep_mode();
39
    }
40
    else {
41
      flag=0;
42
      if((dmx_data >= 127)&&(lastState == 0)){
43
        PORTD |= 16;
44
        lastState = 1;
45
        TIMSK |= (1<<TOIE0); //Enable Overflow T0
46
47
      }
48
      
49
      else if ((dmx_data <= 127) && (lastState == 1)){
50
        PORTD |= 8;
51
        lastState = 0;
52
        TIMSK |= (1<<TOIE0); //Enable Overflow T0
53
      }
54
    }
55
  }
56
}
57
58
ISR(USART_RX_vect) {
59
    static uint16_t dmx_channel, dmx_adress;
60
    uint8_t status, data;
61
 
62
    // read UART data, also clears interrupt flag            
63
    status = UCSRA;
64
  data = UDR;
65
66
  if (status & (1<<FE)) {          // frame error
67
    if (data==0) {            // break -> DMX Reset
68
      dmx_channel=0;
69
      dmx_adress = (~PINB & 0xFF)+1;  // read dip switches which define DMX base address
70
      if (~PIND & (1<<PD6)) dmx_adress +=256;
71
      flag=1;              // trigger update
72
    }
73
    else                // rx error
74
      dmx_channel++;
75
  }
76
  else {
77
    if (dmx_channel == dmx_adress){
78
       dmx_data = data;
79
    }
80
    dmx_channel++;
81
  }
82
}
83
84
85
ISR (TIMER0_OVF_vect)
86
{
87
  if(counter_T !=255){
88
      counter_T++;
89
   }
90
  else
91
    counter_T = 0;
92
    TIMSK &= ~(1<<TOIE0);
93
    PORTD &= ~(24);
94
}

Ich habe schon mit einem USB UART Converter geschaut ob der MAX485 
funktioniert..und der ist OK! Die Relays gehen mit dem entsprechenden 
Testprogramm auch... Der Controller läuft dem Timmer 0 zu urteilen auch 
korekt auf dem 16 MHz Quarz, ERROR ist mit vorteiler 3 für den UART = 0% 
(siehe Datasheet seite 137).

Während des Betriebes zieht NIE ein Relay an. Ich hoffe jemand kann mir 
helfen :)

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Ich hab jetzt nicht alles durch den Simulator laufen lassen, aber du 
solltest erstmal alle Variablen, die in den ISRs geändert werden und im 
Hauptprogramm abgefragt werden, als volatile erklären, also zumindest 
dmx_data und counter_T .

von holger (Gast)


Lesenswert?

Ist das so gewollt oder fehlen da Klammern?

  if(counter_T !=255){
      counter_T++;
   }
  else
    counter_T = 0;
    TIMSK &= ~(1<<TOIE0);
    PORTD &= ~(24);


PS:

Das mag ich nicht:
  if(counter_T !=255){
      counter_T++;
   }

Das mag ich:
  if(counter_T !=255)
  {
      counter_T++;
  }

von BindochnurGast (Gast)


Lesenswert?

1
if (status & (1<<FE)) 
2
{   
3
  if (data==0) 
4
  { 
5
    dmx_channel=0;
6
    dmx_adress = (~PINB & 0xFF)+1;  
7
    if (~PIND & (1<<PD6)) 
8
    { 
9
      dmx_adress +=256;
10
    }
11
    flag=1;              // trigger update
12
  }
13
  else                // rx error
14
  {
15
    dmx_channel++;
16
  }
17
}
18
else 
19
{
20
  if (dmx_channel == dmx_adress)
21
  {
22
    dmx_data = data;
23
  }
24
  dmx_channel++;
25
}

Klammern sind so gesetzt, wie du das programmiert hast. Auch hier sind 
einzeilige if-Anweisungen gewesen - war das so gewollt?

von TestX .. (xaos)


Lesenswert?


von Johny_D94 (Gast)


Lesenswert?

Ich habe nun die genanten Variablen mit volatile gekennzeichnet.
In der Simulation geht alles wunderbar! Ich kann halt einfach nicht die 
Empfangs ISR testen.

So...Themawechsel Codestyle :) Wenn ich selber von Grundauf ein Programm 
schreibe dann sind die Klammern dort wo Ihr sie gerne hättet! Aber 
dieses Programm habe ich aus dem in meinem ersten Beitrag genanten Thema 
kopiert und abgeändert. Ich habe das abgeänderte dem alten angepasst. 
Trotzdem danke für den Tipp! Habe es jetzt noch geändert :)

Das resultat ist leider immer noch dass nichts funktioniert. B.z. es 
zieht nie ein Relay an...

von Bobble (Gast)


Lesenswert?

Bei einem DMX-Empfänger must du auch einen DMX-Sender benutzen.
USB->485 reicht nicht. DMX hat ein spezielles Timing!

von Johny_D94 (Gast)


Lesenswert?

Moing

Ja ich weiss. Ich hab zu Testzwecken ein kleines 6 Ch Pult.
Ich habe den USB => UART nur benutzt, um zu testen ob der MAX485 die DMX 
Signale die das Steuerpult sendet in UART umzuwandelt. Dem Spektakel 
habe ich mit HTerm auf dem PC zu geschaut, man sieht schön die 2 Byte 
die immer 0 sind und dann alle 6 Kanäle den aktuellen wert. Daraus 
schliesse ich dass Fehler NICHT bim MAX485 liegt!

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.