An experimental PWM circuit with 74HCU04 - Page 1
Forum section: electronics / general

author: arvee
author_rank: Contributor
timestamp: December 29, 2021, 08:45:58 pm
content: This is my first post on this forum.Here is another PWM circuit.The switching is done by the 74HCU04 hex unbuffered inverter.The PMOS and NMOS transistors of this inverter have low on-resistance (25 ohms).Logic inverters are normaly optimized for speed.The good news is that here the on-resistance of the transistors is well matched.With six parallel inverters the measured resistances are: PMOS 4.07 ohm, NMOS 3.79 ohm.The difference in only 0.28 ohm.The reference voltage is made with an LM399, the nominal voltage is 7 volt, and 1 ppm is 7 uV.The low-pass filter has resistor 50k ohm and capacitor 1 uF.The error is parabolic and the maximum INL is 0.28 ohm / 50k ohm / 4 = 1.4 ppm.The Arduino clock frequency is 16 MHz.The PWM frequency is 300 Hz (divide by 53333).The length of the sigma-delta modulation is 300.With an integration time of the DMM of one second the resolution is 24 bit.Everything is as simple as possible. There is no output buffer or extra filtering.The load of 10M ohm decreases the output voltage but has little effect on the linearity.The first-order filter has limited attenuation at 300 Hz, but the normal mode rejection of the meter of 60 dB helps.With an integration time of 1 or 2 seconds there is sigma-delta ripple is averaged out.The output voltage is measured with an HP34401A.

author: DeltaSigmaD
author_rank: Contributor
timestamp: December 30, 2021, 10:21:18 pm
content: Thanks for showing the circuit. Certain improvements are possible with minor modifications.- The PWM frequency of 300Hz is very low, so that very long time for averaging is required. With a 16MHz uC, a PWM frequency above 200kHz is possible, including DS update with this rate. A PWM frequency >20 kHz should be no problem with suitable software.- A lowpass of order >=3 and a buffer amplifier are necessary to use the circuit as controllable reference e.g. for calibration.- The reference buffer must have very good dynamic characteristics for high DAC linearity. Your buffer amplifier circuit shows deviations of 1.9 mVpp with a 1mA load step and an output impedance of 1 Ohm. With a small modification (please see below), the deviation can be reduced to <0.3 mVpp, and the output impedance is <0.17 Ohm always, a further improvement is easy.

author: arvee
author_rank: Contributor
timestamp: January 05, 2022, 10:19:39 pm
content: I forgot to mention that the SN74HCU04 is from Texas instruments. Mine has date code October 2019.The measured results are not so bad. The plots are a full sweep from 0 to approximately 7 volt.Parabolic error is 2.02 ppm. It should have been 1.4 pmm, but there is a wire with resistance 0.1 ohm between buffer and inverter.The error from duty cycle error is 0.7 pmm. That is 2.3 ns of the period of 3300 us. This error is visible at the beginning and end of the sweep.After the numeric correction it becomes boring with mostly the noise of the meter.

author: Andreas
author_rank: Super Contributor
timestamp: January 06, 2022, 08:08:50 am
content: Quote from: DeltaSigmaD on December 30, 2021, 10:21:18 pmMy experiences are different: the higher the switching frequency the more bad are the temperature dependant and unsymmetrically rise and fall times.300 Hz is a optimized frequency which will be filtered out together with mains frequency suppression (above 1 NPLC 50 or 60 Hz).Quote from: arvee on January 05, 2022, 10:19:39 pmThat is really a good result.with a single analog switch (74HCT4053) I had around 0.5-0.6 mV / 5V so around 100-120 ppm parabolic error.But you know that the 7V is at the maximum rating for the poor HCU04?with best regardsAndreas

author: arvee
author_rank: Contributor
timestamp: January 06, 2022, 09:33:15 pm
content: The decoupling capacitor of the inverter is 10 µF. It has 1 ohm in series because that is the ESR of the tantalum capacitor.The buffer sees current pulses from the switching of the output inverter.The charge of one pulse can be estimated from the "power dissipation capacitance" CPD = 10 pF.Or you can measure the average current with 10kHz switching frequency.There are six inverters. The charge of one transition is Q = CPD*VDD = 10pF*7V*6/2 = 210 pC.For example a pulse with height 21 mA and width 10 ns.Over the 1 ohm ESR resistor of the decoupling capacitor this makes a voltage pulse of 21 mV, with area 210 pVs.The clock frequency is 16 MHz and the minimum width is 62.5 ns, and with 7 volt the area is 437.5 nVs.The effect of current spikes is very small and it is not needed to remove them with a faster buffer.There is a low pass filter in the feedback to be sure that voltage spike reduce at the input of the bipolar differential pair.The buffer can be made with op amps. The amplifier which drives the output must be fast with 10 MHz unity-gain bandwidth. I think the circuit can still be improved, but this is what I have.The maximum rating of 7 volt should not be a big issue. Perhaps there is long time degradation. The alternative is to use a 5V voltage reference.

author: RoGeorge
author_rank: Super Contributor
timestamp: January 06, 2022, 10:38:15 pm
content: Nice results!If 300Hz is not enough, then using PDM (Pulse Density Modulation) might worth considering.A software PDM is very easy to implement, can be easily extended to more than 16 bits, and the pulses are narrower than those coming from a PWM, so the analog filter might give better results for PDM than for PWM.I did a small demo once, the PDM itself needs only 5 lines:https://hackaday.io/project/6356-delta-sigma-versus-pwmhttps://github.com/RoGeorge/Delta-Sigma_versus_PWM

author: MegaVolt
author_rank: Frequent Contributor
timestamp: January 18, 2022, 10:01:59 am
content: Quote from: RoGeorge on January 06, 2022, 10:38:15 pmIt looks like DDS.

author: arvee
author_rank: Contributor
timestamp: July 25, 2025, 01:21:39 pm
content: Hi,Here an update on the PWM circuit.The changes are:Output buffer with voltage gain 12/7.A pair of Coto relays to switch the output polarity.The resolution is increased to 27 bit (8 seconds integration time).The output range is +/- 12 volt and the step size is 0.1 uV.The steps are tested on my DMM6500 in the 100 mV range.One sweep is 50 mV to 50.025 mV with 1 uV steps.The sweeps are repeated 20 times, and averaged later.The rounding error is 0.1 uV peak-peak.The measurement shows 0.16 uV pp. The units in the graph are 10uV/10V.RobThe modulation is PWM, with the pulse width varied by one clock cycle.Code:timercount = 53333; // Length of the counter, the frequency is 16 MHz/53333 = 300 Hz;modcount = 300; // For one second modulation time;count = timercount * modcount * vset / vref;integerpart = count / modcount;fractionalpart = count % modcount;integerpart_minus_1 = integerpart - 1; // Actual pulse width is 1 longer than the register value;interrupt_routine () {state += fractionalpart;if (state < modcount){pulsewidth = integerpart_minus_1;}else {pulsewidth = integerpart;state -= modcount;}}

author: NNNI
author_rank: Regular Contributor
timestamp: July 26, 2025, 09:55:47 am
content: Hello,Thanks for sharing your interesting project! I worked on something similar a few months ago, where I used MASH modulation to modulate the PWM duty cycle. I have documented the code I used and a few other details here:https://nnnilabs.net/videos/2025/05/15/PWM-DAC-2.htmlThe MASH code itself was adapted from this excellent website, which also has a theoretical description of MASH modulation:http://www.aholme.co.uk/Frac2/Mash.htmThere is, however, one subtlety to modulating on top of PWM - using regular 'fast' PWM can cause some of the higher frequency components to fold down to in-band (i.e., within the passband of the PWM filter) causing ripple. I've found that using 'phase-accurate' PWM can mitigate this. The author of the website has also written about this problem and proposed a solution:http://www.aholme.co.uk/Frac2/Reducing_PWM_distortion_phase_noise_in_fractional-N_synthesizers.pdfGood luck with this project and I'm looking forward to further updates!

author: iMo
author_rank: Super Contributor
timestamp: July 26, 2025, 11:03:25 am
content: Years back the guys here elaborated similar PWM based divider (I think in the LM399 thread) generating similar stuff with an atmel 8pin MCU (plus some ADG switches, low-pass filters, two opamps, etc). How is the MASH method related/compared to that?PS: randomly picked a post about it (..it is 6+ys back already, OMG):https://www.eevblog.com/forum/metrology/lm399-based-10-v-reference/msg2082496/#msg2082496

author: guenthert
author_rank: Frequent Contributor
timestamp: July 26, 2025, 02:04:07 pm
content: Quote from: iMo on July 26, 2025, 11:03:25 amUhm, the MCU controlled PWM was used there to correct time and temperature related drift of the resistor based voltage divider. The range is there pretty small (in the order of 100ppm would be sufficient, methinks), there is no particular need for good linearity and a setting time measured in minutes would be acceptable. But otherwise it's similarBut thanks for the link to the other interesting use of PWM. It's otherwise easily buried in that loooong thread.

author: fourfathom
author_rank: Super Contributor
timestamp: July 26, 2025, 03:44:02 pm
content: Quote from: MegaVolt on January 18, 2022, 10:01:59 amIt looks more like the Bresenham fractional divider. Depending on the application the fractional divider (arbitrary integer) can give you ratios you can only get close to using simple DDS or standard PWM. Fractional or DDS give you a much higher-frequency distribution pattern (10101010 vs 11110000) which makes filtering easier. I've used Bresenham in IC design and software, and this is available in many PLL and clock-synthesizer chips.

author: NNNI
author_rank: Regular Contributor
timestamp: July 26, 2025, 06:32:48 pm
content: Quote from: iMo on July 26, 2025, 11:03:25 amI did a little digging and found the project's original Google Drive folder link in the thread:https://drive.google.com/drive/folders/1GnfWAyInh_M2gaa59xyV-j0-_jiwc0C1Surprisingly, the MASH modulation implemented in the source code seems to be very similar to Andrew Holme's, and the paper I linked above is also present in a sub-folder.Code:ISR (TIM0_OVF_vect){// Carry flip-flopsc = c; c = c; c = c;// Addersd = (q+ValFrac) % DIVISOR;d = (q+d) % DIVISOR;d = (q+d) % DIVISOR;// Carriesc = (q+ValFrac) >> BASIS;c = (q+d) >> BASIS;c = (q+d) >> BASIS;// Latchfor (int i=0; i<3; i++) q = d;OCR0A = ValInt - 1+ c+ c - c+ c - 2*c + c;}

author: fourfathom
author_rank: Super Contributor
timestamp: July 26, 2025, 06:50:18 pm
content: Here is something I posted on my ham blog, discussing various types of dividers. I show a Bresenham example done in Verilog:http://wb6cxc.com/?p=158

author: NNNI
author_rank: Regular Contributor
timestamp: July 26, 2025, 07:05:30 pm
content: Thanks for the link! I'm afraid I haven't looked into Bresenham in any depth (apart from watching a YouTube video about it), but what does it look like spectrally? I'd assume it's the same as a first-order MASH modulator (noise rises at 20dB per decade). MASH has the advantage of being cascadable to get a higher-order response, but the modulation depth (I don't know if that is the correct term) increases, which might negatively affect ripple in the context of a PWM DAC.The numerically controlled oscillator seems to be a basic building block in any noise-shaping architecture.

author: branadic
author_rank: Super Contributor
timestamp: July 26, 2025, 07:40:13 pm
content: Quote from: guenthert on July 26, 2025, 02:04:07 pmPopulating the resistors is optional, I have them not installed, but operate the PWM purely as a non-drifting voltage divider.-branadic-

author: RoGeorge
author_rank: Super Contributor
timestamp: July 26, 2025, 09:51:36 pm
content: Quote from: fourfathom on July 26, 2025, 06:50:18 pmThat method seems the same with this one, implemented with a microcontroller in order to produce PDM (Pulse Density Modulation) for fading LEDs:https://hackaday.io/project/6356-delta-sigma-versus-pwm

author: fourfathom
author_rank: Super Contributor
timestamp: July 26, 2025, 11:34:18 pm
content: Quote from: RoGeorge on July 26, 2025, 09:51:36 pmYeah, I glanced at the code and saw the different addends and subtrahends so figured that it was a Bresenham-type fractional process. I've done the Bresenham in C on a little uC when I need exact fractional timing relationships with minimum jitter.Quote from: NNNI on July 26, 2025, 07:05:30 pmI don't have the math chops to do any precise comparisons, but when I looked at MASH I recall it effectively being a binary noise generator (white? pink?). The Bresenham has a very periodic output pattern which can be useful or problematic depending on what you are trying to accomplish. It would be interesting to run the Bresenham output through a randomizer stage (which maintained the 1/0 ratio) -- this would reduce the periodic content and spread out that spectrum, but would increase the overall jitter magnitude. But if you follow that with an analog filter (as you often do) this might be useful.Of course for many applications these details are completely irrelevant!And for many cases and for many reasons the DDS is generally the go-to technique. I've got a couple of patents on methods to get non-power of 2 division from a DDS, so that certainly isn't an insurmountable problem. But if you want fast arbitrary fractional division then the Bresenham is usually simpler and faster. (DDS is probably simpler in software though.)

author: guenthert
author_rank: Frequent Contributor
timestamp: July 27, 2025, 09:47:53 am
content: Quote from: branadic on July 26, 2025, 07:40:13 pmHa, ha, yeah, that changes everything of course. I just read up a few pages of that thread. Seems at the time the schematic was posted, the software was already meant to implement a high-resolution PWM. Now I'm curious, whether a more modest resolution PWM (using a much smaller amplitude and consequently smaller ripple) had been tried to correct for the temperature and time related drift of a resistor based voltage divider? And if, why it was deemed inadequate.

author: mawyatt
author_rank: Super Contributor
timestamp: July 27, 2025, 03:12:31 pm
content: Our common use of MASH was for in chip frequency synthesis where 4th Order MASH was employed to "spread out and noise push" the fractional spurs in the synthesizer signal output spectrum. By "dithering" the synthesizer feedback divider ratio, this proved very effective in reducing and pushing fractional spurs to noise levels within the on-chip systems we were developing. Very powerful technique!!Best

author: fourfathom
author_rank: Super Contributor
timestamp: July 27, 2025, 04:00:56 pm
content: Quote from: mawyatt on July 27, 2025, 03:12:31 pmI've not used MASH specifically, but have designed in various types of dithering into digital and mixed PLLs for frequency synthesis and clock-domain synchronization. A good number of clock-generator chips these days include different types of dithering.Yes, very powerful, and sometimes dithering can be done with very simple methods. One telecom system I was architecting/managing included a Stratum-1 synchronization block. I had sketched out the digital PLL architecture (FPGA and later ASIC) and reminded the design engineer to *not* use a clock related to the external 1.544 MHz reference. But he did, using our 19.44 MHz clock (that ratio is 2623 / 193 -- these are all standard telecom frequencies) and was struggling with digital phase-detector dead-zones when testing his design. Rather than make him start over, I had him re-clock the reference input with an available 10 MHz clock using a two-stage sampler. Problem solved and no other changes needed! There obviously were spectral spurs created by the 10 MHz sampling process, but these were far removed and well-filtered by the already-designed digital filtering.

author: iMo
author_rank: Super Contributor
timestamp: July 29, 2025, 07:38:28 am
content: Once I was thinking about the branadic's (et al.) wiring (I collected the parts) with a different 8pin mcu (I have some modern pics here), I don't know whether they made the final sw in asm or in C. The usage of C may help with trying the other methods and chips while experimenting..The Vref might be the ADR1001 set to 5V output such we may get 1..10V out of it, for example.

author: Andreas
author_rank: Super Contributor
timestamp: July 29, 2025, 09:28:15 am
content: Hello,for the delta sigma method much less ressources are used when using (inline) assembler for the carry bit handling.Pure C does not help in this case. (see LM399 thread).with best regardsAndreasEdit:and since you need an external XTAL for stability I would start witn minimum 14 pins to have options for temperature compensation etc.

author: iMo
author_rank: Super Contributor
timestamp: July 29, 2025, 02:54:58 pm
content: Quote from: iMo on July 29, 2025, 07:38:28 amWe cannot get it working from 1V in that branadic (et al.) wiring - as the PWM divider is in the feedback of the first non-inverting amp, thus the gain is always bigger than 1. So the output will be from aprox 5V up..

author: Electrole
author_rank: Contributor
timestamp: July 29, 2025, 03:34:45 pm
content: I started developing a MASH-based PWM voltage calibrator a couple of years back, and got fine results. This technique ensures high resolution and very good linearity at the same time, using just one PWM string. One has to make sure to use a proper lowpass filter to filter out not just the PWM but also the rumble that occurs from the MASH-process. I made a DC-accurate lowpass filter and added linearization of the switching stage, and tested the calibrator's linearity against a HP 3458A. The result from 16 voltage sweeps from 1 V to 9 V (201 steps of 40 mV) is shown the the enclosed graph. The graph shows the deviation from a linear fit. The GUI and the MASH driver for the switches was originally made in LabVIEW, for reasons of flexilibity, but I'm moving the design to a controller in order to have a stand-alone solution. Presently, the voltage setting has a resolution of 32 bits, and it's being MASHed into 16 bits of PWM. There are still improvements to be done, but the results so far are promising. MASH with PWM is definitely a thing if you are looking at resolution and linearity, and multi-string PWMs will probably never be able to reach the same levels of linearity without very elaborate trimming.

author: mawyatt
author_rank: Super Contributor
timestamp: July 29, 2025, 04:58:55 pm
content: Quote from: Electrole on July 29, 2025, 03:34:45 pmThat's impressiveBest

author: arvee
author_rank: Contributor
timestamp: August 04, 2025, 08:50:43 pm
content: Here are some notes about the PWM software.The PWM is full range.The output voltage is between 0 volt and the 7 volt reference voltage.#1The unit for the width is one clock cycle (1/16MHz).If the count is zero, all pulses have width 0.If the count is increased then pulses with width 1 appear.This continues until there are 300 pulses with width 1.If the count is increased beyond 300 then pulses with width 2 appear.This continues until all 300 pulses have width 2.There are 3 operating regions:1. In the first region pulses with width 1 appear.The width of these pulses is NOT exactly 1 clock cycle.The level shifter between 5 volt and the reference voltage is not ideal.The rise and fall time can differ.What matters is the actual width.The region is very small: 12V / 53333 = 225 uV.2. In the second region the width of pulses is increased by 1.The increment of the width is exactly 1 clock cycle.The pulses are longer, with a constant width error.3. In the third region, at the top of the range, pulses disappear.It is the inverse of the first region.Each of the 3 regions has a different slope.The error can be corrected with one parameter.The processor frequency is 16 MHz, the period is 62.5 ns.The PWM frequency is 300 Hz, the PWM period is 3.3 ms.A change in the width by 3.3 ns gives 1e-6 error.#2The pulse width can be set from 1 to the period count.Zero width is not included.Zero width can be implemented by setting the output to 0.But then PWM interpolation between 0 and 1 is not possible.The solution is to invert both the count and the polarity of the output.#3The polarity of the output voltage is reversed using two relays.There are two signed zeros depending on the state of the relays.The voltage difference between the two zeros is twice the output offset of the buffer.It is an error of the voltage source.The correction should be with done by a shift over the x-axis.It is easier to do on the y-axis without any loss of accuracy.The error is removed by shifting the positive and negative readings over the y-axis towards each other.The relays are Coto 3402.The datasheet has a picture of the offset over time after the relay is energized.The drift in offset was 10 uV. The measured shift of relays used is less than 1 uV.#4With both relays energized the output is shorted.The buffer's output is also shorted. Therefore the PWM voltage is set to zero volts.In addition there is a 1 k ohm resistor in series with the buffer output.#5The calculation is done with integers.The numerical accuracy is improved with guard digits.