Tag Archives: tutorial

LED Real Time Clock Temperature Sensor Shield for Arduino

Tutorial – LED Real Time Clock Temperature Sensor Shield for Arduino

In this tutorial we look at how to use the neat LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way. That’s a bit of a mouthful, however the shield does offer the following:

  • four digit, seven-segment LED display
  • DS1307 real-time clock IC
  • three buttons
  • four LEDs
  • a active buzzer
  • a light-dependent resistor (LDR)
  • and a thermistor for measuring ambient temperature

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-1

The shield also arrives fully-assembled , so you can just plug it into your Arduino Uno or compatible board. Neat, beginners will love that. So let’s get started, by showing how each function can be used – then some example projects. In no particular order…

The buzzer

A high-pitched active buzzer is connected to digital pin D6 – which can be turned on and off with a simple digitalWrite() function. So let’s do that now, for example:

void setup() {
  // buzzer on digital pin 6
  pinMode(6, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(6, HIGH);   // turn the buzzer on (HIGH is the voltage level)
  delay(1000);                       // wait for a second
  digitalWrite(6, LOW);    // turn the buzzer off by making the voltage LOW
  delay(1000);                       // wait for a second
}

If there is a white sticker over your buzzer, remove it before uploading the sketch. Now for a quick video demonstration. Turn down your volume before playback.

The LEDs

Our shield has four LEDs, as shown below:

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-LEDs

They’re labelled D1 through to D4, with D1 on the right-hand side. They are wired to digital outputs D2, D3, D4 and D5 respectively. Again, they can be used with digitalWrite() – so let’s do that now with a quick demonstration of some blinky goodness. Our sketch turns the LEDs on and off in sequential order. You can change the delay by altering the variable x:

void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(2, OUTPUT); // LED 1
  pinMode(3, OUTPUT); // LED 2
  pinMode(4, OUTPUT); // LED 3
  pinMode(5, OUTPUT); // LED 4
}

int x = 200;

void loop() {
  digitalWrite(2, HIGH);    // turn on LED1
  delay(x);
  digitalWrite(2, LOW);    // turn off LED1. Process repeats for the other three LEDs
  digitalWrite(3, HIGH);
  delay(x);
  digitalWrite(3, LOW);
  digitalWrite(4, HIGH);
  delay(x);
  digitalWrite(4, LOW);
  digitalWrite(5, HIGH);
  delay(x);
  digitalWrite(5, LOW);
}

And in action:

The Buttons

It is now time to pay attention to the three large buttons on the bottom-left of the shield. They look imposing however are just normal buttons, and from right-to-left are connected to digital pins D9, D10 and D11:

LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way

They are, however, wired without external pull-up or pull-down resistors so when initialising them in your Arduino sketch you need to activate the digital input’s internal pull-up resistor inside the microcontroller using:

pinMode(pin, INPUT_PULLUP);

Due to this, buttons are by default HIGH when not pressed. So when you press a button, they return LOW. The following sketch demonstrates the use of the buttons by lighting LEDs when pressed:

void setup() {
  // initalise digital pins for LEDs as outputs
  pinMode(2, OUTPUT); // LED 1
  pinMode(3, OUTPUT); // LED 2
  pinMode(4, OUTPUT); // LED 3

  // initalise digital pins for buttons as inputs
  // and initialise internal pullups
  pinMode(9, INPUT_PULLUP); // button K1
  pinMode(10, INPUT_PULLUP); // button K2
  pinMode(11, INPUT_PULLUP); // button K3
}

void loop()
{
  if (digitalRead(9) == LOW)
  {
    digitalWrite(2, HIGH);
    delay(10);
    digitalWrite(2, LOW);
  }

  if (digitalRead(10) == LOW)
  {
    digitalWrite(3, HIGH);
    delay(10);
    digitalWrite(3, LOW);
  }

  if (digitalRead(11) == LOW)
  {
    digitalWrite(4, HIGH);
    delay(10);
    digitalWrite(4, LOW);
  }
}

You can see these in action via the following video:

The Numerical LED Display

Our shield has a nice red four-digit, seven-segment LED clock display. We call it a clock display as there are colon LEDs between the second and third digit, just as a digital clock would usually have:

LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way with free delivery worldwide

The display is controlled by a special IC, the Titan Micro TM1636:

TM1636 Numerical LED Display Driver IC from PMD Way with free delivery worldwide

The TM1636 itself is an interesting part, so we’ll explain that in a separate tutorial in the near future. For now, back to the shield.

To control the LED display we need to install an Arduino library. In fact the shield needs four, so you can install them all at once now. Download the .zip file from here. Then expand that into your local download directory – it contains four library folders. You can then install them one at a time using the Arduino IDE’s Sketch > Include library > Add .zip library… command:

LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way with free delivery worldwide

The supplied library offers five functions used to control the display.

.num(x);

…this displays a positive integer (whole number) between 0 and 9999.

.display(p,d);

… this shows a digit d in location p (locations from left to right are 3, 2, 1, 0)

.time(h,m)

… this is used to display time data (hours, minutes) easily. h is hours, m is minutes

.pointOn();
.pointOff();

… these turn the colon on … and off. And finally:

.clear();

… which clears the display to all off. At the start of the sketch, we need to use the library and initiate the instance of the display by inserting the following lines:

#include <TTSDisplay.h>
TTSDisplay rtcshield;

Don’t panic – the following sketch demonstrates the five functions described above:

#include <TTSDisplay.h>
TTSDisplay rtcshield;

int a = 0;
int b = 0;

void setup() {}

void loop()
{
  // display some numbers
  for (a = 4921; a < 5101; a++)
  {
    rtcshield.num(a);
    delay(10);
  }

  // clear display
  rtcshield.clear();

  // display individual digits
  for (a = 3; a >= 0; --a)
  {
    rtcshield.display(a, a);
    delay(1000);
    rtcshield.clear();
  }
  for (a = 3; a >= 0; --a)
  {
    rtcshield.display(a, a);
    delay(1000);
    rtcshield.clear();
  }

  // turn the colon and off
  for (a = 0; a < 5; a++)
  {
    rtcshield.pointOn();
    delay(500);
    rtcshield.pointOff();
    delay(500);
  }

  // demo the time display function
  rtcshield.pointOn();
  rtcshield.time(11, 57);
  delay(1000);
  rtcshield.time(11, 58);
  delay(1000);
  rtcshield.time(11, 59);
  delay(1000);
  rtcshield.time(12, 00);
  delay(1000);
}

And you can see it in action through the video below:

The LDR (Light Dependent Resistor)

LDRs are useful for giving basic light level measurements, and our shield has one connected to analog input pin A1. It’s the two-legged item with the squiggle on top as shown below:

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-LDR

The resistance of LDRs change with light levels – the greater the light, the less the resistance. Thus by measuring the voltage of a current through the LDR with an analog input pin – you can get a numerical value proportional to the ambient light level. And that’s just what the following sketch does:

#include <TTSDisplay.h>
TTSDisplay rtcshield;

int a = 0;

void setup() {}
void loop()
{
  // read value of analog input
  a = analogRead(A1);
  // show value on display
  rtcshield.num(a);
  delay(100);
}

The Thermistor

A thermistor is a resistor whose resistance is relative to the ambient temperature. As the temperature increases, their resistance decreases. It’s the black part to the left of the LDR in the image below:

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-LDR

We can use this relationship between temperature and resistance to determine the ambient temperature. To keep things simple we won’t go into the theory – instead, just show you how to get a reading.

The thermistor circuit on our shield has the output connected to analog input zero, and we can use the library installed earlier to take care of the mathematics. Which just leaves us with the functions.

At the start of the sketch, we need to use the library and initiate the instance of the thermistor by inserting the following lines:

#include <TTSTemp.h>
TTSTemp temp;

… then use the following which returns a positive integer containing the temperature (so no freezing cold environments):

.get();

For our example, we’ll get the temperature and show it on the numerical display:

#include <TTSDisplay.h>
#include <TTSTemp.h>

TTSTemp temp;
TTSDisplay rtcshield;

int a = 0;

void setup() {}

void loop() {

  a = temp.get();
  rtcshield.num(a);
  delay(500);
}

And our thermometer in action. No video this time… a nice 24 degrees C in the office:

led-real-time-clock-temperature-sensor-shield-arduino-pmdway-thermometer

The Real-Time Clock 

Our shield is fitted with a DS1307 real-time clock IC circuit and backup battery holder. If you insert a CR1220 battery, the RTC will remember the settings even if you remove the shield from the Arduino or if there’s a power blackout, board reset etc:

LED Real Time Clock Temperature Sensor Shield for Arduino from PMD Way with free delivery worldwide

The DS1307 is incredibly popular and used in many projects and found on many inexpensive breakout boards. We have a separate tutorial on how to use the DS1307, so instead of repeating ourselves – please visit our specific DS1307 Arduino tutorial, then return when finished.

Where to from here? 

We can image there are many practical uses for this shield, which will not only improve your Arduino coding skills but also have some useful applications. An example is given below, that you can use for learning or fun.

Temperature Alarm

This projects turns the shield into a temperature monitor – you can select a lower and upper temperature, and if the temperature goes outside that range the buzzer can sound until you press it.

Here’s the sketch:

#include <TTSDisplay.h>
#include <TTSTemp.h>

TTSTemp temp;
TTSDisplay rtcshield;

boolean alarmOnOff = false;
int highTemp = 40;
int lowTemp = 10;
int currentTemp;

void LEDsoff()
{
  // function to turn all alarm high/low LEDs off
  digitalWrite(2, LOW);
  digitalWrite(4, LOW);
}

void setup() {
  // initalise digital pins for LEDs and buzzer as outputs
  pinMode(2, OUTPUT); // LED 1
  pinMode(3, OUTPUT); // LED 2
  pinMode(4, OUTPUT); // LED 3
  pinMode(5, OUTPUT); // LED 4
  pinMode(6, OUTPUT); // buzzer

  // initalise digital pins for buttons as inputs
  // and initialise internal pullups
  pinMode(9, INPUT_PULLUP); // button K1
  pinMode(10, INPUT_PULLUP); // button K2
  pinMode(11, INPUT_PULLUP); // button K3
}

void loop()
{
  // get current temperature
  currentTemp = temp.get();

  // if current temperature is within set limts
  // show temperature on display

  if (currentTemp >= lowTemp || currentTemp <= highTemp)
    // if ambient temperature is less than high boundary
    // OR if ambient temperature is grater than low boundary
    // all is well
  {
    LEDsoff(); // turn off LEDs
    rtcshield.num(currentTemp);
  }

  // if current temperature is above set high bounday, show red LED and
  // show temperature on display
  // turn on buzzer if alarm is set to on (button K3)

  if (currentTemp > highTemp)
  {
    LEDsoff(); // turn off LEDs
    digitalWrite(4, HIGH); // turn on red LED
    rtcshield.num(currentTemp);
    if (alarmOnOff == true) {
      digitalWrite(6, HIGH); // buzzer on }
    }
  }

  // if current temperature is below set lower boundary, show blue LED and
  // show temperature on display
  // turn on buzzer if alarm is set to on (button K3)

  if (currentTemp < lowTemp)
  {
    LEDsoff(); // turn off LEDs
    digitalWrite(2, HIGH); // turn on blue LED
    rtcshield.num(currentTemp);
    if (alarmOnOff == true)
    {
      digitalWrite(6, HIGH); // buzzer on }
    }
  }
  // --------turn alarm on or off-----------------------------------------------------
  if (digitalRead(11) == LOW) // turn alarm on or off
  {
    alarmOnOff = !alarmOnOff;
    if (alarmOnOff == 0) {
      digitalWrite(6, LOW); // turn off buzzer
      digitalWrite(5, LOW); // turn off alarm on LED
    }
    // if alarm is set to on, turn LED on to indicate this
    if (alarmOnOff == 1)
    {
      digitalWrite(5, HIGH);
    }
    delay(300); // software debounce
  }
  // --------set low temperature------------------------------------------------------
  if (digitalRead(10) == LOW) // set low temperature. If temp falls below this value, activate alarm
  {
    // clear display and turn on blue LED to indicate user is setting lower boundary
    rtcshield.clear();
    digitalWrite(2, HIGH); // turn on blue LED
    rtcshield.num(lowTemp);

    // user can press buttons K2 and K1 to decrease/increase lower boundary.
    // once user presses button K3, lower boundary is locked in and unit goes
    // back to normal state

    while (digitalRead(11) != LOW)
      // repeat the following code until the user presses button K3
    {
      if (digitalRead(10) == LOW) // if button K2 pressed
      {
        --lowTemp; // subtract one from lower boundary
        // display new value. If this falls below zero, won't display. You can add checks for this yourself :)
        rtcshield.num(lowTemp);
      }
      if (digitalRead(9) == LOW) // if button K3 pressed
      {
        lowTemp++; // add one to lower boundary
        // display new value. If this exceeds 9999, won't display. You can add checks for this yourself :)
        rtcshield.num(lowTemp);
      }
      delay(300); // for switch debounce
    }
    digitalWrite(2, LOW); // turn off blue LED
  }
  // --------set high temperature-----------------------------------------------------
  if (digitalRead(9) == LOW) // set high temperature. If temp exceeds this value, activate alarm
  {

    // clear display and turn on red LED to indicate user is setting lower boundary
    rtcshield.clear();
    digitalWrite(4, HIGH); // turn on red LED
    rtcshield.num(highTemp);

    // user can press buttons K2 and K1 to decrease/increase upper boundary.
    // once user presses button K3, upper boundary is locked in and unit goes
    // back to normal state

    while (digitalRead(11) != LOW)
      // repeat the following code until the user presses button K3
    {
      if (digitalRead(10) == LOW) // if button K2 pressed
      {
        --highTemp; // subtract one from upper boundary
        // display new value. If this falls below zero, won't display. You can add checks for this yourself :)
        rtcshield.num(highTemp);
      }
      if (digitalRead(9) == LOW) // if button K3 pressed
      {
        highTemp++; // add one to upper boundary
        // display new value. If this exceeds 9999, won't display. You can add checks for this yourself :)
        rtcshield.num(highTemp);
      }
      delay(300); // for switch debounce
    }
    digitalWrite(4, LOW); // turn off red LED
  }
}

Operating instructions:

  • To set lower temperature, – press button K2. Blue LED turns on. Use buttons K2 and K1 to select temperature, then press K3 to lock it in. Blue LED turns off.
  • To set upper temperature – press button K1. Red LED turns on. Use buttons K2 and K1 to select temperature, then press K3 to lock it in. Red LED turns off.
  • If temperature drops below lower or exceeds upper temperature, the blue or red LED will come on.
  • You can have the buzzer sound when the alarm activates – to do this, press K3. When the buzzer mode is on, LED D4 will be on. You can turn buzzer off after it activates by pressing K3.
  • Display will show ambient temperature during normal operation.

You can see this in action via the video below:

Conclusion

This is a fun and useful shield – especially for beginners. It offers a lot of fun and options without any difficult coding or soldering – it’s easy to find success with the shield and increase your motivation to learn more and make more.

You can be serious with a clock, or annoy people with the buzzer. And at the time of writing you can have one for US$14.95, delivered. So go forth and create something.

A little research has shown that this shield was based from a product by Seeed, who discontinued it from sale. I’d like to thank them for the library.

This post brought to you by pmdway.com – everything for makers and electronics enthusiasts, with free delivery worldwide.

To keep up to date with new posts at tronixstuff.com, please subscribe to the mailing list in the box on the right, or follow us on twitter @tronixstuff.

Tutorial – Using DS1307 and DS3231 Real-time Clock Modules with Arduino

We keep getting requests on how to use DS1307 and DS3231 real-time clock modules with Arduino from various sources – so this is the first of a two part tutorial on how to use them. For this Arduino tutorial we have  two real-time clock modules to use, one based on the Maxim DS1307:

DS1307 real-time clock from PMD Way

and another based on the DS3231:

DS3231 real time clock from PMD Way

There are two main differences between the ICs on the real-time clock modules, which is the accuracy of the time-keeping. The DS1307 used in the first module works very well, however the external temperature can affect the frequency of the oscillator circuit which drives the DS1307’s internal counter.

This may sound like a problem, however will usually result with the clock being off by around five or so minutes per month. The DS3231 is much more accurate, as it has an internal oscillator which isn’t affected by external factors – and thus is accurate down to a few minutes per year at the most. If you have a DS1307 module- don’t feel bad, it’s still a great value board and will serve you well.

With both of the modules, a backup battery is not installed when you receive them – it’s a good idea to buy a new CR2032 battery and fit it to the module.

Along with keeping track of the time and date, these modules also have a small EEPROM, an alarm function (DS3231 only) and the ability to generate a square-wave of various frequencies – all of which will be the subject of a second tutorial.

Connecting your module to an Arduino

Both modules use the I2C bus, which makes connection very easy. If you’re not sure about the I2C bus and Arduino, check out the I2C tutorials (chapters 20 and 21), or review chapter seventeen of the book “Arduino Workshop“.

Moving on – first you will need to identify which pins on your Arduino or compatible boards are used for the I2C bus – these will be knows as SDA (or data) and SCL (or clock).

  • On Arduino Uno or compatible boards, these pins are A4 and A5 for data and clock;
  • On the Arduino Mega the pins are D20 and D21 for data and clock;
  • And if you’re using a Pro Mini-compatible the pins are A4 and A5 for data and clock, which are parallel to the main pins.

DS1307 module

If you have the DS1307 module you will need to solder the wires to the board, or solder on some inline header pins so you can use jumper wires. Then connect the SCL and SDA pins to your Arduino, and the Vcc pin to the 5V pin and GND to GND.

DS3231 module

Connecting this module is easy as header pins are installed on the board at the factory. You can simply run jumper wires again from SCL and SDA to the Arduino and again from the module’s Vcc and GND pins to your board’s 5V or 3.3.V and GND. However these are duplicated on the other side for soldering your own wires.

Both of these modules have the required pull-up resistors, so you don’t need to add your own. Like all devices connected to the I2C bus, try and keep the length of the SDA and SCL wires to a minimum.

Reading and writing the time from your RTC Module

Once you have wired up your RTC module. enter and upload the following sketch. Although the notes and functions in the sketch refer only to the DS3231, the code also works with the DS1307.

#include "Wire.h"
#define DS3231_I2C_ADDRESS 0x68
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
  return( (val/10*16) + (val%10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return( (val/16*10) + (val%16) );
}
void setup()
{
  Wire.begin();
  Serial.begin(9600);
  // set the initial time here:
  // DS3231 seconds, minutes, hours, day, date, month, year
  // setDS3231time(30,42,21,4,26,11,14);
}
void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
dayOfMonth, byte month, byte year)
{
  // sets time and date data to DS3231
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set next input to start at the seconds register
  Wire.write(decToBcd(second)); // set seconds
  Wire.write(decToBcd(minute)); // set minutes
  Wire.write(decToBcd(hour)); // set hours
  Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  Wire.write(decToBcd(month)); // set month
  Wire.write(decToBcd(year)); // set year (0 to 99)
  Wire.endTransmission();
}
void readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
  // retrieve data from DS3231
  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  &year);
  // send it to the serial monitor
  Serial.print(hour, DEC);
  // convert the byte variable to a decimal number when displayed
  Serial.print(":");
  if (minute<10)
  {
    Serial.print("0");
  }
  Serial.print(minute, DEC);
  Serial.print(":");
  if (second<10)
  {
    Serial.print("0");
  }
  Serial.print(second, DEC);
  Serial.print(" ");
  Serial.print(dayOfMonth, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(year, DEC);
  Serial.print(" Day of week: ");
  switch(dayOfWeek){
  case 1:
    Serial.println("Sunday");
    break;
  case 2:
    Serial.println("Monday");
    break;
  case 3:
    Serial.println("Tuesday");
    break;
  case 4:
    Serial.println("Wednesday");
    break;
  case 5:
    Serial.println("Thursday");
    break;
  case 6:
    Serial.println("Friday");
    break;
  case 7:
    Serial.println("Saturday");
    break;
  }
}
void loop()
{
  displayTime(); // display the real-time clock data on the Serial Monitor,
  delay(1000); // every second
}

There may be a lot of code, however it breaks down well into manageable parts.

It first includes the Wire library, which is used for I2C bus communication, followed by defining the bus address for the RTC as 0x68. These are followed by two functions that convert decimal numbers to BCD (binary-coded decimal) and vice versa. These are necessary as the RTC ICs work in BCD not decimal.

The function setDS3231time() is used to set the clock. Using it is very easy, simple insert the values from year down to second, and the RTC will start from that time. For example if you want to set the following date and time – Wednesday November 26, 2014 and 9:42 pm and 30 seconds – you would use:

setDS3231time(30,42,21,4,26,11,14);

Note that the time is set using 24-hour time, and the fourth paramter is the “day of week”. This falls between 1 and 7 which is Sunday to Saturday respectively. These parameters are byte values if you are subsituting your own variables.

Once you have run the function once it’s wise to prefix it with // and upload your code again, so it will not reset the time once the power has been cycled or micrcontroller reset.

Reading the time form your RTC Is just as simple, in fact the process can be followed neatly inside the function displayTime(). You will need to define seven byte variables to store the data from the RTC, and these are then inserted in the function readDS3231time().

For example if your variables are:

byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

… you would refresh them with the current data from the RTC by using:

readDS3232time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);

Then you can use the variables as you see fit, from sending the time and date to the serial monitor as the example sketch does – to converting the data into a suitable form for all sorts of output devices.

Just to check everything is working, enter the appropriate time and date into the demonstration sketch, upload it, comment out the setDS3231time() function and upload it again. Then open the serial monitor, and you should be provided with a running display of the current time and date.

From this point you now have the software tools to set data to and retrieve it from your real-time clock module, and we hope you have an understanding of how to use these inexpensive modules.

You can learn more about the particular real-time clock ICs from the manufacturer’s website – DS1307 and DS3231.

This post brought to you by pmdway.com everything for makers and electronics enthusiasts, with free delivery worldwide.

To keep up to date with new posts at tronixstuff.com, please subscribe to the mailing list in the box on the right, or follow us on twitter @tronixstuff.

Tutorial – L298N Dual Motor Controller Modules and Arduino

Learn how to use inexpensive L298N motor control modules to drive DC and stepper motors with Arduino.

You don’t have to spend a lot of money to control motors with an Arduino or compatible board. After some hunting around we found a neat motor control module based on the L298N H-bridge IC that can allows you to control the speed and direction of two DC motors, or control one bipolar stepper motor with ease.

The L298N H-bridge module can be used with motors that have a voltage of between 5 and 35V DC. With the module used in this tutorial, there is also an onboard 5V regulator, so if your supply voltage is up to 12V you can also source 5V from the board.

So let’s get started!

L298N Dual Motor Controller Module 2A from PMD Way

First we’ll run through the connections, then explain how to control DC motors then a stepper motor. At this point, review the connections on the L298N H-bridge module.

Consider the following image – match the numbers against the list below the image:

L298N Dual Motor Controller Module 2A from PMD Way
  1. DC motor 1 “+” or stepper motor A+
  2. DC motor 1 “-” or stepper motor A-
  3. 12V jumper – remove this if using a supply voltage greater than 12V DC. This enables power to the onboard 5V regulator
  4. Connect your motor supply voltage here, maximum of 35V DC. Remove 12V jumper if >12V DC
  5. GND
  6. 5V output if 12V jumper in place, ideal for powering your Arduino (etc)
  7. DC motor 1 enable jumper. Leave this in place when using a stepper motor. Connect to PWM output for DC motor speed control.
  8. IN1
  9. IN2
  10. IN3
  11. IN4
  12. DC motor 2 enable jumper. Leave this in place when using a stepper motor. Connect to PWM output for DC motor speed control.
  13. DC motor 2 “+” or stepper motor B+
  14. DC motor 2 “-” or stepper motor B-

Controlling DC Motors

To control one or two DC motors is quite easy with the L298N H-bridge module. First connect each motor to the A and B connections on the L298N module. If you’re using two motors for a robot (etc) ensure that the polarity of the motors is the same on both inputs. Otherwise you may need to swap them over when you set both motors to forward and one goes backwards!

Next, connect your power supply – the positive to pin 4 on the module and negative/GND to pin 5. If you supply is up to 12V you can leave in the 12V jumper (point 3 in the image above) and 5V will be available from pin 6 on the module. This can be fed to your Arduino’s 5V pin to power it from the motors’ power supply. Don’t forget to connect Arduino GND to pin 5 on the module as well to complete the circuit.

Now you will need six digital output pins on your Arduino, two of which need to be PWM (pulse-width modulation) pins. PWM pins are denoted by the tilde (“~”) next to the pin number, for example:

Arduino UNO PWM pins

Finally, connect the Arduino digital output pins to the driver module. In our example we have two DC motors, so digital pins D9, D8, D7 and D6 will be connected to pins IN1, IN2, IN3 and IN4 respectively. Then connect D10 to module pin 7 (remove the jumper first) and D5 to module pin 12 (again, remove the jumper).

The motor direction is controlled by sending a HIGH or LOW signal to the drive for each motor (or channel). For example for motor one, a HIGH to IN1 and a LOW to IN2 will cause it to turn in one direction, and  a LOW and HIGH will cause it to turn in the other direction.

However the motors will not turn until a HIGH is set to the enable pin (7 for motor one, 12 for motor two). And they can be turned off with a LOW to the same pin(s). However if you need to control the speed of the motors, the PWM signal from the digital pin connected to the enable pin can take care of it.

This is what we’ve done with the DC motor demonstration sketch. Two DC motors and an Arduino Uno are connected as described above, along with an external power supply. Then enter and upload the following sketch:

// connect motor controller pins to Arduino digital pins
// motor one
int enA = 10;
int in1 = 9;
int in2 = 8;
// motor two
int enB = 5;
int in3 = 7;
int in4 = 6;
void setup()
{
  // set all the motor control pins to outputs
  pinMode(enA, OUTPUT);
  pinMode(enB, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(in3, OUTPUT);
  pinMode(in4, OUTPUT);
}
void demoOne()
{
  // this function will run the motors in both directions at a fixed speed
  // turn on motor A
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enA, 200);
  // turn on motor B
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  // set speed to 200 out of possible range 0~255
  analogWrite(enB, 200);
  delay(2000);
  // now change motor directions
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH); 
  delay(2000);
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);
}
void demoTwo()
{
  // this function will run the motors across the range of possible speeds
  // note that maximum speed is determined by the motor itself and the operating voltage
  // the PWM values sent by analogWrite() are fractions of the maximum speed possible 
  // by your hardware
  // turn on motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH); 
  // accelerate from zero to maximum speed
  for (int i = 0; i < 256; i++)
  {
    analogWrite(enA, i);
    analogWrite(enB, i);
    delay(20);
  } 
  // decelerate from maximum speed to zero
  for (int i = 255; i >= 0; --i)
  {
    analogWrite(enA, i);
    analogWrite(enB, i);
    delay(20);
  } 
  // now turn off motors
  digitalWrite(in1, LOW);
  digitalWrite(in2, LOW);  
  digitalWrite(in3, LOW);
  digitalWrite(in4, LOW);  
}
void loop()
{
  demoOne();
  delay(1000);
  demoTwo();
  delay(1000);
}

So what’s happening in that sketch? In the function demoOne() we turn the motors on and run them at a PWM value of 200. This is not a speed value, instead power is applied for 200/255 of an amount of time at once.

Then after a moment the motors operate in the reverse direction (see how we changed the HIGHs and LOWs in thedigitalWrite() functions?).

To get an idea of the range of speed possible of your hardware, we run through the entire PWM range in the function demoTwo() which turns the motors on and them runs through PWM values zero to 255 and back to zero with the two for loops.

Controlling a Stepper Motor

Stepper motors may appear to be complex, but nothing could be further than the truth. In this example we control a typical NEMA-17 stepper motor that has four wires:

stepper motor from PMD Way

It has 200 steps per revolution, and can operate at at 60 RPM. If you don’t already have the step and speed value for your motor, find out now and you will need it for the sketch.

The key to successful stepper motor control is identifying the wires – that is which one is which. You will need to determine the A+, A-, B+ and B- wires. With our example motor these are red, green, yellow and blue. Now let’s get the wiring done.

Connect the A+, A-, B+ and B- wires from the stepper motor to the module connections 1, 2, 13 and 14 respectively. Place the jumpers included with the L298N module over the pairs at module points 7 and 12. Then connect the power supply as required to points 4 (positive) and 5 (negative/GND).

Once again if your stepper motor’s power supply is less than 12V, fit the jumper to the module at point 3 which gives you a neat 5V power supply for your Arduino.

Next, connect L298N module pins IN1, IN2, IN3 and IN4 to Arduino digital pins D8, D9, D10 and D11 respectively. Finally, connect Arduino GND to point 5 on the module, and Arduino 5V to point 6 if sourcing 5V from the module.

Controlling the stepper motor from your sketches is very simple, thanks to the Stepper Arduino library included with the Arduino IDE as standard.

To demonstrate your motor, simply load the stepper_oneRevolution sketch that is included with the Stepper library, for example:

L298N Dual Motor Controller Module 2A from PMD Way

Finally, check the value for

	const int stepsPerRevolution = 200;

in the sketch and change the 200 to the number of steps per revolution for your stepper motor, and also the speed which is preset to 60 RPM in the following line:

	myStepper.setSpeed(60);

Now you can save and upload the sketch, which will send your stepper motor around one revolution, then back again. This is achieved with the function

	myStepper.step(stepsPerRevolution); // for clockwise
	myStepper.step(-stepsPerRevolution); // for anti-clockwise

So there you have it, an easy an inexpensive way to control motors with your Arduino or compatible board.

This post brought to you by pmdway.com everything for makers and electronics enthusiasts, with free delivery worldwide.

To keep up to date with new posts at tronixstuff.com, please subscribe to the mailing list in the box on the right, or follow us on twitter @tronixstuff.

Tutorial – PCF8574 backpacks for LCD modules and Arduino

Learn how to use inexpensive serial backpacks with character LCD modules with your Arduino.

Introduction

Using LCD modules with your Arduino is popular, however the amount of wiring requires time and patience to wire it up correctly – and also uses a lot of digital output pins. That’s why we love these serial backpack modules – they’re fitted to the back of your LCD module and allows connection to your Arduino (or other development board) with only four wires – power, GND, data and clock.

You can use this with LCD modules that have a HD44780-compatible interface with various screen sizes. For example a 16 x 2 module:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

The backpack can also be used with 20 x 4 LCDs. The key is that your LCD must have the interface pads in a single row of sixteen, so it matches the pins on the backpack – for example:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Hardware Setup

Now let’s get started. First you need to solder the backpack to your LCD module. While your soldering iron is warming up, check that the backpack pins are straight and fit in the LCD module, for example:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Then solder in the first pin, while keeping the backpack flush with the LCD:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

If it’s a bit crooked, you can reheat the solder and straighten it up again. Once you’re satisfied with the alignment, solder in the rest of the pins:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Now to keep things neat, trim off the excess header pins:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Once you’ve finished trimming the header pins, get four male to female jumper wires and connect the LCD module to your Arduino as shown in the following image and table. Then connect your Arduino to the computer via USB:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way
16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Software Setup

The next step is to download and install the Arduino I2C LCD library for use with the backpack. First of all, rename the “LiquidCrystal” library folder in your Arduino libraries folder. We do this just to keep it as a backup.

If you’re not sure where your library folder can be found – it’s usually in your sketchbook folder, whose location can usually be found in the Arduino IDE preferences menu:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

Next, visit https://bitbucket.org/fmalpartida/new-liquidcrysta… and download the latest file, currently we’re using v1.2.1. Expanding the downloaded .zip file will reveal a new “LiquidCrystal” folder – copy this into your Arduino libraries folder.

Now restart the Arduino IDE if it was already running – or open it now. To test the module we have a demonstration sketch prepared, simply copy and upload the following sketch:

/* Demonstration sketch for PCF8574T I2C LCD Backpack 
Uses library from https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads GNU General Public License, version 3 (GPL-3.0) */
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C	lcd(0x27,2,1,0,4,5,6,7); // 0x27 is the I2C bus address for an unmodified backpack

void setup()
{
  // activate LCD module
  lcd.begin (16,2); // for 16 x 2 LCD module
  lcd.setBacklightPin(3,POSITIVE);
  lcd.setBacklight(HIGH);
}

void loop()
{
  lcd.home (); // set cursor to 0,0
  lcd.print(" tronixlabs.com"); 
  lcd.setCursor (0,1);        // go to start of 2nd line
  lcd.print(millis());
  delay(1000);
  lcd.setBacklight(LOW);      // Backlight off
  delay(250);
  lcd.setBacklight(HIGH);     // Backlight on
  delay(1000);
}

After a few moments the LCD will be initialised and start to display our URL and the value for millis, then blink the backlight off and on.

If the text isn’t clear, or you just see white blocks – try adjusting the contrast using the potentiometer on the back of the module.

How to control the backpack in your sketch

As opposed to using the LCD module without the backpack, there’s a few extra lines of code to include in your sketches. To review these, open the example sketch mentioned earlier.

You will need the libraries as shown in lines 3, 4 and 5 – and initialise the module as shown in line 7. Note that the default I2C bus address is 0x27 – and the first parameter in the LiquidCrystal_I2C function.

Finally the three lines used in void setup() are also required to initialise the LCD. If you’re using a 20×4 LCD module, change the parameters in the lcd.begin() function.

From this point you can use all the standard LiquidCrystal functions such as lcd.setCursor() to move the cursor and lcd.write() to display text or variables as normal. The backlight can also be turned on and off with lcd.setBacklight(HIGH) or lcd.setBacklight(LOW).

You can permanently turn off the backlight by removing the physical jumper on the back of the module.

Changing the I2C bus address

If you want to use more than one module, or have another device on the I2C bus with address 0x27 then you’ll need to change the address used on the module. There are eight options to choose from, and these are selected by soldering over one or more of the following spots:

16 x 2 character LCD (white text blue background) with parallel interface from PMD Way

There are eight possible combinations, and these are described in Table 4 of the PCF8574 data sheet which can be downloaded from the NXP website. If you’re unsure about the bus address used by the module, simply connect it to your Arduino as described earlier and run the I2C scanner sketch from the Arduino playground.

This post brought to you by pmdway.com everything for makers and electronics enthusiasts, with free delivery worldwide.

To keep up to date with new posts at tronixstuff.com, please subscribe to the mailing list in the box on the right, or follow us on twitter @tronixstuff.