測(cè)量車輛或電機(jī)的速度/轉(zhuǎn)速一直是一個(gè)值得嘗試的迷人項(xiàng)目。在這個(gè)項(xiàng)目中,我們將使用 Arduino 構(gòu)建一個(gè)模擬速度表。我們將使用紅外傳感器模塊來測(cè)量速度。還有其他方法/傳感器,例如霍爾傳感器來測(cè)量速度,但使用紅外傳感器很容易,因?yàn)榧t外傳感器模塊是非常常見的設(shè)備,我們可以輕松地從市場(chǎng)上獲得它,也可以用于任何類型的電機(jī)/車輛。
在這個(gè)項(xiàng)目中,我們將以模擬和數(shù)字形式展示速度。通過做這個(gè)項(xiàng)目,我們還將提高我們學(xué)習(xí)Arduino和步進(jìn)電機(jī)的技能,因?yàn)檫@個(gè)項(xiàng)目涉及使用中斷和定時(shí)器。在該項(xiàng)目結(jié)束時(shí),您將能夠計(jì)算任何旋轉(zhuǎn)物體所覆蓋的速度和距離,并將它們以數(shù)字格式顯示在 16x2 LCD 屏幕上以及模擬儀表上。因此,讓我們從帶有Arduino的速度表和里程表電路開始
所需材料
阿杜伊諾
雙極步進(jìn)電機(jī)(4線)
步進(jìn)電機(jī)驅(qū)動(dòng)器(L298n模塊)
紅外傳感器模塊
16*2液晶顯示屏
2.2k 電阻
連接線
面包板。
車速表圖片打印輸出
計(jì)算速度并將其顯示在模擬速度表上
紅外傳感器是一種可以檢測(cè)其前方物體存在的設(shè)備。我們使用了兩個(gè)葉片轉(zhuǎn)子(風(fēng)扇),并將紅外傳感器放置在其附近,以便每次葉片旋轉(zhuǎn)時(shí),紅外傳感器都會(huì)檢測(cè)到它。然后,我們使用Arduino中的計(jì)時(shí)器和中斷的幫助來計(jì)算電機(jī)完全旋轉(zhuǎn)所需的時(shí)間。
在這個(gè)項(xiàng)目中,我們使用最高優(yōu)先級(jí)的中斷來檢測(cè)rpm,并將其配置為上升模式。因此,每當(dāng)傳感器輸出從低到高時(shí),將執(zhí)行函數(shù) RPMCount()。由于我們使用了兩個(gè)葉片轉(zhuǎn)子,這意味著該函數(shù)將在一圈內(nèi)調(diào)用 4 次。
知道所花費(fèi)的時(shí)間后,我們可以使用以下公式計(jì)算 RPM,其中 1000/時(shí)間將給我們 RPS(每秒轉(zhuǎn)數(shù)),進(jìn)一步乘以 60 將得到 RPM(每分鐘轉(zhuǎn)數(shù))
rpm = (60/2)*(1000/(millis() - time))*REV/bladesInFan;
獲得 RPM 后,可以通過給定的公式計(jì)算速度:
Speed = rpm * (2 * Pi * radius) / 1000
我們知道Pi = 3.14,半徑為4.7英寸
但首先我們需要將半徑從英寸轉(zhuǎn)換為米:
radius = ((radius * 2.54)/100.0) meters
Speed= rpm * 60.0 * (2.0 * 3.14 * radius)/ 1000.0) in kilometers per hour
在這里,我們將 rpm 乘以 60 將 rpm 轉(zhuǎn)換為 rph(每小時(shí)轉(zhuǎn)數(shù)),除以 1000 將米/小時(shí)轉(zhuǎn)換為公里/小時(shí)。
在以kmh為單位的速度之后,我們可以以數(shù)字形式直接在LCD上顯示這些值,但是要以模擬形式顯示速度,我們需要再進(jìn)行一次計(jì)算才能找出否。步進(jìn)電機(jī)應(yīng)移動(dòng)以在模擬儀表上顯示速度。
在這里,我們使用了一個(gè)用于模擬儀表的 4 線雙極步進(jìn)電機(jī),它具有 1.8 度意味著每轉(zhuǎn) 200 步。
現(xiàn)在我們必須在車速表上顯示 280 公里/小時(shí)。所以要顯示280 Kmh步進(jìn)電機(jī)需要移動(dòng)280度
所以我們有 maxSpeed = 280
最大步數(shù)將是
maxSteps = 280/1.8 = 155 steps
現(xiàn)在我們?cè)?Arduino 代碼中有一個(gè)函數(shù),即map函數(shù),它在這里用于將速度映射到步驟中。
Steps = map(speed,0,maxSpeed,0,maxSteps);
所以現(xiàn)在我們有
steps=map(speed,0,280,0,155);
計(jì)算步長后,我們可以直接將這些步進(jìn)電機(jī)功能應(yīng)用于移動(dòng)步進(jìn)電機(jī)。我們還需要通過使用給定的計(jì)算來照顧步進(jìn)電機(jī)的當(dāng)前步長或角度
currSteps=Steps
steps= currSteps-preSteps
preSteps=currSteps?
這里的 currSteps 是來自上次計(jì)算的當(dāng)前步驟,preSteps 是上次執(zhí)行的步驟。
電路圖和連接
這個(gè)模擬車速表的電路圖很簡單,這里我們使用 16x2 LCD 以數(shù)字形式顯示速度,并使用步進(jìn)電機(jī)旋轉(zhuǎn)模擬車速表指針。
16x2 LCD連接在Arduino的以下模擬引腳上。
RS - A5 RW - GND
EN - A4 D4
- A3 D5
- A2 D6 - A1
D7 - A0
?
2.2k電阻用于設(shè)置LCD的亮度。紅外傳感器模塊,用于檢測(cè)風(fēng)扇的葉片以計(jì)算轉(zhuǎn)速,連接到中斷 0 表示 Arduino 的 D2 引腳。
這里我們使用了步進(jìn)電機(jī)驅(qū)動(dòng)器,即L293N模塊。步進(jìn)電機(jī)驅(qū)動(dòng)器的IN1、IN2、IN3和IN4引腳直接連接到Arduino的D8、D9、D10和D11。其余連接在電路圖中給出。
編程說明
Arduino Speedomete r的完整代碼在最后給出,在這里我們解釋了其中的一些重要部分。
在編程部分,我們包含了所有必需的庫,如步進(jìn)電機(jī)庫、液晶 LCD 庫和它們的聲明引腳。
#include
LiquidCrystal lcd(A5,A4,A3,A2,A1,A0);
#include
const int stepsPerRevolution = 200; ?// change this to fit the number of steps per revolution
Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
在此之后,我們采用一些變量和宏來執(zhí)行計(jì)算。上一節(jié)中已經(jīng)解釋了計(jì)算。
volatile byte REV;
unsigned long int rpm,RPM;
unsigned long st=0;
unsigned long time;
int ledPin = 13;?
int led = 0,RPMlen , prevRPM;
int flag = 0; ? ?
int flag1=1;
#define bladesInFan 2
float radius=4.7; ? // inch
int preSteps=0;
float stepAngle= 360.0/(float)stepsPerRevolution;
float minSpeed=0;
float maxSpeed=280.0;
float minSteps=0;
float maxSteps=maxSpeed/stepAngle;
之后,我們?cè)谠O(shè)置功能中初始化LCD,串行,中斷和步進(jìn)電機(jī)
void setup()
{
myStepper.setSpeed(60);
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
lcd.begin(16,2);
lcd.print("Speedometer");
delay(2000);
attachInterrupt(0, RPMCount, RISING);
}
在此之后,我們讀取循環(huán)函數(shù)中的rpm并執(zhí)行計(jì)算以獲得速度并將其轉(zhuǎn)換為運(yùn)行步進(jìn)電機(jī)的步驟,以模擬形式顯示速度。
void loop()
{
readRPM();
radius=((radius * 2.54)/100.0); ?// convering in meter
int Speed= ((float)RPM * 60.0 * (2.0 * 3.14 * radius)/1000.0);
// RPM in 60 minute, diameter of tyre (2pi r) r is radius, 1000 to convert in km
int Steps=map(Speed, minSpeed,maxSpeed,minSteps,maxSteps);
if(flag1)
{
Serial.print(Speed);
Serial.println("Kmh");
lcd.setCursor(0,0);
lcd.print("RPM: ");
lcd.print(RPM);
lcd.print(" ? ? ? ? ? ");
lcd.setCursor(0,1);
lcd.print("Speed: ");
lcd.print(Speed);
lcd.print(" Km/h ? ? ? ");
flag1=0;
}
int currSteps=Steps;
int steps= currSteps-preSteps;
preSteps=currSteps;
myStepper.step(steps);
}
這里我們有 reapRPM() 函數(shù)來計(jì)算 RPM。
int readRPM()
{
if(REV >= 10 or millis()>=st+1000) ? ? ? ? ? ? ? ? ?// ?IT WILL UPDATE AFETR EVERY 10 READINGS or 1 second in idle
{ ? ? ? ? ?
if(flag==0) ? ? ? ? ? ? ? ?
flag=1; ? ? ? ? ? ? ? ? ? ??
rpm = (60/2)*(1000/(millis() - time))*REV/bladesInFan;?
time = millis(); ? ? ? ? ? ? ? ? ? ? ? ? ??
REV = 0;
int x= rpm; ? ? ? ? ? ? ? ?
while(x!=0)
{
x = x/10;
RPMlen++;
} ? ? ?
Serial.println(rpm,DEC);
RPM=rpm;
delay(500);
st=millis();
flag1=1;
}
}
Finally, we have interrupt routine which is responsible to measure revolution of object
void RPMCount() ? ? ? ? ? ? ? ? ? ? ??
{
REV++; ? ? ? ? ? ? ? ? ? ? ? ? ? ??
if (led == LOW)
{
led = HIGH; ? ? ? ? ? ? ? ? ? ? ? ?
}
else
{
led = LOW;
}
digitalWrite(ledPin, led);
}
評(píng)論