Multi-function shield for Arduino

Hackatronics – Arduino Multi-function Shield

Introduction to the Coding Series

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 we have developed a library, for the multi-function shield we have chosen, that simplifies basic I/O operations. We also provide a set of real world applications that make use of this library, so those new to coding on the Arduino can experiment with and enhance them.

Some familiarity with the Arduino platform is assumed, as is the installation of the Arduino development environment. We got our shield from Hobby Components, but there are a number of other suppliers too. NOTE there are two versions of this shield, with the later version using a different LED display that requires some minor modifications in the library code. The simplest of the changes is to modify all implementations of WriteValueToSegment() in file MultiFuncShield.cpp. Please see the comments section.

Installing the multi-function shield library

If you haven’t already done so, you will need to first install the TimerOne and Software I2C libraries using instructions for installing Arduino libraries. You can download the multi-function shield library from the link below and install using the instructions from the link above:

If for any reason you haven’t 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.

We 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 you’re a kid starting out, be sure to have supervision of a responsible adult.

More about this series

This series is divided in to three main parts (and is also available as an eBook with extra information):

  1. Basic Input / Output
  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, thereby 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:

  • 24 hour alarm clock
  • Heart monitor   – (requires heart pulse sensor)
  • Count down timer
  • Surface incline level indicator– (requires MPU6050 motion sensor)
  • Sonar ranger   – (requires HC SR04 sonar module)
  • Speedometer   – (requires magnet and reed switch)

Each of these has scope to be built upon and expanded, but we leave that to you. Get coding and have fun!

New! Want to control your Arduino with an internet browser? Check out our new Arduino Web Server

Share on LinkedInShare on Google+Tweet about this on TwitterShare on Facebook

45 thoughts on “Hackatronics – Arduino Multi-function Shield

  1. bill

    hi.. if i want all the times a value px 1.00 min or 1.30 how can store the time ??i mean the board and arduino its off ..power on and start with last timer settings .and if easy if start the timer to countdown to open a relay and closed if finish the timer ??.any help
    thanks for your time and nice video

    1. Kashif Baig Post author

      Hi Bill, I’m not sure I fully understand the first part of your question. It is possible to store the timer value in the Arduino’s eeprom, but be aware that after about 100000 memory write operations, the eeprom becomes unreliable. The best way to do this would be store the timer value in eeprom just before powering off, but you would need special circuitry for that. You would read the timer value in eeprom on power up.

      To power a relay would need a driver IC. A mosfet IC might be a possible alternative to a relay.

  2. Luciano usuelli

    Ho caricato lo sketch led display ma non parte
    Ho caricato le librerie che voi suggerite ma sembra che la libreria multifunction non funzuona
    Cosa posso fare?
    Grazie per la aiuto

    1. Cohesive Computing

      Hi Luciano

      It is possible the library has not installed properly. Have you tried copying the library bundle file instead?

  3. Alaiksander

    I’m planning to make a pH controller. I’m thinking to purchase the hardwares. My setup will be 2 peristaltic pumps to pump pH UP and pH Down and a pH probe. I already have a 4x5v relays. Will this shield help me to achieve my setup?

  4. Walter Pletscher

    Congratulation for this very useful tool. It helped a great deal to get first hand experiences with a variety of Arduino related applications. My question is related to Part 3 – Speedometer. After powering the Arduino, the shield display starts counting back (even without holding button 1) until the number 30 appears (diameter of wheel). The sketch doesn’t react on button 2 or 3 for diameter changes. Sketch compile and upload without any error indication. Would appreciate a short feedback. Using Arduino UNO R3. Thanks.

    1. Kashif Baig Post author

      Hi Walter

      Do the other sketches have similar problems, or just the speedometer? I’m assuming you downloaded the source code zip file from here:

      I’m also assuming the correct board was selected in Arduino studio. Are you using a genuine Arduino UNO, or compatible clone? Btw, I haven’t tested the sketches using the SMD UNO, in case you’re using that edition. If you are, try using the 1.0 version of the library using the link I just mentioned.

      1. Walter Pletscher

        Dear Kashif,
        appreciate your immediate feedback – good support. Following replies:
        – I’ve tested about 6-8 other sketches with no problems at all
        – downloaded the source code (cut/paste into my arduino UNO) from your document (page 25,26)
        – using an Arduino UNO – original no compatible
        – I’ve not tested the sketch with Version 1.0 of the library

        1. Kashif Baig Post author

          Walter, I’ve pasted the same code from the document and can confirm that it does indeed work correctly. It is possible in your case the copy/paste has gone wrong somewhere. The full source code is available as a zip file from the link in my previous reply. Have you tried using that instead?

          1. Walter Pletscher

            Kashif, I’ve used the sketch from your source also, but the result remains the same. A test with older libraries – same result. I can only explain the wrong going, with the Multifunction Board I’ve got from the attached source:


            Please provide the source for your “original” board. Thanks a lot – appreciate again your help.

          2. Kashif Baig Post author

            I have a number of these shields from different sources, including one that is just like you have (look where it is written multi function shield, it is spelled incorrectly). Do you have a jumper block on both J2 pins? Could you also provide a link to the exact Arduino you have.

            Upload and run the Buttons sketch in the Basic Input Output folder of the source code zip file, and open the serial monitor. If no buttons are pressed, nothing should be output in the serial monitor. If you are getting false readings, then run the same sketch without the shield. If the false readings stop, it could be a faulty shield.

  5. Walter Pletscher

    Good evening Kashif,
    perfect advice. It was the missing jumper on J2. I can modify wheel diameter (up or down) with either button 2 or button 3. Thank you for your help. And by the way, it’s a board with the name multi function shield spelled incorrectly. I use an Arduino UNO Board Model UNO R3 with a DIL Version of the ATMEGA328P-PU.

    I would like to adapt your sketch for very tiny wheel diameters (9 to 11mm) and the application will be speed and distance measurement for my model train (H0 scale).
    Once again, your support was just excellent – thank you.

  6. olugbenga adebanjo

    Hi Kashif and welldone for the amazing work you’re doing. I am trying to implement your code on a new but generic MFB. At the moment I can’t get to hear any beeping sound both for the countdown and the alarm clock. Also, how does the J1 and J2 work?

    Thanks in advance for your support.

  7. Luis Enrique Piña Juárez

    Hi, im using the countdown for testing, but I have isuues with the 5 and 6, showing a 9 istead a 5, and a 8 instead the 6, do you know what could be causing this ?

    1. Kashif Baig Post author

      Hi Luis. With some Arduinos, the metal part of the USB connector makes contact with connections under the shield. If that is what you are experiencing, then insulate the part of the USB connector that makes contact.

  8. Wolfgang

    Hi. I have a question.
    When the sketch starts, the display is powered off. When it shows a digit or a letter, if i do MFS.write(OFF) it doesnt power off the display and shows a 0. How can i turn off the display??
    This is the sketch i am trying:


    void setup(){

    void loop(){
    int button;
    byte btn = MFS.getButton();
    if (btn){

    byte buttonNumber = btn & B00111111;
    byte buttonAction = btn & B11000000;
    if (buttonNumber == 1){
    button = LED_1;
    if (buttonNumber == 2){
    button = LED_2;
    if (buttonNumber == 3){
    button = LED_3;
    if (buttonAction == BUTTON_PRESSED_IND){
    MFS.writeLeds(button, ON);

    else if (buttonAction == BUTTON_SHORT_RELEASE_IND)
    MFS.writeLeds(button, OFF);


    1. Kashif Baig Post author

      You can blank out the display by writing a blank string, or string of 4 spaces:


      I hope that helps.

      1. Wolfgang

        Hi Kashif !!

        Thank you very much!! It works as expected!!

        You are the machine!! 🙂

  9. Christian T.

    I tried to make a loading bar and Found 2 Bugs:
    causes a 3 time overwrite of the first point so that only one Decimal point is displayed. The same is happening with
    of course.

    Now, it is possible to make the workaround with spaces in between, but them the second problem Kicks in:
    MFS.write(" . . . .");
    MFS.write(". . . . ");
    causes not displaying the last point of the four decimalpoints. Trying to workaround by using the rightJustify as follows
    only moves the problem to the opposite side, because the mistake takes place before rightJustify gehts to work.

    For the first one I’ve made the workaround by changing the comparator from

    for (; *text != 0 && idx < sizeof(displayBuf); text++)


    for (; *text != 0 && idx <= sizeof(displayBuf); text++)

    in MultiFuncShield.cpp forcing the last character to be read. Is that the fault of sizeof(), because it doesn’t want to count ending points, as part of the string?
    If there is something else than a point, it gets cut off anyway .. which is unclean .. but it works to solve the second bug.

  10. Uten

    I have just received two cards from China that breaks this library!

    As I’m new to Arduino (and non of the samples found on the net worked ) I thought I had borked the card by short circuiting it against the usb terminal. But when I got the second card and it behaved the same way I figured something has changed in the hw.

    As I understand it the mapping SEGMENT_MAP_* in the code are found by calculating the off segments. On my cards I have to add the ON segments. So 255 – current_value should work (and it does) on my cards. So SEGMENT_MAP_DIGIT, SEGMENT_MAP_ALPHA has to be changed.

    SEGMENT_SELECT also have to be modified: The segment selection on my cards are SEGMENT_SELECT={0x7, 0xB, 0xD, 0xE}. Seems like any multiple of 16 can be added to those numbers. Not that I have tried them all.

    Turning off a segment (witch I think is hard coded as 255?) has to be modified, as 0 now is the SEGMENT_OFF number.

    The function AsciiToSegmentValue has to be changed according to the new “add on led segments” rule.

    So in MultiFuncShield.cpp change these lines:
    const byte SEGMENT_OFF=0; //Uten added this line

    const byte SEGMENT_MAP_DIGIT[] = {63,6,91,79,102,109,124,7,127,111};
    const byte SEGMENT_MAP_ALPHA[] = {119, 124, 94, 94, 121, 113, 111, 116, 48, 14, 173, 56, 173, 84, 92, 115, 103, 80, 109, 120, 28, 73, 73, 73, 110, 73};
    const byte SEGMENT_SELECT[] = {14,13,11,7};

    WriteValueToSegment(15,SEGMENT_OFF); //Turn all off //Uten: was 255

    displayBuf[idx] = SEGMENT_OFF; //Uten was 255

    for (; i_src >= 0 && displayBuf[i_src] == SEGMENT_OFF; i_src–) ; //Uten: was 255

    displayMemory[i_dst] = SEGMENT_OFF; //Uten: was 255

    WriteValueToSegment(displayIdx, SEGMENT_OFF); //Uten: was 255

    WriteValueToSegment(displayIdx == 0 ? 3 : displayIdx-1, SEGMENT_OFF); //Uten: was 255

    switch (ascii)
    case ‘-‘:
    segmentValue = 64; //Uten was 191
    case ‘.’:
    segmentValue = 128; //Uten was 127
    case ‘_’:
    segmentValue = 8; //Uten was 247
    case ‘ ‘:
    segmentValue = SEGMENT_OFF; //Uten was 255

    Thanks for a great library and tutorial

    Best regards

  11. Shashank

    Hi, my display shows inverse of what it should- the LED’s in the seven segment displays that should be ON are OFF and vice versa. I have made sure that none of the pins at the bottom are contacting. Apart from thinking that the manufacturer has sent a bad board. The piece has correct spellings.

    1. Kashif Baig Post author

      Hi. I think you have the same issue as Uten (above). It seems there are shields that have been designed differently, see if you can incorporate his suggestions. Unfortunately, I don’t have these newer boards to test any code changes against.

      1. Jan van Heck

        Hello Kashif,
        Yes I have the same problem and implement his suggestions in the MultiFunctionShield.cpp in my personal library.
        And now I have a 100% working situation. What I couldn’t make is a Conditional Compilation like you can do in the sketch with
        #define Common_Cathode
        and then
        #ifdef Common_Cathode
        here you will find the Common Cathode code
        and here the Common Anode code
        Is there anyway a possibility to make a library with Conditional Compiling code options ?

        1. Kashif Baig Post author

          Hi Jan. In the library file MultiFuncShield.cpp there is a method WriteValueToSegment(). In fact there is a separate implementation for Uno, Leonardo and Mega2560. Perhaps you could apply a conditional XOR in this method? Is that what you’re looking for?

        2. Jan van Heck

          In the aftermath of what Uten did if have made Conditional Compilation statements in MultiFuncShield.h and *.cpp files. Standard now configured for Common Cathode 4 digit 7 segment displays. The only thing you have to change instead you have the standard shield is comment out the #define Common_Cathode statement in MultiFuncShield.h file.
          Where can I have these both modified library files to ?

          1. Jan van Heck

            After compilation of the Metronome sketch I see a warning error
            D:\Arduino\Shields\Multifunctioneel Shield\Metronome\Metronome.ino:11:1: warning: ‘typedef’ was ignored in this declaration
            Sketch uses 8884 bytes (27%) of program storage space. Maximum is 32256 bytes.
            Global variables use 418 bytes (20%) of dynamic memory, leaving 1630 bytes for local variables. Maximum is 2048 bytes.

            Could I have to ignore it ?

          2. Kashif Baig Post author

            Although I don’t get this compiler warning, it should be OK to ignore.

          3. Kashif Baig Post author

            At the moment the library files are hosted on this website. If you have a blog or website that you can upload to, I’d be happy to link to it.

        3. Jan van Heck

          Hello Kashif,
          Sorry I only can give you my email address. No website, blog, twitter etc.

  12. Jan van Heck

    Subject: Arduino Multi Function shield
    Dear Kashif Baig,

    First of all, I would like to thank you for your excellent documentation, electrical diagrams and example sketches of the Multi Function shield.

    But I also want to ask you for some help. By a local webstore I accidentally made notice of the Arduino shield. I like to use it during a Arduino beginners course of people who know absolutely nothing about the Arduino and how to program it. And because the price is so attractive, € 5.95, I’m going to work to get the students to buy this shield.

    I haven’t had any problem with most of the example sketches copied from the internet. Only those which where the 4 digit 7 segment display is used. While running, I see all segments light up but no readable numbers or characters appear.

    On the Internet I read, the 74HC595 shift register drives to these displays with “low” level signals. It is therefore the zeros in the byte that lightup the segments. In both shields I have this is not the case. After half a day experimenting, I found out that I had to convert both used segment arrays, (SEGMENT_MAP [] & SEGMENT_SELECT []) from Low level to High level active bytes. This was first done by me simply applying an XOR. And now I get readable numbers with the test sketches runs on both shields I have. Problem solved would you say.

    That’s partly true where it’s not that you’ve also made sketches that make use of a “MultiFuncShield” library. And my XOR trick does not go because I do not know how to apply this to a library. With reading and understanding how libraries works, I still have a lot of trouble with it.

    Could you probally help me with that?

    I think the problem is in the Display type used in the shields I bought. In both copies I have, and according to the website shop owner, this is the case in his whole entire party, the used type number HS420361K-A32, a 4 digit 7 segment display and this is a Common Cathode version.
    And I suspect that a Common Anode has been applied to the original shield.

    I have now use in my sketch a #define Common_Cathode command and I test this in the sketch of both arrays, with a #ifdef Common_Cathode if “True” than I use my customed Array’s and in the other case the original arrays. A simple test to make a conditional compilation.

    Is this kind of condition also possible to apply with a library from your sketch ? Then you don’t have to install and maintain two library versions when you have a shield with a Common_Anode or a Common_Cathode display build in the shield.

    I hope to hear from you soon.
    Kind regards Jan

  13. Ugurhan Cakir

    Subject: Arduino Multi Function shield
    Dear Jan,
    To use HS420361K-A32 display
    MultiFuncShield.cpp in file:
    the original two lines for Uno :
    bitWrite(PORTB, 0, !!(Value & (1 << (7 – i))));
    bitWrite(PORTB, 0, !!(SEGMENT_SELECT[Segment] & (1 << (7 – i))));

    change : bitWrite(PORTB, 0, !(Value & (1 << (7 – i))));
    bitWrite(PORTB, 0, !(SEGMENT_SELECT[Segment] & (1 << (7 – i))));

    Similarly,  You must do the same in the other 2 boards ( Leonardo, Mega 2560 )

  14. Jan van Heck

    Subject MultiFuncShield.cpp with Common Cathode 4 digit 7 segment display

    Hello Ugurhan
    YES it works too, but because I only own the Uno I have no possibilities for testing with the Leonardo or Mega 2560 hardware. But I trust that will work also. Thank you very much for your suggestions.

    // —————————————————————————————————-
    #if defined(__AVR_ATmega328P__) // Uno
    /* Write a value to one of the 4 digits of the display */
    void WriteValueToSegment(byte Segment, byte Value) {
    bitClear(PORTD, 4);

    #ifdef Common_Cathode // JJvH 4 Digit 7 Segment Display with Common Cathode display
    for (uint8_t i = 0; i < 8; i++) {
    bitWrite(PORTB, 0, !(Value & (1 << (7 – i)))); // Ugurhan Cakir
    bitSet(PORTD, 7);
    bitClear(PORTD, 7);
    for (uint8_t i = 0; i < 8; i++) {
    bitWrite(PORTB, 0, !(SEGMENT_SELECT[Segment] & (1 << (7 – i)))); // Ugurhan Cakir
    bitSet(PORTD, 7);
    bitClear(PORTD, 7);
    for (uint8_t i = 0; i < 8; i++) {
    bitWrite(PORTB, 0, !!(Value & (1 << (7 – i))));
    bitSet(PORTD, 7);
    bitClear(PORTD, 7);
    for (uint8_t i = 0; i < 8; i++) {
    bitWrite(PORTB, 0, !!(SEGMENT_SELECT[Segment] & (1 << (7 – i))));
    bitSet(PORTD, 7);
    bitClear(PORTD, 7);

    bitSet(PORTD, 4);
    // —————————————————————————————————-

    Add in MultiFuncShield.h
    #include "Arduino.h"
    #define ON 1
    #define OFF 0
    // comment if shield uses a 4 Digit 7 Segment Display with Common Anode display
    #define Common_Cathode // JJvH 4 Digit 7 Segment Display with Common Cathode display

  15. David Hughes

    Hi. Thanks for making the library available. I tried it an it all worked. I have a question re the library. Where or how can I get the library API/declarations. I am not looking for the source code, just the function names and their definitions. I have looked in the keywords txt file. It lists the keywords but where can you see the headers with the data type requirements.?

    I bought the board on AliExpress for AU$2.17 including delivery and half expected it to be a dud. To my surprise, it works perfectly. Did you designed it?


    1. Kashif Baig Post author

      Hi David, I’m glad you find the library useful. You’ll find the necessary declarations in the file MultiFuncShield.h of the library.

      Did I design the shield? No, I can’t take credit for that. I came across it a few years ago when trying to find learning resources for the Arduino. Seeing that there were very few coding examples for it, I decided to develop a library.

      Many thanks

      1. David Hughes

        Hi Kashif.
        Thanks for the quick reply, and a special thanks for writing the library. After I clicked send I figured out the definitions were in the .h files. The problem was that the Arduino development environment does not open .h files. I downloaded Notepad++ and found the declarations.
        I just started playing with Arduinos to teach my son a bit of computing and math. I have been in IT for decades but worked in a more formal environment where we had volumes written defining the interface to a library. I miss reading them but don’t miss writing them. I put together the sonar rangefinder and measured the ceiling height at 393cm and compared it with a Bosch laser device which said it was 3934mm . Not bad for a cheep Arduino. I am glad you didn’t design it because I bought mine on AliExpress for AU$2.17 including postage. How do they make them so cheep!! It would cost me more than that to post you a letter form Oz.

        Again. Thanks for the hard work and making it available.
        David in Adelaide

  16. Fred Page

    I have a multifunction shield from XINY. Using Arduino from Adafruit.
    MFS.initialize(&Timer1) in any code causes a constant buzz.
    Although the button shield and beeper shield do work with constant buzz.
    Any ideas?

    1. Kashif Baig Post author

      Hi Fred

      I haven’t experienced a buzzing beeper before. The beeper is usually connected to digital pin 3, which is also a PWM pin, so it is possible there is a PWM signal being emitted from the pin. Perhaps use analogWrite() with different values to see if the pitch of the buzz changes. If so, then use a value which silences the buzz. I hope that helps.


      1. Fred Page

        To silence my buzzer…. Your idea worked! I inserted “analogWrite(3,0)” after the MFS.initialize in your sample sketches. Buzzer is now silent.

  17. Fred Page

    OK, It kind of worked. If any subsequent “beep” command is used the buzzer stays on. I can silence it after an appropriate “delay” command and then another “analogWrite”. Would if be possible to put the analogWrite inside the initialize and beep commands?
    An FYI… I purchased a second shield from same supplier. Same issue.
    Any guidance would be most appreciated.

    1. Kashif Baig Post author

      Fred, have you tried using previous library versions? If not, download previous versions from here.

  18. Jan

    Hi Kashif Baig, tanks for the for great libary!
    I’ve found an bug in “MultiFuncShield.h” of version 1.2. The POT_IN ist defined as PIN 0
    #define POT_PIN 0

    correct definition
    #define POT_PIN A0


    1. Fred

      POT_PIN is used with analogRead() in the sketches. analogRead(0) is equal to analogRead(A0), so this is no bug.

  19. Seb


    great tool ! but…

    using the 7digit screen, except during initialization, I have all the first segment on on the 4 digits. any reason ? or idea ?

    1. Kashif Baig Post author

      Hi, it could be the underside of the led display is making contact with the USB connector.


Leave a Reply

Your email address will not be published. Required fields are marked *