Forum - MCS Electronics

 

FAQFAQ SearchSearch RegisterRegister Log inLog in

Working With MAX1238/9 12BIT 12 Channel I2C ADC

 
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM Project Blog
View previous topic :: View next topic  
Author Message
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Mon Apr 08, 2013 1:39 pm    Post subject: Working With MAX1238/9 12BIT 12 Channel I2C ADC Reply with quote

Finding that the 10 bit ADCs in the AVRs are just not enough for most of my projects I have been looking for a while for an ADC that is similar to the AVRs but more bits (12 or better) I have tried over sampling but still it was not good enough the best I could get was 3 stable digits no good if I wanted to measure 12.45 Volts or worse still with an analog sensor with 2.453 Volts so recently I saw one at a low cost (on special) the MAX1238 this is a 12 bit, 12 Channel , single ended or differential, I2C buss device. First problem is that its a tiny QSOP package but I found Sparkfun has an adapter PCB ready to go to convert this to 16 pin dip just need a steady hand to solder it and some solder wick to clean up. Next I need to talk to it so read the data sheet, so I read it only to find it half of what I need ok just have to play with it to see what goes.

Step 1: connect it up to an AVR on the I2C buss with resistors fitted.

Step 2: scan the buss to see if it answers back and it did!

Note you can find this in the I2C samples in bascom

Step 3; work out the commands to send to it (read the data sheet again)

Here is some code that works with a lot of the commands to send to the ADC

Code:

'-----------MAX1238------------------------------------------------------------------------
'--MAX1238 slave address
'--MAX1238 is a 12 bit 12 channel I2C ADC
'--write

'Dim Max1239b As Word
'Dim Max1239lh(2) As Byte At Max1239b Overlay

'Dim Volt As Single

'Const Wrmax1238 = &H6A                                      '&B01101010  write to MAX1238
'--read
'Const Rdmax1238 = &H6B                                      '&B01101011  read from MAX1238
'--setup byte
'use internal reference, internal clock, unipolar mode
'Const Setmax1238 = &HD2                                     ' &B11010010


'--configuration bytes

'-scan all adc inputs 0 to 11 single ended
'Const Scanall = &H17                                        '&B00010111


'--convert one ADC channel single ended                      BINARY VALUE
'Const Scan0 = &H61                                          '&B01100001 scan adc 0

'Const Scan1 = &H63                                          '&B01100011 scan adc 1

'Const Scan2 = &H65                                          '&B01100101 scan adc 2

'Const Scan3 = &H67                                          '&B01100111 scan adc 3

'Const Scan4 = &H69                                          '&B01101001 scan adc 4

'Const Scan5 = &H68                                          '&B01101011 scan adc 5

'Const Scan6 = &H6D                                          '&B01101101 scan adc 6

'Const Scan7 = &H6F                                          '&B01101111 scan adc 7

'Const Scan8 = &H71                                          '&B01110001 scan adc 8

'Const Scan9 = &H73                                          '&B01110011 scan adc 9

'Const Scan10 = &H75                                         '&B01110101 scan adc 10

'Const Scan11 = &H77                                         '&B01110111 scan adc 11




'--HSmode
'Const Hsmax1238 = &H08                                      '&B00001000

'-------------------------------------------------------------------------------




'---------------------------------------
'--This sub sets up and reads the values from
'--the MAX1239 12 bit ADC



  Sub Max1239_setup


'use internal reference, internal clock, unipolar mode
  I2csend Wrmax1238 , Setmax1238


  End Sub




  Sub Max1239_read

'use internal reference, internal clock, unipolar mode

  I2creceive Rdmax1238 , Max1239lh(1)
  I2creceive Rdmax1238 , Max1239lh(2)


  End Sub



  Sub Max1239_write

  I2csend Wrmax1238 , Scan0



  End Sub
 


I have it working but need to refine the code more and look into the other modes

Regards Paul


Last edited by Paulvk on Tue Apr 09, 2013 1:02 am; edited 1 time in total
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Tue Apr 09, 2013 12:35 am    Post subject: Reply with quote

Now even though the code is working I was getting wrong values some of the time so I had another look at the data sheet but this was no help! So what was going on it works when it first starts up well I found out what is going on even though the data sheet says nothing about it you need to send the set up every time you want to measure the ports. So the sequence is > send the set up command eg use the internal reference, single ended, unipolar mode then send the instruction to tell it what port or ports to measure, next read the data back. It now works all the time and I am getting a steady 5 digits that do not vary, 3 digits better than I ever got from the AVRs ADC this may be due to two factors one is the 12bits I now have, the second may be that this ADC is not in there with the other bits of the AVR and is on a seperate board connected via onl 4 lines + & - power and the I2C buss so there is far less noise to deal with. Next I will build a function to call the ADC values keeping it in line with bascom its going to be Getmax1238() (use the internal reference, single ended, unipolar mode )

This is the calls to the subs I have been testing it with Note the two shifts 4 bits to get rid of the first four bits that are always "1" as they are not used (we only have 12 bits ADC)
Code:

Call Max1239_setup

Call Max1239_write

Waitms 200

Call Max1239_read

Shift Max1239b , Left , 4
Shift Max1239b , Right , 4

Print "MAX>" ; Max1239b

Volt = Max1239b * 0.00097813

Print "VOLTS>" ; Fusing(volt , "##.####")

 



Regards Paul
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Tue Apr 09, 2013 12:01 pm    Post subject: Reply with quote

I have now combined the commands into one sub "Getmax1239" by putting the channel number it reads that channel eg Getmax1239 1 will read channel number one, the 12bits are stored in the global variable "Max1239b" ready to be worked with making it easy to replace the getadc() command.

Regards Paul

Code:


'----this takes a channel number (Chno) sets up the ADC
'----tells it to do the conversion
'----and reads the value from the channel
Sub Getmax1239(byval Chno As Byte )

  Local Scan_val As Byte

  '--move the bits to the left one place as the last bit
  '--is "1" as we are writing to the ADC

  Shift Chno , Left , 1

 '--&H61 is to read channel 0 so if we add
 '--the channel number to it shifted left
 '--one place we will get the byte to read
 '--the channel number we want

  Scan_val = &H61 + Chno

'use internal reference, internal clock, unipolar mode
  I2csend Wrmax1238 , Setmax1238

  I2csend Wrmax1238 , Scan_val

  '--read in the two bytes using the overlay function
  '--which breaks up the Max1239b word

  I2creceive Rdmax1238 , Max1239lh(1)
  I2creceive Rdmax1238 , Max1239lh(2)

'--move the word to the left 4 bits causing
'--the first 4 bits to get lost then move it
'--back 4 bits which will make them all 0s
'--giving us only the 12bits we want

  Shift Max1239b , Left , 4
  Shift Max1239b , Right , 4



End Sub
 
Back to top
View user's profile
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Mon Jul 01, 2013 1:23 pm    Post subject: Reply with quote

Now an update to fix the problem of the bytes being swapped and to make the code simpler, use less flash, be self contained also work like getadc does in bascom.

All that is now needed is to take a word variable and let it equal Getmax1239(x) so wordvariable = Getmax1239(x) where x is the port of the max1239/8 the variable will be loaded with the value from the port just like getadc in bascom.

Note thus far I have only worked in single ended mode (unipolar) but soon will adjust for differential operation (bipolar) mode.

Regards Paul



Code:

'-----------MAX1238------------------------------------------------------------------------
'--MAX1238 slave address
'--MAX1238 is a 12 bit 12 channel I2C ADC
'--write


 '--This returns the value of the ADC port of the Max1238/9
' Declare Function Getmax1239(byval Chno As Byte ) As Word
'Declare Sub Max1239_setup

'Dim Max1239b As Word
'Dim Max1239lh(2) As Byte At Max1239b Overlay 'lets you wor with each byte of the word

'Dim Volt As Single

'Const Wrmax1238 = &H6A                                      '&B01101010  write to MAX1238
'--read
'Const Rdmax1238 = &H6B                                      '&B01101011  read from MAX1238
'--setup byte
'use internal reference, internal clock, unipolar mode
'Const Setmax1238 = &HD2                                     ' &B11010010


'--configuration bytes

'-scan all adc inputs 0 to 11 single ended
'Const Scanall = &H17                                        '&B00010111


'--convert one ADC channel single ended                      BINARY VALUE
'Const Scan0 = &H61                                          '&B01100001 scan adc 0

'Const Scan1 = &H63                                          '&B01100011 scan adc 1

'Const Scan2 = &H65                                          '&B01100101 scan adc 2

'Const Scan3 = &H67                                          '&B01100111 scan adc 3

'Const Scan4 = &H69                                          '&B01101001 scan adc 4

'Const Scan5 = &H68                                          '&B01101011 scan adc 5

'Const Scan6 = &H6D                                          '&B01101101 scan adc 6

'Const Scan7 = &H6F                                          '&B01101111 scan adc 7

'Const Scan8 = &H71                                          '&B01110001 scan adc 8

'Const Scan9 = &H73                                          '&B01110011 scan adc 9

'Const Scan10 = &H75                                         '&B01110101 scan adc 10

'Const Scan11 = &H77                                         '&B01110111 scan adc 11




'--HSmode
'Const Hsmax1238 = &H08                                      '&B00001000

'-------------------------------------------------------------------------------




'---------------------------------------
'--These subs set up and read the values from
'--the MAX1239 12 bit ADC





'----this takes a channel number (Chno) sets up the ADC
'----tells it to do the conversion
'----and reads the value from the channel
Function Getmax1239(byval Chno As Byte ) As Word

  Local Scan_val As Byte
  Local Adcval As Word

  '--move the bits to the left one place as the last bit
  '--is "1" as we are writing to the ADC

  Shift Chno , Left , 1

 '--&H61 is to read channel 0 so if we add
 '--the channel number to it shifted left
 '--one place we will get the byte to read
 '--the channel number we want

  Scan_val = &H61 + Chno

'use internal reference, internal clock, unipolar mode
  I2csend Wrmax1238 , Setmax1238

  I2csend Wrmax1238 , Scan_val

  'Waitms 1     'this may be needed depending on the cpu clock speed

  '--read in the two bytes using


  I2creceive Rdmax1238 , Adcval


  'Swap the two bytes of the word
  Swap Adcval


'--move the word to the left 4 bits causing
'--the first 4 bits to get lost then move it
'--back 4 bits which will make them all 0s
'--giving us only the 12bits we want

  Shift Adcval , Left , 4
  Shift Adcval , Right , 4

  Getmax1239 = Adcval

End Function










  Sub Max1239_setup


'use internal reference, internal clock, unipolar mode
  I2csend Wrmax1238 , Setmax1238


  End Sub

 
Back to top
View user's profile
albertsm

Administrator



Joined: 09 Apr 2004
Posts: 5922
Location: Holland

blank.gif
PostPosted: Mon Jul 01, 2013 1:34 pm    Post subject: Reply with quote

very nice, thanks for sharing. forgot about that special swap mode Very Happy
_________________
Mark
Back to top
View user's profile Visit poster's website
Paulvk

Bascom Member



Joined: 28 Jul 2006
Posts: 1257
Location: SYDNEY

australia.gif
PostPosted: Tue Dec 04, 2018 12:44 pm    Post subject: Reply with quote

An update!
I have attached the KiCad files to create a board for the MAX1238
But when you look at this board you will see two pads extra
they are pads 1 & 16 at the end and out of sequence maybe a mistake !
but no this board also accepts ADC128D818 another 12bit adc
this IC is rotated to match these pins and the silk screen has ADC128D818 at this end
The J1 input becomes the external reference for the ADC128D818
J10 & J11 set the I2C address on links at R2 & R3 for the ADC128D818

Regards Paul
Back to top
View user's profile
Display posts from previous:   
Post new topic   Reply to topic    www.mcselec.com Forum Index -> BASCOM Project Blog All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You cannot download files in this forum