2022TI杯10月联赛D题——盲盒识别装置

       在准备2023国赛期间,我们从2022TI杯的10月联赛赛题中选择了D题盲盒识别装置作为训练题目。从网上查找了许多资料,期间查询了很多金属探测的方式,大多都是通过电磁感应来检测金属,通过比较不同金属和金属大小对线圈电感的不同影响程度,进而比较不同的硬币情况。

     方案描述


   本文章选择了WL01涡流传感器作为检测硬币的工具,由DSP读取到不同的数据,来进行硬币的识别。

       WL01涡流传感器的工作原理

       当接通传感器系统电源时,在传感器模块内部回产生一个高频信号,在线圈周围产生交变磁场。如果有金属导体接近线圈,则交变磁场将在导体的表面产生电涡流场,该电涡流场也会产生一个方向与之相反的交变磁场,由于反作用,就会改变线圈高频电流的幅度和相位,即改变了线圈的有效阻抗。这种变化既与电涡流效应有关又与静磁学效应有关;既与金属导体的电导率、磁导率、几何形状、线圈几何参数,激励电流频率以及线圈金属导体的距离参数有关。
       

WL01涡流传感器原理图

代码示例

        本文章使用的是DSP28335的开发板进行ADC采样,通过检测WL01涡流传感器的信号变化来识别硬币。本代码显示使用了LCD12864液晶屏进行显示,ADC采样代码不在给出,在CCS工程文件中有相关说明。

 main.c如下:

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
#include "LCD12864.h"
#include "Adc.h"
#include "KEY.h"

void main(void)
{
   InitSysCtrl();
  // InitLedGpio();
   // ADC引脚均为专用引脚,不需要初始化
   Init_Port();

   EALLOW;
   adc_sys_clk();
//      GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;    // GPIO pin
//      GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;     // Output pin
   EDIS;

   DINT;
   InitPieCtrl();
   IER = 0x0000;
   IFR = 0x0000;
   InitPieVectTable();
 //  InitCpuTimers();
   LCD_init();
   InitAdc();    // 使能ADC模块,并上电
  // SetAdcParm(); // 设置ADC模块有关参数
   while(1)
   {
             Adc_Convert();
    //   Scan_Key();
   }
}

LCD12864.c如下:

#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File

/***************全局变量定义****************/
#define uchar unsigned char

/****************端口宏定义*****************/
#define RS GpioDataRegs.GPADAT.bit.GPIO0
#define RW GpioDataRegs.GPADAT.bit.GPIO2
#define EN GpioDataRegs.GPADAT.bit.GPIO1
#define DB GpioDataRegs.GPADAT.all

// 使用前,声明本文件中的相关函数
void Init_Port(void);                //端口初始化
void LCD_init(void);                             //初始化函数
void LCD_write_command(unsigned char command);           //写指令函数
void LCD_write_data(uchar dat);                  //写数据函数
void LCD12864SetAddress_f( uchar x, uchar y );   //地址转换
void show(unsigned char x,unsigned char y,unsigned char *pData);     //用于显示的子函数
void show1(unsigned char x,unsigned char y,unsigned char j);

void Show_Lcd3(Uint16 i);
void Show_Lcd2(Uint16 i);
void Show_Lcd1(Uint16 i);
void LcdClearTxt( void );
void LcdClearTxt2( void );

//C类盲盒

void zl()
{
    show( 3,0,"识别完成");
    show( 1,1, "C");       //在12864的第1行第1列显示
       show(2,1,"类盲盒");
       show(0,2,"硬币数值:");
       show(0,3,"一元站立");

}

void cw()
{
    show( 3,0,"识别完成");
    show( 1,1, "C");       //在12864的第1行第1列显示
       show(2,1,"类盲盒");
       show(0,2,"硬币数值:");
       show(0,3,"一元倾斜");

}

void tcwyj()
{
    show( 3,0,"识别完成");
    show( 1,1, "C");       //在12864的第1行第1列显示
       show(2,1,"类盲盒");
       show(0,2,"硬币数值:");
       show(0,3,"填充物一元");

}

//B类盲盒

void yyswjx()
{
    show( 3,0,"识别完成");
    show( 1,1, "B");       //在12864的第1行第1列显示
       show(2,1,"类盲盒");
       show(0,2,"硬币数值:");
       show(0,3,"一元在上五角在下");

}

void yyxwjs()
{
    show( 3,0,"识别完成");
    show( 1,1, "B");       //在12864的第1行第1列显示
       show(2,1,"类盲盒");
       show(0,2,"硬币数值:");
       show(0,3,"一元在下五角在上");

}

void lgyj()
{
    show( 3,0,"识别完成");
    show( 1,1, "B");       //在12864的第1行第1列显示
       show(2,1,"类盲盒");
       show(0,2,"硬币数值:");
       show(0,3,"两个一角");

}

void wjsyjx()
{
    show( 3,0,"识别完成");
    show( 1,1, "B");       //在12864的第1行第1列显示
       show(2,1,"类盲盒");
       show(0,2,"硬币数值:");
       show(0,3,"五角在上一角在下");

}

void wjxyjs()
{
    show( 3,0,"识别完成");
    show( 1,1, "B");       //在12864的第1行第1列显示
       show(2,1,"类盲盒");
       show(0,2,"硬币数值:");
       show(0,3,"一角在上五角在下");

}

//A类盲盒

void Show_Lcd3(Uint16 i)
{
    show( 3,0,"识别完成");  //  LcdClearTxt();
    show( 1,1, "A");       //在12864的第1行第1列显示
    show(2,1,"类盲盒");
    show(0,2,"硬币数值:");
       show(0,3,"一角");

}

void Show_Lcd2(Uint16 i)
{
  //  LcdClearTxt();
    show( 3,0,"识别完成 ");
    show( 1,1, "A");       //在12864的第1行第1列显示
    show(2,1,"类盲盒");
    show(0,2,"硬币数值:");
    show(0,3,"五角");

}

void Show_Lcd1(Uint16 i)
{
    show( 3,0,"识别完成 ");
      show( 1,1, "A");       //在12864的第1行第1列显示
      show(2,1,"类盲盒");
      show(0,2,"硬币数值:");
        show(0,3,"一元");
}

//按键选择

void Al()
{
    show( 1,1, "A");       //在12864的第1行第1列显示
    show(2,1,"类盲盒");
}

void Bl()
{
     show( 1,1, "B");       //在12864的第1行第1列显示
     show(2,1,"类盲盒");
}

void Cl()
{
     show( 1,1, "C");       //在12864的第1行第1列显示
     show(2,1,"类盲盒");
}

void sbiez()
{
   // LcdClearTxt();
    show( 0,0,"有盲盒");
   // show( 3,0,"识别中");
    DELAY_US(1000000);//延迟100ms
  //  LcdClearTxt();
}

void wumh()
{
   LcdClearTxt2();
  // LCD_init();
    show( 0,0,"无盲盒");
}

/*------------------------------------------*/
/*形式参数:void                            */
/*返回值:void                              */
/*函数描述:初始化gpio端口               */
/*------------------------------------------*/
void Init_Port(void)
{
    EALLOW;
// 用户根据需要可以使能内部上拉或禁止.
// 其他不需要的行注释掉;
  //  SysCtrlRegs.PCLKCR3.bit.GPIOINENCLK = 1;// 开启GPIO时钟
    GpioCtrlRegs.GPAPUD.bit.GPIO0 = 0;    // 使能GPIO1 引脚内部上拉
    GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1;   // 禁止GPIO3 引脚内部上拉
/* 通过I/O功能选择寄存器配置通用I/O功能*/
    GpioCtrlRegs.GPAMUX1.all = 0x000000;   // 配置GPIO0-GPIO15为通用I/O口


/* 设置I/O口为输入引脚*/
    GpioCtrlRegs.GPADIR.all = 0x00FFF;// 配置GPIO1-GPIO11为输出引脚

// 每个输入口可以有不同的输入限定
   // a) 输入与系统时钟 SYSCLKOUT同步
   // b) 输入被指定的采样窗口限定
   // c) 输入异步 (仅对外设输入有效)
   GpioCtrlRegs.GPAQSEL1.all = 0x0000;    // GPIO0-GPIO15与系统时钟SYSCLKOUT 同步
//输出数据LCD_RS置1和LCD_EN清零
   GpioDataRegs.GPADAT.bit.GPIO0 = 1;
   GpioDataRegs.GPADAT.bit.GPIO1 = 0;
    EDIS;
}

/*--------------------------------------
;模块名称:LCD_write_command();
;功    能:LCD12864写指令函数
;参数说明:command为写命令参数
;-------------------------------------*/
void LCD_write_command(uchar command)
{
    RS=0;         //指令
    EN=1;          //允许
    DB=(command<<2)|0x0002;//赋值给D0-D7对应的GPIO4-GPIO11引脚
    DELAY_US(10000);
    EN=0;
    DELAY_US(100);
}

/*--------------------------------------
;模块名称:LCD_write_data();
;功    能:LCD12864写数据函数
;参数说明:dat为写数据参数
;-------------------------------------*/
void LCD_write_data(uchar dat)
{

    RS=1;         //指令
    EN=1;          //允许

    DB=(dat<<2)|0x0003;//赋值给D0-D7对应的GPIO4-GPIO11引脚
    DELAY_US(10000);
    EN=0;
    DELAY_US(100);
}

void LcdClearTxt( void )
{
     uchar i;
   //  LCD_write_command(0x30);      //8BitMCU,基本指令集合
     LCD_write_command(0x80);      //AC归起始位

     for(i=0;i<16;i++)
         LCD_write_data(0x20);
}

void LcdClearTxt1( void )
{
    DELAY_US(1000000);
     uchar i;
 //    LCD_write_command(0x30);      //8BitMCU,基本指令集合
     LCD_write_command(0x80);      //AC归起始位

     for(i=48;i<64;i++)
         LCD_write_data(0x20);
 //    DELAY_US(1000000);
}

void LcdClearTxt2( void )
{
    DELAY_US(1000000);
     uchar i;
 //    LCD_write_command(0x30);      //8BitMCU,基本指令集合
     LCD_write_command(0x80);      //AC归起始位

     for(i=0;i<64;i++)
         LCD_write_data(0x20);
 //    DELAY_US(1000000);
}

/*--------------------------------------
;模块名称:LCD_init();
;功    能:初始化LCD12864
;占用资源:--
;参数说明:--
;-------------------------------------*/
void LCD_init(void)
{
DELAY_US(100000);//延迟100ms
LCD_write_command(0x30);//功能设置
DELAY_US(200);//延迟200us
LCD_write_command(0x30);//功能设置
DELAY_US(200);//延迟200us
LCD_write_command(0x0c);//显示开关控制
DELAY_US(200);//延迟200us
LCD_write_command(0x01);//显示清除
DELAY_US(12000);//延迟12ms
LCD_write_command(0x06);//显示清除
DELAY_US(500);//延迟500us
}


void LCD12864SetAddress_f( unsigned char x, unsigned char y )   //地址转换
{
    unsigned char byAddress;
    switch( y )
    {
        case 0 :
            byAddress = 0x80 + x;
            break;
        case 1 :
            byAddress = 0x90 + x;
            break;
        case 2 :
            byAddress = 0x88 + x;
            break;
        case 3 :
            byAddress = 0x98 + x;
            break;
        default :
            break;
    }
    LCD_write_command( byAddress ) ;
}

void show(unsigned char x,unsigned char y,unsigned char *pData)
{
    LCD12864SetAddress_f( x, y );       //地址转换
    while( *pData != '\0' )
    {
        LCD_write_data( *pData );
        pData++;
        DELAY_US(10);
    }
}
void show1(unsigned char x,unsigned char y,unsigned char j)
{
    LCD12864SetAddress_f( x, y );       //地址转换
    if(j>0){
        LCD_write_data(j/10+0x30);
        LCD_write_data(j%10+0x30);
        DELAY_US(10);
    }
}


检测结果

盲盒识别装置

结果说明

       该项目所要实现的功能基本完成,A、B、C类均能检测。但仍有些许不足:在检测时需要固定位置,如果检测位置改变有可能会使结果不准确,这应该是因为改变了硬币跟涡流传感器之间的距离,从而使得ADC采样的结果发生了改变。

如需完整项目,请关注公众号:【电子设计开发】

  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值