极具创意的自动售货机设计方案推荐

更新时间:2021-06-30 02:38:47

概况

技术发明一直在改变人们的生活方式。自动售货机便是其中之一,在不需要工作人员或人工协助的情况下,它可以 24 小时向客户分发产品。整个售货过程都由机器自动完成,使人们在购买物品和交易方面更加便利。

使用涂鸦 LZ201 CAT1 模组,借助涂鸦 MCU SDK 低代码开发方式,开发者可以跟随本教程在涂鸦 IoT 平台上快速开发一款自动售货机产品原型。

物料清单

硬件 (8)软件 (2)
  • 74HC165

    数量:1

    八位并行输入,串行输出的移位寄存器,用于检测电机转动位置情况查看详情

  • 74HC595

    数量:2

    八位串行输入、并行输出的移位寄存器,用于提供输出各个电机的控制信号查看详情

  • FDS9945

    数量:10

    N 沟道 MOS 管,用于驱动电机查看详情

  • FDS9958

    数量:10

    P 沟道 MOS 管,用于驱动电机查看详情

  • LZ201-CN

    数量:1

    涂鸦 LZ201-CN Cat.1 模组,用于售货机和云平台的信息交互查看详情

  • STM32

    数量:1

    主控芯片,控制售货机正常工作查看详情

  • Motor

    数量:10

    减速电机,控制物品掉落

  • ST-LINK

    数量:1

    用于 STM32 微控制器的调试和编程。查看详情

步骤

  • 第 1 步:硬件设计

    整体硬件由供电单元、主控单元、电机驱控控制单元、电机到位检测单元、无线通讯单元和其他外设单元组成。具体如下图所示:
    frame

    供电单元

    本款自动售货机主要包含以下几个部件的供电:

    • 主电源:需要输入 24V 直流电作为主电源。该 24V 直流电可以直接接 MOS 管作为售货机中电机的输入电源。
    • 无线通信单元:供电电压为 4V,可以使用 LM2576 这款 DC-DC 稳压芯片将 24V 转换成 4V。LM2576 最大可驱动 3A 的负载,有优异的线性和负载调整能力,完全满足无线通信单元的需求。
    • 主控单元芯片:一般供电电压为 3.3V,可以采用 S-1206B33-U3T1G 这款 LDO 芯片将 4V 电压降到 3.3V。

    主控单元

    该单元采用 STM32F103RET6 作为主控芯片。该芯片是一款基于 ARM 架构的高密度性能 32 位微处理器,主频最大可支持 72MHZ,多达 11 个定时器,内部集成了复位电路、低电压检测、调压器和精确的 RC 振荡器电路。更多关于该芯片的信息,请参考 STM32F103RE 芯片介绍;更多关于该芯片的数据规格,请参考 STM32F103RE 数据规格书。

    STM32

    电机驱动控制单元

    控制单元组成
    该单元采用 74HC595 (74HC595 数据规格书)八位串行输入、并行输出的移位寄存器用于提供输出各个电机的控制信号。
    74HC595

    每个电机的两端各接一个 FDS9945 N 沟道 MOS 管(FDS9945 数据规格书)和一个 FDS9958 P 沟道 MOS 管(FDS9958 数据规格书),其中

    • FDS9958 的源极接 24V,栅极接信号线,漏极接电机的正极。
      FDS9958
    • FDS9945 的源极接 GND,栅极接信号线,漏极接电机的负极。
      FDS9945
      当 FDS9945 和 FDS9958 两个 MOS 管同时导通的时候,电机便可转动。

    组件数量

    • 信号线:需要 11 条。本款自动售货机总共有 10 个货道,需采用 10 个电机,理论上总共需要 20 条信号线。为了节约资源,可以将所有电机的负极连接到同一个 FDS9945 的漏极,这样可以将信号线减少至 11 条。
    • 芯片:需要 2 颗串联。一颗 74HC595 只支持 8 位串入并出,为了满足 11 位数据需求,可以将两颗 74HC595 串联,这样最多可支持 16 位信号数据。

    电机到位检测单元

    该单元采用 74HC165 (74HC165 数据规格书)八位并行输入,串行输出的移位寄存器用于检测电机转动位置情况。
    74HC165

    当电机转动到一定位置时,到位开关输出低电平信号给 74HC165 并行输入脚。主控单元读取 74HC165 串行输出脚,检测到某一位低电平时,将对应位的电机停转,避免多次掉落物品。

    由于 I/O 口资源有限,开发者可以让 10 个电机共用一个到位开关。

    无线通信单元

    该单元主要用于售货机和云平台的信息交互,可以采用涂鸦 LZ201-CN CAT1 模组。这是由涂鸦智能开发的一款 LTE Cat.1 蜂窝网络模组。关于该模组的数据规格,请参考 LZ201-CN CAT1 模组规格书。

    LZ201

    模组主要由一个高集成度的 LTE Cat.1 芯片 UIS8910DM 及其外围电路构成,其中:

    • 内置了 LTE Cat.1 网络通信协议栈和丰富的库函数。
    • 内嵌了 Cortex A5 应用处理器和 Cat.1bis 调制解调器。
    • 集成了 64MB Flash,128 MB SRAM。
    • 支持 USB、UART、SDIO、SPI、I2C、I2S 和 ADC 等接口。
    • 支持显示屏、摄像头、键盘矩阵、麦克风、喇叭、充电、MicroSD 卡和 USIM 卡等外设。

    开发者只需要通过移植涂鸦 MCU SDK,即可以实现对 App、云、售货机三者的通信控制。当然,这部分也可以用 WB3S Wi-Fi 模组或者其他通信模组来代替。

    其他外设单元

    该单元的外设,可以根据开发者自身需求自行设计添加,比如

    • 增加网络指示灯,用于表示当前网络状态。
    • 增加电源指示灯,用于表示当前电源状态。
    • 增加温度传感器,用于检测售货机内部温度。
    • 增加掉落检测装置,用于检测物品是否确实掉落,形成反馈。
    • 增加多路按键,用于需要实现某种特定的按键功能。
    • 增加 RS-485 通信接口,用于售货机与其他 RS-485 设备通信,增强联动性。
    • 增加液晶显示单元,用于人机交互。

    完成以上硬件的设计后,可以根据结构尺寸,设计对应的 PCB,并且完成焊接,测试等工作。下图为参考示例:
    PCB

  • 第 2 步:在涂鸦 IoT 平台上创建产品

    1. 登录 涂鸦IoT平台,单击 创建产品。

    2. 在 标准类目 导航栏中,选择 户外出行 > 智能电动车。
      选择品类

    3. 选择 自定义方案 中的 智能电动车 方案。

    4. 输入产品名称,产品型号(可选),选择通信协议为 LTE Cat1,并单击 创建产品。
      智能电动车

    5. 在功能定义选项中,根据自身需要选择功能。
      标准功能

    6. (可选)若标准功能中缺少您需要的功能,可在 自定义功能 区域单击 添加功能,根据实际需求进行配置。
      例如,本次可以添加两个 DP 点,一个用于指示平台下发的数据,一个用于指示自动售货机上报的数据。
      自定义功能

    7. 在 设备面板 页签中选择想要的面板,开始调试时可选择开发调试面板,后面可根据自身需要自由配置面板。
      设备面板

    8. 在 硬件开发 页签中,选择 涂鸦标准模组MCU SDK开发,并选择 LZ201-CN LTE Cat.1模组。
      硬件开发

    9. 上述操作完成之后,单击 下载全部 下载所有开发需要用到的资料,开始嵌入式程序的开发。

  • 第 3 步:嵌入式开发

    开发者在获取了 MCU SDK 开发包之后,需要将 SDK 文件添加到自己的工程中,根据编译中的错误信息提示逐个修改。

    由于 MCU 和选择的 PIN 脚不一定相同,以下为一些驱动程序,仅供参考。完整示例程序请参考 tuya-iotos-embeded-mcu-demo-4g-vending-machine。

    串口配置

     /***********************************************************
     *   Function:  USART3_Init
     *   Input:     uint32_t pclk2,uint32_t bound
     *   Output:    none
     *   Return:    none
     *   Notice:    串口初始化
     ***********************************************************/
    void USART3_Init(uint32_t pclk2,uint32_t bound)
    {  	 
    	float temp;
    	uint16_t mantissa;
    	uint16_t fraction;	   
    	temp=(float)(pclk2*1000000)/(bound*16);//得到USARTDIV
    	mantissa=temp;				 //得到整数部分
    	fraction=(temp-mantissa)*16; //得到小数部分	 
    	mantissa<<=4;
    	mantissa+=fraction; 
    
    	RCC->APB2ENR|=1<<3;   //使能PORTB口时钟  
    	RCC->APB1ENR|=1<<18;  //使能串口3时钟 
    	GPIOB->CRH&=~(0xf<<8|0xf<<12);
    	GPIOB->CRH|=0X0B<<8|8<<12;//IO状态设置	  
    	GPIOB->ODR|=1<<11;
    
    	RCC->APB1RSTR|=1<<18;   //复位串口3
    	RCC->APB1RSTR&=~(1<<18);//停止复位	   	   
    	//波特率设置
    	USART3->BRR=mantissa; // 波特率设置	 
    	USART3->CR1|=0X200C;  //1位停止,无校验位.					  
    	USART3->CR1|=1<<8;    //PE中断使能
    	USART3->CR1|=1<<5;    //接收缓冲区非空中断使能	    	
    	MY_NVIC_Init(1,2,USART3_IRQn,2);//组2  			  
    } 	
    

    串口接收数据

     /***********************************************************
     *   Function:  USART3_IRQHandler
     *   Input:     none
     *   Output:    none
     *   Return:    none
     *   Notice:    串口中断服务函数,接收一个字节数据
     ***********************************************************/
    void USART3_IRQHandler(void)
    {
    	if(USART3->SR&(1<<5))//接收到数据
    	{
    		uart_receive_input((unsigned char)(USART3->DR));
    	}
    } 	
    

    串口发送数据

     /***********************************************************
     *   Function:  Uart3_PutChar
     *   Input:     uint8_t
     *   Output:    none
     *   Return:    uint8_t
     *   Notice:    发送一个字节数据,并返回发送是否超时的状态
     ***********************************************************/
    uint8_t Uart3_PutChar(uint8_t data)
    {
    	uint8_t ret=1;
    	uint16_t timeout=0x8000;
    
    	USART3->DR = data;
    	while((USART3->SR&1<<6)!=1<<6)//等待发送完毕
    	{
    		timeout--;
    		if( 0 == timeout )
    		{
    			ret = 1;
    			break;
    		}
    	}
    
    	if( 0 != timeout )
    	{
    		ret = 0;
    	}
    	return ret;
    }
    /**
     * @brief  串口发送数据
     * @param[in] {value} 串口要发送的1字节数据
     * @return Null
     */
    void uart_transmit_output(u8 value)
    {
        //#error "请将MCU串口发送函数填入该函数,并删除该行"
    	Uart3_PutChar(value);
    /*
        //Example:
        extern void Uart_PutChar(u8 value);
        Uart_PutChar(value);                                    //串口发送函数
    */
    }
    

    读取 74HC165 数据

     /***********************************************************
     *   Function:  HC165In
     *   Input:     none
     *   Output:    none
     *   Return:    uint8_t
     *   Notice:    读取 74HC165 的八个引脚状态,并返回对应的八位数据
     ***********************************************************/
    uint8_t HC165In(void)
    {
    	uint8_t i,dat=0;
    	CP_SET;
    	PL_RESET;
    	delay_us(10);
    	PL_SET;	
    	delay_us(10);
    	for(i=0;i<8;i++)
    	{
    		dat=dat<<1;
    		if(ODATA==1)
    		{
    			dat=dat+1;
    		}
    		CP_RESET;
    		delay_us(10);		
    		CP_SET;
    		delay_us(10);		
    	}
    	CP_RESET;
    	return dat;
    }
    

    发送 74HC595 数据

    本函数通过 74HC595 输出不同的电平信号给 N 沟道 MOS 管和 P 沟道 MOS 管,由此实现电机转动控制。

     /***********************************************************
     *   Function:  HC595Send
     *   Input:     uint16_t
     *   Output:    none
     *   Return:    none
     *   Notice:    将 16 位的数据通过两个 74HC595 引脚输出
     ***********************************************************/
    void HC595Send(uint16_t data)
    {
        uint8_t j;
        LOCK_RESET;
        delay_us(10);
        for (j = 16; j > 0; j--)
        {
    		SHIFT_RESET;
            delay_us(10);
    
            if(data & 0x8000)
            {
                INDATA_SET;
            }
            else
            {
                INDATA_RESET;
            }
    
            delay_us(10);
            data <<= 1;
            SHIFT_SET;
            delay_us(10);
        }
        LOCK_SET;
        delay_us(10);
    }
    

    例如,我们想让第 X 个(0≤X≤9)电机转动使物品掉落,只要调用

    HC595Send(1<<X||1<<10);
    

    其中 1<<X 表示给第 X 个 P 沟道 MOS 管高电平信号;1<<10 表示给 N 沟道 MOS 管高电平信号。

    说明:由于电路中所有的 N 沟道 MOS 管共用了一个信号口,所以调用时固定为 1<<10。

    同理,我们想让电机停止转动,只需要调用

    HC595Send(0);
    

    由于不同电路设计差异,函数中的实际参数会有所不同,需要根据实际硬件来处理。

    下发的串口事件处理

    下发数据的长度为 6 个字节,可以约定第 0 位为货道号,第 1 位为物品序号,后面 4 位为订单号。

    开发者也可以根据自己的需要,规定通讯协议。以下程序,仅供参考。

    /*****************************************************************************
    函数名称 : dp_download_m_num_handle
    功能描述 : 针对DPID_M_NUM的处理函数
    输入参数 : value:数据源数据
            : length:数据长度
    返回参数 : 成功返回:SUCCESS/失败返回:ERROR
    使用说明 : 只下发类型,需要在处理完数据后上报处理结果至app
    *****************************************************************************/
    static unsigned char dp_download_m_num_handle(const unsigned char value[], unsigned short length)
    {
        //示例:当前 DP 类型为 RAW
        unsigned char ret;
    		const unsigned char error[6]={"ERROR1"};
        /*
        //RAW类型数据处理
        
        */
    		if((length==6)&&(value[0]<11)&&(value[1]<10))
    		{
    			IoT_receive[Q_U3.rear].data[0]=value[0];
    			IoT_receive[Q_U3.rear].data[1]=value[1];
    			IoT_receive[Q_U3.rear].data[2]=value[2];
    			IoT_receive[Q_U3.rear].data[3]=value[3];
    			IoT_receive[Q_U3.rear].data[4]=value[4];
    			IoT_receive[Q_U3.rear].data[5]=value[5];
    			F_TASK_MOTOR_OPEN++;
    			rear_inc(&Q_U3);
    		}
    		else
    		{
    			mcu_dp_raw_update(DPID_R_NUM,error,6);
    		}
        //处理完 DP 数据后应有反馈
        ret = mcu_dp_raw_update(DPID_M_NUM,value,length);
        if(ret == SUCCESS)
            return SUCCESS;
        else
            return ERROR;
    }
    

    编译与下载

    程序编写完成之后,单击 Build 并根据软件提示修改相关错误或者警告信息。

    待程序编译通过之后,就可以下载到开发板中进行调试和测试。

    STM32 支持 ST-Link ,J-Link 等工具下载,这里推荐 ST-Link,引脚连接方式如下:

    ST-Link STM32F103
    SWCLK SWCLK
    SWDIO SWDIO
    NRST NRST
    VDD VDD
    GND GND

    连接无误后,单击 Download 把程序下载到开发板中。

  • 第 4 步:操作演示

    打开涂鸦智能 App,在 Item 输入栏中输入 XXYYZZZZZZZZ,其中

    • XX 表示第 X 个货道;
    • YY表示货道上剩余的物品数量;
    • ZZZZZZZZ 为订单号(可以为任意值)。

    如,输入0104aabbccdd,表示第 1 个货道剩余 4 个物品,订单号为 aabbccdd。

    数据发送成功后,可以看到电机开始转动,当物品掉落后,电机停止转动。

    注意:当前货道的物品剩余量务必要和输入物品号相同,比如第 1 个货道有4个物品时,只有输入 0104 才会有效,输入 0105 或 0103 等其他值,电机都是不会转动的。

    App 操作

小结

涂鸦物联网开发平台为开发者提供了便捷的 IoT 开发工具与服务,助力开发者更高效的完成设备接入,并为开发者提供物联网应用开发及场景服务能力。