Byte Tank

Pedro Lopes Blog

Inside the Box: Everything I Did With an Arduino Starter Kit

Earlier this year I saw a Tech Ingredients episode where a laser gimbal automatically tracks drones and shoots them down. I was fascinated by their motion control mechanism, specially the usage of a PI Controller, a high-frequency clock Teensy microcontroller, and their integration with custom hardware and a machine vision powered tracker.

Soon after I was researching the underlying electronics and how to experiment upon their concepts. The most obvious microcontroller to drive these would be an Arduino, but several recommendations pointed towards acquiring a kit rather than a single microcontroller, and the Elegoo Arduino Uno R3 Starter Kit seemed the best.

The kit contains over 200 components and an extensive guided tutorial, which I’ve completed (except for the last section using an extra expansion shield). In this article, I’ll go through the highlights of this journey, delightful deviations along the way, and exploration of core electronics concepts. Let’s dive in!


LEDs

Hello World: Light up a LED

I’ve been involved with electronics in different ways throughout my life, but surprisingly I hadn’t yet done its Hello World equivalent, which is to light up a LED. This simple exercise it by itself incredibly interesting that opened a series of questions:

  • Q: Why is a resistor needed? A: High current and increased temperature damage its delicate heterojunction structures, which eventually cause it to burnout
  • Q: What happens if the polarity is inverted? A: Similar to a normal diode, current will not flow and the LED will not light up. As long as this reverse power is not high, the LED will not burn and can still be used with correct polarity afterwards
  • Q: How to interpret its data sheet? A: There are several interesting aspects its datasheet, like the LED’s wavelength curve, operating current and voltage, etc

RGB LED [Code]

RGB LEDs package a red, green and blue LED inside it that can be controlled independently, allowing for wide range color representation using three pulse width modulation (PWM) outputs from the Arduino.

PWM is a technique used to control the average power delivered to an electrical device by varying the width of pulses in a digital signal, which when done fast enough in a visual output such as a LED, is perceived to the human eye as being of a smooth continuous amplitude, instead of a stream of single bursts.

Progressively changing the colors of a RGB LED

8 LEDs controlled via 74HC595 [Code]

We can attach an 74HC595 IC to extend the number of outputs possible by an Arduino, at the cost of some latency.

When writing the desired values for each of the inputs into 74HC595, they won’t be externalized until its latch is activated. Once the latch is triggered, all of the stored inputs will be externalized in one go. Very similar purpose of double buffering in video. A flicker free experience.

We are essentially controlling a piece of very limited external memory.

8 LEDs controlled via 74HC595

Smooth LED intensity fade out using capacitors

Capacitors are essentially energy stores (i.e. batteries) that with consistent charge and discharge times. By placing a condenser (or two, as in this video, so that their capacitance is summed up) in parallel with a LED, when powering the circuit both the LED immediately lights up and the condenser(s) charge in tandem. Once the main power source is removed, the condenser(s) start to smoothly discharge into the LED, creating a smooth fade out of their intensity.

Smooth LED intensity variation using Capacitors

Display

One Unit Segment Display: Digit Countdown [Code]

We can control this single unit seven segment display at the segment level, and in this example we sequentially write a set of segment sets that we perceive as digits.

Digit Countdown

One Unit Segment Display: Custom Patterns [Code]

We can also create any patterns, in whichever sequence and timing we so desire. Here are three examples of some custom patterns.

Rotation Pattern

Figure Eight Pattern

Alternating Pattern

Four Unit Segment Display: Same Character for All [Code]

Expanding on the above, if we write the same patterns as above on a four unit segment display, we see these replicated on all units.

Same Character for All

Four Unit Segment Display: Distinct Characters [Code]

In order for each of the units to present their specific segment pattern, we need to write the pattern and then select which of the units should have this pattern written to, wait for a short amount of time, and then move to the next unit, where we will do the exact same thing, only this time selecting the unit(s) that should have this pattern written.

Distinct Characters

LED Matrix: Scrolling [Code]

This LED Matrix accepts an explicit bitmap, where each of the pixels is either enabled or disabled. To achieve a scrolling effect we set an offset based on value received via the potentiometer.

Scrolling through a bitmap

LCD Display: Showing a Long String [Code]

The scrolling effect is achieved by leveraging a functionality from the LiquidCrystal library. Here we are using a string of normal characters, but custom characters can also be used.

Scrolling through a long string

Sound

Buzzer

From the guide: “We should be careful not to use the UNO R3 board analogWrite() function to generate a pulse to the active buzzer, because the pulse output of analogWrite() is fixed (500Hz)”. I’ve used analogWrite(), and this is the result:

Varying the pitch of a buzzer

Making the buzzer sound like an 8-bit engine [Code]

By adjusting the frequency in which the buzzer is discretely triggered, we can achieve a perceived effect similar to PWM used above for controlling LEDs intensity, only this time to allude to a certain sound pitch, which in this case is quite similar to the sonority from older computer / console games.

“8bit” engine sound using a buzzer

Sensing Sound [Code]

I’ve burned the on-board LED (13) while voice fiddling with this integration, since one of the dupont wires touched a wrong spot of the board while going through this.

The red LED represents audio peaks, the yellow LED represents audio troughs.

Detecting snapping of fingers and voice

Spatial Sensors

Tilt ball switch [Code]

This component consists of a very conductive sphere that is free to move inside the component’s cylindrical shape. One face of the cylinder conducts electricity, and the opposite does not.

Tilting the component to elicit its change of state

Ultrasonic sensor to measure distances [Code]

I wondered why an external module was required to calculate distances, so I’ve implemented an algorithm from scratch that took into account the speed of sound and the time taken by an ultrasonic pulse to be received back by the sensor. I’ve validated the measurements using a real life ruler, and they were actually accurate! No external code modules required.

Distance measurement using custom algorithm built from scratch

Passive infrared sensor (PIR) Motion Sensor [Code]

This is a sensor commonly used to detect movement from heat emitting, like people, and then trigger a side-effect, such as a hall light. Its output is a simple binary HIGH or LOW.

Detecting motion via PIR sensor

MPU-6050: Accelerometer and Gyroscope Plotting [Code]

Used the Arduino’s Serial Plotter Tool to visualize the inputs from the MPU-6050 module that bundles an accelerometer, gyro and temperature sensor.

Accelerometer and Gyroscope Plotting

MPU-6050: Interrupt signals [Code]

Going through the datasheets of the gyro module, I’ve noticed that the module could be commanded to dispatch an interrupt signal whenever a certain threshold of movement was detected. This could be useful for low power systems for example, where this interrupt would signal that relevant movement data is starting and the main controller should be fully active.

The objective of this experiment was to make the blue LED blink whenever the gyro was disturbed, but this resulted in a mostly unpredictable output, where the root cause is likely to lie on the incorrect combination of commands needed to set up the module. Further exploration would be needed here.

Attempting to get an interrupt signal when movement starts

Environmental Sensors

Light intensity measurement via photoresistor [Code]

A photoresistor is a light-sensitive resistor whose resistance decreases when light falls on its surface, if we place wire in connected from one of Arduino’s analog inputs between the photoresistor and another fixed value resistor, we are able to detect the resulting voltage caused the photoresistor’s variable resistance.

Light intensity shown on LCD display

Temperature measurement [Code]

With the exact same setup as above (save from the slight tweak of the script), by replacing the photoresistor with a thermistor (which yet another variable resistor, only this time changing its resistance based on temperature) we are able to measure ambient temperature, which I manipulate by using my hand’s warmth and the cooling it off by blowing air into the thermistor.

Temperature shown on LCD display

Water level sensor [Code]

This consisted of some nervous plunging of the water level sensor into a tea mug, near my computer 😬

Water level sensor change as it is further submerged under water

Actuators

BJT Transistor driven DC motor: Controlled via On/Off Button [Code]

The Arduino is made to drive logical circuits with low output currents, so when we want to control a high power circuit, we want our Arduino microcontroller to control the “valve”, but not the “pipes” themselves. This is a perfect application for a transistor (or relays, as we’ll see below), where the transistor functions as a “valve” that either lets current flow through freely, or block it completely.

The kit comes included with two models of NPN bipolar junction transistor (BJT) transistors: the PN2222 and S8050. Both are often used interchangeably (as seen in this video), but the PN2222 has a higher voltage rating for collector-to-emitter voltage (60V vs 25V), which in this case is not relevant, since we are not surpassing the 5V barrier. In these, the base is the “valve”, and collector and emitter function as the “pipes”.

Note here I am not using a flyback diode to protect the circuit from back EMF voltage spikes caused when the DC motor is switched off, which is not the wisest idea when performing multiple tests. I was not aware of that effect at the time, and fortunately no harm was done.

DC Motor controlled via On/Off Button

BJT Transistor driven LED and DC motor: Controlled via Potentiometer [Code]

Same setup as above, only this time we are driving a LED instead of a DC motor.

LED controlled via Potentiometer

DC motor controlled via Potentiometer

L293D driven DC Motor using battery power [Code]

L293D is a neat IC that packs inside everyone one needs to drive inductive loads such as relays, solenoids, DC and bipolar stepping motors, along with bidirectional drive and overcurrent and kickback protection (so no flyback diode needed).

Notice that when attempting to drive the DC motor at low power it struggles to start its rotation, but once power is increased of a slight nudge is given, it quickly starts to rotate freely.

L293D driven DC Motor using battery power

L293D + Relay driven DC Motor [Code]

Relays are larger and have slower switching speeds when compared to transistors, but handle higher currents and voltages and provide good electrical isolation.

As a fun fact, in older cars, “tick-tock” heard when activating the turn signal are actually the sound of the respective relay closing and opening the circuit to light up the blinker. Those relays are very similar to the one used here, and a similar noise can be heard in the video, as the relay closes and opens the circuit that powers the DC motor

L293D + Relay driven DC Motor

Resistor and Capacitor (RC) circuit for delayed triggering

When setting up a Resistor and Capacitor (RC) circuit, we can take advantage of its predictable charging curve to delay the activation of a transistor, which in turn can activate another set of components. Depending if the transistor is a BJT (current-controlled) or a MOSFET (voltage-controlled), they would have different current or voltage thresholds at which they allow current to flow between the collector and emitter (BJT), or drain and source (MOSFET).

In this case, a bipolar junction transistor (BJT) has its base connected to RC circuit, and upon its activation a LED and/or a DC motor are activated. Notice that the DC motor either does not have enough power to start, or barely has a delay once a smaller resistor is placed on the RC circuit, which I think to be caused by having low capacitance capacitors, and not having the ideal resistor being used on RC circuit, but this would warrant further exploration and a deeper understanding of the problem.

Delayed LED lighting via RC Circuit + BJT Transistor

Delayed LED lighting and DC Motor via RC Circuit + Single BJT Transistor

Delayed LED lighting and DC Motor via RC Circuit + Two BJT Transistors

Servo Motor controlled via Potentiometer [Code]

Servo motors are used in applications requiring precise and controlled movement, where the motor’s position, speed, and torque need to be accurately controlled. In this example a button is used to switch between the state where the servo’s position is synced position defined by the potentiometer, and the state where a default servo motor position is set.

Notice as well how the slight voltage noise created when manipulating the detached potentiometer input wire, and the effect it has on the servo that is attempting to sync with these received values.

Servo Motor controlled via Potentiometer

Stepper Motor: Automatic Control [Code]

The stepping motor is a clever piece of engineering that enables precision movement without the need of external feedback.

In this setup the motor is controlled fully by an automated script, and since the 9V battery was starting to die, it was powered via power adapter.

Stepper Motor: Automatic Control

Stepper Motor: Rotary Encoder Control, using ELEGOO script [Code]

To the above we add a rotary encoder to send precise commands of how much we want the stepper to move. This rotary encoder is the same you’ll find in several appliances such as mouse wheels, car radio knobs and washing machines.

Notice that the movement is quite jerky, and no matter how much we move the rotary encoder, only the most recent movements are actually accounted for.

Stepper Motor: Rotary Encoder Control, using ELEGOO script

Stepper Motor: Rotary Encoder Control, with Extra Precision [Code]

To fix the above behaviour, this script takes into account all the movements from the rotary encoder to establish a target rotation angle that every cycle the stepper motor is correcting itself towards.

Notice that in the beginning of the video the two LEDs are lighting up as the rotary encoder is manipulated, so that we can see which are the signals captured by our script. These signals consist of a predictable gray code sequence that lets us perceive with high accuracy whether it is rotating right or left.

Once the two demonstration LEDs are disconnected, we’ll have signals coming through our Arduino inputs, that we interpret leveraging the above concepts, plus we also make sure to trigger device interrupts not only for one of the inputs (as in the script above), but for both inputs, so that we can capture all movements.

Stepper Motor: Rotary Encoder Control, with Extra Precision

Stepper Motor: IR Remote Control [Code]

Combining the IR sensor and remote above, we can also control this stepper motor using this remote control mechanism.

Stepper Motor: IR Remote Control

Communication Interfaces

How Arduino Keypad Works under the hood, from scratch, without extra libraries

One of the peripherals you can provide as input to Arduino is a 16 button keypad that provides a useful human interface component for microcontroller projects.

This keypad module comes included in the Elegoo UNO R3 Starter Kit, which also comes with its respective tutorial and library that helps facilitates its usage.

In this video we will code from scratch an implementation that will use this keypad module, without using extra libraries, and we will go through the respective concepts and circuits, including how pull-up resistors work (which are accessible via INPUT_PULLUP)

How Arduino Keypad Works under the hood

Supporting code:

Note that the code resorts to a fair amount of duplication, but this is explicitly show how the entire mechanism works, without occluding via abstractions

IR Signal Replication [Code]

While exploring how common infrared communication protocols are used in every day appliances, I wondered if it was possible punch in custom light pulses via a red LED source that could be interpreted as valid signals by the IR receiver, and started by pulsing it in 25ms intervals in order comply with the 38khz signal modulation expectation on the IR receiver (1 second / 38000 Hz ~= 25ms).

Turns out this would never work with a normal red LED, since its wavelength sits around the 640nm peak, whereas we would need a 900nm to 1000nm wavelength for an IR receiver to pick that signal.

In this attempt, I am comparing the continuous pulsing by the red LED vs the pulsing generated by a standard IR remote. An interesting follow up would be to attempt the same setup, but with a IR LED emitter instead.

IR Signal Replication Attempt

RFID Card Reader [Code]

This video shows what the MIFARE content dump from the two cards included with the kit, but the setup is able to read minimal information from other sources, like credit cards or electronic passports.

Note that this module reference voltage works best when connected to the Arduino’s VIn output, instead of Arduino’s 3.3v power output.

Content dump of the information read from the two cards included with the kit

Joystick [Code]

This joystick module is essentially the same used in several game controllers, and its usage is fairly straighforward using an Arduino.

Joystick module demonstration

Communication and Storage

Transmitting Serial Information via TX output [Code]

This might come as obvious to many, but only after using Serial.print() on different Arduino scripts as a debugging mechanism, did I realize that this command actually sends structured information not only to the host via USB (computer), but also via Arduino’s TX output.

This video/script are very simple: they write very long strings and individual bytes to the serial interface, using a very low baud rate, so that their individual bits can be roughly seen upon the right yellow LED that is attached to the TX output. The left green LED stays enabled before we start sending commands to the serial interface, and is disabled once the writing phase is completed.

Notice that even after all writes were committed, there are still bits flowing through the TX output. This goes on until Arduino’s internal serial communication buffer is completely flushed.

Left green LED stays enabled during writing phase. Yellow LED represents single bits in the TX communication stream

Writing individual bits and feeding them back via RX input [Code]

Building up on the above, if we write individual bits by carefully timing the a normal pin output’s LOW and HIGH to comply with the UART standard to form 8 bit packets, feed these through a wire to the Arduino’s Rx pin, read the resulting serial communication receive buffer, and then finally write these contents into the serial port, we are able to see these logged into the serial monitor.

This was one of the most 🤯 while fiddling around with the Arduino.

Writing individual bits and feeding them back via RX input

Sending information from the host to Arduino [Code]

Using the Serial Monitor, we can easily send packets of information to the Arduino via Serial communication. In this script, Arduino reads from the serial communication buffer an enables or disables a LED if the corresponding received information is a zero or a one.

Sending information from the host to Arduino

Using internal EEPROM to persist information [Code]

Building on the above setup, we integrate ATmega’s integrated EEPROM to persist information. This means that even after a power outage that information is still available, as seen in the video below.

Using internal EEPROM to persist information

Sending information from the host to Arduino + 74CH95 to drive LEDs [Code]

We can attach an 74HC595 IC to extend the number of outputs possible by an Arduino, and do the same as above but for extra outputs. The setup supports 7 different LEDS, but only 3 are shown in the video, and for this specific example there is no real gain from using 74CH95 IC, other than demonstrating its usage.

Serial read side effects using 3 LEDs and 74HC595

Time

Real Time Clock (RTC) Module Square Wave Output [Code]

I was curious about the RTC module’s square wave output, and found a YouTube video on how to send a command to the module that forces the square wave pin (SQW) to output a 1Hz square wave, meaning that the cycle of this wave repeats every second.

In the video, this signal is first connected to a LED, which leads it to blink every second, and then the output is directed towards Arduino’s pin 8, thus showing this cycle’s result on the serial output.

Square Wave Output visible first on LED, then on serial output logs

Integration

Putting it all together: the Timer [Code]

The time project is the opus maximus of the provided tutorials provided by Elegoo, but there were components which were not working directly, namely the interrupt library, so I’ve adapted the provided example to use the built in Arduino interrupt library, and changed some of the connections, leading to a beautiful culmination of all the the lessons from above.

Timer Integration