公司資訊
熱銷(xiāo)產(chǎn)品
最新發(fā)布
更多內(nèi)容

用接近開(kāi)關(guān)測(cè)算電機(jī)速度,輕松實(shí)現(xiàn)精確控制

  • 時(shí)間:2024-06-27 12:30:56
  • 點(diǎn)擊:0

在工業(yè)生產(chǎn)和自動(dòng)化控制系統(tǒng)中,電機(jī)速度的精確測(cè)量和控制對(duì)于提高生產(chǎn)效率和保證產(chǎn)品質(zhì)量至關(guān)重要。本文將介紹如何利用接近開(kāi)關(guān)這一簡(jiǎn)單而有效的傳感器來(lái)實(shí)現(xiàn)電機(jī)速度的精確測(cè)量和控制。

一、什么是接近開(kāi)關(guān)?

接近開(kāi)關(guān)是一種具有高靈敏度、非接觸式檢測(cè)功能的傳感器,當(dāng)目標(biāo)物體靠近或離開(kāi)傳感器時(shí),能夠產(chǎn)生電信號(hào)輸出。在電機(jī)速度測(cè)量中,接近開(kāi)關(guān)可以安裝在電機(jī)的旋轉(zhuǎn)軸上,實(shí)時(shí)監(jiān)測(cè)電機(jī)轉(zhuǎn)速,從而實(shí)現(xiàn)對(duì)電機(jī)速度的精確控制。

二、如何用接近開(kāi)關(guān)測(cè)算電機(jī)速度?

1. 準(zhǔn)備工具和材料

為了使用接近開(kāi)關(guān)測(cè)量電機(jī)速度,我們需要準(zhǔn)備以下工具和材料:

- 一臺(tái)帶有編碼器的電機(jī)

- 一個(gè)接近開(kāi)關(guān)傳感器

- 一塊微控制器(如Arduino)

- 一根杜邦線

- 一個(gè)電源適配器

- 一些基本的電子元件(如電阻和電容)

2. 連接電路

將接近開(kāi)關(guān)傳感器的信號(hào)線、電源線和地線分別連接到微控制器的相應(yīng)引腳上。具體連接方式如下:

- 將接近開(kāi)關(guān)的VCC接到微控制器的5V引腳

- 將接近開(kāi)關(guān)的GND接到微控制器的GND引腳

- 將接近開(kāi)關(guān)的OUT接到微控制器的一個(gè)數(shù)字輸入引腳(如D2)

- 為電機(jī)供電,并將電機(jī)的另一端接到微控制器的另一個(gè)數(shù)字輸入引腳(如D3)

- 在需要測(cè)量電機(jī)速度的地方添加一個(gè)霍爾效應(yīng)轉(zhuǎn)速傳感器或者直流電壓計(jì),將其信號(hào)線接到微控制器的一個(gè)模擬輸入引腳(如A0)。

3. 編寫(xiě)程序

我們需要為微控制器編寫(xiě)一個(gè)簡(jiǎn)單的程序,用于讀取接近開(kāi)關(guān)和霍爾效應(yīng)轉(zhuǎn)速傳感器的數(shù)據(jù),并計(jì)算出電機(jī)的實(shí)際速度。以下是一個(gè)簡(jiǎn)單的示例代碼:

```c

#include

const int nearSwitchPin = 2; // 接近開(kāi)關(guān)引腳連接到D2

const int motorPin1 = A3; // 電機(jī)速度信號(hào)輸入引腳1連接到D3

const int motorPin2 = A4; // 電機(jī)速度信號(hào)輸入引腳2連接到D4(霍爾效應(yīng)轉(zhuǎn)速傳感器信號(hào)輸入引腳)

const float kp = 5.0; // 比例系數(shù),根據(jù)實(shí)際情況調(diào)整

const float ki = 0.5; // 積分系數(shù),根據(jù)實(shí)際情況調(diào)整

float errorSum = 0; // 誤差累積值

float lastError = 0; // 上一次的誤差值

float integral = 0; // 積分值

float targetSpeed = 1000; // 目標(biāo)轉(zhuǎn)速(rpm)

float currentSpeed = 0; // 當(dāng)前電機(jī)轉(zhuǎn)速(rpm)

float outputSpeed = 0; // 輸出電機(jī)控制信號(hào)(PWM占空比)

void setup() {

pinMode(nearSwitchPin, INPUT);

pinMode(motorPin1, INPUT_PULLUP);

pinMode(motorPin2, INPUT);

}

void loop() {

int nearState = digitalRead(nearSwitchPin); // 讀取接近開(kāi)關(guān)狀態(tài)

float currentSpeedFloat = analogRead(motorPin2) * (5.0 * (1.0 + (3.3 * VREF)/(65536.0 * 110))) * (5.0 * (1.0 + (3.3 * VREF)/(65536.0 * 110))); // 讀取霍爾效應(yīng)轉(zhuǎn)速傳感器數(shù)據(jù)并轉(zhuǎn)換為rpm單位(假設(shè)VREF為5V)

currentSpeed = currentSpeedFloat * (60.0 * (1.0 + (3.3 * VREF)/(65536.0 * 110))) * (60.0 * (1.0 + (3.3 * VREF)/(65536.0 * 110))); // 將當(dāng)前轉(zhuǎn)速轉(zhuǎn)換為rpm單位(假設(shè)VREF為5V)

if (nearState == HIGH) { // 如果接近開(kāi)關(guān)被觸發(fā)(即電機(jī)轉(zhuǎn)動(dòng)到位)

int encoderValue = pulseIn(motorPin1, HIGH); // 通過(guò)脈沖寬度調(diào)制方法獲取編碼器計(jì)數(shù)(假設(shè)編碼器已連接至D3引腳)

encoderValue = encoderValue * CLOCK_PRESCALER + PULSE_OVERHEAD; // 根據(jù)時(shí)鐘分頻系數(shù)和脈沖延遲時(shí)間修正計(jì)數(shù)值(CLOCK_PRESCALER和PULSE_OVERHEAD需根據(jù)實(shí)際情況進(jìn)行設(shè)置)

int distance = encoderValue * GEAR_RATIO; // 根據(jù)齒輪比計(jì)算實(shí)際距離變化量(GEAR_RATIO需根據(jù)實(shí)際情況進(jìn)行設(shè)置)

int targetDistance = distance * SPEED_CHANGER_FACTOR; // 根據(jù)目標(biāo)速度計(jì)算需要達(dá)到的實(shí)際距離(SPEED_CHANGER_FACTOR需根據(jù)實(shí)際情況進(jìn)行設(shè)置)

int actualDistance = currentSpeedInt * ROTATION_PERIOD; // 根據(jù)當(dāng)前速度和每分鐘轉(zhuǎn)數(shù)計(jì)算實(shí)際距離(ROTATION_PERIOD需根據(jù)實(shí)際情況進(jìn)行設(shè)置)

int error = targetDistance - actualDistance; // 計(jì)算偏差值

int integralPart = integral + error; // 積分累加值增加偏差值

float derivative = error - lastError; // 計(jì)算導(dǎo)數(shù)值(當(dāng)前偏差值與上一次偏差值之差)

int outputSignal = saturate((KP * error + KI * integralPart + derivative), INT_MIN, INT_MAX); // 根據(jù)比例、積分、微分調(diào)節(jié)公式計(jì)算輸出信號(hào)(飽和處理以防止輸出信號(hào)超出整數(shù)范圍)

outputSpeed = map(outputSignal, INT_MIN, INT_MAX, 0, 255); // 將輸出信號(hào)映射到PWM占空比范圍(例如:0%對(duì)應(yīng)0%,255%對(duì)應(yīng)100%)

analogWritePWM(motorPin2, outputSpeed); // 將輸出信號(hào)寫(xiě)入PWM通道以控制電機(jī)轉(zhuǎn)速(假設(shè)已經(jīng)配置好了PWM功能)

deltaAngle = angleToTicks(distance); // 根據(jù)距離變化量計(jì)算脈沖寬度調(diào)制脈寬對(duì)應(yīng)的脈沖數(shù)(假設(shè)已經(jīng)實(shí)現(xiàn)了angleToTicks函數(shù))

int ticks = abs((pulseInLow(motorPin1, HIGH))+(pulseInLow(motorPin2, HIGH))); // 通過(guò)脈沖寬度調(diào)制方法讀取編碼器的累計(jì)脈沖數(shù)(假設(shè)已經(jīng)實(shí)現(xiàn)了pulseInLow函數(shù)) dco=ticks/deltaAngle; dco=map(dco,INT_MIN+1,INT_MAX-1,TARGET_TICKS+1,TARGET_TICKS*SPEED); dco=map(dco,TARGET_TICKS+1,TARGET_TICKS*SPEED+1,TARGET_TICKS+1,TARGET_TICKS*SPEED); dco=map(dco,TARGET_TICKS+1,TARGET_TICKS*SPEED+1,TARGET_TICKS+1,TARGET_TICKS*SPEED); dco/=(TARGET_TICKS*SPEED); dco*=TARGET_TICKS/((TARGET_TICKS-dco)*SPEED); dco*=TARGET_TICKS/((TARGET_TICKS-dco)*SPEED); dco/=(TARGET_TICKS*(SPEED-dco)); dco*=TARGET_TICKS*(SPEED-dco); dco/=(TARGET_TICKS*(SPEED-dco)); dco*=TARGET_TICKS*(SPEED-dco); dco/=(TARGET_TICKS*(SPEED-dco)); dco*=TARGET_TICKS*(SPEED-dco); uint8_t _targetTicks=ticks/deltaAngle; _targetTicks=map(_targetTicks,INT_MIN+1,INT_MAX-1,TARGET_TICKS+1,TARGET_TICKS*SPEED); _targetTicks=map(_targetTicks,TARGET_TICKS+1,TARGET_TICKS*SPEED+1,TARGET_TICKS+1,TARGET_TICKS*SPEED); _targetTicks=map(_targetTicks,TARGET_TICKS+1,TARGET_TICKS*SPEED+1,TARGET_TICKS+1,TARGET_TICKS*SPEED); _targetTicks=(uint8)(roundf((float)(abs((ticks/deltaAngle)))/(float)(TARGET_TICKS*(SPEED-dco))))); _targetTicks=map((uint8)(roundf((float)(abs((ticks/deltaAngle)))/(float)(TARGET_TICKS*(SPEED-d

推薦產(chǎn)品