Switched modbus implementation and added state machine

This commit is contained in:
Geens 2024-08-03 17:26:46 +02:00
parent 6a1183ccf5
commit 09ac0bda50
7 changed files with 116 additions and 26 deletions

24
main.py
View File

@ -1,4 +1,4 @@
import minimalmodbus
from pymodbus.client import ModbusSerialClient
import time
import traceback
import argparse
@ -16,7 +16,7 @@ def main():
help='COM port for the Modbus connection')
parser.add_argument('--slave_id', type=int, default=1,
help='Slave ID for the Modbus device')
parser.add_argument('--cycle_time', type=float, default=0.01,
parser.add_argument('--cycle_time', type=float, default=0.05,
help='Cycle time in seconds for the main loop')
args = parser.parse_args()
@ -26,14 +26,17 @@ def main():
while True:
try:
instrument = minimalmodbus.Instrument(com_port, slave_id)
instrument.serial.baudrate = 9600
instrument.serial.bytesize = 8
instrument.serial.parity = minimalmodbus.serial.PARITY_NONE
instrument.serial.stopbits = 1
instrument.serial.timeout = 1
client = ModbusSerialClient(
port=com_port,
baudrate=57600,
bytesize=8,
parity='N',
stopbits=1,
timeout=1
)
client.connect()
time.sleep(3)
hardware = Hardware(instrument)
hardware = Hardware(client, slave_id)
while True:
start_time = time.time()
@ -55,6 +58,9 @@ def main():
print(f"Error: {e}")
print(traceback.format_exc())
time.sleep(5)
finally:
if 'client' in locals():
client.close()
if __name__ == "__main__":
main()

View File

@ -1 +1 @@
minimalmodbus==1.0.2
pymodbus==3.1.0

View File

@ -1,2 +1,3 @@
from .hardware import Hardware
from .logic import loop
from .logic import loop
from .buttons_timers_and_relays import ButtonsTimersAndRelays

View File

@ -0,0 +1,79 @@
from enum import Enum
import time
class ButtonsTimersAndRelays:
class State(Enum):
RELAY_0_LOW = 0
RELAY_0_HIGH = 1
BUTTON_1_PRESSED = 2
RELAY_1_HIGH_1 = 3
RELAY_1_LOW = 4
RELAY_1_HIGH_2 = 5
def __init__(self):
self.current_state = self.State.RELAY_0_LOW
self.state_change_time = time.time()
self.time_in_current_state = 0
def loop(self, hardware):
next_state = self.current_state
# State transitions
match self.current_state:
case self.State.RELAY_0_LOW:
if hardware.get_button_0():
next_state = self.State.RELAY_0_HIGH
elif hardware.get_button_1():
next_state = self.State.BUTTON_1_PRESSED
case self.State.RELAY_0_HIGH:
if not hardware.get_button_0() and hardware.get_button_1():
next_state = self.State.BUTTON_1_PRESSED
case self.State.BUTTON_1_PRESSED:
if hardware.get_button_0():
next_state = self.State.RELAY_0_HIGH
elif not hardware.get_button_1():
next_state = self.State.RELAY_1_HIGH_1
case self.State.RELAY_1_HIGH_1:
if hardware.get_button_0():
next_state = self.State.RELAY_0_HIGH
elif self.time_in_current_state > 1:
next_state = self.State.RELAY_1_LOW
case self.State.RELAY_1_LOW:
if hardware.get_button_0():
next_state = self.State.RELAY_0_HIGH
elif self.time_in_current_state > 1:
next_state = self.State.RELAY_1_HIGH_2
case self.State.RELAY_1_HIGH_2:
if hardware.get_button_0():
next_state = self.State.RELAY_0_HIGH
elif self.time_in_current_state > 1:
next_state = self.State.RELAY_0_LOW
# Time calculation
if next_state != self.current_state:
self.state_change_time = time.time()
self.time_in_current_state = 0
else:
self.time_in_current_state = time.time() - self.state_change_time
self.current_state = next_state
# Outputs
match self.current_state:
case self.State.RELAY_0_LOW:
hardware.set_relay_0(False)
hardware.set_relay_1(False)
case self.State.RELAY_0_HIGH:
hardware.set_relay_0(True)
hardware.set_relay_1(False)
case self.State.BUTTON_1_PRESSED:
hardware.set_relay_0(False)
hardware.set_relay_1(False)
case self.State.RELAY_1_HIGH_1:
hardware.set_relay_0(False)
hardware.set_relay_1(True)
case self.State.RELAY_1_LOW:
hardware.set_relay_0(False)
hardware.set_relay_1(False)
case self.State.RELAY_1_HIGH_2:
hardware.set_relay_0(False)
hardware.set_relay_1(True)

View File

@ -1,22 +1,23 @@
import minimalmodbus
from pymodbus.exceptions import ModbusException
class Hardware:
def __init__(self, instrument):
self.instrument = instrument
self.relay_0_address = 0
self.relay_1_address = 1
self.button_0_address = 0
self.button_1_address = 1
def __init__(self, client, slave_id):
self.client = client
self.slave_id = slave_id
self.relay_0 = False
self.relay_1 = False
self.button_0 = False
self.button_1 = False
def update(self):
self.instrument.write_bit(self.relay_0_address, self.relay_0, functioncode=5)
self.instrument.write_bit(self.relay_1_address, self.relay_1, functioncode=5)
self.button_0 = self.instrument.read_bit(self.button_0_address, functioncode=2)
self.button_1 = self.instrument.read_bit(self.button_1_address, functioncode=2)
try:
self.client.write_coils(0, [self.relay_0, self.relay_1], slave=self.slave_id)
input_response = self.client.read_discrete_inputs(0, 2, slave=self.slave_id)
if not input_response.isError():
self.button_0 = input_response.bits[0]
self.button_1 = input_response.bits[1]
except Exception as e:
print(f"Modbus error: {e}")
def set_relay_0(self, value):
self.relay_0 = value

View File

@ -1,3 +1,6 @@
from src.buttons_timers_and_relays import ButtonsTimersAndRelays
buttons_timers_relays = ButtonsTimersAndRelays()
def loop(hardware):
hardware.set_relay_0(hardware.get_button_0() != hardware.get_button_1())
hardware.set_relay_1(hardware.get_button_0() and hardware.get_button_1())
buttons_timers_relays.loop(hardware)

View File

@ -1,6 +1,6 @@
#include <ModbusSerial.h>
#define BAUD_RATE 9600
#define BAUD_RATE 57600
#define SLAVE_ID 1
#define COIL_COUNT 4
#define COIL_START 1