Hallo, ich würde gerne mit einem Mikrocontroller ein Sinus Signal erzeugen. Folgendes muss dabei gewährleistet sein: Amplitude von 0-12V einstellbar Frequenz mindestens zwischen 50Hz und 60Hz einstellbar. Grundsätzlich sollte das über PWM und eine Verstärkung ja möglich sein. Ich möchte das Signal aber lieber direkt von einem Baustein bekommen (externer DAC) und nicht verstärken, da der Sinus nochmal hochtransformiert wird, und ich durch das verstärken und transformieren zu ungenau werde. Hat jemeand Erfahrung mit externen DACs? Welchen Baustein kann ich dafür einsetzen und wie muss ich diesen beschalten? Ich denke mal I2C würde sich anbieten für den Mikrocontroller? Danke für eure Hilfe! LG, poschi8
Wie genau soll der Sinus sein? Wenn du einen DAC benutzt, dann mußt du ja zu genau definierten Zeiten die Stützstellen einstellen. Bei 20 Stützstellen einer Welle sind das schon 1000 Änderungen pro Sekunde. Dann sollte dann auch schon per Interrupt ablaufen. Wenn man dann noch I2C Bausteine nimmt, dann kann das schon ungenau werden, weil eine Einstellung bei 100 KHZ Bustakt schon fast 200us braucht. (jedenfalls bei meinem MCP4728)
"50 bis 60 Hz" und "hochtransformiert" klingt ein wenig danach, als würdest du etwas Leistung benötigen. Welche Ströme bzw. Leistungen erwartest du denn am Eingang deines Trafos? DACs sind im Normalfall nicht dafür gemacht, signifikant Leistung zu treiben. Heinz peter P. schrieb: > Ich denke mal I2C würde sich anbieten für den Mikrocontroller? oder SPI oder paralleles Interface. Je nachdem, was dein (uns unbekannter) Mikrocontroller so alles mitbringt und wie viele Pins er frei hat. PittyJ schrieb: > weil > eine Einstellung bei 100 KHZ Bustakt schon fast 200us braucht. was für 1000 Samples pro Sekunde immer noch viel schneller ist als benötigt.
PittyJ schrieb: > Wie genau soll der Sinus sein? Naja, es muss jetzt nicht das "perfekte" Signal sein, es dürfen schon kleinere Stufen drinnen sein, aber es sollte doch als Sinus erkennbar sein. LG, poschi8
Hallo Poschi8, mit einem PSoC4 oder 5LP z.B. brauchst Du keinen externen DAC- Baustein. Hier hatte ich vor einiger Zeit mal etwas zum Thema veröffentlicht: Beitrag "Sinusgenerator mit PSoC 4"
ATMega/ATTiny (Sinustabelle mit 256 Werten) | V PWM (256 * f [50 - 60 Hz] updates) | V Filter (Low-Pass) | V OPAmp (Puffer ...) | v Endstufe (... Leistungsteil)
Schon mal über einen AD9850 oder AD9851 mit Nachbrenner (z.B. TDA2003) nachgedacht? Den AD9850/1 kannst du z.B. mit einem Arduino oder einem SAD504 ansteuern.
R2R Netzwerk? Wenn dir 8Bit Auflösung reichen kann das jeder AVR. Falls du 16Bit Auflösung anstrebst würde ich zu einem 32Bit Controller greifen oder einem 8 Bitter mit Latch dahinter.
Hier ein fertiges Projekt mit R2R Netzwerk: AVR DDS V2.0 signal generator http://www.scienceprog.com/avr-dds-signal-generator-v20/ http://www.radiolocman.com/shem/schematics.html?di=69926 Kann Sinus, Rechteck, Dreieck, Sägezahn, Sägezahn reverse - von 0Hz bis ca. 60kHz.
Erew schrieb: > ATMega/ATTiny (Sinustabelle mit 256 Werten) > | > V > PWM (256 * f [50 - 60 Hz] updates) > | > V > Filter (Low-Pass) > | > V > OPAmp (Puffer ...) > | > v > Endstufe (... Leistungsteil) Das wäre meine Ursprüngliche Idee gewesen, aber da habe ich wieder deine Verstärkung, da ich mit der PWM ja nur 0-3.3V schaffe. Als Enstufe häte isch sowas hier: http://www.amateurfunkbasteln.de/nfamps/nfamps.html (Die 2. Schaltung) SCKL schrieb: > Schon mal über einen AD9850 oder AD9851 mit Nachbrenner (z.B. TDA2003) > nachgedacht? Ja den habe ich auch schon gesehen, ich habe aber Probleme damit den Baustein zu verstehen bzw. weiß ich nicht wie ich diesen richtig beschalten muss. Ingo L. schrieb: > R2R Netzwerk? Wenn dir 8Bit Auflösung reichen kann das jeder AVR. Ja mit der Auflösung würde ich schon klar kommen, aber wie würde das im Detail aussehen mit so einem R2R Netzwerk, und wie sieht das Signal am Ende aus? Danke für die zahlreichen Antworten :)) LG, poschi8
SCKL schrieb: > Hier ein fertiges Projekt mit R2R Netzwerk: > > AVR DDS V2.0 signal generator Danke das ist schon mal so etwas ähnliches, jedoch muss ich es schaffen das ich die Amplitude über die Software einstelle. Das passiert hier ja über ein Poti wenn ich das richtig verstanden habe, oder? LG, poschi8
Heinz peter P. schrieb: > > jedoch muss ich es schaffen > das ich die Amplitude über die Software einstelle. Dazu brauchst Du 2 DACs. Mit dem einen stellst Du die Amplitude ein, der zweite ist der DAC für das Signal. Schau Dir mal die SPI-DACs von Microchip an: http://ww1.microchip.com/downloads/en/DeviceDoc/22250A.pdf an. Esgeht dabei um die Familie. Wenn Du eine genügend stabile Referenz hinkriegst, kannst Du den Dual-DAc mit externer VREF nehmen. Wenn nicht, mach ein Päärchen aus MCP4801 für die Amplitude und MCP4901 für das Signal. Mit dem Ausgang des 4801 steuerst Du die Amplitude des 4901. Leider musst Du den Ausgang immer noch mit einem OP-Amp (konstant) verstärken, um auf die 12V zu kommen, da VREF max. VCC sein darf.
Ok alles klar, das verstehe ich. Danke für deine Erklärung. Aber in diesem Fall kann ich dann doch einfach die PWM machen und so beschalten: ATMega/ATTiny (Sinustabelle mit 256 Werten) | V PWM (256 * f [50 - 60 Hz] updates) | V Filter (Low-Pass) | V Endstufe (... Leistungsteil) Als Endstufe würde ich dann eine Schaltung mit dem TDA2030 bauen. Denn Verstärken muss ich ja sowieso also ist es egal, oder nicht? LG, poschi8
Irgendwo musst Du ja die Signalamplitude einstellen. Das passiert bei meinem Vorschlag mit der Referenzspannung des 2. DAC. Es geht natürlich auch mit spannungsgesteuerten Verstärkern (VCAs), da kannt Du dann ein mit PWM erzeugtes Signal steuern. Dazu könntest Du eine zweite PWM nehmen. Bauteil hierfür wäre ein LM13700. Aber ob das vom Aufwand einfacher ist?
Heinz peter P. schrieb: > Denn Verstärken muss ich ja sowieso also ist es egal, oder nicht? so ist es: du brauchst offensichtlich sowieso die Nachverstärkung, also ist es weitgehend egal ob dein DAC maximal 0-3,3V oder 0-12V kann: das ergibt jeweils nur eine andere Einstellung des Potis R7 in deiner verlinkten Schaltung. Jörg schrieb: > Irgendwo musst Du ja die Signalamplitude einstellen. Warum nicht einfach den jeweiligen Digitalwert mit einem entsprechenden Versärkungsfaktor (in Software) skalieren, ehe er zum DAC geschickt wird? Ob 8 Bit Auflösung dann noch aureichen müsste man schauen: es hängt davon ab, in welchen Bereichen die Verstärkung variiert werden soll und wie folgende Aussage genau zu interpretieren ist: Heinz peter P. schrieb: > Naja, es muss jetzt nicht das "perfekte" Signal sein, es dürfen schon > kleinere Stufen drinnen sein, aber es sollte doch als Sinus erkennbar > sein.
Also der Hintergrund des ganzen ist folgendes: Ich möchte eine Wechselspannung zwischen 100V und 350V einstellen können. Sollte eigentlich in 1V Schritten einstellbar sein. Dazu wird das PWM Signal verstärkt und dann über einen Trafo hochtransformiert... Und mit der PWM müsste ich schon die Amplitude einstellen können, den wenn ich mit einer Sinustabelle arbeite kann ich den Wert ja anpassen. Wenn 255 3.3V entspricht, dann kann ich das ganze ja auch mal 0.5 rechnen und müsste für alle Werte in der Tabelle die hälfte erhalten und hab somit die Amplitude verändert. So hab ich mir das zumindest gedacht ;) LG, poschi8
Und hier noch, wie ein Sinus-DDS aussehen kann:
1 | const int sinewave_length=256; |
2 | const unsigned char sinewave_data[] PROGMEM = { |
3 | 0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae, |
4 | 0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8, |
5 | 0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5, |
6 | 0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff, |
7 | 0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7, |
8 | 0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc, |
9 | 0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3, |
10 | 0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83, |
11 | 0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51, |
12 | 0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27, |
13 | 0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a, |
14 | 0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00, |
15 | 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08, |
16 | 0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23, |
17 | 0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c, |
18 | 0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c}; |
19 | |
20 | |
21 | volatile uint32_t akku_inkr=0x05bd26e9; |
22 | volatile uint32_t akku = 0x00000000; |
23 | |
24 | #define GETINDEX(a) ((a & 0xff000000) >> 24)
|
25 | |
26 | |
27 | ISR(TIM0_OVF_vect) { |
28 | akku+=akku_inkr; |
29 | OCR0A = pgm_read_byte(&sinewave_data[GETINDEX(akku)]); |
30 | }
|
Die Konstante akku_inkr musst du an deine Bedürfnisse anpassen ... Bsp: Overflow-Timer-Interrupt (PWM selbst tacktet dann mit 10kHz*256 = 2,56Mhz) läuft auf 10kHz und du möchtest 50Hz Sinus-Frequenz f = (10kHz*akku_inkr)/256 akku_inkr = 50Hz * 256 / 10kHz = 1,28 Die 1,28 noch mit 2^24 multiplizieren und hex-Wandeln, Nachkommastellen abschneiden: akku_inkr = 0x0147AE14; Ist jetzt für einen AVR, aber du hast ja nicht geschrieben, welchen µC du verwenden möchtest. Am PWM-Output kannst du dann den Low-Pass-Filter und Verstärker wie weiter oben einfach anschließen.
:
Bearbeitet durch User
Alles klar, danke! Ich werde einen Arduino nehmen und mich bei der Softare an diese Vorlage halten: https://www.arduino.cc/en/Tutorial/DueSimpleWaveformGenerator Brauche ich den Tiefpass am Ende der PWM? Bzw wozu ist der gedacht? Nach welchen Kriterien muss ich diesen Dimensionieren? LG, poschi8
Sicher hast du bei deinem einfachen Code auch berücksichtigt, was passiert, wenn du OCR0A von 130 auf 120 setzt, der Zähler aber schon bei 125 ist?
ASM Superprofi schrieb: > Sicher hast du bei deinem einfachen Code auch berücksichtigt, was > passiert, wenn du OCR0A von 130 auf 120 setzt, der Zähler aber schon bei > 125 ist? Das verstehe ich nicht?! xD
ASM Superprofi schrieb: > Sicher hast du bei deinem einfachen Code auch berücksichtigt, was > passiert, wenn du OCR0A von 130 auf 120 setzt, der Zähler aber schon bei > 125 ist? Ah, ich verstehe, was du meinst ... Das kann nicht passieren, da beim Timer-Overflow der Counter 0 ist und dann der neue PWM Wert gesetzt wird. Der neue PWM-Wert wird erst beim nächsten Überlauf ins eigentliche OCR geladen. Man hat quasi 100µs Zeit, den OCR zu laden, ohne dass es hier Probleme gibt. Der landet zunächst ja in einem Shadow-Register. Es gibt halt ein Sample Zeitversatz, was aber nicht ins Gewicht fällt.
:
Bearbeitet durch User
Shadow Register? Sowas hat nur der xmega. "However, changing TOP to a value close to BOTTOM when the counter is run- ning with none or a low prescaler value must be done with care since the CTC mode does not have the double buffering feature. If the new value written to OCR0A is lower than the current value of TCNT0, the counter will miss the Compare Match. The counter will then have to count to its maximum value (0xFF) and wrap around starting at 0x00 before the Compare Match can occur." Wenn du aber bei 0 den Wert änderst, kann nichts passieren. Man sollte diese Falle aber im Hinterkopf behalten.
ASM Superprofi schrieb: > Shadow Register? Sowas hat nur der xmega. Du bist ja tatsächlich ein Superprofi ... seufz Niemand verwendet CTC für PWM ... Lies dir das mal das Datenblatt durch ;) CTC (und der "normale" Modus) sind auch die einzigen Modis, in denen OCR sofort aktualisiert wird. Da gibts eine schöne Tabelle im Datenblatt. Und ja, das gilt auch für die ATTinys! > The OCR0x Registers are double buffered when using any of the Pulse > Width Modulation (PWM) modes. For the normal and Clear Timer on Compare > (CTC) modes of operation, the double buffering is disabled. The double > buffering synchronizes the update of the OCR0x Compare Registers to > either top or bottom of the counting sequence. The synchronization > prevents the occurrence of odd-length, non-symmetrical PWM pulses, > thereby making the output glitch-free. Also wenn du schon Oberschläue verbreitest, dann bitte auch fachlich korrekt bleiben ;-) *edit*: Ach, das weiß ich zufällig, weil ich in das OCR-Update-Problem erst selbst reingelaufen bin ??? Beitrag "[AVR] Update von OCR0A bei FastPWM ausgetrickst"
:
Bearbeitet durch User
Mampf F. schrieb: > Niemand verwendet CTC für PWM Niemand ausser eben echte Superprofis. Erste Anwendung: Hohe Frequenzen. Selbst bei 8 MHz kommst du ohne CTC nur auf 31.25 kHz. Zweite Anwendung: Hohe Batterielaufzeit. Reicht dir eine Auflösung von 64 Schritten, kannst du den Takt deiner CPU auf 25% setzen und damit gut 60-70% Strom sparen.
Naja ich nutze halt meistens CTC. Deshalb ging ich davon aus, dass das alle so machen ;) Man konnte aus deinem Code die Timerinitialisierung nicht rauslesen, oder ich habe es übersehen.
ASM Superprofi schrieb: > Erste Anwendung: Hohe Frequenzen. Selbst bei 8 MHz kommst du ohne CTC > nur auf 31.25 kHz. > > Zweite Anwendung: Hohe Batterielaufzeit. Reicht dir eine Auflösung von > 64 Schritten, kannst du den Takt deiner CPU auf 25% setzen und damit gut > 60-70% Strom sparen. Und aufgrund deiner Sonderfälle sagst du, mein PWM würde nicht funktionieren, obwohl du von schrägen Voraussetzungen ausgegangen bist? Ich glaube, mit dir diskutiere ich nicht weiter ;-)
einfach 12Euro STM32F4 Discovery board. Der µC hat einen 12bit DAC eingebaut. Für den Sinus muss der Prozessor dank DMA keinen Finger rühren. Kleine Audio-Endstufe hinten drann und fertig.
Mampf F. schrieb: > Und hier noch, wie ein Sinus-DDS aussehen kann: Ist dir schon mal aufgefallen, dass man für die Werte eines Sinus garnicht die ganzen 360 Grad tabellieren muss? Die Werte wiederholen sich in jedem 90Grad-Quadranten, man braucht also nur eine Tabelle von 0..90 Grad. Georg
Heinz peter P. schrieb: > ich würde gerne mit einem Mikrocontroller ein Sinus Signal erzeugen. > Folgendes muss dabei gewährleistet sein: > Amplitude von 0-12V einstellbar > Frequenz mindestens zwischen 50Hz und 60Hz einstellbar. 20 Beiträge später weiß immer noch niemand, welche Ausgangsleistung Dein Generator bringen soll. Auch die gewünschte Signalqualität ist unbekannt. Aufgrund Deiner aktuellen Vorgaben, würde ich Dir so einen Baustein empfehlen: https://www.amazon.de/Stromerzeuger-Notstromaggregat-Stromaggregat-Automatischer-%C3%96lmangelsicherung/dp/B00DPXFF68/ref=sr_1_4?ie=UTF8&qid=1490961861&sr=8-4&keywords=Notstromaggregat Mit dem Mikrocontroller machst Du dann eine Frequenzregelung - ist halt ein Gefrickel und u.U. schlecht für die Lebensdauer, falls dauerhaft 60Hz gewünscht werden. Ansonsten: STM32-DISCO mit Nachbrenner, wie bereits jemand geschrieben hat. Wenn Du Dich mit STM32F103R auskennst, hätte ich hier auch noch so einen Generator bzw. ein paar leere Platinen rumliegen. Wurde für die Messung von Motorinduktivitäten gebaut. Sollte zum Basteln reichen. Eckdaten: - STM32F103R - 2x Endstufe OPA544 - jede Endstufe mit Strom-/Spannungsmessung - RS232 / USB Bei Bedarf PM.
Georg schrieb: > man braucht also nur eine Tabelle von > 0..90 Grad. Jup, weiß ich :) Aus pragmatischen Gründen und weil ich nicht mit dem Platz sparen muss, hab ich trotzdem eine ganze Schwingung gespeichert :) Optimieren, wo es notwendig ist ... Hier war es nicht nötig :)
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.