User Tools

Site Tools


No ai soldati italiani all'estero




Rigacci.Org usa energia elettrica da fonti rinnovabili, grazie al gruppo di acquisto Merci Dolci.

Merci Dolci - Energia Rinnovabile

Software libero!

Petizione contro i brevetti software

Faunalia: Soluzioni GIS professionali


Altre libertà

MoVimento 5 Stelle Campi Bisenzio


Raspberry Pi Explorer Kit

In this page I will tell you about some experiments that I made with the Aerocene Explorarion Tools. I got an exploration kit consisting of the following parts:

  • The Raspberry Pi 2 Model B
  • One solar panel with litium-ion polymer battery (5000 mAh)
  • One Adafruit Ultimate GPS HAT for the Raspberry Pi
  • One Miuzei Raspberry Pi camera module (OV5647 sensor, 2592×1944 = 5 Mpixels)
  • One LogiLink USB WiFi dongle
  • Two BME280 pressure/temperature/humidity sensor
  • One Plantower PMS5003 particulate matter sensor
  • One USB-to-serial adapter

Here it is a photo of the prototype assembled into a plastic case:

Connecting the Hardware

Adafruit GPS unit

The Adafruit GPS unit communicates with the Raspberry Pi using the serial interface which is available on PIN 8 and PIN 10 of the Raspberry Pi, marked as GPIO14/UART0_TXD and GPIO15/UART0_RXD on many pinout schemes. The standrad Raspbian configuration allocate the serial line for a console (boot messages and login prompt), so a special configuration is required to free the serial line. The raspi-config tool will be used for this.

BME280 sensors

The BME280 sensors are mounted on small breakout modules, which provide the I2C and the power interface. The I2C bus is available on the Raspberry Pi at PIN 3 and PIN 5 marked as GPIO2/SDA1 and GPIO3/SCL1. We have to connect also a ground PIN and a power PIN. The breakouts we used are capable to use both 3.3 or 5.0 volt power available from the Raspberry Pi connector. To connect two sensors at the same time, they must use different I2C addresses, to change the default address 0x76 to the alternative 0x77 it is required to cut and solder a track on the breakouts circuit itself.

PMS5003 sensors

The Plantower PMS5003 particulate matter sensor has a serial interface and requires a 5 volt power. If the serial port of the Raspberry Pi is already taken by the GPS module, we have to provide anoter serial interface via an USB adapter. There are several cheap USB to serial adapter, which also provide a pin for the 5 volt power.

USB to serial adapter

As said above, we required this adapter to connect the PMS5003 sensor. The one we used is based on a Prolific Technology PL2303 chip (USB id 067b:2303), which is automatically detected by the Linux kernel and exposed as the /dev/ttyUSB0 serial device.

WiFi dongle

The WiFi connection is provided by a simple adapter based on the Ralink RT5370 chip (USB id 148f:5370). To operate the adapter we need the rt2870.bin firmware (non-free), which is shipped into the firmware-misc-nonfree package. The package is already installed into the default Raspbian Stretch Lite distribution.

Raspberry Pi Camera Module

Image captured by the OV5647 camera The camera mounted in our kit is based on the OV5647 sensor, capable of 2592×1944 pixels (5 Mpixels). The camera has a wide viewing angle of 175°. The camera requires a manual focus adjust, turning the lens mount clockwise or counerclockwise. The focus resulted a bit critical: trying to focus to infinity it resulted that the mere rotation of 1/16 of a turn, can mess-out the focus very badly. Also the quality of the pictures is not exceptional, they miss the crisp level that we would expect from a 5 Mpixels sensor.

Software Setup

We used a GNU/Linux box to download the software and to prepare the micro SD for the Raspberry Pi.

Installing the Raspbian Distribution

Download the Raspbian Stretch Lite 2018-06-27 distribution from Unzip and copy the file to the micro SD:

dd bs=4M if=2018-06-27-raspbian-stretch-lite.img of=/dev/sdc conv=fsync

To enable ssh and WiFi at the first Raspberry Pi bootstrap, we created two files into the first FAT partition of the micro SD. The first file must be named ssh and can be empty, the second file must be named wpa_supplicant.conf and should contain the credential to access your WiFi network:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev

Those files will be seend by the bootstrap procedure and will configure the ssh and WiFi services.


We used the raspi-config tool, which customizes several system configuration files and re-configure some installed packages. Once logged into the Raspberry via ssh, we gained root privileges with sudo su - and launched raspi-config, then we configured the following options:

  • Localisation Options
    • Change Locale
      • en_US.UTF-8
      • it_IT.UTF-8
    • Change Timezone
      • Europe/Rome
  • Interfacing Options
    • Camera (Yes)
    • I2C (Yes)
    • Serial
      • Login shell over serial (No)
      • Serial port hardware enabled (Yes)

The files changed by that configuration are (among others):

  • /boot/config.txt
  • /boot/cmdline.txt
  • /etc/timezone

Adding Extra Packages

To operate the hardware devices and to run our software, we need some extra packages, available from the Raspbian distribution. From the command line, using the root privileges, run:

apt-get update
apt-get upgrade
apt-get install git i2c-tools python-dev python-setuptools python-spidev
apt-get install gpsd gpsd-clients python-gps pps-tools
apt-get install busybox-syslogd

Other required software is not included into the official Raspbian distribution, so we will download (and install) from a GitHub respository:

cd /usr/local/src/
git clone
cd Adafruit_Python_GPIO
python install

This procedure will download and install the Adafruit_Python_GPIO library and the pre-required Adafruit_PureIO library. The destination directory of the installation is /usr/local/lib/python2.7/dist-packages/.

Beware to install setuptools and spidev from the official Raspbian packages before this setup procedure, otherwise the procedure will try to download and install those libraries from extra respositories, possibly messing the things a bit.

Hardware Setup and Test

Adafruit GPS

Run the dmesg command and verify that the kernel detected the serial device /dev/ttyAMA0 (this is for the Raspberry Pi 2 models). Edit the /etc/default/gpsd file and set:


restart the gpsd service:

systemctl restart gpsd.service

Notice that recent implementations of gpsd (as the one provided by the Raspbian Stretch distro) do not start the gpsd daemon automatically at bootstrap. Instead they start an Unix socket (/var/run/gpsd.sock) and listen there for incoming client connections. Beside that, they terminate the gpsd instance if no clients are connected for some time.

We need instead an ever-running gpsd, because it will provide precise clock information via shared memory to the ntpd daemon. For this purpose the -n option will prevent gpsd to terminate if no clients are connected. We need also to launch a client at least for a short time to fire-up the gpsd instance, e.g. adding this single line in /etc/rc.local:

# Start a gpsd client for a short time, so that gpsd will be started.
gpspipe -r -n 5 > /dev/null 2>&1 &

Now you can verify that the GPS is running and providing position data (place the device in open sky view, it does not work in a closed room!):

gpspipe -r -n 10

gpxlogger bug

I use gpxlogger (from the gpsd-clients Debian package) to acquire track logs from the GPS. It seems that the program has a bug handling the -f option, sometimes it crashes with the error free(): invalid next size (fast). I opened bug #909082 on Debian. Changing the file name to be created, is a workaround for this problem.

Time Syncronization with GPS and NTP

The gpsd daemon provides time syncronization data via shared memory, and the ntpd daemon is able to read that information and adjust system time. This is very important because the Raspberry Pi does not have a RTC (realtime clock), so it does not have the correct system time at bootstrap. The ntpd can get time from the network and/or from gpsd, just edit the /etc/ntp.conf file and add the following, after the pool information:

# GPS Serial data reference (NTP0)
fudge refid GPS

The magic pseudo-IP address is not a real IP address, it identifies the ntpd shared-memory driver connected to the serial data given by gpsd.

You can verify that shared memory information are available for NTP, using ntpshmmon:

#      Name   Seen@                Clock                Real               L Prec
sample NTP0 1536230152.827339676 1536230152.627168673 1536230152.000000000 0  -1
sample NTP0 1536230153.638095698 1536230153.637403780 1536230153.000000000 0  -1

GPS time is very accurate, but serial communication from GPS device and gpsd is not. A means to get a more precise timing is activating a PPS (Pulse per second) signal. The Adafruit GPS HAT can provide PPS on GPIO 4 and the Linux kernel must be instructed to read that signal, add the following line at the end of /boot/config.txt file:

# Enable GPS PPS (Pulse Per Second) kernel device, drived by GPIO#14.

At the next reboot you should read the following kernel logs via dmesg:

pps_core: LinuxPPS API ver. 1 registered
pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <>
pps pps0: new PPS source pps@4.-1
pps pps0: Registered IRQ 169 as PPS source
pps_ldisc: PPS line discipline registered
pps pps1: new PPS source ttyAMA0
pps pps1: source "/dev/ttyAMA0" added

the important part is pps0: new PPS source pps@4 stating that a /dev/pps0 device is created, exposing the PPS signal from GPIO#4. When the GPS has a fix, we can check that the PPS source is working with ppstest (from the pps-tools package):

ppstest /dev/pps0
trying PPS source "/dev/pps0"
found PPS source "/dev/pps0"
ok, found 1 source(s), now start fetching data...
source 0 - assert 1537517136.001471057, sequence: 787 - clear  0.000000000, sequence: 0
source 0 - assert 1537517137.001467380, sequence: 788 - clear  0.000000000, sequence: 0

We can see one PPS signal per second, as expected. Now we need to instruct gpsd to get data from that device too, not only from the serial line. Edit /etc/default/gpsd and set:

DEVICES="/dev/ttyAMA0 /dev/pps0"

Restart the gpsd service and check that bot time sources are availables via shared memory:

#      Name   Seen@                Clock                Real               L Prec
sample NTP2 1537596317.998856273 1537596284.999277455 1537596285.000000000 0 -20
sample NTP0 1537596318.371946497 1537596318.371124108 1537596318.000000000 0  -1

you should see both NTP0 (GPS via serial line) and NTP2 (PPS via GPIO) time sources. Finally we have to instruct ntpd to use both sources; in /etc/ntp.conf write the lines:

# GPS Serial data reference (NTP0) from gpsd shared memory.
fudge refid GPS

# GPS PPS reference (NTP2) from kernel /dev/pps0 device.
server prefer
fudge refid PPS

here again and are not actual IP addresses, but codes referring two drivers included into ntpd, both reading data from shared memory. The first (NTP0) gives normal gpsd data, the second (NTP2) is the combination of GPS (from serial line) data and PPS signal (from /dev/pps0 device) arranged by gpsd too. NOTICE: we will not set the fudge offset for the GPS serial line. That parameter is shown in some tutorials, but we actualy don't have an estimate of the latency between the time source and the real time.

Restart the ntp service. After several minutes (about 20), we can check the NTP status with ntpq:

ntpq -p -n
     remote           refid      st t when poll reach   delay   offset  jitter
 0.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.001
 1.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.001
 2.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.001
 3.debian.pool.n .POOL.          16 p    -   64    0    0.000    0.000   0.001
x127.127.28.0    .GPS.            0 l    9   64  377    0.000  -466.82  48.992
*    .PPS.            0 l   12   64  367    0.000    0.095   0.607
#     2 u   33   64  177   70.913   -4.211  16.929
+  2 u   35   64  177   60.899    0.280   1.602
#    3 u   22   64  357   66.601    1.309   5.264
-     3 u   27   64  377   57.357    2.066   2.908
#   2 u   24   64  377   55.375   -2.227   4.100
-  2 u   20   64  377   58.875   -0.302   5.721
+  2 u   25   64  377   49.941    0.257   8.541
-  2 u   24   64  377   55.687   -1.385   4.176
#      2 u   20   64  377   51.587    2.128   9.808
- .CTD.            1 u   21   64  377   69.029    0.926   5.152

Notice the .GPS. and .PPS. refid lines: they are our GPS time sources. Verify the reach field: our sources must be reachable and that number must be greather than zero. The output of the ntpq command is explained in this page: Real Life NTP.

The offset field is the difference in milliseconds (using root mean squares) between the client server and the source, the jitter indicates the root mean squared deviation of your offsets, in milliseconds. The single character at the right of the remote name is an x for our .GPS. source, it means that it is discarded by the Intersection algorithm. FIXME Should we add the fudge offset in ntp.conf to fix this?

PMS5003 Sensor

First of all we need to build a cable to connect the Plantower PMS5003 sensor to the standard 2.54 mm pins of the Raspberry Pi (or the USB to serial adapter). I used the little cable provided with the sensor and some spare cables with Dupont female connectors, I had to solder and insulate with heat shrink tubing. Here it is a photo:

You can connect the PMS5003 through a Serial/USB adaptor or directly to the Raspberry Pi. This table will help you:

PMS5003 Pin Color To Serial/USB… …or direct to the Raspberry Pi
1 VCC Violet +5V PIN 2 - 5V
2 GND Orange GND PIN 6 - GND
5 TXD Green RXD PIN 10 - GPIO#15 UART0_RXD

For the software part, we will install some scripts from the AirPi project on GitHub:

cd /usr/local/src
git clone
cd AirPi
make install-lib

Edit (create) the configuration file /etc/airpi/airpi.cfg with your settings:

DEVICE: /dev/ttyUSB0

We are ready to read data from the sensor, just launch the script /usr/local/lib/airpi/pms5003:

2018-09-13 09:35:57 INFO Sending wakeup command
2018-09-13 09:35:59 INFO Waiting 40 seconds for sensor to settle
2018-09-13 09:36:53 DEBUG Got valid data frame:
 PM1.0 (CF=1) μg/m³: 12;
 PM2.5 (CF=1) μg/m³: 16;
 PM10  (CF=1) μg/m³: 17;
 PM1.0 (STD)  μg/m³: 12;
 PM2.5 (STD)  μg/m³: 16;
 PM10  (STD)  μg/m³: 17;
 Particles >  0.3 μm count: 2154;
 Particles >  0.5 μm count: 632;
 Particles >  1.0 μm count: 56;
 Particles >  2.5 μm count: 9;
 Particles >  5.0 μm count: 2;
 Particles > 10.0 μm count: 0;
 Reserved: 0x91 0x00;
 Checksum: 709;
2018-09-13 09:36:53 INFO Got 16 valid readings, calculating average
2018-09-13 09:36:53 INFO Exiting main loop

The script, after 16 valid reads from the sensor, calculates the values average, writes them into the /var/run/pms5003.status file, and then exits. If you want the script to run in continous loop, set the option AVERAGE_READS_SLEEP to the interval in seconds between consecutive reads, e.g.:


Beware that if the sleep time is lower than three times the sensor settling time (default 40 x 3 = 120 seconds), the sensor fan will not be stopped between each read, so be prepared for a shorter life of the sensor.

Web References

doc/appunti/hardware/raspberry_explorer.txt · Last modified: 2018/09/22 08:32 by niccolo