嘉立创产业服务站群
必应搜索
发作品签到
专业版

2024电赛Ti杯三子棋

工程标签

1.0k
0
0
7

简介

24电赛三子棋,参加校赛最后评测出了点小问题。代码和机械都有很多要优化的地方,发出来抛转引玉,欢迎大家指点批评。

简介:24电赛三子棋,参加校赛最后评测出了点小问题。代码和机械都有很多要优化的地方,发出来抛转引玉,欢迎大家指点批评。
复刻成本:600

开源协议

GPL 3.0

创建时间:2025-01-16 09:27:01更新时间:2025-04-02 01:52:32

描述

视频链接:

[B站视频]https://www.bilibili.com/video/BV18MZYYfE9p/?spm_id_from=333.1387.homepage.video_card.click&vd_source=c5264ed3939a6a674d4069dff1ca5d90
立创开源广场链接:(https://oshwhub.com/xu_duoduo/san-zi-qi)
github链接:(https://github.com/JourneyXuu/mitsuko-2024E)

项目简介

本系统采用模块化的设计思想,以STM32F407为中央处理器,由庐山派K230视觉模块、曲柄连杆、张大头闭环步进电机、舵机、龙邱电源模块、陶晶池串口屏、电磁铁。

原理解析(硬件说明)

此处可填写项目的设计原理,将设计的原理拆分解析,示例:

主控:STM32F407VET6(只引出了串口、CAN、I2C、定时器TIM1和ADC1的部分通道)
主控图片
拍的丑将就看一下

调试PCB遇到的问题
1.原本使用时舵机的电源和主控公共用1个5V,发现舵机启动电流过大,会导致舵机不工作,version1的PCB最后外部连接了龙邱的电源给舵机单独供电,现在提交的PCB已经修改为version2。
2.按键画错了,v1的按键焊接时全部拆除
3.预留的串口触摸屏没有用,直接用了陶晶驰的串口屏

分电板

**分电线**

恒流源补光板

支出输入电压:3V-18V

灯太亮了,所以做了一个外壳挡挡光

供电结构图

下位机软件代码

软件代码结构

IO接线

串口2控制步进电机

张大头的步进电机使用串口控制,使用多机同步,电机1、2必须同步
电机1、2使用多圈无限位碰撞回零操作说明
电机3使用单圈就近回零
在上位机中修改回零

/*  
*@brief: 控制三电机运动x,y三轴
*note:   电机1、2控制x方向,电机3控制y方向
*@param: x_distance:    电机1、2运动距离
*@param: dir_X:         电机1、2运动方向 
*@param: y_distance:    电机3运动距离
*@param: dir_y:         电机3运动方向
*note:如果发送失败则重新发送命令
*/
void control_t(uint32_t x_distance,uint32_t y_distance)
{
   Emm_V5_Pos_Control(1, 0, velocity, acc, x_distance, raf, 1); Delay_Timer(10);while(!checkDelayTimer());// 多机同步标志位置1
   Emm_V5_Pos_Control(2, 1, velocity, acc, x_distance, raf, 1); Delay_Timer(10);while(!checkDelayTimer());
   Emm_V5_Pos_Control(3, 1, velocity, acc, y_distance, raf, 1); Delay_Timer(10);while(!checkDelayTimer());
   Emm_V5_Synchronous_motion(0); 
}

串口3解包陶晶驰

只有检测到包头和包尾的数据才修改数据

这里写的串口DMA接收写的不够好,可以修改为双缓冲区,不过本题很够用了

void  TJC_UART_UnPack(uint8_t *dma_buffer)
{
    uint8_t data;
    for (uint16_t i = 0; i < MAX_PACKET_LENGTH; i++) 
    {
        data = dma_buffer[i];   
            switch (tjc_rx_handler.state) {
                case RX_WAIT_HEADER:
                    if (data == PACKET_HEADER) { // 检测到包头
                        tjc_rx_handler.index = 0;// 直接重置索引,不存储包头
                        tjc_rx_handler.state = RX_RECEIVING;
                    }
                    break;

                case RX_RECEIVING:
                    if (data == PACKET_FOOTER) { // 检测到包尾
                        //检测到包尾时不存储包尾,直接进行数据有效性检查。
                        // 数据有效性检查(可添加CRC校验)
                        if (tjc_rx_handler.index >= 2) { // 最小有效包长度判断
                            Task_Flag    = tjc_rx_handler.buffer[0];
                            Selected_Chess = tjc_rx_handler.buffer[1];
                            Selected_Board = tjc_rx_handler.buffer[2];
                            break_flag = tjc_rx_handler.buffer[3];
                        }
                        
                        tjc_rx_handler.state = RX_COMPLETE;
                    } else {
                        if (tjc_rx_handler.index < MAX_PACKET_LENGTH - 1) {
                            tjc_rx_handler.buffer[tjc_rx_handler.index++] = data;
                        } else { // 数据超长处理
                            tjc_rx_handler.state = RX_WAIT_HEADER;
                        }
                    }
                    break;

                case RX_COMPLETE: // 完成一帧接收后复位状态机
                default:
                    tjc_rx_handler.state = RX_WAIT_HEADER;
                    memset(tjc_rx_handler.buffer, 0, sizeof(tjc_rx_handler.buffer));
                    tjc_rx_handler.index = 0;
                    break;
            }
    }

    HAL_UARTEx_ReceiveToIdle_DMA(&huart3, dma_buffer, DMA_BUFFER); // 启用空闲中断接收
    __HAL_DMA_DISABLE_IT(&hdma_usart3_rx, DMA_IT_HT);          

}

上位机软件代码

K230实际跑起来帧率比较低,可以修改像素
MINIMAX算法
最后一题长按庐山派上的用户按键开启第六题,我们都用的最简单最笨的方法
哈哈,能用就行

def minimax(board, depth, is_maximizing):
    computer = 'X'
    player = 'O'

    if check_win(board, computer):
        return 10 - depth
    if check_win(board, player):
        return depth - 10
    if check_draw(board):
        return 0

    if is_maximizing:
        best_score = float('-inf')
        for i in range(SIZE):
            for j in range(SIZE):
                if board[i][j] == ' ':
                    board[i][j] = computer
                    score = minimax(board, depth + 1, False)
                    board[i][j] = ' '
                    best_score = max(score, best_score)
        return best_score
    else:
        best_score = float('inf')
        for i in range(SIZE):
            for j in range(SIZE):
                if board[i][j] == ' ':
                    board[i][j] = player
                    score = minimax(board, depth + 1, True)
                    board[i][j] = ' '
                    best_score = min(score, best_score)
        return best_score

机械结构

有一个好的机械手可以帮大家省去很多麻烦
本设备使用的十字滑台,由3个步进电机和传送带组成,结构如图3所示。步进电机A和步进电机B保持同速转动,可实现上下方向的移动,步进电机C保持同速转动,可实现左右方向的移动。

舵机连杆操作

注意事项

  • 准备一个电源来调,免得步进疯了撞来撞去
  • 分电板可以自己改改,加个开关
  • 代码太多了,自己看看吧

鸣谢

没有躺赢狗,大家都是MVP,感谢一起陪伴做比赛,很珍惜这段时间
电控、硬件(up本人): @xuduoduo
视觉算法:@Gone with the wind
机械:@是祺不是琪

实物图

此处可放入组装完成后完整实物图
图1:v1版本的PCB:(目前已修复大部分错误,打板最新的就行)

图2:分电板PCB(没咋改过)

图3:呆唯补光板

设计图

未生成预览图,请在编辑器重新保存一次

BOM

暂无BOM

附件

序号文件名称下载次数
1
三子棋.mp4
38
2
三子棋.mov
34
3
电赛E题三字棋.rar
113
4
TJC_Code.rar
49
克隆工程
添加到专辑
0
0
分享
侵权投诉

工程成员

评论

全部评论(1)
按时间排序|按热度排序
粉丝0|获赞0
相关工程
暂无相关工程

底部导航