Tutorial: How to use the GY-521 module (MPU-6050 breakout board) with the Arduino Uno

GY-521 breakout board with an MPU-6050 MEMS.

GY-521 breakout board with an MPU-6050 MEMS.

The GY-521 module is a breakout board for the MPU-6050 MEMS (Microelectromechanical systems) that features a 3-axis gyroscope, a 3-axis accelerometer, a digital motion processor (DMP), and a temperature sensor. The digital motion processor can be used to process complex algorithms directly on the board. Usually, the DMP processes algorithms that turn the raw values from the sensors into stable position data. This tutorial gives only a brief introduction to the GY-521/MPU-6050. In particular, it is shown how to retrieve the raw sensor values. The sensor values are retrieved by using the I2C serial data bus, which requires only two wires (SCL and SDA). If you plan to use the full range of features or require reliable and stable position data, then I recommend to have also a look at ready-to-use libraries. Please follow this link to find an excellent library with many examples: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– Breadboard [Search on Aliexpress | Amazon]
– GY-521 module [Search on Aliexpress | Amazon]

Wiring scheme:
The GY-521 breakout has eight pins:

  • VCC (The breakout board has a voltage regulator. Therefore, you can connect the board to 3.3V and 5V sources.)
  • GND
  • SCL (Serial Clock Line of the I2C protocol.)
  • SDA (Serial Data Line of the I2C protocol.)
  • XDA (Auxiliary data => I2C master serial data for connecting the module to external sensors.)
  • XCL (Auxiliary clock => I2C master serial clock for connecting the module to external sensors.)
  • AD0 (If this pin is LOW, the I2C address of the board will be 0x68. Otherwise, if the pin is HIGH, the address will be 0x69.)
  • INT (Interrupt digital output)

Wiring layout:

Fritzing file that shows how to wire the GY-521 breakout board to an Arduino Uno.

Fritzing file that shows how to wire the GY-521 breakout board to an Arduino Uno.

In this tutorial we will make use only of the first four pins: VCC, GND, SDA, and SCL. First, we connect the module’s VCC to the Arduino’s 5V pin. Then, the module’s GND is connected to one of the Arduino’s GND pins.
Next, we have to set up the I2C connection between the module and the Arduino. Most Arduino Uno variants have an SCL and SDA pin. If you have such an Arduino Uno, just connect SCL to SCL and SDA to SDA.
If you can’t find an SCL and SDA pin on your Arduino, you have to use other pins. Unfortunately, you cannot use just any pin. For each type of Arduino, SCL and SDA are tied to different pins:

  • Arduino Uno, Arduino Ethernet, Arduino Nano: A4 (SDA), A5 (SCL)
  • Arduino Mega2560: 20 (SDA), 21 (SCL)
  • Arduino Leonardo: 2 (SDA), 3 (SCL)
  • Arduino Due: 20 (SDA), 21 (SCL)

So, if you have an Arduino Uno without SCL and SDL pins, then connect the Arduino’s A4 pin to the module’s SDA pin. Next, connect the Arduino’s A5 pin to the module’s SCL pin.

Example source code:

We make use of the Arduino platform’s in-built library (Wire) to establish an I2C connection between the Arduino Uno and the GY-521 sensor. At the beginning of our source code, the Wire library’s header file is included. Next, we define and declare some variables.
Then, a convert-function is defined. The convert-function makes sure that all sensor values have the same width when they are printed out to the serial monitor later.
In the setup function, a serial connection is established. Moreover, we start our first I2C transmission to the GY-521 board to wake it up from sleep mode.
In the loop function, seven sensor values (3x accelerometer, 1x temperature, and 3x gyro) are requested from the GY-521 module. The MPU-6050 has many registers which can be read. Fourteen of these registers contain the sensor values that we need. As a first step, we tell the GY-521 module where we are going to start reading (“Wire.write(0x3B);”). Then, we request to read 14 registers (“Wire.requestFrom(MPU_ADDR, 7*2, true);”). If you are wondering, why 14 registers are read instead of 7 registers, the reason is quite simple: Each sensor value has a size of 2 byte. As each register has a size of one byte, a single sensor value must be retrieved by accessing two registers. The first register contains the so-called “high byte” and the second register contains the “low byte”. Next, all values are retrieved and printed out to the serial connection. At the end of the loop function, a delay of one second is added in order to avoid flooding the serial monitor with messages.

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de

#include "Wire.h" // This library allows you to communicate with I2C devices.

const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.

int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data
int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data
int16_t temperature; // variables for temperature data

char tmp_str[7]; // temporary variable used in convert function

char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor.
  sprintf(tmp_str, "%6d", i);
  return tmp_str;
}

void setup() {
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board)
  Wire.write(0x6B); // PWR_MGMT_1 register
  Wire.write(0); // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
}
void loop() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40]
  Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active.
  Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers

  // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
  accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
  accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
  accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
  temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
  gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
  gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
  gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)

  // print out data
  Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x));
  Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y));
  Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z));
  // the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30]
  Serial.print(" | tmp = "); Serial.print(temperature/340.00+36.53);
  Serial.print(" | gX = "); Serial.print(convert_int16_to_str(gyro_x));
  Serial.print(" | gY = "); Serial.print(convert_int16_to_str(gyro_y));
  Serial.print(" | gZ = "); Serial.print(convert_int16_to_str(gyro_z));
  Serial.println();

  // delay
  delay(1000);
}

If the code is compiled and transferred to the Arduino Uno, you should see the sensor values in the serial monitor of the Arduino IDE. Moreover, when the GY-521 board is rotated or moved, the sensor values should change according to the movement.
As mentioned before, this is basically a “hello world program” for the GY-521. if you plan to use the board more seriously, I highly recommend to dig deeper into the possibilities of the MPU-6050 MEMS.

If the GY-521 is moved (left hand side), the sensor values should change accordingly (right hand side).

If the GY-521 is moved (left hand side), the sensor values should change accordingly (right hand side).

Video Tutorial:

Tutorial: How to control a servo motor (SG90) with the Arduino Uno

Typically, servo motors are a combination of four things: a conventional DC motor, a set of gearings, a potentiometer, and a control circuit. Among these four things, the potentiometer acts as a position sensor. As a result, servo motors can be controlled very precisely. In particular, a command can be sent to the servo so that the servo’s shaft rotates to a specific position. However, the disadvantage of these servos is that the rotation range is limited (e.g. between 0 and 180 degrees). Nonetheless, servo motors are very useful if a projects requires a motor with a precise control and awareness of its current position.

The SG90 micro servo motor. In the background is a rotary angle sensor module and a potentiometer. Both can be used to control the servo motor.

The SG90 micro servo motor. In the background is a rotary angle sensor module and a potentiometer. Both can be used to control the servo motor.

The SG90 is such a servo motor that can rotate approximately 180°. Moreover, is is very small and lightweight (Weight: 9g; Dimension: 22.2 x 11.8 x 31 mm). In this tutorial, it is shown how to control the SG90 servo motor. In order to control the motor, a so-called rotary angle sensor module is used. This module is nothing more than a conventional potentiometer combined with a knob. Therefore, it can be simply replaced by almost any potentiometer, since it is used here only for convenience reasons.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– Mini breadboard [Search on Aliexpress | Amazon]
– Rotary angle sensor [Search on Aliexpress | Amazon]
– Potentiometer (in alternative to the rotary angle sensor) [Search on Aliexpress | Amazon]

Pin layout:

A scheme that shows how to wire the micro servo motor SG90 to an Arduino Uno. In order to control the SG90, a rotary angle sensor is used.

A scheme that shows how to wire the micro servo motor SG90 to an Arduino Uno. In order to control the SG90, a rotary angle sensor is used.

First, we connect the SG90 servo motor to the Arduino Uno. Both, the servo and the rotary angle sensor need a voltage supply. Since the Arduino Uno has only one 5V pin, we use a breadboard to split the 5V signal. The Arduino’s 5V pin is connected to a breadboard. Then, the servo’s red wire is connected to the breadboard (same column as previous pin). Next, the brown wire of the SG90 must be connected to one of the Arduino’s GND pins. In order to control the SG90 servo, PWM signals (Pulse Width Modulation) must be sent through the yellow wire. In this tutorial, digital pin 9 of the Arduino is used for this task and, therefore, wired to the SG90’s yellow pin.
Following, we have to wire the rotary angle sensor to the Arduino. The sensor’s left pin is the ground which must be connected to one of the Arduino’s GND pins. The pin in the middle is the VCC pin, which must be connected to breadboard (same column as the other two pins). Finally, the sensor’s SIG pin must be connected to one of the Arduino’s analog input pins. Here, I make use of analog pin A0. If a potentiometer is used instead of the rotary angle sensor: Typically, the outer pins of the potentiometer must be connected to the power supply (GND and 5V pin of the Arduino). The pin in the middle is the signal pin which corresponds to the sensor’s SIG pin and must be connected to an analog input pin (e.g. A0).

Example source code:
Luckily, the Arduino IDE has already a built-in servo library. In order to use this library, we have to include its header file. Next, we define two pins: digital pin 9 for the servo motor and analog pin A0 for the rotary angle sensor (or potentiometer). Then, a servo object is created that will be used to control the servo motor. Subsequently, two variables are defined. The first one is used to store the values retrieved from the sensor/potentiometer. The second variable is the rotation value that will be sent to the servo motor.
In the setup function, we attach digital pin number 9 to the servo object. The servo object is now fully initialized and ready to control the servo.
In the loop function, we read the analog value of the rotary angle sensor’s knob (or value of the potentiometer). As the Arduino’s analog-to-digital converter will map the voltage to values between 0 and 1023, we have to remap these values to an rotary angle value that is supported by our servo motor. Since the SG90 supports approximately 180°, we map the value two values between 5° and 175°. According to my experience, the SG90 does not sound very “healthy”, if the full range of 180° is used. Therefore, we subtracted 10° in order to avoid damaging our servo motor. After calling the map-function, the resulting value is used to let the servo turn its shaft. At the end of the loop function, we add a delay of 20ms to give the servo some time to turn its shaft.


// (c) Michael Schoeffler 2017, http://www.mschoeffler.de

#include "Servo.h"

#define PIN_SERVO 9
#define PIN_KNOB A0

Servo servo; // creates servo object to control the SG90 servo

int value_knob = 0; // will be used to store the value of the potentiometer/knob
int value_servo = 0; // will be used to control the servo => should be between 5 and 175 degrees

void setup()
{
servo.attach(PIN_SERVO); // assigns pin 9 to the servo object
}

void loop()
{
value_knob = analogRead(PIN_KNOB); // reads value of the knob/potentiometer. Return value will be between 0 and 1023.
value_servo = map(value_knob, 0, 1023, 5, 175); // will map knob value range to servo value range
servo.write(value_servo); // shaft of servo will start to rotate. value_servo is interpreted as an absolute position.
delay(20); // give servo some time to rotate
}

After transferring the program to the Arduino Uno, you should be able to rotate the servo’s shaft.

A SG90 servo motor that can be controlled by the knob of a rotary angle sensor.

A SG90 servo motor that can be controlled by the knob of a rotary angle sensor.

Video tutorial:

Tutorial: How to drive the 28BYJ-48 stepper motor with a ULN2003A driver board and an Arduino Uno

A 28BYJ-48 stepper motor connected to a ULN2003A driver board.

A 28BYJ-48 stepper motor connected to a ULN2003A driver board.

A stepper motor divides a full rotation in multiple steps. As a result, a stepper motor can be driven much more precisely than a conventional dc motor. In particular, stepper motors are driven step by step. After having a quick look into the data sheet of a stepper, we know exactly how many degrees correspond to a single step of our motor. With this information, we can precisely turn the rotor of our stepper motor, since we then know how many degrees correspond to a single step.

The 28BYJ-48 is a very cheap stepper motor that often comes with a ULN2003A driver board. Luckily, the Arduino platform has already a built-in stepper library that allows us to control the 28BYJ-48 stepper motor with the ULN2003A driver board. In this tutorial, it is shown how to control the 28BYJ-48 with an Arduino Uno.

List of materials:
– Arduino Nano [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– 28BYJ-48 stepper motor [Search on Aliexpress | Amazon]
– ULN2003A driver board [Search on Aliexpress | Amazon]

Pin layout:

Pin layout that shows how to connect a 28BYJ-48 stepper motor to a ULN2003A driver board and an Arduino Uno.

Pin layout that shows how to connect a 28BYJ-48 stepper motor to a ULN2003A driver board and an Arduino Uno.

Typically, the 28BYJ-48 motor comes with a 5-pin connector that fits to driver board’s connector. The driver board has two pins for the power supply which are labeled GND and VCC. The board’s GND pin must be wired to the Arduino’s GND pin. Accordingly, the board’s VCC pin must be connected to the Arduino’s 5V pin.
Important remark: With this setup, we are powering the motor directly from the Arduino. The advantage is that this is the possible easiest solution for providing power to the motor. However, if the motor consumes too much power, the Arduino can be permanently damaged. If you use a different setup (driver, motor, source code, etc.), make sure that you do not draw more than about 300mA out of the Arduino. If you need more power, just use an external voltage supply for your driver board.
Lastly, the driver board’s IN1, IN2, IN3 and IN4 pins must be connected to the Arduino. In this tutorial, pins 8 to 11 of the Arduino are used (IN1<->8, IN2 <-> 9, IN3 <-> 10, IN4 <-> 11).

Example source code:
In the beginning, we include the header file of the Arduino plattform’s built-in stepper library. Then, we define the number of steps that the motor needs for one revolution. Stepper motors can turn out very complicated, therefore, it is not that easy to look up this number.

For example, you can typically drive stepper motors in different modes and, moreover, they have a specific gear ration. Both have an influence on the number of steps per revolution. Since we drive the motor in the so-called full step mode (control sequence with four steps), each step corresponds to a rotation of 11.25 degrees according to the data sheet. This corresponds to 32 steps per revolution (360° / 11.25° = 32). In addition, the manufacturer specified a gear ratio of 64:1 for this type of motor. Normally, this gear ratio must be multiplied by the 32 steps. If you examine the 28BYJ-48 in more detail, it turns out that the actual gear ratio is approximately 63.68395:1. Therefore we set the final number of steps to 2038 (32 * 63.68395=2037.8864).

Next, we initialize the stepper. The first parameter of the Stepper constructor is the number of steps. The other parameters correspond to the Arduino’s pins that we used to connect the ULN2003A driver board.

In the loop function, we start to drive the motor. First, we set the speed to one revolutions per minute . Next, we tell the stepper motor to do 2038 steps. As one revolution corresponds to 2038 steps, the motor’s shaft should move a full revolution in approximately one minute. Next, we set a delay of one second. Then, we do the same thing again. But this time, we set the speed to 6 rounds per minute and move the shaft in the other direction (by setting a negative number of steps). As the the shaft moves six times faster now, the motor should finish a full revolution in about 10 seconds (60s/6=10s).

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de

#include <Stepper.h>

#define STEPS 2038 // the number of steps in one revolution of your motor (28BYJ-48)

Stepper stepper(STEPS, 8, 10, 9, 11);

void setup() {
  // nothing to do
}

void loop() {
  stepper.setSpeed(1); // 1 rpm
  stepper.step(2038); // do 2038 steps -- corresponds to one revolution in one minute
  delay(1000); // wait for one second
  stepper.setSpeed(6); // 6 rpm
  stepper.step(-2038); // do 2038 steps in the other direction with faster speed -- corresponds to one revolution in 10 seconds
}
The stepper motor is driven by the ULN2003A driver board. The board's LEDs show the current control sequence state.

The stepper motor is driven by the ULN2003A driver board. The board’s LEDs show the current control sequence state.

Video Tutorial:

Tutorial: How to use the HC-SR505 PIR sensor with the Arduino

HC-SR505 PIR Sensor

HC-SR505 PIR Sensor.

PIR (Pyroelectric InfraRed) sensors measure infrared (IR) light that is radiating from objects in the detection area. The HC-SR505 is such a sensor. It very easy-to-use as it already delivers a HIGH signal if something is moving in the detection area. This HIGH signal lasts about 8 seconds, which is sometimes seen as a disadvantage. Unfortunately, this disadvantage can not be solved on software level, i.e. adding a workaround to the source code does not work (I’m almost 100% sure that this can only be solved by replacing one of the capacitors or resistors). The module has an operating voltage between 4.5V and 20V. According to the data sheet, the sensor detects movement up to a distance of 3m. In this tutorial, it is shown how to use the HC-SR505 sensor with the Arduino Platform.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– Breadboard [Search on Aliexpress | Amazon]
– HC-SR505 [Search on Aliexpress | Amazon]

Pin layout

Pin layout used in this tutorial to wire the HC-SR505 PIR sensor to the Arduino Uno.

Pin layout used in this tutorial to wire the HC-SR505 PIR sensor to the Arduino Uno.

In order to wire the SR505 to the Arduino, you need only three wires. The SR505 has three pins which are marked on the back: “-“, “OUT”, and “+”. First, make sure that the SR505 is provided with enough voltage: One of the Arduino’s GND pins must be connected to the SR505’s “-” pin. Next, the Arduino’s 5V pin must be connected to the “+” pin of the SR505.
The remaining “OUT” pin returns either LOW or HIGH, depending on whether something was detected. This pin must be connected to one of the Arduino’s digital pins. In this tutorial, pin #2 is used.

Example source code
The program is very simple. First, a serial connection is opened in the setup function. The serial connection is used later to print the sensor’s state to the serial monitor. Then, pin #2 is declared as an input pin. In the loop function, the state of pin #2 is read. If the pin has a HIGH signal, the message “Movement detected.” is printed. Otherwise, if the pin has a LOW signal, a message is printed indicating that the sensor did not detect any movement. At the end of the loop function, a delay of a second is added to avoid flooding the serial monitor with too many messages.

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de

#define SIGNAL_PIN 2

void setup()  
{
  Serial.begin(9600);
  pinMode(SIGNAL_PIN, INPUT);
}
void loop()  
{
  if(digitalRead(SIGNAL_PIN)==HIGH) {
    Serial.println("Movement detected.");
  } else {
    Serial.println("Did not detect movement.");
  }
  delay(1000);
}

When the code has been compiled and transferred to the Arduino, the serial monitor (“Tools”-> “Serial monitor”) should show the current state of the PIR sensor. You can easily trigger the sensor to detect something by moving your hand above the sensor.

Serial Monitor output sent by the HC-SR505 PIR sensor.

Serial Monitor output sent by the HC-SR505 PIR sensor.

 

Video Tutorial

How to control an LED pixel strip (WS2812B) with an Arduino and the FastLED library

WS2812B modules

On the left is an LED pixel strip which has WS2812B modules on it (30 WS2812B modules per meter). To the right are raw WS2812B modules (front and back).

LED pixel strips are strips which have small LED modules mounted on it. One of these LED modules is the WS2812B which features a cascading port transmission mechanism which needs only a single line.

This means that multiple WS2812B can be cascaded and individually controlled by a single connection for data transmission. Therefore, cascading many WS2812B modules requires only wiring for VCC, GND, and the data transmission. As a result, the WS2812B modules are well suited for LED pixel strips. Today, WS2812B-based LED pixel strips are available in all kinds of variants. Typically, strips can be bought with 30 to 144 WS2812B modules per meter. When having 144 modules per meter, there is almost no space left between the modules. In this tutorial it is shown how to program an Arduino in order to control a WS2812B-based LED strip with the FastLED library. FastLED is a library that allows to control all kinds of LED strips (WS2810, WS2811, LPD8806, Neopixel etc.).

List of materials:
– Arduino Nano [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– Breadboard [Search on Aliexpress | Amazon]
– WS2812B-based LED strip [Search on Aliexpress | Amazon]

Pin layout:

This fritzing file shows a schematic of how to wire an Arduino Nano to the LED pixel strip.

This fritzing file shows a schematic of how to wire an Arduino Nano to the LED pixel strip.

Wiring up a basic setup is very easy, as the LED pixel strip has only three input pins which must be connected. Typically, these input pins represent GND, Vdd 5V, and a data connection. My LED pixel strip has three wires: white (GND), red (Vdd), and green (data). The color of the inputs might differ among manufacturers. Therefore, have a look at the description or datasheet of the LED pixel strip that you bought.
An Arduino can provide enough power to an LED strip with thirty WS2812B modules. For this reason, we can connect the GND pin and the 5V pin directly to the white and red wire, correspondingly. According to some forum entries, you get about 400mA from the Arduino’s 5V pin. Last but not least, we connect the data pin (green wire) to the Arduino’s pin 3. Basically, you can use any pin that supports PWM signals.

Example source code:
As mentioned before, the program utilizes the FastLED library to control the LED strip. At the beginning, the FastLED header file is included. In the setup function, the LED strip representation is initialized. As the FastLED supports many more LED strips (different LED modules, different lengths, etc.), the initialization needs the LED module type, Arduino pin number used for data transfer, color order, reference to an array representing the LEDs, and the number of LEDs. Optionally, a color correction can be set in order to improve the fidelity of the colors.
Next, there is a function which switches off all pixels (“showProgramCleanUp”). This function becomes very useful to “reset” the LED strip.
The example source code contains three different “light programs”. Each light program is implemented as a function. The first program switches on all LEDs in randomly selected colors (“showProgramRandom”). The next program shows a single-colored pixel being shifted from the beginning of the LED strip to the end (“showProgramShiftSinglePixel”). The last program shows how multiple pixel are shifted from the beginning to the end (“showProgramShiftMultiPixel”). In this light program, each pixel has a randomly selected color.
In the loop function, each light program is called twice with different parameters. Before a function call to a light program is made, all pixels of the LED strip are switched off by calling the special program “showProgramCleanUp”.

// (c) Michael Schoeffler 2017, http://www.mschoeffler.de
#include "FastLED.h"

#define DATA_PIN    3
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    30
#define BRIGHTNESS  96

CRGB leds[NUM_LEDS];

void setup() {
  delay(3000); // initial delay of a few seconds is recommended
  FastLED.addLeds&amp;lt;LED_TYPE,DATA_PIN,COLOR_ORDER&amp;gt;(leds, NUM_LEDS).setCorrection(TypicalLEDStrip); // initializes LED strip
  FastLED.setBrightness(BRIGHTNESS);// global brightness
}


// switches off all LEDs
void showProgramCleanUp(long delayTime) {
  for (int i = 0; i &amp;lt; NUM_LEDS; ++i) { 
    leds[i] = CRGB::Black;
  }
  FastLED.show();
  delay(delayTime);
}

// switches on all LEDs. Each LED is shown in random color. 
// numIterations: indicates how often LEDs are switched on in random colors
// delayTime: indicates for how long LEDs are switched on.
void showProgramRandom(int numIterations, long delayTime) {
  for (int iteration = 0; iteration &amp;lt; numIterations; ++iteration) { 
    for (int i = 0; i &amp;lt; NUM_LEDS; ++i) { 
      leds[i] = CHSV(random8(),255,255); // hue, saturation, value
    }
    FastLED.show();
    delay(delayTime);
  }
}

// Shifts a single pixel from the start of strip to the end. 
// crgb: color of shifted pixel
// delayTime: indicates how long the pixel is shown on each LED
void showProgramShiftSinglePixel(CRGB crgb, long delayTime) {
  for (int i = 0; i &amp;lt; NUM_LEDS; ++i) { 
    leds[i] = crgb;
    FastLED.show();
    delay(delayTime);
    leds[i] = CRGB::Black;
  }
}

// Shifts multiple pixel from the start of strip to the end. The color of each pixel is randomized.
// delayTime: indicates how long the pixels are shown on each LED
void showProgramShiftMultiPixel(long delayTime) {
  for (int i = 0; i &amp;lt; NUM_LEDS; ++i) { for (int j = i; j &amp;gt; 0; --j) { 
      leds[j] = leds[j-1];
    }
    CRGB newPixel = CHSV(random8(),255,255);
    leds[0] = newPixel;
    FastLED.show();
    delay(delayTime);
  }
}

// main program
void loop() {
  showProgramCleanUp(2500); // clean up
  showProgramRandom(100, 100); // show "random" program
  
  showProgramCleanUp(2500); // clean up
  showProgramRandom(10, 1000); // show "random" program

  
  showProgramCleanUp(2500); // clean up
  showProgramShiftSinglePixel(CRGB::Blue, 250); // show "shift single pixel program" with blue pixel
  
  showProgramCleanUp(2500); // clean up
  showProgramShiftSinglePixel(CRGB::Maroon, 100); // show "shift single pixel program" with maroon pixel

  
  showProgramCleanUp(2500); // clean up
  showProgramShiftMultiPixel(500); // show "shift multi pixel" program
  
  showProgramCleanUp(2500); // clean up
  showProgramShiftMultiPixel(50); // show "shift multi pixel" program
}

When the source code is compiled and transferred to the Arduino, the LED strip should show colored pixels according the active light program.

LED pixel strip controlled by an Arduino Uno.

LED pixel strip controlled by an Arduino Uno.

Video Tutorial

How to control a DC motor with the Arduino Uno and the L298N Dual Motor Controller

L298N Module

Pin description (for controlling DC motors):
1: + (DC motor 1)
2: – (DC motor 1)
3: If jumper enabled, 5V output on pin 6(e.g. for driving an Arduino)
4: Vcc of motor voltage supply
5: GND
6: 5V output, if jumper enabled
7 (ENA): One of Arduino’s PWM pins can be connected (to the lower pin) to control the speed of motor 1. If the jumper is enabled, motor 1 will run on full speed.
8 (IN1): Controls direction of motor 1
9 (IN2): Controls direction of motor 1
10 (IN3): Controls direction of motor 2
11 (IN4): Controls direction of motor 2
12 (ENB): One of Arduino’s PWM pins can be connected (to the lower pin) to control the speed of motor 2. If the jumper is enabled, motor 2 will run on full speed.
13: + (DC motor 2)
14: – (DC motor 2)

In order to control a DC motor with the Arduino Uno, a motor controller module is required. Such module is needed, for various reasons: For example, the Arduino can’t power DC motors with a voltage higher than 5V. However, many DC motors need more than 5V, especially when they are supposed to move on full speed. Moreover, most DC motors need more power than the Arduino could provide. In this tutorial, the L298N Dual Motor Controller is used to control a single DC motor with the Arduino Uno. The L298N module can also be used to control two motors with different directions and speeds.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– Jumper wire clamps [Search on Aliexpress | Amazon]
– Breadboard [Search on Aliexpress | Amazon]
– L298N module [Search on Aliexpress | Amazon]
– DC motor [Search on Aliexpress | Amazon]
– USB power boost 5V-to-9V (optional) [Search on Aliexpress | Amazon]
– DC power jack socket (optional) [Search on Aliexpress | Amazon]

Pin Layout:
In order to power the DC motor, two voltage supplies with different voltages are needed. The used DC motor has an operating voltage of 3V up to 12V. As the L298N module drops the voltage by more than 2V, the 5V voltage supply (USB) of the Arduino can’t be used. Therefore, a second voltage supply of 9V is used. In this tutorial, a USB Power boost (5V-to-9V) is used in combination with a DC power jack socket. Then, the power jack socket is connected to the breadboard. The breadboard’s “+” line (Vcc) is connected to pin 1 of the L298N module. The breadboard’s “-” line (GND) is connected to pin 2 of the L298N module. It is important that the L298N module and the Arduino share the same GND. Therefore, the breadboard’s “-” line is also connected to one of the Arduino’s GND pins.

Scheme of the tutorial's setup

Scheme of the tutorial’s setup. An Arduino is wired to an L298N module to control a DC motor.

The Arduino’s pin 6 is connected to the ENB pin of the module. This connection is used to control the speed of the motor and, therefore, using one of the Arduino’s PWM-enabled pins is required. Then, the Arduino’s pins 7 and 8 is connected to the module’s pins IN3 and IN4, respectively. These pins are used to control the direction of the DC motor (IN3=HIGH/IN4=LOW or IN3=LOW/IN4=HIGH).
As a final step, the module’s output pins for the second motor (pin 13 and 14) are connected to the DC motor.

Example source code:

Picture of the setup

Picture of the setup.

This source code drives the motor in four different states: Forward in slow and fast mode as well as backward in slow and fast mode. The functions slow() and fast() write an analog value to the PWM pin that is connected to ENB. The higher the value (0 to 255), the higher the speed of the motor. Please note, that the motor will not work if the values are too low.
In the loop function, the motor is driven forward in slow mode for five seconds. Naturally, the direction of the motor also depends on the direction you mounted the motor as well as on how you connected the motors pin to the module’s pins 13 and 14. Then, the motor drives in fast mode for 5 seconds. Next, the motor changes the direction and is driven in slow mode for 5 seconds as well as in fast mode for 5 seconds.

// (c) Michael Schoeffler 2016, http://www.mschoeffler.de

const int enb = 6; // PWM pin 6
const int in3 = 7;
const int in4 = 8;

void setup() {
 pinMode(in3, OUTPUT);
 pinMode(in4, OUTPUT);
 pinMode(enb, OUTPUT);

}

void slow() {
 analogWrite(enb, 128);
}

void fast() {
 analogWrite(enb, 255);
}

void loop() { 
 digitalWrite(in3, LOW);
 digitalWrite(in4, HIGH);
 slow();
 delay(5000);
 fast();
 delay(5000);
 // change of direction
 digitalWrite(in3, HIGH);
 digitalWrite(in4, LOW);
 slow();
 delay(5000);
 fast();
 delay(5000);
}

Video Tutorial

Side Notes:

  • The L298N module can also be used to drive stepper motors.
  • You can also drive more than two motors. Just share the pins 13 and 14 (or 1 and 2) with multiple motors. If multiple motors share the same pins they will also share the direction and speed.
  • The module’s pins 7 to 12 (ENA, IN1, IN2, IN3, IN4 and ENB) work with TTL logic levels (5V). Therefore, we can set the values directly from the Arduino if the same GND is shared.

How to use the “MicroSD Card Adapter” with the Arduino Uno

Pin layout of MicroSD Card Adapter and Arduino Uno.

In this tutorial, it is shown how to read and write SD cards utilizing the “MicroSD Card Adapter” module and Arduino Uno. An major advantage of the module is that it can be used with the SD library that comes with the Arduino IDE. The SD library makes initialization, reading, and writing of the card very easy.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– MicroSD Card Adapter [Search on Aliexpress | Amazon]
– MicroSD card [Search on Aliexpress | Amazon]

How to connect the “MicroSD Card Adapter” module to the Arduino Uno?

Schematic view of pin layout.

The module comes with a voltage regulator. Therefore, the Arduino’s 5V and 3.3V pin can be used for the voltage supply. The module communicates via SPI (Serial Peripheral Interface) to the Arduino Uno.  The following table shows the complete pin layout.

MicroSD Card Adapter Pin Arduino Uno Pin
CS 4
SCK 13
MOSI 11
MISO 12
VCC 5V
GND GND

How to program the RFID reader?
As mentioned before, reading and writing an SD card is very simple when the standard SD library of the Arduino IDE is used. Make sure to use the latest version of the SD library (Sketch -> Include Library -> Manage Libraries -> Search for “SD”). For example, in my case, version 1.1.0 did not work with the module. Fortunately, version 1.1.1 did work without any problems. Moreover, the SD card must be formatted as FAT16 or FAT32. If something does not work as expected, a good start for debugging is always to upload CardInfo example of the library (File -> Examples -> SD -> CardInfo) to the Arduino and read the messages of the serial monitor.
In this tutorial’s code, a random number between 0 and 9 is written to an SD card. In particular, the number is written to a file named “file.txt”. Next, the content of “file.txt” is read. At the end of the loop function, a delay of 5 seconds is added. Please note that when the Arduino is started, it is checked whether a file named “file.txt” exists (see setup function). If so, the file is deleted.

// (c) Michael Schoeffler 2016, http://www.mschoeffler.de
#include <SD.h> //Load SD library

int chipSelect = 4; //chip select pin for the MicroSD Card Adapter
File file; // file object that is used to read and write data

void setup() {
  Serial.begin(9600); // start serial connection to print out debug messages and data

  pinMode(chipSelect, OUTPUT); // chip select pin must be set to OUTPUT mode
  if (!SD.begin(chipSelect)) { // Initialize SD card
    Serial.println("Could not initialize SD card."); // if return value is false, something went wrong.
  }

  if (SD.exists("file.txt")) { // if "file.txt" exists, fill will be deleted
    Serial.println("File exists.");
    if (SD.remove("file.txt") == true) {
      Serial.println("Successfully removed file.");
    } else {
      Serial.println("Could not removed file.");
    }
  }
}

void loop() {
  file = SD.open("file.txt", FILE_WRITE); // open "file.txt" to write data
  if (file) { 
    int number = random(10); // generate random number between 0 and 9
    file.println(number); // write number to file
    file.close(); // close file
    Serial.print("Wrote number: "); // debug output: show written number in serial monitor
    Serial.println(number);
  } else {
    Serial.println("Could not open file (writing).");
  }

  file = SD.open("file.txt", FILE_READ); // open "file.txt" to read data
  if (file) {
    Serial.println("--- Reading start ---"); 
    char character; 
    while ((character = file.read()) != -1) { // this while loop reads data stored in "file.txt" and prints it to serial monitor 
      Serial.print(character);
    } 
    file.close();
    Serial.println("--- Reading end ---"); 
  } else {
    Serial.println("Could not open file (reading).");
  } 
  delay(5000); // wait for 5000ms
}

If everything works correctly, the serial monitor should show a similar output as shown in the following screenshot:

Serial monitor output while using MicroSD Card Adapter.

Video Tutorial

How to use the ultrasonic sensor/actuator “HC-SR04” with the Arduino Uno

In this tutorial, it is shown how to use the ultrasonic sensor (and actuator) “HC-SR04” with the Arduino Uno. The HC-SR04 has an ultrasonic transmitter and receiver. The transmitter sends out a 40 kHz burst signal (which is not audible by humans). The receiver captures the signal if it is reflected by an obstacle. Therefore, the HC-SR04 can be used for distance measurements and alarm detection systems. The HC-SR04 supports 50 measurements per second and distances between 2cm and about 300cm.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires [Search on Aliexpress | Amazon]
– ultrasonic sensor HC-SR04 [Search on Aliexpress | Amazon]

How to connect the HC-SR04 to the Arduino?

Schematics of how to connect the HC-SR04 ultrasonic sensor module to the Arduino.

The HC-SR04 module has four pins. The module’s Vcc pin has to be connected with the 5V pin of the Arduino. In this tutorial, the module’s “Trig” pin (trigger) is connected to the Arduino digital pin 2 and the “Echo” pin is connected to Arduino’s digital pin 3. Lastly, the module’s “Gnd” pin is connected to one of the Arduino’s GND pins. Here, a mini breadboard is also utilized so that the HC-SR04 can be connected to the Arduino in an upright position.

How to program distance measurements with the HC-SR04?
The ultrasonic module is used to measure the distance between the module and an obstacle. In order to measure the distance, the module must be prepared to send out the 40 kHz burst signal. The burst signal is sent when the signal of the “Trig” pin goes from HIGH to LOW. In addition, the HIGH signal must have been present for at least 10 microseconds. The module sends a pulse on the echo pin with the duration of the round-trip-time of the burst signal. The round-trip-time is the time from the transmitter to an obstacle and from the obstacle to the receiver. Fortunately, the pulseIn-function covers this use-case perfectly. If the second parameter is HIGH, the pulseIn-function waits for the pin to go HIGH, starts timing, then waits for the pin to go LOW.
In order to obtain the distance, the duration has to be divided by two, since only the one-way distance is of interested (from module to obstacle). Next, the acoustic velocity of the air has to be taken into account which is about 343.5 meters per second (only at a temperature of 20°C). Since the duration measured by the pulseIn-function is in microseconds and we are interested in cm, the  divided duration has to be multiplied by 0.03435.


// (c) Michael Schoeffler 2016, http://www.mschoeffler.de

const int pinTrigger = 2; // pin for sending out the signal
const int pinEcho = 3; // pin for receiving the echo of the signal
long duration = 0; // the roundtrip duration of the signal in us
void setup() {
pinMode(pinTrigger, OUTPUT);
pinMode(pinEcho, INPUT);
Serial.begin(9600); // open serial connection to print out distance values
}

void loop() {
digitalWrite(pinTrigger, LOW); // turn off the trigger
delayMicroseconds(3);
noInterrupts(); // disable interrupts as they might interfere with the measurement
digitalWrite(pinTrigger, HIGH);// prepare to send "trigger" command to module
delayMicroseconds(10); // wait for 10us (module sends signal only, if trigger had a HIGH signal for at least 10 us)
digitalWrite(pinTrigger, LOW); // module sends signal now
duration = pulseIn(pinEcho, HIGH); // waiting for a HIGH signal on the echo pin.
interrupts(); // enable interrupts, we are done with the measurement

// from roundtrip duration to distance:
long durationOneWay = duration / 2; // divided by two, since duration is a roundtrip signal
// acoustic velocity of air at a temperature of 20°C => ~343.5 m/s
// => 0.03435 cm/us
long distance = durationOneWay * 0.03435; // distance in cm
Serial.print("Distance[cm]: ");
Serial.println(distance);

delay(500); // wait for 500ms (added only for debugging reasons)
}

Distance measurement with the Arduino Uno and HC-SR04 module.

If the code is uploaded to an Arduino, the output of the serial monitor should show the distance between the module and an obstacle. Since many factors, such as temperature, the obstacle’s material and surface characteristics, have an influence on the accuracy of the measurements, it is very challenging to achieve highly accurate measurements with such a low-cost ultrasonic sensor. Nevertheless, the HC-SR04 is a cheap and easy-to-use ultrasonic module with a wide range of possible applications.

Video Tutorial

How to use the RFID-RC522 module (RFID reader) with the Arduino Uno

Setup of this tutorial: RFID reader and two RFID tags.

RFID stands for Radio-frequency identification and can be used for many application that require an identification mechanism. In this tutorial, it is shown how to use the RFID-RC522 module with the Arduino Uno. The RFID-RC522 module is an RFID reader, which can read RFID tags in close-range. In order to read an RFID tag, the reader and the tag must have the same frequency. The RFID-RC522 module reads only High frequency tags at 13.56 MHz.
In order to demonstrate the RFID-RC522 module, a simple application is programmed which identifies a user based on an RFID tag.

List of materials:
– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires (female/male) [Search on Aliexpress | Amazon]
– RFID-RC522 module [Search on Aliexpress | Amazon]
– RFID tags [Search on Aliexpress | Amazon]

How to connect the RFID-RC522 to the Arduino?

Schematic of how to connect the RFID-RC522 to the Arduino.

The RFID-RC522 module comes with eight pins (of which seven pins are used in this tutorial). In the following, the pin layout is shown as recommended by the documentation of the MFRC522 library (used later in the programming section). The RFID-RC522 module runs with 3.3V. Therefore, the module’s 3.3V pin must be connected to the Arduino’s 3.3V. The module might get damaged, if it is accidentally connected to the Arduino’s 5V pin. The complete pin layout is shown by the following table (works only for the Arduino Uno! Mega, Nano etc. have different recommended pin layouts!):

RFID-RC522 Pin Arduino Uno Pin
SDA 10
SCK 13
MOSI 11
MISO 12
IRQ UNUSED
GND GND
RST 9
3.3V 3.3V

How to program the RFID reader?
The code makes use of an existing RFID library which can be found here: https://github.com/miguelbalboa/rfid. If you are using the Arduino IDE, the library can be easily installed by clicking “Sketch->Include Library->Manage Libraries”. Then, search for “RFID” and you will find an entry with the title “MFRC522 by GithubCommunity”. If you cannot find such an entry, I recommend to visit the official website of the library for further assistance. In order to get the RFID reader running, you have to setup the library itself, a SPI connection, as well as the reader. Luckily, the library offers two very handy convenience functions for reading tags: The first functions allows to detect whether an RFID tag/card is present. The second function reads the RFID tag id. In the following code, a for-loop is used to iterate through the tag. In each iteration, a single byte is read and printed out as hexadecimal value (00..FF). Such an mechanism can be used to identify users, when each user owns a different RFID tag.

// (c) Michael Schoeffler 2014, http://www.mschoeffler.de

#include "SPI.h" // SPI library 
#include "MFRC522.h" // RFID library (https://github.com/miguelbalboa/rfid)

const int pinRST = 9;
const int pinSDA = 10;

MFRC522 mfrc522(pinSDA, pinRST); // Set up mfrc522 on the Arduino

void setup() {
  SPI.begin(); // open SPI connection
  mfrc522.PCD_Init(); // Initialize Proximity Coupling Device (PCD)
  Serial.begin(9600); // open serial connection 
}

void loop() {
  if (mfrc522.PICC_IsNewCardPresent()) { // (true, if RFID tag/card is present ) PICC = Proximity Integrated Circuit Card
    if(mfrc522.PICC_ReadCardSerial()) { // true, if RFID tag/card was read
      Serial.print("RFID TAG ID:"); 
      for (byte i = 0; i &lt; mfrc522.uid.size; ++i) { // read id (in parts)
        Serial.print(mfrc522.uid.uidByte[i], HEX); // print id as hex values
        Serial.print(" "); // add space between hex blocks to increase readability
      }
      Serial.println(); // Print out of id is complete. 
    }
  }
}

If the code has been successfully uploaded to the Arduino and an RFID card or tag is in close-range to the RFID reader, the output on the Serial Monitor (Tools->Serial Monitor, Ctrl+Shift+M) should look like this (picture shows position of the RFID card as well as the corresponding serial monitor output):

RFID reader is reading the ID of an RFID card. In addition, the serial monitor output of the program is shown.

Video Tutorial:

How to build an optical/light barrier with the Arduino, the Keyes laser module (KY-008) and a laser receiver/detector module

Light barrier built with the Arduino, a laser module, and a laser detector module.

In this tutorial, it shown how to build an optical barrier. The barrier detects any movement between the sender and the receiver. The sender is a laser module (Keyes KY-008) that emits red light (wavelength: 650nm). The laser detector/receiver is an unnamed module that returns either a LOW signal or a HIGH signal (no “analog values” in between).

List of materials:

– Arduino Uno [Search on Aliexpress | Amazon]
– Jumper wires (female/male) [Search on Aliexpress | Amazon]
– KY-008 red laser module [Search on Aliexpress | Amazon]
– Unnamed laser detector/receiver [Search on Aliexpress | Amazon]

Schematic of a laser barrier.

How to connect the laser module and laser detector to the Arduino?


The laser module has three pins. Only two pins are used: The “-” pin is connected to one of the Arduino’s GND pins. The “S” pin of the laser module is connected to the Arduino’s pin “2”. Therby, the laser can be switched off or on by sending either a LOW signal or a HIGH signal. The detector module has also three pins. The module’s “VCC” pin is connected to the Arduino’s “5V” pin and the GND of the module is connected to the Arduino’s GND. Lastly, the signal pin”OUT” of the module is connected to pin “3”.

How to program the light/optical barrier?
First, the pin values for the laser and the receiver are initialized. Next, the laser pin is set to OUTPUT mode and the receiver pin is set to INPUT mode. Then, the laser is switched on by setting “pinLaser” to HIGH. In order to monitor the light barrier’s state, a serial connection is started.
In the loop function, the value of the receiver is read. The retrieved value can either be LOW or HIGH. LOW means that the laser does not reach the detector, e.g., something went through the light barrier and is located between the laser and the detector. Then, the value of the detector is written to the console. Finally, a delay of 1000ms is added for convenience purposes (serial monitor is not “flashing” the values).

// (c) Michael Schoeffler 2014, http://www.mschoeffler.de

const int pinLaser = 2; // output signal pin of laser module/laser pointer
const int pinReceiver = 3; // input signal pin of receiver/detector (the used module does only return a digital state)


void setup() {
  pinMode(pinLaser, OUTPUT); // set the laser pin to output mode
  pinMode(pinReceiver, INPUT); // set the laser pin to output mode
  digitalWrite(pinLaser, HIGH); // emit red laser
  Serial.begin(9600); // Setup serial connection for print out to console
}

void loop() {
  int value = digitalRead(pinReceiver); // receiver/detector send either LOW or HIGH (no analog values!)
  Serial.println(value);  // send value to console
  delay(1000); // wait for 1000ms
}

If the code has been successfully uploaded to the Arduino, the output on the Serial Monitor (Tools->Serial Monitor, Ctrl+Shift+M) should look like this:

Serial monitor output of the light barrier example. If something is inside the light barrier, “0” is printed out to the monitor. Otherwise, if the red laser light points to the detecctor, “1” is printed out.

Remarks:
The detector’s LED, which is located next to the detector, indicates whether the detector is connected to a power supply.

Video Tutorial: