Ich versuche hier einen Sinus als PWM auszugeben. Was mit einer LED auch soweit ganz gut aussah (der _delay-Wert war um es sichtbar zu machen natürlich höher als jetzt), entpuppte sich mit kürzeren _delay-Wert und Oszi am PORT D5 (OC1A) als reine Berg- und Talfahrt auf den Scheitelpunkten. Als uP verwende ich einen Mega32 mit 12 Mhz Quarz. Als RC-Glied habe ich nach Vorgaben 100K un 22nF eingesetzt und unten audfgeführtes Programm geflasht #include <stdlib.h> #include <avr/io.h> #define F_CPU 12000000UL #include <util/delay.h> #include <avr/interrupt.h> unsigned short a; unsigned char Tabelle[] = { 0x80,0x83,0x86,0x89,0x8C,0x8F,0x92,0x95, 0x98,0x9B,0x9E,0xA1,0xA4,0xA7,0xAA,0xAD, 0xB0,0xB3,0xB6,0xB9,0xBB,0xBE,0xC1,0xC3, 0xC6,0xC9,0xCB,0xCE,0xD0,0xD3,0xD5,0xD7, 0xD9,0xDC,0xDE,0xE0,0xE2,0xE4,0xE6,0xE7, 0xE9,0xEB,0xED,0xEE,0xF0,0xF1,0xF2,0xF4, 0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC, 0xFC,0xFD,0xFD,0xFE,0xFE,0xFE,0xFE,0xFE, 0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFD,0xFD, 0xFC,0xFC,0xFB,0xFA,0xF9,0xF8,0xF7,0xF6, 0xF5,0xF4,0xF2,0xF1,0xF0,0xEE,0xED,0xEB, 0xE9,0xE7,0xE6,0xE4,0xE2,0xE0,0xDE,0xDC, 0xD9,0xD7,0xD5,0xD3,0xD0,0xCE,0xCB,0xC9, 0xC6,0xC3,0xC1,0xBE,0xBB,0xB9,0xB6,0xB3, 0xB0,0xAD,0xAA,0xA7,0xA4,0xA1,0x9E,0x9B, 0x98,0x95,0x92,0x8F,0x8C,0x89,0x86,0x83, 0x80,0x7C,0x79,0x76,0x73,0x70,0x6D,0x6A, 0x67,0x64,0x61,0x5E,0x5B,0x58,0x55,0x52, 0x4F,0x4C,0x49,0x46,0x44,0x41,0x3E,0x3C, 0x39,0x36,0x34,0x31,0x2F,0x2C,0x2A,0x28, 0x26,0x23,0x21,0x1F,0x1D,0x1B,0x19,0x18, 0x16,0x14,0x12,0x11,0x0F,0x0E,0x0D,0x0B, 0x0A,0x09,0x08,0x07,0x06,0x05,0x04,0x03, 0x03,0x02,0x02,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x02,0x02, 0x03,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 0x0A,0x0B,0x0D,0x0E,0x0F,0x11,0x12,0x14, 0x16,0x18,0x19,0x1B,0x1D,0x1F,0x21,0x23, 0x26,0x28,0x2A,0x2C,0x2F,0x31,0x34,0x36, 0x39,0x3C,0x3E,0x41,0x44,0x46,0x49,0x4C, 0x4F,0x52,0x55,0x58,0x5B,0x5E,0x61,0x64, 0x67,0x6A,0x6D,0x70,0x73,0x76,0x79,0x7C }; int main(void) { DDRD = 0xFF; PORTD = 0x00; TCCR1A |= (1<<WGM10); // MODE TCCR1B |= (1<<CS11); //PRE TIMSK |= (1<<OCIE1A); sei(); while(1) { for(a = 1; a < 255; a++) { OCR1A = Tabelle[a]; _delay_us(10); } } return 0; } ISR(TIMER1_COMPA_vect) { PORTD ^= (1<<PD5); } Was haut denn hier jetzt nicht hin ? Gruß aus Berlin Ingo
@ Ingo Laabs (grobian) >Scheitelpunkten. Als uP verwende ich einen Mega32 mit 12 Mhz Quarz. Als >RC-Glied habe ich nach Vorgaben 100K un 22nF eingesetzt und unten >audfgeführtes Programm geflasht 12 MHz und 8-Bit PWM macht 46,8kHz PWM-Frequenz. 100K und 22nF macht 72Hz Grenzfreqeunz. Sollte erstmal passen. ABER > TCCR1A |= (1<<WGM10); // MODE > TCCR1B |= (1<<CS11); //PRE > TIMSK |= (1<<OCIE1A); Ne Hardware-PWM braucht keinen Output Compare Overflow. Das kann die Hardware alleine. > OCR1A = Tabelle[a]; > _delay_us(10); Ähhhhh, bei 48kHz (~20us) PWM-Frequenz ist ein Reload von 10us wenig sinnvoll. Besser wäre es, den Reload im Timer Overflow Interrupt zu machen, dann ist es nämlich immer synchron und es gehen keine Werte verloren. MFG Falk
ein screenshot sagt mehr als Gschichterln ala "reine Berg- und Talfahrt auf den Scheitelpunkten" - die Hellseherei hat heute geschlossen -mah
Michael Haberler schrieb: > ein screenshot sagt mehr als Gschichterln ala "reine Berg- und Talfahrt > auf den Scheitelpunkten" - die Hellseherei hat heute geschlossen > > -mah werde gleich Foto machen...moment
so Foto da.....Glaskugel wird nicht gebraucht. Ist zwar ein wenig undeutlich, aber man erkennt das Problem..denke ich doch
1 | uint8_t a; //läuft automatisch über |
2 | |
3 | while(1) |
4 | {
|
5 | OCR1A = Tabelle[a]; |
6 | _delay_us(10); |
7 | a++; |
8 | }
|
Ist bestimmt etwas besser.
Falk Brunner schrieb:
> Mach mal das Delay länger, so 100..200us.
ich war schon bei 1 ms ohne Wirkung.
ich denke mal die Aussage, dass Werte ausgelassen werden oder verloren
gehen erklärt -denke ich mal mein Problem.
Das blöde ist nur..ich muss jetzt jedesmal in den Keller rennen um die
Schaltung am Oszi anzuschließen, weil kein Rechner im Keller...stöhn
Ich würde mal folgendes versuchen: - Vorteiler nur 1 nicht 8, CS11 nicht setzen, Freq ist so nur 2,9.. kHz - Pin OC1A auf Ausgang - Mode SET, COM1A1/A0 setzen - Interrupt weglassen - Wenn Vorteiler 1, OCR1A ca alle 30-50 ms nachladen gruß avr
@ Ingo Laabs (grobian) >ich war schon bei 1 ms ohne Wirkung. Ich sagte bereits, deine PWM ist keine PWM. Du togglest nur! Mach es richtig wie im Datenblatt bzw bei LED-Fading PWM per Hardware!
1 | TCCR1A = 0x81; // non-inverted PWM on OC1A, 8 Bit Fast PWM |
MfG Falk
Hallo Forumsgemeinde, nachdem ich nun meinen Sinus mit unten aufgefürtem Programm "glatt" hinbekommen habe, möchte ich jetzt, anstatt der Werte für den Sinus eine Wave Datei (natürlich mit 8 Bit) benutzen. Ist das in dieser Form so möglich (das ich dabei die Zählschleife entsprechend anpassen muss ist mir dabei klar). Wie ändere ich dabei den delay-Wert. Gilt dabei delay= 1/Samplingfrequenz ? #include <stdlib.h> #include <avr/io.h> #define F_CPU 12000000UL #include <util/delay.h> #include <avr/interrupt.h> unsigned short a; unsigned char Tabelle[] = { 0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95, 0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae, 0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4, 0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8, 0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8, 0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5, 0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc, 0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe, 0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7, 0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec, 0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc, 0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9, 0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3, 0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c, 0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83, 0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a, 0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51, 0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b, 0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27, 0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17, 0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a, 0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03, 0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01, 0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13, 0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23, 0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36, 0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c, 0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63, 0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c }; int main (void) { DDRD = (1 << PD5 ); TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (0<<WGM11) | (1<<WGM10) ; TCCR1B = (0<<CS12) | (0<<CS11) | (1<<CS10); while(1) { for(a = 1; a < 255; a++) { OCR1A = Tabelle[a]; _delay_us(100); } } return 0; }
@ Ingo Laabs (grobian) >Wie ändere ich dabei den delay-Wert. >Gilt dabei delay= 1/Samplingfrequenz ? Im Prinzip ja, ABER! Das mit dem Delay ist nur ein Q&D Test. Das macht man solide mit einem Timer, oder wie bereits gesagt im Overflow Interrupt der PWM. Dann gibt es natürlich nur ganzzahlige Teiler der maximalen Samplingfrequenz. Sollte aber für deine Anwendung reichen. Ach ja, als Filter ist ein einfacher RC-Filter natürlich grottenschlecht. Hier sollte schon mind. ein 4poliger, aktiver Filter rein, Ob nun Thebycheff, Bessel oder wasauchimmer ist dann eine Frage der Anwendung. Grössere Daten packt man aber direkt in den Flash und liest sie von dort, denn RAM ist immer knapp. Wie das geht steht im GCC-Tutorial. MFG Falk P.S. Ist kompakt geworden dein Programm, nicht wahr? ;-) MFG Falk
Falk Brunner schrieb: > > Im Prinzip ja, ABER! > Das mit dem Delay ist nur ein Q&D Test. Wassn das ?? > Das macht man solide mit einem > Timer, oder wie bereits gesagt im Overflow Interrupt der PWM. Dann gibt > es natürlich nur ganzzahlige Teiler der maximalen Samplingfrequenz. > Sollte aber für deine Anwendung reichen. > Grössere Daten packt man aber direkt in den Flash und liest sie von > dort, denn RAM ist immer knapp. Wie das geht steht im GCC-Tutorial. mit progmem... ist hier aber in der Versuchsphase noch nicht relevant geworden > > MFG > Falk > > P.S. Ist kompakt geworden dein Programm, nicht wahr? ;-) jepp...dank dir ;-)
@ Ingo Laabs (grobian) >> Das mit dem Delay ist nur ein Q&D Test. >Wassn das ?? Quick & Dirty.
@falk
>> Overflow Interrupt
kannst Du das mal genauer erläutern..versteh das jetz nicht ganz
@ Ingo Laabs (grobian) >>> Overflow Interrupt >kannst Du das mal genauer erläutern..versteh das jetz nicht ganz Der Timer 1 läuft als 8-Bit Timer und macht bei 255 einen Überlauf (Overflow). Die PWM-Periode ist zu Ende und beginnt neu. Gleichzeitig wird ein Interrupt ausgelöst. Dort schreib man die neuen PWM-Daten. Hat den Vorteil, dass a) das ganze synchron passiert, somit keine Daten verschluckt oder abgehackt werden und man b) eine genaue Zeitbasis hat. Man müsste ggf. aber auf Phase Correct PWM wechseln, damit die Hardware die neuen PWM Daten immer korrkt am Ende der nächsten PWM-Periode verarbeitet. Sonst kann es komische Sprünge geben. MFG Falk
Also, ich habe jetzt ne Wave-Datei reinkopiert (die ersten 44Byte natürlich entfernt) und es klingt alles so wie ich es mir vorgestellt habe. Nächster Schritt wird jetz wohl ein EEPROM sein, weil Flash ist zu klein, noch besser wäre ne SD. Würde da die Möglichkeit bestehen da ne Wave-Datei über Windows aufzuspielen und die dann mit dem AVR abzuspielen ? Kennt sich einer mit SD hier aus ? Im Tutorial finde ich auf Anhieb nichts. Gruß aus Berlin Ingo #include <stdlib.h> #include <avr/io.h> #define F_CPU 12000000UL #include <util/delay.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> unsigned short a; unsigned char pgmTabelle[] PROGMEM = { 0x7C, 0x7C, 0x78, 0x75, 0x75, 0x69, 0x6C, 0x7B, 0x79, 0x74, 0x7E, 0x84, 0x88, 0x8D, 0x8E, 0x93, 0x92, 0x86, 0x7B, 0x7B, 0x74, 0x6E, 0x79, 0x7F, 0x7B, 0x76, 0x7C, 0x7A, 0x71, 0x72, 0x73, 0x79, 0x7B, 0x77, 0x75, 0x6D, 0x67, ………ganz, ganz viele Daten… 0x82, 0x85, 0x90, 0x92, 0x86, 0x87, 0x8F, 0x8B, 0x85, 0x7C }; int main (void) { DDRD = (1 << PD5 ); TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (0<<WGM11) | (1<<WGM10) ; TCCR1B = (0<<CS12) | (0<<CS11) | (1<<CS10); while(1) { for(a = 1; a < 14674; a++) { OCR1A = pgm_read_byte (&pgmTabelle[a]); _delay_us(100); } } return 0; }
Ingo Laabs schrieb: > while(1) > { > for(a = 1; a < 14674; a++) > { > OCR1A = pgm_read_byte (&pgmTabelle[a]); > _delay_us(100); > } > } Den _delay solltest du ganz schnell loswerden, sonst wird das nichts. Du musst das Nachladen in einen Interrupt verbannen, damit es auch dann geschieht, wenn du von der SD-Karte den nächsten Datenblock einliest. Ansonsten wird dein Musikstück ständig stottern. Libraries die SD Karten ansteuern können, gibt es viele. Einfach danach goggeln.
Hallo Karl Heinz, naja soweit bin ich ja noch nicht. Mühsam ernahrt sich das Eichhörnchen. Erstmal soll es mit einem EEPROM geschehen. Die ganze Sache soll ja auch einen gewissen Lerneffekt haben. Ich denke mal, wenn ich jetzt erstmal ein EEPROM rangetüddelt habe, wird die sache mit der SD-Karte aktuell. Ich will ja nicht per copy und paste einen Code zurechtkopieren den ich dann letzendlich nicht verstehe. Das ist irgendwie nicht Sinn der sache.
Ingo Laabs schrieb: > Hallo Karl Heinz, > naja soweit bin ich ja noch nicht. Mühsam ernahrt sich das Eichhörnchen. > Erstmal soll es mit einem EEPROM geschehen. Die ganze Sache soll ja auch > einen gewissen Lerneffekt haben. Ich denke mal, wenn ich jetzt erstmal > ein EEPROM rangetüddelt habe, Na ja. So gross ist der Lerneffekt dann auch wieder nicht. pgm_read_byte durch die entsprechende eeprom Funktion ersetzen und fertig. Oder meinst du ein externes EEPROM?
@ Ingo Laabs (grobian)
>joooo...extern
Nimm mal lieber externen Flash, der ist grösser und schneller. Gibts bei
CSD, IT-WNS und Co. Und mit 4..32 Mbit kann man schon einiges anfangen.
Dazu noch 20 Mbit/s per SPI und alles wird easy.
Das Ganze per SD-Karte wird DEUTLICH anspruchsvoller, weil man auf jeden
Fall einen Softwarepuffer braucht, welcher mindestens eine Sektor (=512
Bytes) zwischenspeichern kann.
MFG
Falk
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.