Introduction: How to Interface Any Sensor

Electronics is the art of controlling electrons.

Software begins at the end of electronics. Software scales electronics. At the end of software is humans. Software allows humans to communicate with machines. At the beginning of electronics is the physical world. Software is abstract, the real world is not. The bridge between the two is paved with basic principles - the path to full stack IoT engineering.

Technology changes, basics don't.

Step 1: Conductors

Elements with more less than 4 electronics in the outer shell have free electrons and will conduct electricity when a potential difference(voltage) is applied across them. Elements with greater than 4 electrons in the other shell are non-conductors of electricity. Elements with 4 electrons in the outer shell are semi-conductors as they can lose an electron to conduct electricity or gain an electron to become a non-conductor.

Step 2: Water Flow

The easiest way to visualize the flow of electricity is to visualize the
flow of water from a raised container as shown in the image. The flow of the water in the pipes is determined by, the volume of water in the raised tank, it's height, the length of the piping, the pipes cross-sectional area (controlled by the water valve) and the load the turbine presents to the system.

Step 3: Electron Flow

A battery is a storage tank for electrons. When the switch is closed to complete the circuit, electrons will flow from the negative terminal of the battery, through the wire conductors and through the winding of the motor, back into the positive terminal of the battery. The conventional current flow is opposite the flow of electrons. Current flows from the positive terminal to the negative terminal.

The motor's winding is surrounded by permanent magnets. When the current flows through the motor, it will spin in a direction determined by Flaming's left-hand law. The system will lose energy as heat due to the winding's resistance and hysteresis which will progressively drain the battery.

Step 4: Electric Circuit

When the switch is closed, the voltage V will cause a current I to flow through the resistor R depending on Ohms law.

Voltage V = Current I x Resistance R
V = IR 

where V is specified in volts, I in amperes and R and ohms.

Ohm's law is the fundamentals of how electric circuits behave. Almost everything else is an application of this law.

Step 5: Resistive Sensors

Resistance is the ability of a conductor to oppose the current flowing through it. A resistor is usually made up of conductors - either metallic wire or other composite materials such as carbon film.

The resistance R is directly proportional to the length of the conductor and inversely proportional to it's cross-sectional area A. That is:

Resistance ∝ Length/Area


R = K (length/Area)

Where the constant K is the coefficient of resistance and depends on the material.

Step 6: Physical Properties

Electrons in a conductor will spin faster on their orbits when heated. This results in larger orbits which makes the conductors expand. Likewise, they will contract when cooled down.

The expansion changes the cross-sectional area of the conductor in a way that is proportional to the heat. If this conductor is part of a circuit, then the resistance will change based on its coefficient.

This is very similar to mercury or alcohol expanding in a glass thermometer.

Step 7: Temperature and Current

ohms law states: 
V = IR

the resistance of the conductor is:
R = K(l/A)

therefore the resistance of the material is
V = I K(l/A)
the resistance of the material is:

This means that the current in the circuit will increase as the resistor is heated (as it will expand) and decrease when it is cooled.

A temperature dependent resistor is called a Thermistor and can be used as a temperature sensor.

Step 8: Connecting to a Micro-Controller

The easiest way to read temperature using a thermistor is to connect it to a micro-controller such as the v2 controller. The current going to the micro computers analogue out put will increase or decrease with temperature.

There is a catch though, microcomputers are not current driven devices and typically have a very high input impedance (resistance to signals). So we have to convert the current going to the micro-controller into a voltage signal using a signal conditioning circuit.

Step 9: Potential Divider Circuit

Since R1 and R2 are in series, the current flowing through R1 is the same as that flowing through R2.

Using Ohm's law:

V = IR

For the outer circuit
Vcc = I(R1 + R2)

For the inner circuit
V2 = IR2

Since the current is the same in both circuits
Vcc/(R1+R2) = v2/R2

V2 = Vcc(R2/(R1+R2))

That is in a potential divider circuit V2 is a fraction of the supply voltage Vcc dependent on the ratio of R2 to the total resistance R1+R2

Step 10: Reading Temperature

Now the current in the potential divider depends on the temperature of the thermistor. This cause a voltage drop across the analogue pin A1 of the micro-controller that is dependent on the temperature.

All we need to do is to read the analogue pin A1

int thermistor = analogRead(A1);

Then calibrate for the temperature using Steinhart-Hart's equation.

Step 11: Capacitive Sensors

A capacitor is an electronic device that converts electrical voltage into an electrical field. Physically it consists of two conductive non-touching plates with a surface area "A" separated by the distance "d". A non-conductive electrically polarized material called a dielectric is inserted between the plates to increases the capacitance. Air has a low dielectric permeability constant.

Capacitance C increases with the surface area "A" of its plates and decreases as the distance "d" between the plates increases

Capacitance ∝ Area/distance
C ∝ A/d


Capacitance =  ε . Area/distance

"ε" is a constant and is the capacitance permeability of the dielectric material.

Since the plated don't touch, the circuit is an open circuit to direct current DC. When the circuit is completed, the capacity will charge instantly and the voltage across the capacitor will be equal to that of the battery.

Step 12: RC Circuits

An RC circuit is created when a resistor R is added to the capacitor C in series.

The circuit is still an open circuit to DC. When the circuit is closed, the capacitor will charge to the same voltage as the battery at a rate determined by the resistor capacitor combination.

Step 13: RC Time Constant

The time it takes for the capacitor to fully charge to the supply voltage is called Tau - T and is the product of the resistor R and capacitor C in the circuit.

T = RC (seconds)

Step 14: Detecting Liquid Level Using Capacitance

Using the properties of a capacitor, we can measure liquid levels inside non-metallic containers or pipes from the outside. Using copper foils and a resistor we can build an RC circuit and use water as a dielectric to detect and measure the level of fluids unobtrusively from outside the vessel of pipes. Such a setup is shown

Step 15: Equivalent RC Circuit

The equivalent circuit for the vessel with copper foil liquid sensor is shown.

The resistor R is in series with the capacitor sensor C making an RC resonant circuit.

The circuit is activated by putting 5v on the send pin by raising D1 high. This causes the capacitor C to charge based on the time constant RC. The level of fluid in container will affect the capacitance by changing the capacitance due to a change in the dielectric. This the RC time constant is detected by the micro-controller on pin D2 when this switches from Low to High. The time constant measured will be different based on the liquid in the vessel, giving an almost linear relationship as the liquid level changes, All that is required is to calibrate our readings.

Capacitors and the basic properties can be used for many sensing applications.

Step 16: Measuring Liquid Level

The graphs show how the time constant changes with the liquid level.

The higher the level of the liquid, the higher the dielectric permeability, the higher the capacitance, the faster it will charger so the shorter the RC time constant

The code for this is very simple as one can use the arduino capsense library.

It begins by declaring the send and receive pin

const int capacitor_receive =  4;<br>const int capacitor_send =  2;

Creating the capsense object

CapacitiveSensor   cs_4_2 = CapacitiveSensor(capacitor_send,capacitor_receive);

The using the library to send and monitor the charge on the receive pin

long total =  cs_4_2.capacitiveSensor(30);<br>Serial.print("chargeDuration\":");

Step 17: Digital Sensors

Digital sensors have two states, a High state or logic 1 when the sensor detects 5v (Vcc) and a Low state or logic 0 when the sensor detects 0v (Gnd).

Step 18: Logic Level 1

In the circuit shown, "switch 1" are contacts of say a magnetic reed switch embedded within a magnetic door sensor that activates when the door is shut closed.

When the switch is closed, Vcc is applied on the digital pin D3 of the micro-controller which sees a logic level 1.

When the switch is opened, D2 is neither at Vcc or Gnd. It is floating and it has an intermittent value - it acts as an antenna and can pickup electrical noise from nearby equipment which can be undesirable.

Step 19: Pull-Down Resistors

A pull-down resistor will prevent unwanted noise from the sensor pin by preventing the pin to float.

When the switch is open, the resistor will pull the pin down to ground and the micro-controller pin will be at 0v. It will interpret this as a logic level 0 signal

When the switch is closed, the micro-controller digital input will be at Vcc which is 5v for an Arduino and will interpret that as a logic level 1 signal.

Step 20: Logic Level 0

In this case, we have an active low configuration. When the switch is closed, the digital pin will be at ground. The micro-controller will read that as a logic 0.

When the switch is open, the micro-controllers input pin is neither at Vcc or Gnd, it is floating. It could take any value as it can pick up noise including electromagnetic interference.

Step 21: Pull-Up Resistors

A pull-up resistor is used to keep the micro-controller pin connected at Vcc when the switch is open. Active low circuits maintain a signal with logic level 1 by default without a signal.

When the switch contacts are activated, say the contacts are completed by water flow on a leak sensor, the micro-controller will detect this as a logic level 0 - an active low level signal that indicates a potential water leak.

Step 22: Reading Digital Sensors

Reading digital data is easy. We declare the specific micro-controller pin as an input pin.

const int D5 = 5;
pinMode(D5, INPUT);

Then we read and print it.

int d5 = (digitalRead(D5));<br>Serial.print(d5);

Step 23: 1-Wire and I2C Sensors

Some sensors are intelligent with their on inbuilt micro-controllers that condition their signals and compute their own values. Normally such sensors are addressable such as 1-wire sensor allowing multiple sensors to be connected to the same pin. The 1-wire bus is an open drain that requires pulling up using a 4.7k ohm resistor. I think of i2c as 2 1-wire buses with a clock.

Using these sensors is easy as they normally give the actual value and units measured and there are libraries. The following examples shows how to read temperature from a 1-wire temperature sensor.

We start by loading the one wire library as well as the temperature sensor library.

#include <onewire.h>
#include <DallasTemperature.h>

The we tell the micro-controller on which pin the sensor is connected

#define ONE_WIRE_BUS 28

Then we initialize the one wire temperature sensor object

OneWire oneWire(ONE_WIRE_BUS)

We ask all the sensors on the wire to read temperatures


Then we get the address of the first device (or only device if only one is connected)

sensors.getAddress(sensorAddress, 0))

Then we read the temperature value for the first sensor on the wire as a float.

temperature = sensors.getTempC(sensorAddress);

Step 24: Serial Sensors

Traditionally serial devices use the RS232 protocol which operates at +-12Vdc. In this case we are talking of devices that work at 5v or 3.3v that can connect directly to the micro-controllers.

Serial sensors have a receive RX and transmit TX lines. Most micro-controllers have UART lines which is another name for serial interfaces and also have a RX and TX pins.

Generally data flows from the sensors transmit TX line to the micro-controller receive line RX and control signals from the micro-controller's TX line to the sensors RX line..

Since all the data sent down single wire TX connection is not self clocking nor synchronized with an external clock, the devices must establish a common communications transmission speed called the Baud Rate to exchange data.

Serial devices are easy to read. For example to read the Electrical Conductivity from an atlas scientific EC sensor connected on the second serial line, one could do the following.

Set the Baud rate and initialize the UART port

long baudRate = 38400;

If there is data on the serial interface,, read the next 24 characters from the receive pin, store the data in a temporal array and terminate the array with a \0 and return the value as a integer.

while (Serial2.available() > 0 && index < 24 ) {
	inData_TDS[index] =;
inData_TDS[index] = '\0';
char* string_EC = strtok_r(inData_TDS, ",", &p);
* string_EC = strtok_r(inData_TDS, ",", &p);
EC_val = atoi(string_EC);

Step 25: 2-Wire (4-20mA Current Loop) Sensors

Sensors used in industrial control processes are normally located at great distances in noisy environments. In these kinds of applications, 2-wire sensors that require a constant current source at 4-20mA (Milli-amps) are used. For instance, pressure sensors rated at 50psi will draw 4mA from the current source when no pressure is applied (0psi) and draw 20mA when the maximum pressure is applied at 50psi.

The microcontroller's input has a high impedance so the changes in the current drawn by the sensor are converted into a measurable voltage by the 250ohm resistor.

The value of the 250 ohm resistor is determined using the sensors maximum current 20mA and the micro-controllers maximum input voltage which if Vcc at 5v for the Arduino.

Using Ohms law:
5 = 20mA x R 
R = 5/20mA = 250 ohms

All that remains is to read the sensor, calibrate the result using the map function as these sensor outputs are typically linear.

sensorValue = analogRead(2-wireSensorPin);
minPressure = 0;//psi 
maxPressure = 50; //psi 
pressureDetected =  map(sensorValue, minPressure, maxPressure, 0, 255)

Step 26: Wheatstone Bridges

When the resistance changes in a resistive sensor are so small (micro-ohms) that they cannot be measured between terminals, a signal conditioning circuit such as a Wheatstone bridge is used. Typical sensors in this category are strain gauges used for measuring force. The strain gauges are used in load-cells that compress or stretch the sensor changing their resistance. Normally R1 is a variable resistor and the circuit is tuned such that the Wheatstone bridge is balanced, V out is 0v without a load.

This happens when

Rstrain= R1.R2/R3  where V is 0v

Step 27: Reading Load Cells

Normally the output voltage from the bridge is still very low and we have to amplify this using an op-amp before we can read it as an analogue voltage on the micro-controller. In the image, the strain gauge is connected to the Wheatstone bridge whose output is connected to an Op-amp configured as a differential amplifier

The signal from the strain gauge is multiplied by 10 as shown by the gain (amplification) of the Op-amp circuit.

A = R4/R5
Typical values are R4=1M and R5=100k ohm
so the gain (amplification) is 10

This is then read by the micro-control as a regular analogue signal and calibrated to show the force applied on the load-cell and strain gauge sensor.

Step 28: Hall Effect Sensors

Hall effect sensors are examples of using magnetic material properties to translate physical entities into electrical signals for processing.

A conductor carrying current will experience a potential difference (voltage) on its side when a magnet is brought perpendicular to it from the bending of electron paths in the conductor. This voltage generated is proportional to the strength and the distance of the magnetic field. It can be measured and used in micro-controller circuits.

This is used to detect motion, rotation and counting revolutions of spinning objects.

Step 29: Hall Effect Circuits

Hall effect sensors are active sensors in that they require a voltage supply. The devices have three pins, Vcc, Gnd and the Signal line. A permanent magnet on the rotating member eg wind turbine blade and the sensor is placed in such a way that the magnet passes across it on every rotation creating a voltage pulse on the signal cable.

As the turbine rotates, we can detect all the pulse from the magnet using the Hall effect sensor if the micro-controller is dedicated to this function only. Often the micro-controller is also computing other functions so they will miss some of the pulses that come from the sensor when the micro-controller is busy.

To overcome this problem, the output from the sensor is connected to an interrupt pin on the micro-controller. The computer will stop what it is doing to service a signal on the interrupt pin. To measure the revolution of the turbine, we put out computer to sleep for 1 second, then count how many interrupt pulses we get in that 1 second duration. If we got say 5 pulses, then the speed of the turning is 5 pulses per second. A little calibration and we can get the speed in different units eg, gallons per second. This is shown below.

We start by declaring the interrupt, and telling the micro-controller what do when an interrupt is detected. Interrupt 0 is the first hardware interrupt pin on the Arduino mega and is on pin 2. rpm is the coll back function. This is the function that will be called when an interrupt is detected

attachInterrupt(0, rpm, RISING); //and the interrupt is attached

Next we initialize the global count variable

NbTopsFan = 0;    //Set NbTops to 0 ready for calculations

The we sleep for 1 second as we count interrupts, happening on the rpm callback

delay (1000);    //Wait 1 second

The we disconnect the interrupt to free the micro-controller to continue with it's other tasks.


Get the results from the call back function

RevPerMinute = (NbTopsFan * 60);

The call back function rpm has only one line;


Step 30: Photo Transistors

Semi-conductors conduct electricity when they have extra carries - electrons (N-type) or holes (P-type) and an electric potential(voltage) is applied across them.

A bipolar junction is formed where N-type material meets the P-type material. A bipolar junction is a diode and allows current to flow in one direction (P-type to N-type) and not the other direction (N-type to P-type). A npn bipolar transistor is created when N-type, P-type, N-type semi-conductor materials are doped as shown above in the cross-section giving the emitter, base and collector of the device.

Normally, current will not flow between the emitter and collector of the transistor unless the base is biased with a voltage that overcomes it's forward voltage drop. Rather than connecting a base terminal, the base material is windowed and made bigger in a photo-transistor, so extra carries are created in the base region when it is exposed to light. These extra carries in the base as a result of light, open up the channel allowing current to flow between emitter to the collector.

The current that flows is proportional to the amount of light falling on the photo-transistor base window allowing the photo-transistor to be used as an optical sensor.

Step 31: Photo Transistor Circuits

Since the photo-transistor allows current to flow based on the light levels, we must convert this into a voltage to read it in a micro-controller. The easiest way is to make this part of the potential divider circuit. The current will cause a voltage drop over the resistor and we can measure and calibrate this for our application.

There are two ways to use a photo-transistor, as an amplifier using the analogue input, or as a switch by saturating it and using the digital input. Either way it's state can be determined with a simple analogue or digital input command on the micro such as

int thermistor = analogRead(A1);


const int D1 = 1;<br>pinMode(D1, INPUT);

depending on the application.

Step 32: Sensor Input Sections

The image shows a potential divider circuit and the different input sections for the different sensors described in this Instructable.

Notice the similarities in the micro-controller input sections and the potential divider. One of the two resistors in a potential divider is replaced by either:

  • a resistive analogue sensor such as a thermistor
  • contact switches from a digital sensor such a water float switch
  • a capacitor from a water level or touch sensitive sensor
  • a semiconductor-based photo-transistor optical sensor
  • a parasitic resistor for 1-wire or i2c based sensors
  • removed entirely for a magnetic based hall effect sensor

But they still all have similar circuit configurations, a two terminal component on the top that normally connects to a supply voltage, a middle connection to the micro-controllers and a two terminal component at the bottom that connects to ground.

Step 33: Abstracting the Physical Layer

Abstraction in software is used to generalize processes by representing only the essential features without including the background details. It allows software to be modular, reusable and scalable.

The physical input interface to a micro-controller can be abstracted and generalized with the schematic shown above where either a switch, sensor, electronic component or other electrical signal can be connected to any of the terminals reducing the need for multiple external sensor boards.

Step 34: Scaling Interface Circuits

And it extends to the other micro-controller input pins making it a scalable way to abstract the IoT physical layer.

Step 35: V1.3 Controller

The v1.3 controller board is an Arduino based standalone board that abstracts the physical layer by generalizing the sensor inputs used.

It assumes that only three kinds of physical input come to a micro-controller

  • Signals that vary between the supply voltage Vcc and ground (Analogue signals)
  • Signals that are either the supply voltage or ground (Digital data)
  • Signals from intelligent sensors that require custom timing (streaming sensors eg UART, i2c. etc)

Step 36: V1,3 Controller Parts List

The v1.3 smart controller kit bom is shown

Step 37: Adding Resistors

We begin by adding resistors including some generic resistors for the sensor chains in the bottom section of the board

  • a 4.7k ohm parasitic resistor for 1 wire sensors
  • 3 10k pull-down resistors for digital sensors
  • 2 10k top resistors for analogue sensor potential divider circuits
  • 1 without any resistors for a sensor that produces voltage levels of its own

Step 38: Adding LEDs

These are used for indicating the status of the relay drivers.

Also add the micro-controller 16Mhz crystal.

Step 39: Adding the IC Socket

Next, add the IC socket for the standalone Arduino Atmega 328 chip

Step 40: Adding Transistors

We never covered these in the sensor interface Indestructible, but the 4 open collector transistor circuits in the output stage are used for controlling and driving loads such as relays.

Step 41: Headers and Pins

Next, we add the PCB headers and sensor connection points.

Step 42: Adding the Atmega Chip

Next, we add the micro-controller Atmega 328 chip.

An Arduino UNO or programmer such as the ISPTiny can be used to program the chip with the correct firmware that can be found here

Step 43: Wiring Sensors

Sensors are normally either passive or active. Passive sensors don't use power and usually have 2 connections a signal connection and a ground connection. Active sensor use power and have Vcc or other power supply connected to them as well as the signal and ground connections. Depending on the data types active sensors have 3 or 4 connections as there could be 2 data lines. Using heat shrink tubing makes for safe wiring as seen with the float switch sensor connections.

Step 44: Connecting a Digital Sensor

The float switch contacts are connected to a reed switch which is either open or closed depending on the position of the magnetic float. This is connected to a digital connection with a pull-down resistor as shown

Step 45: 1-Wire Temperature Sensor

The sensor and the micro-controller communicate by exchanging streams of 1's and 0's. Special timing is required so a specific pin is dedicated to 1-wire sensors. In this case, the 4.7k parasitic resistor is used on the pull up position. Connecting a one wire temperature sensor is shown. Multiple 1-wire sensors can be connected to the same pin in parallel.

Step 46: Connecting an Analogue Sensor

A light depend resistor sensor is passive and connects directly to any analogue pin to complete a potential divider circuit with the resistor on the pull up position.

Step 47: A Digital Analog Sensor

A water leak sensor is made of contacts weaved close by one another which are normally an open circuit until water drops from say a leak complete the circuit.

This senor will work as both a digital sensor or analogue sensor. If the water is sufficient it will behave as closed circuit and can be used as a digital sensor. But at the same time, the resistance changes bases on the amount of water on the sensor in which case it can be used as an analogue sensor where different thresholds of leaks can be determined.

In this example, it is used as an analogue sensor and connected to an analogue potential divided pin as shown.

Step 48: Polling the Sensors

This is the design of the first and only sketch I have written. It polls all the sensor outputs and returns a JSON string. It also listens for relay commands in the background.

The output from the v1.3 board every couple of seconds is a JSON string with raw values read from every pin on the board whether it has a sensor or not.


The code to produce this looks something like this

loop() { 

Step 49: Adding a Micro-Computer

If the output from the micro-controller is connected as console input to a Linux computer, then the output from the v1.3 controller can be used as a file by Linux for reading sensors as well as writing to send commands to the micro-controller. This means we can use all the Linux tools on the micro-controller to give this setup super powers by scaling the abstracted generalized designer further.

Here we can examine the pin strings for errors as well as respond to critical things such as leaks. If there are no problems we can append Linux data to the data string before sending the JSON object for further processing and visualization to remote database servers.

The new JSON object could for instance have identification information, say like a board name, timezone information as shown


Step 50: Adding Relays

Finally, some applications call for responding physically to data that we read from sensors. In this case, we need to interface say actuators or larger loads than the micro-controller can handle. This can be done directly with the open collector transistors on the v2 controller board or by using the transistor to drive relay to control say ac main's loads.

The v1.3 controller firmware is listening for commands on the serial input. To control the relays one sends the following instructions from the Linux micro-computer to the micro-controller.

relay01on or relay01off
relay02on or relay02off
relay03on or relay03off
relay04on or relay04off

Step 51: An Application

How about an Iinstructaable

Electronics Tips & Tricks Challenge

Runner Up in the
Electronics Tips & Tricks Challenge