今天,無(wú)論是電表還是出租車(chē)計(jì)費(fèi)表,數(shù)字儀表都在取代各個(gè)領(lǐng)域的模擬儀表。主要原因是模擬儀表的機(jī)械部件在長(zhǎng)時(shí)間使用時(shí)容易磨損,并且不如數(shù)字儀表準(zhǔn)確。
一個(gè)很好的例子是模擬車(chē)速表和里程表,用于舊摩托車(chē)測(cè)量速度和行駛距離。它們具有稱(chēng)為小齒輪和齒條裝置的特殊部件,其中當(dāng)車(chē)輪旋轉(zhuǎn)時(shí),電纜用于旋轉(zhuǎn)速度計(jì)的銷(xiāo)釘。長(zhǎng)時(shí)間使用會(huì)磨損,也需要更換和維護(hù)。
在數(shù)字儀表中,不是使用機(jī)械部件,而是使用一些傳感器,如光斷續(xù)器或霍爾傳感器來(lái)計(jì)算速度和距離。這比模擬儀表更準(zhǔn)確,并且不需要長(zhǎng)時(shí)間維護(hù)。
今天,在本教程中,我們將使用 Arduino 制作數(shù)字出租車(chē)計(jì)費(fèi)器的原型。該項(xiàng)目計(jì)算出租車(chē)車(chē)輪行駛的速度和距離,并在16x2 LCD 顯示屏上連續(xù)顯示。當(dāng)我們按下按鈕時(shí),它會(huì)根據(jù)行駛的距離生成票價(jià)金額。
下圖顯示了數(shù)字出租車(chē)計(jì)程表項(xiàng)目的完整設(shè)置
這個(gè)原型有一個(gè) RC 汽車(chē)底盤(pán),帶有一個(gè)速度傳感器模塊和一個(gè)連接到電機(jī)的編碼器輪。一旦測(cè)量了速度,我們可以通過(guò)按下按鈕測(cè)量行駛的距離并找到票價(jià)金額。我們可以使用電位器設(shè)置車(chē)輪的速度。要了解有關(guān)在 Arduino 中使用 LM-393 速度傳感器模塊的更多信息,請(qǐng)點(diǎn)擊鏈接。讓我們看一下速度傳感器模塊的簡(jiǎn)短介紹。
紅外開(kāi)槽光學(xué) LM-393 速度傳感器模塊
這是一種槽型模塊,可用于測(cè)量編碼器輪的旋轉(zhuǎn)速度。該速度傳感器模塊基于插槽式光斷續(xù)器工作,也稱(chēng)為光源傳感器。該模塊需要 3.3V 至 5V 的電壓并產(chǎn)生數(shù)字輸出。因此它可以與任何微控制器接口。
紅外光 傳感器 由光源(IR-LED)和光電晶體管傳感器組成。兩者之間都有一個(gè)小間隙。當(dāng)物體放置在 IR LED 和光電晶體管的間隙之間時(shí),它將中斷光束,導(dǎo)致光電晶體管停止通過(guò)電流。
因此,對(duì)于這個(gè)傳感器,使用可以連接到電機(jī)的開(kāi)槽盤(pán)(編碼器輪),當(dāng)輪隨電機(jī)旋轉(zhuǎn)時(shí),它會(huì)中斷 IR LED 和光電晶體管之間的光束,從而使輸出打開(kāi)和關(guān)閉(產(chǎn)生脈沖)。
因此,當(dāng)源和傳感器之間存在中斷時(shí)(當(dāng)任何物體放置在兩者之間時(shí))它會(huì)產(chǎn)生高電平輸出,而當(dāng)沒(méi)有放置物體時(shí)會(huì)產(chǎn)生低電平輸出。在模塊中,我們有一個(gè) LED 來(lái)指示引起的光中斷。
該模塊帶有LM393 比較器 IC,用于在輸出端產(chǎn)生準(zhǔn)確的 HIGH 和 LOW 信號(hào)。因此這個(gè)模塊有時(shí)被稱(chēng)為L(zhǎng)M393 速度傳感器。
測(cè)量行駛速度和距離以計(jì)算票價(jià)
要測(cè)量旋轉(zhuǎn)速度,我們需要知道編碼器輪中存在的槽數(shù)。我有一個(gè)編碼輪,里面有 20 個(gè)插槽。當(dāng)它們旋轉(zhuǎn)一整圈時(shí),我們?cè)谳敵龆擞?20 個(gè)脈沖。因此,要計(jì)算速度,我們需要每秒產(chǎn)生的脈沖數(shù)。
例如
如果一秒內(nèi)有 40 個(gè)脈沖,那么
速度 = Noo。脈沖數(shù)/槽數(shù) = 40/20 = 2RPS(每秒轉(zhuǎn)數(shù))
為了以 RPM(每分鐘轉(zhuǎn)數(shù))計(jì)算速度,請(qǐng)乘以 60。
以 RPM 為單位的速度 = 2 X 60 = 120 RPM(每分鐘轉(zhuǎn)數(shù))
測(cè)量距離
測(cè)量車(chē)輪行駛的距離非常簡(jiǎn)單。在計(jì)算距離之前,應(yīng)該知道車(chē)輪的周長(zhǎng)。
車(chē)輪周長(zhǎng) = π* d
其中 d 是車(chē)輪的直徑。
π 的值為 3.14。
我有一個(gè)直徑為 6.60 厘米的輪子(RC 車(chē)輪),所以周長(zhǎng)是(20.7 厘米)。
因此,要計(jì)算行進(jìn)的距離,只需將檢測(cè)到的脈沖數(shù)乘以周長(zhǎng)即可。
行駛距離 = 車(chē)輪周長(zhǎng) x(脈沖數(shù) / 槽數(shù))
因此,當(dāng)一個(gè)周長(zhǎng)為 20.7 厘米的輪子需要 20 個(gè)脈沖,即編碼器輪轉(zhuǎn)一圈時(shí),輪子行進(jìn)的距離由下式計(jì)算
行駛距離 = 20.7 x (20/20) = 20.7cm
為了計(jì)算以米為單位的距離,將以厘米為單位的距離除以 100。
注意:這是一個(gè)小型 RC 汽車(chē)車(chē)輪,實(shí)時(shí)汽車(chē)的車(chē)輪比這個(gè)大。所以我假設(shè)本教程中車(chē)輪的周長(zhǎng)為 230 厘米。
根據(jù)行駛距離計(jì)算票價(jià)
要獲得總票價(jià)金額,請(qǐng)將行駛距離乘以票價(jià)(金額/米)。
注意:在本教程中,我假設(shè)每米收費(fèi) 5 盧比。
因此,如果車(chē)輪行駛 20m,則票價(jià)將為 20*5=100 盧比。
所以現(xiàn)在讓我們獲取組件并構(gòu)建電路。
所需組件
Arduino UNO
液晶顯示器 (16x2)
按鈕
電位器 -10k
ULN2003電機(jī)驅(qū)動(dòng)IC
LM393 速度傳感器模塊 (FC-03)
帶速度編碼器的 RC 智能汽車(chē)底盤(pán)
電池 9V
面包板
連接電線(xiàn)
電路原理圖
使用 Arduino 的數(shù)字出租車(chē)計(jì)費(fèi)器項(xiàng)目的電路圖 如下所示:
用遙控車(chē)底盤(pán)安裝速度傳感器
速度傳感器安裝在傳感器間隙之間的編碼器輪。在我的機(jī)箱中,我有一個(gè)用于放置傳感器的特殊孔。見(jiàn)下圖
速度傳感器模塊和 Arduino 之間的連接
Arduino 和 16x2 LCD 之間的連接
Arduino 與 ULN2003 之間的連接
ULN2003、直流電機(jī)和9v電池之間的連接
我使用了 9V 電池和 ULN2003 IC 為電機(jī)外部供電。
按鈕和電位器連接
帶有下拉電阻的按鈕連接到 Arduino 的引腳 3,用于在按下時(shí)生成票價(jià)金額。
電位器用于向 Arduino 的引腳 A0 提供模擬輸入電壓,以改變電機(jī)輪的速度。
為數(shù)字出租車(chē)計(jì)價(jià)器編程 Arduino
本教程末尾提供了帶有演示視頻的完整代碼。在這里,我們了解了代碼的幾個(gè)重要部分。
在進(jìn)入代碼之前,我們需要了解代碼中使用的中斷和定時(shí)器 One 庫(kù)。
此處使用中斷是因?yàn)槲覀冃枰粩鄼z查在速度傳感器模塊處檢測(cè)到的輸出作為高優(yōu)先級(jí)。所以代碼中使用了ISR。ISR 是中斷服務(wù)程序,當(dāng)中斷引腳 2 和 3 發(fā)生中斷時(shí)調(diào)用。
Arduino UNO 有兩個(gè)中斷引腳 2 和 3。
在引腳 2 處,連接速度傳感器 D0 的輸出。
在引腳 3 處,連接了一個(gè)帶有下拉電阻的按鈕。
此代碼中使用TimerOne 庫(kù)來(lái)檢查一秒鐘內(nèi)檢測(cè)到多少次旋轉(zhuǎn)(多少個(gè)脈沖),據(jù)此我們可以計(jì)算每秒的速度并將其顯示在輸出中。此 ISR 函數(shù)每秒執(zhí)行一次
那么讓我們?cè)敿?xì)看看我們的代碼:
1. 首先,包含程序中要使用的函數(shù)的庫(kù)。
#include "TimerOne.h" #include
2. 接下來(lái)聲明全局變量,因?yàn)樗鼈儗⒃谡麄€(gè)程序中使用。
揮發(fā)性無(wú)符號(hào)整數(shù)計(jì)數(shù)器=0; 揮發(fā)性無(wú)符號(hào)整數(shù)旋轉(zhuǎn)=0; 浮動(dòng)旋轉(zhuǎn)inm = 0; 無(wú)符號(hào)整數(shù)速度=0;
3. 接下來(lái)定義并初始化連接到 Arduino 的 LCD 引腳。
const int rs = 12, en = 13, d4 = 8, d5 = 9, d6 = 10, d7 = 11; LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
4. 接下來(lái)在void setup()
定義引腳模式,此處引腳 A0 用于從電位器獲取模擬輸入,引腳 5 用于寫(xiě)入連接到 ULN2003 IC 的 IN1 引腳的模擬輸出。
pinMode(A0,輸入); pinMode(5,輸出);
接下來(lái)顯示一些歡迎信息并清除它們。
lcd.開(kāi)始(16,2);//設(shè)置 LCD 為 16x2 類(lèi)型 lcd.setCursor(0,0); lcd.print("電路文摘"); lcd.setCursor(0,1); lcd.print("歡迎來(lái)到出租車(chē)"); 延遲(3000); lcd.clear(); lcd.print("開(kāi)始吧:)"); 延遲(1000); lcd.clear();
下一個(gè)重要部分是設(shè)置中斷引腳和中斷發(fā)生時(shí)要調(diào)用的 ISR
首先,我們需要將 timer1 設(shè)置為 1 秒,然后為 timer1 附加一個(gè) ISR,以便每秒調(diào)用一次此 ISR。ISR 名稱(chēng)是timerIsr
Timer1.initialize(1000000); Timer1.attachInterrupt(timerIsr);
接下來(lái)附加兩個(gè)外部中斷。第一個(gè)中斷使 Arduino 引腳 2 作為中斷引腳,并在引腳 2 檢測(cè)到 RISING(LOW TO HIGH)時(shí)調(diào)用 ISR(計(jì)數(shù))。此引腳 2 連接到速度傳感器模塊的 D0 輸出。
第二個(gè)使 Arduino 引腳 3 作為中斷引腳,并在引腳 3 檢測(cè)到高電平時(shí)調(diào)用 ISR(generatefare)。該引腳通過(guò)下拉電阻連接到按鈕。
attachInterrupt(digitalPinToInterrupt(2),計(jì)數(shù),上升); attachInterrupt(digitalPinToInterrupt(3), generatefare , HIGH);
5.接下來(lái)看看我們這里使用的ISR:
ISR1-count()當(dāng)引腳 2(連接到速度傳感器)發(fā)生上升(從低到高)時(shí)調(diào)用 ISR。
void count() // 速度傳感器計(jì)數(shù)的 ISR { counter++; // 將計(jì)數(shù)器值增加 一圈++;//將旋轉(zhuǎn)值增加一個(gè) delay(10); }
ISR2- timerIsr()每隔一秒調(diào)用一次 ISR 并執(zhí)行 ISR 中存在的那些行。
無(wú)效 timerIsr() { detachInterrupt(digitalPinToInterrupt(2)); Timer1.detachInterrupt(); lcd.clear(); 浮動(dòng)速度=(計(jì)數(shù)器/20.0)* 60.0; 浮動(dòng)旋轉(zhuǎn)= 230 *(旋轉(zhuǎn)/ 20); rotationinm = 轉(zhuǎn)數(shù)/100; lcd.setCursor(0,0); lcd.print("距離(m):"); lcd.print(旋轉(zhuǎn)); lcd.setCursor(0,1); lcd.print("速度(RPM):"); lcd.print(速度); 計(jì)數(shù)器=0; int 類(lèi)比 = 類(lèi)比讀?。ˋ0); int motorspeed = map(analogip,0,1023,0,255); 模擬寫(xiě)入(5,電機(jī)速度); Timer1.attachInterrupt(timerIsr); attachInterrupt(digitalPinToInterrupt(2),計(jì)數(shù),上升); }
這個(gè)函數(shù)包含實(shí)際上首先分離 Timer1 和 Interrupt pin2 的行,因?yàn)槲覀冊(cè)?ISR 中有 LCD 打印語(yǔ)句。
為了以 RPM 計(jì)算SPEED,我們使用以下代碼,其中 20.0 是編碼器輪中預(yù)設(shè)的插槽數(shù)。
浮動(dòng)速度=(計(jì)數(shù)器/20.0)* 60.0;
并使用以下代碼計(jì)算距離:
浮動(dòng)旋轉(zhuǎn)= 230 *(旋轉(zhuǎn)/ 20);
這里假設(shè)車(chē)輪周長(zhǎng)為 230 厘米(因?yàn)檫@對(duì)于實(shí)時(shí)汽車(chē)來(lái)說(shuō)是正常的)
接下來(lái)通過(guò)將距離除以 100 來(lái)轉(zhuǎn)換以 m 為單位的距離
rotationinm = 轉(zhuǎn)數(shù)/100;
之后我們?cè)谝壕э@示屏上顯示速度和距離
lcd.setCursor(0,0); lcd.print("距離(m):"); lcd.print(旋轉(zhuǎn)); lcd.setCursor(0,1); lcd.print("速度(RPM):"); lcd.print(速度);
重要提示:我們必須將計(jì)數(shù)器重置為 0,因?yàn)槲覀冃枰@取每秒檢測(cè)到的加號(hào)數(shù),因此我們使用此行
計(jì)數(shù)器=0;
接下來(lái)讀取模擬引腳 A0 并將其轉(zhuǎn)換為數(shù)字值(0 到 1023)并進(jìn)一步將這些值映射到 0-255 用于 PWM 輸出(電機(jī)的設(shè)置速度),最后使用連接到 ULN2003 的模擬寫(xiě)入函數(shù)寫(xiě)入這些 PWM 值電機(jī)集成電路。
int 類(lèi)比 = 類(lèi)比讀取(A0); int motorspeed = map(analogip,0,1023,0,255); 模擬寫(xiě)入(5,電機(jī)速度);
ISR3:generatefare()ISR 用于根據(jù)行駛距離生成票價(jià)金額。當(dāng)檢測(cè)到中斷引腳 3 為高電平(按下按鈕時(shí))時(shí)調(diào)用此 ISR。該函數(shù)分離引腳 2 的中斷和定時(shí)器中斷,然后清除 LCD。
無(wú)效generatefare () { detachInterrupt(digitalPinToInterrupt(2)); 引腳 2 Timer1.detachInterrupt(); lcd.clear(); lcd.setCursor(0,0); lcd.print("票價(jià)盧比:"); 浮動(dòng)盧比=rotationinm * 5; lcd.print(盧比); lcd.setCursor(0,1); lcd.print("每米 5 盧比"); }
之后,行駛距離乘以 5(我使用 5 表示 5 盧比/米的費(fèi)率)。您可以根據(jù)自己的意愿進(jìn)行更改。
浮動(dòng)盧比=rotationinm * 5;
計(jì)算金額值后,將其顯示在連接到 Arduino 的 LCD 顯示器上。
lcd.setCursor(0,0); lcd.print("票價(jià)盧比:"); lcd.print(盧比); lcd.setCursor(0,1); lcd.print("每米 5 盧比");
完整代碼
#include "TimerOne.h" //包含使用Timer1函數(shù)的Timer1庫(kù)
#include
const int rs = 12, en = 13, d4 = 8, d5 = 9, d6 = 10, d7 = 11; //定義 LCD 引腳
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
揮發(fā)性無(wú)符號(hào)整數(shù)計(jì)數(shù)器=0;
揮發(fā)性無(wú)符號(hào)整數(shù)旋轉(zhuǎn)=0;
浮動(dòng)旋轉(zhuǎn)inm = 0;
無(wú)符號(hào)整數(shù)速度=0;
void count() // 速度傳感器計(jì)數(shù)的 ISR
{
counter++; //將計(jì)數(shù)器值增加
一圈++;//將旋轉(zhuǎn)值增加一個(gè)
delay(10);
}
無(wú)效 timerIsr()
{
detachInterrupt(digitalPinToInterrupt(2)); //停止中斷引腳2
Timer1.detachInterrupt(); //停止timer1中斷
lcd.clear();
浮動(dòng)速度=(計(jì)數(shù)器/20.0)* 60.0;//以分鐘為單位計(jì)算速度(20-編碼器輪中的槽數(shù))
浮點(diǎn)旋轉(zhuǎn) = 230*(旋轉(zhuǎn) / 20);//以厘米為單位計(jì)算距離(230-車(chē)輪周長(zhǎng)假設(shè)為 20-槽數(shù))
rotationinm = rotations/100;
lcd.setCursor(0,0);
lcd.print("距離(m):");
lcd.print(旋轉(zhuǎn));//在LCD顯示rotationinm
lcd.setCursor(0,1);
lcd.print("速度(RPM):");
lcd.print(速度);//在 RPM
計(jì)數(shù)器中顯示速度=0;//重置計(jì)數(shù)器為0
int 類(lèi)比 = 類(lèi)比讀?。ˋ0);// 從引腳 A0 讀取模擬
量 int motorspeed = map(analogip,0,1023,0,255); //將數(shù)字值 0-1023 轉(zhuǎn)換為 0-255 模擬寫(xiě)入
(5,電機(jī)速度);//設(shè)置引腳 5 的 PWM 值
Timer1.attachInterrupt( timerIsr ); //再次啟動(dòng)timer1
attachInterrupt(digitalPinToInterrupt(2), count, RISING); //再次在pin2處附加中斷
}
void generatefare() //ISR 生成票價(jià)
{
detachInterrupt(digitalPinToInterrupt(2)); //在 2 處禁用中斷引腳
Timer1.detachInterrupt(); //禁用Timer1中斷
float rupees = rotationinm*5; //行駛距離乘以 5(每米 5 盧比)
lcd.clear(); //清除 LCD
lcd.setCursor(0,0);
lcd.print("票價(jià)盧比:");
lcd.print(盧比);//顯示票價(jià)金額
lcd.setCursor(0,1);
lcd.print("每米 5 盧比");
}
無(wú)效設(shè)置()
{
pinMode(A0,INPUT);//將引腳A0設(shè)置為INPUT
pinMode(5,OUTPUT); //將引腳 5 設(shè)置為 OUTPUT
lcd.begin(16,2); //設(shè)置 LCD 為 16x2 類(lèi)型
lcd.setCursor(0,0); //以下代碼顯示歡迎信息
lcd.print("CIRCUIT DIGEST");
lcd.setCursor(0,1);
lcd.print("歡迎來(lái)到出租車(chē)");
延遲(3000);
lcd.clear();
lcd.print("開(kāi)始吧:)");
延遲(1000);
lcd.clear();
Timer1.initialize(1000000); //初始化 timer1 1 秒
Timer1.attachInterrupt( timerIsr ); //每隔一秒調(diào)用一次 ISR 例程
attachInterrupt(digitalPinToInterrupt(2), count, RISING); // 引腳 2 作為中斷引腳,計(jì)數(shù) ISR 在發(fā)生從低到右時(shí)被調(diào)用。
attachInterrupt(digitalPinToInterrupt(3), generatefare, HIGH); //當(dāng)檢測(cè)到高電平時(shí),引腳 3 作為帶有 generatefare ISR 的中斷引腳被調(diào)用。
}
無(wú)效循環(huán)()
{
}
-
顯示屏
+關(guān)注
關(guān)注
28文章
4436瀏覽量
74053 -
計(jì)費(fèi)器
+關(guān)注
關(guān)注
0文章
7瀏覽量
7319 -
Arduino
+關(guān)注
關(guān)注
187文章
6457瀏覽量
186502
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論