dusttyler13
Posts: 6
Joined: Fri May 31, 2013 11:31 am

MCP3201 SPI bit bang

Tue Jul 02, 2013 1:09 pm

I am attempting to communicate with an MCP3201 ADC, using a bit bang approach. I have a 10k potentiometer hooked up to the ADC, so I can see the values change as I adjust the potentiometer, but the values I get are very gittery and, while they are close to what the input voltage should be, they are far from exact.
I was wondering if someone could look at my code and let me know if there's anything that I can adjust to give me better values.
Also, I wasn't sure which of the 16 bits collected counted toward the data. If anyone could shed some light on this as well, it would be greatly appreciated.

Code: Select all

import RPi.GPIO as GPIO
from time import sleep

# set up pins
GPIO.setmode(GPIO.BCM)

GPIO.setup(11, GPIO.OUT)
GPIO.setup(9,GPIO.IN)
GPIO.setup(8,GPIO.OUT)

# name pins
clock = 11
miso = 9
cs = 8

# bring clock and cs high
GPIO.output(clock,True)
GPIO.output(cs,True)

# begin loop to print a stream of data
while True:

    # bring cs low
    GPIO.output(cs,False)

    # create a string to store the bits
    data = str()

    # begin loop to take in data
    for i in range(16):

        # bring clock low
        GPIO.output(clock, False)

        # read miso pin
        if GPIO.input(miso):
            data += "1"
        else:
            data += "0"

        # bring clock high
        GPIO.output(clock, True)

    # remove the first 4 bits from the data
    data = data.replace(' ','')[4:15]

    # convert the data from binary to decimal
    data = int(data,2)*(3.3/2045)
    data = str(data)
    
    # print data
    print data

    # bring cs high
    GPIO.output(cs, True)

    sleep(1)

User avatar
pluggy
Posts: 3635
Joined: Thu May 31, 2012 3:52 pm
Location: Barnoldswick, Lancashire,UK
Contact: Website

Re: MCP3201 SPI bit bang

Tue Jul 02, 2013 1:23 pm

In common with many ADCs the MCP3201 uses a reference voltage on an external pin, depending on numerous factors such as the quality of the power supply and how much extra smoothing you've put on the reference pin, it is probably measuring the jitter coming in from your power supply to some extent. If its crucial I'd be putting a scope on whats on the Input and Reference pin of the chip. And see what it's doing in the extreme short term. Failing that I'd stick plenty of extra decoupling around the ADC.
Don't judge Linux by the Pi.......
I must not tread on too many sacred cows......

dusttyler13
Posts: 6
Joined: Fri May 31, 2013 11:31 am

Re: MCP3201 SPI bit bang

Tue Jul 02, 2013 1:27 pm

Ok, thanks. I'm just using the 3v3 from the pi as my power supply, so maybe I'm just getting some noise going on.

dusttyler13
Posts: 6
Joined: Fri May 31, 2013 11:31 am

Re: MCP3201 SPI bit bang

Tue Jul 02, 2013 3:27 pm

Oh! I figured it out. The code should read in 15 bits and then drop the first 3. It works much better now.

dusttyler13
Posts: 6
Joined: Fri May 31, 2013 11:31 am

Re: MCP3201 SPI bit bang

Sun Oct 06, 2013 12:42 am

It's been a while since I worked on this project, but someone asked me to post the code I used to read in data from the ADC. So here it is. I didn't end up using the Pi's SPI pins, opting for a "bit bang" approach instead.

Code: Select all

# begin loop to print stream of data
while True:
    
    # bring cs pin low
    GPIO.output(cs,Fals)
    
    # create a string to store the bits
    data = str()

    # begin loop to take in data
    for i in range(15):
    
        # bring clock low
       GPIO.output(clock,False)

        # read from miso pin
        if GPIO.input(miso):
            data += "1"
        else:
            data += "0"

        # bring clock high
        GPIO.output(clock, True)

# bring cs high
GPIO.output(cs,True)

data = data.replace(' ','')[2:14]
This is just the part of the code to accept data from the ADC.

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Mon May 15, 2017 9:27 am

Thank you very much for your post, this saved me a lot of hassle. I was using the gpiozero-code

Code: Select all

from gpiozero import MCP3201

with MCP3201() as Nummer:
  print("%.2f " % Nummer.value)
and I got completely strange numbers. I was wondering whether the chip is broken and using your code I realized that there must be an error in gpiozero - your code gives me (almost) constant 3.1V whereas with gpiozero I get random numbers between 0 and 1 (and it is supposed to be equal to 3.1/3.3).

Is there a webpage where I can ask for gpiozero-patches? Or maybe I can use gpiozero as random number generator ;-)
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

User avatar
joan
Posts: 14878
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: MCP3201 SPI bit bang

Mon May 15, 2017 9:39 am

andies wrote: ...
whereas with gpiozero I get random numbers between 0 and 1 (and it is supposed to be equal to 3.1/3.3).
...
You are describing correct documented behaviour.

http://gpiozero.readthedocs.io/en/stabl ... erters-adc

The returned ADC value is 0.0 to 1.0. You need to multiply that by the reference voltage (which only you know).

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Mon May 15, 2017 9:43 am

Yes, I know (the voltage is 3.3). The problem is: The above code gives me constantly (around) 3.1 voltage, hence gpiozero should show (around) 0.939. But instead I see values as in the above picture which is inconsistent.
valuesGPIOzero Kopie.jpg
valuesGPIOzero Kopie.jpg (58.28 KiB) Viewed 4322 times
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

Danilk
Posts: 108
Joined: Wed Feb 01, 2017 7:47 pm
Location: Russia, St-Peterburg

Re: MCP3201 SPI bit bang

Mon May 15, 2017 6:33 pm

Code: Select all

import spidev
spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 40000

    def GetADC():
        M0 = 0
        muestras = 0
        while muestras <= 49:
            adc = spi.xfer2([0, 0])
            hi = (adc[0] & 0x1F);
            low = (adc[1] & 0xFC);  # FE for B, FC for C chip (MCP3201-B/C) ©Danil
            dato = (hi << 8) | low;
            M0 += dato
            muestras += 1
        dato = M0 / 50
        V = dato * 2.5 / 8192.0; #2.5 is REF V
        return V
Last edited by Danilk on Tue May 16, 2017 6:21 am, edited 1 time in total.

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Mon May 15, 2017 7:31 pm

Thanks - what is the difference to the above code? Is it better? Why?
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

Danilk
Posts: 108
Joined: Wed Feb 01, 2017 7:47 pm
Location: Russia, St-Peterburg

Re: MCP3201 SPI bit bang

Mon May 15, 2017 7:42 pm

That's my real code of the real device. I'm reading 6 mcp3201 through mux = 6 channels pt100. 40khz freq gives the stable values (also as a result of average of the 50 measurements)

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Tue May 16, 2017 3:04 am

@Danilk, I am not able to run your code. What I am using is

Code: Select all

from time import sleep
import sys
import spidev

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 40000

def GetADC():
        Msum = 0
        s = 0
        while s <= 49:
            adc = spi.xfer2([0, 0])
            hi = (adc[0] & 0x1F);
            low = (adc[1] & 0xFE);  # FE for B, FC for C chip (MCP3201-B/C) Danil
            data = (hi << 8) | low;
            Msum += data
            s += 1
        data2 = float(Msum / 50)
        return data2

try:
    while True:
        sys.stdout.write(str(GetADC()) + ' ')
        sys.stdout.flush()
        sleep(.1)    
except:
    spi.close()
    print ("\nSPI cleanup finished")
and the result is

Code: Select all

pi@heizung:~ $ sudo python3 test2.py
0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 ^C
SPI cleanup finished
pi@heizung:~ $ sudo python test2.py
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ^C
SPI cleanup finished
Do yo have any idea what is going on here? I used FE as well as FC.
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

Danilk
Posts: 108
Joined: Wed Feb 01, 2017 7:47 pm
Location: Russia, St-Peterburg

Re: MCP3201 SPI bit bang

Tue May 16, 2017 4:33 am

I think you made mistake in wiring connections or SPI is not enabled in raspi-config or Vin+ Vin- = 0

i fixed error spidev above. your code is right

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Tue May 16, 2017 4:36 pm

Got it, thanks Danilk! I was running GPIO and they blocked SPI. After a reboot everything was fine.
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

Danilk
Posts: 108
Joined: Wed Feb 01, 2017 7:47 pm
Location: Russia, St-Peterburg

Re: MCP3201 SPI bit bang

Tue May 16, 2017 5:36 pm

and which code did you select for your app?

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Tue May 16, 2017 7:16 pm

I am taking your code. I am still struggling which the best frequency would be. The higher the coarser the data get. 40kHz seems a reasonable choice, if the value is lower it takes too long. I am now running a longer test over night to see which numbers are best.
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

Danilk
Posts: 108
Joined: Wed Feb 01, 2017 7:47 pm
Location: Russia, St-Peterburg

Re: MCP3201 SPI bit bang

Tue May 16, 2017 8:15 pm

40khz is about recommended value from datasheet when VCC is 3.3V
I've made several tests and set average of 50 points and spi freq 40khz.

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Sun May 21, 2017 9:28 am

Danielk: I have a question concering the ADcontroller. I have run (for test purposes) averages over 1 (blue line below) and over 100 iterations (red line below) before reporting the output. You see the differences below and they are striking. My question is: For me, this looks like the MCP is useless unless you do a lot of iterations/averages. But the chip is supposed to deliver a perfect value which it isn't. So, why use a AD in the first pace?! :?:

Code: Select all

spi = spidev.SpiDev()
spi.open(0, 0)
spi.max_speed_hz = 40000
numdata = 1 # <== this is what I changed

def GetADC():
        Msum = 0
        s = 0
        while s < numdata:
            adc = spi.xfer2([0, 0])
            hi = (adc[0] & 0x1F);
            low = (adc[1] & 0xFE);  # FE for B, FC for C chip (MCP3201-B/C) Danil
            data = (hi << 8) | low;
            Msum += int(data)
            s += 1
        return int(Msum/(4*numdata))
...
Attachments
averages Kopie.jpg
averages Kopie.jpg (53.66 KiB) Viewed 4060 times
Last edited by andies on Sun May 21, 2017 9:47 am, edited 2 times in total.
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

Danilk
Posts: 108
Joined: Wed Feb 01, 2017 7:47 pm
Location: Russia, St-Peterburg

Re: MCP3201 SPI bit bang

Sun May 21, 2017 9:42 am

i made pt100 circuit based on Microchip datashit http://ww1.microchip.com/downloads/en/a ... 00687c.pdf

i have unexpected values too: black & yellow lines

now im going to buy industrial module with modbus over 485 to replace my DIY board

Image Image Image
Last edited by Danilk on Sun May 21, 2017 9:52 am, edited 1 time in total.

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Sun May 21, 2017 9:50 am

Danilk wrote:now im going to buy industrial module with modbus over 485 to replace my DIY board
Do you have a link?
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

Danilk
Posts: 108
Joined: Wed Feb 01, 2017 7:47 pm
Location: Russia, St-Peterburg

Re: MCP3201 SPI bit bang

Sun May 21, 2017 9:55 am

Last edited by Danilk on Mon May 22, 2017 7:16 pm, edited 1 time in total.

Danilk
Posts: 108
Joined: Wed Feb 01, 2017 7:47 pm
Location: Russia, St-Peterburg

Re: MCP3201 SPI bit bang

Sun May 21, 2017 10:16 am

smth similar from the chinese brothers
https://ru.aliexpress.com/wholesale?cat ... dbus+pt100
but there is a difference: the russian module can eat any sensors, the chinese module does not

flohwie
Posts: 4
Joined: Sat Jun 10, 2017 7:39 am

Re: MCP3201 SPI bit bang

Sat Jun 10, 2017 7:43 am

I had similar problems with the gpiozero library using the MCP3201. If interested you try out a module I wrote. Has been tested with test cicuits using LDR or potentiometer and seems to work quite nicely. Cheers, Wolfgang
please check out https://github.com/flohwie/raspi-MCP3201

andies
Posts: 141
Joined: Mon Nov 11, 2013 8:12 pm
Location: Berlin

Re: MCP3201 SPI bit bang

Sat Jun 10, 2017 1:34 pm

I had to average the raw results from the microprocessor to get reliable values. Is this necessary with your approach as well? It does not seems so and this would be a great improvement.
raspberry B, Noir camera, Mac Book Air, iPhone, Bezzera

flohwie
Posts: 4
Joined: Sat Jun 10, 2017 7:39 am

Re: MCP3201 SPI bit bang

Sat Jun 10, 2017 1:45 pm

No averaging needed as the ADC data seem to be very stable and reliable (as long as the minimum wait time of 100 ms between single reads is maintained). Depending on your application, averaging over a time span might be a good idea, though. I wrote the code just for learning, and I think it could be improved / shortened.

Return to “General discussion”