This article is based in this very good one

I added some comments, examples, circuits and Zabbix configuration.

The main goal is having a common interface to read analog values and generate graphs, alarms, actions etc. with Zabbix.

Analog Sensors Reading with Raspberry Pi as Interface

The Raspberry Pi has no built in analogue inputs which means it is a bit of a pain to use many of the available sensors. We need a A/D interface easy to configure in the RPi and the MCP3008 is the answer.

The MCP3008 is a 10bit 8-channel Analogue-to-digital converter (ADC). It is cheap, easy to connect and doesn’t require any additional components. It uses the SPI bus protocol which is supported by the Pi’s GPIO header.

This article explains how to use an MCP3008 device to provide 8 analogue inputs which you can use with a range of sensors. In the example circuit below I use a MCP3008 to read a light sensor and control/supervise the light inside Zabbix.

The hardware:

  • Raspberry Pi
  • MCP3008 8 channel ADC
  • Light dependent resistor (LDR)
  • 10 Kohm resistor
  • Breadboard
  • Some wiring

SPI Bus

The MCP3008 read the analog value and give a 10 bits number that is transmitted by the SPI Bus. SPI

The Serial Peripheral Interface bus or SPI bus is a synchronous serial data link standard, that operates in full duplex mode.

Devices communicate in master/slave mode where the master device initiates the data frame. Multiple slave devices are allowed with individual slave select lines.

Sometimes SPI is called a four-wire serial bus, contrasting with three-, two-, and one-wire serial buses. SPI is often referred to as SSI (Synchronous Serial Interface).

To enable hardware SPI on the RPi we need to make a modification to one of the system files:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

Add a ‘#’ character in front of the line spi-bcm2708. Use CTRL-X, then Y, then Return to save the file and exit. Reboot using the following :

sudo reboot

To check the change has worked run the following command :

lsmod

You should see “spi_bcm2708″ listed in the output.

Install Python SPI Wrapper

In this project we are going to use Python and In order to read data from the SPI bus in Python we can install a library called ‘py-spidev’. To install it we first need to install ‘python-dev’ :

sudo apt-get install python-dev

Then to finish we can download ‘py-spidev’ and compile it ready for use :

mkdir py-spidev
cd py-spidev
wget https://raw.github.com/doceme/py-spidev/master/setup.py
wget https://raw.github.com/doceme/py-spidev/master/spidev_module.c
sudo python setup.py install

Circuit

The following list shows how the MCP3008 can be connected. It requires 4 GPIO pins on the Pi P1 Header.mcp3008

MCP3008 RPi
VDD 3.3V
VREF 3.3V
AGND GROUND
CLK GPIO11 (P1-23)
DOUT GPIO9 (P1-21)
DIN GPIO10 (P1-19)
CS GPIO8 (P1-24)
DGND GROUND

The CH0-CH7 pins are the 8 analogue inputs.

Next we can see the schematic of the circuit:

ssm-light_schem.png

Here is the breadboard circuit :

SSM-Light_bb

It uses CH0 for the light sensor. The other 7 inputs are spare.

Here is a photo of my test circuit on a small piece of breadboard:

SSM-Light_photo

Light Dependent Resistor

I chose a LDR EG & G Vactec, VT43, CdS, 8 Ω to 300 KΩ. Under normal lighting its resistance is approximately 10Kohm while in the dark this increases to over 2Mohm.ldr_example

When there is lots of light the LDR has a low resistance resulting in the output voltage dropping towards 0V.

When it is dark the LDR resistance increases resulting in the output voltage increasing towards 3.3V. In this project has been used a LDR but whatever device changing his resistance depending of some phenomenon can be used and wired in the IC to be controlled.

Reading The Data

The ADC is 10bit so it can report a range of numbers from 0 to 1023 (2 to the power of 10). A reading of 0 means the input is 0V and a reading of 1023 means the input is 3.3V. Our 0-3.3V range would equate to a 0-10000 Lux range.

To read the data I used this Python script get_light.py:

#!/usr/bin/python

import spidev
import time
import os

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)

# Function to read SPI data from MCP3008 chip
# Channel must be an integer 0-7

def ReadChannel(channel):
  adc = spi.xfer2([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  return data

# Function to convert data to voltage level,
# rounded to specified number of decimal places.

def ConvertVolts(data,places):
  volts = (data * 3.3) / 1023
  volts = round(volts,places)
  return volts

# Define sensor channels
light_channel = 0

# Define delay between readings
delay = 1

while True:
  # Read the light sensor data
  light_level = 1024 - ReadChannel(light_channel)
  light_volts = ConvertVolts(light_level,2)

  # Print out results
  print "--------------------------------------------"
  print("Light: {} ({}V)".format(light_level,light_volts))

  # Wait before repeating loop
  time.sleep(delay)

The output with normal light is:

pi@pi-access-lab ~ $ ./get_light.py
--------------------------------------------
Light: 904 (2.92V)
--------------------------------------------
Light: 895 (2.89V)
--------------------------------------------
Light: 903 (2.91V)
--------------------------------------------
Light: 895 (2.89V)
--------------------------------------------
Light: 904 (2.92V)
--------------------------------------------
Light: 906 (2.92V)
--------------------------------------------
Light: 896 (2.89V)
--------------------------------------------
Light: 887 (2.86V)
--------------------------------------------
Light: 894 (2.88V)
--------------------------------------------
Light: 906 (2.92V)
--------------------------------------------

ZABBIX Integration

Zabbix Agent

The Zabbix Agent must be installed in the RPi in order to receive the requests from the server and send the value read. Install the agent with:

sudo apt-get update && sudo apt-get install zabbix-agent

The script written in Python has to be modified a bit. we want to have 100% light for the maximum light and 0% for the minimum.

SSM Server request light to RPi → Zabbix Agent send only the percent as a number.

Here is the python code modified:

#!/usr/bin/python

import spidev
import time
import os

# Open SPI bus
spi = spidev.SpiDev()
spi.open(0,0)

# Function to read SPI data from MCP3008 chip
# Channel must be an integer 0-7
def ReadChannel(channel):
  adc = spi.xfer2([1,(8+channel)<<4,0])
  data = ((adc[1]&3) << 8) + adc[2]
  return data

# Function to convert data to voltage level,
# rounded to specified number of decimal places.
def ConvertVolts(data,places):
  volts = (data * 3.3) / 1023
  volts = round(volts,places)
  return volts

# Define sensor channels
light_channel = 0

# Read the light sensor data
light_level = (1024 - ReadChannel(light_channel)) / 10.24
light_volts = ConvertVolts(light_level,2)

# Print out results
print("{:.3}".format(light_level))

The output with normal light is:

pi@pi-access-lab ~ $ ./ssm_get.py
88.4

The zabbix_agent must be configured as usual with the Zabbix Server server etc, and add the command lines at the end of the configuration file. When the server request light the agent must know what to do. That is done editing the file:

/etc/zabbix/zabbix_agentd.conf

and adding:


### Option: UserParameter

# User-defined parameter to monitor. There can be several user-defined parameters.
# Format: UserParameter=,
# Note that shell command must not return empty string or EOL only.
# See 'zabbix_agentd' directory for examples.
#
# Mandatory: no
# Default:

UserParameter=light,sudo /home/pi/ssm_get.py

Another important hack is that the user running the zabbix_agent (in my case zabbix) must have the rights to execute the command as root since we are accessing to the SPI port of the RPi. If we want to avoid writing the passwords in the scripts we can authorise the user zabbix in the sudoers file only for the command or in my case more general:

/etc/sudoers
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
pi ALL=(ALL) NOPASSWD: ALL
zabbix ALL=(ALL) NOPASSWD: ALL

Zabbix Server

To check the installation before adding the host and checks in the server we can run in the Zabbix Server:

[root@ssm ~]# zabbix_get -s pi-access-lab -k light
87.5

If that works and return the value, we can add the RPi in the Zabbix Server and create an item called light or whatever we want and associate an external check:

SSM_1.1_Configuration_of_items_-_2014-01-13_11.52.22
We can create screens for the data, graphs or whatever we need. Refer to the Zabbix documentation to do it. The result after 2 or 3 days getting data in my desk is:
SSM_1.1_Custom_graphs_[refreshed_every_30_sec]_-_2014-01-13_11.57.21

Advertisements