mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATxMega16A4: Zu dumm für PWM?!


Autor: Christoph S. (mcseven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi *,

ich glaub ich bin zu doof, mir ein PWM Ambilight zu bauen. Code anbei, 
ist für die Hardware des STK-600 geschrieben (man kan also einfach die 
beigelegten Kabel stecken auf PortD und ein zweipoliges für USART).
#define F_CPU 7373742
#define MAX_CHANNELS 9
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

const unsigned int gamma22[256] = { 0, 564, 1125, 1684, 2240, 2794, 3345, 3893, 4438, 4981, 5521, 6059, 6594, 7126, 7656, 8183, 8707, 9229, 9748, 10265, 10779, 11290, 11799, 12305, 12808, 13309, 13807, 14303, 14796, 15286, 15774, 16260, 16742, 17222, 17700, 18175, 18647, 19117, 19584, 20048, 20510, 20970, 21427, 21881, 22333, 22782, 23229, 23673, 24114, 24553, 24989, 25423, 25855, 26283, 26710, 27133, 27554, 27973, 28389, 28803, 29214, 29622, 30028, 30432, 30833, 31231, 31627, 32021, 32411, 32800, 33186, 33569, 33950, 34329, 34705, 35078, 35449, 35818, 36184, 36547, 36908, 37267, 37623, 37977, 38328, 38677, 39023, 39367, 39709, 40048, 40384, 40718, 41050, 41379, 41706, 42031, 42353, 42672, 42989, 43304, 43616, 43926, 44234, 44539, 44841, 45142, 45440, 45735, 46028, 46319, 46607, 46893, 47177, 47458, 47737, 48014, 48288, 48560, 48829, 49096, 49361, 49623, 49883, 50141, 50397, 50650, 50900, 51149, 51395, 51639, 51880, 52119, 52356, 52591, 52823, 53053, 53281, 53506, 53729, 53950, 54169, 54385, 54599, 54811, 55020, 55228, 55433, 55635, 55836, 56034, 56230, 56424, 56616, 56805, 56992, 57177, 57360, 57541, 57719, 57895, 58069, 58241, 58411, 58578, 58743, 58906, 59067, 59226, 59383, 59537, 59690, 59840, 59988, 60134, 60278, 60420, 60559, 60697, 60832, 60965, 61097, 61226, 61353, 61478, 61601, 61722, 61841, 61957, 62072, 62185, 62295, 62404, 62511, 62615, 62718, 62818, 62917, 63014, 63108, 63201, 63292, 63380, 63467, 63552, 63635, 63716, 63795, 63872, 63948, 64021, 64092, 64162, 64230, 64296, 64360, 64422, 64482, 64540, 64597, 64652, 64705, 64756, 64806, 64854, 64900, 64944, 64986, 65027, 65066, 65103, 65139, 65173, 65205, 65236, 65265, 65293, 65319, 65343, 65366, 65387, 65406, 65424, 65441, 65456, 65470, 65482, 65493, 65503, 65511, 65518, 65524, 65528, 65531, 65533, 65535, 65535 };
unsigned char volatile currentChannelNumber = 255;
unsigned char volatile channelValues[MAX_CHANNELS] = {0,0,0,0,0,0,0,0,0};


ISR(USARTC1_RXC_vect) {
  unsigned char data;

  data  = USARTC1.DATA;
  
   if (currentChannelNumber == 0) { PORTD.OUT &= 0x7F; }

  channelValues[currentChannelNumber] = data;

  if (currentChannelNumber == 8)   {
    PORTD.OUT |= 0x80;
    TCD0.CCA = gamma22[channelValues[0]];
    TCD0.CCB = gamma22[channelValues[1]];
    TCD0.CCC = gamma22[channelValues[2]];
    TCD0.CCD = gamma22[channelValues[3]];
    TCD1.CCA = gamma22[channelValues[4]];
    TCD1.CCB = gamma22[channelValues[5]];
  }
  currentChannelNumber++;

  if (currentChannelNumber==9) { currentChannelNumber=0; }

}

int main() {
  
  PORTD.DIR = 0xFF;
  PORTD.OUT = 0b11111111;


  OSC.CTRL = OSC_RC32MEN_bm | OSC_XOSCEN_bm; //enable 32MHz oscillator and external OSC

  while(!(OSC.STATUS & OSC_RC32MRDY_bm)); //wait for stability for 32MHz


  while(!(OSC.STATUS & OSC_XOSCRDY_bm));  //wait for stability for External Clock Source

  CCP = CCP_IOREG_gc; // Conf.Änderung erlauben
  CLK.CTRL = 0x03;    // CSource Clock Extern
  CCP = CCP_IOREG_gc; // Conf.Änderung erlauben
  CLK.PSCTRL = 0x00;  // Prescaler 0 (Teiler)


  //USART INIT
  PORTC.DIR &= 0b10111111; // RX Bit (6) als Eingang
  PORTC.DIR |= 0b10000000; // TX Bit (7) als Ausgang
  USARTC1.CTRLA = 0b00010000; // Interrupt-Level: RX High, alles andere Off
  USARTC1.CTRLC = 0b00000011; // Async, NoPar, 1SBit, 8Bit Wortgröße

  USARTC1.BAUDCTRLA = 0b00010111; // 23 = 19k2
  USARTC1.BAUDCTRLB = 0b00000000; //BSCALe=3x0, 23 hat keine high bits, daher auch 0

  USARTC1.CTRLB = 0b00011000; // 000, RX ein, TX ein, Single-Speed, No-Multi, 2xDontCare

  //TIMER PORTD_0 INIT
  TCD0.CTRLA = 0x01;    // divide clock by 0, enable Timers
  TCD0.PER   = 0xFFFF;  // set resolution to 16Bit
  TCD0.CTRLB = 0xF3;    // enable frequency generation for all 4 Channels

  //TIMER PORTD_1 INIT
  TCD1.CTRLA = 0x01;
  TCD1.PER   = 0xFFFF;
  TCD1.CTRLB = 0xF3;    // Es scheint nichts zu machen, wenn mann Bits für
                        // Output-Compare setzt, die nicht vorhanden sind.
            // Manual schweigt sich darüber aus.

  CCP = CCP_IOREG_gc;   // Conf.Änderung erlauben
  PMIC.CTRL  = 0b00000111; // EN hi mi und lo level interrupts

  sei();

  TCD0.CCA = 0xFFFF;
  TCD0.CCB = 0xFFFF;
  TCD0.CCC = 0xFFFF;
  TCD0.CCD = 0xFFFF;
  TCD1.CCA = 0xFFFF;
  TCD1.CCB = 0xFFFF;

  while (1) { }

}

Ich möchte einfach nur, dass die LEDs entsprechend hell oder dunkler 
werden, die Software auf dem PC ist boblight 1.3; das Protokoll momo 
(also einfach 9 Bytes für R1-3,G1-3,B1-4); es funktioniert auch soweit 
ganz gut, nur flackern die LEDs reproduzierbar sporadisch auf. Habe 
Single-Slope,
DualS und Freq-Modi der Timer probiert.

Ich hatte zunächst auf ein Indexproblem mit der Channelnumber getippt, 
aber wie ich's auch drehe und wende, das glaub ich ist es nicht. Es 
scheint eine Art Konflikt zwischen USART Interrupt und Timer Interrupt 
zu sein, denn wenn ich Code zum ändern der Helligkeit ohne USART 
schreibe funktioniert alles einwandfrei.

Könnte das vielleicht jemand auf einem STK600 nachvollziehen oder hätte 
sonst jemand einen Tip?

Danke, Christoph

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christoph Söllner schrieb:
> ich glaub ich bin zu doof

Kommt drauf an, wie Deine Vorkenntnisse mit MCs sind.

Die Xmega sind ja noch sehr wenig verbreitet, daher vielleicht nicht 
gerade für Einsteiger geeignet.

Ich benutze lieber die ATtiny, die sind so schön klein und 
unkompliziert.

Du solltest vielleicht erstmal das Protokoll beschreiben, nachdem Du die 
Daten über die UART schickst.
Bzw. wenn Du kein Protokoll hast, solltest Du schleunigst eins 
spezifizieren, da Du ja mehr als ein Byte übertragen willst.

Ein Protokoll muß minimal synchronisierend sein. D.h. nach einem 
Übertragungsfehler muß es für den Master eine Möglichkeit geben, dem 
Slave ein gültiges Paket zu senden, völlig unabhängig davon, wo grade 
die Statemachine (bzw. der Parser) des Slaves hängt.


Ich mache für die UART immer erstmal ne FIFO.
Die Mainloop liest dann die FIFO aus und überprüft den Paketrahmen.
Wenn ein vollständiges und gültiges Paket empfangen wurde, parst die 
Mainloop es.


Peter

Autor: Christoph S. (mcseven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Peter, Protokoll ist einfach 9 Bytes hintereinander, dann 10ms Pause, 
dann wieder 9 Bytes hintereinander usw.

Es geht mir aber nicht um die Syncronisation. Zum Testen soll es 
ausreichen, dass bei einem Byteverlust sich die Kanalwerte verschieben.

Es geht mir darum, dass ich wohl die HArdware-PWM entweder falsch 
ansteuere, der Chip defekt ist (unwahrscheinlich) oder eben einen Bug 
hat.

Am Oszi sehe ich auf dem entsprechenden PWM-Kanal, dass bei Änderung des 
Wertes zwischendurch hin und wieder ein Zyklus übersprungen wird, also 
entweder ein falscher Wert in das Timer-Register geschrieben wird oder 
der Timer sich irgendwie resettet.

Daher meine Frage an die Gemeinschaft, ob der Code oben Sinn macht mit 
nem
Xmega A4; Kenntnisse mit normalen Megas und Tinys hab ich genug, aber 
keiner von denen hat 16 16bit Hardware-PWM-Channels. Und Soft-PWM hab 
ich schon, die ist zu langsam.

Danke, Christoph

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Xmega habe ich noch keinen. Die scheinen aber langsam verfügbar zu sein, 
Farnell hat schon einige Typen lagernd.

Was mir bei den Xmega aber schwer auf den Magen schlägt, ist die 
fehlende 5V-Toleranz der IO-Pins. Daher sind die zur Zeit für mich tabu.

Die Gerätelogik ist für TTL-Pegel ausgelegt (2,4..5V = high). D.h. ARM7 
von NXP kann ich daher verwenden.

Es ist auch blöd, daß die XMega nicht pinkompatibel zu ATmega128/1280 
sind.


Peter

Autor: Knut Ballhause (Firma: TravelRec.) (travelrec) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
XMegas gibt es lagernd bei CSD-electronics und bei TME.eu . 5V-I/O 
braucht man bei den XMegas nicht mehr wirklich, alle dafür interessante 
Peripherie (SD-Karte, Bluetooth, Ethernet, RS232/RS485) gibt es als 
3.3V-Bausteine. Lediglich bei einigen LCDs und blauen/weißen LEDs muß 
man ein wenig in die Trickkiste greifen.

Autor: GG (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Servus,

3,3 Volt Displays:

 DOGM128, DOGM132, DOGM162  gibt es bei Reichelt.

Gruß GG

Autor: Christoph S. (mcseven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi *,

danke, ich denke, es wird gelöst werden. Kann es erst heute abend 
testen, aber der Fehler scheint im Schreibzugriff auf die *.CCx-Register 
zu liegen. Diese sind (wie übrigens im Datenblatt nur winzigst erwähnt) 
die direkten Counter-Werte. Möchte man die gepufferte Variante benutzen, 
so ist auf CCxBUF[L:H] zu schreiben.
    TCD0.CCA = gamma22[channelValues[0]];
    TCD0.CCB = gamma22[channelValues[1]];
    TCD0.CCC = gamma22[channelValues[2]];
    TCD0.CCD = gamma22[channelValues[3]];
    TCD1.CCA = gamma22[channelValues[4]];
    TCD1.CCB = gamma22[channelValues[5]];

müßte somit werden zu:
    TCD0.CCABUF = gamma22[channelValues[0]];
    TCD0.CCBBUF = gamma22[channelValues[1]];
    TCD0.CCCBUF = gamma22[channelValues[2]];
    TCD0.CCDBUF = gamma22[channelValues[3]];
    TCD1.CCABUF = gamma22[channelValues[4]];
    TCD1.CCBBUF = gamma22[channelValues[5]];

und alles sollte passen. Wie gesagt, verifiziert wird das heute abend. 
Vielleicht erspart das noch jemandem 3 Abende Kopfkratzen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.