国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

分享21年電賽F題-智能送藥小車-做題記錄以及經(jīng)驗分享

這篇具有很好參考價值的文章主要介紹了分享21年電賽F題-智能送藥小車-做題記錄以及經(jīng)驗分享。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

前言

自己是今年準備電賽的同學一名,電賽結(jié)束了,想把自己之前刷過的題目,通過這篇文章,來分享一波做這道題的思路和調(diào)試方法

自己在做之前的電賽題目時,也苦苦沒有思路,不知道該怎么去下手,面對題目的要求和限制,應該如何去分析和實現(xiàn)

由于我們主要是準備小車相關(guān)的,大部分時間都用來刷電賽期間出現(xiàn)的小車題目了

其中包括21年F題——智能送藥小車、22年C題——小車跟隨系統(tǒng)、22年B題——自動泊車系統(tǒng)

可是今年電賽題目并沒有小車,小車和無人機一起

可以看出電賽題目更貼近于綜合,對個人能力的要求更高了

好了,廢話不多說,我會在這段時間,將學習到的知識和做電賽題目的代碼一步一步寫出文章分享和教學,希望以后的同學可以參考學習,而不是盲目無從下手
分享21年電賽F題-智能送藥小車-做題記錄以及經(jīng)驗分享,電賽真題,STM32,經(jīng)驗分享,stm32,電賽

一、賽題分析

賽題地圖如下
分享21年電賽F題-智能送藥小車-做題記錄以及經(jīng)驗分享,電賽真題,STM32,經(jīng)驗分享,stm32,電賽

1、車型選擇

在做這道題目的時候,采用過好幾種車型,并且采用過不同的方案,其中一種是

  • 四輪小車,前輪為舵機轉(zhuǎn)向,后兩輪為驅(qū)動輪
  • 三輪小車,前輪為萬向輪或牛眼輪,后兩輪為驅(qū)動輪

在實踐的過程中,因為題目要求是轉(zhuǎn)向90°,這種情況下三輪小車前輪為從動輪的更占優(yōu)勢,轉(zhuǎn)向更為方便,而舵機前輪后輪驅(qū)動的車型轉(zhuǎn)向就無法像三輪一般絲滑,略顯笨重,但是也可以實現(xiàn)

2、巡線

巡線有兩種方案

  • OpenMv巡線
  • 灰度循跡

這兩種循跡方案都是差不多的,都是檢測當前小車行進的位置的偏差的誤差值來改變小車的行進方向

就是接收誤差,將誤差帶入PID進行計算,得出巡線補償,使小車始終保持在期望中心

1、OpenMv循跡

這部分我就不多寫了,OpenMv有很多種方法,來巡線,這部分是隊友負責,我大概也知道一些,比如二值化、色塊追蹤、模擬灰度傳感器等

32這邊始終接收到的數(shù)據(jù)就是一個偏差Err,根據(jù)這個Err來計算PID,調(diào)節(jié)PID參數(shù),到達期巡線望值

最后這個計算出來的值一般也是串起來的,循線環(huán)輸出帶入速度環(huán)的輸入,兩輪不同的方向,一邊+,一邊-,調(diào)節(jié)PID參數(shù)即可絲滑循跡


float location_pid_realize(_pid *pid, float actual_val)
{
    /*    計算偏差    這里的偏差是指 巡線偏差 設(shè)定的巡線期望值 和 MV傳回的巡線實際值 得偏差 */
    pid->err = pid->target_val - actual_val;

    pid->integral += pid->err; // 誤差累積

    // if (pid->err >= 1000) // 積分限幅
    // {
    //     pid->err = 0;
    // }

    // if (huidu.output >= 550)
    //     huidu.output = 550;
    // if (huidu.output <= -600)
    //     huidu.output = -600;

    /*PID算法實現(xiàn)*/
    pid->actual_val = pid->Kp * pid->err + pid->Ki * pid->integral + pid->Kd * (pid->err - pid->err_last);

    /*誤差傳遞*/
    pid->err_last = pid->err;

    /*返回當前實際值*/
    return pid->actual_val;
}


/**
 * @brief  巡線pid輸出函數(shù)      后輪差速
 * @param  actual_val:實際值
 *	@note 	無
 * @retval 通過PID計算后的輸出
 */
float OpenMV_location_pid_control(void)
{

    float Expect_Pwm = 0.0; // 當前控制值

    Pid_location = OpenMv_data1 * 10; // 獲取巡線模塊當前誤差       后輪差速

    // Pid_location = 0;

    Expect_Pwm = location_pid_realize(&OpenMv_pid_track, Pid_location); // 進行 PID 計算

    //  #if defined(PID_ASSISTANT_EN)
    //    set_computer_value(SEND_FACT_CMD, CURVES_CH1, &actual_speed, 1);                // 給通道 1 發(fā)送實際值
    //  #endif

    return Expect_Pwm;
}

2、灰度循跡

這部分我使用的是五路灰度循跡,也是根據(jù)灰度管檢測當前時刻的巡線變化來得出巡線偏差,帶入PID進行計算,這和OpenMv巡線類似,我給出如何獲得誤差,大家就可以把誤差帶入PID進行計算了

最后這個計算出來的值一般也是串起來的,循線環(huán)輸出帶入速度環(huán)的輸入,兩輪不同的方向,一邊+,一邊-,調(diào)節(jié)PID參數(shù)即可絲滑循跡

/*
 * @Author: _oufen
 * @Date: 2023-04-15 09:06:56
 * @LastEditTime: 2023-07-27 19:50:46
 * @Description:  五路灰度傳感器
 */

/* Includes -------------------------------------------------------------------------------------------------------------*/
#include "tracking.h"

/* Define -----------------------------------------------------------------------------------------------------------------*/
PID_Track pid_track;
/* Functions -----------------------------------------------------------------------------------------------------------------*/
/**
 * @brief 五路灰度GPIO初始化
 * @param None
 * @retval None
 * 分別使用到了 PB0/PB1/PB8/PB9/PA4
 */
void Tracking_Init(void)
{
    // GPIO初始化  上拉輸入
    MY_GPIO_Init(GPIOB, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | GPIO_Pin_9, GPIO_Mode_IPD);
    MY_GPIO_Init(GPIOA, GPIO_Pin_4, GPIO_Mode_IPD);
}

/**
 * @brief 五路灰度GPIO初始化
 * @param None
 * @retval None
 * 分別使用到了 PB0/PB1/PB8/PB9/PA4
 * 計劃使用中間三路進行巡線  最左端和最右端進行識別十字路口和丁字路口
 * 這里行駛的距離和巡線要有巡線補償
 * 低電平有效輸出   感應黑色輸出高電平
 */
void Tracking_Control(void)
{
}

void PID_xun_init(void) // 五路灰度循跡pid初始化
{
    pid_track.Kp = 35.0;
    pid_track.Ki = 0.0;
    pid_track.Kd = 0.0;

    pid_track.err = 0.0;
    pid_track.err_last = 0.0;
    pid_track.integral = 0.0;
    pid_track.output = 0.0;
}

/**
 * @brief   循跡模塊對應所有初始化
 * @param   None
 * @retval  None
 */
void Tracking_All_Init(void)
{
    Tracking_Init(); // 循跡GPIO初始化
    PID_xun_init();  // 循跡PID參數(shù)初始化
}

float PID_output(void)
{
    if ((L2 == 1) && (L1 == 0) && (M == 0) && (R1 == 0) && (R2 == 0)) // 10000
    {
        pid_track.err = -3;
    }

    else if ((L2 == 1) && (L1 == 1) && (M == 0) && (R1 == 0) && (R2 == 0)) // 11000
    {
        pid_track.err = -2;
    }

    else if ((L2 == 0) && (L1 == 1) && (M == 0) && (R1 == 0) && (R2 == 0)) // 01000
    {
        pid_track.err = -1.5;
    }

    else if ((L2 == 0) && (L1 == 1) && (M == 1) && (R1 == 0) && (R2 == 0)) // 01100
    {
        pid_track.err = -1;
    }

    else if ((L2 == 1) && (L1 == 1) && (M == 1) && (R1 == 0) && (R2 == 0)) // 11100
    {
        pid_track.err = -4;
    }

    else if ((L2 == 0) && (L1 == 0) && (M == 1) && (R1 == 0) && (R2 == 0)) // 00100
    {
        pid_track.err = 0;
    }

    else if ((L2 == 0) && (L1 == 0) && (M == 1) && (R1 == 1) && (R2 == 0)) // 00110
    {
        pid_track.err = 1;
    }

    else if ((L2 == 0) && (L1 == 0) && (M == 0) && (R1 == 1) && (R2 == 0)) // 00010
    {
        pid_track.err = 1.5;
    }

    else if ((L2 == 0) && (L1 == 0) && (M == 0) && (R1 == 1) && (R2 == 1)) // 00011
    {
        pid_track.err = 2;
    }

    else if ((L2 == 0) && (L1 == 0) && (M == 0) && (R1 == 0) && (R2 == 1)) // 00001
    {
        pid_track.err = 3;
    }

    else if ((L2 == 0) && (L1 == 0) && (M == 1) && (R1 == 1) && (R2 == 1)) // 00111
    {
        pid_track.err = 4;
    }

    // 十字路口

    else if ((L2 == 0) && (L1 == 0) && (M == 1) && (R1 == 0) && (R2 == 1)) // 00101
    {
        pid_track.err = 4;
    }

    else
        pid_track.err = 0;

    pid_track.integral += pid_track.err;

    pid_track.output = pid_track.Kp * pid_track.err + pid_track.Ki * pid_track.integral + pid_track.Kd * (pid_track.err - pid_track.err_last);

    pid_track.err_last = pid_track.err;

    return pid_track.output;
}

/*****************************************************END OF FILE*********************************************************/

3、裝載藥品

是否裝載藥品采用紅外對管來實現(xiàn)

這部分我也不多說了,就是檢測紅外的高低電平,分別對應藥品的狀態(tài)

4、識別數(shù)字

識別數(shù)字,我們采用的是OpenMv4和OpenMv4Plus,病房前識別數(shù)字采用模板匹配,小車行進時采用神經(jīng)網(wǎng)絡(luò)匹配數(shù)字,效果很好

但是由于我不是負責這方面的,所以,只知道一個大概思路

5、LED指示

這個也沒什么好說的,到達相應的狀態(tài)時,點亮和熄滅LED就行了

6、雙車通信

這里我們采用的方案有兩種

  • 藍牙通信模塊,HC-05
  • Zigbee通信模塊

其實,配置好了之后,這兩種使用都是一樣的,不同的方面就是Zigbee相較于藍牙配置好配置一些,更方便一些

就一般的通信來說,藍牙足夠了

關(guān)于這方面的通信模塊,一般肯定不會只發(fā)一個數(shù)據(jù),這個時候就需要定義數(shù)據(jù)包協(xié)議,以保證發(fā)方和收方接收的數(shù)據(jù)的準確性

我自己定義的數(shù)據(jù)包協(xié)議和OpenMv協(xié)議相同

數(shù)據(jù)包為 b3 b3 data1 data2 data3 5b

其中b3 b3為幀頭,5b為幀尾

下方是相關(guān)代碼

/*
 * @Author: _oufen
 * @Date: 2023-07-06 15:05:38
 * @LastEditTime: 2023-07-07 16:55:46
 * @Description:
 */
#include "usart3.h"

int Bluetooth_Receive_Buff[6]; // 藍牙接收數(shù)據(jù)
int16_t data1;                 // 三個有效數(shù)據(jù)位  第一個為  模式選擇
int16_t data2;                 // 第二個為  停車標志
int16_t data3;                 // 第三個為   主車走的圈數(shù)

/**
 * @brief 	串口3初始化
 * @param 	無
 * @retval  無
 */
void uart3_init(u32 bound)
{
    // GPIO端口設(shè)置
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 使能USART3,GPIOB時鐘

    // USART3_TX   GPIOB2       RX 	PA2
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; // PA2
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; // 復用推挽輸出
    GPIO_Init(GPIOB, &GPIO_InitStructure);          // 初始化GPIOB2

    // USART3_RX	GPIOB3   	TX  	PA3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;            // PB11
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 浮空輸入
    GPIO_Init(GPIOB, &GPIO_InitStructure);                // 初始化GPIOB3

    // USART3 NVIC 配置
    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // 搶占優(yōu)先級3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;        // 子優(yōu)先級3
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;           // IRQ通道使能
    NVIC_Init(&NVIC_InitStructure);                           // 根據(jù)指定的參數(shù)初始化VIC寄存器

    // USART 初始化設(shè)置
    USART_InitStructure.USART_BaudRate = bound;                                     // 串口波特率
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;                     // 字長為8位數(shù)據(jù)格式
    USART_InitStructure.USART_StopBits = USART_StopBits_1;                          // 一個停止位
    USART_InitStructure.USART_Parity = USART_Parity_No;                             // 無奇偶校驗位
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 無硬件數(shù)據(jù)流控制
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;                 // 收發(fā)模式

    USART_Init(USART3, &USART_InitStructure);      // 初始化串口2
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE); // 開啟串口接受中斷
    USART_Cmd(USART3, ENABLE);                     // 使能串口2
}

/**
 * @brief 	串口3發(fā)送數(shù)據(jù)包
 * @param 	無
 * @retval  無
 */
void u3_sendData(u8 *str)
{

    u8 i = 0;
    for (i = 0; i < 2; i++) // b3 b3
    {
        USART_SendData(USART3, 0xb3);
        while (USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET)
            ;
    }

    for (i = 0; i < 3; i++) // 發(fā)送三位有效位
    {
        USART_SendData(USART3, str[i]);
        while (USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET)
            ;
    }

    USART_SendData(USART3, 0x5b); // 0x5b
    while (USART_GetFlagStatus(USART3, USART_FLAG_TC) != SET)
        ;
}

void Bluetooth_Data(void) // 處理藍牙接收的數(shù)據(jù)
{
    data1 = Bluetooth_Receive_Buff[2];
    data2 = Bluetooth_Receive_Buff[3];
    data3 = Bluetooth_Receive_Buff[4];
}

/**
 * @brief 	串口3接收數(shù)據(jù)包  解析接收數(shù)據(jù)包   解析數(shù)據(jù)包   b3 b3 data1 data2 data3 5b
 * @param 	無
 * @retval  無
 */
void Bluetooth_Receive_Data(int16_t data)
{
    int i = 0;
    static u8 state = 0; // 初始化狀態(tài)值

    if (state == 0 && data == 0xb3) // 第一個幀頭 0xb3
    {
        state = 1;
        Bluetooth_Receive_Buff[0] = data;
    }
    else if (state == 1 && data == 0xb3) // 第二個幀頭  0xb3
    {
        state = 2;
        Bluetooth_Receive_Buff[1] = data;
    }
    else if (state == 2) // 第一個有效數(shù)據(jù)
    {
        state = 3;
        Bluetooth_Receive_Buff[2] = data;
    }
    else if (state == 3) // 第二個有效數(shù)據(jù)
    {
        state = 4;
        Bluetooth_Receive_Buff[3] = data;
    }
    else if (state == 4) // 第三個有效數(shù)據(jù)
    {
        state = 5;
        Bluetooth_Receive_Buff[4] = data;
    }
    else if (state == 5) // 接收幀尾
    {
        if (data == 0x5b) // 是幀尾  直接回到初始狀態(tài)
        {
            state = 0;
            Bluetooth_Receive_Buff[5] = data;
            Bluetooth_Data(); // 處理數(shù)據(jù)
        }
        else if (data != 0x5b) // 不是幀尾  所有數(shù)據(jù)置0
        {
            state = 0;
            for (i = 0; i < 6; i++)
            {
                Bluetooth_Receive_Buff[i] = 0;
            }
        }
    }
    else
    {
        state = 0;
        for (i = 0; i < 6; i++)
        {
            Bluetooth_Receive_Buff[i] = 0;
        }
    }
}

/**
 * @brief 	串口3接收中斷
 * @param 	無
 * @retval  無
 */
void USART3_IRQHandler(void) // 串口2中斷服務(wù)程序
{
    uint8_t ReceiveData;
    if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET) // 接收中斷(接收到的數(shù)據(jù)必須是0x0d 0x0a結(jié)尾)
    {

        USART_ClearITPendingBit(USART3, USART_IT_RXNE); // 清除中斷標志

        ReceiveData = USART_ReceiveData(USART3); // 接收的數(shù)據(jù)

        Bluetooth_Receive_Data(ReceiveData);

        Bluetooth_Data();

        // USART_SendData(USART3, ReceiveData);
        //  測試收發(fā)數(shù)據(jù)
        // if (ReceiveData == 58) // 當接收到0x3A后  接收數(shù)據(jù)燈亮    這個是基于最小系統(tǒng)板的測試程序
        // {
        //     MY_GPIO_Init(GPIOC, GPIO_Pin_13, GPIO_Mode_Out_PP);
        // }
    }
}

/********************************* 測試藍牙接收數(shù)據(jù) ****************************************************/

// 在主函數(shù)中顯示  但是要先引入usart3頭文件   注意要在主函數(shù)中初始化  連線連接無錯誤

// 在上位機中以定義協(xié)議格式發(fā)送 b3 b3 01 02 03 5b

// 接收數(shù)據(jù)在OLED上顯示  如發(fā)送數(shù)據(jù)和接收數(shù)據(jù)相同 則表示接收協(xié)議無錯誤

// 下一步就是接收藍牙主機的數(shù)據(jù)

// // 顯示串口3接收數(shù)據(jù)  這是藍牙從機  接收數(shù)據(jù)
// OLED_ShowNum(3, 8, data1, 2);  // 有效數(shù)據(jù)1
// OLED_ShowNum(3, 11, data2, 2); // 有效數(shù)據(jù)2
// OLED_ShowNum(3, 14, data3, 2); // 有效數(shù)據(jù)3

/*********************************** 結(jié)束 *************************************************************/

7、轉(zhuǎn)向方案

轉(zhuǎn)向方案可有很多種了嘞

在經(jīng)過實際測試后,我總結(jié)出來了主要的三種轉(zhuǎn)向方案

  • 開環(huán)轉(zhuǎn)向
  • 位置環(huán)速度環(huán)串級轉(zhuǎn)向
  • MPU6050轉(zhuǎn)向
1、開環(huán)轉(zhuǎn)向

就是電機IO,分別給0、1,然后給一個PWM,記錄此時兩輪的脈沖數(shù)相加的絕對值,當超過設(shè)定的脈沖時就停止

這時設(shè)定的脈沖,就可以是90°的脈沖和180度的脈沖,這需要自己一步一步的測試

我經(jīng)過測試發(fā)現(xiàn)可行,并且還挺穩(wěn)定的

下面給出相關(guān)代碼

/**
 * @brief 轉(zhuǎn)向   開環(huán)轉(zhuǎn)向
 * @param 脈沖值;方向(左1 右2) pwm
 * @retval 無
 */
void Car_turn(int pluse, int mode, int pwm)
{

    while (1)
    {
        if (mode == 1) // 向左
        {
            Load_Motor_PWM(-pwm, pwm);
        }
        else if (mode == 2) // 向右
        {
            Load_Motor_PWM(pwm, -pwm);
        }
        if (pathLenth > pluse) // 達到預設(shè)角度
        {
            break;
        }
    }
    Load_Motor_PWM(0, 0); // 立馬定住
    Motor_Left_DIR(STOP);
    Motor_Right_DIR(STOP);
}

void TIM6_IRQHandler(void) // 10ms
{
    if (TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
    {
        LED_RED = !LED_RED; // 測試程序是否卡死
        TIM_ClearITPendingBit(TIM6, TIM_IT_Update);

        a = -Read_Encoder(2);
        b = Read_Encoder(3);

        pathLenth += MyABS(a) + MyABS(b); // 累積脈沖數(shù)

        // rpm   330脈沖

        //        speed1 = ((float)a * 60000.0) / 13200;
        //        speed2 = ((float)b * 60000.0) / 13200;
    }
}

可以看出當小車當前脈沖到達自己設(shè)置的脈沖時,小車就停止,這個時候小車差速,即可到達期望角度

// Car_turn(2000, 1, 1000); // 開環(huán)轉(zhuǎn)彎 左轉(zhuǎn)90
// Car_turn(2000, 2, 1000); // 開環(huán)轉(zhuǎn)彎 右轉(zhuǎn)90
// Car_turn(4000, 1, 1000); // 掉頭180

2、位置環(huán)速度環(huán)閉環(huán)串級轉(zhuǎn)向

位置環(huán)為外環(huán),速度環(huán)為內(nèi)環(huán),位置環(huán)的輸出即是速度環(huán)的輸入

這個時候小車旋轉(zhuǎn)的角度就是以小車兩輪為直徑的圓的四分之一的距離,這個距離如何計算呢

小車轉(zhuǎn)一圈的脈沖我們知道,假定1040個脈沖

那么當前行進的脈沖數(shù)/小車轉(zhuǎn)一圈的脈沖數(shù),我們就是不是就知道了小車轉(zhuǎn)了幾圈,然后把這個×小車轉(zhuǎn)一圈的周長,就知道了小車行進的距離

把小車行進距離轉(zhuǎn)換為脈沖帶入位置環(huán),得到輸出后賦值給速度環(huán)即可,使小車轉(zhuǎn)90°的距離恒定,掉頭的距離也恒定,轉(zhuǎn)向就完成了

這部分代碼有些多,我在文末會貼出代碼,大家可以自行查看

3、MPU6050轉(zhuǎn)向

通過yaw角的反饋,來改變小車的旋轉(zhuǎn)方向,yaw角為90°時即轉(zhuǎn)向90°,yaw角為180°時即掉頭

這個也是串起來的PID,角度環(huán)的輸出是速度環(huán)的輸入

調(diào)節(jié)好PID參數(shù)后即可絲滑轉(zhuǎn)向



/**
 * @brief  角度環(huán)pid輸出函數(shù)
 * @param  actual_val:實際值  6050yaw
 *	@note 	無
 * @retval 通過PID計算后的輸出
 */
float Angle_pid_realize(_pid *pid, float actual_val)
{
    /*    計算偏差    這里的偏差是指 巡線偏差 設(shè)定的巡線期望值 和 MV傳回的巡線實際值 得偏差 */
    pid->err = pid->target_val - actual_val;

    if (pid->err > 180) // 防止小車轉(zhuǎn)到180度時一直旋轉(zhuǎn)的問題
        pid->err = pid->err - 360;
    if (pid->err < -180)
        pid->err = pid->err + 360;

    pid->integral += pid->err; // 誤差累積

    // if (pid->err >= 1000) // 積分限幅
    // {
    //     pid->err = 0;
    // }

    // if (huidu.output >= 550)
    //     huidu.output = 550;
    // if (huidu.output <= -600)
    //     huidu.output = -600;

    /*PID算法實現(xiàn)*/
    pid->actual_val = pid->Kp * pid->err + pid->Ki * pid->integral + pid->Kd * (pid->err - pid->err_last);

    /*誤差傳遞*/
    pid->err_last = pid->err;

    /*返回當前實際值*/
    return pid->actual_val;
}

/**
 * @brief  角度環(huán)pid輸出函數(shù)
 * @param  actual_val:無
 *	@note 	無
 * @retval 通過PID計算后的輸出
 */
float Angle_pid_control(void)
{

    float Expect_Pwm = 0.0; // 當前控制值

    // pid_speed1.actual_val = ((float)Param.UnitTime_Motor1Pluse * 1000.0 * 60.0) / (RESOULTION_TOTAL_RATIO * REDUCTION_RATIO * PID_PERIOD);

    // Pid_speed2 = ((float)Param.UnitTime_Motor2Pluse * 60000.0) / 17680;

    Pid_Actual_angle = KLM(yaw); // 實際值 為yaw  濾波后的數(shù)據(jù)

    Expect_Pwm = Angle_pid_realize(&pid_angle, Pid_Actual_angle); // 進行 PID 計算

    //  #if defined(PID_ASSISTANT_EN)
    //    set_computer_value(SEND_FACT_CMD, CURVES_CH1, &actual_speed, 1);                // 給通道 1 發(fā)送實際值
    //  #endif

    return Expect_Pwm;
}

二、調(diào)試經(jīng)驗分享

大家在實際做題的時候肯定會出現(xiàn)非常多的問題,不要慌,慢慢來,分析造成這種問題的原因是什么,從現(xiàn)象出發(fā),再回到代碼

等調(diào)出想要的代碼的實際效果時,那一刻就會感覺之前的努力都值了

關(guān)于這道題,主要調(diào)試的有以下幾部分

1、循跡

這個循跡,只要偏差值沒錯,補償值兩輪,一正一負,后面就是調(diào)節(jié)PID的問題了

2、識別數(shù)字

這個也是關(guān)鍵,如何準確識別數(shù)字,然后小車根據(jù)MV發(fā)過來的數(shù)據(jù)進行運動
識別數(shù)字的準確率也要有相應的保證,小車一切行進的基礎(chǔ)都是在準確識別到數(shù)字的基礎(chǔ)上的

3、轉(zhuǎn)向

在調(diào)試的時候,多次發(fā)現(xiàn)小車不能完全轉(zhuǎn)向90度,造成小車循跡出線,壓黑線等
這個時候,要檢查一下小車的硬件結(jié)構(gòu)是否合理,程序是不是哪個地方寫錯了等

4、雙車通信

通信部分,我建議的是,首先在上位機上模擬OpenMv或者藍牙主機,發(fā)送定義的數(shù)據(jù)包協(xié)議,將接收到的數(shù)據(jù)在OLED上進行顯示,如果接收到正確的數(shù)據(jù),即可證明通信無問題,再去排除其他問題

5、邏輯處理

其實,在掌握了以上知識點后,我覺得邏輯還是很重要的,由自己親身經(jīng)歷過,就是你知道如何實現(xiàn)單個功能,但是融合起來后就完全不行了,在比賽過程中是很浪費時間的,會造成時間的大量浪費,再加上身體的高強度運作和心態(tài),就悲劇了

千萬要在平時加強對程序邏輯的判斷和處理,作者本人親身經(jīng)歷,不要學我
比如這道題目,我首先是在OpenMv識別數(shù)字后,放上藥品才可以小車行進去指定的病房送藥,一二號病房沒有太大難度,寫死即可,后面的病房要根據(jù)OpenMv二次判斷,來進行更正進病房,并要求返回藥房。

這個邏輯就很重要,識別到Mv就返回一個標志位,左邊為0x3A,右邊即為0x3B等。發(fā)揮部分,從車等待主車卸載藥品后取藥,這個時候是主車卸載完藥品后才給從車發(fā)行進標志,從車才可以動,防止撞車等

6、心態(tài)問題

不要被一種方案限制住了,比賽嗎,有無限可能的,發(fā)揮不同的思路和方法,只要能實現(xiàn)就是好方法

我已經(jīng)給大家以身試法過了,這次參加的電賽,由于沒有車,只能做E題,賽前玩了玩二維云臺追蹤小球,大部分心思還是壓在了車上,而這道題目比賽完后,再次復盤回想起這道題,是自己的思維局限把自己限定死了,導致越調(diào)越不行,前兩天,想著閉環(huán)跑,可惜沒有實現(xiàn),后面自己稀里糊涂的實現(xiàn)了閉環(huán),但是速度不可控,還是會超出黑線,誤差很大,導致每分,自己也很急,就這樣,第一次電賽也是最后一次就結(jié)束了

總歸來說還是心態(tài)和實力,想的太多,每次力爭最優(yōu)解

電賽還是很考驗人的,雖說可能結(jié)果不會怎么樣,但是我覺得在準備電賽得過程中還是很棒得,一起每天早起得隊友,大家互相配合,完成題目得喜悅,一起解決問題得思考,還是很有意義的。

總結(jié)

希望大家吸取教訓,大家有什么不懂得問題也可以在評論區(qū)留言,看到了得話就肯定會恢復給大家解答,希望自己得綿薄之力可以幫助大家

大家一定要不斷的加強訓練,對學習的東西進行一個總結(jié)和匯總,加強控制題目的訓練,而不是僅僅做小車,小車是一個載體,其內(nèi)部原理也是控制的精細程度

開源鏈接

我會在這兩天將自己這個開源鏈接的代碼進行一個講解

我采用了不同的主控,不同的巡線方案、大家可以自行訪問,進行下載

下方為gitee開源鏈接,請大家點一個star,謝謝
oufen / 2021年電賽F題-智能送藥小車

分享21年電賽F題-智能送藥小車-做題記錄以及經(jīng)驗分享,電賽真題,STM32,經(jīng)驗分享,stm32,電賽文章來源地址http://www.zghlxwxcb.cn/news/detail-641154.html

到了這里,關(guān)于分享21年電賽F題-智能送藥小車-做題記錄以及經(jīng)驗分享的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 電賽智能送藥小車_OpenMV巡線&識別十字路口完整代碼

    ? 整體思路 :通過劃分ROI區(qū)域分區(qū)進行識別,中央 ROI 區(qū)域為巡線,左右兩側(cè)的 ROI_L 和 ROI_R 為十字路口識別 . 主程序如下 : # 本文代碼中所導入的pid.py就是OpenMV官網(wǎng)上例程的代碼 需要完整源碼請私信我。

    2024年02月12日
    瀏覽(99)
  • 2021全國大學生電子設(shè)計競賽論文(智能送藥小車(F題))(電賽論文模板)

    2021全國大學生電子設(shè)計競賽論文(智能送藥小車(F題))(電賽論文模板)

    電賽是一個很奇妙的過程,可能有些人覺得電賽的門檻太高,那便意味著,當你決定要參加電賽的那一刻起,這一段路、這些日子就注定不會太輕松; 我現(xiàn)在回頭看真的很感謝電賽,從前期備賽面對自己未曾涉獵的技術(shù)不知如何下手的迷茫與懷疑,再到后來四天三夜緊張到不

    2024年02月05日
    瀏覽(28)
  • 21年電賽無人機G題思路

    21年電賽無人機G題思路

    21年電賽結(jié)束了,我們選擇的題目是無人機G題。通過題目也能感受到今年的難度,在這里旨在為大家提供一個G題的解題思路和方案。 讀完題目,可以發(fā)現(xiàn)主要有兩個難題需要解決 1.飛行路徑問題(如何確保飛行能覆蓋全部播撒區(qū)域) 2.視覺識別問題(如何識別到條形碼和入

    2024年02月15日
    瀏覽(20)
  • 2021電賽F題送藥小車視覺部分的一種思路(雙OpenMV法)

    2021電賽F題送藥小車視覺部分的一種思路(雙OpenMV法)

    前言: 最近參加了2021年電賽的F題,因為諸多原因未能完賽,現(xiàn)將圖像識別部分的記錄一下,交流學習。 因為只介紹視覺部分,我們就節(jié)選相關(guān)的部分吧。 設(shè)計并制作智能送藥小車,模擬完成在醫(yī)院藥房與病房間藥品的送取作業(yè)。院區(qū)結(jié)構(gòu)示意如圖 1 所示。院區(qū)走廊兩側(cè)的

    2024年02月15日
    瀏覽(16)
  • 基于PID算法下STM32控制的坡道行駛電動小車(2020年電賽)

    基于PID算法下STM32控制的坡道行駛電動小車(2020年電賽)

    本題源于2020年TI杯大學生電子設(shè)計競賽C題-----坡道行駛電動小車 由于手上沒有MSP430/MSP432 板子,所以本篇采用stm32實現(xiàn) 任務(wù) 利用 TI 的 MSP430/MSP432 平臺,設(shè)計制作一個四輪電動小車。要求小車能沿著指定路線在坡道上自動循跡騎線行駛。小車必須獨立運行,車外不能使用任何

    2024年02月16日
    瀏覽(52)
  • 基于MSP432P401R爬坡小車【2020年電賽C題】

    基于MSP432P401R爬坡小車【2020年電賽C題】

    主控板: MSP432P401R 數(shù)據(jù)顯示: OLED 電機: 霍爾編碼器電機 電池: 7.3V航模電池 巡線: OpenMV H7 Plus 警報: 蜂鳴器 電機驅(qū)動: TB6612 儀器: 3D打印機 視覺云臺: 3D建模打印 轉(zhuǎn)向: 數(shù)字舵機 其他: 銅柱、螺絲螺母、開關(guān)、面包板等。 編譯器: Keil、OpenMV IDE 建模軟件: Sketc

    2024年02月15日
    瀏覽(21)
  • K210實現(xiàn)單目測算距離—以21年電賽F題為例

    K210實現(xiàn)單目測算距離—以21年電賽F題為例

    單目測距在無人駕駛,路徑規(guī)劃中的地位越來越重要,比激光雷達和深度相機的成本更低,更適合于項目的開發(fā)。 單目測算距離的原理就是初中物理上學的小孔成像原理,但是由于我們不知道高度,所以會造成深度丟失。所以我們第一步就是測量我們要測量物體的真實寬度和

    2024年02月14日
    瀏覽(18)
  • 21年電賽F 題jetson nano+32F4識別數(shù)字(附源碼和數(shù)據(jù)集)

    21年電賽F 題jetson nano+32F4識別數(shù)字(附源碼和數(shù)據(jù)集)

    目錄 前言 一、Opencv采集數(shù)字圖像 二、標記圖像數(shù)字位置 三、yolov4-tiny機器學習訓練 四、jetson nano識別數(shù)字 五、識別效果 單個數(shù)字識別 ???? 兩個數(shù)字識別 ?四個數(shù)字識別 命令行結(jié)果顯示 小車OLED屏幕顯示 總結(jié)+數(shù)據(jù)集權(quán)重文件+小車程序 前言 ??!四天三夜的電賽終于結(jié)

    2024年02月14日
    瀏覽(53)
  • 全國電子設(shè)計競賽-國二--智能送藥小車

    全國電子設(shè)計競賽-國二--智能送藥小車

    不過這一次的比賽是真的很幸運,因為參加過比賽都知道,這一次沒有了線下比賽,線上評審,不過拿到試題的那一天也是蠻緊張的,我們隊伍做的是F題智能送藥小車,現(xiàn)在的控制類的題目是真的越來越難了,相對于之前的控制類的題目。 還是講一下比賽期間發(fā)生的一些事

    2024年02月14日
    瀏覽(25)
  • 智能送藥小車(一)——K210巡線

    這部分基本就是例程上的內(nèi)容,添加了一點注釋。關(guān)于相關(guān)的運用到的函數(shù)解釋,可以參考K210顏色識別.

    2024年02月12日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包