Arduino GPS Speedometer With a Ks0108 - 128x64 GLCD (display)





Introduction: Arduino GPS Speedometer With a Ks0108 - 128x64 GLCD (display)

About: Passionate about computers and stuff :-)

I wanted to build a digital speedometer for my car. There was nothing wrong with the one already installed in my car, I just wanted to have a big LCD display that will be positioned in a more convenient position - right in front of me. And as I did not want to mess with my car's electronic parts in order to tap in and read the "speed" signal straight from the car's computer, I opted for the GPS version.

Components needed:

1. Arduino Uno (Nano or other Arduino boards might be fine as well)

2. GPS module, I got this one (if the link is not working when clicked, just copy and paste it into your browser's address bar)

3. Graphic LCD (

4. 10k trimpot for adjusting the contrast of the LCD

5. 4.7k potentiometer for adjusting the brightness of the LCD

6. 100 ohm resistor to limit the current for the LCD brightness

7. Wires, suction cup, self-adhesive velcro, kitchen aluminium foil (or similar), soldering iron, pliers, hot glue gun, etc.


8. USB cable for powering the Arduino board (and LCD) and separately the GPS module

9. 2 x USB (5V) car power adapters (at least 1A each)

10. Plastic enclosure (or you could build one)

11. and of course, a car with a battery to power the whole stuff

Step 1:


I would advise that you build a prototype version first, and only when tested and working start the actual building of the enclosure.

In order to be able to upload sketches to the Arduino board, the GPS module will have to be disconnected, as it uses the same RX and TX pins to communicate with the Arduino board as the Arduino IDE. While the GPS module was left connected, attempts to upload sketches failed in my case.

PS. As YukselV suggested, you could use SoftwareSerial instead of the "simple" Serial, in case you want to test other features which means uploading the sketch multiple times - you won't have to disconnect the GPS module in this case. Thanks YukselV! (

Similarly, the LCD power will have to be disconnected while uploading sketches to the Arduino board. This is due to the RESET pin being connected to the LCD, which interferes with the Arduino IDE. I read that one could simply connect the RESET pin of the LCD to +5V on the Arduino (permanently), or simply temporarily disconnect the RESET wire while uploading the sketch to the Arduino board. I simply disconnected the power supply when required.


First, because my LCD order would take a while to arrive, I started by testing the GPS module using a LED display.

*********** UPDATE 31.10.2016 ********************

I have attached the .INO sketch for using with a 4-Digit-7-Segment-LED-Display

*********** end of UPDATE 31.10.2016 ********************

When the LCD finally arrived, it took me a while finding out the correct wiring for the LCD. I found a tutorial in Italian ( that shows the wiring ( That however was not working properly for me, so I had to change some stuff around:

- I had to change some wiring around the 10k trimpot (controlling the LCD contrast)

- I added another 4.7k potentiometer in series with a 100 ohm resistor, that will allow me to control the LCD brightness as well.

EDIT: Thanks to ibenkos for pointing out that the +5v engine in my original wiring image was connected to ground rail on the breadboard. It should of course be connected to the positive rail - updated picture uploaded.

Then I wanted for the speed to be displayed instantly after starting my car engine and moving off. However I didn't want to leave the whole stuff powered up all the time and risk for the car battery to go dead. Therefore I would power the Arduino board and the LCD only when I start the engine, while the GPS module would be powered all the time, even when the engine is off (so that it won't take "I don't care how many seconds to lock onto the positioning satellites for required data to be sent to Arduino for processing").

It's up to you however to locate the appropriate points where to get power from the fuse board.

Using one USB car power adapter I would get continuous 5V to power the GPS module, while the second USB car power adapter would give me 5V to power the Arduino and the LCD only when I start the car engine.

One more thing to note: I used fused wires to connect to both car power adapters, so that they will blow in case of a short circuit, and not some other car electronics.

Step 2:

Here I was testing the LCD wiring - note the resistors I was using instead of the trimpot, which I did not have at the time.

Step 3:

I cut a whole in the plastic enclosure (that I bought from a local shop) that will allow the LCD display to fit in, and then I hot-glued the LCD in place. I've cut a piece of plastic sheet and placed it on the back of the LCD then I added some aluminium foil on top. I also added aluminium foil all around the plastic enclosure, including the back cover, and connected everything to ground. The idea is: try to enclose the Arduino board inside an improvised Faraday cage ( in order to prevent any interference from other electronic devices that could affect the functionality of the Arduino board. That's the idea, anyway :-) Is this really necessary? I don't know.

However, make sure that you are not shorting any contacts on either the LCD or Arduino.

Step 4:

Because I needed two different 5V power supplies (one for Arduino and LCD, the other for the GPS module), and another wire that will connect to the potentiometer controlling the LCD brightness - four wires in total, if we account for the ground as well - I decided that I will use an USB cable, which is conveniently screened.

I took the USB connector off the Arduino board (I didn't have another one at that time, and having uploaded and tested the whole thing before), I cut another hole in the plastic enclosure, and there I had my required power connection. You could use an additional USB connector, if you think you might need to upload updated sketches to the Arduino board.

Or of course, you could use another type of an electrical connector altogether if you wish. The idea is to get those four wires inside the box connected to the appropriate power source - continuous 5V, engine on 5V, LCD brightness signal coming from the potentiometer, and ground.

Step 5:

I happened to have a suction cup from an old sat nav, which I wasn't using anymore. This will hold the whole box onto the windscreen of the car. The GPS module is attached using some self-adhesive velcro, with a small hole allowing the four wires (5v, ground, TX, RX) to go and connect inside the box.

Step 6:

And there it is, the final product located onto the dashboard, connected by the USB cable to the power supply and the potentiometer conveniently located beside the steering wheel (please note, I have a left hand driving car, the steering wheel is located therefore on the right hand side of the car)

And you can watch it working here:

Sorry for the video going in and out of focus - I was using a compact camera, with no option for a fixed focus.

Step 7:

Now for the code...

First, you need to download two libraries (in case you don't have them already in your Arduino's library folder):

1. OpenGLCD -

(more information can be found here: and here

2. TinyGPS -

Unzip and copy them in your Arduino's library folder (normally C:\Program Files (x86)\Arduino\libraries\). If the Arduino IDE is open, you have to close and re-open it, to allow for the new libraries to be loaded.

Step 8:

Then I found it very awkward to generate new fonts (as high as the screen height) that will be displayed onto my LCD. Therefore what I did was to create bitmaps (numbers 0 to 9 plus a blank) that will be displayed on my LCD.

After "installing" the openGLCD library, look for the file name called "glcdMakeBitmap.pde", normally located here

C:\Program Files (x86)\Arduino\libraries\openGLCD\bitmaps\utils\glcdMakeBitmap\

EDIT - April 12th, 2016!!!!

Added OpenGLCD library, which already has the .h (header) files. You need to copy and unzip where your Arduino IDE is located - normally C:\Program Files (x86)\Arduino\libraries\

EDIT - April 12th, 2016!!!! [ends]

To run this file you will need to download and install an additional piece of free software, called Processing, which is very similar to Arduino IDE.

EDIT - March 14th, 2016!!!!

Thanks ab710 for pointing out that using some newer Processing versions will give an error while trying to run the code. Please use the link below to download Processing 2.2.1 which in my case allows for properly running of the code.


EDIT - March 14th, 2016!!!! [ends]

Open "glcdMakeBitmap.pde" in Processing and click Run, in the top-left corner.

The purpose of "glcdMakeBitmap.pde" application is to allow you to "feed" it with image files (gif, jpg, bmp, tga, png), and then some .h (header) files will automatically be created within the "bitmaps" folder of the openGLCD library. They will eventually be used to display your numbers (as images) onto the LCD.

I have attached an archive file named "" which you can download, unzip, and then drag each one of those .BMP files onto the running "glcdMakeBitmap.pde" in order to create the 11 header files (0 to 9, plus blank). But if you wish, you can design your own numbers, using different fonts, save them as BMP or other supported image file extension, and use them to create the header files which will be displayed onto the LCD.

PS. In case you're wondering why did I not upload the header (.h) files instead of the .BMP files, and save you the trouble of downloading and installing Processing, and running "glcdMakeBitmap.pde": It's not enough to simply copy the .h files into "bitmaps" folder, as the files named "allBitmaps.h" will be automatically updated as well (by the Processing application) to refer to the new files. Plus, in case you don't like my numbers, you now know how to create your own :-)

Step 9:

And finally the sketch, which is not very complicated, and should be self-explanatory.

I have also attached the .ino sketch for your convenience.


#include //math library to use for round function

#include "TinyGPS.h" //GPS module library

#include // LCD library

TinyGPS gps; //create a gps object

float fLat, fLong; //floats for longitude and latitude; will be used to determine whether the GPS data is up to date or not

unsigned long fix_age; // returns +- latitude/longitude in degrees

int digit1, digit2, digit3; //integers to hold the three digits making up the speed

int iSpeed; //integer to hold the speed value from the GPS module

void setup()


Serial.begin(9600); //start the serial communication

// initialise the library, non inverted writes pixels onto a clear screen



void loop()


while (Serial.available())


//incoming serial data from GPS

int c =;

if (gps.encode(c))


// process new gps info here, in case you want to display more details



gps.f_get_position(&fLat, &fLong, &fix_age); //get longitude and latitude, used to find if data is up to date

if (fix_age == TinyGPS::GPS_INVALID_AGE || fix_age > 2000)


//data was not updated for some time, assume that GPS connection is lost

iSpeed = 0;




//GPS connection is up to date, get the speed information, and round it to closest integer value

iSpeed = round(gps.f_speed_kmph()); // speed in km/h


//when not moving, the GPS module will still read some "speed" value, not necessarily zero

//in that case assume the car is not moving; only display values greater than 2

if (iSpeed == 1) iSpeed = 0;

displaySpeed(iSpeed); //call function to display the speed, digit by digit


void displaySpeed(int iSpeed)


//"simple" maths to extract each digit value

digit1 = iSpeed / 100;

iSpeed = iSpeed - (digit1 * 100);

digit2 = iSpeed / 10;

digit3 = iSpeed - (digit2 *10);

//display "blank" bitmap when necessary, instead of number zero

if (digit2 == 0 && digit1 == 0) digit2 = -1; //digit 2 is blank

if (digit1 == 0) digit1 = -1; //digit 1 is blank

//call function to display each digit, at their required position

drawDigit(digit1, 0);

drawDigit(digit2, 45);

drawDigit(digit3, 90);


void drawDigit(int digit, int pos)


switch (digit)


case 0:

GLCD.DrawBitmap(Number0, pos, 0);


case 1:

GLCD.DrawBitmap(Number1, pos, 0);


case 2:

GLCD.DrawBitmap(Number2, pos, 0);


case 3:

GLCD.DrawBitmap(Number3, pos, 0);


case 4:

GLCD.DrawBitmap(Number4, pos, 0);


case 5:

GLCD.DrawBitmap(Number5, pos, 0);


case 6:

GLCD.DrawBitmap(Number6, pos, 0);


case 7:

GLCD.DrawBitmap(Number7, pos, 0);


case 8:

GLCD.DrawBitmap(Number8, pos, 0);


case 9:

GLCD.DrawBitmap(Number9, pos, 0);



GLCD.DrawBitmap(NumberBlank, pos, 0);




Step 10:

If you have any comments, questions or ideas, please let me know. And I hope you'll enjoy (as much as I did) building your own Arduino based GPS speedometer.

3 People Made This Project!


  • Casting Contest

    Casting Contest
  • Planter Challenge

    Planter Challenge
  • Make it Move Contest

    Make it Move Contest

We have a be nice policy.
Please be positive and constructive.


1 Questions


Do you have circuit diagram for LED version please ?.




Hi, at the end of step 1, in the speedometerLEDdisplay.INO you can find instructions on how to connects the LED display to Arduino.


Well explained Studvio. This will surelyhelp me out in my current LED project.

Sir, I am new to arduino and I need to build a speedometer which can send the speed of the vehicle to a PC/mobile and also displayit on a LED screen on the vehicle. I don't know how to do that. Can you please help me?

1 reply

Hi, if you follow the tutorial above, you should be able to build the LCD version. For the laptop / mobile version you would need some communication shield (bluetooth, wifi, etc.) and an appropriate app to receive and process the information that is being received. I don't know what exactly you have in mind for this aspect, and as you say, you are new to Arduino, which means that it might take a while to build it yourself without extensive additional support. I'm not saying that it is not possible, and I don't want to discourage you from trying this project. However, unfortunately I am involved in some other projects and I won't be available to assist you with every step at this stage.

The following video is for a project I'm still working on, just to give you an idea about Arduino & mobile app communication via Bluetooth. I can gladly provide you with the source code for Ardiuno and the phone app, but again... I won't be able to provide further step-by-step support, and it is definitely not for beginners.

Hello, Good day. I badly need some help, hehe.

my goal is to warn the driver of a vehicle with a voice message when the speed reached 80 km/hr, and also sends information like latitude and longitude via text message to a mobile phone.

Initially, I did not put the voice alert function, just the text message function. There was no problem with the GPS module getting a fix information when it was connected to the Arduino UNO and GSM module, I did not use a library for the GSM module. It was working fine by then. The values from the GPS module are updated.

But when I wired the mp3 player module and included the DFPlayer_Mini_Mp3.h
library and its commands to my sketch, the voice alert was fine, the GSM
module sends a message to my phone, but values from the GPS module is not updated, just zero values. ex. LAT: 000000, LONG: 000000.

here is my sketch, i just badly need help right now, hehe:

#include <TinyGPS++.h>
#include <DFPlayer_Mini_Mp3.h>
#include <SoftwareSerial.h>

SoftwareSerial mySerialGPS(2, 3);
SoftwareSerial mySerialGSM(7, 8);
SoftwareSerial mySerial_mp3(10, 11); //Arduino pin 10 to DFPlayer TX,
//Arduino pin 11 to DFPlayer RX

TinyGPSPlus gps;

void setup()
mySerialGSM.begin(2400); // Setting the baud rate of GSM Module
mySerial_mp3.begin (9600);
mp3_set_serial (mySerial_mp3); //set softwareSerial for DFPlayer-mini mp3
mp3_set_volume (15);

void loop()

if (gps.speed.kmph() > 80)
//play file 0080.mp3

pinMode(13, OUTPUT);
digitalWrite(13, LOW);


void speed_alert_80()
mySerialGSM.println(“AT+CMGF=1″); //Sets the GSM Module in Text Mode
smartDelay(500); // Delay of 500 milli seconds or 1 second
mySerialGSM.println(“AT+CMGS=\”+63xxxxxxxxxx\”\r”); // Replace x with mobile
mySerialGSM.println(“Alert! there was a speed offender!”);// The SMS text you
//want to send
mySerialGSM.println(“The vehicle’s speed has reached 80 km/hr.”);
mySerialGSM.print(“SPEED(kmph): “);
mySerialGSM.print(“LAT: “);
mySerialGSM.print(“LONG: “);
mySerialGSM.println((char)26);// ASCII code of CTRL+Z

void SendMessage()
//play file 0101.mp3

mySerialGSM.println(“AT+CMGF=1″); //Sets the GSM Module in Text Mode
smartDelay(500); // Delay of 500 milli seconds or 1 second

mySerialGSM.println(“AT+CMGS=\”+639487567571\”\r”); // Replace x with mobile

mySerialGSM.println(“GPS module’s current state.\n”);// The SMS text you want
//to send

mySerialGSM.print(“LAT: “);

mySerialGSM.print(“LONG: “);

mySerialGSM.print(“DATE(ddmmyy): “);

mySerialGSM.print(“SPEED(kmph): “);

mySerialGSM.print(“# of Sat. in use: “);


mySerialGSM.println((char)26);// ASCII code of CTRL+Z

//play file 0102.mp3

static void smartDelay(unsigned long ms)
unsigned long start = millis();
while (mySerialGPS.available())
} while (millis() – start < ms);

4 replies

Hi, in your code you're only calling the function SendMessage() in the Setup, but not when a speed over 80 km/h was read. Try adding a call to SendMessage() within the body

if (gps.speed.kmph() > 80)




and see if that's working. I can't test it for real, for I don't have the necessary parts.

PS. why are you calling the function SendMessage() in the Setup?

Hello Studvio, thanks for the reply.

yes i did not call SendMessage() within the body, but I did call speed_alert_80() within the body

if (gps.speed.kmph() > 80)
//play file 0080.mp3

and for your question:

why are you calling the function SendMessage() in the Setup?

-- I just wanna check first at home if the system can get reliable values from the GPS module before testing it on the road.

-- Initially, without the mp3 player module and the DFPlayer_Mini_Mp3.h library, every time I reset the arduino UNO, I receive a message like this:

GPS module’s current state.

LAT: 8.241666

LONG: 126.025932

DATE(ddmmyy): 151116

SPEED(kmph): 0.00

# of Sat. in use: 11

--but when I added the mp3 player module and its libary, its like this:

LAT: 0.000000

LONG: 0.000000

DATE(ddmmyy): 000000

SPEED(kmph): 0.00

# of Sat. in use: 0

-- what do you think was the culprit? bmb, thanks in advance.

Hi, yes, you are right about that call, I wasn't sure why you want to have the speed_alert_80() though.

I know that you can not transmit data over the Software Serial to more than one device at a time. I also notice that you have the 3 second delay between sending data to the mp3 player module and sending data to the GSM module. I reckon that this could be the problem, whereas for some reason the communication is messed up somehow. Again, I don't have the required parts and I can not test it myself, but what I would suggest you to try:

1. Under if (gps.speed.kmph() > 80), comment out the call to play the file, mp3_play(80). You already mentioned that without the MP3 module it works properly, but I'm note sure whether you removed the whole library altogether, or you simply didn't make the call. Does it work now? I mean, the SMS text has all the data you need?

2. If the above is working now, try swapping the calls around like this

if (gps.speed.kmph() > 80)




//play file 0080.mp3




so that you are sending the SMS first, and then play the MP3 file. (I see that you are doing that in this order in SendMessage(). Does the mp3 file plays the first time, when you reset the Arduino board?)

If step 1 doesn't work, try also commenting the line SoftwareSerial mySerial_mp3(10, 11); but allow for the mp3 library to be included. If still doesn't work, then it may be that the DFPlayer_Mini_Mp3.h library is creating the problems.

3. Try something like

if (mySerialGPS.available())




I hope any of this helps, but let me know in either case please.

Hello sir. I already got mine working just fine. hehe.

thank you so much for your ideas.

-- the culprit was this lines, particularly the order:


mySerial_mp3.begin (9600);

-- I changed it into this:


mySerial_mp3.begin (9600);

mySerialGPS.begin(9600); //the baud rate of the GPS module should

//be set last. I dont no why but at least it

//works for me. hehe

-- do you have any idea why it worked properly in that order of setting baud rates? bmb, tnx in advance ..

Hi! very nice project, but my LCD display is quite different from yours and does't work!! So.. it is possible having the project with the led display? I think is more easy and quite retro..

1 reply

Hi there, in step one I've added the required .INO sketch. I hope it will work for you.

Hi Studio, this is excellent. Thanks so much for sharing.

I've rigged it up as a prototype and I can see the GPS is powered and receiving data (green LED is flashing). My display however is showing zero all the time.

I've stripped the wiring out and redone it, but still the same result.

I must be missing something with the unit. From the GPS, I'm not connecting the EN (yellow) and PPS (white) wires. I do not see them connected on the wiring diagram.

Any ideas, friends?

4 replies

How are you? I am assuming that you are moving about with the prototype
powered on, so that your speed would be higher than 2km/h. Then if at
all possible, connect the stuff to a laptop / netbook, start the serial
monitor and watch for incoming values from the GPS unit (iSpeed). You
will need to add the necessary lines of code for that, of course, and
use the Softserial method.

Hi Studvio. It was a schoolboy error on my part: I hadn't stripped any extra insulation from the Rx and Tx on the GPS module. Once I did that, the data was passing into the Arduino. :o)

I'll post a picture when it's all up and running.

Take care :o)

Hi, glad to hear that you were able to fix it, and thanks for your appreciation.

Thanks, I'll give that a try :)

Thank you very much.. It helped me alot

Hello again! After a little break from working on this i have finally started again and i am having more issues with processing. When i try and put the bitmap images into the small window i get an error code which says "couldnt create a writer for C:\Program Files (x86)\Arduino\libraries\openGLCD\bitmaps\utils\glcdMakeBitmap\..\..\allBitmaps.h". Im assuming that this is the reason that none of the .h files are loading into my openGLCD\bitmaps folder. Im having the same "Number0 was not declared in this scope" error as MeghaA2 was but i believe that the error in processing is causing the .h files not to load which in turn causes arduino IDE to give me an error as well. Any help would be greatly appreciated. Thanks!

3 replies

Hi, just confirming that you're using Arduino IDE version 1.6.5, Processing 2.2.1, and the correct GLCD library... as I understand these could potentially generate troubles.
I have updated the tutorial and at step 8 I included the GLCD library I am using (again, an older version), which is working for me, and it already has the necessary header (.h) files. Please give it a try and let me know.

So i downloaded the new library and that fixed it and it all uploaded alright. now after i have everything wired up following the diagrams, the GLCD comes on and i can change brightness and contrast however none of the numbers are displaying. Im not sure what to do from here. Thanks for the help on the last one!

Hi, in this case I would reckon that some connections are loose. I had this exact problem myself, where I was able to adjust the contrast / brightness, but nothing was displayed. Are you using the correct values for the (trim) pots and the resistor? Also, make sure that your GLCD's pinout is the same as in my schematics, as there are different models that one can buy, and the pins' order might be slightly different. The GLCD library comes with a testing app that will display different info on the display. Try that as well, and see if the problem is in the GPS code or with the wiring.