Hackatronics Arduino Multi Function Shield PDF
Hackatronics Arduino Multi Function Shield PDF
Using an
Arduino Multi-function Shield
By Kashif Baig
2015 cohesivecomputing.co.uk
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
When I was about 10 years old my folks bought me a C64 computer, and very soon I was learning
how to connect some basic components and sensors to its joystick and parallel ports to try and do
some interesting things. This was way back in 1983. On one occasion, I actually managed to fry this
350 computer while soldering a wire that was connected to a port when it was switched on.
Fortunately, I got the C64 repaired at minimal cost, but dont try something like that yourself.
Today, the Raspberry Pi and Arduino range of microcontrollers is a great way to start to learn how
to write code that connects with the outside world. In addition, there are numerous electronic add-
ons with components already built on to them, ready to be utilized with a bit of code. One such
add-on is a multi-function Arduino shield available at low cost from internet suppliers, one such
being Hobby Components:
Simple I/O that is usually taken for granted on PCs, like reading key presses, outputting to a
display, and sounding an alarm, often get in the way of the focus of the main task when developing
for microcontrollers. It is for this reason I have developed a library for this multi-function shield
that simplifies basic and mundane I/O operations. I also provide a set of real world applications that
make use of this library as part of a coding series, so those new to coding on the Arduino can
experiment with and enhance them. Well, thats how I learnt how to code all those years ago.
Some familiarity with the Arduino platform is assumed, as is the installation of the Arduino
development environment. A demo video of some of the Arduino applications is available from my
website.
You can download the multi-function shield library from the link below and install as a .zip library,
referring to the instructions in the link above:
If for any reason you havent been successful installing any of the libraries, then download this
library bundle instead, unzip and copy to your Documents\Arduino\libraries folder (if using
Windows) or OS equivalent. Although we do everything to ensure our downloads are free from
viruses and malware, please check that your virus and malware scanning software is up to date
before hand.
I must point out that by following the Hackatronics series, you agree to do so at your own risk, and
agree to take full responsibility for any loss or damages you may incur upon yourself or others. If
youre a kid starting out, be sure to have supervision of a responsible adult.
Page 3 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
2. Reading Sensors
3. Real World Applications
Part 1 demonstrates the ease with which the multi-function shield buttons, beeper and display can
utilized by using the shield library, consequently making it easier to concentrate on the logic of the
application.
Part 2 demonstrates how the shield library can be used to read values from external sensors, such as
temperature, sonar and motion sensors, and how to process electronic pulses from an external
source.
Part 3 explores working applications using the library and the multi-function shield:
Each of these has scope to be built upon and expanded, but I leave that to you.
Page 4 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
This is part one of the Applied Hackatronics Series for the Arduino Multi-function shield, which
shows how to use the shield library to access the multi-function shield buttons, buzzer and display.
If you havent already done so, youll need to download the source code and install the libraries
using the links in the introduction.
By following the Hackatronics series, you agree to do so at your own risk, and agree to take full
responsibility for any loss or damages you may incur upon yourself or others.
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
MFS.initialize(&Timer1); // initialize multi-function shield library
delay(1000);
void loop() {
// put your main code here, to run repeatedly:
void setup() {
Page 5 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
void loop() {
// put your main code here, to run repeatedly:
if (btn)
{
byte buttonNumber = btn & B00111111;
byte buttonAction = btn & B11000000;
Serial.print("BUTTON_");
Serial.write(buttonNumber + '0');
Serial.print("_");
if (buttonAction == BUTTON_PRESSED_IND)
{
Serial.println("PRESSED");
}
else if (buttonAction == BUTTON_SHORT_RELEASE_IND)
{
Serial.println("SHORT_RELEASE");
}
else if (buttonAction == BUTTON_LONG_PRESSED_IND)
{
Serial.println("LONG_PRESSED");
}
else if (buttonAction == BUTTON_LONG_RELEASE_IND)
{
Serial.println("LONG_RELEASE");
}
}
}
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
MFS.initialize(&Timer1); // initialize multi-function shield library
MFS.write("Hi");
delay(2000);
MFS.write(-273);
delay(2000);
MFS.write(3.141, 2); // display to 2 decimal places.
delay(2000);
}
int counter=0;
byte ended = false;
Page 6 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
void loop() {
// put your main code here, to run repeatedly:
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
MFS.initialize(&Timer1); // initialize multi-function shield library
MFS.writeLeds(LED_ALL, ON);
delay(2000);
MFS.blinkLeds(LED_1 | LED_2, ON);
delay(2000);
MFS.blinkLeds(LED_1 | LED_2, OFF);
void loop() {
// put your main code here, to run repeatedly:
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
Page 7 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
void loop() {
// put your main code here, to run repeatedly:
MFS.write(analogRead(POT_PIN));
delay(100);
}
All the code samples and applications have been tested and work. If you experience any difficulties,
please leave a comment, and Ill get back to you as soon as I can.
Page 8 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
This is part two of the Applied Hackatronics Series for the Arduino Multi-function shield, and
shows how the multi-function shield library can be used to read values from external sensors, such
as temperature, sonar and motion sensors, and how to process electronic pulses from an external
source. If you havent already done so, youll need to download the source code and install the
libraries using the links in the introduction.
By following the Hackatronics series, you agree to do so at your own risk, and agree to take full
responsibility for any loss or damages you may incur upon yourself or others.
Counting pulses
The multi-function shield library has support for counting pulses (up to 500Hz) applied to an input
pin of the Arduino. The counting of pulses is managed in the background using interrupts, which
allows your application to focus on performing its main task. After uploading this sketch, repeatedly
press button 1 to generate the pulses and see a reading of the press rate on the digit display.
#include <TimerOne.h>
#include <Wire.h>
#include <MultiFuncShield.h>
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
MFS.initialize(&Timer1); // initialize multi-function shield library
MFS.initPulseInCounter(
BUTTON_1_PIN, // use button 1 as means of generating pulses.
1500, // the number of milliseconds to wait for a pulse, before
resetting pulse in period to 0.
LOW // trigger pulse on LOW input.
);
}
void loop() {
// put your main code here, to run repeatedly:
if (pulsePeriodMs == 0)
{
MFS.write(0.0, 1);
}
else
{
MFS.write(1000.0 / pulsePeriodMs, 1); // calculate pulses per second. Display
to 1 decimal place.
}
}
Page 9 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
#include <TimerOne.h>
#include <Wire.h>
#include <MultiFuncShield.h>
// NOTE: make sure jumper J1 is removed from shield, and that LM35 is inserted
correctly.
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
MFS.initialize(&Timer1); // initialize multi-function shield library
void loop() {
// put your main code here, to run repeatedly:
delay(100);
}
#include <TimerOne.h>
#include <Wire.h>
#include <MultiFuncShield.h>
Page 10 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
void setup() {
// put your setup code here, to run once:
pinMode(TrigPin, OUTPUT);
pinMode(EchoPin, INPUT);
Timer1.initialize();
MFS.initialize(&Timer1); // initialize multi-function shield library
void loop() {
// put your main code here, to run repeatedly:
MFS.write((int)MFS.getSonarDataCm(TrigPin, EchoPin));
delay(100);
}
#define _SOFTI2C_H
#include <SoftI2CMaster.h>
#include <Wire.h>
#include <TimerOne.h>
#include <MultiFuncShield.h>
#include "SoftwareI2C.h"
#include "I2C.h"
#include "MPU6050.h"
#define SOFTWARE_I2C
MPU6050 MPU;
void displayHeading(byte mode);
void setup() {
Serial.begin(9600);
Page 11 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
// Uno and Leonardo, use pin 5 for SCL and 6 for SDA. Mega2560, use pin A5 for
SDA.
SoftI2C1.initialize();
MPU.initialize(&SoftI2C1, MPU_DEFAULT_ADDRESS << 1);
#else
// Use hardware I2C
Wire.begin();
I2C1.initialize(&Wire);
MPU.initialize(&I2C1, MPU_DEFAULT_ADDRESS);
#endif
MFS.initialize(&Timer1);
MFS.write("Acc");
}
void loop() {
// put your main code here, to run repeatedly:
if (displayValues)
{
displayHeading(displayMode);
}
else
{
MFS.write("Off");
}
}
if (displayValues)
{
// Use button 2 to cycle though the display modes.
if (btn == BUTTON_2_PRESSED)
{
displayMode++;
if (displayMode == 3)
{
displayMode = 0;
}
displayHeading(displayMode);
}
if (displayMode == 0)
{
// display raw acceleration values.
MPU.getAccelRaw();
Serial.print((float)MPU.accel_X_Raw / MPU.accelScaleValue);
Serial.print("\t");
Serial.print((float)MPU.accel_Y_Raw / MPU.accelScaleValue);
Serial.print("\t");
Serial.print((float)MPU.accel_Z_Raw / MPU.accelScaleValue);
Serial.print("\t\n");
}
else if (displayMode == 1)
{
// display raw gyrovalues
MPU.getGyroRaw();
Serial.print((float)MPU.gyro_X_Raw / MPU.gyroScaleValue);
Page 12 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
Serial.print("\t");
Serial.print((float)MPU.gyro_Y_Raw / MPU.gyroScaleValue);
Serial.print("\t");
Serial.print((float)MPU.gyro_Z_Raw / MPU.gyroScaleValue);
Serial.print("\t\n");
}
else if (displayMode == 2)
{
// display temperature value.
Serial.println((float)MPU.getTemp10th() / 10);
}
}
delay(50);
}
All the code samples and applications have been tested and work. If you experience any difficulties,
please leave a comment, and Ill get back to you as soon as I can.
Page 13 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
This is part three of the Applied Hackatronics Series for the Arduino Multi-function shield, and
explores working applications using the library and the multi-function shield. If you havent already
done so, youll need to download the source code and install the libraries using the links in the
introduction.
For each of the applications below there is an accompanying online video, as well as a summary
video.
By following the Hackatronics series, you agree to do so at your own risk, and agree to take full
responsibility for any loss or damages you may incur upon yourself or others.
Countdown timer
This countdown timer is similar to a countdown timer you might find in a microwave oven. You set
the time, start the countdown timer, and when it reaches zero, the alarm sounds. You can
pause/continue the timer, and reset to zero. Use the multi-function shield buttons 2 and 3 to set the
minutes and seconds. A short press of button 1 starts or stops the timer, and a long press resets it.
Possible enhancements for this application are to have a device switched on only whilst the timer is
counting down.
#include <TimerOne.h>
#include <Wire.h>
#include <MultiFuncShield.h>
enum CountDownModeValues
{
COUNTING_STOPPED,
COUNTING
};
byte tenths = 0;
char seconds = 0;
char minutes = 0;
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
MFS.initialize(&Timer1); // initialize multi-function shield library
MFS.write(0);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
switch (countDownMode)
{
case COUNTING_STOPPED:
if (btn == BUTTON_1_SHORT_RELEASE && (minutes + seconds) > 0)
{
// start the timer
countDownMode = COUNTING;
Page 14 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
}
else if (btn == BUTTON_1_LONG_PRESSED)
{
// reset the timer
tenths = 0;
seconds = 0;
minutes = 0;
MFS.write(minutes*100 + seconds);
}
else if (btn == BUTTON_2_PRESSED || btn == BUTTON_2_LONG_PRESSED)
{
minutes++;
if (minutes > 60)
{
minutes = 0;
}
MFS.write(minutes*100 + seconds);
}
else if (btn == BUTTON_3_PRESSED || btn == BUTTON_3_LONG_PRESSED)
{
seconds += 10;
if (seconds >= 60)
{
seconds = 0;
}
MFS.write(minutes*100 + seconds);
}
break;
case COUNTING:
if (btn == BUTTON_1_SHORT_RELEASE || btn == BUTTON_1_LONG_RELEASE)
{
// stop the timer
countDownMode = COUNTING_STOPPED;
}
else
{
// continue counting down
tenths++;
if (tenths == 10)
{
tenths = 0;
seconds--;
MFS.write(minutes*100 + seconds);
}
delay(100);
}
break;
}
}
Page 15 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
This application demonstrates a digital clock with an alarm capability. When the Arduino is
powered on, the multi-function shield display flashes until the user sets the time. Hold button 1 to
set the time or alarm. When setting the time use button 3 to set the hour or minutes. Press button 2
to view alarm time or cancel the alarm if in progress. Holding button 3 enables or disables the alarm
(LED1 indicates alarm is enabled). Possible enhancements to this application are to have a snooze
feature, or to have multiple on/off periods during the day for a device.
#include <TimerOne.h>
#include <Wire.h>
#include <MultiFuncShield.h>
/*
button 1 : hold to set time or alarm
button 2 : press to view alarm time or cancel alarm if in progress
button 3 : increment hour / minute when setting (alarm) time. Hold to toggle
alarm setting.
enum displayModeValues
{
MODE_CLOCK_TIME,
MODE_CLOCK_TIME_SET_HOUR,
MODE_CLOCK_TIME_SET_MINUTE,
MODE_ALARM_TIME,
MODE_ALARM_TIME_SET_HOUR,
MODE_ALARM_TIME_SET_MINUTE
};
//-------------------------------------------------------------------------------
void setup()
{
Timer1.initialize();
MFS.userInterrupt = clockISR;
MFS.initialize(&Timer1);
MFS.blinkDisplay(DIGIT_ALL);
//MFS.beep(500);
}
void loop()
{
// put your main code here, to run repeatedly:
switch (displayMode)
{
case MODE_CLOCK_TIME:
displayTime(clockHours, clockMinutes);
Page 16 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
if (btn == BUTTON_2_PRESSED)
{
MFS.beep(0); // cancel the alarm.
displayMode = MODE_ALARM_TIME;
}
else if (btn == BUTTON_1_LONG_PRESSED)
{
MFS.blinkDisplay(DIGIT_ALL, OFF);
MFS.blinkDisplay(DIGIT_1 | DIGIT_2);
displayMode = MODE_CLOCK_TIME_SET_HOUR;
clockEnabled = false;
clockMilliSeconds = 0;
clockSeconds = 0;
}
else if (btn == BUTTON_3_LONG_PRESSED && !alarmTogglePressed)
{
alarmTogglePressed = true;
alarmEnabled = !alarmEnabled;
MFS.writeLeds(LED_1, alarmEnabled);
}
else if (btn == BUTTON_3_LONG_RELEASE)
{
alarmTogglePressed = false;
}
break;
case MODE_CLOCK_TIME_SET_HOUR:
if (btn == BUTTON_1_PRESSED)
{
MFS.blinkDisplay(DIGIT_1 | DIGIT_2, OFF);
MFS.blinkDisplay(DIGIT_3 | DIGIT_4);
displayMode = MODE_CLOCK_TIME_SET_MINUTE;
}
else if (btn == BUTTON_3_PRESSED || btn == BUTTON_3_LONG_PRESSED)
{
clockHours++;
if (clockHours >= 24)
{
clockHours = 0;
}
displayTime(clockHours, clockMinutes);
}
break;
case MODE_CLOCK_TIME_SET_MINUTE:
if (btn == BUTTON_1_PRESSED)
{
MFS.blinkDisplay(DIGIT_3 | DIGIT_4, OFF);
displayMode = MODE_CLOCK_TIME;
clockEnabled = true;
}
else if (btn == BUTTON_3_PRESSED || btn == BUTTON_3_LONG_PRESSED)
{
clockMinutes++;
if (clockMinutes >= 60)
{
clockMinutes = 0;
}
displayTime(clockHours, clockMinutes);
}
break;
case MODE_ALARM_TIME:
displayTime(alarmHours, alarmMinutes);
Page 17 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
MFS.blinkDisplay(DIGIT_ALL, OFF);
MFS.blinkDisplay(DIGIT_1 | DIGIT_2);
displayMode = MODE_ALARM_TIME_SET_HOUR;
alarmEnabled = false;
}
break;
case MODE_ALARM_TIME_SET_HOUR:
if (btn == BUTTON_1_PRESSED)
{
MFS.blinkDisplay(DIGIT_1 | DIGIT_2, OFF);
MFS.blinkDisplay(DIGIT_3 | DIGIT_4);
displayMode = MODE_ALARM_TIME_SET_MINUTE;
}
else if (btn == BUTTON_3_PRESSED || btn == BUTTON_3_LONG_PRESSED)
{
alarmHours++;
if (alarmHours >= 24)
{
alarmHours = 0;
}
displayTime(alarmHours, alarmMinutes);
}
break;
case MODE_ALARM_TIME_SET_MINUTE:
if (btn == BUTTON_1_PRESSED)
{
MFS.blinkDisplay(DIGIT_3 | DIGIT_4, OFF);
displayMode = MODE_CLOCK_TIME;
alarmEnabled = true;
MFS.writeLeds(LED_1, ON);
}
else if (btn == BUTTON_3_PRESSED || btn == BUTTON_3_LONG_PRESSED)
{
alarmMinutes++;
if (alarmMinutes >= 60)
{
alarmMinutes = 0;
}
displayTime(alarmHours, alarmMinutes);
}
break;
}
}
//--------------------------------------------------------------------------------
void clockISR ()
{
// Perform ripple count for all time components.
if (clockEnabled)
{
clockMilliSeconds++;
if (clockMilliSeconds >= 1000)
{
clockMilliSeconds = 0;
clockSeconds++;
if (clockSeconds >= 60)
{
clockSeconds = 0;
Page 18 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
clockMinutes++;
if (clockMinutes >= 60)
{
clockMinutes = 0;
clockHours++;
if (clockHours >= 24)
{
clockHours = 0;
}
}
// If current time coincides with alarm time, and alarm is enabled, engage
the alarm.
if (alarmEnabled && (clockMinutes == alarmMinutes) && (clockHours ==
alarmHours))
{
MFS.beep(
10, // on period
5, // off period
4, // number of cycles
100, // number of loop cycles
50 // delay between loop cycles
);
}
}
}
}
}
Heart monitor
After powering on the Arduino, gently but firmly place the index finger on the sensor and wait for
the display to start blinking. This indicates the sensor has normalized, after which the shield display
will show the beats per minute, and the beeper will sound. If the display remains at 0 and doesnt
blink after several seconds, remove the finger, wait for a while and try again. Ensure the finger is
placed with consistent pressure.
Possible modification for this application is to have an LED light synchronised with each heart beat.
#include <TimerOne.h>
#include <Wire.h>
#include <MultiFuncShield.h>
void initializeSensorReading();
int data[4];
byte dataIdx=0;
Page 19 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
MFS.initialize(&Timer1);
initializeSensorReading();
//Serial.begin(9600);
}
void loop()
{
if (MFS.getTimer() == 0)
{
MFS.setTimer(10000); // reset millisecond countdown timer.
if (lastPulseTime != -1)
{
lastPulseTime = 10000 + lastPulseTime;
}
}
if (lastPulseTime == -1)
{
lastPulseTime = MFS.getTimer();
}
else
{
int pulsePeriod = lastPulseTime - MFS.getTimer(); // calculate time
between pulses in millseconds.
lastPulseTime = MFS.getTimer();
if (bpm < 45 || bpm > 230) // bpm is outside acceptible range, so clear
the data buffer.
{
initializeSensorReading();
}
else
{
// bpm is within range, but still need to calculate average.
data[dataIdx++] = bpm;
if (dataIdx >= 4)
{
dataIdx = 0;
}
Page 20 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
if (data[0] && data[1] && data[2] && data[3]) // check if data buffer
is full before calculating avg bpm.
{
int avgBpm = (data[0] + data[1] + data[2] + data[3]) / 4;
MFS.blinkDisplay(DIGIT_ALL, OFF);
MFS.write(avgBpm);
MFS.beep();
}
else
{
// buffer not full, so blink the display.
MFS.blinkDisplay(DIGIT_ALL, ON);
}
}
}
}
}
else if (sensorValue < (1024 / 2)) // value is falling, so must be end of
pulse.
{
pulseDetected = false;
}
//Serial.println(sensorValue);
//delay(10);
}
dataIdx = 0;
for (int i=0; i<4; i++)
{
data[i] = 0;
}
MFS.write(0);
MFS.blinkDisplay(DIGIT_ALL, OFF);
}
The surface incline indicator application uses the MPU6050 motion sensor to determine the angle of
inclination of a flat surface. You will need to download the full source code before uploading to the
Arduino. Because the application uses software I2C, when using R3 boards Uno and Leonardo, use
pin 5 for SCL and 6 for SDA. For Mega2560, use pin 5 for SCL and pin A5 for SDA.
After powering on the Arduino, place the motion sensor on a surface that is as level as possible,
then press and hold button 1 on the multi-function shield. LED 1 blinks while the sensor is
calibrated. Thereafter, by placing the motion sensor on inclined surfaces the shield will display the
angle of inclination.
Presently the incline is displayed only for a single axis, but the application could modified to the
show the incline for an additional axis.
#define _SOFTI2C_H
#include <SoftI2CMaster.h>
#include <Wire.h>
#include <TimerOne.h>
#include <MultiFuncShield.h>
Page 21 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
#include "SoftwareI2C.h"
#include "I2C.h"
#include "MPU6050.h"
#define SOFTWARE_I2C
void calibrate();
MPU6050 MPU;
void setup() {
// put your setup code here, to run once:
Timer1.initialize();
MFS.initialize(&Timer1);
}
void loop() {
// put your main code here, to run repeatedly:
if (btn == BUTTON_1_LONG_PRESSED)
{
calibrate();
}
MPU.getAccelRaw();
MPU.accel_X_Raw -= xOffset;
MPU.accel_Y_Raw -= yOffset;
float angle;
if (MPU.accel_Z_Raw == 0)
{
angle = 90;
}
else
{
angle = atan((float)MPU.accel_Y_Raw / (MPU.accel_Z_Raw * zScaleOffset)) *
radToDeg; // calculate for y axis
//angle = atan((float)MPU.accel_X_Raw / (MPU.accel_Z_Raw * zScaleOffset)) *
radToDeg; // calculate for X axis
}
MFS.write(angle, 1);
delay(200);
}
Page 22 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
void calibrate()
{
MFS.write(" ");
MFS.writeLeds(LED_1, ON);
MFS.blinkLeds(LED_1, ON);
MFS.blinkLeds(LED_1, OFF);
Sonar ranger
The sonar ranger application uses the HC SR04 sonar module to measure distance between the
module and a solid object up to 5 meters away. This application works in a way similar to the
obstacle sensor of some vehicles the assist the driver in parking manoeuvres. As an obstacle nears
the sonar module, the beeper is sounded at shorter and shorter intervals. The shields button 1 is
used for engaging or disengaging the sonar module.
The trigger and echo pins of the sonar module are connected to Arduino pins 5 and 6 respectively,
which are exposed on the multi-function shield. After powering on the Arduino, place a solid object
at different distances away from the sonar module.
#include <TimerOne.h>
#include <Wire.h>
#include <MultiFuncShield.h>
enum sonarModeValues
{
MODE_SONAR_OFF,
MODE_SONAR_ON
};
void setup()
Page 23 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
{
//Serial.begin(9600);
pinMode(TrigPin, OUTPUT);
pinMode(EchoPin, INPUT);
Timer1.initialize();
MFS.initialize(&Timer1);
MFS.write("off");
}
void loop()
{
byte btn = MFS.getButton();
switch (sonarMode)
{
case MODE_SONAR_OFF:
if (btn == BUTTON_1_PRESSED)
{
sonarMode = MODE_SONAR_ON;
MFS.beep(5, 95, 1,0,0);
MFS.write("on");
}
break;
case MODE_SONAR_ON:
if (btn == BUTTON_1_PRESSED)
{
sonarMode = MODE_SONAR_OFF;
MFS.beep(0);
MFS.write("off");
MFS.blinkDisplay(DIGIT_ALL, OFF);
MFS.initSonar();
}
else
{
int distance = MFS.getSonarDataCm(TrigPin, EchoPin);
if (offPeriod < 0)
{
offPeriod = 0;
}
MFS.write(distance);
MFS.setBeepOffPeriod(offPeriod);
Speedometer
The speedometer application calculates the speed of a wheel (in kilometres/hour) by using a magnet
and a reed switch, which is connected to Arduino pin 5. It should also be possible to fabricate your
own wheel encoder using a line or mark sensor.
After powering on the Arduino, press and hold button 1 of the multi-function shield until the
display blinks, then use buttons 2 and 3 to set the wheel diameter in centimetres. Press button 1
again when finished. Turn the wheel to see the speed indicated on the shield display.
Page 24 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
A possible enhancement for this application is to keep a record of trip distance in kilometres.
#include <TimerOne.h>
#include <Wire.h>
#include <MultiFuncShield.h>
enum SpeedoModeValues
{
SETUP_WHEEL,
CALCULATE_SPEED
};
void setup() {
// put your setup code here, to run once:
pinMode(5, INPUT_PULLUP);
Timer1.initialize();
MFS.initialize(&Timer1);
MFS.initPulseInCounter(
5, // use digital pin 5 for pulse input.
2000, // the number of milliseconds to wait for a pulse, before
resetting pulse in period to 0.
LOW // trigger pulse on LOW input.
);
}
void loop() {
// put your main code here, to run repeatedly:
switch (speedoMode)
{
case SETUP_WHEEL:
if (btn == BUTTON_1_PRESSED)
{
speedoMode = CALCULATE_SPEED;
MFS.blinkDisplay(DIGIT_ALL, OFF);
wheelCirmcumferenceCm = (wheelDiameterCm * 314) / 100;
}
else if (btn == BUTTON_2_PRESSED || btn == BUTTON_2_LONG_PRESSED)
{
wheelDiameterCm--;
Page 25 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
MFS.write(wheelDiameterCm);
}
break;
case CALCULATE_SPEED:
if (btn == BUTTON_1_LONG_PRESSED)
{
speedoMode = SETUP_WHEEL;
MFS.write(wheelDiameterCm);
MFS.blinkDisplay(DIGIT_ALL, ON);
}
else
{
unsigned int pulsePeriodMs = MFS.getPulseInPeriod();
if (pulsePeriodMs == 0)
{
MFS.write(0.0, 1);
}
else
{
MFS.write(SpeedKmh(wheelCirmcumferenceCm, pulsePeriodMs), 1);
}
}
break;
}
delay(100);
}
All the code samples and applications have been tested and work. If you experience any difficulties,
please post a comment, and Ill get back to you as soon as I can.
Page 26 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
Appendices
Multi-function Shield Library Help
#define ON 1
#define OFF 0
#define LED_1_PIN 13
#define LED_2_PIN 12
#define LED_3_PIN 11
#define LED_4_PIN 10
#define POT_PIN 0
#define BEEPER_PIN 3
#define BUTTON_1_PIN A1
#define BUTTON_2_PIN A2
#define BUTTON_3_PIN A3
#define LATCH_PIN 4
#define CLK_PIN 7
#define DATA_PIN 8
#define LM35_PIN A4
#define DIGIT_1 1
#define DIGIT_2 2
#define DIGIT_3 4
#define DIGIT_4 8
#define DIGIT_ALL 15
#define LED_1 1
#define LED_2 2
#define LED_3 4
#define LED_4 8
#define LED_ALL 15
#define SMOOTHING_NONE 0
#define SMOOTHING_MODERATE 1
#define SMOOTHING_STRONG 2
class MultiFuncShield
{
public:
// Pointer to user interrupt with frequency of 1khz.
void (*userInterrupt)() = NULL;
Page 27 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
// Initializes this instance, but interrupt based features are not available.
void initialize();
// Engage the beeper, which is managed in the background. Period timing is in 100th
of second
void beep(unsigned int onPeriod = 20, unsigned int offPeriod = 0, byte cycles = 1,
unsigned int loopCycles = 1 /* 0=indefinitely */, unsigned int loopDelayPeriod =0);
// Use this to set the off period whilst the beeper is engaged,
void setBeepOffPeriod(unsigned int offPeriod);
// Queues button short press and release actions. Long button presses are not
supported, and long releases are reported as short releases.
// Should not be used whilst interrupt based features are available.
void manualButtonHandler();
// Initializes the pulse counter. Used for counting pulses applied to an input pin.
Max pulse frequency 500hz.
void initPulseInCounter(byte pin = BUTTON_1_PIN, // input pin
unsigned int timeOut = 3000, // the number of milliseconds
to wait for a pulse, before resetting pulse in period to 0.
byte trigger = LOW // trigger counter on either
rising or falling edge
);
Page 28 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
// Sets the pulse in timeout, which is the number of milliseconds to wait for a
pulse, before resetting pulse in period to 0.
void setPulseInTimeOut(unsigned int timeOut);
// Initializes temperature reading feature. Needs LM35 sensor. Must remove jumper J1
from shield.
void initLM35(byte level = SMOOTHING_MODERATE); // level 0=none, 1=moderate, 2=strong
};
Page 29 of 30
Hackatronics Using an Arduino Multi-function Shield cohesivecomputing.co.uk
MPU6050 Help
class MPU6050
{
public:
int accel_X_Raw;
int accel_Y_Raw;
int accel_Z_Raw;
int gyro_X_Raw;
int gyro_Y_Raw;
int gyro_Z_Raw;
// accel scale
#define ACCEL_FS_2 0x00
#define ACCEL_FS_4 0x01
#define ACCEL_FS_8 0x02
#define ACCEL_FS_16 0x03
// gyro scale
#define GYRO_FS_250 0x00
#define GYRO_FS_500 0x01
#define GYRO_FS_1000 0x02
#define GYRO_FS_2000 0x03
// dlpf
#define DLPF_BW_256 0x00
#define DLPF_BW_188 0x01
#define DLPF_BW_98 0x02
#define DLPF_BW_42 0x03
#define DLPF_BW_20 0x04
#define DLPF_BW_10 0x05
#define DLPF_BW_5 0x06
Page 30 of 30