Picomite issues with MCP3002, dual channel ADC SPI


Author Message
karlelch

Senior Member

Joined: 30/10/2014
Location: Germany
Posts: 218
Posted: 11:35am 01 Feb 2025      

Hi

not sure if it helps. I wrote a library for the MCP3208 (SPI, 12 bit, 8 channel), using the respective Arduino C(++) code as an example.

' lib_mcp3208.bas v0.1.2
' -----------------------
' MCP3208 8-channel ADC driver
' 2024-02-04 - v0.1.1 - No constants to save global variable slots
' 2024-11-25 - v0.1.2 - Test routine added
' Example:
'   Const PIN_SPI2_RX      = MM.Info(PinNo GP12)
'   Const PIN_SPI2_TX      = MM.Info(PinNo GP11)
'   Const PIN_SPI2_CLK     = MM.Info(PinNo GP10)
'   Const PIN_MCP3208_CS   = MM.Info(PinNo GP13)
'   MCP3208.init PIN_SPI2_RX, PIN_SPI2_TX, PIN_SPI2_CLK, PIN_MCP3208_CS
'   Dim v(3)
'   MCP3208.readADCChans 4, v()
'   Math V_print v()
'   MCP3208.close
' ---------------------------------------------------------------------------
Option Base 0
Option Explicit
Option Escape
Option Default Float

Dim integer MCP3208.cs = MM.Info(PinNo GP13)

' ===========================================================================
' MCP3208 8-channel ADC driver
' ---------------------------------------------------------------------------
Sub MCP3208.init rx%, tx%, clk%, cs%
 ' Setup user SPI2
 Print "Initializing MCP3208 via SPI2 ..."
 SetPin rx%, tx%, clk%, SPI2
 SetPin MCP3208.cs, DOUT
 Pin(MCP3208.cs) = 0
 Pause 50
 Pin(MCP3208.cs) = 1
 SPI2 Open 1000000, 0, 8 ' 1MHz, mode 0, 8 bits
 Print "| Ready."
End Sub

Function MCP3208.readADC(ch%)
 ' Read channel `ch%`
 Local integer val, addr = &H60 Or ((ch% And &H07) << 2)
 Pin(MCP3208.cs) = 0
 SPI2 Write 1, addr
 val = SPI2(0) << 4
 val = val Or (SPI2(0) >> 4)
 Pin(MCP3208.cs) = 1
 MCP3208.readADC = val
End Function

Sub MCP3208.readADCChans n%, dta%()
 ' Read channels 0 to `n%`-1 into `dta%()`
 Local integer i, addr
 For i=0 To n%-1
   addr = &H60 Or ((i And &H07) << 2)
   Pin(MCP3208.cs) = 0
   SPI2 Write 1, addr
   dta%(i) = SPI2(0) << 4
   dta%(i) = dta%(i) Or (SPI2(0) >> 4)
   Pin(MCP3208.cs) = 1
 Next
End Sub

Sub MCP3208.close
 ' Close SPI2 devices
 SPI2 Close
 SetPin MCP3208.cs, OFF
End Sub

' ---------------------------------------------------------------------------
Sub MCP3208.test
 Local integer rx, tx, clk, cs, i, j
 Local integer v(7)
 rx  = MM.Info(PinNo GP12)
 tx  = MM.Info(PinNo GP11)
 clk = MM.Info(PinNo GP10)
 cs  = MM.Info(PinNo GP13)

 Print "Test is using SPI1 with:"
 Print "  VSYS -> VDD, VREF"
 Print "  GND  -> AGND, DGND"
 Print "  GP10 -> CLK"
 Print "  GP11 -> DIN"
 Print "  GP12 -> DOUT"
 Print "  GP13 -> CS/SHDN"
 Print

 MCP3208.init rx, tx, clk, cs
 For i=0 To 50
   /*
   For j=0 To 7
     v(j) = MCP3208.readADC(j)
   Next
   */
   MCP3208.readADCChans 7, v()
   Math V_print v()
   Pause 500
 Next
 MCP3208.close
End Sub


It is mean to be loaded as a library, but it comes with a simple test.
Here, I am varying the voltage on channel 0 (left most value) from 0V to 5V and back to 0V using a potentiometer.
> mcp3208.test
Test is using SPI1 with:
 VSYS -> VDD, VREF
 GND  -> AGND, DGND
 GP10 -> CLK
 GP11 -> DIN
 GP12 -> DOUT
 GP13 -> CS/SHDN

Initializing MCP3208 via SPI2 ...
| Ready.
4, 0, 0, 0, 0, 0, 0, 0
4, 0, 0, 7, 22, 31, 69, 0
3, 60, 61, 71, 89, 107, 178, 0
90, 149, 141, 191, 242, 322, 506, 0
970, 542, 481, 532, 588, 676, 823, 0
1452, 804, 794, 832, 847, 874, 885, 0
2186, 935, 888, 858, 832, 839, 854, 0
4063, 960, 881, 807, 810, 790, 765, 0
4095, 887, 839, 764, 730, 703, 667, 0
2050, 790, 763, 693, 662, 624, 552, 0
1432, 611, 540, 431, 370, 275, 131, 0
972, 253, 202, 91, 48, 0, 0, 0
371, 25, 14, 0, 0, 0, 0, 0
4, 0, 0, 0, 0, 0, 0, 0
4, 0, 0, 8, 22, 21, 73, 0
3, 66, 59, 69, 94, 118, 190, 0
>

Cheers
Thomas
Edited 2025-02-01 21:36 by karlelch