迪文科技论坛

 找回密码
 立即注册
搜索
查看: 329|回复: 0

【开源】基于T5L迪文屏的零食机

[复制链接]

5

主题

6

回帖

617

积分

高级会员

Rank: 4

积分
617
发表于 2025-2-21 14:00:11 | 显示全部楼层 |阅读模式
本帖最后由 good 于 2025-2-21 14:04 编辑

一.介绍
大家可能都去商场的游戏厅玩过哈,是否对下面的游戏机有一种熟悉感呢?




就是抓零食, 抓玩具等各种游戏机, 它们有的是用LCD12864单色屏做的,有的是用更简单的数码管做的,不管外观咋样,仪器内部的实现原理基本都是差不多的,大概可以分为如下几部分构成:
1.电机,机械臂,导轨等结构
2.摇杆, 按键, 显示系统, 投币器, 光耦定位等硬件
3.游戏状态机, 充值, 厂家后台等软件组件

     哈哈,大家都知道现在商场里面的游戏机都是可以调节难易程度的, 一般小白可能不知情哈, 这里我给大家解密一下, 这些调节参数都是在我们的"厂家后台"软件组件中调节的, 比如调节爪子力度大小, 中奖概率, 电机移动速度, 送币概率, 下降绳长等参数,当然了
我们用户一般是无法进入到这个"厂家后台"调试界面的, 一般在游戏机柜内有一个按键, 可以通过长按来触发进入的,
    好了现在进入主题, 本项目采用了迪文触摸彩屏来实现零食机, 也算是市面上的一个革新点吧, 然后还有许多硬件模块其实它内部是封装好了的, 它内部处理掉了复杂的处理事项, 只是暴露简单的接口来供我们控制, 比如其中的投币器

二.GUI设计
1.所有图片素材如下:


2.首先游戏机开机后会进入到开机界面,这里其实是在完成各组件模块的自检流程,如果出错了,就会跳到相应的报错界面


3.自检没有问题后,就会进入到正常的主界面,也就是所谓的游戏状态机
在这里会显示用户投币的累计总局数,每玩一次会减少1, 然后还会显示每一次游戏的倒计时,时间一到系统将会自动出爪,然后还会显示投几个币才能玩一局等,
当然了这里的时间,和几币一局都是在后台可以设置的喔


4.然后就是前面我们所说到的"厂家后台"界面,它是通过长按一个按键来进入的,后台系统的界面是比较复杂的,它不仅要给车间工人提供调试接口,还要给游戏厅老板提供参数设定接口

看上图就知道复杂程度了,里面的每一个一级菜单项又细分出来了很多二级菜单项的,比如"C基础设置"


三.代码设计

1.迪文屏和主控的通信代码

void uart2_master_isr()        interrupt 4
{
        u8 res;
        
        if(RI0)
        {
                RI0 = 0;
                res = SBUF0;
                uart2_rx_timeout = UART2_RX_TIMEOUT;
                if((uart2_rx_sta&UART2_PACKET_OK)==0)
                {
                        if(step==0)
                        {
                                recv_len = 0;
                                if(res==0x15)
                                        step = 1;
                        }else if(step==1)
                        {
                                date_len = res;
                                step  = 2;
                                if(date_len>UART2_PACKET_MAX_LEN)
                                        step = 0;
                        }else if(step==2)
                        {
                                if(recv_len==date_len)
                                {
                                        step = 0;
                                        if(res==0x16)
                                        {
                                                uart2_rx_sta = date_len;
                                                uart2_rx_sta |= UART2_PACKET_OK;
                                        }
                                }else
                                        uart2_buf[recv_len++] = res;
                        }
                }
        }        
}


2.电机的驱动代码

void motor_move(MOTOR motor,MOTOR_DIR dir)
{        
        if(motor==MOTOR_Z)//Z轴上的爪子电机
        {
                if(dir==MOTOR_DIR_NONE)//停止
                {
                        MOTOR_Z_DISABLE();
                }else
                {
                        if((IS_MOTOR_Z_BACKWARD_POS()&&(dir==MOTOR_DIR_BACKWARD))
                                ||(IS_MOTOR_Z_FORWARD_POS()&&(dir==MOTOR_DIR_FORWARD)))
                        {
                                MOTOR_Z_DISABLE();
                                dir = MOTOR_DIR_NONE;
                        }else
                        {
                                MOTOR_Z_ENABLE();
                                MOTOR_Z_DIR_PIN = (dir==MOTOR_DIR_BACKWARD);
                        }
                }
        }else if(motor==MOTOR_X)//X轴移动电机
        {
                if(dir==MOTOR_DIR_NONE)//停止
                {
                        MOTOR_X_DISABLE();
                }else
                {
                        if(IS_MOTOR_X_BACKWARD_POS()&&(dir==MOTOR_DIR_BACKWARD))
                        {
                                MOTOR_X_DISABLE();
                                dir = MOTOR_DIR_NONE;
                        }else
                        {
                                MOTOR_X_ENABLE();
                                MOTOR_X_DIR_PIN = (dir==MOTOR_DIR_BACKWARD);
                        }
                }
                x_last_dir = dir;
        }else if(motor==MOTOR_Y)//Y轴移动电机
        {
                if(dir==MOTOR_DIR_NONE)//停止
                {
                        MOTOR_Y_DISABLE();
                }else
                {
                        if((IS_MOTOR_Y_BACKWARD_POS()&&(dir==MOTOR_DIR_BACKWARD))
                                ||(IS_MOTOR_Y_FORWARD_POS()&&(dir==MOTOR_DIR_FORWARD)))
                        {
                                MOTOR_Y_DISABLE();
                                dir = MOTOR_DIR_NONE;
                        }else
                        {
                                MOTOR_Y_ENABLE();
                                MOTOR_Y_DIR_PIN = (dir==MOTOR_DIR_BACKWARD);
                        }
                }
                y_last_dir = dir;
        }else if(motor==MOTOR_CLAW)
        {
                if(dir==MOTOR_DIR_NONE)
                {
                        MOTOR_CLAW_RELEASE();
                }else
                {
                        MOTOR_CLAW_HOLD();
                }
        }
        
}


3.爪子调力度,速度的代码(采用的是PWM)

const u16 MOTOR_DUTY[MOTOR_TOTAL][MOTOR_SPEED_MAX+1] = {
        {45+DUTY_OFFSET,60+DUTY_OFFSET,80+DUTY_OFFSET,110+DUTY_OFFSET,130+DUTY_OFFSET,160+DUTY_OFFSET,200+DUTY_OFFSET,250+DUTY_OFFSET,550+DUTY_OFFSET,TIM_ARR},//X
        {45+DUTY_OFFSET,60+DUTY_OFFSET,80+DUTY_OFFSET,110+DUTY_OFFSET,130+DUTY_OFFSET,160+DUTY_OFFSET,200+DUTY_OFFSET,250+DUTY_OFFSET,550+DUTY_OFFSET,TIM_ARR},//Y
        {45,60,80,110,130,160,200,250,550,TIM_ARR},//Z
        {200,220,240,270,290,320,360,410,550,TIM_ARR}//爪子
};



void motor_set_speed(MOTOR motor,u8 speed)
{
        if(speed>MOTOR_SPEED_MAX)
                return;
        
        pwm_set_duty((PWM_CH)motor,MOTOR_DUTY[motor][speed]);
}



void motor_set_claw_strength_by_vol(float vol)
{
        #define CLAW_DUTY_MIN                        200
        #define CLAW_DUTY_MAX                        TIM_ARR
        u16 duty;
        
        vol = (float)(vol-QZLDY_MIN)/(QZLDY_MAX-QZLDY_MIN);
        if(vol<0)
                vol = 0;
        else if(vol>1)
                vol = 1;
        duty = (u16)(vol*(CLAW_DUTY_MAX-CLAW_DUTY_MIN)+0.5f)+CLAW_DUTY_MIN;
        
        pwm_set_duty(PWM_CH_MOTOR_CLAW, duty);
}


4.厂家后台按键长按检测

u8 key_check_long_press(KEY key,u32 time)
{
        while(1)
        {
                if(!(KEY_Scan(1)&key))
                        return 1;//失败
                if(time)
                {
                        sys_delay_ms(1);
                        time--;
                        if(time==0)
                                return 0;//成功
                }
        }
}


四.视频演示
https://b23.tv/7rEnD5J

GUI参考:


vs代码参考:



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|迪文科技论坛 ( 京ICP备05033781号-1 )

GMT+8, 2025-5-10 03:11 , Processed in 0.111364 second(s), 23 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表