Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

Perl interface to analog inputs on the Raspberry Pi

by stevieb (Canon)
on Jan 11, 2017 at 16:16 UTC ( #1179406=CUFP: print w/replies, xml ) Need Help??

Over the last few months, I've been writing Perl modules/distributions to interact with a Raspberry Pi, its GPIO, and external hardware/devices. My primary objective is to create a complete indoor grow room automation system.

The past week and a half, I have been focusing on writing a distribution that provides Perl users a way to interact with Adafruit's ADS1xxx Analog to Digital Converters (ADC), so that I could communicate with analog devices via the Pi which does not have any analog inputs. Hence, RPi::ADC::ADS was born.

The vast majority of functionality specified in the unit's datasheet has been incorporated into this XS-based module, and the documentation outlays all of the critical pieces from the hardware docs.


  • operates on the i2c bus, can connect four units simultaneously for a total of 16 analog inputs
  • ability to access all four channels on each ADC
  • continuous and single conversion modes
  • all eight Data Rate settings available
  • ability to change comparator polarity
  • ability to modify the comparator queue
  • all programmable gain amplifier modes available
  • ability to operate in single-ended mode or differential mode**
  • ability to return either the input data as raw, as a percentage, or as voltage
  • very easy to configure and run; most users won't have to set any parameters or call any configuration methods; the defaults are very sane
  • the documentation is extensive and detailed, but easy to understand and laid out reasonably well (I hope)
  • it has zero dependencies, Perl or otherwise (well, other than the need for a C compiler for the XS file)
  • works with any ADS1xxx model, and will properly bit-shift according to whether we're on a 16-bit wide resolution model, or a 12-bit one

** - single-ended mode is the measurement of voltage of a single input relative to ground. Differential mode retrieves the voltage difference between two separate inputs.

Here's a basic example, and for the most part, exactly how I use the software. Say I have a moisture sensor connected to analog input A0 (0 as far as the software is concerned) and I want to get the moisture level from it:

use warnings; use strict; use RPi::ADC::ADS; my $adc = RPi::ADC::ADS->new; my $v = $adc->volts; my $p = $adc->percent; my $r = $adc->raw;

Volts is a floating point number, percent is a float chopped at .2f and raw is the raw 16-bit unsigned int.

If you have more than one channel active at a time, specify which channel you want to fetch from:

# A0, A1 and A3 input channels for (0, 1, 3){ print $adc->percent($_) ."\n"; }

All configuration register options can be changed on the fly, as they each have their own setter/getter. Say you are using two inputs (eg: A0 and A3) as single-ended inputs and at one point in code, you need to retrieve the value of the difference in levels between them. The documentation has a map for parameter value to hardware functionality for all settings. All fetch methods allow you to send in the channel to retrieve on the fly, so we don't have to do anything special here. Per the map in the docs above, either of these will work:

my $diff_a0_a3 = $adc->percent(5); # or $adc->channel(5); my $diff_a0_a3 = $adc->percent;

The software is quite complete, and I have tested the vast majority of the configuration settings. I'm about 85% test coverage so there's a bit more work to do there, but I digress.

My next project is to write a Perl distribution for a BMP 180 barometric and altimiter sensor which I just bought and soldered yesterday, and an MCP3008 analog-digital converter. The 3008 has 10 input channels whereby the ADS only has four, but the ADS has 12-bit or 16-bit of resolution accuracy, where the MCP3008 only has 10-bit, so I decided I'd write code for both.

See also:

WiringPi::API, my original and nearly feature complete wrapper for the WiringPi libraries.

RPi::WiringPi, OO interface for the above wrapper with error detection, safe exit on unexpected terminations, and more.

RPi::DHT11, module to access the DHT11 temperature and humidity sensor.

App::RPi::EnvUI, my Dancer2 and jQuery one-page app for indoor grow room control (not yet fully completed).

RPi::WiringPi::Constant, module that contains commonly used names in the Raspberry Pi/electrical/electronics realm.

Replies are listed 'Best First'.
Re: Perl interface to analog inputs on the Raspberry Pi
by Discipulus (Abbot) on Jan 12, 2017 at 08:51 UTC
    Congratulations! is big jump in just 6 months!

    Continue sharing please; one day I hope I'll have enough spare time to jump on Perl's electronic point of view.


    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      A fraction over a year since your post here, and I'm about one week away from going live with the first official, non-beta release of App::RPi::EnvUI distribution with full pictorial POD and everything that I spoke of in your mentioned thread. I've been using my grow room environment controller in a production (albeit a "test", six plant) grow room for some time now.

      It's been quite a ride. For the RasPi, I have an extremely rigorous, custom-designed and written Continuous Integration testing platform I run on a 24x7 basis, and is triggered any time I make a commit that affects change to any related distribution, with a detailed breadboard layout for replicating the hardware aspect of the testing platform.

      I've got a PCB on order for the test platform so that I can just solder all the stuff together without having to utilize the space two breadboards take up, and the harsh errors that can happen over time when wires become loose. That went through about six different prototypes using typical perforated PCBs for testing.

      Here's the absolute latest code (on Github) for the original reason I started down this path. There are a few handfuls of issues most of which are "enhancements". All of the show-stopper ones have been fixed. My CPAN release of v1.00 has not happened yet as this next release primarily is focused on rendering a proper POD layout (which I haven't started yet as I've corrected some other issues).

      Again, about a week and the first version that I am confident won't burn down anybody's house, nor render grow lamps to turn on at an incorrect time has been achieved. (Note: I do have Residential and Commercial qualifications for the 120/240v electrical stuff, so if you don't, you'll want to get professional advice. The documentation will have physical set-up pics of one of my prototypes, with clear warnings about the dangers of live-electrical yada-yada)

Re: Perl interface to analog inputs on the Raspberry Pi
by Anonymous Monk on Jan 11, 2017 at 21:31 UTC
    Congratulations. You may have posted the most valuable piece of content to this site in nearly 10 years. Great job!

      I wouldn't go near that far, but thanks nonetheless!

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: CUFP [id://1179406]
Approved by haukex
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chanting in the Monastery: (6)
As of 2022-01-26 17:33 GMT
Find Nodes?
    Voting Booth?
    In 2022, my preferred method to securely store passwords is:

    Results (69 votes). Check out past polls.