Forum: Mikrocontroller und Digitale Elektronik DMX - kein Empfang


von Kai (kai_tl91)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich bin seit Tagen am verzweifeln. Ich möchte per ATmega644P DMX 
empfangen (ganzes Uni) und danach UART an den PC senden.
Die Verbindung PC <-> MC funktioniert. Allerdings erkennt der MC kein 
DMX Break und somit empfänger er nichts. Das DMX Pult ist ein kleines 6 
Kanal und funktioniert bei Lampen entsprechend.

Im Anhang der Schaltplan. Was ich schon versucht habe: Pins am Stecker 
getauscht (A-B), Signal mit ~DATA inventiert, Baud Einstellungen 
überarbeitet, etc. Bislang ohne Erfolg. Leider sieht man manchmal den 
Wald vor lauter Bäume nicht.
F_CPU 16000000UL
1
void init_DMX_RX(void)
2
{ 
3
UBRR1L  = ((F_CPU/16000000UL)-1);          //250kbaud, 8N2
4
  UBRR1H = 0;
5
  //UBRR1L = ((16000/4000)-1);
6
  //UBRR1 = ((F_CPU)/((250000)*16)-1);
7
  //((F_CPU)/((250000)*16)-1); //  
8
  //UCSR1C  = (3<<UCSZ10)|(1<<USBS1);
9
  UCSR1C = (1<<USBS1)|(1<<UCSZ12)|(1<<UCSZ10);
10
  UCSR1B  = (1<<RXEN1)|(1<<RXCIE1);
11
  
12
  gDmxState= IDLE;
13
14
  uint16_t i;
15
  for (i=0; i<sizeof(DmxRxField); i++)
16
  {
17
    DmxRxField[i]= 0;
18
  }
19
  DmxAddress = 1;
20
}
21
22
ISR (USART1_RX_vect)
23
{
24
  uint8_t USARTstate= UCSR1A;            //get state
25
  uint8_t DmxByte= (UDR1);              //get data
26
  uint8_t DmxState= gDmxState;          //just get once from SRAM!!!
27
28
  IndFlags |= (1<<SIGNAL_COMING);
29
 
30
  if (USARTstate & (1<<0xFE))            //check for break
31
    {
32
      UCSR1A &= ~(1<< 0xFE);              //reset flag
33
      DmxCount=  DmxAddress;            //reset frame counter
34
      gDmxState= BREAK;
35
      DMXStateOPT = 0x01;
36
    }
37
38
  else if (DmxState == BREAK)
39
    {
40
      if (DmxByte == 0) 
41
      {
42
        gDmxState= STARTB;            //normal start code detected
43
        gDmxPnt= ((uint8_t*)DmxRxField +1);
44
        DMXStateOPT = 0x01; //Gültiger DMX Wert empfangen
45
      }
46
      else gDmxState= IDLE;
47
    }
48
  
49
  else if (DmxState == STARTB)
50
    {
51
      PORTD |= ( 1 << PD7 ); //PORTD ^= ( 1 << PD7 );
52
      if (--DmxCount == 0)            //start address reached?
53
      {
54
        gDmxState= STARTADR;
55
        DmxRxField[0]= DmxByte;
56
      }
57
    }
58
59
  else if (DmxState == STARTADR)
60
    {
61
      uint8_t *DmxPnt;
62
      DmxPnt= gDmxPnt;
63
      *DmxPnt= DmxByte;
64
      if (++DmxPnt >= (DmxRxField +sizeof(DmxRxField)))   //all ch received?
65
      {
66
        gDmxState= IDLE;
67
        IndFlags |= (1<<VALID_DMX);
68
      }
69
      else gDmxPnt= DmxPnt;
70
      //PORTD &= ~( 1 << PD7 );
71
    }
72
    //PORTD |= ( 1 << PD7 );    
73
  uart_putc(DmxByte);   //send to PC        
74
}

In Main wird die Schleife solange durchlaufen, bis ein gültiges Signal 
anliegt:
1
//FIXME
2
dev_mode = 0;
3
  if (dev_mode == 0)
4
  {
5
    //DMX Start Rec
6
    init_DMX_RX();
7
    dmx_set_receive(1);
8
  } else if (dev_mode == 1)
9
  {
10
    //DMX Start Trasmit
11
    init_DMX_TX();
12
    dmx_set_receive(0);
13
  }
14
  mytimer_wait_MS(200);
15
  led_status(1);
16
  while(DMXStateOPT != 0x01) //Warte auf erstes DMX Paket
17
  {
18
    led_status(1);
19
    for (i=0; i < 150; i++)
20
    {
21
      service_uart_read(subuf);
22
      mytimer_wait_MS(1);
23
      scheduler();
24
    }
25
    led_status(0);
26
    for (i=0; i < 150; i++)
27
    {
28
      service_uart_read(subuf);
29
      mytimer_wait_MS(1);
30
      scheduler();
31
    }
32
  }
33
34
led_status(0);
35
  
36
  for (;;)
37
  {
38
    led_status(0);
39
    scheduler();
40
    service_uart_read(subuf);
41
  }
42
  while(1);

Ich kann den Fehler im Code einfach nicht finden. Oder ist es vielleicht 
ein Hardwareproblem? Ich wäre über Hilfe sehr dankbar. Grüße

von H. H. (hhinz)


Lesenswert?

Du hast den 75176 spiegelverkehrt im Verdrahtungsplan eingezeichnet. 
Hast du im realen Aufbau darauf geachtet?

von Kai (kai_tl91)


Lesenswert?

Nein, was meinst du? Ich hatte das Pinlayout überprüft. Sollte eig. 
Passen.

von Monk (roehrmond)


Lesenswert?

Die beiden Versorgungspins auf der rechten Seite des AVR sind nicht 
angeschlossen.

Außerdem fehlen auf beiden Seiten die Abblock-Kondensatoren der 
Stromversorgung.

Warum benutzt du zur Einstellung der Baudrate nicht die Makros azs der 
libc? 
https://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html

Hast den Taktteiler per Fuse oder CLKPR Register auf 1 geändert?

von Gerald B. (gerald_b)


Lesenswert?

Bei RS485, was DMX ja ist, A und B zu vertauschen ist auch ein beliebter 
Fehler, der die Funktion zuverlässig verhindert.

von Monk (roehrmond)


Lesenswert?

Rx und Tx würde ich nicht so völlig ungeschützt auf die Sub-D Buchse 
legen. Packe da wenigstens zwei 100 Ohm Widerstände zwischen.

von H. H. (hhinz)


Angehängte Dateien:

Lesenswert?

Kai schrieb:
> Nein, was meinst du?

Siehe Anhang.

von Kai (kai_tl91)


Lesenswert?

Ich hatte mit einem alten Oszi am Kontroller gemessen. Da kam was an, 
wenn das Pult sendet. Ich vermute, dass der Empfänger korrekt eingebaut 
ist.

von H. H. (hhinz)


Lesenswert?

Kai schrieb:
> Ich vermute,

Das ist natürlich eine verdammt gute Methode.

von Kai (kai_tl91)


Lesenswert?

Monk schrieb:
> Die beiden Versorgungspins auf der rechten Seite des AVR sind nicht
> angeschlossen.
>
> Außerdem fehlen auf beiden Seiten die Abblock-Kondensatoren der
> Stromversorgung.
>
> Warum benutzt du zur Einstellung der Baudrate nicht die Makros azs der
> libc?
> https://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html
>
> Hast den Taktteiler per Fuse oder CLKPR Register auf 1 geändert?

Stimmt! Werde ich nochmal probieren!

von Kai (kai_tl91)


Lesenswert?

H. H. schrieb:
> Kai schrieb:
>> Ich vermute,
>
> Das ist natürlich eine verdammt gute Methode.

Ja, es war nicht die einzigste Prüfung. Soweit alles wie nach Schaltplan 
verdrahtet.

von Kai (kai_tl91)


Lesenswert?

Kai schrieb:
1
> ISR (USART1_RX_vect)
2
> {
3
>   uint8_t USARTstate= UCSR1A;            //get state
4
>   uint8_t DmxByte= (UDR1);              //get data
5
>   uint8_t DmxState= gDmxState;          //just get once from SRAM!!!
6
>   IndFlags |= (1<<SIGNAL_COMING);
7
> 
8
>   if (USARTstate & (1<<0xFE))            //check for break
9
>     {
10
>       UCSR1A &= ~(1<< 0xFE);              //reset flag
11
>       DmxCount=  DmxAddress;            //reset frame counter
12
>       gDmxState= BREAK;
13
>       DMXStateOPT = 0x01;
14
>     }

Der Fehler liegt im DETAIL:
1
 if (USARTstate & (1<<0xFE))            //check for break

muss heißen:
1
 if (USARTstate & (1<<FE1))            //check for break

Jetzt wird der Break wohl erkannt, die Werte sind allerdings 
unbrauchbar. Ich probiere morgen nochmal Leitung A-B zu tauschen.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Kai schrieb:
> Ich probiere morgen nochmal Leitung A-B zu tauschen.
Du hast doch ein Oszi, dann musst du doch nichts probieren. Einfach 
messen, was an uC-Pin ankommt.

von Kai (kai_tl91)


Lesenswert?

Lothar M. schrieb:
> Kai schrieb:
>> Ich probiere morgen nochmal Leitung A-B zu tauschen.
> Du hast doch ein Oszi, dann musst du doch nichts probieren. Einfach
> messen, was an uC-Pin ankommt.

Es ist leider ein altes Oszi. Es hat keine Speicherung und somit sind 
Daten daraus schlecht auszulesen. Das was am mc ankommt ist klar... nur 
ob die Daten korrekt sind ist unklar.

: Bearbeitet durch User
von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Kai schrieb:
> Es hat keine Speicherung und somit sind
> Daten daraus schlecht auszulesen.

Du musst erstmal gar keine Datn mit dem Oszi dekodieren, sondern nur 
schauen, ob die RX Leitung am MC in Ruhe auf high ist.

von Kai (kai_tl91)


Lesenswert?

Ich habe A-B getauscht und zusammen mit dem Softwarefehler in der Break 
Erkennung funktioniert das System nun endlich.

Eine Frage ist mir aber noch geblieben: Wieso:
Monk schrieb:
> Rx und Tx würde ich nicht so völlig ungeschützt auf die Sub-D Buchse
> legen. Packe da wenigstens zwei 100 Ohm Widerstände zwischen.

?

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.