一、项目介绍
随着智能物联网技术的不断发展,人们的生活方式和消费习惯也正在发生改变。如今越来越多的人习惯于在线购物、自助购物等新型消费模式,因此智能零售自助柜应运而生。
本项目设计开发一款基于STM32主控芯片的智能零售自助柜,通过重力传感器监测货柜内商品重量变化,并通过WiFi通信模块与手机端实现交互。用户可以通过输入账号密码,柜门自动打开,用户自取商品后关闭柜门,柜门锁定,系统根据重量变化判断用户拿取的商品并从账户自动扣费。同时,用户也可以通过手机端查看消费流水、商品库存,并进行补货和充值等操作。
智能零售自助柜的应用场景非常广泛,可以应用于商场、超市、酒店、机场、车站等各类场景。通过自助购物,可以提高消费者的消费体验和购物效率,同时也降低了商家的人力成本和物流成本。
二、设计思路
【1】功能细节总结
(1)ESP8266配置成AP+TCP服务器模式与手机APP连接。
(2)手机APP可以完成用户的注册,充值功能,然后通过连接货柜将数据同步到货柜的存储芯片上(W25Q64-FLASH保存数据)。
(3)手机APP连接货柜之后,可以拉取数据显示,了解货柜现在的物品哪些已经售卖出去,哪些还没有售卖。,每个物品是放在一个货柜格子里,透明玻璃可以查看到物品。
【2】硬件选型
- 主控芯片:STM32F103RCT6是一款主流的32位ARM Cortex-M系列微控制器,具有高性能、低功耗和易于开发等特点,因此被选择作为该系统的主控芯片。
- 重力传感器:HX711重力传感器模块采用24位高精度芯片,能够精确测量重量,适用于该系统中货柜内商品的重量监测。
- SG90舵机:该系统需要控制柜门的打开和关闭,因此使用舵机来实现柜门控制。
- 矩阵键盘:用户需要输入账号密码进行登录,因此使用矩阵键盘作为输入设备。
- 显示屏:OLED显示屏具有低功耗、高对比度、快速响应等特点,适用于该系统中的桌面显示界面。
- WiFi模块:ESP8266-WIFI模块是一款成本低、体积小、性能稳定的WiFi通信模块,适合在该系统中与手机APP进行无线通信。
【2】程序设计思路
- 初始化系统,包括各个外设的初始化,如WiFi模块、重力传感器HX711模块、矩阵键盘等;
- 用户输入账号密码,判断是否为有效用户;
- 根据重力传感器读取货柜内商品重量,判断用户拿取的商品并从账户自动扣费;
- 控制柜门打开和关闭,同时显示屏上显示相关提示信息;
- 同步数据到手机APP。
【3】设备操作流程
- 用户输入账号密码,系统进行验证,判断是否为有效用户;
- 如果验证通过,屏幕上显示“登录成功”,并显示货柜内商品列表和对应价格;
- 用户选择需要购买的商品,系统根据重力传感器读取货柜内商品重量,并判断用户拿取的商品并从账户自动扣费;
- 系统控制电磁锁或舵机将柜门打开,用户自取商品后关闭柜门;
- 重力传感器监测到货柜内重量变化,系统自动判断用户拿取的商品种类和数量,并在显示屏上显示相关提示信息,如显示扣费金额;
- 控制柜门锁定,确保商品安全,同时在显示屏上显示“门已锁定”等相关提示信息;
- 同步扣费记录和商品库存信息到手机APP,以便用户查看消费流水和进行补货等操作。
- 如需要充值,用户可以在手机APP上进行余额充值操作。
三、代码实现
【1】OLED显示屏驱动代码
下面是OLED显示屏的测试代码。使用的SPI接口的OLED显示屏。
#include "stm32f10x.h"
#include "OLED.h" // OLED驱动库头文件
void OLED_ShowString(uint8_t x, uint8_t y, uint8_t *str)
{
uint8_t i = 0;
while(str[i] != '\\0'){
if(x > OLED_WIDTH - 8){ // 满行自动换行
x = 0;
y++;
}
OLED_ShowChar(x, y, str[i]); // 显示单个字符
x += 8; // 水平方向上的下一个字符
i++;
}
}
void OLED_SPI_SendByte(uint8_t data)
{
while(SPI_I2S_GetFlagStatus(OLED_SPI_PORT, SPI_I2S_FLAG_TXE) == RESET); // 等待发送缓冲区空
SPI_I2S_SendData(OLED_SPI_PORT, data); // 通过SPI发送数据
}
void OLED_WriteCmd(uint8_t cmd)
{
OLED_DC_Clr(); // 将DC置为0,表示发送命令
OLED_CS_Clr(); // 将CS置为0,选中OLED芯片
OLED_SPI_SendByte(cmd); // 发送命令
OLED_CS_Set(); // 将CS置为1,取消OLED芯片选中
}
void OLED_WriteData(uint8_t data)
{
OLED_DC_Set(); // 将DC置为1,表示发送数据
OLED_CS_Clr(); // 将CS置为0,选中OLED芯片
OLED_SPI_SendByte(data); // 发送数据
OLED_CS_Set(); // 将CS置为1,取消OLED芯片选中
}
int main(void)
{
uint32_t i;
// 初始化SPI接口
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // 打开SPI1时钟
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // 设置SPI工作模式
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; // 数据位宽8bit
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; // 时钟极性为低电平
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // 时钟第一个边沿采样
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; // 软件控制CS信号
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; // 预分频系数为256
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // MSB先行
SPI_InitStructure.SPI_CRCPolynomial = 7; // CRC校验值
SPI_Init(SPI1, &SPI_InitStructure);
SPI_Cmd(SPI1, ENABLE); // 使能SPI1
// 初始化OLED显示屏
OLED_Init(); // OLED初始化
// 显示数字
char str[] = "1234567890";
OLED_ShowString(0, 0, (uint8_t *)str); // 在(0,0)坐标处显示字符串
while(1){
for(i = 0; i < 10000000; i++); // 延时等待
}
}