91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【開源分享】DIY 電動滑板玩出黑科技!TOF 激光剎車 + 平滑調(diào)速性能體驗感雙在線!

電子發(fā)燒友論壇 ? 2026-01-15 08:07 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

本項目是【RT-Thread 2025年度嵌入式大賽——硬件拓展板賽道】優(yōu)秀作品

本次大賽作品由 [華秋電子] 、[KiCad 華秋發(fā)行版] 提供硬件制作支持。

更多大賽作品:https://p.eda.cn/collection/rtthw

2f944800-f1a6-11f0-8ce9-92fbcf53809c.png


1. 前言

在2018年我本科在萬宇杰老師的帶領(lǐng)下和小伙伴們一起立了校級重點科研立項——《DIY電動滑板》,非常懷戀那時候的干勁,閑暇時分傍晚和枚金江一起玩滑板飛馳綠道,白天和劉姣一起畫工程圖,晚上和葉俊吉萬金華他們做舞蹈機器人,時光就是這樣一點點緩緩流淌過。

不知不覺中雙元班的同窗們都各自高飛,而我還在艱難的求學(xué)中(2025年10月被OE、11月CEP拒稿)。恰巧也讓我有了新的想法,之前的滑板是用Arduino Uno加拓展板設(shè)計的硬件,現(xiàn)在運輸小船做實驗就由我的滑板小小的身體承受著,每次都要走公里才能到達海邊?;遢d著小船漫步過海濱小路,載著我跑過鄉(xiāng)村小路,載著打印機溜過校園大道彎兒,值得高興的是我的滑板已經(jīng)累計有200公里左右,也沒有出現(xiàn)什么故障,嘻嘻。



接著這樣的機會嘗試用本次《2025RTT硬件設(shè)計大賽》中的Vision board來移植原來的Arduino Uno方案,以此來紀(jì)念我的青春創(chuàng)作,保留原先Uno拓展板的電氣與硬件。這次比賽首先是繪制類似Arduino Uno原先的端口封裝與Vision board之間的拓展板,其次移植藍牙控制程序和改進主動剎車功能。

2fac600c-f1a6-11f0-8ce9-92fbcf53809c.jpg

2. 設(shè)計方案

本設(shè)計采用長板滑板版面,選用直流無刷電機,購買繪制特殊規(guī)格長板滑板的皮帶輪及電機架,以航模電池3S5200MAH電池供電。配以專用直流無刷電機電調(diào)。主控電路與遙控電路均以Vision Board為核心,使用藍牙數(shù)據(jù)通訊協(xié)議進行無線數(shù)據(jù)透傳,采用PWM脈沖寬度調(diào)制方式,采用TOF激光距離傳感器進行緊急制動判斷。以下為各模塊設(shè)計簡介。

2.1 機械結(jié)構(gòu)模塊

機械模塊主要解決傳動系統(tǒng)搭建及電機的安裝。車架架設(shè)計為高64MM,長248MM7.25英寸的支架。傳動系統(tǒng)采用同步輪傳動,使用皮帶連接。齒輪比是大輪36齒,小輪12齒,用5M*270,11帶寬齒的齒輪帶連接,傳動比為3:1,如圖電機支架同步輪及配件。

2fb7d8ce-f1a6-11f0-8ce9-92fbcf53809c.jpg

2.2 電機模塊

電機的KV值,決定著電機的轉(zhuǎn)速增加量,KV值越大轉(zhuǎn)速越快。電動滑板在啟動時,由于靜摩擦的原因,啟動的階段阻力非常大,之后阻力會突然變小。所以,電動滑板在啟動之后常常有頓挫感。電機的選擇對滑板的安全性的提升顯得尤為重要。根據(jù)滑板的啟動的特性,應(yīng)選用KV值越小的電機。

2.2.1 電機選擇

本設(shè)計電機選用N5065外轉(zhuǎn)子無刷電機270KV,其各項參數(shù)指標(biāo)如圖左邊為無刷電機N5065,右邊為C5065

2fc1a4e4-f1a6-11f0-8ce9-92fbcf53809c.jpg

首先從電機型號上來說n5065表示電機尺寸為:直徑50mm,長度65mm。前面的n和c表示系列號,其中n系列做工和工作效率高于c系,N電機比C電機功率大,發(fā)熱小,扭力大。N電機比C電機的磁鐵長度和定子長度稍微長一些,n系尾部為平面,c系尾部為錐形。詳細參數(shù)如下: 可以看到,n5065的功率要比c5065大,一個是1820W,一個是1665W。電壓比c5065高,重量也比c5065重50g。(注:這里只說了KV值400的,你也可以選擇270的) 根據(jù)公式:轉(zhuǎn)速=KV值X電壓; n5065電機轉(zhuǎn)速=KV (400)x22(v)=8800rpm ; c5065電機轉(zhuǎn)速=KV (400) x20(v)=8000rpm ;

2.2.2 電機控制

單片機的控制信號,可以輕松輸出0或1,如果需要控制電機信號就需要PWM脈沖寬度調(diào)制,也可參考SG90舵機控制。在本設(shè)計中使用KV值為270KV的N5065無刷電機,無刷電機和有刷電機有相似之處,也有轉(zhuǎn)子和定子,只不過和有刷電機的結(jié)構(gòu)相反;有刷電機的轉(zhuǎn)子是線圈繞組,和動力輸出軸相連,定子是永磁磁鋼;無刷電機的轉(zhuǎn)子是永磁磁鋼,連同外殼一起和輸出軸相連,定子是繞組線圈,去掉了有刷電機用來交替變換電磁場的換向電刷,故稱之為無刷電機。依靠改變輸入到無刷電機定子線圈上的電流波交變頻率和波形,在繞組線圈周圍形成一個繞電機幾何軸心旋轉(zhuǎn)的磁場,這個磁場驅(qū)動轉(zhuǎn)子上的永磁磁鋼轉(zhuǎn)動,電機就轉(zhuǎn)起來了,電機的性能和磁鋼數(shù)量、磁鋼磁通強度、電機輸入電壓大小等因素有關(guān),更與無刷電機的控制性能有很大關(guān)系,因為輸入的是直流電,電流需要電子調(diào)速器將其變成3相交流電,還需要從遙控器接收機那里接收控制信號,控制電機的轉(zhuǎn)速,以滿足模型使用需要。相比于傳統(tǒng)直流有刷電機相比,無刷電機能量密度高,力矩大,重量輕,性能好等優(yōu)點。增強了電機的可靠性,但是無刷電機的驅(qū)動比有刷電機要復(fù)雜得多,需要通過專門的電子驅(qū)動器才能正常工作,為降低開發(fā)難度的目的,該部分采用了車模用的無刷電機調(diào)速器,該調(diào)速器可根據(jù)輸入的PWM信號占空比的大小來控制無刷電機的轉(zhuǎn)速。

2.3 主控板及其遙控模塊

本設(shè)計選用Vision board作為控制芯片,手機app收發(fā)作為上位機遙控。app使用參考

2fcb4800-f1a6-11f0-8ce9-92fbcf53809c.jpg

2.3.1 主控芯片選擇

Vision Board搭載全球首顆 480 MHz Arm Cortex-M85芯片,擁有Helium和TrustZone技術(shù)的加持。SDK包里集成了OpenMV機器視覺例程,配合MicroPython 解釋器,使其可以流暢地開發(fā)機器視覺應(yīng)用。Vision Board搭載了全球首款基于 ARM Cortex-M85 架構(gòu)的瑞薩電子RA8 MCU,6.39 CoreMark/MHz,可以快速而高效地運行機器視覺算法,實現(xiàn)圖像處理、等功能。雖然在這個電動滑板大材小用,但是給代碼框架和使用安全上提高了不少。

2fd74dee-f1a6-11f0-8ce9-92fbcf53809c.jpg

參考資料見:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/tutorial/make-bsp/renesas-ra/%E7%91%9E%E8%90%A8VisionBoard%E5%BC%80%E5%8F%91%E5%AE%9E%E8%B7%B5%E6%8C%87%E5%8D%97

2.3.2 無線通信模塊的選取

本設(shè)計的無線通信模塊選擇經(jīng)典HC-05主從機一體藍牙模塊,該模塊能耗低,穩(wěn)定性強,具有很好的抗干擾能力。選用藍牙模塊以后,可以實現(xiàn)雙向通訊,加入顯示模塊及其他傳感器模塊后,遙控器可顯示電池電量,行駛速度,行駛里程和載重等。為之后功能的增加和改進,提供了便利,同時大量搭載藍牙的設(shè)備可以用于控制滑板,例如開發(fā)手機APP控制端,將手機作為遙控端使用。

2fe0254a-f1a6-11f0-8ce9-92fbcf53809c.jpg

本設(shè)計的遙控器和主控板上,分別有一塊Vision board和一個HC-05藍牙模塊。藍牙模塊設(shè)置了自動配對之后,上電之后它們就進入“傳輸”狀態(tài),這時,使用函數(shù)串口8編寫讀取解析程序,便可實現(xiàn)遙控器與主控板之間的數(shù)據(jù)傳輸。

2.3.3 自動緊急剎車控制

防追尾系統(tǒng)對于駕駛員來說是一大必要輔助駕駛利器。此次設(shè)計的防追尾系統(tǒng)主要利用超聲波在空氣中的傳播速度和關(guān)系進行測量。超聲波具有指向性強、能量消耗慢且在介質(zhì)中傳播距離較遠特點。其實說到超聲波,我們就會想到蝙蝠,是的,它的工作原理就是模仿蝙蝠的。先發(fā)出一個聲音,然后在接收返回的聲音,通過發(fā)出和返回的時間差來可以計算出距離,就這么簡單。所以我們就要有一個機制,發(fā)出多長的光信號,回收采集的理論上應(yīng)該是發(fā)出的同時就要采樣收集了。

原先的方案是超聲波測距,之前實測發(fā)現(xiàn)會頻繁誤觸,而且采樣時間非常長(兩次連續(xù)判斷1.5m障礙物大約需要0.5s,如果車速在2m/s,會明顯剎車來不及,主要是反應(yīng)時間有點長,發(fā)生碰撞危險),這次采用I2c距離TOF傳感器,看看效果應(yīng)該要好一點點

2feaa8b2-f1a6-11f0-8ce9-92fbcf53809c.jpg

3. 實驗步驟

3.1 實驗材料

主控板:Vision board開發(fā)板,sensor shield拓展板,USB數(shù)據(jù)線 傳感器:TOF傳感器,光照傳感器 執(zhí)行器:N5056無刷電機,LED燈,一路高電平觸發(fā)繼電器,有源蜂鳴器 通訊:藍牙HC05 輔助硬件:滑板,同步帶結(jié)構(gòu),盒子,泡沫,熱熔膠,公母線若干 軟件:一臺安裝RT-Thread開發(fā)環(huán)境的電腦

3.2 根據(jù)原理圖搭建電路

實驗原理圖: 2ff697da-f1a6-11f0-8ce9-92fbcf53809c.jpg

藍牙RX接uart8的TX,藍牙TX接uart8的RX

有源蜂鳴器引腳2

繼電器引腳4,然后單獨接led燈與外接電源串聯(lián)

ESC定義無刷電機引腳9,電調(diào)提供電源

TOF測距SDA接A4,SCL接A5

光照檢測接A0

3.4 PCB及三維圖

300314b0-f1a6-11f0-8ce9-92fbcf53809c.jpg

整體元器件非常少,就2202.54排母下面連接Vision board,然后6/2*8/10排母在上方連接Arduino Uno拓展板

下面是硬件細節(jié)圖 拓展板焊接效果 300f7714-f1a6-11f0-8ce9-92fbcf53809c.jpg

30187f30-f1a6-11f0-8ce9-92fbcf53809c.jpg


控制器電源電調(diào)都安裝在防水盒中 30231620-f1a6-11f0-8ce9-92fbcf53809c.jpg控制盒整體外觀

30304f84-f1a6-11f0-8ce9-92fbcf53809c.jpg

3.5 源碼分享

配置串口2

303d4ea0-f1a6-11f0-8ce9-92fbcf53809c.jpg


配置PWM12

304e95c0-f1a6-11f0-8ce9-92fbcf53809c.jpg


配置軟件I2C

3058c13a-f1a6-11f0-8ce9-92fbcf53809c.jpg3064bd50-f1a6-11f0-8ce9-92fbcf53809c.jpg307210cc-f1a6-11f0-8ce9-92fbcf53809c.jpg


配置ADC

307c8a34-f1a6-11f0-8ce9-92fbcf53809c.jpg


rt-thread設(shè)備驅(qū)動勾選

30895322-f1a6-11f0-8ce9-92fbcf53809c.jpg

下面是程序控制源碼

/*
? Copyright (c) 2024, YourName

? 項目:基于 RT-Thread 的電機 ESC 控制(移植自 Arduino)

? 功能:通過串口接收指令控制電機轉(zhuǎn)速、LED、蜂鳴器,集成VL53L0X主動剎車和光線檢測自動夜燈

? 已移除:超聲波、光敏電阻、自動急停

? 新增:所有速度檔位切換必須平滑加減速(逐步 ±1,每次延時 50ms)
? 修復(fù):ESC電調(diào)上電初始化問題
? 新增:VL53L0X激光測距主動剎車功能
? 新增:光線檢測自動夜燈功能
*/

#include
#include
#include
#include"hal_data.h"

// ====================== 引腳 / 設(shè)備 宏定義 ======================
#definePWM_DEV_NAME "pwm12" // PWM設(shè)備名,請根據(jù)實際連接修改
#definePWM_CHANNEL 0 // PWM通道

#defineLED_PIN BSP_IO_PORT_00_PIN_01 // LED引腳(根據(jù)實際修改)
#defineBUZZER_PIN BSP_IO_PORT_05_PIN_05 // 蜂鳴器引腳(根據(jù)實際修改)

#defineSERIAL_DEVICE_NAME "uart2" // 串口設(shè)備名,如USB轉(zhuǎn)串口 / 藍牙模塊

// ====================== VL53L0X 配置 ======================
#defineTOF_DEVICE_NAME "tof_vl53l0x" // VL53L0X設(shè)備名
#defineBRAKE_DISTANCE 1000 // 剎車距離閾值:1000mm = 1m
#defineBRAKE_SAMPLE_COUNT 2 // 連續(xù)檢測次數(shù)

// ====================== ADC 光線檢測配置 ======================
#defineADC_DEV_NAME "adc1" // ADC 設(shè)備名稱
#defineADC_DEV_CHANNEL 4 // ADC 通道
#defineREFER_VOLTAGE 330 // 參考電壓 3.3V,數(shù)據(jù)精度乘以100保留2位小數(shù)
#defineCONVERT_BITS (1 << 12) ? // 轉(zhuǎn)換位數(shù)為12位
#defineLIGHT_THRESHOLD 200 // 光線閾值,小于200為夜間
#defineLIGHT_SAMPLE_DELAY 2000 // 光線檢測間隔:2秒

// ====================== 速度檔位定義 ======================
volatile int item = 1000; // 當(dāng)前速度值(擴大10倍以支持小數(shù)計算)
const int speed_level = 1000; // 啟動速度(對應(yīng)1.0ms)
const int speed_min = 950; // 最低速度(對應(yīng)0.95ms)
const int speed_one = 1150; // 檔位1(對應(yīng)1.15ms)
const int speed_two = 1250; // 檔位2(對應(yīng)1.25ms)
const int speed_three = 1300; // 檔位3(對應(yīng)1.3ms)
const int speed_max = 1400; // 檔位4(最高速,對應(yīng)1.4ms)
const int speed_add = 50; // 每次調(diào)整步進(對應(yīng)0.05ms)

// ====================== 全局變量 ======================
static struct rt_device_pwm *pwm_dev;
static rt_device_t serial_dev;
static rt_device_t tof_dev = RT_NULL; // VL53L0X設(shè)備句柄
static rt_adc_device_t adc_dev = RT_NULL; // ADC設(shè)備句柄
char rx_buffer[64];
int rx_len = 0;

static bool is_started = false; // 系統(tǒng)是否已啟動
static bool esc_initialized = false; // ESC是否已完成初始化
static bool auto_brake_enabled = true; // 自動剎車功能是否啟用
static bool auto_light_enabled = true; // 自動夜燈功能是否啟用
static bool manual_light_control = false; // 手動燈光控制標(biāo)志
static int brake_counter = 0; // 連續(xù)剎車檢測計數(shù)器
static int current_light_level = 0; // 當(dāng)前光線強度

// ====================== PWM脈沖寬度計算 ======================
// 將速度值轉(zhuǎn)換為PWM脈沖寬度(納秒)
static int speed_to_pulse(int speed_val)
{
// 將速度值映射到安全范圍內(nèi)
int pulse_ns = 950000 + (speed_val - 950) * (450000 / (1400 - 950));

// 確保在安全范圍內(nèi)
if (pulse_ns < 950000) pulse_ns = 950000;
if (pulse_ns > 1400000) pulse_ns = 1400000;

return pulse_ns;
}

// ====================== 蜂鳴器控制 ======================
void buzzer_beep(int count, int duration_ms)
{
for (int i = 0; i < count; i++)
{
rt_pin_write(BUZZER_PIN, PIN_HIGH);
rt_thread_mdelay(duration_ms);
rt_pin_write(BUZZER_PIN, PIN_LOW);
rt_thread_mdelay(duration_ms);
}
}

// ====================== ESC初始化序列 ======================
static void esc_init_sequence(void)
{
rt_kprintf("[ESC] Starting initialization sequence...\r\n");

// 發(fā)送安全啟動信號
rt_kprintf("[ESC] Setting to safe start position (1.0ms)...\r\n");
rt_pwm_set(pwm_dev, PWM_CHANNEL, 20000000, 1000000); // 1.0ms
rt_thread_mdelay(1000);

esc_initialized = true;
rt_kprintf("[ESC] Initialization completed successfully!\r\n");
buzzer_beep(3, 100); // 3聲短鳴表示初始化完成
}

// ====================== LED 控制 ======================
void led_on(void)
{
rt_pin_write(LED_PIN, PIN_HIGH);
}

void led_off(void)
{
rt_pin_write(LED_PIN, PIN_LOW);
}

// ====================== ADC 光線檢測函數(shù) ======================
static int read_light_level(void)
{
rt_uint32_t value, vol;
rt_err_t ret = RT_EOK;

if (adc_dev == RT_NULL)
{
rt_kprintf("[LIGHT] ADC device not initialized!\r\n");
return -1;
}

// 使能設(shè)備
ret = rt_adc_enable(adc_dev, ADC_DEV_CHANNEL);
if (ret != RT_EOK)
{
rt_kprintf("[LIGHT] Failed to enable ADC channel!\r\n");
return -1;
}

// 讀取采樣值
value = rt_adc_read(adc_dev, ADC_DEV_CHANNEL);

// 轉(zhuǎn)換為對應(yīng)電壓值(乘以100保留2位小數(shù))
vol = value * REFER_VOLTAGE / CONVERT_BITS;

// 關(guān)閉通道
ret = rt_adc_disable(adc_dev, ADC_DEV_CHANNEL);

// 返回原始ADC值(0-4095),值越小表示光線越暗
return (int)value;
}

// ====================== 自動燈光控制 ======================
static void auto_light_control(void)
{
if (!auto_light_enabled || manual_light_control)
{
return;
}

int light_level = read_light_level();
if (light_level < 0)
{
return; // 讀取失敗
}

current_light_level = light_level;

// 光線閾值判斷:小于200為夜間
if (light_level < LIGHT_THRESHOLD)
{
// 夜間模式,開啟LED
led_on();
static bool night_mode_reported = false;
if (!night_mode_reported)
{
rt_kprintf("[LIGHT] Night mode detected. Light level: %d, LED ON\r\n", light_level);
night_mode_reported = true;
}
}
else
{
// 白天模式,關(guān)閉LED
led_off();
static bool day_mode_reported = false;
if (!day_mode_reported)
{
rt_kprintf("[LIGHT] Day mode detected. Light level: %d, LED OFF\r\n", light_level);
day_mode_reported = true;
}
}
}

// ====================== 緊急剎車函數(shù) ======================
static void emergency_brake(void)
{
rt_kprintf("[BRAKE] EMERGENCY BRAKE ACTIVATED! Distance too close.\r\n");

// 快速減速到最小值(比平滑減速更快)
int current_speed = item;
rt_kprintf("[BRAKE] Rapid deceleration from %d to %d\r\n", current_speed, speed_min);

while (item > speed_min)
{
item -= 2; // 每次減2,更快減速

// 防止低于最小值
if (item < speed_min)
{
item = speed_min;
}

int pulse = speed_to_pulse(item);
rt_pwm_set(pwm_dev, PWM_CHANNEL, 20000000, pulse);
rt_thread_mdelay(20); // 更短的延時,快速剎車
}

// 剎車提示
buzzer_beep(3, 100);
led_on(); // LED亮起表示剎車狀態(tài)

rt_kprintf("[BRAKE] Emergency brake completed. Speed: %d\r\n", item);
}

// ====================== 平滑加減速函數(shù) =======================
static void smooth_set_speed(int target)
{
if (!esc_initialized)
{
rt_kprintf("[ERROR] ESC not initialized! Cannot set speed.\r\n");
return;
}

int step = (target > item) ? 1 : -1;

rt_kprintf("[Smooth] Changing speed from %d to %d...\r\n", item, target);

while (item != target)
{
item += step;

// 防止超過目標(biāo)
if ((step > 0 && item > target) || (step < 0 && item < target))
{
item = target;
}

// 設(shè)置 PWM
int pulse = speed_to_pulse(item);
rt_pwm_set(pwm_dev, PWM_CHANNEL, 20000000, pulse);
rt_thread_mdelay(30);

rt_kprintf("[Smooth] Now at: %d (Pulse: %dns)\r\n", item, pulse);
}

rt_kprintf("[Smooth] Reached target: %d\r\n", item);
}

// ====================== VL53L0X 距離監(jiān)測線程 ======================
static void distance_monitor_thread_entry(void *parameter)
{
struct rt_sensor_data sensor_data;
rt_size_t res;

rt_kprintf("[VL53L0X] Distance monitoring thread started.\r\n");

// 查找VL53L0X設(shè)備
tof_dev = rt_device_find(TOF_DEVICE_NAME);
if (tof_dev == RT_NULL)
{
rt_kprintf("[VL53L0X] ERROR: Cannot find VL53L0X device: %s\r\n", TOF_DEVICE_NAME);
return;
}

// 打開設(shè)備
if (rt_device_open(tof_dev, RT_DEVICE_FLAG_RDONLY) != RT_EOK)
{
rt_kprintf("[VL53L0X] ERROR: Failed to open VL53L0X device.\r\n");
return;
}

rt_kprintf("[VL53L0X] Device opened successfully. Starting distance monitoring...\r\n");

while (1)
{
// 只有系統(tǒng)已啟動且自動剎車啟用時才進行距離檢測
if (is_started && auto_brake_enabled && esc_initialized)
{
res = rt_device_read(tof_dev, 0, &sensor_data, 1);
if (res == 1)
{
int distance = sensor_data.data.proximity;

// 調(diào)試輸出(可選,避免輸出過于頻繁)
static int debug_counter = 0;
if (debug_counter++ % 10 == 0) // 每10次輸出一次
{
rt_kprintf("[VL53L0X] Distance: %d mm\r\n", distance);
}

// 檢測到障礙物距離小于閾值
if (distance > 0 && distance < BRAKE_DISTANCE)
{
brake_counter++;
rt_kprintf("[VL53L0X] Obstacle detected: %d mm (counter: %d/%d)\r\n",
distance, brake_counter, BRAKE_SAMPLE_COUNT);

// 連續(xù)2次檢測到障礙物,觸發(fā)緊急剎車
if (brake_counter >= BRAKE_SAMPLE_COUNT)
{
emergency_brake();
brake_counter = 0; // 重置計數(shù)器
}
}
else
{
// 距離安全,重置計數(shù)器
if (brake_counter > 0)
{
rt_kprintf("[VL53L0X] Distance safe: %d mm. Reset brake counter.\r\n", distance);
brake_counter = 0;
// 注意:這里不關(guān)閉LED,因為LED可能由光線控制
}
}
}
else
{
rt_kprintf("[VL53L0X] ERROR: Failed to read distance data.\r\n");
}
}
else
{
// 系統(tǒng)未啟動或剎車禁用,重置計數(shù)器
brake_counter = 0;
}

rt_thread_mdelay(50); // 50ms檢測周期
}
}

// ====================== 光線檢測線程 ======================
static void light_monitor_thread_entry(void *parameter)
{
rt_kprintf("[LIGHT] Light monitoring thread started.\r\n");

// 初始化ADC設(shè)備
adc_dev = (rt_adc_device_t)rt_device_find(ADC_DEV_NAME);
if (adc_dev == RT_NULL)
{
rt_kprintf("[LIGHT] ERROR: Cannot find ADC device: %s\r\n", ADC_DEV_NAME);
return;
}

rt_kprintf("[LIGHT] ADC device initialized successfully.\r\n");

while (1)
{
// 只有系統(tǒng)已啟動時才進行光線檢測
if (is_started)
{
auto_light_control();
}

rt_thread_mdelay(LIGHT_SAMPLE_DELAY); // 2秒檢測一次
}
}

// ====================== 指令動作處理函數(shù) ======================
void action(const char *throttle)
{
rt_kprintf("[Action] Received: %s\r\n", throttle);

if (strcmp(throttle, "stop") == 0)
{
smooth_set_speed(speed_level);
// 注意:這里不控制LED關(guān)閉,因為可能由光線控制
buzzer_beep(1, 500);
rt_kprintf("[Action] STOPPED. Speed set to level.\r\n");
is_started = false;
brake_counter = 0; // 重置剎車計數(shù)器
}
else if (strcmp(throttle, "decrease") == 0)
{
int target = item - speed_add;
if (target < speed_min)
target = speed_min;
smooth_set_speed(target);
buzzer_beep(1, 100);
rt_kprintf("[Action] DECREASED (smooth). Speed: %d\r\n", item);
}
else if (strcmp(throttle, "increase") == 0)
{
int target = item + speed_add;
if (target > speed_max)
target = speed_max;
smooth_set_speed(target);
buzzer_beep(1, 200);
rt_kprintf("[Action] INCREASED (smooth). Speed: %d\r\n", item);
}
else if (strcmp(throttle, "one") == 0)
{
smooth_set_speed(speed_one);
buzzer_beep(1, 150);
rt_kprintf("[Action] SPEED 1 (smooth). Speed: %d\r\n", item);
}
else if (strcmp(throttle, "two") == 0)
{
smooth_set_speed(speed_two);
buzzer_beep(2, 150);
rt_kprintf("[Action] SPEED 2 (smooth). Speed: %d\r\n", item);
}
else if (strcmp(throttle, "three") == 0)
{
smooth_set_speed(speed_three);
buzzer_beep(3, 150);
rt_kprintf("[Action] SPEED 3 (smooth). Speed: %d\r\n", item);
}
else if (strcmp(throttle, "four") == 0)
{
smooth_set_speed(speed_max);
buzzer_beep(4, 150);
rt_kprintf("[Action] SPEED 4 (MAX, smooth). Speed: %d\r\n", item);
}
else if (strcmp(throttle, "turn on") == 0)
{
manual_light_control = true; // 進入手動控制模式
led_on();
buzzer_beep(1, 200);
rt_kprintf("[Action] LED ON (Manual control)\r\n");
}
else if (strcmp(throttle, "turn off") == 0)
{
manual_light_control = true; // 進入手動控制模式
led_off();
buzzer_beep(1, 200);
rt_kprintf("[Action] LED OFF (Manual control)\r\n");
}
else if (strcmp(throttle, "auto light") == 0)
{
manual_light_control = false; // 退出手動控制,返回自動模式
rt_kprintf("[Action] Auto light control ENABLED\r\n");
buzzer_beep(1, 200);
}
else if (strcmp(throttle, "buzzer on") == 0)
{
buzzer_beep(2, 300);
rt_kprintf("[Action] BUZZER ON\r\n");
}
else if (strcmp(throttle, "buzzer off") == 0)
{
buzzer_beep(2, 100);
rt_kprintf("[Action] BUZZER OFF\r\n");
}
else if (strcmp(throttle, "init esc") == 0)
{
esc_init_sequence();
}
else if (strcmp(throttle, "brake on") == 0)
{
auto_brake_enabled = true;
rt_kprintf("[Action] Auto brake ENABLED\r\n");
buzzer_beep(1, 200);
}
else if (strcmp(throttle, "brake off") == 0)
{
auto_brake_enabled = false;
rt_kprintf("[Action] Auto brake DISABLED\r\n");
buzzer_beep(2, 200);
}
else if (strcmp(throttle, "light on") == 0)
{
auto_light_enabled = true;
rt_kprintf("[Action] Auto light ENABLED\r\n");
buzzer_beep(1, 200);
}
else if (strcmp(throttle, "light off") == 0)
{
auto_light_enabled = false;
rt_kprintf("[Action] Auto light DISABLED\r\n");
buzzer_beep(2, 200);
}
else if (strcmp(throttle, "test brake") == 0)
{
rt_kprintf("[Action] Testing emergency brake...\r\n");
emergency_brake();
}
else if (strcmp(throttle, "light status") == 0)
{
rt_kprintf("[LIGHT] Current light level: %d, Threshold: %d, Auto: %s, Manual: %s\r\n",
current_light_level, LIGHT_THRESHOLD,
auto_light_enabled ? "ON" : "OFF",
manual_light_control ? "ON" : "OFF");
}
else
{
rt_kprintf("[Action] Unknown command: %s\r\n", throttle);
}
}

// ====================== 串口指令線程 ======================
static void serial_cmd_thread_entry(void *parameter)
{
rt_size_t len;

while (1)
{
memset(rx_buffer, 0, sizeof(rx_buffer));
len = rt_device_read(serial_dev, 0, rx_buffer, sizeof(rx_buffer) - 1);
if (len > 0)
{
// 去除換行符和回車符
for (int i = 0; i < len; i++)
{
if (rx_buffer[i] == '\r' || rx_buffer[i] == '\n')
{
rx_buffer[i] = '\0';
break;
}
}

rt_kprintf("[Serial] Rx: %s\r\n", rx_buffer);

if (!is_started)
{
if (strcmp(rx_buffer, "start") == 0)
{
if (!esc_initialized)
{
rt_kprintf("[System] Initializing ESC for first start...\r\n");
esc_init_sequence();
}

is_started = true;
rt_kprintf("[System] System STARTED.\r\n");
buzzer_beep(2, 300);
}
else
{
rt_kprintf("[System] ERROR: System NOT STARTED. Send 'start' first.\r\n");
}
}
else
{
action(rx_buffer);
}

rx_buffer[0] = '\0';
}
rt_thread_mdelay(10);
}
}

// ====================== VL53L0X 硬件初始化 ======================
static int rt_hw_vl53l0x_port(void)
{
struct rt_sensor_config cfg;

cfg.intf.dev_name = "i2c1"; /* i2c bus */
cfg.intf.user_data = (void *)0x29; /* i2c slave addr */

// 注意:這個函數(shù)名稱需要根據(jù)你實際的VL53L0X驅(qū)動來調(diào)整
rt_hw_vl53l0x_init("vl53l0x", &cfg, 57); /* xshutdown ctrl pin */

rt_kprintf("[VL53L0X] Hardware port initialized.\r\n");
return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_vl53l0x_port);

// ====================== 初始化函數(shù) ======================
int motor_control_app_init(void)
{
rt_kprintf("=== Motor Control System Starting ===\r\n");

// 1. 初始化 PWM
pwm_dev = (struct rt_device_pwm *) rt_device_find(PWM_DEV_NAME);
if (pwm_dev == RT_NULL)
{
rt_kprintf("Cannot find PWM device: %s\r\n", PWM_DEV_NAME);
return -1;
}

// 啟用PWM設(shè)備,設(shè)置安全啟動位置
rt_pwm_enable(pwm_dev, PWM_CHANNEL);
rt_pwm_set(pwm_dev, PWM_CHANNEL, 20000000, 1000000); // 1.0ms
rt_thread_mdelay(1000);
rt_kprintf("PWM ESC device enabled at safe position.\r\n");

// 2. 初始化 LED & 蜂鳴器
rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
rt_pin_mode(BUZZER_PIN, PIN_MODE_OUTPUT);
led_off();
rt_pin_write(BUZZER_PIN, PIN_LOW);

// 3. 打開串口
serial_dev = rt_device_find(SERIAL_DEVICE_NAME);
if (serial_dev == RT_NULL)
{
rt_kprintf("Cannot find serial device: %s\r\n", SERIAL_DEVICE_NAME);
return -1;
}

rt_device_open(serial_dev, RT_DEVICE_FLAG_INT_RX);

// 4. 創(chuàng)建串口指令線程
rt_thread_t tid = rt_thread_create("serial_cmd", serial_cmd_thread_entry, RT_NULL, 1024, 20, 10);
if (tid != RT_NULL)
{
buzzer_beep(1, 500);
rt_thread_startup(tid);
rt_kprintf("Serial command thread started.\r\n");
}
else
{
rt_kprintf("Failed to create serial command thread.\r\n");
}

// 5. 創(chuàng)建距離監(jiān)測線程(優(yōu)先級較高,確保及時剎車)
rt_thread_t distance_tid = rt_thread_create("distance_monitor",
distance_monitor_thread_entry,
RT_NULL,
1024,
15, // 較高優(yōu)先級
10);
if (distance_tid != RT_NULL)
{
rt_thread_startup(distance_tid);
rt_kprintf("Distance monitoring thread started.\r\n");
}
else
{
rt_kprintf("Failed to create distance monitoring thread.\r\n");
}

// 6. 創(chuàng)建光線檢測線程
rt_thread_t light_tid = rt_thread_create("light_monitor",
light_monitor_thread_entry,
RT_NULL,
1024,
18, // 中等優(yōu)先級
10);
if (light_tid != RT_NULL)
{
rt_thread_startup(light_tid);
rt_kprintf("Light monitoring thread started.\r\n");
}
else
{
rt_kprintf("Failed to create light monitoring thread.\r\n");
}

rt_kprintf("=== System Initialization Complete ===\r\n");
rt_kprintf("Commands: start, stop, increase, decrease, one-two-three-four\r\n");
rt_kprintf(" turn on/off, auto light, light on/off, light status\r\n");
rt_kprintf(" brake on/off, test brake, init esc\r\n");

return 0;
}

// ====================== 導(dǎo)出組件初始化 ======================
INIT_APP_EXPORT(motor_control_app_init);

需要修改rt_config.h中adc0為1:#defineBSP_USING_ADC1

3094e192-f1a6-11f0-8ce9-92fbcf53809c.jpg

這是一個基于RT-Thread的智能電機控制系統(tǒng),通過串口指令控制無刷電機轉(zhuǎn)速,集成了VL53L0X激光測距主動剎車和光線檢測自動夜燈功能,具備多線程安全保護和智能決策能力。

30a128a8-f1a6-11f0-8ce9-92fbcf53809c.jpg

流程說明:

多線程并行:三個獨立線程分別處理用戶指令、障礙物監(jiān)測和光線檢測

安全保護:距離監(jiān)測線程具有較高優(yōu)先級,確保及時剎車

智能決策:基于連續(xù)檢測和閾值判斷,避免誤觸發(fā)

模式切換:支持手動/自動模式靈活切換

平滑控制:電機速度變化采用漸進式調(diào)節(jié),提升系統(tǒng)穩(wěn)定性


4.動手操作

a.首先進行光照檢測,如光線較弱則自動打開前燈; b.連接好藍牙,發(fā)送“start”字符串開始遙控,發(fā)送“one”,“two”,“three”,“four”即可實現(xiàn)穩(wěn)步增速,發(fā)送“increase”、“dicrease”即可實現(xiàn)精準(zhǔn)調(diào)速,發(fā)送“turn on”、“turn off”即可打開前燈led繼電器,發(fā)送“buzeer on”、“buzeer off”即可觸發(fā)有源蜂鳴器聲響,app不完全配置

30ab7556-f1a6-11f0-8ce9-92fbcf53809c.jpg

c.發(fā)送stop即可實現(xiàn)關(guān)閉所有增益,發(fā)送“reset”即可實現(xiàn)復(fù)位跳出循環(huán),再次發(fā)送發(fā)送“start”字符串又開始遙控。超聲波測距檢測前方物體距離小于100cm及時關(guān)閉所有增益,起到自動緊急剎車保護,程序中執(zhí)行動作時有蜂鳴器響應(yīng)反饋;還有心跳包程序,可判斷是否藍牙斷開(若斷開及時關(guān)閉所有增益,起到失控保護)


這是一個功能完善、安全機制到位的嵌入式智能控制系統(tǒng),移植了原先Arduino Uno項目,替換更好的TOF距離傳感器,體現(xiàn)了Vision Board多傳感器融合與實時控制的良好實踐。


開源地址

最后是該項目的開源地址:https://p.eda.cn/d-1302180533932916736有興趣的小伙伴可以去華秋開源硬件社區(qū)查看!有商業(yè)訴求的,請聯(lián)系項目的作者。


30b6316c-f1a6-11f0-8ce9-92fbcf53809c.png聲明:本文由華秋·開源硬件社區(qū)發(fā)布,轉(zhuǎn)載請注明以上來源。如需平臺合作及入群交流,請咨詢18925255684(微信同號:elecfans123),謝謝!


關(guān)注我們

源于工程師,服務(wù)工程師。華秋致力于提供電子產(chǎn)業(yè)鏈一站式服務(wù),讓硬件創(chuàng)新更簡單!請關(guān)注華秋電子旗下業(yè)務(wù):


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • DIY
    DIY
    +關(guān)注

    關(guān)注

    176

    文章

    898

    瀏覽量

    359137
  • 開源
    +關(guān)注

    關(guān)注

    3

    文章

    4199

    瀏覽量

    46102
  • 電動滑板
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    7151
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    基于 RT-Thread 的 Vision Board 智能電動滑板設(shè)計 | 技術(shù)集結(jié)

    目錄前言設(shè)計方案實驗步驟動手操作好物直達1前言在2018年我本科在萬宇杰老師的帶領(lǐng)下和小伙伴們一起立了校級重點科研立項——《DIY電動滑板》,非常懷戀那時候的干勁,閑暇時分傍晚和枚金江一起玩
    的頭像 發(fā)表于 02-26 20:15 ?5087次閱讀
    基于 RT-Thread 的 Vision Board 智能<b class='flag-5'>電動</b><b class='flag-5'>滑板</b>設(shè)計 | 技術(shù)集結(jié)

    基于Vision Board開發(fā)板的電動滑板設(shè)計方案

    核心,使用藍牙數(shù)據(jù)通訊協(xié)議進行無線數(shù)據(jù)透傳,采用PWM脈沖寬度調(diào)制方式,采用TOF激光距離傳感器進行緊急制動判斷。以下為各模塊設(shè)計簡介。
    的頭像 發(fā)表于 01-13 14:12 ?5164次閱讀
    基于Vision Board開發(fā)板的<b class='flag-5'>電動</b><b class='flag-5'>滑板</b>設(shè)計方案

    采用XIAO MG24開發(fā)板的手套動作控制電動滑板設(shè)計

    本篇應(yīng)用文章來自于Silicon Labs(芯科科技)在線技術(shù)社區(qū),作者分享了運用XIAO MG24開發(fā)板來打造通過手套動作控制電動滑板(Electric Skateboard)的簡要開發(fā)步驟和關(guān)鍵電路原理。
    的頭像 發(fā)表于 12-25 11:37 ?2456次閱讀
    采用XIAO MG24開發(fā)板的手套動作控制<b class='flag-5'>電動</b><b class='flag-5'>滑板</b>設(shè)計

    CW32F030C8T7永磁同步電機無FOC控制的方案

    基于ARM?Cortex?-M0+內(nèi)核的微控制器CW32F030C8T7,在永磁同步電機無FOC控制方案中展現(xiàn)了卓越的性能,為電機控制領(lǐng)域注入新的活力。 CW32F030C8T7永磁同步電機無
    發(fā)表于 12-03 06:34

    用CW32L010的ADC采樣值波動導(dǎo)致電機調(diào)速平滑怎么解決?

    用CW32L010的ADC采樣值波動導(dǎo)致電機調(diào)速平滑
    發(fā)表于 11-18 06:30

    電動滑板車核心技術(shù)方案解析

    隨著城市交通日益擁堵、人們環(huán)保意識增強,電動滑板(Electric Skateboard)作為新一代便攜智能出行工具,正迅速走入大眾視野。 ? ? 電動滑板是在傳統(tǒng)
    的頭像 發(fā)表于 08-22 10:16 ?803次閱讀
    <b class='flag-5'>電動</b><b class='flag-5'>滑板</b>車核心技術(shù)方案解析

    霍爾IC在電動調(diào)速轉(zhuǎn)把中的應(yīng)用與原理

    霍爾IC(霍爾效應(yīng)集成電路)在電動調(diào)速轉(zhuǎn)把中的應(yīng)用與原理可概括如下: 一、核心應(yīng)用 ?調(diào)速控制? 調(diào)速轉(zhuǎn)把通過內(nèi)置線性霍爾IC,將騎行者的旋轉(zhuǎn)角度轉(zhuǎn)化為連續(xù)電壓信號。轉(zhuǎn)把轉(zhuǎn)動時,磁鐵
    發(fā)表于 08-07 10:46

    電動滑板車核心技術(shù)方案解析及高性價比芯片選型推薦SI24R1+AT2401C

    CB2401或AT2401C的電動滑板無線控制方案,以其低功耗、高性能和成本效益的特性,為電動滑板的智能化、遠距離控制提供了理想選擇。 無
    發(fā)表于 07-29 17:04

    霍爾IC在電動調(diào)速轉(zhuǎn)把中的應(yīng)用與原理

    本帖最后由 h1654155984.7392 于 2025-7-29 11:00 編輯 霍爾IC(霍爾效應(yīng)集成電路)在電動調(diào)速轉(zhuǎn)把中的應(yīng)用與原理可概括如下:一、核心應(yīng)用?調(diào)速控制?調(diào)速
    發(fā)表于 07-29 10:57

    BUCK變換器在高速凸極電動調(diào)速系統(tǒng)的研究

    摘 要:首先分析了傳統(tǒng)PWM調(diào)制方式下,高速凸極電動機在換相區(qū)和非換相區(qū)的工作模態(tài),指出了傳統(tǒng)PWM調(diào)制方法會出現(xiàn)電流上升過快,存在較大的電流紋波和轉(zhuǎn)矩脈動,從而影響電機的運行特性。為此提出了在三
    發(fā)表于 07-22 17:15

    電動滑板車散熱系統(tǒng)設(shè)計

    為基材,添加氧化鋁、氮化硼等高導(dǎo)熱填料,通過特殊工藝合成的界面導(dǎo)熱材料。它填補了傳統(tǒng)散熱材料的性能短板,在電動滑板車散熱設(shè)計中展現(xiàn)出多重優(yōu)勢: 微觀填充能力:材料具備優(yōu)異的柔軟性與彈性(硬度通常為
    發(fā)表于 07-01 13:55

    變頻器如何選擇變頻調(diào)速系統(tǒng)的電動機?

    在選擇與變頻器配合使用的變頻調(diào)速系統(tǒng)電動機時,需要考慮以下關(guān)鍵因素: 一、了解電動機類型 交流電動機主要分為異步電動機和同步
    的頭像 發(fā)表于 04-28 17:22 ?1252次閱讀
    變頻器如何選擇變頻<b class='flag-5'>調(diào)速</b>系統(tǒng)的<b class='flag-5'>電動</b>機?

    電動滑板車的VMP認(rèn)證流程

    西班牙DGT(Directorate-GeneralforTraffic,交通總局)提供針對電動滑板車的認(rèn)證服務(wù),在西班牙,電動滑板車(即“VehículosdeMovilidadPe
    的頭像 發(fā)表于 04-18 23:53 ?1032次閱讀
    <b class='flag-5'>電動</b><b class='flag-5'>滑板</b>車的VMP認(rèn)證流程

    MATLAB仿真在直流電機閉環(huán)調(diào)速系統(tǒng)中的應(yīng)用

    。直流電動機是將直流電能轉(zhuǎn)化為機械能的設(shè)備,其 調(diào)速范圍大 , 平滑性較高 , 并且能夠?qū)崿F(xiàn)快速啟動 , 制動 和逆向運轉(zhuǎn),廣泛應(yīng)用于高性能的可控電力拖動領(lǐng)域 中。而在電力拖動系統(tǒng)中,
    發(fā)表于 03-20 13:03

    直流電機閉環(huán)數(shù)字調(diào)速系統(tǒng)設(shè)計與實現(xiàn)

    電樞電流構(gòu)成電流環(huán)。軟件編程實現(xiàn)改進的轉(zhuǎn)速、電流閉環(huán)PI控 制器,利用單片機的定時器生成占空比可調(diào)的PWM信號,光耦隔離后經(jīng)功率驅(qū)動放大,通過 控制H橋驅(qū)動電路對直流電機進行無級平滑調(diào)速。實驗表明該系統(tǒng)控制精度高,可靠性和穩(wěn)定
    發(fā)表于 03-20 12:55