/* Ver 1.0 RGK 2023 Minimalistic example for the Arduino based Modbus communication It uses one master and one slave. The master can switch 8 digital outputs for LED's or relays on and off at the slave and displays the voltage from a potentiometer connected to the slave. */ // include the library code: #include #include #include #include LiquidCrystal_I2C lcd(0x27,16,2); // set the LCD address to 0x27 for a 20 chars and 4 line display #define adr0 0 //eeprom save address #define Rot_A 3 //rotary encoder defines #define Rot_B 2 #define Rot_enter 4 //modbus settings #define baud 9600 #define timeout 1000 #define polling 10 // the scan rate #define retry_count 100 // used to toggle the receive/transmit pin on the driver #define TxEnablePin 5 // The total amount of available memory on the master to store data #define TOTAL_NO_OF_REGISTERS 2 enum { PACKET1, PACKET2, TOTAL_NO_OF_PACKETS // leave this last entry }; // Create an array of Packets to be configured Packet packets[TOTAL_NO_OF_PACKETS]; // Masters register array unsigned int regs[TOTAL_NO_OF_REGISTERS]; unsigned int counter=0; unsigned int counter_old; bool rystat=0; bool Ry[8]; unsigned char RELAYS=0; byte rotary; byte up; void setup() { // Initialize each packet modbus_construct(&packets[PACKET1], 1, PRESET_MULTIPLE_REGISTERS, 0, 1, 0);//write to slave regs[0] modbus_construct(&packets[PACKET2], 1, READ_HOLDING_REGISTERS, 1, 1, 1);//read from slave regs[1] // Initialize the Modbus Finite State Machine modbus_configure(&Serial, baud, SERIAL_8N2, timeout, polling, retry_count, TxEnablePin, packets, TOTAL_NO_OF_PACKETS, regs); //rotary encoder pinning pinMode(Rot_A,INPUT_PULLUP); pinMode(Rot_B,INPUT_PULLUP); pinMode(Rot_enter,INPUT_PULLUP); // External Interrupt 0 service routine attachInterrupt(digitalPinToInterrupt(Rot_A), read_rot, FALLING); //I2C display initialisation Wire.begin(); lcd.init(); RELAYS=EEPROM.read(adr0); //recall last settings on switch-on for(int x=0;x<8;x++){ //fill status array with ON/OFF status of all relays Ry[x]=bitRead(RELAYS,x); } lcd.backlight(); lcd.setCursor(0,0); counter_old = counter; rystat=Ry[counter]; update_display(counter); update_status(rystat,counter); modbus_update(); } void loop() { unsigned int potmeter; modbus_update(); potmeter = regs[1]; update_potmeterposition(potmeter); counter=rot_update(counter,0,7); if(counter != counter_old){ update_display(counter); counter_old=counter; } if(digitalRead(Rot_enter)==LOW){ rystat = !rystat; update_status(rystat,counter); update_display(counter); while(digitalRead(Rot_enter)==LOW); } } void read_rot(){ rotary = 1; up = digitalRead(Rot_B); // that's all folks... } // control any variable with the rotary encoder int rot_update(int var,int min,int max){ noInterrupts(); if(rotary) { rotary = 0; if(up) var ++; else var --; } if(var>max) var=min; if(var