• 方案介紹
  • 附件下載
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

【RT-Thread 作品秀】瞎轉(zhuǎn)悠

2020/12/19
729
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

原理圖設(shè)計.zip

共4個文件

【ART-Pi作品秀】瞎轉(zhuǎn)悠

 

作者: 樊曉杰


概述

簡單介紹項目應(yīng)用產(chǎn)生的背景 ,所產(chǎn)生的軟硬件方案 及主要實現(xiàn)的功能。

應(yīng)用產(chǎn)生背景

在和娃玩老鷹轉(zhuǎn)小雞時候,突然就想做個小車,可以和孩子互動,就想到人擋在小車前面,然后轉(zhuǎn)向,就一直這么循環(huán)下去,一個很簡單的功能。就是漫無目的 瞎轉(zhuǎn)悠,這就是名字的由來。也是一個提醒,尤其到冬天了還是在疫情期間,沒事別瞎轉(zhuǎn)悠,老實在家呆著沒事 就玩玩rt-thread,多參加參加電路城的活動。

 

所采用的硬件方案

硬件方案采用 : 主控板 ART-Pi + SR04 超聲波 測距儀 + 小車套件。

1.ART-Pi 簡介

ART-Pi是 RT-Thread 團隊經(jīng)過半年的精心準(zhǔn)備,專門為嵌入式軟件工程師開源創(chuàng)客設(shè)計的一款極具擴展功能的 DIY 開源硬件。

板載資源:

  • - STM32H750XBH6 - On-board ST-LINK/V2.1 - USB OTG with Type-C connector

  • - SDIO TF Card slot - SDIO WIFI:AP6212 - HDC UART BuleTooth:AP6212

  • - RGB888 FPC connector - 32-Mbytes SDRAM - 16-Mbytes SPI FLASH

  • - 8-Mbytes QSPI FLASH - D1(blue) for 3.3 v power-on - Two user LEDs:D2 (blue),D2 (red)

  • - Two ST-LINK LEDs: D4(blue),D4 (red) - Two push-buttons (user and reset)

 

擴展接口:

  • - 4路UART(LPUART) - 3路SPI - 2路hardware iic

  • - 1路USB-FS - 1路ETH - 1路SAI

  • - 1路DCMI - 2路CANFD - 超過5路ADC (支持查分輸入ADC)

  • - 超過15路PWM(支持高精度定時器HRTIM)

 

驅(qū)動支持:

  • - UART - SPI - SDMMC - CAN - QSPI

  • - ADC - PWM - DCMI - SAI - LTDC

  • - USB - ETH - SDRAM - HRTIM - I2C

2.SR04 超聲波測距傳感器

超聲波測距 我們這里采用很常見的一個模塊 SR04 。HC-SR04超聲波模塊常用于機器人避障、物體測距、液位檢測、公共安防、停車場檢測等場所。HC-SR04超聲波模塊主要是由兩個通用的壓電陶瓷超聲傳感器,并加外圍信號處理電路構(gòu)成的。

 

3. 小車套件

小車基礎(chǔ)平臺采購慧凈電子四驅(qū)智能小車底盤 及驅(qū)動板。

 

 

 

4.電機驅(qū)動模塊:

 

每一路需要3個信號控制,一路pwm ,一路正傳一路反轉(zhuǎn)。

所采用軟件方案

 

軟件方案 基于 RT-Thread IoT RTOS 此方案中使用SR04 超聲波測距軟件包,RT-Robot 軟件包。

開發(fā)環(huán)境:

使用的是rt-thread 4.0.3 版本軟件,使用mdk 結(jié)合env 工具 開發(fā)。

分別簡介如下:

RT-Thread 的架構(gòu)簡介:

近年來,物聯(lián)網(wǎng)(Internet Of Things,IoT)概念廣為普及,物聯(lián)網(wǎng)市場發(fā)展迅猛,嵌入式設(shè)備的聯(lián)網(wǎng)已是大勢所趨。終端聯(lián)網(wǎng)使得軟件復(fù)雜性大幅增加,傳統(tǒng)的 RTOS 內(nèi)核已經(jīng)越來越難滿足市場的需求,在這種情況下,物聯(lián)網(wǎng)操作系統(tǒng)(IoT OS)的概念應(yīng)運而生。物聯(lián)網(wǎng)操作系統(tǒng)是指以操作系統(tǒng)內(nèi)核(可以是 RTOS、Linux 等)為基礎(chǔ),包括如文件系統(tǒng)、圖形庫等較為完整的中間件組件,具備低功耗、安全、通信協(xié)議支持和云端連接能力的軟件平臺,RT-Thread 就是一個 IoT OS。

 

RT-Robot 是 RT-Thread 的機器人框架,希望能夠支持智能小車、機械臂、無人機等各種不同類型的機器人。

當(dāng)前以智能車為主要目標(biāo),希望支持兩輪差分驅(qū)動、四輪差分驅(qū)動、麥克納姆輪驅(qū)動、經(jīng)典 Ackerman (兩輪差分,一方向連桿) 的小車底盤。

當(dāng)前功能特點:

  • 支持兩輪差分驅(qū)動、四輪差分驅(qū)動、麥克納姆輪驅(qū)動的小車底盤

  • 支持增量、位置式 PID

  • 支持單相、AB 相編碼器

  • 支持雙 PWM、單 PWM 的直流電機驅(qū)動,支持驅(qū)動舵機

  • 支持 PS2 遙控器

  • 支持 ANO_TC 匿名科創(chuàng)地面站

 

SR04 軟件包工作流程 ultrasonic sensor v2.0 a.單片機引腳觸發(fā)Trig測距,給至少 10us 的高電平信號; b.模塊自動發(fā)送 8 個 40khz 的方波,自動檢測是否有信號返回; c.有信號返回,通過 IO 輸出一高電平,并單片機定時器計算高電平持續(xù)的時間; d.超聲波從發(fā)射到返回的時間. 計算公式:測試距離=(高電平時間*聲速(340M/S))/2;

目前 程序使用如下線程:

線程 功能 優(yōu)先級
按鍵處理線程 處理按鍵響應(yīng) 20
小車控制線程 控制小車四輪驅(qū)動 23
測距線程 處理距離數(shù)據(jù)處理 16
led 線程 程序正常運行指示 10
FinSH線程 命令行組件,方便調(diào)試 20

 

實現(xiàn)功能

  1. 按鍵按下,小車功能啟動;

  2. 小車一直測量前方距離,當(dāng)距離小于30cm 時,左拐,然后前進

  3. 然后一直循環(huán)上述判斷過程

  4. 按鍵再次按下,小車停止。

     

RT-Thread 使用情況概述

應(yīng)用中RT-Thread 使用情況:

內(nèi)核部分:

1.使用到四個線程:按鍵處理線程,超聲波測距線程,小車控制線程,led 狀態(tài)顯示線程。

2.線程間通信使用:郵箱在超聲波測距線程中將距離數(shù)據(jù)發(fā)送給小車控制線程,

3.線程間同步使用:信號量作為按鍵 處理線程 和 電機控制線程之間 啟動停止的信號 同步。

設(shè)備驅(qū)動部分:

1.PWM 設(shè)備及驅(qū)動-------電機驅(qū)動部分用到

2.定時器設(shè)備及驅(qū)動-------超聲波測距 部分用到

 

組件部分:

1.FinSH控制臺 ----------------調(diào)試用到

軟件包部分:

  1. SR04 超聲波測距 軟件包 ,一貫的好用,方便集成;地址如下:

    SR04軟件包地址

  2. robot RT-Thread 的機器人框架軟件包 ,數(shù)據(jù)結(jié)構(gòu)優(yōu)美的一個軟件包 .地址如下:

    robot 軟件包地址

     

硬件框架說明

主控芯片 STM32H750XBH6 Cortex-M系列高性能處理器,M7內(nèi)核,主頻400MHz
超聲波測距模塊 SR04 可提供 2cm - 400cm 的非接觸式距離感測功能
電機驅(qū)動板 L298P直流電機驅(qū)動模塊 4路直流電機驅(qū)動模塊
小車車架 4輪驅(qū)動 智能小車底盤套件
供電模塊 2節(jié) 18650 3.7V 大容量鋰電池

硬件方案 直接使用 ART-Pi開發(fā)板,使用的外設(shè)說明如下:

  1. 按鍵用來啟動小車,停止小車;

  2. 測距模塊使用定期器來換算 距離;

  3. 直流電機驅(qū)動模塊使用PWM 驅(qū)動;

  4. led 顯示系統(tǒng)正常運行;

     

    接線說明:這個系統(tǒng)使用到的引腳如下

    超聲波
    ?
    TRIG   PB1
    ?
    ECHO  PB2
    ?
    定時器13.
    ?
    PWM:  有網(wǎng)友說用到  time2  --- 2,3  tim5 兩個引腳 。
    ?
    PH10  CH1   TIME5      正轉(zhuǎn) PB12  反轉(zhuǎn)  PG10 
    ?
    PH11 CH2  TIME5        正轉(zhuǎn) PA15  反轉(zhuǎn) PH15
    ?
    PH12   CH3  TIME5       正傳PH13  反轉(zhuǎn)  反轉(zhuǎn) PI3
    ?
    PI0       CH4  TIME5       正轉(zhuǎn) PH7  反轉(zhuǎn) PH9 
    ?
    led:
    ?
    RED:   PC15
    ?
    BLUE: PI8 
    ?
    按鍵:
    ?
    PH4  低電平有效。

     

     

軟件框架說明

【主要介紹應(yīng)用所采用的軟件方案框圖、流程圖等】

最終的使用的線程情況如下:

msh />ps
thread   pri  status      sp     stack size max used left tick  error
-------- ---  ------- ---------- ----------  ------  ---------- ---
sr04      16  suspend 0x00000118 0x00000400    27%   0x00000002 000
tshell    20  running 0x00000108 0x00001000    12%   0x00000004 000
keythrea  20  suspend 0x00000080 0x00000200    25%   0x00000005 000
motor_ru  23  suspend 0x00000150 0x00000400    32%   0x00000004 000
tidle0    31  ready   0x00000044 0x00000100    32%   0x0000000a 000
timer      4  suspend 0x00000060 0x00000200    18%   0x00000009 000
main      10  suspend 0x0000008c 0x00000800    16%   0x00000004 000
?
?

 

軟件流程:

  1. 上電開機 led 顯示系統(tǒng)正常運行;

  2. 電機控制線程 接收按鍵信號 啟動信號量 ,啟動電機 直行,;

  3. sr04 超聲波測距模塊線程 接收到啟動信號后 ,開始測距,并將測量數(shù)據(jù)發(fā)給 通過郵箱 發(fā)給 電機控制線程;

  4. 電機控制線程通過郵箱 接收到距離數(shù)據(jù)判斷有障礙物,就左轉(zhuǎn),直行;

  5. 電機控制線程接收到按鍵 停止信號 停止信號量 ,然后停車。

     

軟件模塊說明

(介紹應(yīng)用軟件關(guān)鍵部分的邏輯、采用的實現(xiàn)方式等)

1.電機控制模塊處理

電機控制模塊,主要控制電機的直行 轉(zhuǎn)向 ,停止 及對接收到的距離數(shù)據(jù)的處理,關(guān)鍵代碼具體如下:

static void motor_entry(void *parameter)
{
    rt_uint32_t count = 0;
    motor_t letf_moto = RT_NULL;
    motor_t right_moto = RT_NULL;
    //chassis_t chas;
    struct velocity target_vel;
    // 1. Initialize two wheels - left and right
wheel_t* c_wheels = (wheel_t*) rt_malloc(sizeof(wheel_t) * 4);
if (c_wheels == RT_NULL)
{
    LOG_D("Failed to malloc memory for wheels");
}
?
// 1.1 Create two motors
//motor_t left_motor  = motor_create(left_motor_init,  left_motor_enable,  left_motor_disable,  left_motor_set_speed,  DC_MOTOR);
//motor_t right_motor = motor_create(right_motor_init, right_motor_enable, right_motor_disable, right_motor_set_speed, DC_MOTOR);
single_pwm_motor_t left_forward_motor = single_pwm_motor_create(LEFT_FORWARD_PWM,LEFT_FORWARD_PWM_CHANNEL, LEFT_FORWARD_STRAIGHT_PIN, LEFT_FORWARD_BACK_PIN);
single_pwm_motor_t left_backward_motor = single_pwm_motor_create(LEFT_BACKWARD_PWM,LEFT_BACKWARD_PWM_CHANNEL, LEFT_BACKWARD_STRAIGHT_PIN, LEFT_BACKWARD_BACK_PIN);
single_pwm_motor_t right_forward_motor = single_pwm_motor_create(RIGHT_FORWARD_PWM,RIGHT_FORWARD_PWM_CHANNEL, RIGHT_FORWARD_STRAIGHT_PIN, RIGHT_FORWARD_BACK_PIN);
single_pwm_motor_t right_backward_motor = single_pwm_motor_create(RIGHT_BACKWARD_PWM,RIGHT_BACKWARD_PWM_CHANNEL, RIGHT_BACKWARD_STRAIGHT_PIN, RIGHT_BACKWARD_BACK_PIN);
?
?
// 1.2 Create two encoders
//encoder_t left_encoder  = encoder_create(LEFT_ENCODER_PIN, PULSE_PER_REVOL);
//encoder_t right_encoder = encoder_create(RIGHT_ENCODER_PIN, PULSE_PER_REVOL);
single_phase_encoder_t left_forward_encoder = single_phase_encoder_create(LEFT_ENCODER_PIN,PULSE_PER_REVOL,SAMPLE_TIME );
single_phase_encoder_t right_forward_encoder = single_phase_encoder_create(RIGHT_ENCODER_PIN,PULSE_PER_REVOL,SAMPLE_TIME);
?
// 1.3 Create two pid contollers
//pid_control_t left_pid  = pid_create();
//pid_control_t right_pid = pid_create();
inc_pid_controller_t left_pid = inc_pid_controller_create(kp,ki,kd,SAMPLE_TIME);
inc_pid_controller_t right_pid = inc_pid_controller_create(kp, ki,kd,SAMPLE_TIME);
// 1.4 Add two wheels
//wheel_t wheel_create(motor_t w_motor, encoder_t w_encoder, controller_t w_controller, float radius, rt_uint16_t gear_ratio)
?
c_wheels[0] = wheel_create((motor_t)left_forward_motor,  (encoder_t)left_forward_encoder,(controller_t)left_pid,   WHEEL_RADIUS, GEAR_RATIO);//left_pid
c_wheels[2] = wheel_create((motor_t)left_backward_motor, (encoder_t)left_forward_encoder,(controller_t)left_pid,  WHEEL_RADIUS, GEAR_RATIO);//left_pid
c_wheels[1] = wheel_create((motor_t)right_forward_motor, (encoder_t)right_forward_encoder,(controller_t)right_pid, WHEEL_RADIUS, GEAR_RATIO);//left_pid
c_wheels[3] = wheel_create((motor_t)right_backward_motor, (encoder_t)right_forward_encoder,(controller_t)right_pid,  WHEEL_RADIUS, GEAR_RATIO);//left_pid
?
?
// 2. Iinialize Kinematics - Two Wheel Differential Drive
kinematics_t c_kinematics = kinematics_create(FOUR_WD, WHEEL_DIST_X, WHEEL_DIST_Y, WHEEL_RADIUS);
?
// 3. Initialize Chassis
chas = chassis_create(c_wheels, c_kinematics);
?
// 4. Enable Chassis
//chassis_enable(chas);
?
// Set Sample time
encoder_set_sample_time(chas->c_wheels[0]->w_encoder, SAMPLE_TIME);
encoder_set_sample_time(chas->c_wheels[1]->w_encoder, SAMPLE_TIME);
encoder_set_sample_time(chas->c_wheels[2]->w_encoder, SAMPLE_TIME);
encoder_set_sample_time(chas->c_wheels[3]->w_encoder, SAMPLE_TIME);
//pid_set_sample_time(chas->c_wheels[0]->w_pid, PID_SAMPLE_TIME);
//pid_set_sample_time(chas->c_wheels[1]->w_pid, PID_SAMPLE_TIME);
?
// 4. Enable Chassis
chassis_enable(chas);
// Turn left
        **struct rt_sensor_data *sensor_data;//關(guān)鍵地方**
        while(1)
        {
     //chassis_update(chas);
              /* 永久方式等待信號量,獲取到信號量,則執(zhí)行number自加的操作 */
        result = rt_sem_take(start_sem, RT_WAITING_FOREVER);
        if (result != RT_EOK)
        {
            rt_kprintf("thread2 take a start semaphore, failed.n");
            rt_sem_delete(start_sem);
            return;
        }
        else
        {
            number++;
            rt_kprintf("thread2 take a start semaphore. number = %dn", number);
                     while(1)
                     {                      
                                run();//直行 
                                /* 從郵箱中收取郵件 */
                                if (rt_mb_recv(&mb, (rt_uint32_t *)&sensor_data, RT_WAITING_FOREVER) == RT_EOK)
                                {
                                    //  rt_kprintf("thread1: get a mail from mailbox, the content:%sn", );
                                    
                                    if (sensor_data.data.proximity/10 < 30)
                                    {
                                    rt_kprintf("distance:%3d.%dcm, timestamp:%5d turn left n", sensor_data.data.proximity / 10, sensor_data.data.proximity % 10, sensor_data.timestamp);
                                        left();
                                    }
                                            /* 延時100ms */
                                        rt_thread_mdelay(100);
                                }
                                  result = rt_sem_take(stop_sem, RT_WAITING_NO);
                                    if (result == RT_EOK)
                                    {
                                            //rt_kprintf("thread2 take a start semaphore, failed.n");
                                            //rt_sem_delete(stop_sem);
                                            stop();
                                            break;
                                    }
                                                    
                        
                     }
        }
                    rt_thread_mdelay(1500);
?
        }
?
}

調(diào)試說明:

①主要看pwm 是否可以正常輸出波形。

可以通過命令:來測試。遇到過 有下面波形,但和電機程序結(jié)合起來的話,沒有輸出波形。

msh />pwm_set pwm5 2 1000 500
msh />pwm_e
pwm_enable
msh />pwm_enable pwm5 2
msh />pwm_disable pwm5 2

② 有個電機控制引腳,PA15,初始就是高電平,導(dǎo)致一上電就轉(zhuǎn),換一個其他引腳。

③先把幾個引腳都先調(diào)通,對應(yīng)起來,可以通過直接將引腳接高電平的方式,來測試,因為線不一定接的對??梢韵雀鶕?jù)引腳的分布,初步先列出來控制引腳序號。然后再通過調(diào)試,進行調(diào)整。

④ 通過第一步調(diào)試,證明pwm 驅(qū)動沒有問題,但任然出現(xiàn)過 robot 程序 沒有輸出pwm 波形,原因分析如下:

通過單步調(diào)試,發(fā)現(xiàn)最終只是設(shè)置了速度,并沒有最后的運行。也就是這句 chassis_update(chas);

⑤ 有波形 但占空比很低的話,電機也跑不起來,可以在

  rt_pwm_set(mot_sub->pwm_dev, mot_sub->channel, MOTOR_PWM_PERIOD, pluse + 28000 );//50 000 在一半的  基礎(chǔ)上增加。 

⑥ 調(diào)試其他幾個方向,比如不動的話,可以實時調(diào)整參數(shù)。比如下面幾個:

void stop(void)
{
    struct velocity target_vel;
    target_vel.linear_x = 0.0;   // m/s
  target_vel.linear_y = 0;    // m/s
  target_vel.angular_z = 0; // rad/s

  chassis_set_velocity(chas, target_vel);
    chassis_update(chas);
   rt_thread_mdelay(500);
}

MSH_CMD_EXPORT(stop, moto stop);
void left(void)
{
        struct velocity target_vel;
            // Turn left
        target_vel.linear_x = 0.8;//0.06;   // m/s
        target_vel.linear_y = 0;    // m/s
        target_vel.angular_z = PI / 4; // rad/s

        chassis_set_velocity(chas, target_vel);
     chassis_update(chas);
        rt_thread_mdelay(800);
                stop();
}
MSH_CMD_EXPORT(left, moto left);
void right(void)
{
        struct velocity target_vel;
        // Turn right
        target_vel.linear_x = 0.8;//0.06;   // m/s
        target_vel.linear_y = 0;    // m/s
        target_vel.angular_z = - PI / 4; // rad/s

        chassis_set_velocity(chas, target_vel);
     chassis_update(chas);
        rt_thread_mdelay(400);
            stop();
}
MSH_CMD_EXPORT(right, moto right);

void run(void)
{
    
rt_kprintf("runrn");
struct velocity target_vel;
// Go straight
target_vel.linear_x = 1.0;//0.08;   // m/s
target_vel.linear_y = 0;    // m/s
target_vel.angular_z = 0;

 chassis_set_velocity(chas, target_vel);
 chassis_update(chas);
 rt_thread_mdelay(500);
 
}
MSH_CMD_EXPORT(run, moto straight);
void back(void)
{
struct velocity target_vel;
// Go straight
target_vel.linear_x = -1.0;//-0.08;   // m/s
target_vel.linear_y = 0;    // m/s
target_vel.angular_z = 0;

 chassis_set_velocity(chas, target_vel);
    chassis_update(chas);
  rt_thread_mdelay(500);
}
MSH_CMD_EXPORT(back, moto back);

2.按鍵處理模塊

按鍵處理模塊,主要 是 發(fā)送開始 和停止信號。

關(guān)鍵代碼:

#define USER_KEY_1    GET_PIN(H,4)
static rt_uint8_t flag_start = 0;
/* 指向信號量的指針 */
rt_sem_t start_sem = RT_NULL;
rt_sem_t stop_sem = RT_NULL;
?
void process_key(void *args)
{
        rt_thread_mdelay(50);
        if (rt_pin_read(USER_KEY_1) == 0)
      { 
                if (flag_start == 0)
                {
                    flag_start = 1;
                    rt_sem_release(start_sem);
                }
                else
                {
                    flag_start = 0;
                    rt_sem_release(stop_sem);
                }
        }
}
static void key_entry(void *parameter)
{
        rt_pin_mode(USER_KEY_1, PIN_MODE_INPUT_PULLUP);
        rt_pin_attach_irq(USER_KEY_1, PIN_IRQ_MODE_FALLING, process_key, RT_NULL);
        
        while(1)
        {
            rt_thread_mdelay(1000);
        }
      
    
}

3. SR04 超聲波測距模塊

超聲波測距模塊,完成距離測量,并將數(shù)據(jù)通過郵箱發(fā)給電機控制模塊。關(guān)鍵代碼分析:

為什么這里選擇郵箱作為兩個線程間通信的方式?

(1)郵箱的開銷比較低,效率高;

(2)非阻塞方式的郵件發(fā)送過程能夠安全地應(yīng)用于中斷服務(wù)中,是線程,中斷服務(wù),定期器想線程發(fā)送消息的有效手段。

如何用郵箱來發(fā)送一個傳感器接收的數(shù)據(jù)?

(1)

為什么這里選擇郵箱作為兩個線程間通信的方式?

(1)郵箱的開銷比較低,效率高;

(2)非阻塞方式的郵件發(fā)送過程能夠安全地應(yīng)用于中斷服務(wù)中,是線程,中斷服務(wù),定期器想線程發(fā)送消息的有效手段。

如何用郵箱來發(fā)送一個傳感器接收的數(shù)據(jù)?

(1) 就是如何發(fā)送這個數(shù)據(jù)結(jié)構(gòu)的地址,然后接收線程可以解析這個數(shù)據(jù)接收,也就是通過郵箱發(fā)送指定數(shù)據(jù)結(jié)構(gòu)的數(shù)據(jù)。直接取這個數(shù)據(jù)結(jié)構(gòu)的地址,接收線程,定義一個 對應(yīng)數(shù)據(jù)結(jié)構(gòu)的指針,然后取 & 這個地址,取出數(shù)據(jù),就可以。這是取到正確數(shù)據(jù)最關(guān)鍵的地方。

struct rt_sensor_data
{
    rt_uint32_t         timestamp;          /* The timestamp when the data was received */
    rt_uint8_t          type;               /* The sensor type of the data */
    union
    {
        struct sensor_3_axis acce;          /* Accelerometer.       unit: mG          */
        struct sensor_3_axis gyro;          /* Gyroscope.           unit: mdps        */
        struct sensor_3_axis mag;           /* Magnetometer.        unit: mGauss      */
        rt_int32_t           temp;          /* Temperature.         unit: dCelsius    */
        rt_int32_t           humi;          /* Relative humidity.   unit: permillage  */
        rt_int32_t           baro;          /* Pressure.            unit: pascal (Pa) */
        rt_int32_t           light;         /* Light.               unit: lux         */
        rt_int32_t           proximity;     /* Distance.            unit: centimeters */
        rt_int32_t           hr;            /* Heart rate.          unit: bpm         */
        rt_int32_t           tvoc;          /* TVOC.                unit: permillage  */
        rt_int32_t           noise;         /* Noise Loudness.      unit: HZ          */
        rt_uint32_t          step;          /* Step sensor.         unit: 1           */
        rt_int32_t           force;         /* Force sensor.        unit: mN          */
        rt_uint32_t          dust;          /* Dust sensor.         unit: ug/m3       */
        rt_uint32_t          eco2;          /* eCO2 sensor.         unit: ppm         */
    } data;
};

 

 struct rt_sensor_data sensor_data;
 static void sr04_read_distance_entry(void *parameter)
{
    rt_device_t dev = RT_NULL;
    
    rt_size_t res;
?
    dev = rt_device_find(parameter);
    if (dev == RT_NULL) {
        rt_kprintf("Can't find device:%sn", parameter);
        return;
    }
?
    if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) {
        rt_kprintf("open device failed!n");
        return;
    }
    rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100);
?
    while (1) {
        res = rt_device_read(dev, 0, &sensor_data, 1);
        if (res != 1) {
            rt_kprintf("read data failed!size is %dn", res);
            rt_device_close(dev);
            return;
        }
        else {
            rt_mb_send(&mb, (rt_uint32_t)&sensor_data);//發(fā)送 數(shù)據(jù)
            rt_kprintf("distance:%3d.%dcm, timestamp:%5dn", sensor_data.data.proximity / 10, sensor_data.data.proximity % 10, sensor_data.timestamp);
        }
        rt_thread_mdelay(2000);
    }
}

 

4. LED顯示模塊

主要就是系統(tǒng)正常運行指示。

關(guān)鍵代碼如下:

#define LED_PIN GET_PIN(I, 8)
int main(void)
{
    rt_uint32_t count = 1;
?
    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
    
      
    while(count++)
    {
        rt_thread_mdelay(500);
        rt_pin_write(LED_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED_PIN, PIN_LOW);
    }
    return RT_EOK;
}
?

 

演示效果

視頻播放地址:目前只有超聲波測距部分視頻,后續(xù)會在這個地址添加完整版。

(1)小車

  (2) 超聲波測距

瞎轉(zhuǎn)悠 

電機控制演示

完整視頻

第一次下地視頻

比賽感悟

雖然實現(xiàn)的功能很簡單,但是完全利用時間搞要搞成功,還是挺不容易的,還是整體的時間安排不好。主要收獲是對rt-thread 的線程間的同步和通信增強了認(rèn)識和體驗,實踐出真知,多多參與這樣的活動。給主辦方點個贊。

主要克服的難點:

(1)是之前pwm 驅(qū)動一直卡著,沒有進展,最后在網(wǎng)友的支援下順利解決,主要是初始化時候,沒有使能相應(yīng)的時鐘,陷在完全按照之前添加bsp 的方式搞,沒明白這其中的細(xì)節(jié),感謝網(wǎng)友支持;

(2)還有就是郵箱發(fā)送 結(jié)構(gòu)體數(shù)據(jù)的正確的接收和發(fā)送處理。

主要收獲:

(1)第一次使用H7 高性能MCU, 很多處理方式跟之前不一樣,比如燒錄方式,也折騰了好幾天,這個過程中,收獲不少

(2) 這個art pi 開發(fā)板 很不錯的學(xué)習(xí)平臺,也開源了挺多好的擴展板項目,后續(xù)希望可以搞一個專門的小車方面的擴展板,應(yīng)該挺不錯的,很好玩。

  • 原理圖設(shè)計.zip
    下載
    描述:BOM, 接線說明,模塊介紹
  • art_pi_Sisyphus.zip
    下載
    描述:源代碼
  • 基于RT-Thread 使用Art-Pi 之瞎轉(zhuǎn)悠.pdf
    下載
    描述:主要文檔
  • [RT-Thread作品秀]瞎轉(zhuǎn)悠.pdf
    下載

相關(guān)推薦