Electronics is the art of controlling electron flow.

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 science principles and electrical circuitry – the path to full stack IoT engineering.

Technology changes, basics don’t.

Electron Flow

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 – in essence, it is the ability to become a conductor or not that allows the control of electron flow in electric circuitry using semiconductor materials.

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.

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.

Resistive Sensors

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.

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.

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.

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.

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 output 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.

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

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.

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.

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.

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)

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

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.

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;
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);

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).

In the circuit shown below, “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, D3 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.

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.

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.

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.

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);

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);

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] = Serial2.read();
inData_TDS[index] = '\0';
char* string_EC = strtok_r(inData_TDS, ",", &p);
* string_EC = strtok_r(inData_TDS, ",", &p);
EC_val = atoi(string_EC);

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)

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

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.

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.

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;


Photo Transistors

Semiconductors 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 semiconductor 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 the 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.

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.

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.

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.

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