Wednesday, March 30, 2016

ESP8266 - ADC Input frontend



Autorange Analog frontend


For a deeper Hardware description please take a look at the ESP8266 Analog Extension Board





What we will need:
 


ADC Frontend description

 Selection of the input voltage divider is done using an analog switch driven by PCF8574 PORT P0 and P1 bits:

0 - 1:20 Divider
1 - 1:10 Divider
2 - 1:5 Divider
3 - Full Voltage Range


As the ADC Input is programmed to be used in the 0-2V range that will give us the followings available ranges:

0 -> 0 - 40V
1 -> 0 - 20V
2 -> 0 - 10V
3 -> 0 - 2V

In the case of using the MCP3421 ADC at 12 Bit resolution, we will have the following corresponding LSB values:

- 1:20 Divider  -  0.02V
- 1:10 Divider  -  0.01V
- 1:5 Divider    -  0.005V
- Full Range    -  0.001V




Software implementation

1. Init I2C bus/interface

 Standard I2C Bus Initialisation function:

function init_I2C()
    i2c.setup(bus, sda, scl, i2c.SLOW)
end

 2. Set PCF8574 PORT Register Function
function setPort( port, stat) 
    i2c.start(id)
    i2c.address(id, dev_addr ,i2c.TRANSMITTER)
    i2c.write(id,stat)
    i2c.stop(id)
end

 3. Set Port function 

 Just a nicer way to write data to PCF8574 Register. Remember that we need to write a "ZERO" to the corresponding bit. We are sinking not sourcing !!

function setPortdata(p)
    pp = 255-p
    setPort(0x20,pp)
end


4. Set Voltage Divider function

  Select the desired Voltage divider ratio based on the choosen ratio value and calibrated LSB data.

--calibration data
x20 = 0.020056
x10 = 0.01014
x5  = 0.005014
xfl = 0.0010075
xrt = x20 --by default start with highest VDIV!
function SetVDivider(rtio)
    if (rtio==0) then xrt=x20 end
    if (rtio==1) then xrt=x10 end
    if (rtio==2) then xrt=x5 end
    if (rtio==3) then xrt=xfl end
    print("XRT = "..xrt)
    setPortdata(rtio)    -- select desired voltage divider
    return xrt
end



       -- Set/Change Voltage Divider ratio:
SetVDivider(0)  -- 1:20 Divider
SetVDivider(1)  -- 1:10 Divider
SetVDivider(2)  -- 1:5  Divider
SetVDivider(3)  -- 1:1  Full Voltage in!!


5. MAIN Program


-- Main Program
id = 0
sda=2 --GPIO4
scl=1 --GPIO5
dev_addr = 0x20
--calibration data
x20 = 0.020056
x10 = 0.01014
x5  = 0.005014
xfl = 0.0010075
xrt = x20 --by default start with highest VDIV!
--init I2C Bus
init_I2C()

--Init Volatage divider
setPortdata(0) -- --by default start with highest VDIV!
SetVDivider(0)  -- 1:20 Divider

----MCP3421 ADC
require('mcp3421')
sda=2 --GPIO4
scl=1 --GPIO5
mcp3421:init(sda, scl)
mcp3421:write_ADC_config(0x68, 0x10)

tmr.alarm( 0, 1000, 1, function()
    adc_val = mcp3421:read_ADC_data(0x68)
    print("\nADC Value : "..adc_val.." \n Voltage  : " ..adc_val*xrt)
    return adc_val
end)





No comments:

Post a Comment