得益于创新技术,我们的生活方式变得更加高效和智能。简单的自动售货机是现代的伟大发明之一。这是供应商使用的一种高效且低成本的方法,可以 24/7 全天候向最终用户交付产品。
本教程将向您展示如何基于涂鸦 LZ201 Cat.1 模块和 MCU SDK 以低代码方式制作自动售货机原型。
硬件由电源单元、单片机单元(MCU)、电机驱动与控制单元、电机到位检测单元、无线通信单元等外围单元组成。框图如下。
三台机组需要供电:
STM32F103RET6 是一款 32 位高密度性能 MCU。它采用 ARM Cortex-M3 架构,工作频率为 72 MHz。它具有 11 个定时器和一个内部复位电路、电压检测器、电压调节器和微调 RC 振荡器。有关产品和数据表的更多信息,请分别参见STM32F103RE 概述和STM32F103RE 数据表。
元器件74HC595是一个8位串行输入并行输出移位寄存器,用于向电机输出控制信号。( 74HC595 数据表)
将电机的每个端子分别连接到 FDS9945 n 沟道 MOSFET(FDS9945 数据表)和 FDS9958 p 沟道 MOSFET(FDS9958 数据表)。连接方法如下:
当 FDS9945 和 FDS9958 都处于导通状态时,电机可以旋转。
元件数量
74HC165是一个8位并行输入和串行输出移位寄存器,用于确定电机旋转方向。( 74HC165 数据表)
当电机旋转到指定位置时,限位开关向74HC165移位寄存器上的并行输入引脚输出一个低电平信号。MCU 可以从 74HC165 上的串行输出引脚读取数据。当单片机检测到某个位的低电平时,会停止相应的电机。
由于我们没有足够的 I/O,10 个电机可以共享同一个限位开关。
无线通信单元
涂鸦专有的 LZ201-CN Cat.1 蜂窝模块可以在自动售货机和涂鸦 IoT Cloud 之间建立通信。有关详细信息,请参阅LZ201-CN Cat.1 模块数据表。
该模块由高度集成的LTE Cat.1芯片UIS8910DM和外围电路组成。它的特点:
只需移植涂鸦MCU SDK,即可实现自动售货机联网云端,通过APP实现设备控制。您还可以选择 WB3S Wi-Fi 模块或其他通信协议的模块。
其他外围设备
下面列出了一些可选外设:
完成硬件设计后,即可进行 PCB 布局、焊接和测试。下图显示了我们完成的PCB。
1.登录涂鸦物联网平台,点击创建。
2.找到标准品类,点击户外出行>智能电动车。
3. 单击自定义解决方案选项卡上的智能电动汽车。
4.填写基本信息,协议选择LTE Cat.1 ,点击创建。
5.根据需要添加标准功能。
6.(可选)如果没有找到需要的功能,找到自定义功能,点击+添加创建功能。我们创建两个功能:一个是Item ,从云端获取数据,另一个是Inventory ,发送数据到云端.
7.单击设备面板选项卡并选择一个面板。为了方便测试,您可以选择调试面板,稍后再更改。
8.单击硬件开发选项卡。选择涂鸦标准模组MCU SDK ,然后选择LZ201-CN LTE Cat.1 Module 。
9.向下滚动页面并找到下载文档。单击全部下载以获取嵌入式编程的所有文件。
将 SDK 中的文件添加到您的项目中,并根据错误消息更正您的代码。
您可能会使用不同的 MCU,因此以下驱动程序供您参考。完整示例代码见tuya-iotos-embeded-mcu-demo-4g-vending-machine 。
配置串口
/***********************************************************
* Function: USART3_Init
* Input: uint32_t pclk2,uint32_t bound
* Output: none
* Return: none
* Notice: USART initialization
***********************************************************/
void USART3_Init(uint32_t pclk2,uint32_t bound)
{
float temp;
uint16_t mantissa;
uint16_t fraction;
temp=(float)(pclk2*1000000)/(bound*16);// Get USARTDIV.
mantissa=temp; // Get the integer part.
fraction=(temp-mantissa)*16; // Get the decimal part.
mantissa<<=4;
mantissa+=fraction;
RCC->APB2ENR|=1<<3; // Enable the clock for PORTB.
RCC->APB1ENR|=1<<18; // Enable the clock for USART3.
GPIOB->CRH&=~(0xf<<8|0xf<<12);
GPIOB->CRH|=0X0B<<8|8<<12;// // Configure GPIO state.
GPIOB->ODR|=1<<11;
RCC->APB1RSTR|=1<<18; // Reset USART3.
RCC->APB1RSTR&=~(1<<18);// Stop reset.
// Set baud rate.
USART3->BRR=mantissa; // Set baud rate.
USART3->CR1|=0X200C; // No parity, and 1 stop bit. USART3->CR1|=1<<8; // Enable PE interrupt.
USART3->CR1|=1<<5; // Enable the RXNE interrupt.
MY_NVIC_Init(1,2,USART3_IRQn,2);// Group 2
}
接收串行数据
/***********************************************************
* Function: USART3_IRQHandler
* Input: none
* Output: none
* Return: none
* Notice: USART interrupt handler function. Receive one byte of data in interrupt mode.
***********************************************************/
void USART3_IRQHandler(void)
{
if(USART3->SR&(1<<5))// Received data.
{
uart_receive_input((unsigned char)(USART3->DR));
}
}
发送串口数据
/***********************************************************
* Function: Uart3_PutChar
* Input: uint8_t
* Output: none
* Return: uint8_t
* Notice: Send one byte of data to check whether a timeout has happened.
***********************************************************/
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)// Wait until the transmission is completed.
{
timeout--;
if( 0 == timeout )
{
ret = 1;
break;
}
}
if( 0 != timeout )
{
ret = 0;
}
return ret;
}
/**
* @brief Send serial data
* @param[in] {value} The one byte of data to be sent by UART.
* @return Null
*/
void uart_transmit_output(u8 value)
{
//#error "Specify the UART transmission function and delete this line"
Uart3_PutChar(value);
/*
// Example:
extern void Uart_PutChar(u8 value);
Uart_PutChar(value); // UART transmission function
*/
}
通过74HC165移位寄存器读取数据
/***********************************************************
* Function: HC165In
* Input: none
* Output: none
* Return: uint8_t
* Notice: Read values of the eight pins of 74HC165 and return 8-bit data.
***********************************************************/
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沟道MOSFET和p沟道MOSFET输出不同电平的信号。这样,我们可以控制电机旋转。
/***********************************************************
* Function: HC595Send
* Input: uint16_t
* Output: none
* Return: none
* Notice: Output 16-bit data through pins of the two 74HC595 shift registers.
***********************************************************/
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<1||<<10);
1<表示高电平信号输出到第 X 个 p 沟道 MOSFET。<>
注意:电路中的所有 n 沟道 MOSFET 使用相同的信号引脚,因此1<<10
是固定的。
要停止电机旋转,我们可以调用
HC595Send(0);
该功能的参数因电路设计而异。根据您的硬件调整它们。
处理来自云端的命令
来自云端的数据长度为 6 个字节。我们可以指定位 0 为产品托盘编号,位 1 为产品编号,位 2 至位 5 为订单编号。
您可以根据需要指定通信协议。以下程序供您参考。
/*****************************************************************************
Function name: dp_download_m_num_handle
Feature description: a processing function for DPID_M_NUM.
Input parameters: value indicates the data source
: length: the length of the data
Return parameters: Return SUCCESS on success, and ERROR on failure
Instruction: For the send-only data point, the results must be sent to the cloud after the operation is completed.
*****************************************************************************/
static unsigned char dp_download_m_num_handle(const unsigned char value[], unsigned short length)
{
// Example: This is a data point of raw type.
unsigned char ret;
const unsigned char error[6]={"ERROR1"};
/*
// Process data of raw type.
*/
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);
}
// Return the result of the operation.
ret = mcu_dp_raw_update(DPID_M_NUM,value,length);
if(ret == SUCCESS)
return SUCCESS;
else
return ERROR;
}
编译下载
编程完成后,如果出现任何错误,请单击构建并更正您的代码。
然后,将程序下载到开发板上进行测试。
STM32 支持 ST-Link 和 J-Link 等调试器。建议使用 ST-Link。下表概述了要连接的引脚:
将 ST-Link 连接到您的开发板后,单击下载。
第 4 步:演示
打开涂鸦智能应用,点击您为自动售货机选择的面板。找到创建的数据点Item ,输入XXYYZZZZZZZZ格式的值进行测试。
XX
表示第 X 个产品托盘。
YY
表示托盘上的剩余产品。
ZZZZZZZZ
表示订单号。它可以是任何值。
例如输入
0104aabbccdd
,表示第一个托盘现在有四个产品,订单号是aabbccdd
。
数据发送后,您会发现电机开始转动,产品掉落后停止。
注意:库存值必须与项目匹配。例如,如果第一个托盘有四个产品,则有效值为0104
。无效值如0105
和0103
不能使电机旋转。
概括
涂鸦物联网平台提供便捷的物联网开发工具和服务,旨在让您的物联网项目更轻松、更高效。查看并发现更多很棒的想法。
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
全部0条评论
快来发表一下你的评论吧 !