---------------------------------- UPDATE --------------------------------------
For a ADC Input Frontend with Auto-range capabilities in the 0-40V Input range take a look also at the new ADC Input related article
--------------------------------- UPADTE ----------------------------------------
After testing the ESP8266 Internal ADC I think it's time to see also a higher resolution ADC at work. For this project we will use Microchip MCP3421 I2C ADC.
The MCP3421 is a single channel, low-noise, high accuracy delta-sigma A/D converter with differential inputs and up to 18 bits of resolution in a small SOT-23-6 package. The on-board precision 2.048V reference voltage enables an input range of ±2.048V differentially.
The device uses a two-wire I2C compatible serial interface and operates from a single power supply ranging from 2.7V to 5.5V.
This device has an onboard programmable gain amplifier (PGA). User can select the PGA gain of x1, x2, x4, or x8 before the analog-to-digital conversion takes place. This allows the MCP3421 device to convert a smaller input signal with high resolution.
The device has two possible to configure conversion modes:
- Continuous mode
- One-Shot mode.
FEATURES:
- 18-bit resolution
- Small 6-lead SOT-23 packaging
- Differential input operation
- On-board voltage reference with 5 ppm/°C drift
- On-board PGA, gains of 1, 2, 4, 8
- Programmable data rate options
- 3.75 SPS (18 bits)
- 15 SPS (16 bits)
- 60 SPS (14 bits)
- 240 SPS (12 bits)
- INL 10 ppm of FSR max
- Low current consumption, 145 µA at 3V
- One-shot or continuous conversion options
- Supports I2C™ serial interface
- Extended temperature range: -40°C to +125°C
For more details, please see MCP3421 Datasheet
As been available in SOT-23-6 package, we will use again an DIP adaptor that will make it easy to integrate it on our CBDB Board expansion slots:
MCP3421 - SOT-23-6 To DIP Adapter |
- 12 Bit DAC
- Selectable 12-14-16-18 Bit ADC
- RTC
- High Precision Temperature sensor
- Expansion slot for PIR sensor / Triac Main Power Switch module or anything else you want
- LCD
- Programming port - USB Adapter
Because of the high interest and the number of requests raised by the CBDB project in the next weeks we will run small batches of CBDB based devboard PCBs. The main purpose of the CBDB board was for local training and drivers development but if any new one interested please express your wishes at: tech at esp8266-projects.com.
It will be nothing fancy, just CBDB Board
CBDB DevBoard v2.0b |
What we will need for our ADC project:
- CBDB Board
- USB adapter (take a look on Part 1 for details how to connect them together)
- MCP3421 Module from above
- Battery Module
- Voltage divider
- LCD Display
MCP3421 ADC I2C Driver implementation
As MCP3421 has a I2C compatible compatible interface, driver building it following more or less the same process as before for I2C devices.
Few important consideration about MCP3421:
The MCP3421 has an 8-bit wide configuration register to select for: PGA gain, conversion rate, and conversion mode. This register allows the user to change the operating condition of the device and check the status of the device operation. The user can rewrite the configuration byte any time during the device operation.
The MCP3421 device accepts a fully differential analog input signal which is connected on the VIN+ and VINinput pins. The differential voltage that is converted is defined by VIN = (VIN+ - VIN-) where VIN+ is the voltage applied at the VIN+ pin and VIN- is the voltage applied at the VIN- pin.
The input signal level is amplified by the programmable gain amplifier (PGA) before the conversion.
The digital output code produced by the MCP3421 is a function of PGA gain, input signal, and internal reference voltage. In a fixed setting, the digital output code is proportional to the voltage difference between the two analog inputs.
The output data format is a binary two’s complement.
With this code scheme, the MSB can be considered a sign indicator. When the MSB is a logic ‘0’, it indicates a positive value. When the MSB is a logic ‘1’, it
indicates a negative value. The following is an example of the output code:
- for a negative full-scale input voltage: 100...000
- for a zero differential input voltage: 000...000
- for a positive full-scale input voltage: 011...111.
The MSB is always transmitted first through the serial port. The number of data bits for each conversion is 18, 16, 14, or 12 bits depending on the conversion mode selection.
LSB size vs. conversion mode set :
Bit Resolutions LSB (V)
12 bits 1 mV
14 bits 250 μV
16 bits 62.5 μV
18 bits 15.625 μV
For programming and uploading the driver and the software we will continue to use the LuaUploader as before.
1. Init I2C bus/interface
init = function (self, sda, scl)
i2c.setup(0x0, sda, scl, i2c.SLOW)
end
2. Write ADC Register Function
write_ADC_config = function ( self, dev_addr, set)
i2c.start(0x0)
i2c.address(0x0, dev_addr ,i2c.TRANSMITTER)
i2c.write(0x0,set)
i2c.stop(0x0)
end
3. READ ADC Function - 12, 14, or 16 bit-mode, 0-2.048V Range
read_ADC_data = function (self,dev_addr)
i2c.start(0x0)
i2c.address(0x0, dev_addr,i2c.RECEIVER)
c = i2c.read(0x0,3)
i2c.stop(0x0)
vadc = (bit.lshift(string.byte(c, 1), 8) + string.byte(c, 2))
return vadc
end
For testing, pack it together and save the code on ESP as 'mcp3421.lua', restart ESP and run:
require('mcp3421') -- call for new created MCP3421 Module Driver
sda=2 --GPIO4
scl=1 --GPIO5
mcp3421:init(sda, scl) -- init I2C
mcp3421:write_ADC_config(0x68, 0x10) -- Write Register config: 12Bit/CCV/PGA = 1V/V
adc_val = mcp3421:read_ADC_data(0x68) -- Read ADC Data
print("ADC Value : "..adc_val)
lsb=1 -- 12 bit -> LSB = 1mA
vts = (adc_val * l1)/1000*4.3043 --calibrate based on your power supply, Vref and divider
print("\nValue = " ..adc_val.." \nVolts = "..string.format("%g",vts).." mV")
print("\nValue = " ..adc_val.." \nVolts = "..string.format("%.4f",vts).." mV")
MCP3421 ADC - First test |
Filtered clean source voltage measurement :
4. Read ADC and Print values on LCD
read_ADC_LCD1 = function()
adc_val = mcp3421:read_ADC_data(0x68)
l1=1 -- 12 bit
--l1=0.0625 -- 16 bit
val = (adc_val * l1)/1000*4.3043
print(" ReadADC : "..val)
val = string.format("%g",val)
st7032i:lcd_print(0,2,adc_val)
st7032i:lcd_print(9,2,val)
end
For testing, pack it together and save the code on ESP as 'mcp3421.lua', restart ESP and run:
require('mcp3421') -- call for new created MCP3421 Module Driver
sda=2 --GPIO4
scl=1 --GPIO5
mcp3421:init(sda, scl) -- init I2C
mcp3421:write_ADC_config(0x68, 0x10) -- Write Register config: 12Bit/CCV/PGA = 1V/V
require('st7032i')
st7032i:init_LCD()
st7032i:lcd_setCursor(0,1)
st7032i:lcd_write("ADC_Val Volts")
tmr.alarm(0, 1000, 1, function() read_ADC_LCD1() end) -- read ADC and Print on LCD
MCP3421 ADC - LCD Print test |
MCP3421 ADC - LCD Print test |
1. Test done in filtered environment - highly stable voltage
2. Test done in noisy environment - using real bus voltage - unfiltered
3. Test done in noisy environment - values are printed directly on CBDB DevBoard LCD Display
Thank you all for your continuous support and great feedback!
5 comments:
Hi,
I tested your code and it does not works. Can you please publish all the code to download?
Thank you.
Fero
Hi Fero,
Are you sure that you are using the right I2C address for the ADC? It can be different than in the case above, please read datasheet about.
Full MCP3421 ADC I2C driver code:
https://drive.google.com/file/d/0B0rG5x0nlgpXMmo5ZVlCdFdoVjA/view?usp=sharing
Hi,
thank you for your response. Can you please write me which parameter is necessary to change ( I2C address ) ?
It's in the function write_ADC_config(0x68, 0x10)?
Thank you.
Fero
you need to replace "dev_addr" that in my case is 0x68 with de I2C address of your ADC, look what version you have and choose address based on the datasheet.
I have used so far these variants: MCP3421A0T, MCP3421A1T, MCP3421A2T. Each one have a different I2C address.
hmm
Post a Comment