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