Forum: Mikrocontroller und Digitale Elektronik DMX Servo- und Ledcontroller mit PWM


von Adrian S. (adrian_s)


Angehängte Dateien:

Lesenswert?

Hallo MC-Freunde,

ich hab ein Problem und benötige dringend Eure Hilfe.
Da ich hier neu bin, kurz was zu meiner Person. Mein Name ist Adrian, 
bin 29 Jahre jung oder alt und "studiere" Elektrotechnik in der 
Technikerschule Augsburg.
Da ich im Fach Mikrocontroller Technik nicht alzu gut dastehe, hat mir 
der Dozent angeboten ein Referat über ein Projekt eines anderen Dozenten 
zu halten.

Hierbei dreht es sich um einen DMX Controller für zwei Servoantriebe 
(Pan und Tilt) sowie einer RGB LED. Die Ansteuerung erfolgt über ein DMX 
Lichtpult. Diese DMX Signale werden durch diesen Controller 
http://www.hoelscher-hi.de/hendrik/light/dmxservo.htm
auf brauchbare Siganle für die Servos und LED gewandelt (PWM).

So, das Referat ist soweit fertig (DMX Bus und Protokoll sowie das 
Projekt an sich selbst sind erklärt). Nur muss ich nun noch die PWM 
erklären.
Und da hängst bei mir.

Wie funktioniert das genau. Ich gebe über einen Fader ein DMX Signal 
aus; wie wird damit dann die PWM angesteuert sodas, je nach 
Faderstellung die LED heller oder dunkler wird, bzw. sich der Motor nach 
link oder rechts bewegt.

Ich hab keine Ahnung. Ich hoffe Ihr könnt mir helfen.

Beste Grüße und ein schönes Wochenende
Adrian

von Narfie (Gast)


Lesenswert?

Hi Adrian,

du hast ja bereits das DMX-Protokoll beschrieben (verstanden?). Pro 
Kanal wir ein Wert übertragen im Bereich von 0..255 
(http://www.soundlight.de/techtips/dmx512/dmx512.htm).

Diesen Eingabewert nutzt der DMX Decoder um ein Servo bzw. die LED auf 
einen bestimmten Stellwert bzw. Helligkeit zu fahren. Wie PWM 
funktioniert findest du auf dieser Seite ausführlich beschrieben, ebenso 
wie die Ansteuerung eines Servos mit Hilfe eines MC funktioniert.

Viele Grüße.

von Adrian S. (adrian_s)


Lesenswert?

Hallo Narfie,

vielen Dank für die Antwort. Mir ist es nur nicht klar wie der DMX Wert 
vom MC im Programm aufgenommen wird, sprich wie der Code hierbei 
aussehen muss.
Bin da nämlich nicht so fit. Hast du mir oder jemand vielleicht nen 
Beispielcode?

Vielen Dank und nen schönen Sonntag

von Martin P. (billx)


Lesenswert?

beispiel gibts doch bei hendrik?

von Adrian S. (adrian_s)


Lesenswert?

Echt? Sind das nicht nur Assembler Codes?

von weinbauer (Gast)


Lesenswert?

Du weißt aber schon, dass digitale Daten aus Bits und Bytes bestehen?
Dass 8 Bit ein Byte sind? Dass n Byte nen Wert von 0 bis 255 annehmen
kann und dass bei der Übertragung per UART / serielle Schnittstelle
meist 8-Bit ergo 1 Byte hintereinander weg übertragen werden?
Das die DMX-Frames ebenso jeweils ein Byte sind?

von Adrian S. (adrian_s)


Lesenswert?

Ja schon, aber was hat das bezüglich mit meiner Frage zu tun?

von Stephan (Gast)


Lesenswert?

Nun, er fragt ganz einfach, ob Du überhaupt die Grundlagen der 
Digitaltechnik verstanden hast...

Umwandlung von DMX zu PWM geht so:

DMX512 bedeutet, das DMX-Steuerpult hat maximal 512 Potentiometer zur 
Verfügung. Jedes Poti kann einen analogen Spannungswert zwischen 0V und 
VCC an einen Analog-Digital-Eingang eines Mikrocontrollers geben, mit 
einer Auflösung von 8 Bit. Dieser Mikrocontroller setzt die maximal 512 
Werte zu einem "Stream" aus 512 Acht-Bit-Werten (also maximal 512 Byte) 
zusammen, plus Start-Byte "0" am Anfang, und gibt diesen Stream an der 
UART als seriellen Datenstream aus.

Jeder Empfänger hat eine vorher eingestellte Adresse, zwischen 1 und 
512, z. B. "13". Der Stream wird ständig überwacht, und die Bytes 
mitgezählt. Wenn nun sein 13. Byte an der Reihe ist, wird dieser Wert 
gespeichert, z. B. "240". Das Beispiel bedeutet, dass das Poti fast ganz 
am Anschlag bzw. VCC steht.

Da das Auge nicht linear empfindlich ist, sondern so ähnlich wie 
logarithmisch, muss man also die möglichen 256 Werte in einen 
logarithmischen Wert umwandeln. Auch reicht oftmals die Auflösung von 8 
Bit nicht aus, um ein sanftes Auf- und Abblenden zu erreichen.

Wenn also 8 Bit Auflösung zu wenig ist, braucht man also z. B. 10 Bit 
oder 12 Bit. Wir versuchen das Ganze mal mit 10 Bit und berechnen also 
1024 mal den Logarithmus aus 0 bis 1024. Daraus nehmen wir dann jeden 4. 
Wert und haben unsere 256 logarithmischen Werte für die PWM.

Einfach wird's wenn der Microkontroller eine Hardware-PWM hat. Man 
stellt sie auf 10 Bit ein, und gibt das dann ungefähr so aus:

LOGLISTE(255) = {0,0,1,1,3,6,13,50,...240,250,255} //255 Werte.

Input I; //Lese den 13. Wert aus dem Datenstream ein
OUT PWM-Register (LOGLISTE(I)); //Suche diesen Wert in der 256-Einträge- 
//Liste "LOGLISTE"
                                //und schreibe ihn in das PWM-Register

So ähnlich funktioniert das.
Stephan.

von Stephan (Gast)


Lesenswert?

Kleine Korrektur: Die LOGLISTE enthält 256 Werte, und geht natürlich bis 
1024. "0" bedeutet bei den LEDs (und einer 10-Bit-PWM), sie sind ganz 
ausgeschaltet, "1024" bedeutet, sie sind ganz angeschaltet.
Stephan.

von Adrian S. (adrian_s)


Lesenswert?

Okay,

danke Jungs für die Erklärung. Dann schau ich mal ob ich damit klar 
komm.

Gruß
Adrian

von Adrian S. (adrian_s)


Lesenswert?

@ Stephan...

Die Frage ob ich die Grundlagen verstanden habe...na ja, das Fach hatte 
ich vor 2 Jahren abgelegt und muss eben jetzt noch ne gute mündliche 
Note erreichen, da es sonst schlecht aussieht. Da soviel Zeit dazwischen 
liegt, bin ich in dem Gebiet der Mikrocontroller-Technik ein 
wenig...okay sehr...eingerostet.

von Adrian S. (adrian_s)


Lesenswert?

Hallo Freunde,

ich bekomm das einfach nicht hin. Ich hab hier ein STK500 mit nem 
ATMEGA32 und versuche eine PWM bzw LED Fading hinzubekommen. Ich schaff 
es einfach nicht. Wollte nämlich selbst an dem Board testen, um ein 
wenig mehr Verständnis für die Thematik zu bekommen.
Könnt Ihr mir bitte helfen oder mit einem Beispielprogramm unter die 
Arme greifen?

Vielen vielen Dank
Grüße
Adrian

von Falk B. (falk)


Lesenswert?

Siehe Artikel LED-Fading.

von markus (Gast)


Lesenswert?

schonmal an das tutorial hier gedacht? da ist alles super erklärt

von Adrian S. (adrian_s)


Lesenswert?

Guten Morgen miteinander,

ich bin jetzt mal soweit gekommen das die letzte LED auf dem Board von 
selbst fadet (na ja eher blinkt), und ich mit zweit Tastern die 
Helligkeit von der ersten LED regeln kann.

Ich würde aber gern die Helligkeit anhand eines externen Potis oder 
Faders regeln. Könnt Ihr mir dabei helfen. Anbei der Code.


// Defines an den Controller und die Anwendung anpassen

#define F_CPU 8000000                   // Systemtakt in Hz
#define F_PWM 100                       // PWM-Frequenz in Hz
#define PWM_STEPS 255                   // PWM-Schritte pro 
Zyklus(1..255)
#define PWM_PORT PORTD                  // Port für PWM
#define PWM_DDR DDRD                    // Datenrichtungsregister für 
PWM

// ab hier nichts ändern, wird alles berechnet

#define T_PWM (F_CPU/(F_PWM*PWM_STEPS)) // Systemtakte pro PWM-Takt

// includes

#include <stdint.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
 #include <avr/delay.h>
// globale Variablen

volatile uint8_t pwm_setting[8];                    // Einstellungen für 
die einzelnen PWM-Kanäle

// Timer 1 Output COMPARE A Interrupt

ISR(TIMER1_COMPA_vect) {
    static uint8_t pwm_cnt=0;
    uint8_t tmp=0, i=0, j=1;

    OCR1A += (uint16_t)T_PWM;

    for (; i<8; i++) {
      if (pwm_setting[i] > pwm_cnt) tmp |= j;
            j<<=1;
  }
    PWM_PORT = ~tmp;                         // PWMs aktualisieren
    if (pwm_cnt==(uint8_t)(PWM_STEPS-1))
        pwm_cnt=0;
    else
        pwm_cnt++;


}




int main(void) {

    // PWM einstellen

    PWM_DDR = 0xFF;         // Port als Ausgang
  DDRA = 0x00;

  PORTA=1;

    // Timer 1 OCRA1, als variablem Timer nutzen

    TCCR1B = 1;             // Timer läuft mit vollem Systemtakt
    TIMSK |= (1<<OCIE1A);   // Interrupt freischalten

    sei();                  // Interrupts gloabl einschalten

/******************************************************************/
// nur zum Testen, im Anwendungsfall löschen

    volatile uint8_t tmp;
const uint8_t t1[8]={27, 40, 3, 17, 150, 99, 5, 9};
const uint8_t t2[8]={27, 40, 3, 0, 150, 99, 5, 9};
const uint8_t t3[8]={27, 200, 238, 50, 3, 99, 3, 255};
const uint8_t t4[8]={0, 0, 0, 0, 0, 0, 0, 0};
const uint8_t t5[8]={0, 0, 0, 0, 0, 0, 0, 9};
const uint8_t t6[8]={33, 33, 33, 33, 33, 33, 33, 33};

// Messung der Interruptdauer
    tmp =0;
    tmp =0;
    tmp =0;

// Debug
 pwm_setting[0]=1;
 pwm_setting[1]=10;
 pwm_setting[2]=15;
 pwm_setting[3]=20;
 pwm_setting[4]=25;
 pwm_setting[5]=70;
 pwm_setting[6]=200;
 pwm_setting[7]=254;

 //   memcpy(pwm_setting, t3, 8);

  //  memcpy(pwm_setting, t2, 8);

//    memcpy(pwm_setting, t3, 8);

    //memcpy(pwm_setting, t4, 8);

   // memcpy(pwm_setting, t5, 8);

 //   memcpy(pwm_setting, t6, 8);

/*********************************************************************/

while(1){
  if(!(PINA & (1<<0)))

    pwm_setting[0]++;

  if(!(PINA & (1<<1)))

    pwm_setting[0]--;




    _delay_us(100);
pwm_setting[7]=pwm_setting[7] + 1;
if(pwm_setting[7] == 150)
  pwm_setting[7] = 1;
_delay_us(100);
_delay_us(100);
_delay_us(100);
_delay_us(100);

}
   return 0;
}

von Falk B. (falk)


Lesenswert?

@  Adrian Spiegel (adrian_s)

>ich bin jetzt mal soweit gekommen das die letzte LED auf dem Board von
<selbst fadet (na ja eher blinkt),

Dann stimmt der Takt nicht. Prüfe die AVR Fuses, vor allem CLKDIV.

>Ich würde aber gern die Helligkeit anhand eines externen Potis oder
>Faders regeln. Könnt Ihr mir dabei helfen. Anbei der Code.

Bring erstmal den aktuellen Code VOLLSTÄNDIG in Ordnung. Die LED muss 
faden, nicht blinken!

Dann lies dir das Tutorial zum ADC durch, dort steht alles drin.

MFG
Falk

von Adrian S. (adrian_s)


Lesenswert?

Okay danke...ich werd mein bestes versuchen.

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.