Python code for multiple SDI-12 sensors

As you probably know, the SDI-12 sensor logger code in Python can only log one sensor at a time. It is not a hardware limitation. I wrote the logger code as an example of how to do logging with the SDI-12 adapters and Python. To make sure people don’t have the wrong ideas that you can ONLY get one sensor logged, I have been working on the logger code for the past couple of days and have increased the number of sensors from one to any number you need. The improvement is backward compatible with the configuration file for Raspberry Pi logging, in case you wonder. All that is changed to the user interface is the prompt:

Original prompt:

‘SDI-12 sensor address: (0-9, A-Z, a-z)’

New prompt:

‘Enter all SDI-12 sensor addresses, such as 1234:’


So if you have 4 sensors you want to log together, then just enter all their addresses in a string, such as 1234 and hit enter. All sensor inputs will be saved to log file and sent to sparkfun’s data server. The only limitation on the code now is the sparkfun data server stream. The server stream is set up to only take 6 values so the logger code will send the first 6 values from all sensors to the server. If you wish to lift this limitation, you should create your own stream and set up as many values per data point as you need, and modify the logger code (see the magic number 6?).

Below are some sample data logs:

2/3/2017  12:15:25 AM 1 1.11 26 z 5.09419 5.09381 0.24388 5.09419
2/3/2017  12:15:56 AM 1 1.11 26 z 5.09325 5.0925 0.24388 5.09306
2/3/2017  12:16:28 AM 1 1.11 26 z 5.09363 5.094 0.24375 5.09438
2/3/2017  12:17:02 AM 1 1.11 26 z 5.09194 5.09269 0.24375 5.09306

As you can see, the data are separated by sensor address. The address z is the analog-to-digital converter’s address for SDI-12 + Analog adapter. As you can see, my computer outputs 5.09V instead of the nominal 5V on its USB port.

Here is a link to the new logger code. Give it a try and let me know how you like it.

SDI-12 bus scan code

In case you need to diagnose your SDI-12 data logger, I posted SDI-12 bus scan code for the SDI-12 USB adapter (in Python) and for the SDI-12 data logging shield (in C for Arduino). Their links are under Data logger programs or Downloads.

Here is a screen shot of the Python code:


The Arduino code has a similar interface without the serial port select (you select Arduino serial port in Arduino serial monitor). It’s fun translating C code into Python. C is famous for manipulating strings as arrays of ASCII characters. Doing such in Python seems like a hassle because it has no pointer mechanism, loose types, and aims to handle Unicode so it buries the ASCII characters under layers of things. Anyway, each language has its own strengths and weaknesses.

Notice that the scanner shows a Decagon 5TM sensor at address ‘1’ and also shows the SDU-12 translator at address ‘z’. Make sure that each sensor already has a unique address before scanning the bus. To configure sensors with unique addresses, run the configuration code for either the SDI-12 USB adapter or the SDI-12 data logging shield. Hope this helps. Comments?

Log data with SDI-12 USB adapter

On my last post, I showed a couple of videos of how to connect an SDI-12 sensor to the SDI-12 USB adapter. Here is a video of how to configure an SDI-12 sensor and log data with the adapter:


Sorry there was some noise in the background that I couldn’t get rid off with the authoring software. Here is the transcript in case you need it. I will explain how to send data to sparkfun’s data server in my next post.

Let’s plug in the SDI-12 USB adapter. Windows will automatically install its driver and create a COM port, in this case, COM18. If this is your first time installing a COM port on your computer, you will need to be patient.

What we are looking at are two windows. The window on the left is the python shell. It shows you the input and output of python scripts. The window on the right side is the SDI-12 configuration script version 1.1. We run this script to set up the sensor’s SDI-12 address.

On the left window, you can see the messages printed by the configuration script in blue. This script runs on windows, mac, linux, and raspberry pi.

The script has discovered a number of COM ports and listed them all on the left window. The first one, item zero, is our SDI-12 USB adapter, i.e. COM18. Type zero and enter. Ignore the rest. If you are unsure about the COM port number, run this script with the adapter disconnected and then run it again with the adapter connected. This way you can see which port belongs to the adapter.

After a short moment, the script has detected the SDI-12 sensor at address 1. The information printed out indicates sensor address 1, compliant with SDI-12 standard version 1.3, and the manufacturer is Decagon. The sensor is a spectral reflectance sensor and its serial number is also printed out.

What this script does is to detect the one-character SDI-12 sensor address, print out the sensor information, and allows you to change its SDI-12 sensor address. Valid address includes 0-9, A-Z, and a-z.

Let’s set the sensor address to 2. To check that this has taken effect, we run the script again.

Now it has detected the new address. The address is saved on the sensor until it is changed again.

Now let’s look at the data logger script.

What this script does is: it logs data to two places, a file on the computer, and it also sends the same data to a server at sparkfun electronics. Everyone that runs this sample data logging script shares the same storage on the server and can see results from everyone else. You can also create your own storage or stream on sparkfun so you can keep the data to yourself.

Here I have python shell and sdi_12_logger script version 1.1. Let’s run the script with F5. This time there is a longer printout and it does say it runs on Mac OSX.

Next we see a list of serial ports. We select zero for COM18, like before.

Then we are required to enter the total number of data points. Let’s try 5. You can enter any large number of data points and stop the data acquisition anytime with Ctrl-C. Data saved on your computer and sent to the server will not be lost if you stop the script.

Delay between data points is specified in seconds. We’ll use 10 seconds. Then we decide whether to store each data point with local or universal time. Enter 1 to pick local time.

Enter the SDI-12 sensor address, 2.

Here is the first data point. Date and time, then two spectral reflectance values, and then 2.0 for facing upward.

The curl command that appears on the next line will only appear if you have curl installed, which is a tool to send HTTP requests. So besides a local copy of your data, you also have an online copy on sparkfun electronics server.

OK now we finished collecting 5 data points and the python shell prompt has returned.

We will take a look at the data file and the server data next.

Install python on windows PC

Last time I described how to install python on Debian or Raspberry Pi. If you are a beginner and have a windows PC, here is my short tutorial on how to install python AND pyserial on a windows PC. Since I’m interested in Arduino, I will certainly need a serial module in python to talk to Arduino, such as sending Real time (yyyy/mm/dd hh:mm:ss or epoch) to Arduino to set its Real Time Clock or collect data from Arduino.

Python as of the writing has two main versions, Python 2.x and 3.x. The latest 2.x is 2.7.11. Lots of code have been developed on Python 2.x so many people still hang on to this version. The other day I tinkered with a Raspberry Pi LCD hat (add-on) and the Adafruit Python module that drives it can only be installed on Python 2.7.11. The most current version of Python 3 is 3.5.1. We will focus on this version since it has been out for quite a while. Also, Pyserial works flawlessly on Python 3.5.1.

First, download the installer here:

Go to the bottom of the page and find your PC’s version (32 or 64 bit).

Install Python. Now, you need to find where the installed Python resides so you can include its path in your system’s PATH environment variable.

For me, it is here:


Make sure you replace your_username with your actual user name (usually shortened from your full user name in windows 10).

Right click your “This PC” icon on desktop and select “Properties”. Then go to “Advanced system settings” on the left pane.

Once the dialog pops up, select “Environment Variables” on bottom right:

Advanced system settings

Once opened, you see the top half as user variables.

Environment VariablesClick PATH and Edit. Add the following TWO paths:



Save and restart your computer.

Now you should have Python installed and ready to go. Still, you will need to install various modules to expand your Python, or simply to run “that script that wants this and that module”. Lots of modules are available to Python such as pyserial (serial port support) and idlex (more customization to Python’s IDE).

To install pyserial (or any other module), first open a command prompt. Then type in:

“pip install pyserial”

The package will install automatically. You are done!


30-day temperature data

Since I was going away for a month, I decided, before I left, to set my SDI-12 data logger to run a 30-day data collection routine, just to see how robust the software is. Here is the result:

30-day temperature

The temperature sensor was in my office so its variation was small. The steep slope towards the end was because I opened the window after I got back and kept the window open for a whole day. You may notice the lack of variation of temperature between 5/10 and 5/13 but that WAS what happened. History data from showed less-than-average variation of outdoor temperature in my area during the same period:

wundergroundSo my conclusion was that my python data logger code running on raspberry pi was robust enough for at least 30 days so was the SDI-12 USB adapter. If this were done outdoors, then the raspberry pi and the SID-12 USB adapter both need protection from the element. Also a solar panel and battery will be needed.

Parts and components:

Raspberry pi 2 B (or 3 B)

SDI-12 USB adapter (Free python data logger code)

Decagon 5TM soil sensor


Soil data logger telemetry

I have finally found time to build a simple website for my soil data logger with telemetry. The system works as the following:

  1. The data logger consists of a raspberry pi and my SDI-12 USB adapter with a Decagon 5TM soil sensor
  2. The data logger runs the open-source datalogger code I wrote in Python to first get parameters from the user (COM port, SDI-12 address, delay etc.), and then collect data, save to a local .CSV file, and then send the same data to sparkfun’s phant server.
  3. I constructed a web interface to plot the data using Google Charts and download .CSV version from sparkfun’s phant server.

Here is a screen shot:

soil logger webpage

I’ve uploaded the webpage to a server with a link below. The sensor is apparently NOT buried in soil so I can easily take the setup and set it up in different places to test its stability.

Link to the website: Link

Update SDI-12 USB adapter firmware

I have just released an update to the SDI-12 USB adapter. This update makes the adapter recover from errors in communication so it won’t hang your data logging process in case a sensor is broken while you are logging.

To make the firmware update easy, I wrote a Python script to use avrdude.exe to load the firmware to the adapter. You will run the script just like the data logging script or config script:

  1. Install Python 3.5 with Pyserial 3.0 (instruction in the manual).
  2. Unzip the content of the firmware update package in a folder.
  3. Check the properties of avrdude.exe to make sure that it is not blocked from running.
  4. Run the script in Python environment IDLE.
  5. Select the adapter’s serial port from a list.
  6. Pick the firmware file, usually SDI_12_translator_v1_x.hex (must be stored in the same folder as the script), then wait for it to complete, which takes less than 30 seconds.

Here is the output from Python:


sdi-12 USB adapter firmware update

I had the adapter on COM4.

Once updated, try connect to it using a terminal program and send zI! (zee-EYE!) and you will see the response has version 1.2 in it.

(Updated) This script now works on Windows, Mac OSX, GNU/Linux (64-bit) and Raspberry Pi.

Dropbox Python API

Assume that you are building a data logger and need to send your data from your logger to you, one option that will not cost you money or much programming time is to send your data file to your Dropbox. This requires some minimal setup. Once set up, you can proceed to add the file upload feature to your code. I am using Python to do the job. It is quick and easy. Plus, you can port your code to any operating system, such as PC running windows, GNU/Linux, Mac OSX, or Raspberry Pi. I am assuming that you have Python 3.X.

There are two versions of Dropbox Python API, V1 and V2. V2 came out around the end of 2015 and only has minimal tutorial on Nevertheless, I will use V2. Installing the API is a snap:

On Windows:

Start a command prompt and enter:

pip install dropbox

On Raspberry Pi (Raspbian Jessie) or Debian PC

sudo pip3 install dropbox

If you still have Raspbian Wheezy, pip3 may tell you that there is a newer version of pip. Don’t attempt to upgrade your pip or pip3. It will break.

Here is a short Python script to upload and download files:

import dropbox
dbx=dropbox.Dropbox('Your access token')
with open(file_name, 'rb') as f:

dbx.files_download_to_file('Copy of '+file_name,dropbox_path+file_name)

This was easy. There are only three functions that I used, first an authentication, then upload, followed by download. Your access token is generated by Dropbox. This post has the details.
The function dropbox.Dropbox() returns an object. You can use this object to upload or download files and more.
The files_upload() function does the upload. You need to first open the file on your local computer with open(). I am assuming the file is stored in the same folder as your Python script. This returns a file handler f. Then pass f to the files_upload(). This is the first argument. The next argument is the path you want the file to be uploaded to dropbox. It has to start with ‘/’, then the file name (including additional path). You don’t have to preserve file name. The third argument is useful. When you sent mute to True, you won’t get notification for the file upload. If you are making a camera trap, you don’t want your PC flooded with Dropbox notifications just because a bunny decides to visit your backyard.
The files_download_to_file requires first a local computer name, then the Dropbox file name. Again you don’t have to preserve file name. It’s useful to first check if the file exists on your local computer and decide what to do (overwrite, or add prefix/postfix to new file).
This is it! How you use it is up to you.

If you are interested, you can explore the rest of the API, such as creating folders, moving files, listing folders, etc. by reading the documentation (alert: document is very dry)

In my next post, I will make a simple Raspberry Pi camera logger to activate only during several intervals of time of the day.

Connect to Dropbox

If you are making a data logger, or camera trap, this is definitely good news. With the right approach, you can sit in your home and data/pictures just flow to your desktop. All you need is internet connection and some Dropbox programming. With a raspberry pi or a pc, you can have your data logger or camera logger automatically upload data to your Dropbox. On a windows PC, this is nothing more than saving your data file to a folder inside your Dropbox folder. Still, constantly writing to a Drpobox file is not the best way to make use of it. You won’t be able to have a meaningful history of the file since the your data logger updates the file too many times. Also, raspberry pi doesn’t have dropbox client. So it makes sense to programmatically upload your file to Dropbox using its API or application programming interface.

I am starting a series or posts to detail how to upload files to Dropbox from within your code. This post only explains how to set things up.

Using Python, it is extremely easy to upload files to dropbox. There is only one catch, you have to set up as an app developer. Here is their logic thus how to get set up:

You have some good ideas for an app. You want to store your app’s data files on dropbox so your user can access them on any device they are using. Good idea, but how to set it up?

First you need a Dropbox account yourself. Once you’re set, log on with your web browser. You’ll see three circles on the bottom left of your window:

dropbox dev-1

Clicking the dots brings up a menu. Select Developers:

dropbox dev-2


Click “Create app” to create a new app. I’ve already created a couple of similar apps. It looks like I’ve been trying this camera logger idea for one too many times 😀

dropbox dev-3

Make sure that you select the right options. Select “App folder” access so all your actions are contained in a folder inside the App folder. It used to be called sandbox access. You may not want this app to access your entire Dropbox folder and accidentally delete files it is not intended to touch.

dropbox dev-4

Once done, you will be able to edit your project. Scroll down to find “Generated access token”. This will give you a very long alpha-numeric sequence that grants access to your Dropbox app folder, or the entire Dropbox if you chose “Full Dropbox”. Safeguard this string. If you need to ask questions about your code, remove/black out this string. Anyone with this string can do anything they want with your Dropbox app folder, no password needed. alternatively, you may try the App key and App secret path. That is a longer path than we need to take, just to show how things work.

dropbox dev-5

Now you are all set to develop this app, which is probably a program that uploads data/pictures to your dropbox. Read my next post about how to access Dropbox using Python. Python is one of the least preferred language I use but there are benefits of using it. It’s quick to see results. I am a big fan of Arduino. Unfortunately, it is almost impossible to upload to Dropbox using just an Arduino (except Arduino Yun).

SDI-12 USB adapter on Raspberry pi

I have successfully developed Python code to run the SDI-12 USB adapter data logger on Raspberry PI. It was quite a learning experience for me but I was able to boil down the steps into a tutorial on how to install the latest Python on Debian/Raspbian here.

Here are some screen shots of the data logger:


2016-02-05-100346_1680x1050_scrotI was using a Decagon 5TM soil temperature and humidity sensor (hanging free in air and sometimes touching my table).

I have translated the Tera Term scripts into Python so it would run on all operating systems, including Win 10, Linux (Debian), and Raspberry PI (Raspbian). I have not got my Mac fixed but don’t expect any issues.

Now you have two Python scripts:

The configuration script detects the SDI-12 sensor’s address, prints the name of the sensor, and you can change it to a different address.

The data logger script lists all available serial ports to let you choose the correct one, then asks for sensor address, total data points, delays between data points, and also what time (GMT or local) to use. You can expand the script to take data from multiple probes and upload data to a server. I’ll add more info on the server upload to sparkfun’s phant data server.

While developing the code, I also discovered that the serial port console was very useful. You can set up auto login and run the data logger script upon auto login. This way the data logger starts logging data once the RPI boots up and auto logs on. No need to log in or use VNC (not good if your logger is using 4G hotspot for internet). Just a command prompt is all that is needed. Next step is to add a config file so the data logger will no longer ask for user inputs when this file exists and takes parameters from the file. This config file will reside in the FAT partition so that the user can easily update the parameters without having to boot into raspberry pi. Just remove the sd card and change parameters on a PC.

%d bloggers like this: