Topic: Keep an analog signal digital as long as possible - including the power amplifier - and by doing that, avoid all that efficiency losses (and heat generation) of analog amplifiers.
When you think about a DAC, you often imagine a mechanism that generates an output level based on a numeric value.
E.g.: 0x00 is 0 V, 0XFF = 5 V, any value in between is a proportional part of 5 V.
Another popular DAC mechanism is duty cycle modulation. You 'll know it from Arduino analog out pins.
In that case, the device outputs a square wave with fixed frequency. The % of the square wave that's high, defines the output voltage.
E.g.: 0x00 is a duty cycle of 0% - the signal always stays low and is 0V. 0XFF is 100% duty cycle. The signal is always high at 5 V.
Any value in between makes the signal partly high, partly low. The output voltage is again the proportional part of 5 V.
I'm testing this option here while making a class-D amplifier (option 3rd is also valid for class-D operation).
A 3rd option is PWM: In this case, the pulse width is modulated.
It is again a square wave (pulse wave is a more appropriate name). The difference with duty cycle modulation is that frequency isn't constant. Together with the duty cycle, like the second option above, frequency can be modulated (stretched).
All three options have one principle in common. They generate a signal with an amount of energy based on a programmable value. And the output analog signal is a (linear) function of that.
Options 2 and 3 use the time domain to translate digital to analog. While option 1 uses the voltage domain directly.
In the time domain modulated signals; it's not the level of the signal that determines the output. It's the amount of time that the signal stays high that determines it.
And that amount of time is digitally controlled here, by the timer. So I claim it's a digital signal.
We'll see a bit later, when reviewing the amp, that the level of the high signal will be important, because that will be the energy sent to the speakers. But it will still be binary.
I'm trying to show a working version of class-D with a microcontroller and as little extra components possible.
Class-D components
A full source-to-speaker class-D chain has these 3 components:
source: wikipedia
An analog to PWM converter, a digital amplifier and a low pass filter.
- In my example , I start after the analog to PWM converter. I have the digitised form of my source data available already (like you have at home when playing a CD or mp3 file).
I use the programmable timer of a Hercules controller to turn that sampled data into PWM representation. - The GPIO output of my microcontroller is in essence a digital push-pull amplifier:
- I use an RC filter as low pass. Just two fairly randomly chosen parts. As long as their cut-off is over 350 Hz ...
In a power design, you'd definitely use an inductor instead of a resistor - because a resistor is bad for the efficiency (an inductor has a big imaginary impedance, while a resistor burns energy with it's strictly real resistance).
And because this is in essence a Buck converter.
The Design
Most of my Project14 projects are not my own. This time it's no different. I just implemented a Texas Instrument application note.
My activity was to port it to a generally available LaunchPad. The note is written for an upscale evaluation board with a higher end controller.
source: part of a diagram from TI application note SPNA217: Sine Wave Generation Using PWM With Hercules N2HET
That note shows how to generate a software DAC that can generate a sinus from sampled data using PWM.
This timer is a bit crazy. Hard to program, but real-time savvy. You feed it the raw sampled signal levels and it can autonomously generate the PWM pulse train.
If you take a Hercules controller with DMA support, it can do that with virtually no load on the main ARM controller.
I'm using the cheapest and simplest Hercules here, without DMA. In this case, the ARM controller has some work moving data. I chose that one to stay within a Project14-friendly budget (LaunchPadLaunchPad just under $50).
The sampled sine wave may look familiar. It's the same table of data that's used in many DAC examples.
float sine_table_percent[SAMPLE_SIZE] = {0.5,0.52452141,0.548983805,0.573328313,0.597496346, 0.62142974,0.645070896,0.668362917,0.691249749,0.71367631,0.735588627,0.756933966, // .... 0.400942069,0.425096628,0.449431454,0.47388798 };
The difference is that now, it's not sent to a DAC and then to an analog amplifier.
The timer is turning it into a PWM.
PWM_PERIOD .equ 10 PWM_PIN_NUM .equ 9 INIT_COMPARE .equ 3 INIT_HR_DELAY .equ 5 ; Use CNT to generate a virtual counter. The counter period is changable by the host ; application. When counter reaches the PWM_PERIOD value, a DMA request is generated. The ; HTU is setup to take this request and return a new duty cycle. The new duty cycle will ; be written to the MOV32 data field as the new compare value. L00 CNT { reqnum=0,request=GENREQ,reg=A,irq=OFF,max=PWM_PERIOD}; ; ECMP is setup in high resolution mode to create a compare value against the current ; counter value in CNT instruction. Whenever, there is a match, it will set the specified ; pin low until the end of the PWM period. The pin starts as high at the beginning of the ; PWM cycle. The specified pin is changable by the host application. L01 ECMP { next=L03,hr_lr=HIGH,en_pin_action=ON,cond_addr=L02,pin=PWM_PIN_NUM, action=PULSELO,reg=A,irq=OFF,data=INIT_COMPARE,hr_data=INIT_HR_DELAY}; ; MOV32 instruction is only executed when ECMP has a compare match. When this instruction ; is executed, it will copy its data field value which contains the latest duty cycle ( ; the compare value) back to ECMP's data field. The MOV32's data field is updated by the HTU ; with the new duty cycle value when responding to the request by the CNT instruction. L02 MOV32 { remote=L01,type=IMTOREG&REM,reg=NONE,data=INIT_COMPARE,hr_data=INIT_HR_DELAY}; ; Branch back to the beginning. L03 BR { next= L00, cond_addr=L00, event= NOCOND }
And that signal is sent to the GPIO output stage, a digital output stage that adds extra energy (amplifies) to that signal. With little heat loss because we switch, instead of burn parts of the energy in the output transistors.
The project, with all code, translated from the app note to a general available TMS570LS04 Launchpad, is attached.
Captures:
In the first capture, you see a PWM representation (the "high-energy" PWM digital signal) after the output stage) in blue, and the same signal after the filter in yellow (the analog sinus).
The photo below is the PWM only.
The one down here is the filtered output only:
If you think I've taken a too big grab of freedom by saying that the GPIO output is a digital amplifier (Jan you are lazy), leave it in the comments.
Adding a bigger power stage can be fun. But I like the simplicity and focus of the little solution here.
For the savvy googlers: there is an identical example available online that works for an Arduino UNO....
Related blog |
---|
Create and Measure signals with Hercules High End Timer (HET) - 2: Generate Dynamic Duty Cycle |
Top Comments