Forum: Mikrocontroller und Digitale Elektronik AVR Webserver und DMX


von Floxx (Gast)


Lesenswert?

Hallo Leute,

ich habe den Webserver von Uli Radig auf einen ATmega644 gespielt und 
läuft.
Nun will ich DMX Werte auslesen und diese am Webserver anzeigen. Gleich 
hab ich die DMX Bibliothek eingebunden, die ich schon bei vielen 
Projekten verwendet habe (natürlich angepasst) und ich stelle folgendes 
Problem fest:
Wenn das DMX Pult nicht angeschlossen ist, läuft der AVR Webserver ganz 
normal. Sobald ich aber den Webserver mit dem Pult über den SN75176 
verbinde, scheint sich der ATmega644 aufzuhängen.
Es wird auf keine pings mehr geantwortet, die Webseite lässt sich nicht 
mehr darstellen und der ENC28J60 schmiert ab.

Unten die DMX Routine zum Empfangen, obwohl ich nicht glaube, dass die 
einen Fehler hat. Vielleicht kommt ja wer von euch drauf, was da 
zwischen Webserver und USART nicht zusammenspielt. Die USART Routinen 
von Ulis Code hab ich übrigens komplett rausgehaut. Kommen also 
nirgendswo mehr vor.

Über Tipps bedanke ich mich schon im Voraus!
1
#include <stdlib.h>
2
#include <avr/io.h>
3
#include "config.h"
4
#include <util/delay.h>
5
#include <avr/interrupt.h>
6
#include "dmx_in.h"
7
8
#define        F_OSC        16000  //Oszillatorfrequenz in kHz (Arbeitet mit 8 und 16 Mhz)
9
#define       IBG           10    //IBG in ms
10
#define       DMX_Channels    512    //Anzahl der zu empfangenden DMX Kanäle
11
12
//Variablen
13
uint8_t   DMX_State_RX;        //DMX Empfangsstaus: 0=Leerlauf, 1=Break Empfangen, 2=Startbyte Empfangen, 3=Startadresse erreicht
14
uint8_t  DMX_Data[512];         //DMX Daten
15
uint16_t  DMX_Start_Address;      //DMX Startadresse für DMX Empfang
16
uint16_t   DMX_RX_Bytecounter;      //Variable für DMX Byte Counter (gezählt von Paket 1) für empfangen
17
18
uint16_t  DMX_Start_Address = 1;      //DMX Startadresse für DMX Empfang
19
uint8_t    DMX_Data[512];
20
21
//============================================================================================
22
//DMX Inizialisierung
23
//============================================================================================
24
void init_DMX_RX(void)
25
{
26
  UBRR0H  = 0;                    //Baud Rate Register Higher Byte
27
  UBRR0L  = ((F_OSC/4000)-1);              //Baud Rate Register Lower Byte
28
  UCSR0C  = (3<<UCSZ00)|(1<<USBS0);          //250kBaud, 2 Stopbits
29
  UCSR0B  = (1<<RXEN0)|(1<<RXCIE0);          //Empfang und IRQ aktivieren
30
  DMX_State_RX = 0;                  //DMX Empfang startet mit "Leerlauf"
31
}
32
33
ISR (USART0_RX_vect)
34
{
35
  
36
  uint8_t  UART_Status = UCSR0A;          //UART Status (Enthält auch das Flag für Frameerror)
37
  uint8_t  UART_Byte   = UDR0;          //Daten vom UART laden
38
  
39
  //Prüfung auf DMX RESET/BREAK
40
  if (UART_Status &(1<<FE0))              //UART Status auf Frameerror prüfen (wenn JA => Break Empfangen)
41
  {
42
    UCSR0A &= ~(1<<FE0);              //Frameerror Flag löschen
43
    DMX_RX_Bytecounter =  DMX_Start_Address;  //DMX Byte Counter auf >Startadresse<
44
//    DMX_RX_Bytecounter =  DMX_get_startaddress();  //DMX Byte Counter auf >Startadresse<
45
    DMX_State_RX = 1;                //DMX Status "Break Empfangen" (1)
46
  }
47
48
  //Prüfung auf Startbyte (und kein Frameerror war)
49
  else if (DMX_State_RX == 1)              //DMX Status "Break Empfangen" (1) abfragen
50
  {
51
    if (UART_Byte == 0)                //Wenn empfangenes Byte = 0 (=Startbyte)
52
    {DMX_State_RX = 2;}              //DMX Status "Startbyte Empfangen" (2)
53
    else
54
    {DMX_State_RX = 0;}              //ansonnsten DMX Status "Leerlauf" (0)  (und wieder alles von vorne)
55
  }
56
57
  //Prüfung auf Startadresse erreicht
58
  else if (DMX_State_RX == 2)              //DMX Status "Startbyte Empfangen" (2) abfragen
59
  {
60
    if (--DMX_RX_Bytecounter == 0)          //DMX Byte Counter -1 (und hat er "0" erreicht?)
61
    {
62
      DMX_RX_Bytecounter = 1;            //Bei Kanal 1 beginnen zu zählen...
63
      DMX_Data[0]= UART_Byte;            //Wert des 1. DMX Kanals in Speicher "0" speichern
64
      DMX_State_RX = 3;              //DMX Status "Startadresse erreicht" (3)
65
    }
66
  }
67
68
  //Weitere Kanäle speichern und abbrechen wenn alle Kanäle empfangen
69
  else if (DMX_State_RX == 3)              //DMX Status "Startadresse erreicht" (3) abfragen
70
  {
71
    DMX_Data[DMX_RX_Bytecounter++]= UART_Byte;    //Wert des X. DMX Kanals in Speicher "..." speichern
72
    if (DMX_RX_Bytecounter >= DMX_Channels)     //Prüfen ob die korrekte Anzahl an Kanälen empfangen wurde
73
    {DMX_State_RX = 0;}              //Wenn Ja: DMX Status "Leerlauf" (0)
74
  }
75
  
76
}

von Christian (Gast)


Lesenswert?

Also DMX und Webserver auf einem ATmega ist schon sportlich. Das Problem 
ist das er bei jedem Byte was er empfängt in den Interrupt springt.
Und ich kann dir aus meiner Efrahrung sagen das du je nach DMX Sender zu 
nicht mehr viel anderem kommst. Das heist ein paar PWM register für LED 
ansteuerung setzen geht schon zwischen den einzelenen DMX Blöcken. Aber 
eine Webseite auszugeben wird vermutlich nicht klappen. Ansonsten hängt 
dann solange dein DMX Empfang. Sprich du must dann den Empfang 
deaktivieren.
Gerade ein Webserver auf so einem kleinen Controller lastet ein System 
eigentlich auch voll aus.

Du könnstest das ganze z.B. mit einem Cortex M3 probieren. Die haben 
eine bessere Einbindung für Ethernet und du kannst z.B. den DMA nehmen 
um automatisch Daten von den Schnittstellen in den Speicher zu 
schauffeln. Mal davon abgesehen das die Controller noch wesentlich höher 
getaktet werden können.

Ansonsten kann man für sowas sicher auch ein Raspberry Pi einsetzen. Da 
läuft dann auch ein echter Webserver drauf. Der schafft das dann 
sicherlich die Daten aufzubereiten und darzustellen.

von Sven (Gast)


Lesenswert?

musst du bzw möchtest du die daten live aktualisiert?
Eventuell könntest du die dmx daten halt nur alle x milisekunden 
einlesen und während der unterbrechung die webschnitstelle bedinen.

von Floxx (Gast)


Lesenswert?

Hallo Sven,
Einmal vor anzeigen der Webseite die DMX Werte abfragen würde reichen!
Danke euch beiden für den Tipp ;-)

Man steht ab und zu einfach auf der Leitung...

von c-hater (Gast)


Lesenswert?

Christian schrieb:

> Gerade ein Webserver auf so einem kleinen Controller lastet ein System
> eigentlich auch voll aus.

Ach was. Ein vernünftig implementierter Webserver (also gerade ein 
nicht in C geschriebener und praktisch eine einzige riesige Busy-Loop 
darstellender) lastet das System zu ungefähr Null Prozent aus, solange 
niemand auf den Webserver zugreift. Da ist dann nämlich nur ein bissel 
LAN-Broadcast-Traffic zu bewältigen und sonst nix.

Wenn jemand zugreift, dann wird natürlich das System voll ausgelastet, 
um die Webseiten mit Vmax auszuliefern. Aber das ist jederzeit durch 
Interrupts unterbrechbar. Die einzige Folge ist, daß halt die Seiten 
langsamer ausgeliefert werden, sonst nix.

Natürlich kann man mit hinreichender Interruptfolgefrequenz die 
Seitenauslieferung ganz zum Erliegen bringen. Das wird aber mit DMX 
schwerfallen, denn das kann wegen der festgelegten Datenrate von 
250KBit/s und der ebenfalls festgelegten Zahl von 11 Bits/Paket maximal 
mit 22,7kHz Interrupts auslösen. Ein mit 20MHz getakteter AVR kann 
zwischen jedem der IRQs also mindestens rund 880 Befehle ausführen. Man 
muß den DMX-Listener schon richtig Scheiße implementieren 
(wahrscheinlich auch wieder in C und auch wieder als idiotische 
Busy-Loop), wenn davon nix mehr zum Betrieb eines Webserver über bleiben 
sollte...

Fazit: Nur C-ler glauben, daß der AVR für praktisch alles zu langsam 
ist. Richtige Programmierer wissen es besser.

von holger (Gast)


Lesenswert?

>Fazit: Nur C-ler glauben, daß der AVR für praktisch alles zu langsam
>ist. Richtige Programmierer wissen es besser.

Wo kommt dieser Schwachkopf eigentlich her?

von Christian (Gast)


Lesenswert?

Es geht halt nicht nur um Geschwindigkeit, Speicher ist halt auch immer 
ein Thema auf den kleinen Controllern. Und wer zum Teufel schreibt heute 
einen Webserver in Asembler...
C ist halt Standard. Und wenn man Code für verschiedene µC schreibt dann 
ist C sicher das Mittel der wahl. Außerdem kostet ein schneller und 
großer Controller auch nicht mehr als ATMega. Da hat man dann halt 
gleich das passende Interface drin.

Ich nehm heutzutage auch nen 32 Bitter um eine LED Blinken zu lassen. 
Denn ein Cortex M0 gibts auch schon ab 50 Cent ;-)

Gerade wenn man verschiedene Codeprojekte zusammen baut wird man sicher 
nicht gleich das beste Ergebnis haben weil jedes Stück für sich 
Entwickelt wurde. Wenn man alles gleich von vornerein darauf optimiert 
das man DMX Empfangen möchte und eine Webseite darstellen kann man 
sicher gewissen Overhead rauswerfen und das schnell genug bekommen.

Also ich denke man bedient sich heute einfach den technischen 
Möglichkeiten die da sind. Ich hab an meiner Wetterstation auch nen 
Raspberry Pi als Webserver dran. Kann man schön per ssh warten. Macht 
gleich einen FTP upload... Hatte das früher auch mal mit einem AVR am 
laufen. Aber so hab ich jetzt auch gleich noch ein Backup auf der SD 
Karte... und das Teil langweilt sich halt die meiste Zeit.

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.