Arduino PLC Modbus Communication to read plc input register - arduino

I am trying to communicate Arduino UNO and Wecon(LX3v-0806MR) PLC with RS485. Here the arduino is the master and the plc is the slave. I want to now read the values from the input registers (04) of plc and present it on serial monitor. For that purpose I am using the following code.
#include <ModbusMaster.h>
/*!
We're using a MAX485-compatible RS485 Transceiver.
Rx/Tx is hooked up to the hardware serial port at 'Serial'.
The Data Enable and Receiver Enable pins are hooked up as follows:
*/
#define MAX485_DE 3
#define MAX485_RE_NEG 2
// instantiate ModbusMaster object
ModbusMaster node;
void preTransmission()
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
void setup()
{
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
// Init in receive mode
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// Modbus communication runs at 115200 baud
Serial.begin(115200);
// Modbus slave ID 1
node.begin(1, Serial);
// Callbacks allow us to configure the RS485 transceiver correctly
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
bool state = true;
void loop()
{
uint8_t result;
uint16_t data[6];
// Toggle the coil at address 0x0002 (Manual Load Control)
result = node.writeSingleCoil(0x0002, state);
state = !state;
// Read 16 registers starting at 0x3100)
result = node.readInputRegisters(0x3100, 16);
if (result == node.ku8MBSuccess)
{
Serial.print("Vbatt: ");
Serial.println(node.getResponseBuffer(0x04)/100.0f);
Serial.print("Vload: ");
Serial.println(node.getResponseBuffer(0xC0)/100.0f);
Serial.print("Pload: ");
Serial.println((node.getResponseBuffer(0x0D) +
node.getResponseBuffer(0x0E) << 16)/100.0f);
}
delay(1000);
}
I tried the codes many a times but it is not working. If anyone knows how to do it please share the codes with me. I just want read int value from plc.
*Note: The sensor used is for TTL to rs485 is MAX485.

Related

How to send orders from Arduino to Esp32 and make it keypress

I need to send orders from Arduino to ESP32.
I have one joystick button to test.
Arduino nano is sender
Esp32 is receiver
Esp32 receives the joystick button information from Arduino (each time I push the button).
I need the Esp32 to Serial.write according to the data, for example:
If I press the button in Arduino: Send the data to Esp32 and turn bluetooth on (or turn a led on).
These are my codes:
//Arduino NANO sender
byte j = 45;
#define boton_joystick A1
void setup() {
Serial.begin(9600);
pinMode(boton_joystick, INPUT_PULLUP);
}
int boton_joystick_state;
void loop() {
//Serial.println("100");
//Serial.write("BOTON EN GRANDE");
//delay(1500);
if(!digitalRead(boton_joystick)) {
boton_joystick_state = 1;
delay(170);
} else {
boton_joystick_state = 0;
}
if (boton_joystick_state) {
Serial.println(j);
Serial.print(" ");
Serial.write(j);
Serial.println();
}
//ESP-32 receiver
#define RXD2 16
#define TXD2 17
byte j = 45;
int comdata;
void setup() {
Serial.begin(115200);
Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);
}
void loop() {
//Serial.print("LEYENDO ARDUINO");
Serial.println(Serial2.readString());
if (Serial2.available() >0) {
char comdata = char(Serial2.read());
if (comdata == 'j') {
Serial.println("joystick activado");
}
}
}
am not sure
but am using Nano 33 BLE with UART and Nano has also Serial1 no need to serial2 no need to Softwearserial. Sensd on serial 1 and recive in Serial 1 but also you have to connect it Via USB. so your serial is USB and your serial 1 is TX RX.
for me it work so you can try it.

Using arduino Nano 32 IOTs BLE to create LED display boards

I am working on a project for which I need to get a panel of 7 buttons to light up led strips on a display about 5m away. So far I have made it so I can control 1 led strip with one button and this works well. I am now confused on how to get the other 6 to connect to the same arduino via BLE. The idea is to have one arduino with all the buttons connected, then 1 arduino for each led strip. You press button 1 on the button arduino and this sends a signal to the display 1 arduino, lighting the display.
Here is my code so far, what would I need to do to it to add multiple buttons in ?
Thanks !!
//this code is loaded onto the board that is connected to the led strip
//if the code doesnt work it seems to kick start it by opening the serial monitor and then it will connect, not sure why this is
#include <ArduinoBLE.h>
#include <Adafruit_DotStar.h>
#include <SPI.h>
#define NUMPIXELS 144 // Number of LEDs in strip
#define BUTTON_PIN 9 //pin the button is on
#define DATAPIN 4 //the pin the data is plugged into
#define CLOCKPIN 5 //the pin the clock wire is plugged into
BLEService ledService("19B10000-E8F2-537E-4F6C-D104768A1214"); // adress of the ledstrip that is referenced in the other set of code
Adafruit_DotStar strip(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BRG);
// BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central
BLEByteCharacteristic switchCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLEWrite);
const int ledPin = 2; // pin to use for the LED
void setup() {
// set LED pin to output mode
pinMode(ledPin, OUTPUT);
// begin initialization
if (!BLE.begin()) {
Serial.println("starting BLE failed!");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("LED");
BLE.setAdvertisedService(ledService);
// add the characteristic to the service
ledService.addCharacteristic(switchCharacteristic);
// add service
BLE.addService(ledService);
// set the initial value for the characeristic:
switchCharacteristic.writeValue(0);
// start advertising
BLE.advertise();
Serial.println("BLE LED Peripheral");
strip.begin();
strip.show(); //pixels to 'off'
}
uint32_t white= strip.Color(255, 255, 255); //colour you want the lights
uint32_t off= strip.Color(0, 0, 0); //colour 'off'
void loop() {
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
Serial.print("Connected to central: ");
// print the central's MAC address:
Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected()) {
// if the remote device wrote to the characteristic,
// use the value to control the LED:
if (switchCharacteristic.written()) {
if (switchCharacteristic.value()) { // any value other than 0
strip.fill(white, 0, 144); //fill(Color,first pixel,last pixel)
strip.setBrightness(5); //set the brightness of the leds here, would keep about 40, doesnt like anything above that
strip.show(); //update the leds
delay(7000); //time you want the LEDs
strip.fill(off, 0, 144); //turns off leds
strip.setBrightness(0);
strip.show();
} else { // a 0 value
strip.fill(off, 0, 144);
strip.setBrightness(0);
strip.show();
}
}
}
// when the central disconnects, print it out:
Serial.print(F("Disconnected from central: "));
Serial.println(central.address());
}
}
//this code gets loaded onto the button board
#include <ArduinoBLE.h>
// variables for button
const int buttonPin = 2;
int oldButtonState = LOW;
void setup() {
// configure the button pin as input
pinMode(buttonPin, INPUT);
// initialize the BLE hardware
BLE.begin();
Serial.println("BLE Central - LED control");
// start scanning for peripherals
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214"); //Put the adress of what you want the button to control here
}
void loop() {
// check if a peripheral has been discovered
BLEDevice peripheral = BLE.available();
if (peripheral) {
// discovered a peripheral, print out address, local name, and advertised service
Serial.print("Found ");
Serial.print(peripheral.address());
Serial.print(" '");
Serial.print(peripheral.localName());
Serial.print("' ");
Serial.print(peripheral.advertisedServiceUuid());
Serial.println();
if (peripheral.localName() != "LED") {
return;
}
// stop scanning
BLE.stopScan();
controlLed(peripheral);
// peripheral disconnected, start scanning again
BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214");
}
}
void controlLed(BLEDevice peripheral) {
// connect to the peripheral
Serial.println("Connecting ...");
if (peripheral.connect()) {
Serial.println("Connected");
} else {
Serial.println("Failed to connect!");
return;
}
// discover peripheral attributes
Serial.println("Discovering attributes ...");
if (peripheral.discoverAttributes()) {
Serial.println("Attributes discovered");
} else {
Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
// retrieve the LED characteristic
BLECharacteristic ledCharacteristic = peripheral.characteristic("19b10001-e8f2-537e-4f6c-d104768a1214");
if (!ledCharacteristic) {
Serial.println("Peripheral does not have LED characteristic!");
peripheral.disconnect();
return;
} else if (!ledCharacteristic.canWrite()) {
Serial.println("Peripheral does not have a writable LED characteristic!");
peripheral.disconnect();
return;
}
while (peripheral.connected()) {
// while the peripheral is connected
// read the button pin
int buttonState = digitalRead(buttonPin);
if (oldButtonState != buttonState) {
// button changed
oldButtonState = buttonState;
if (buttonState) {
Serial.println("button pressed");
// button is pressed, write 0x01 to turn the LED on
ledCharacteristic.writeValue((byte)0x01);
} else {
Serial.println("button released");
// button is released, write 0x00 to turn the LED off
ledCharacteristic.writeValue((byte)0x00);
}
}
}
Serial.println("Peripheral disconnected");
A typical way of doing this with BLE would be for the button to be the Peripheral and the LED strip to be the Central. The Central would connect to the Peripheral and subscribe to notifications on the "button" characteristic. Typically libraries/hardware aren't setup to have multiple Centrals connected at the same time to one Peripheral. This would seem to rule out doing it this way with your required hardware setup.
An alternative would be to have the buttons as the Central and the LED strips as the Peripheral. The Central would already know the details of the Peripheral device and initiate a connection and then do a write when a button is pressed. I would expect there to be a lot of lag between the button being pressed and something happening on the LED strip with this setup.
Another alternative is to do this with connection-less BLE, if security isn't a concern. The button board could act as a BLE beacon and you could encode information about which button has been pressed in the Service Data or the Manufacturer Data. The LED strips would be scanners reading the data from the beacon. I am not very familiar with BLE libraries on Arduino, there appears to be the command to set the Manufacturer Data but I couldn't find any command to read the data.

Arduino Mega and RS485 Modbus Sensor

I'm trying to connect a soil sensor using RS485 communication to arduino mega and I can't get it to work. I'm using the SparkFun RS485 breakout: https://www.sparkfun.com/products/10124
I've connected TX to pin 18, RS to pin 19 and RTS to pin 8.
I've tried to adapt the code from here: https://www.youtube.com/watch?v=tBw15SfmuwI using the sensor's manufacturers default setting:
Modbus address fixed to 0
The communication configuration is 9600,N,8,1(9600bps, no check bit, 8 data bits,
1 stop bit)
Communication protocol is Modbus-RTU
While the addresses I need to read are 0x0000-0x0002.
However, I get random characters as output when I open the serial monitor "?", any idea why? I'd appreciate any help reading the sensor's output.
This is the code I've used:
#include <ModbusMaster.h>
#define MAX485_DE 8
#define MAX485_RE_NEG 8
ModbusMaster node;
void preTransmission () {
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}
void postTransmission () {
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
void setup() {
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
Serial.begin(9600);
node.begin(0,Serial);
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop() {
uint8_t resultMain;
resultMain = node.readInputRegisters(0x0000, 3);
if (resultMain == node.ku8MBSuccess) {
Serial.println("-------");
Serial.print("Temp: ");
Serial.println(node.getResponseBuffer(0x00) /100);
Serial.print("VWC: ");
Serial.println(node.getResponseBuffer(0x01) /100);
Serial.print("EC: ");
Serial.println(node.getResponseBuffer(0x02) /100);
}
}
The arduino mega has 3 serial ports:
Serial
Serial1
Serial2
You could think of it as Serial as Serial0 (the zero is never written). This port is hardwired to the USB port on the arduino mega.
Your RS485 breakout board is connected to Serial1. You may notice the screenprinting on the mega next to pins 18 and 19 says TX1 and RX1.
So when you initialize your node at this line:
node.begin(0,Serial);
you should pass it Serial1 instead of Serial
eg
node.begin(0,Serial1);

Communication between Arduino Nano and HM-10 BLE controller is not working

I want to check if communication is working between my SerialMonitor in Arduino IDE and BLE controller.
I typed command AT to my SerialMonitor and it suppose to return OK response but nothing happened.
This is scheme what I used:
Code:
#include <SoftwareSerial.h>
SoftwareSerial bleSerial(2, 3); // RX, TX
void setup() {
//initialize serial port for logs
Serial.begin(9600);
while (!Serial) {
}
bleSerial.begin(9600);
}
void loop() {
if (bleSerial.available()) {
Serial.write(bleSerial.read());
}
if (Serial.available()) {
bleSerial.write(Serial.read());
}
}
UPDATE:
Changed values for SoftwareSerial bleSerial(3, 2); // RX, TX still doesnt work.
UPDATE2:
I've tried switching pins and code, nothing works. I should at least see HM-10 controller in my bluetooth devices on my Android phone, but I cant see anything.
UPDATE3:
I've used code from this Stackoverflow post and its working fine. I can finally see controller in my bluetooth devices on my Android phone also It returned name MLT-BT05 after AT+NAME? command. Looks like you have to read message per char and put delay 10ms between chars, otherwise it will not be possible to read message from BLE controller. That was the only problem.
You should connect RX-TX and TX-RX (not RX-RX and TX-TX like your graphic shows) so change the cables and the code from
SoftwareSerial bleSerial(2, 3); // RX, TX
to
SoftwareSerial bleSerial(3, 2); // RX, TX
Connect according to this graphic (incl voltage divider)
Abd use the following sketch to test (read comments for details):
// SerialIn_SerialOut_HM-10_01
//
// Uses hardware serial to talk to the host computer and AltSoftSerial for communication with the bluetooth module
//
// What ever is entered in the serial monitor is sent to the connected device
// Anything received from the connected device is copied to the serial monitor
// Does not send line endings to the HM-10
//
// Pins
// BT VCC to Arduino 5V out.
// BT GND to GND
// Arduino D8 (SS RX) - BT TX no need voltage divider
// Arduino D9 (SS TX) - BT RX through a voltage divider (5v to 3.3v)
//
#include <SoftwareSerial.h>
SoftwareSerial BTserial;
char c=' ';
bool NL = true;
void setup()
{
Serial.begin(9600);
Serial.print("Sketch: "); Serial.println(__FILE__);
Serial.print("Uploaded: "); Serial.println(__DATE__);
Serial.println(" ");
BTserial.begin(9600);
Serial.println("BTserial started at 9600");
}
void loop()
{
// Read from the Bluetooth module and send to the Arduino Serial Monitor
if (BTserial.available())
{
c = BTserial.read();
Serial.write(c);
}
// Read from the Serial Monitor and send to the Bluetooth module
if (Serial.available())
{
c = Serial.read();
if (c!=10 & c!=13 )
{
BTserial.write(c);
}
// Echo the user input to the main window. The ">" character indicates the user entered text.
if (NL) { Serial.print("\r\n>"); NL = false; }
Serial.write(c);
if (c==10) { NL = true; }
}
}

arduino as modbus RS485 slave sending message to master

I am French speaking, excuse my poor English. I am working on a rs485 modbus communication between 2 arduino megas. I would like the slave to send for example the value "10" to the master.
On the slave I use the example of the library https://github.com/yaacov/ArduinoModbusSlave :
#include <ModbusSlave.h>
// explicitly set stream to use the Serial serialport
Modbus slave(Serial, 1); // stream = Serial, slave id = 1, rs485 control-pin = 8
void setup() {
// register handler functions
slave.cbVector[CB_READ_INPUT_REGISTERS] = ReadAnalogIn;
// slave.cbVector[CB_READ_HOLDING_REGISTERS] = readMemory;
// start slave at baud 9600 on Serial
Serial.begin( 9600 ); // baud = 9600
slave.begin( 9600 );
}
void loop() {
// listen for modbus commands con serial port
slave.poll();
}
// Handel Read Input Registers (FC=04)
uint8_t ReadAnalogIn(uint8_t fc, uint16_t address, uint16_t length) {
// write registers into the answer buffer
for (int i = 0; i < length; i++) {
uint16_t res;
res = 221;
//slave.writeRegisterToBuffer(i, analogRead(address + i));
slave.writeRegisterToBuffer(i,10);
}
return STATUS_OK;
}
on the master I use an example from the librabry https://github.com/4-20ma/ModbusMaster
´´´
#include <ModbusMaster.h>
// instantiate ModbusMaster object
ModbusMaster node;
void setup()
{
// use Serial (port 0); initialize Modbus communication baud rate
Serial.begin(9600);
// communicate with Modbus slave ID 1 over Serial (port 0)
node.begin(1, Serial);
}
void loop()
{
static uint32_t i;
uint8_t j, result;
uint16_t data[6];
i++;
// set word 0 of TX buffer to least-significant word of counter (bits 15..0)
// node.setTransmitBuffer(0, lowWord(i));
// set word 1 of TX buffer to most-significant word of counter (bits 31..16)
// node.setTransmitBuffer(1, highWord(i));
// slave: write TX buffer to (2) 16-bit registers starting at register 0
// result = node.writeMultipleRegisters(0, 2);
// slave: read (6) 16-bit registers starting at register 2 to RX buffer
result = node.readHoldingRegisters(2, 6);
// do something with data if read is successful
if (result == node.ku8MBSuccess)
{
Serial.println(result);
}
}
´´´
but it does not work, it seems that there is no communication between the arduino. does anyone have a solution?

Resources