This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.
machines-backup/extrusion/lydia-print-head-v1/firmware/firmware/ModbusBridge.cpp

408 lines
9.1 KiB
C++

#include <Streaming.h>
#include "./Addon.h"
#include "ModbusRtu.h"
#include "ModbusBridge.h"
#include "config.h"
#include <SPI.h>
#include <Ethernet.h>
#define RS485Serial 3
#define MasterModbusAdd 0
#define SlaveModbusAdd 1
Modbus master(MasterModbusAdd, RS485Serial);
modbus_t ModbusQuery[1];
uint16_t ModbusSlaveRegisters[8];
millis_t WaitingTime;
int _state = IDLE;
bool debugQuery = true;
void ModbusBridge::setDebugSend(bool debug)
{
master.debugSend = debug;
}
Modbus *ModbusBridge::modbus()
{
return &master;
}
// Modbus TCP
short ModbusBridge::setup()
{
master.begin(MODBUS_RS485_BAUDRATE, MODBUS_RS485_PORT);
master.setTimeOut(MODBUS_RS485_TIMEOUT);
WaitingTime = millis() + nextWaitingTime;
_state = IDLE;
Ethernet.begin(MB_MAC, MB_IP, MB_GATEWAY, MB_SUBNET);
for (uchar i = 0; i < MAX_QUERY_BUFFER; i++)
{
queries[i].reset();
queries[i].id = i;
}
for (uchar i = 0; i < 50; i++)
{
mb->R[i] = MODBUS_TCP_DEFAULT_REGISTER_VALUE;
}
startTS = millis();
}
Query *ModbusBridge::nextByPrio(uchar state, int prio)
{
Query *oldest;
for (int i = 0; i < MAX_QUERY_BUFFER; i++)
{
if (!oldest)
{
oldest = &queries[i];
}
if (queries[i].state == state && queries[i].prio == prio)
{
oldest = &queries[i];
}
}
return oldest;
}
bool didm = false;
Query *ModbusBridge::nextQueryByState(uchar state = DONE, int owner = -1)
{
if (owner > 0)
{
Query *q = nextQueryByOwner(state, owner);
if (q != NULL)
{
return q;
}
}
millis_t t = millis();
Query *oldest = NULL;
for (int i = 0; i < MAX_QUERY_BUFFER; i++)
{
if (queries[i].state == state)
{
if (_state == QUEUED && t - queries[i].ts > 1000 * 10)
{
queries[i].reset();
continue;
}
if (_state == PROCESSING && t - queries[i].ts > 1000 * 10)
{
queries[i].reset();
continue;
}
if (queries[i].ts == 0)
{
queries[i].ts = t;
}
if (queries[i].prio != MB_QUERY_TYPE_CMD && t - queries[i].ts > 1000)
{
return &queries[i];
}
if (!oldest)
{
oldest = &queries[i];
}
if (queries[i].ts > oldest->ts)
{
oldest = &queries[i];
}
}
}
return oldest;
}
Query *ModbusBridge::nextQueryByOwner(uchar state = DONE, int owner = -1)
{
millis_t t = millis();
Query *oldest = NULL;
for (int i = 0; i < MAX_QUERY_BUFFER; i++)
{
if (queries[i].state == state && queries[i].owner == owner)
{
if (_state == QUEUED && t - queries[i].ts > 1000 * 10)
{
queries[i].reset();
continue;
}
if (_state == PROCESSING && t - queries[i].ts > 1000 * 10)
{
queries[i].reset();
Serial.println("reset processing");
continue;
}
if (queries[i].ts == 0)
{
queries[i].ts = t;
}
if (queries[i].prio == MB_QUERY_TYPE_CMD && t - queries[i].ts > 300)
{
return &queries[i];
}
if (!oldest)
{
oldest = &queries[i];
}
if (queries[i].ts > oldest->ts)
{
oldest = &queries[i];
}
}
}
return oldest;
}
Query *ModbusBridge::nextSame(uchar state, short slave, int addr, short fn, int value)
{
millis_t t = millis();
Query *oldest;
for (int i = 0; i < MAX_QUERY_BUFFER; i++)
{
if (queries[i].state == state)
{
Query *q = &queries[i];
if (q->addr == addr && q->fn == fn && q->value == value && q->slave == slave)
{
if (!oldest)
{
oldest = &queries[i];
}
if (queries[i].ts > oldest->ts)
{
oldest = &queries[i];
}
}
}
}
return oldest;
}
int ModbusBridge::numSame(uchar state, short slave, int addr, short fn, int value)
{
int num = 0;
for (int i = 0; i < MAX_QUERY_BUFFER; i++)
{
if (queries[i].state == state)
{
Query *q = &queries[i];
if (q->addr == addr && q->fn == fn && q->value == value && q->slave == slave)
{
num++;
}
}
}
return num;
}
int ModbusBridge::numByState(int state = DONE)
{
int num = 0;
for (int i = 0; i < MAX_QUERY_BUFFER; i++)
{
if (queries[i].state == state)
{
num++;
}
}
return num;
}
void ModbusBridge::print()
{
Serial.print("----- Queries : --- ");
Serial.print("Proccessing : ");
Serial.print(numByState(PROCESSING));
Serial.print(" | QUEUED : ");
Serial.print(numByState(QUEUED));
Serial.print(" | DONE: ");
Serial.print(numByState(DONE));
Serial.print(" | ADDR: ");
Serial.print(addr);
Serial.print(" | FN: ");
Serial.print(fn);
Serial.print(" | NOW : ");
Serial.print(millis());
Serial.print("-----\n");
for (int i = 0; i < MAX_QUERY_BUFFER; i++)
{
Serial.print(" - ");
Serial.print(queries[i].id);
Serial.print(". \t ");
queries[i].print();
Serial.print("\n");
}
}
short ModbusBridge::qstate()
{
return _state;
}
short ModbusBridge::loop()
{
loop_test();
mb->Run();
if (mb->R[9])
{
print();
mb->R[9] = 0;
}
}
short ModbusBridge::query(int slave, short function, long start, int coils, Addon *_addon, AddonFnPtr _mPtr)
{
if (_state != IDLE)
{
return WAITING;
}
addr = 0;
id = slave;
fn = function;
addr = start;
nb = coils;
owner = _addon;
updatedPtr = _mPtr;
if (debugQuery)
{
Serial.print("\n --------------Modbus QUERY --------- SLAVE : ");
Serial.print(id);
Serial.print(" | FN : ");
Serial.print(fn);
Serial.print(" | NB : ");
Serial.print(coils);
Serial.print(" | Address : ");
Serial.print(addr, HEX);
Serial.print(" | STATE : ");
Serial.print(_state);
Serial.print(" | OWNER : ");
Serial.println(owner->id);
Serial.println(" \n ");
}
_state = WAITING;
return E_OK;
}
short ModbusBridge::loop_test()
{
switch (_state)
{
case IDLE:
{
return;
}
case WAITING:
{
if (millis() > WaitingTime)
{
_state++; // set to query state
}
break;
}
case QUERY:
{
ModbusQuery[0].u8id = id; // slave address
ModbusQuery[0].u8fct = fn; // function code (this one is registers read)
ModbusQuery[0].u16RegAdd = addr; // start address in slave
ModbusQuery[0].u16CoilsNo = nb; // number of elements (coils or registers) to read
ModbusQuery[0].au16reg = ModbusSlaveRegisters; // pointer to a memory array in the CONTROLLINO
master.query(ModbusQuery[0]); // send query (only once)
_state++; // set to RESPONSE
break;
}
case RESPONSE:
{
master.poll(); // check incoming messages
if (master.getState() == COM_IDLE)
{
int errors = master.getErrCnt();
if (errors)
{
if (owner && onError != NULL)
{
(owner->*onError)(master.getLastError());
master.clearError();
}
else
{
Serial.print("ModbusBridge:: Have Errors : ");
Serial.println(master.getLastError());
}
_state = IDLE;
return;
}
long onMessageError = 0;
if (owner && onMessage)
{
onMessageError = (owner->*onMessage)(master.rxSize, master.rxBuffer);
}
short ret = (owner->*updatedPtr)(onMessageError);
WaitingTime = millis() + nextWaitingTime;
if (TEST(debug_flags, DEBUG_RECEIVE) && onMessageError == ERROR_OK)
{
}
/*
Serial.print("--------------Modbus RESPONSE --------- FN : ");
Serial.print(fn);
Serial.print(" | NB : ");
Serial.print(nb);
Serial.print(" | SLAVE : ");
Serial.print(id);
Serial.print(" | Address : ");
Serial.println(addr);
*/
_state = IDLE;
}
break;
}
}
}
short ModbusBridge::debug(Stream *stream)
{
// *stream << this->name << ":";
return false;
}
short ModbusBridge::info(Stream *stream)
{
// *stream << this->name << "\n\t";
}