Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 13:30 27 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Micromite MK2:MCP342x i2c ADCs

Author Message
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9122
Posted: 05:36am 21 Nov 2014
Copy link to clipboard 
Print this post

Another favorite range of chips. The MCP3424 is a 4 channel 18 bit ADC with programmable gain (1,2,4,8) and 4 possible i2c addresses allowing up to 16 channels of high resolution conversion (1 LSB=0.015625 millivolts at a gain of 8). The MCP3423 has 2 channels and 4 possible i2c addresses. The MCP3422 is 2 channel on a single fixed i2c address and the MCP3421 is single channel single address. The base address conflicts with DS1307 beware! The MCP3424 is available as a breakout from Jeelabs if you ignore their strange labeling of the i2c signals, 3424 and 3422 are available as SOIC so easy to solder to a PDIP adapter.

The thing I really like about these chips is the programmable gain which allows them to be used for things like strain gauges and thermocouples with no addition signal conditioning. I'll post full thermocouple conversion for K-type thermocouples including cold junction compensation using a DS18B20 in a subsequent thread.

In the example code I use a DAC to generate a test voltage and then convert it at various gains and number of bits.

Output on my test rig as follows:
12 bit conversion, Gain = 1 Voltage = 0.174
14 bit conversion, Gain = 1 Voltage = 0.17375
16 bit conversion, Gain = 1 Voltage = 0.173813
18 bit conversion, Gain = 1 Voltage = 0.173813
12 bit conversion, Gain = 2 Voltage = 0.174
14 bit conversion, Gain = 2 Voltage = 0.173875
16 bit conversion, Gain = 2 Voltage = 0.173906
18 bit conversion, Gain = 2 Voltage = 0.173898
12 bit conversion, Gain = 4 Voltage = 0.17375
14 bit conversion, Gain = 4 Voltage = 0.173813
16 bit conversion, Gain = 4 Voltage = 0.0434531
18 bit conversion, Gain = 4 Voltage = 0.173824
12 bit conversion, Gain = 8 Voltage = 0.173625
14 bit conversion, Gain = 8 Voltage = 0.173625
16 bit conversion, Gain = 8 Voltage = 0.173625
18 bit conversion, Gain = 8 Voltage = 0.173621


' MCP 342x 18bit Multi-channel ADC with I2C interface demo program
'
cpu 48
option explicit
option default FLOAT
const ADCi2c = &B1101000 ' set to match your hardware
const ADCBits12=&B10000000
const ADCBits14=&B10000100
const ADCBits16=&B10001000
const ADCBits18=&B10001100
const ADCbits12timeout= 2 'number of 5 msec loops to wait for ADC conversion before giving up
const ADCbits14timeout= 5
const ADCbits16timeout= 15
const ADCbits18timeout= 60
const ADCBits12size= 0.001
const ADCBits14size= 0.00025
const ADCBits16size= 0.0000625
const ADCBits18size= 0.000015625
'max voltages
' gain 1 = +/- 2.048V
' gain 2 = +/- 1.024V
' gain 4 = +/- 0.512V
' gain 8 = +/- 0.256V
const signed=1
const unsigned=0
' Pin assignments
'
' DAC pin 1 = VDD
const cs=23 'DAC pin 2 connected to digital output on micromite
' Pin 25 = SCK : DAC Pin 3
' Pin 3 = SDI : DAC Pin 4
const ldac=24 ' DAC Pin 5 connected to digital output on micromite
const voutb=7 ' DAC Pin 6 connected to analogue input on micromite
' DAC Pin 7 = GND
const vouta=6 ' DAC Pin 8 connected to analogue input on micromite
'
'Pin use
'
setpin cs, dout
setpin ldac, dout
setpin vouta,ain
setpin voutb,ain
'
dim voltage
dim i as integer,gain as integer
'
INIT:
pin(cs)=1 'set chip select inactive
pin(ldac)=1 'set ldac inactive
spi open 5000000,0,16 '5 MEG, 16 bit transfer, CLK active high, data on leading edge
i2c open 400,1000
'
MAIN:
voltage=setdac(0,1,0.173)
for i=0 to 3
gain=1<<i
print "12 bit conversion, Gain = ",gain," Voltage = ",readadc(0,gain,12)
print "14 bit conversion, Gain = ",gain," Voltage = ",readadc(0,gain,14)
print "16 bit conversion, Gain = ",gain," Voltage = ",readadc(0,gain,16)
print "18 bit conversion, Gain = ",gain," Voltage = ",readadc(0,gain,18)
next i
end
'
function readadc(channel as integer, adcgain as integer, bits as integer)
' config byte for chip is:
' bits 0 and 1 - Gain 1,2,4,8
' bits 2 and 3 - # of bits 12,14,16,18; 240,60,15,3.75 samples per second respectively
' bit 4 - 0=one-shot conversion ; 1=continous; we will always use 0 to allow changes to config e.g. which channel
' bits 5 and 6 - channel number 0-3
' bit 7 - set to start conversion, wait for clear to indicate conversion end
' max voltages
' gain 1 = +/- 2.048V with both vin- and vin+ between VSS and VDD
' gain 2 = +/- 1.024V
' gain 4 = +/- 0.512V
' gain 8 = +/- 0.256V
local channelmask as integer,gainmask as integer, scratch as integer, timeout as integer
local configbyte as integer, ADCreading as integer
local ADCret$ length 4
local bitsize as float
scratch=adcgain
gainmask=0
do while not(scratch and 1)
scratch=scratch>>1
gainmask=gainmask+1
loop
scratch=((bits-12)\2) + 1
if channel<0 or channel>3 or gainmask<0 or gainmask>3 or scratch<1 or scratch>4 then
readadc=100 'impossible value
exit function
endif
on scratch goto bit12,bit14,bit16,bit18
bit12:
timeout=ADCbits12timeout
configbyte=ADCbits12
bitsize=ADCbits12size
goto addgainbits
bit14:
timeout=ADCbits14timeout
configbyte=ADCbits14
bitsize=ADCbits14size
goto addgainbits
bit16:
timeout=ADCbits16timeout
configbyte=ADCbits16
bitsize=ADCbits16size
goto addgainbits
bit18:
timeout=ADCbits18timeout
configbyte=ADCbits18
bitsize=ADCbits18size
addgainbits:
configbyte=configbyte or gainmask
channelmask=channel << 5
configbyte=configbyte or channelmask
i2c write ADCi2c, 0,1,configbyte
do
pause 5
i2c read ADCi2c, 0,4,ADCret$
scratch =asc(right$(ADCret$,1)) AND &B10000000
timeout=timeout-1
loop until (scratch=0) or (timeout=0)
if timeout <>0 then
if bits=18 then
adcreading=intconv(left$(ADCret$,3),signed)
else
adcreading=intconv(left$(ADCret$,2),signed)
endif
readadc=adcreading*bitsize/adcgain
else
readadc=0
endif'
end function
'
' Function to set output on one of the DAC channels
'
function setdac (DAC as integer, dacgain as integer, volts)
local dacdata as integer,FuncRet as integer
dacdata=cint(volts * 2000 / dacgain)
if dacdata>4095 or dacdata<0 or DAC<0 or DAC>1 or dacgain<1 or dacgain>2 then
setDAC=0
exit function
endif
setdac= dacdata /2000 * dacgain
if DAC=0 then
dacdata=dacdata or &B0011000000000000
else
dacdata=dacdata OR &B1011000000000000
endif
if dacgain=2 then dacdata=dacdata and &B1101111111111111 'clear bit 13 to set gain of 2
pin(cs)=0 'enable data reception
FuncRet=spi(dacdata) 'output the control bits and the data
pin(cs)=1 'disable data reception
pulse ldac,0.005
end function
'
CFunction intconv
00000000
27bdfff8 00001021 00001821 afa20000 afa30004 90880000 1900000b 01003821
2503ffff 03a31821 24020001 00823021 90c60000 a0660000 24420001 00e2302a
10c0fffa 2463ffff 8ca20000 1040000d 03a81021 9042ffff 30420080 10400009
29020008 10400007 03a81021 27a40008 2403ffff a0430000 24420001 5444fffe
a0430000 8fa20000 8fa30004 03e00008 27bd0008
End CFunction


Edited by matherp 2014-11-22
 
twofingers
Guru

Joined: 02/06/2014
Location: Germany
Posts: 1243
Posted: 05:48am 21 Nov 2014
Copy link to clipboard 
Print this post

Hi

very impressive and useful! Thanks!

Regards
Michael
causality ≠ correlation ≠ coincidence
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9122
Posted: 08:07am 21 Nov 2014
Copy link to clipboard 
Print this post

Got the resolution wrong in my note above, 1 LSB @ 18 bits and gain 8 = 1.953125 MICRO voltsEdited by matherp 2014-11-22
 
Plasmamac

Guru

Joined: 31/01/2019
Location: Germany
Posts: 554
Posted: 11:11pm 24 Oct 2023
Copy link to clipboard 
Print this post

Will this work on picomite ? I like to use Picomite wlan to share the values over udp .
Thx
Plasma
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3194
Posted: 01:06am 25 Oct 2023
Copy link to clipboard 
Print this post

No, it uses a CFunction.
CFunctions contain binary code compiled for a specific CPU.
Geoff Graham - http://geoffg.net
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6099
Posted: 01:50am 25 Oct 2023
Copy link to clipboard 
Print this post

The CFunction only converts the input data so it would be easy enough to do that in Basic.
The pico doesn't have the DAC so you would have to organize a test voltage differently.

The chip is I2C so that part is OK.

Jim
VK7JH
MMedit   MMBasic Help
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3802
Posted: 07:04am 25 Oct 2023
Copy link to clipboard 
Print this post

The logic would convert to Basic and the pico is fast so maybe no CSUB (equivalent of the CFunction) would be needed.

John
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 9122
Posted: 07:30am 25 Oct 2023
Copy link to clipboard 
Print this post

Intconv can be replaced by the inbuilt function str2bin
 
Plasmamac

Guru

Joined: 31/01/2019
Location: Germany
Posts: 554
Posted: 11:52pm 25 Oct 2023
Copy link to clipboard 
Print this post

What DAC are you using here ? Only for interest? Thx
Plasma
 
Print this page


To reply to this topic, you need to log in.

© JAQ Software 2024