8
今天硬創(chuàng)邦給大家?guī)?lái)的產(chǎn)品是一款GPS速度計(jì),當(dāng)然,它可不是計(jì)算步行速度的,它可以用在車?yán)铩B牭竭@兒肯定許多人會(huì)感到奇怪,車?yán)锊皇怯袃x表盤嗎?難道你開的是自行車???是啊,但很多人的單任務(wù)運(yùn)行的大腦總覺得簡(jiǎn)單易懂的數(shù)字速度計(jì)更符合我的要求,而且可以直接把它固定在面前。
此外,本次教程的作者做的GPS版本并不會(huì)像其他人改裝車一樣,把車?yán)锱膩y七八糟的。接下來(lái)我們就看一下教程吧。
1. Arduino Uno開發(fā)板(其他版本的Arduino開發(fā)板也可以使用)。
2.GPS模塊,購(gòu)買地址:https://www.dfrobot.com/wiki/index.php?title=GPS_M...
3.液晶顯示屏,購(gòu)買地址:http://www.aliexpress.com/item/20PIN-LCD12864-Graphic-LCD-Module-KS0107-KS0108-Drive-IC-5V-Yellow-Backlight/2037961119.html?spm=2114.01020208.3.40.olQVGl&ws_ab_test=searchweb201556_7_79_78_77_80,searchweb201644_5,searchweb201560_9
4.一個(gè)10K的微調(diào)電位,用來(lái)調(diào)整LCD的對(duì)比度。
5.4.7k的電位計(jì),用來(lái)調(diào)整LCD的亮度。
6.100歐姆的電阻器,用來(lái)限制通過(guò)LCD的電流。
7.線材,吸盤,自粘魔術(shù)貼,廚房鋁箔或類似的東西,烙鐵,鉗子和熱熔膠槍等等。
可選配件:
8.可為Arduino開發(fā)板和LCD等設(shè)備供電的USB線。
9.兩個(gè)5V的USB車載電源適配器,電流輸出至少要達(dá)到1A。
10.塑料外殼(你也可以自己做一個(gè))。
11.當(dāng)然,首先你得有輛車。
請(qǐng)各位注意:
我建議你在正式制作前先試做一個(gè),在完成測(cè)試工作后再正式開始制作。
想要順利將sketch上傳至Arduino開發(fā)板,你需要先斷開GPS模塊的連接,因?yàn)樗虯rduino IDE用的是相同的RX和TX接口。我試過(guò)不斷開就上傳,但一直都沒能成功。
此外,上傳過(guò)程中還要斷開LCD的電源連接,因?yàn)橹刂媒涌跁?huì)對(duì)Arduino IDE造成干擾。有人說(shuō),連接Arduino上的+5V電源也能完成上傳,不過(guò)我覺得上傳時(shí)拔掉線纜貌似更簡(jiǎn)單。
首先,之前因?yàn)榭爝f不給力,我的LCD還沒到,所以我只能用LED顯示屏先測(cè)試GPS模塊了。
好不容易盼來(lái)了LCD,我又發(fā)現(xiàn)了個(gè)蛋疼的問(wèn)題,這線也太難接了。好嘛,我只好去翻了那本意大利語(yǔ)的教程(鏈接:http://www.mauroalfieri.it/elettronica/lcd-grafico-128x64-arduino.html)。不過(guò)最終我也沒能找到正確的方法,所以我只好做了些許變通:
-在10k微調(diào)電位的布線上,我做了一些調(diào)整。
-我將另一個(gè)4.7k的電位計(jì)和100歐姆的電阻器串聯(lián)了起來(lái),這樣就可以控制LCD的亮度了。
另外,為了使用方便,我希望引擎啟動(dòng)時(shí)速度計(jì)就會(huì)開始顯示,不過(guò)這樣做耗電量可能會(huì)有些大。所以只有引擎啟動(dòng)時(shí)Arduino開發(fā)板和LCD才會(huì)開始工作,不過(guò)GPS模塊會(huì)一直處于開機(jī)狀態(tài)(這樣就不用每次啟動(dòng)都要等著GPS去搜星了)。
不過(guò),你也可以根據(jù)需要自行決定供電方式。
只需一個(gè)車載電源適配器就能穩(wěn)定的給GPS模塊供電,另一個(gè)電源適配器則可在車輛啟動(dòng)后為Arduino開發(fā)板和LCD供電。
還有一個(gè)點(diǎn)需要注意:連接電源適配器時(shí)我用了保險(xiǎn)絲,所以如果發(fā)生短路它們會(huì)即使熔斷,以防損壞其他車載電子元件。
這一步我測(cè)試了LCD的線路。不過(guò)當(dāng)時(shí)我還沒用電阻器替代微調(diào)電位。
如圖所示,我在備好的塑料外殼上打了個(gè)洞,這樣就能把LCD裝進(jìn)去了,下一步點(diǎn)上熱熔膠固定好LCD,接著在上面鋪一層鋁箔,對(duì)了,記得在塑料殼周圍也加一層鋁箔。此外,你要將Arduino開發(fā)板封在一個(gè)簡(jiǎn)易的法拉第籠中,這樣就能避免來(lái)自其他設(shè)備的干擾。這玩意真的這么有用嗎?實(shí)話說(shuō),我也不知道,不過(guò)照做就是了。
但可要記得理好線路,省的引起LCD或者Arduino開發(fā)板短路。
這個(gè)項(xiàng)目里的線是真不少,除了兩個(gè)電源適配器需要連接,我們還需要通過(guò)電位計(jì)來(lái)調(diào)整屏幕亮度,這下一共就有4根線了,所以我決定將這些線換成USB線,以便后期檢查。
我將Arduino開發(fā)板里的USB接口拔了下來(lái)(當(dāng)時(shí)我只有這一個(gè)接口,不過(guò)在那之前我已經(jīng)上傳了sketch而且對(duì)速度計(jì)進(jìn)行了初步的測(cè)試),而且在塑料盒上又開了個(gè)口,留給所需的電源連接。如果你想后期給開發(fā)板升級(jí)sketch,一定要再去買個(gè)USB接口。
當(dāng)然,你還可以選擇其他類型的接口。我這樣處理是為了將這四根線都放進(jìn)盒子里收納整齊,這樣會(huì)比較美觀。
正好我手邊有個(gè)閑置的導(dǎo)航,它上面有個(gè)吸盤,所以我就直接用它將速度計(jì)吸在了前擋風(fēng)玻璃上。此外,我用魔術(shù)貼將GPS模塊綁在速度計(jì)的塑料外殼上。不過(guò)可要記得在外殼上給四條線纜留口哦。
此時(shí),速度計(jì)的硬件就組裝完成了,現(xiàn)在我們需要用USB線將它連接到電源適配器上。而電位計(jì)則安裝在方向盤旁邊(請(qǐng)各位注意,我開的是右舵車,如果你的車是左舵車,請(qǐng)對(duì)電位計(jì)的位置作相應(yīng)調(diào)整)。
好啦,該搞定代碼的問(wèn)題了。
首先,你得先去下載兩個(gè)庫(kù)(確認(rèn)你的Arduino開發(fā)板里沒有這兩個(gè)庫(kù))。
OpenGLCD,下載鏈接:https://code.google.com/p/glcd-arduino/downloads/list
更多詳細(xì)信息請(qǐng)參閱:http://playground.arduino.cc/Code/GLCDks0108和https://bitbucket.org/bperrybap/openglcd/wiki/Home。
TinyGPS,下載地址:http://arduiniana.org/libraries/tinygps/
解壓下載好的文件并將它們放入你的Arduino庫(kù)文件夾中(一般為C:\Program Files (x86)\Arduino\libraries\)。如果Arduino IDE處于開機(jī)狀態(tài),請(qǐng)關(guān)掉并重啟,這樣才能加載出新的庫(kù)。
剛剛解決了庫(kù)的問(wèn)題后,我又發(fā)現(xiàn)了新問(wèn)題,那就是生成的新字體看起來(lái)很違和。于是我創(chuàng)建了一個(gè)新的位圖,它會(huì)直接顯示在LCD上。
安裝了OpenGLCD庫(kù)之后,請(qǐng)找到那個(gè)名為"glcdMakeBitmap.pde"的文件,一般情況下它都保存在:
C:\Program Files (x86)\Arduino\libraries\openGLCD\bitmaps\utils\glcdMakeBitmap\
想要運(yùn)行這個(gè)文件,你需要下載并安裝另一款名叫Processing的免費(fèi)軟件,它和Arduino IDE非常相似。下面附上下載地址:https://processing.org/download/
在軟件中打開"glcdMakeBitmap.pde"并點(diǎn)擊左上角的運(yùn)行按鍵。
"glcdMakeBitmap.pde"可以讓你不斷喂給OpenGLCD庫(kù)新的圖片文檔,隨后一些.h文檔就會(huì)自動(dòng)在新的位圖文件夾中生成,最終它們將成為L(zhǎng)CD上不斷跳動(dòng)的數(shù)字。
在第八步的最下方我還貼了一個(gè)名為"numbers.zip"的文件,你可以下載后解壓,隨后將其中的.BMP文件拖到運(yùn)行中的"glcdMakeBitmap.pde"中去,這樣就可以創(chuàng)建11個(gè)頭文件(0到9,還有空格)。不過(guò)如果你是這方面的大神,你還可以設(shè)計(jì)自己的字體并保存為BMP或其他文檔,隨后再創(chuàng)建出獨(dú)一無(wú)二的頭文件,這樣你的速度計(jì)就會(huì)變得狂拽酷炫叼炸天了。
備注:你們可能會(huì)覺得很奇怪,為什么我不直接用.h文檔來(lái)替代.BMP文檔,留給你們一個(gè)爛攤子(下載安裝Processing并運(yùn)行"glcdMakeBitmap.pde")來(lái)收拾呢?因?yàn)橹皇呛?jiǎn)單的將.h文檔復(fù)制粘貼到位圖文件夾中的話,一個(gè)名為"allBitmaps.h" 的文件就會(huì)自動(dòng)更新。此外,這樣你們也能學(xué)會(huì)怎么設(shè)計(jì)字體,創(chuàng)造自己的個(gè)性速度計(jì)了。
最后我們要搞定sketch,這一步不是很復(fù)雜,我就不詳細(xì)來(lái)講了。
下面我會(huì)附上.ino sketch供大家參考。
#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
GLCD.Init(NON_INVERTED);
}
void loop()
{
while (Serial.available())
{
//incoming serial data from GPS
int c = Serial.read();
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;
}
else
{
//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);
break;
case 1:
GLCD.DrawBitmap(Number1, pos, 0);
break;
case 2:
GLCD.DrawBitmap(Number2, pos, 0);
break;
case 3:
GLCD.DrawBitmap(Number3, pos, 0);
break;
case 4:
GLCD.DrawBitmap(Number4, pos, 0);
break;
case 5:
GLCD.DrawBitmap(Number5, pos, 0);
break;
case 6:
GLCD.DrawBitmap(Number6, pos, 0);
break;
case 7:
GLCD.DrawBitmap(Number7, pos, 0);
break;
case 8:
GLCD.DrawBitmap(Number8, pos, 0);
break;
case 9:
GLCD.DrawBitmap(Number9, pos, 0);
break;
default:
GLCD.DrawBitmap(NumberBlank, pos, 0);
break;
}
}
2015-2016賽季全球創(chuàng)客馬拉松深圳大學(xué)站已經(jīng)開始接受報(bào)名啦!關(guān)注“硬創(chuàng)邦”(微信號(hào):leiphone_bang),回復(fù)“深大”即可參與報(bào)名!此外還可加入全球創(chuàng)客馬拉松主群(群號(hào):259592983),參與我們的互動(dòng)討論~
雷峰網(wǎng)原創(chuàng)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。