Saturday, November 2, 2024

Want an additional ADC? Add one for just a few cents



Want an additional ADC? Add one for just a few cents

When designing gadgets with microcontrollers (MCU), I like to make use of among the analog-to-digital converter (ADC) inputs to measure onboard voltages together with all of the required sensors inputs. This implies I usually run out of ADC inputs. So introduced here’s a method so as to add extra ADCs with out including exterior chips, costing lower than 5 cents, and taking on negligible house on a PCB!

There are two issues within the MCU you might be utilizing: a pulse width modulator (PWM) output and an onboard analog comparator. Some MCU traces which have these are the PIC, AVR, and ATmega MCUs from Microchip. Additionally, TI’s Piccolo line and STMicroelectronics STM32L5 have each a PWM and comparator.

So, let’s have a look at how that is configured.

The essential idea

Determine 1 is a diagram exhibiting the addition of a resistor and capacitor to your MCU mission.

Determine 1 Fundamental idea of the circuit that makes use of an MCU with an onboard PWM and comparator, in addition to an RC filter to create an ADC.

The resistor and capacitor type a single pole low-pass filter. So, the circuit idea takes the output of an onboard PWM, filters it to create a DC sign that’s set by the PWM’s responsibility cycle. The DC stage is then in comparison with the enter sign utilizing the on-board comparator. The circuit may be very easy so let’s discuss in regards to the code used to create an ADC from this association.

To get a pattern studying of the enter sign, we begin by setting the PWM to a 50% responsibility cycle. This square-wave PWM sign will probably be filtered by the RC low-pass filter to create a voltage that’s ½ of the MCU’s system voltage. The comparator output will go excessive (or output a digital 1) if the filtered DC stage is larger than the instantaneous enter sign voltage, in any other case the comparator output will go low (outputting a digital 0).

The code will now learn the comparator output and execute a search to discover a new stage that forces the comparator to an reverse output. In different phrases, if the comparator is a 0 the code will modify the PWM responsibility cycle up till the comparator outputs a 1. If the comparator is at the moment exhibiting a 1 the PWM responsibility cycle will probably be diminished till the comparator outputs a 0. If the PWM is able to one thing like 256 steps (or extra) in responsibility cycle, this search may take some important time. To mitigate this, we’ll do a binary search so if there are 256 steps accessible within the PWM, it should solely take log2(256), or 8, steps to check the degrees.

A fast description of the binary search is that after the primary 50% stage studying, the following take a look at will probably be at a 25% or 75% stage, relying on the state of the comparator output. The steps after this can once more take a look at the center of the remaining ranges.

An instance of the circuit’s perform

Let’s present a fast instance and assume the next:

  • System voltage: 5 V
  • PWM accessible ranges: 256
  • Instantaneous enter sign: 1 V

The primary take a look at will probably be executed with the PWM at about 50% responsibility cycle (a setting of 128), making a 2.50-V sign that’s utilized to the “+” enter of the comparator. This implies the comparator will output a excessive which suggests that the PWM responsibility cycle is simply too excessive. So, we’ll reduce the responsibility cycle in half giving a setting of 64, which creates 1.25 V on the “+” enter. The comparator once more will output a 1… to excessive so we drop the PWM responsibility cycle by half once more to 32. This provides a “+” stage of 0.625 V. Now the comparator will output a 0 so we all know we went too low, and we improve the PWM responsibility cycle. We all know 64 was too excessive and 32 was too low so we go to the middle, or (64+32)/2 = 48, giving 0.9375 V. We’re nonetheless too low so we break up the distinction of 64 and 48 leading to 56 or about 1.094 V…too excessive. This continues with (56+48)/2=52, giving 1.016 V…too excessive. Once more, with a PWM setting of (52+48)/2=50, giving 0.9766 V. One final step, (52+50)/2=51 giving 0.9961 V.

This was 8 steps and bought us as shut as we will to the reply. So, our ADC setup would return a solution that the instantaneous enter sign was 0.9961 V.

Pattern circuit with Arduino Nano

Let’s check out a real-world instance. This instance makes use of an Arduino Nano which makes use of an ATmega328P which has a lot of PWM outputs and one analog comparator. The PWM we’ll use could be clocked at numerous charges and we wish to clock it quick as this can make the filtering simpler. It would additionally velocity up the time for the filter output to settle to its ultimate stage. We’ll choose a PWM clocking price of about 31.4 kHz. Determine 2 reveals the schematic with a one pole RC low-pass filter.

Determine 2 Schematic of the pattern circuit utilizing an Arduino Nano and a one-pole RC low-pass filter.

On this schematic D11 is the PWM output, D6 is the comparator’s “+” enter, whereas D7 is the comparator’s “-” enter. The filter consists of a 20kΩ resistor and a 0.1 µF capacitor. I arrived at these values by taking part in round in an LTspice simulation to attempt to reduce the remnants of the PWM pulse (ripple) whereas additionally sustaining a reasonably quick settling time. A goal for the ripple was the decision of a 1-bit change within the PWM, or much less. Utilizing the 5 V of the system voltage and the knowledge that the PWM has 8-bit (256 settings) adjustability we get 5 V/256 = ~20 mV. Within the LTspice simulation I bought 18 mV of ripple whereas the dc stage settled in inside just a few millivolts of its ultimate worth at 15 ms. Due to this fact, when writing the code, I used 15 ms because the delay between samples (with a small twist you’ll see beneath). Because it takes 8 readings to get a ultimate usable pattern, it should take 8*15 ms = 120 ms, or 8.3 samples per second. As famous originally, you received’t be sampling at audio charges, however you possibly can actually monitor DC voltages on the board or slow-moving analog alerts.

[This may be a good place to note that the analog input does not have a sample-and-hold as most ADCs do, so readings are a moving target. Also, there is no anti-aliasing filter on the input signal. If needed, an anti-alias filter can remove noise and also act as a rough sample and hold.]

Pattern code

Under is the code itemizing to be used in an Arduino growth surroundings. You can even obtain it right here. It would learn the enter sign, do the binary search, convert it to a voltage, after which show the ultimate 8-bit DAC worth, corresponding voltage studying, and a slower shifting filtered worth.

The next offers a deeper description of the code:

  • Traces 1-8 outline the pin we’re utilizing for the PWM and declares our variables. Notice that line 3 units the system voltage. This worth ought to be measured in your MCU’s Vcc pin.
  • Traces 11 and 12 arrange the PWM on the required frequency.
  • Traces 15 and 16 arrange the on-board comparator we’re utilizing.
  • Line 18 initializes the serial port we’ll print the outcomes on.
  • Line 22 is the place the primary code begins. First, we initialize some variables every time to start a binary search.
  • Line 29 we start the 8-step binary search and line 30 units the responsibility cycle for the PWM. A 15-millisecond delay is then launched to permit for the low-pass filter to settle.
  • Line 34 is the “small twist” hinted at above. This introduces a second, random, delay between 0 and 31 microseconds. That is included as a result of the PWM ripple that’s current, after the filter, is correlated to the 16-MHz MCU’s clock so, to help in filtering this out of our ultimate studying, we inject this delay to interrupt up the correlation.
  • Traces 37 and 38 will verify the comparator after the delay is carried out. Relying on the comparability verify, the vary for the following PWM responsibility cycle is adjusted.
  • Line 40 calculates the brand new PWM responsibility cycle inside this new vary. The code then loops 8 instances to finish the binary search.
  • Traces 43 and 44 calculate the voltage for the present instantaneous voltage studying in addition to a filtered common voltage studying. This voltage averaging is completed utilizing a quite simple IIR filter.
  • Traces 46-51 ship the knowledge to the Arduino serial monitor for show.
1  #outline PWMpin 11 // pin 11 is D11
2  
3  float systemVoltage = 4.766; // Precise voltage powering the MCU for calibrating printedoutput voltage
4  float ADCvoltage = 0; // Remaining found voltage
5  float ADCvoltageAve = 0; // Remaining found voltage averaged
6  uint8_t currentPWMnum = 0; // Quantity despatched to the PWM to generate the requested voltage
7  uint8_t minPWMnum = 0; 
8  uint8_t maxPWMnum = 255; 
9  
10 void setup()  B00000001;  // Set timer 1 to 31372.55 Hz which is now the D11 PWM frequency
13 
14   // Arrange comparator
15   ADCSRB = 0b01000000; // (Disable) ACME: Analog Comparator Multiplexer disabled
16   ACSR = 0b00000000; //allow AIN0 and AIN1 comparability with interrupts disabled  
17 
18   Serial.start(9600); // open the serial port at 9600 bps:
19 
20 
21 
22 void loop() {
23 
24   currentPWMnum = 127; // Begin binary search on the midway level  
25   minPWMnum = 0; 
26   maxPWMnum = 255; 
27 
28   // Carry out a binary seek for matching comparator setting
29   for (int8_t i = 0; i < 8; i++) { // Loop 8 instances   
30     analogWrite(PWMpin, currentPWMnum); // Regulate PWM to new dutycycle setting  
31       
32     // Now wait
33     delay(15); // Wait 15 ms to let the low-pass filter to settle.
34     delayMicroseconds(random(0,32)); // Delay a random variety of microseconds (0 via 31) to interrupt attainable correlation (dithering)
35   
36     // Verify to see if comparator reveals AIN0 > AIN1 ( in that case ACO in ACSR is about to 1)
37     if (ACSR & (1<<ACO))  maxPWMnum = currentPWMnum; // (AIN0 > AIN1) Transfer max pointer
38     else minPWMnum = currentPWMnum; // Transfer min pointer  
39 
40     currentPWMnum= minPWMnum + ((maxPWMnum - minPWMnum) / 2); // Set new take a look at quantity to the center of PWMmin and PWMmax
41   } 
42 
43   ADCvoltage = systemVoltage * ((float)currentPWMnum/255); // Set the PWM for binary search of voltage (assumes 0 to 5v sign
44   ADCvoltageAve = (ADCvoltageAve * 0.95) + (ADCvoltage * 0.05); // Generate a mean worth to clean studying
45 
46   Serial.print("PWM Setting = ");
47   Serial.print(currentPWMnum);
48   Serial.print("   ADC Voltage  = ");
49   Serial.print(ADCvoltage, 4);
50   Serial.print("   ADC Voltage Filtered = ");
51   Serial.println(ADCvoltageAve, 4);
52 }    

Check outcomes

Step one was to measure the system voltage on the +5-V pin or the Arduino Nano. This worth (4.766 V) was entered on line 3 of the code. I then ran the code on an Arduino Nano V3 and monitored the output on the Arduino serial monitor. To check the code and system, I first linked a 2.5-V reference voltage to the sign enter. This reference was first warmed up and a voltage studying was taken on a calibrated 5 ½ digit DMM. The reference learn 2.5001 V. The serial monitor confirmed an instantaneous voltage various from 2.5232 to 2.4858 V and the common voltage diversified from 2.5061 to 2.5074 V. That is round 0.9% error within the instantaneous voltage studying and about 0.3% on the averaged voltage studying. This reveals we’re getting a studying with about ±1 LSB error within the instantaneous voltage studying and a filtered studying of about ± 0.4 LSB. When inputting numerous different voltages I bought comparable accuracies.

I additionally examined with an enter of Vcc (4.766 V) and seen outcomes of 4.7473 V which suggests it may work up very near the higher rail. With the enter grounded the instantaneous and filtered voltages confirmed 0.000 V.

These appear to be an excellent consequence for an ADC created by including two cheap components.

So subsequent time you’re in need of ADCs give this a attempt. The fee is negligible, PCB house may be very minimal, and the code is small and straightforward to grasp.

Damian Bonicatto is a consulting engineer with a long time of expertise in embedded {hardware}, firmware, and system design. He holds over 30 patents.

Phoenix Bonicatto is a contract author.

Associated Content material

<!–
googletag.cmd.push(perform() { googletag.show(‘div-gpt-ad-native’); });
–>

The put up Want an additional ADC? Add one for just a few cents appeared first on EDN.


👇Observe extra 👇
👉 bdphone.com
👉 ultraactivation.com
👉 trainingreferral.com
👉 shaplafood.com
👉 bangladeshi.assist
👉 www.forexdhaka.com
👉 uncommunication.com
👉 ultra-sim.com
👉 forexdhaka.com
👉 ultrafxfund.com
👉 ultractivation.com
👉 bdphoneonline.com

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles