I am trying to read data via SPI from an ozone sensor that I have connected to the Raspberry Pi's GPIO. This set up uses a Mikro Pi click shield and Mikro Ozone 2 click sensor. The output of the sensor is analog, so an ADC has been included.

The ADC model is the single-channel, 22-bit MCP3551, which does not appear to be that common. I have written the below python code using this example, which thankfully works and reads the data from the ADC via SPI in 3-byte 'chunks'. This appears to be the only example on the internet in python for this ADC.

import spidev
import time

spi = spidev.SpiDev()
spi.open(0, 0)
spi.mode = 0b11
#spi.max_speed_hz = 1000000
    while True:
        resp = spi.readbytes(3)
        if (resp[0] != 255):
            #value = 256*resp[0] + resp[1]
            value = resp[1] + resp[2]
            byte1 = bin(resp[0])[2:].rjust(8,'0')
            byte2 = bin(resp[1])[2:].rjust(8,'0')
            byte3 = bin(resp[2])[2:].rjust(8,'0')
            bits = byte1 + byte2 + byte3
except KeyboardInterrupt:

The bits variable is a concatenation of the three bytes, so that I can see the 24 bits in a row. However, looking at the MCP3551 data sheet, I cannot work out how to interpret these bits and get a value (ideally a voltage). It seems the three bytes make up a 22-bit reading with 2 overflow bits.

Here is the data sheet for the ozone sensor, if that helps at all. This other question on the Raspberry Pi forums may be helpful, but is for a different 8-channel ADC.

I've tried to provide all the information I can, but I am a beginner in this area so apologies if I have missed anything. Any help would be much appreciated. Thanks!

Edit - the three bytes received are shown below in the square brackets:

[1, 3, 252]

[1, 3, 3]

[1, 3, 10]

[1, 3, 16]

[1, 3, 23]

[1, 3, 28]

  • Please add the bytes you send and the bytes you receive (over SPI). – joan Jun 21 '18 at 13:30
  • I've added the bytes received @joan. I don't think I am sending any bytes at the moment (?), unless I'm being naive. – the_butler Jun 21 '18 at 13:51
  • @joan I have also tried the code you provided to KeithSloan (first link of my post) that uses pigpio. That code works, in case you would prefer to answer in terms of your library. – the_butler Jun 21 '18 at 14:23
# provided the measurement is in range, so the overflow bits are irrelevant
# bitshift the bytes and add them
counts = (resp[0] << 16) + (resp[1] << 8) + resp[2]

# now decode the data from the 2's complement format
if counts > 2**21: # the number is actually negative
    counts = 2**21 - counts

# now convert to voltage
Vref = 5.0 # change this if it's not 5 volt reference
volts = Vref * counts / 2**21
| improve this answer | |
  • As a side note, the site has a bot marking code-only answers as "low quality". And that bot is not smart enough to see that you have formatted the explanations as comments inside the code block. – Dmitry Grigoryev Nov 20 '19 at 8:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.