mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-26 22:22:16 +03:00
...
This commit is contained in:
175
src/modules/display/Smi2_m/Modbus_master_for_Smi2_m.cpp
Normal file
175
src/modules/display/Smi2_m/Modbus_master_for_Smi2_m.cpp
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
#include "Modbus_master_for_Smi2_m.h"
|
||||||
|
#include "HardwareSerial.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
Smi_display::Smi_display() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Modbus Master
|
||||||
|
void Smi_display:: modbus_update()
|
||||||
|
{
|
||||||
|
idle();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Smi_display:: idle()
|
||||||
|
{
|
||||||
|
static unsigned int packet_index;
|
||||||
|
|
||||||
|
unsigned int failed_connections = 0;
|
||||||
|
|
||||||
|
unsigned char current_connection;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (packet_index == total_no_of_packets) // wrap around to the beginning
|
||||||
|
packet_index = 0;
|
||||||
|
|
||||||
|
// proceed to the next packet
|
||||||
|
packet = &packetArray[packet_index];
|
||||||
|
|
||||||
|
// get the current connection status
|
||||||
|
current_connection = packet->connection;
|
||||||
|
|
||||||
|
if (!current_connection)
|
||||||
|
{
|
||||||
|
// If all the connection attributes are false return
|
||||||
|
// immediately to the main sketch
|
||||||
|
if (++failed_connections == total_no_of_packets)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
packet_index++;
|
||||||
|
|
||||||
|
// if a packet has no connection get the next one
|
||||||
|
}while (!current_connection);
|
||||||
|
|
||||||
|
constructPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Smi_display:: constructPacket()
|
||||||
|
{
|
||||||
|
packet->requests++;
|
||||||
|
frame[0] = packet->id;
|
||||||
|
frame[1] = packet->function;
|
||||||
|
frame[2] = packet->address >> 8; // address Hi
|
||||||
|
frame[3] = packet->address & 0xFF; // address Lo
|
||||||
|
frame[4] = packet->data >> 8; // MSB
|
||||||
|
frame[5] = packet->data & 0xFF; // LSB
|
||||||
|
|
||||||
|
unsigned char frameSize;
|
||||||
|
|
||||||
|
// construct the frame according to the modbus function
|
||||||
|
if (packet->function == PRESET_MULTIPLE_REGISTERS)
|
||||||
|
frameSize = construct_F16();
|
||||||
|
else // else functions 1,2,3,4,5 & 6 is assumed. They all share the exact same request format.
|
||||||
|
frameSize = 8; // the request is always 8 bytes in size for the above mentioned functions.
|
||||||
|
|
||||||
|
unsigned int crc16 = calculateCRC(frameSize - 2);
|
||||||
|
frame[frameSize - 2] = crc16 >> 8; // split crc into 2 bytes
|
||||||
|
frame[frameSize - 1] = crc16 & 0xFF;
|
||||||
|
sendPacket(frameSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char Smi_display::construct_F16()
|
||||||
|
{
|
||||||
|
unsigned char no_of_bytes = packet->data * 2;
|
||||||
|
|
||||||
|
// first 6 bytes of the array + no_of_bytes + 2 bytes CRC
|
||||||
|
frame[6] = no_of_bytes; // number of bytes
|
||||||
|
unsigned char index = 7; // user data starts at index 7
|
||||||
|
unsigned char no_of_registers = packet->data;
|
||||||
|
/*unsigned*/ int temp;
|
||||||
|
|
||||||
|
for (unsigned char i = 0; i < no_of_registers; i++)
|
||||||
|
{
|
||||||
|
temp = register_array[packet->local_start_address + i]; // get the data
|
||||||
|
frame[index] = temp >> 8;
|
||||||
|
index++;
|
||||||
|
frame[index] = temp & 0xFF;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
unsigned char frameSize = (9 + no_of_bytes); // first 7 bytes of the array + 2 bytes CRC + noOfBytes
|
||||||
|
return frameSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Smi_display::modbus_configure(HardwareSerial* SerialPort,
|
||||||
|
long baud,
|
||||||
|
unsigned char byteFormat,
|
||||||
|
int rx,
|
||||||
|
int tx,
|
||||||
|
unsigned int _TxEnablePin,
|
||||||
|
Packet* _packets,
|
||||||
|
unsigned int _total_no_of_packets,
|
||||||
|
/*unsigned*/ int* _register_array)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
TxEnablePin = _TxEnablePin;
|
||||||
|
total_no_of_packets = _total_no_of_packets;
|
||||||
|
packetArray = _packets;
|
||||||
|
register_array = _register_array;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ModbusPort = SerialPort;
|
||||||
|
(*ModbusPort).begin(baud, byteFormat,rx,tx);
|
||||||
|
|
||||||
|
pinMode(TxEnablePin, OUTPUT);
|
||||||
|
digitalWrite(TxEnablePin, LOW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Smi_display::modbus_construct (Packet *_packet,
|
||||||
|
unsigned char id,
|
||||||
|
unsigned char function,
|
||||||
|
unsigned int address,
|
||||||
|
unsigned int data,
|
||||||
|
unsigned int local_start_address)
|
||||||
|
{
|
||||||
|
_packet->id = id;
|
||||||
|
_packet->function = function;
|
||||||
|
_packet->address = address;
|
||||||
|
_packet->data = data;
|
||||||
|
_packet->local_start_address = local_start_address;
|
||||||
|
_packet->connection = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int Smi_display::calculateCRC(unsigned char bufferSize)
|
||||||
|
{
|
||||||
|
unsigned int temp, temp2, flag;
|
||||||
|
temp = 0xFFFF;
|
||||||
|
for (unsigned char i = 0; i < bufferSize; i++)
|
||||||
|
{
|
||||||
|
temp = temp ^ frame[i];
|
||||||
|
for (unsigned char j = 1; j <= 8; j++)
|
||||||
|
{
|
||||||
|
flag = temp & 0x0001;
|
||||||
|
temp >>= 1;
|
||||||
|
if (flag)
|
||||||
|
temp ^= 0xA001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Reverse byte order.
|
||||||
|
temp2 = temp >> 8;
|
||||||
|
temp = (temp << 8) | temp2;
|
||||||
|
temp &= 0xFFFF;
|
||||||
|
// the returned value is already swapped
|
||||||
|
// crcLo byte is first & crcHi byte is last
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Smi_display::sendPacket(unsigned char bufferSize)
|
||||||
|
{
|
||||||
|
digitalWrite(TxEnablePin, HIGH);
|
||||||
|
|
||||||
|
for (unsigned char i = 0; i < bufferSize; i++)
|
||||||
|
(*ModbusPort).write(frame[i]);
|
||||||
|
|
||||||
|
(*ModbusPort).flush();
|
||||||
|
|
||||||
|
|
||||||
|
digitalWrite(TxEnablePin, LOW);
|
||||||
|
}
|
||||||
81
src/modules/display/Smi2_m/Modbus_master_for_Smi2_m.h
Normal file
81
src/modules/display/Smi2_m/Modbus_master_for_Smi2_m.h
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define PRESET_MULTIPLE_REGISTERS 16
|
||||||
|
#define BUFFER_SIZE 64
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
unsigned char id;
|
||||||
|
unsigned char function;
|
||||||
|
unsigned int address;
|
||||||
|
|
||||||
|
|
||||||
|
unsigned int data;
|
||||||
|
unsigned int local_start_address;
|
||||||
|
|
||||||
|
// modbus <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
|
||||||
|
unsigned int requests;
|
||||||
|
unsigned int successful_requests;
|
||||||
|
unsigned int failed_requests;
|
||||||
|
unsigned int exception_errors;
|
||||||
|
unsigned int retries;
|
||||||
|
|
||||||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
unsigned char connection;
|
||||||
|
|
||||||
|
}Packet;
|
||||||
|
|
||||||
|
class Smi_display {
|
||||||
|
public:
|
||||||
|
Smi_display();
|
||||||
|
|
||||||
|
~Smi_display();
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
void modbus_update();
|
||||||
|
void modbus_construct(Packet *_packet,
|
||||||
|
unsigned char id,
|
||||||
|
unsigned char function,
|
||||||
|
unsigned int address,
|
||||||
|
unsigned int data,
|
||||||
|
unsigned _local_start_address);
|
||||||
|
|
||||||
|
void modbus_configure(HardwareSerial* SerialPort,
|
||||||
|
long baud,
|
||||||
|
unsigned char byteFormat,
|
||||||
|
int rx,
|
||||||
|
int tx,
|
||||||
|
unsigned int _TxEnablePin,
|
||||||
|
Packet* _packets,
|
||||||
|
unsigned int _total_no_of_packets,
|
||||||
|
/*unsigned*/ int* _register_array);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
void idle();
|
||||||
|
void constructPacket();
|
||||||
|
unsigned char construct_F16();
|
||||||
|
unsigned int calculateCRC(unsigned char bufferSize);
|
||||||
|
void sendPacket(unsigned char bufferSize);
|
||||||
|
|
||||||
|
private:
|
||||||
|
unsigned char state;
|
||||||
|
unsigned char retry_count;
|
||||||
|
unsigned int TxEnablePin;
|
||||||
|
unsigned char frame[BUFFER_SIZE];
|
||||||
|
unsigned char buffer;
|
||||||
|
unsigned int T1_5; // <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
unsigned int frameDelay; // <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
unsigned int total_no_of_packets;
|
||||||
|
Packet* packetArray; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
Packet* packet; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
/*unsigned*/ int* register_array; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> master <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||||
|
HardwareSerial* ModbusPort;
|
||||||
|
|
||||||
|
};
|
||||||
75
src/modules/display/Smi2_m/Smi2_m.cpp
Normal file
75
src/modules/display/Smi2_m/Smi2_m.cpp
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
|
||||||
|
#include "Global.h"
|
||||||
|
#include "classes/IoTItem.h"
|
||||||
|
|
||||||
|
#include "Modbus_master_for_Smi2_m.h"
|
||||||
|
#include "modules/sensors/UART/Uart.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// Общая сумма доступной памяти на ведущем устройстве, чтобы хранить данные
|
||||||
|
#define TOTAL_NO_OF_REGISTERS 4
|
||||||
|
|
||||||
|
// This is the easiest way to create new packets
|
||||||
|
// Add as many as you want. TOTAL_NO_OF_PACKETS
|
||||||
|
// is automatically updated.
|
||||||
|
enum {
|
||||||
|
PACKET1,
|
||||||
|
TOTAL_NO_OF_PACKETS // leave this last entry
|
||||||
|
};
|
||||||
|
|
||||||
|
// Масив пакетов модбус
|
||||||
|
Packet packets[TOTAL_NO_OF_PACKETS];
|
||||||
|
|
||||||
|
// Массив хранения содержимого принятых и передающихся регистров
|
||||||
|
/*unsigned*/ int regs[TOTAL_NO_OF_REGISTERS];
|
||||||
|
|
||||||
|
class Smi2_m : public IoTItem {
|
||||||
|
private:
|
||||||
|
Smi_display* smi;
|
||||||
|
unsigned int _pin; // номер порта, управляющий передачей по RS-485
|
||||||
|
long int _baud; // скорость обмена, бит/с
|
||||||
|
int _rx, _tx; // номера ножек мк, к которым подключен UART
|
||||||
|
String _show;
|
||||||
|
int i = 10;
|
||||||
|
|
||||||
|
public:
|
||||||
|
public:
|
||||||
|
Smi2_m(String parameters) : IoTItem(parameters) {
|
||||||
|
smi = new Smi_display();
|
||||||
|
|
||||||
|
_pin = jsonReadInt(parameters, "pin");
|
||||||
|
_baud = jsonReadLInt(parameters, "baud");
|
||||||
|
_rx = jsonReadInt(parameters, "rx");
|
||||||
|
_tx = jsonReadInt(parameters, "tx");
|
||||||
|
// Настраиваем пакеты
|
||||||
|
// Шестой параметр - это индекс ячейки в массиве, размещенном в памяти ведущего устройства, в которую будет
|
||||||
|
// помещен результат или из которой будут браться данные для передачи в подчиненное устройство. В нашем коде - это массив reg
|
||||||
|
// Пакет,SLAVE адрес,функция модбус,адрес регистра,количесво запрашиваемых регистров,локальный адрес регистра.
|
||||||
|
// Пакет,SLAVE адрес,функция модбус,адрес регистра,данные,локальный адрес регистра.
|
||||||
|
smi->modbus_construct(&packets[PACKET1], 1, PRESET_MULTIPLE_REGISTERS, 4200, 1, 0);
|
||||||
|
smi->modbus_configure(&Serial, _baud, SERIAL_8N1, _rx, _tx, _pin, packets, TOTAL_NO_OF_PACKETS, regs);
|
||||||
|
|
||||||
|
jsonRead(parameters, "id2show", _show);
|
||||||
|
}
|
||||||
|
|
||||||
|
void doByInterval() {
|
||||||
|
if (smi) {
|
||||||
|
smi->modbus_update();
|
||||||
|
|
||||||
|
float tmpStr = getItemValue(_show).toFloat();
|
||||||
|
regs[0] = tmpStr * 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~Smi2_m(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
void* getAPI_Smi2_m(String subtype, String param) {
|
||||||
|
if (subtype == F("Smi2_m")) {
|
||||||
|
return new Smi2_m(param);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
57
src/modules/display/Smi2_m/modinfo.json
Normal file
57
src/modules/display/Smi2_m/modinfo.json
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"menuSection": "Экраны",
|
||||||
|
"configItem": [
|
||||||
|
{
|
||||||
|
"global": 0,
|
||||||
|
"name": "Smi2_m",
|
||||||
|
"type": "Writing",
|
||||||
|
"subtype": "Smi2_m",
|
||||||
|
"id": "Smi",
|
||||||
|
"widget": "",
|
||||||
|
"page": "Дисплеи",
|
||||||
|
"descr": "",
|
||||||
|
"int": 2,
|
||||||
|
"pin": 4,
|
||||||
|
"id2show": "id датчика",
|
||||||
|
"baud": "9600",
|
||||||
|
"rx": "16",
|
||||||
|
"tx": "17"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"about": {
|
||||||
|
"moduleName": "Smi2_m",
|
||||||
|
"moduleVersion": "1.0",
|
||||||
|
"usedRam": {
|
||||||
|
"esp32_4mb": 15,
|
||||||
|
"esp8266_4mb": 15
|
||||||
|
},
|
||||||
|
"moduleDesc": "Позволяет вывести индикацию на семисегментный индикатор по Modbus (Работает в Slave режиме, Read Holding Registers 0х03)",
|
||||||
|
"propInfo": {
|
||||||
|
"int": "Период времени в секундах обновления информации на экране по конкретному элементу.",
|
||||||
|
"pin": "номер порта, управляющий передачей по RS-485",
|
||||||
|
"id2show": "id элемента конфигурации.",
|
||||||
|
"baud": "скорость обмена, бит/с"
|
||||||
|
},
|
||||||
|
"funcInfo": [
|
||||||
|
{
|
||||||
|
"name": "descr",
|
||||||
|
"descr": "Задает приставку слева от значения",
|
||||||
|
"params": [
|
||||||
|
"Строка"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "id2show",
|
||||||
|
"descr": "Задает ИД элемента, значение которого хотим отображать на экране",
|
||||||
|
"params": [
|
||||||
|
"Имя элемента конфигурации"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"defActive": true,
|
||||||
|
"usedLibs": {
|
||||||
|
"esp32_4mb": [],
|
||||||
|
"esp8266_4mb": []
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user