Pi IoT In Python Using GPIO Zero - Complex Input
Written by Harry Fairhead & Mike James   
Monday, 18 January 2021
Article Index
Pi IoT In Python Using GPIO Zero - Complex Input
Custom Sensor

A Custom Complex Input Device

The LightSensor class is more useful than it appears. As it detects the time it takes for a capacitor to discharge, it can be used to measure resistance or capacitance. If the resistor is fixed then the time depends on the value of the capacitor. If the capacitor is fixed then the time depends on the value of the resistor. Any sensor that varies its resistance or capacitance in response to external conditions can be used with the LightSensor class. For example, a thermistor is a temperature-dependent resistor and can be read using the LightSensor class. You can create a presence sensor by using a metal plate as one side of a capacitor. As people move closer or further away its capacitance changes and hence you can use it with the LightSensor class.

As an example, we can create a simple moisture sensor. You need to construct two metal probes that can be stuck into the soil. The probes have to be non-corrosive and we used a pair of metal kebab skewers held in place by being passed through a plastic wire connector block, which also makes the task of connecting to the skewers easy. The block also holds the skewers apart at a fixed distance and makes putting them into the soil easier. Of course, the accuracy of measurement depends on the contact with the soil and minimization of movement. The circuit is exactly the same as for the LightSensor but with the resistor replaced by the moisture sensor:


There is no difference between this and the LightSensor, so you could just use the LightSensor class to implement the moisture sensor. However, it is easy to modify the name of LightSensor and change some of its methods:

from gpiozero import LightSensor
class Moisture(LightSensor):
    def __init__(self, pin=None, queue_len=5,
                 charge_time_limit=0.01, threshold=0.1,
                       partial=False, pin_factory=None):
       super(Moisture, self).__init__(pin, 
threshold=threshold, queue_len=queue_len,
charge_time_limit=charge_time_limit, pin_factory=pin_factory) Moisture.wait_for_dry=Moisture.wait_for_light Moisture.wait_for_wet=Moisture.wait_for_dark Moisture.when_dry=Moisture.when_light Moisture.when_wet=Moisture.when_dark

The only real difference is that now the resistance of the soil can be in the range 100Ω to 500KΩ, or even higher, depending on soil structure and the amount of contact and distance between the probes. You can adjust for this by changing the size of the capacitor or you can modify the charge_time_limit. For example:

for d in moisture.values:

You have to find the appropriate values of both parameters by experiment.

If you have a raw sensor that works in terms of resistance or capacitance then the same procedure will produce a suitable class to work with it.

HC-SR04 Distance Sensor

An ultrasonic distance sensor works by sending out a pulse of ultrasonic sound and timing how long it takes to detect an echo. There are a number of similar modules on the market, but the HC-SR04 is common and inexpensive.


However, it needs to work with 5V data lines and this means using a divider to shift the voltage to 3.3V. A simpler solution is to use the HC-SR04P, which is nearly the same price and works at 3.3V.

Whichever module you use, there are four connections Vcc, Ground, Trig (Trigger) and Echo. You have to connect each of Trig and Echo to a GPIO line. The basic operation is that the Trig line is set high for a short time and this causes the module to send a pulse. The Echo line goes high when a reflected pulse is detected. The time between the two events gives you the distance.

The constructor requires that you specify the two pins used as the first two parameters:

DistanceSensor(echo, trigger, *, queue_len=30, 
max_distance=1, threshold_distance=0.3, partial=False,

Notice that readings are the smoothed average of 30 measurements – ultrasonic distance measuring is very noisy. You can also specify a max_distance which is use to scale the value parameter. The threshold_distance is used to specify a “too close” event via wait_for_in_range , wait_for_out_of_range, when_in_range or when_out_of_range. The distance property gives an estimate of the current distance from 0 to max_distance and value gives a scaled distance in the range 0 to 1.

In chapter but not included in this extract:

  • Source/Values – An Alternative Approach
  • Source Functions
  • Combining Sources
  • A Custom Combining Function
  • Data Sources
  • A Custom Value Source
  • Internal Devices
  • A Custom Internal Device
  • The Limitations of Source/Values?


  • SmoothedInputDevice is the base class for a set of more sophisticated input devices which average or process their raw inputs in some way.

  • The LineSensor class uses a IR diode and sensor to detect the reflectivity of a surface.

  • MotionSensor is a standard IR motion sensor.

  • LightSensor uses an LDR to measure the current light level. It can be used to measure resistance or capacitance. For example, you can use it to measure the moisture content of soil.

  • DistanceSensor is a standard ultrasonic distance sensor.

  • The Source/Values mechanism can be use to connect output devices to input devices so that the input is transferred to the output every hundredth of a second.

  • To make Source/Values more useful, there are functions that can transform and combine values.

  • There are also functions that can generate values to be fed to output devices and it is easy to create your own.

  • A number of internal devices can also act as sources of values.


Raspberry Pi IoT In Python Using GPIO Zero
Second Edition

By Harry Fairhead & Mike James


Buy from Amazon.


  1. Why Pi for IoT?
  2. Getting Started With Python And GPIO Zero
  3. Introduction to the GPIO
  4. Python - Class and Object
  5. Simple On/Off Devices
      Extract 1: On/Off Devices *
  6. Pins And Pin Factories
      Extract 1: Pins ***NEW!!
  7. Some Electronics
  8. Simple Input
  9. Complex Input Devices
      Extract 1: Complex Input *
  10. Pulse Width Modulation
      Extract 1:  PWM*
  11. Controlling Motors And Servos
      Extract 1: DC Motors *
  12. Working With Compound Devices
      Extract 1: Compound Devices*
  13. The SPI Bus
  14. Custom SPI Devices
  15. Using The Lgpio Library
  16. Appendix Visual Studio Code Remote Python
    *Extracts from first edition - will be updated.


To be informed about new articles on I Programmer, sign up for our weekly newsletter, subscribe to the RSS feed and follow us on Twitter, Facebook or Linkedin.


Anaconda Joins AI Alliance

Anaconda has announced that it is joining the AI Alliance. Anaconda is best known as a provider of open-source distributions of Python and R for scientific computing.

TornadoInsight Brings The Power Of TornadoVM Inside Intellij

TornadoInsight is plugin for Jetbrain's popular Intellij IDE for Java developers, that makes working with TornadoVM a much smoother experience.

More News

raspberry pi books



or email your comment to: comments@i-programmer.info

Last Updated ( Monday, 18 January 2021 )