2.1、下位机
A、读码模块:读取条形码数据;
B、按键:区分出/入库操作,每扫一次码就按一次键;
C、OLED显示屏:下位机操作期间的信息提示;
D、Arduino:接受输入数据——条形码、按键,一要将数据发送给OLED显示屏显示,二要发送给WiFi模块,以保证网络传输的数据基础。
D、WiFi模块:ESP8266模块,接收来自Arduino的数据,整合成Json格式,作为MQTT发布者向服务器发送该Json数据。
2.2、上位机
A、MQTT服务器:接收发布者的信息,接收订阅者的订阅请求。
B、服务器后台程序:即MQTT订阅者程序,实现连接MQTT服务器;接入服务器数据库;订阅、取出信息,并根据信息具体数值采用SQL命令更新数据库。
提示:程序中有些头文件,需要在Arduino IAE>>工具>>管理库中安装相应的库。
从上一张图可以看出,Arduino需要将接收到的条形码数据、按键数据发送到两个方向,一是OLED显示屏,二是WiFi模块。主要实现以下功能:
A、接收条形码数据;
B、接收按键数据;
C、发送给OLED显示屏进行显示;
D、发送给ESP8266模块。
具体代码如下:
#include
SoftwareSerial softSerial(11, 10);
#include
#include
#include
LCD_SSD1306 lcd; /* for SSD1306 OLED module */
char a[100];
int num;
bool begin_flag = 0;
bool display_flag = 0;
#define key_add 12
#define key_reduce 5
void setup() {
Serial.begin(9600);
softSerial.begin(9600);
pinMode(key_add, INPUT_PULLUP);
pinMode(key_reduce, INPUT_PULLUP);
lcd.begin();
lcd.setCursor(0, 0);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print("Waiting.......");
}
void loop() {
read_code();
key_down();
while (Serial.available()) {
Serial.read();
};
}
void read_code() {
while (softSerial.available() > 0) {
delay(1);
a[num] = softSerial.read();
num++;
begin_flag = 1;
display_flag = 1;
}
if (display_flag == 1) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print("Card NUM:");
lcd.setCursor(0, 2);
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.print(a);
display_flag = 0;
}
}
void key_down() {
if (begin_flag) {
if (digitalRead(key_add) == 0) {
delay(10);
if (digitalRead(key_add) == 0) {
display_flag = 0;
Serial.print("A");
for (int i = 0; i < num; i++) {
Serial.print(a[i]);
}
Serial.println();
lcd.clear();
lcd.setCursor(0, 0);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print("Card NUM:");
lcd.setCursor(0, 2);
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.print(a);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.setCursor(0, 4);
lcd.print("OPerMode:");
lcd.setCursor(80, 4);
lcd.print(1);
begin_flag = 0;
num = 0;
memset(a, 0, sizeof(a));
while (!digitalRead(key_add));
}
}
else if (digitalRead(key_reduce) == 0) {
delay(10);
if (digitalRead(key_reduce) == 0) {
display_flag = 0;
Serial.print("B");
for (int i = 0; i < num; i++) {
Serial.print(a[i]);
}
Serial.println();
lcd.clear();
lcd.setCursor(0, 0);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.print("Card NUM:");
lcd.setCursor(0, 2);
lcd.setFontSize(FONT_SIZE_SMALL);
lcd.print(a);
lcd.setFontSize(FONT_SIZE_MEDIUM);
lcd.setCursor(0, 4);
lcd.print("OPerMode:");
lcd.setCursor(80, 4);
lcd.print(0);
begin_flag = 0;
num = 0;
memset(a, 0, sizeof(a));
while (!digitalRead(key_reduce));
}
}
}
}
程序烧写进Arduino开发板上。
实现以下功能:
A、接入WiFi环境;
B、连接MQTT服务器;
C、接收来自Arduino的数据;
D、将数据整合成Json格式;
E、将Json数据发送给MQTT服务器;
具体代码如下:
#include
#include
#include
#include
const char *ssid = "Monica";
const char *password = "12345678";
WiFiClient espClient;
PubSubClient client(espClient);
char Barcode[30];
char OperMode[1];
bool update_flag = 0;
int num;
void reconnect()
{
while (!client.connected())
{
Serial.print("Attempting MQTT connection...");
if (client.connect("mybrokerClient", "admin", "admin"))
{
Serial.println("connected");
}
else
{
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
char arr[length];
for (int i = 0; i < length; i++) {
arr[i] = (unsigned char)payload[i];
Serial.print(arr[i]);
}
arr[length] = '\0';
}
void setup()
{
Serial.begin(9600);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
client.setServer("192.168.0.105", 61613);
client.setCallback(callback);
}
void loop()
{
if (!client.connected())
{
reconnect();
}
client.loop();
while (Serial.available() > 0) {
delay(100);
char i = Serial.read();
if (i == 'A') {
OperMode[0] = 1;
update_flag = 1;
memset(Barcode, 0, sizeof(Barcode));
while (Serial.available()) {
char end_num = Serial.read();
if (end_num != 0x0d) {
Barcode[num] = end_num;
num++;
}
else if (end_num == 0x0d) {
if (Serial.read() == 0x0a) {
num = 0;
}
}
}
}
else if (i == 'B') {
OperMode[0] = 0;
update_flag = 1;
memset(Barcode, 0, sizeof(Barcode));
while (Serial.available()) {
char end_num = Serial.read();
if (end_num != 0x0d) {
Barcode[num] = end_num;
num++;
}
else if (end_num == 0x0d) {
if (Serial.read() == 0x0a) {
num = 0;
}
}
}
}
}
StaticJsonBuffer<300> JSONbuffer;
JsonObject& JSONencoder = JSONbuffer.createObject();
JSONencoder["Barcode"] = Barcode;
JSONencoder["OperMode"] = OperMode[0];
char JSONmessageBuffer[100];
//将JSON消息打印到char缓冲区
JSONencoder.printTo(JSONmessageBuffer, sizeof(JSONmessageBuffer));
if (update_flag == 1) {
client.publish("itemId", JSONmessageBuffer);
Serial.println("Message:");
Serial.println(JSONmessageBuffer);
Serial.println("Sending message to MQTT topic..");
update_flag = 0;
}
delay(10);
}
烧写进ESP8266模块,Arduino IDE>>工具>>开发板,选择“NodeMCU 0.9 (ESP-12 Module)”。
提示:ESP8266模块可接串口线,在Arduino IDE>>工具>>串口监视器 查看程序运行状态。
搭建MQTT服务器,参考文章:https://blog.csdn.net/qq_40384309/article/details/106870359
程序运行环境:nodejs;
nodejs安装教程:
程序主要实现以下功能:
A、接入服务器数据库;
C、连接MQTT服务器;
D、向MQTT服务器订阅主题,获取Json数据;
E、取出Json中的数据,根据其值分别进行具体的更新操作。
具体代码如下:
/*连接MySQL*/
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : 'rxe519772.',
port : '3306',
database : 'warehouse'
});
/*接收MQTT协议数据*/
var mqtt = require('mqtt')
var fs = require('fs')
var client = mqtt.connect('mqtt://192.168.0.105:61613',
{username:"admin",password:"admin"})
//成功连接服务器并订阅主题
client.on('connect', function () {
console.log("正在订阅");
client.subscribe('itemId');
console.log("订阅完成");
})
//收到来自topic的消息
client.on('message', function (topic, message) {
switch (topic){
case "itemId":
console.log("message:"+message);
var messageObj = JSON.parse(message);
console.log("OperMode:"+messageObj["OperMode"]);
if(messageObj["OperMode"]==0){
var addSql = "UPDATE tb_item set num=num-1 WHERE barcode=?";
connection.query(addSql,messageObj["Barcode"],function (err,result) {
if(err){
console.log('[UPDATE ERROR] - ',err.message);
return;
}
})
}else
if(messageObj["OperMode"]==1){
var addSql = "UPDATE tb_item set num=num+1 WHERE barcode=?";
connection.query(addSql,messageObj["Barcode"],function (err,result) {
if(err){
console.log('[UPDATE ERROR] - ',err.message);
return;
}
})
}
break;
}
})
在命令行窗口采用nodejs运行:node warehousePLC.js