读码模块+Arduino+MQTT——实现网络数据传输并更新到数据库

一、硬件及其架构设计

1、MQTT三种身份

2、硬件架构设计

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命令更新数据库。

 

二、实操步骤

1、单片机(Arduino NANO)

提示:程序中有些头文件,需要在Arduino IAE>>工具>>管理库中安装相应的库。

从上一张图可以看出,Arduino需要将接收到的条形码数据、按键数据发送到两个方向,一是OLED显示屏,二是WiFi模块。主要实现以下功能:

A、接收条形码数据;

B、接收按键数据;

C、发送给OLED显示屏进行显示;

D、发送给ESP8266模块。

具体代码如下:


#include<SoftwareSerial.h>
SoftwareSerial softSerial(11, 10);

#include <Arduino.h>
#include <Wire.h>
#include <MicroLCD.h>

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开发板上。

2、WiFi模块(ESP8266模块/订阅者)

实现以下功能:

A、接入WiFi环境;

B、连接MQTT服务器;

C、接收来自Arduino的数据;

D、将数据整合成Json格式;

E、将Json数据发送给MQTT服务器;

具体代码如下:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Arduino.h>
#include <ArduinoJson.h>

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>>工具>>串口监视器 查看程序运行状态。

 

3、MQTT服务器

搭建MQTT服务器,参考文章:https://blog.csdn.net/qq_40384309/article/details/106870359

4、服务器后台程序(js文件/订阅者)

程序运行环境: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

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章