1. Home
  2. Docs
  3. Device Kits
  4. Kit 1: Gadget, ADCs, and Python Oh My!

Kit 1: Gadget, ADCs, and Python Oh My!

This device kit seeks to display how simple Gadget can make IoT projects and is intended for a Raspberry Pi. In this tutorial, we’ll use the Python (3) programming language and we’re going to get friendly with the subprocess module in order to drive (or control) Gadget. We’ll also learn how to hook up an ADC (analog-to-digital converter) to an arbitrary sensor with an analog output and a Raspberry Pi. The ADC we’ll be using is the MCP3008-I/P. We should note that the MCP3008-I/P uses SPI for communication to its controller (in our case a Raspberry Pi). The last piece of information we’ll need before getting started is that we’ll be using another Python module for ease of access to the Raspberry Pi’s peripherals (in our case, SPI): gpiozero. The gpiozero module is the recommended Python module for controlling the Raspberry Pi’s peripherals.

Components

(1) From the CLI, run sudo raspi-config and enable SPI via Interfacing Options > P4 SPI > Yes. Next, reboot: sudo reboot. Finally, verify /dev/spidev0.0 is present in the filesystem. If you run into any issues, please visit this page for help troubleshooting.

(2) If you need help flashing an SD card with a Raspbian image, please visit here.

(3) To install the Python module gpiozero, you’ll first want to make sure your repository list is up to date by running sudo apt update. Second, install the module for Python (3) using the following command: sudo apt install python3-gpiozero. If you run into any issues, please visit here for help troubleshooting.

Hardware Setup

First, let’s wire up our MCP3008. Following is the pinout for the MCP3008, obtained here, and the associated Raspberry Pi (PX) and analog sensor (AX) pin connections: alt text NOTE: The Raspberry Pi pin connections are from the Raspberry Pi 40 pinout header (Not the physical Broadcom connections). This link contains a great representation of the Raspberry Pi 40 pinout header and the associated Broadcom connections.

The analog sensor connections are (usually) simple and can be determined via the sensor’s datasheet. For the soil humidity sensor I’m using: connect P0 (3V3) and P6 (GND) to the specified (+) and (-) pins respectively and connect the analog out to A0 of the MCP3008.

Software Setup

The script:

import subprocess

from time import sleep
from gpiozero import MCP3008, DigitalOutputDevice

def get_soil_moisture():
    # gpiozero has a MCP3008 implementation that
    # has SPI under the hood
    adc = MCP3008(channel=0)
    sleep(.1)

    r_val = adc.value
    adc.close()

    # Values determined through sensor
    # calibration and through usage of the
    # equation of a line
    r_val = 100.0 * (-1.33 * r_val + 1.33)

    return r_val

# Use your own Avimesa credentials here
gadget_args = ['avmsagadget',
               '-i',
               'DEADBEEFDEADBEEFDEADBEEFDEADBEEF',
               'DEADBEEFDEADBEEFDEADBEEFDEADBEEF']

# Wrap Gadget using Popen class
gadget = subprocess.Popen(gadget_args,
                          stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE)

# Let's use Gadget's AUTORUN feature
# to automatically send sensor data
gadget.stdin.write(b'set AUTORUN = 1\n')
gadget.stdin.flush()

# GPIO17 for momentary sensor power.
# Slow degradation to soil moisture
# sensor
sensor_power = DigitalOutputDevice(17)

while True:
    try:
        # Only apply power to soil moisture sensor
        # whenever we take a reading
        sensor_power.on()
        sleep(.001)

        # A little gross, JSON to inject with sensor
        # reading
        reading = ('{{"chans":[{{"ch_idx":0,"ch_data":['
                   '{{"data_idx":0,"units":1,"val":{0}}}]}}]}}'
                   '\n'.format(get_soil_moisture()))

        # Turn string into binary
        reading = reading.encode()

        # Write command to STDIN
        gadget.stdin.write(reading)
        gadget.stdin.flush()

        sensor_power.off()
        sleep(5)
    except KeyboardInterrupt:
        # Trick to send EOF to STDIN
        # in order to close Gadget
        gadget.stdin.close()
        gadget.wait()
        print('Gadget exited with rc {0}'.format(gadget.returncode))
        break
Avimesa.Live Integration

If you have an active Avimesa.Live account, you can add your sensor there and get some output like this: alt text NOTE: The spike in the graph here is me pouring water into the soil near the soil humidity sensor.