ozone 2 click

Discuss with MikroElektronika software developers about current library development.
Post Reply
Author
Message
arott
Posts: 2
Joined: 15 Jun 2020 05:07

ozone 2 click

#1 Post by arott » 15 Jun 2020 05:18

Hello, looking for a way to read the measured values off the ozone sensor board using Pi 3 click shield and the ozone 2 click board on a raspberry pi 3.

Do you have e.g. python code or C headers/libraries for configuring and communication using SPI?

Thank you

User avatar
filip.grujcic
Posts: 822
Joined: 14 May 2018 08:34

Re: ozone 2 click

#2 Post by filip.grujcic » 15 Jun 2020 11:17

Hello,

We do not officially provide examples or libraries for Raspberry Pi, as it is not a Mikroe product.
If you would like us to provide you with a source code of our library for Ozone 2 Click board which you could try porting over to RPi, please submit a ticket on our helpdesk: https://www.mikroe.com/support

Kind regards,
Filip Grujcic

arott
Posts: 2
Joined: 15 Jun 2020 05:07

Re: ozone 2 click

#3 Post by arott » 21 Jun 2020 15:04

For those who might be looking for some starting point - reading of the mcp3551:

Code: Select all

$ cat mcp3551.py
#!/usr/bin/python3
#
import spidev
import time

class MCP3551:
        def __init__(self, spi_channel=0, spi_ce=0, speed_hz=1000000, spi_mode=0b00):
                self.conn = spidev.SpiDev()
                self.conn.open(spi_channel, spi_ce)
                self.max_speed_hz = speed_hz
                self.conn.max_speed_hz = speed_hz
                self.spi_mode = spi_mode
                self.conn.mode = spi_mode

        def __del__( self ):
                self.close

        def close(self):
                if self.conn != None:
                        self.conn.close
                        self.conn = None
        
        def read(self, adc_channel=0):
            count_safeguard = 0
            COUNT_SAFEGUARD_LIMIT = 10000
            while True:
                count_safeguard = count_safeguard + 1
                if (count_safeguard > COUNT_SAFEGUARD_LIMIT):
                    return -1
                res = 0
                if self.spi_mode == 0b00:
                    # In SPI mode 0,0, data is read using 25 clocks or four
                    #byte transfers. Please note that the data ready bit is
                    #included in the transfer as the first bit in this mode.
                    reply_bytes = self.conn.readbytes(4)
                    #print(reply_bytes)
                    # see http://ww1.microchip.com/downloads/en/DeviceDoc/20001950F.pdf, Figure 5-7
                    if (reply_bytes[0] < 0b1000000): # Ready bit present - good read
                        res = (reply_bytes[0] << 17) + (reply_bytes[1] << 9) + (reply_bytes[2] << 1) + (reply_bytes[3] >> 7)
                        return res
                else: #self.spi_mode == 0b11
                    # See Figure 5-6
                    #
                    reply_bytes = self.conn.readbytes(3)
                    #print(reply_bytes)
                    if (reply_bytes[0] < 0b11000000):
                        # good read
                        res = (reply_bytes[0] << 16) + (reply_bytes[1] << 8) + (reply_bytes[2] << 0)
                        return res

if __name__ == '__main__':
        spi = MCP3551(0, 0)
        a0 = spi.read()
        print("%04d" % a0)
Reading ADC mcp3204/3208 on MikroE Pi 3 Shield: see https://pypi.org/project/mcp3208/

Reading O3 sensor and calculating Rs:

Code: Select all

$ cat O3Sens.py
#!/usr/bin/python3
# Reading sensor data
# MikroE Ozone 2 sensor with MQ131 gas sensor
# and MCP3551 22-bit ADC
#
import mcp3551
import mcp3208
import time

SAMPLE_PERIOD=10 # seconds

# On the MikroE O3 sensor, Vin- is GND and delta measured is always positive,
# 0..Vdd
maxADCValue = 0x1FFFFF # MCP3551 doc, figure 5-1

# Initialize mcp3551 spi communication
SPI = 0         # MikroE click boards are on SPI0
SPI_CS = 0      # Pi 3 Shield from MikroE, slot 1
# SPI_CS = 1    # Pi 3 Shield from MikroE, slot 2
sensor = mcp3551.MCP3551(SPI, SPI_CS)

# microchip Pi 3 shield on board adc
# 100000 hz is sufficient
PI3SHIELD_ADC_SPI_CH = 1
PI3SHIELD_ADC_CE = 2
PI3SHIELD_ADC_CLK_HZ = 100000 # 100 kHz
pi3shieldadc = mcp3208.MCP3208(PI3SHIELD_ADC_SPI_CH, PI3SHIELD_ADC_CE, PI3SHIELD_ADC_CLK_HZ)
Vcc = 5        # 5V nominal
# Actual Vref can be measured on the board between Gnd and +5V
# Alternatively, another ADC can be used to read real-time like in the example
# below

# Rl - MikroE O3 sensor has a potentiometer. Rl has to be
# adjusted and measured using an ohm meter, then entered here.
# Rl on the board comprises VR1 and R2, measurement needs to
# be performed from MQ131 B to GND
Rl = 5100 # Ohms

def SampleVcc():
    count = 0
    sample_size = 10
    v_1_2 = 0 # half of the measurement
    # range of the onboard ADC can't go over 4.096V so use two divider resistors
    # and AN2 of the slot 2 of the MikroE Pi 3 Shield (empty slot)
    while True:
            count += 1
            #AN1_adc_chan = 0
            AN2_adc_chan = 1
            v_1_2 += pi3shieldadc.read(AN2_adc_chan)
            if count == sample_size:
                count = 0
                return 2 * v_1_2 / sample_size / 1000.0

Rs_running_avg = 0
n_iters = 0
sample_start_time = time.time()
while True:
    if n_iters == 0:
        sample_start_time = time.time()
        print("Sampling for {} seconds...".format(SAMPLE_PERIOD))
    value = sensor.read()
    if value < 0:
        print("Error reading ADC")
        continue
    Vref = SampleVcc()
    Vrl = (Vref * value) / maxADCValue
    #print("Raw ADC reading: {}".format(value))
    Rs = (Vref / Vrl - 1) * Rl # Rs - sensor resistance
    n_iters = n_iters + 1
    Rs_running_avg = (Rs_running_avg * (n_iters - 1) + Rs) / n_iters
    if int(time.time() - sample_start_time) >= SAMPLE_PERIOD:
        Rs = Rs_running_avg
        Rs_running_avg = 0
        n_iters = 0
        print("Sensor reading: Vrl={:.4f}[V] Rs={:.4f}[Ohm] Vref={:.4f}[V] R_L={}[Ohm]".format(Vrl, Rs, Vref, Rl))

Sample output:

Code: Select all

$ ./O3Sens.py
Sampling for 10 seconds...
Sensor reading: Vrl=4.4436[V] Rs=392.7957[Ohm] Vref=4.7836[V] R_L=5100[Ohm]
Sampling for 10 seconds...
Sensor reading: Vrl=4.4385[V] Rs=388.7485[Ohm] Vref=4.7758[V] R_L=5100[Ohm]

Remaining questions I have not figured out yet: how to actually correlate the readings with actual O3 ppm without having a reference of 50ppm of CL2 (as per the MQ131 doc).

Post Reply

Return to “Library Development Discussion”