Technical Features

ESP32 PLC Family

Initial installation

Arduino IDE

Arduino IDE is the original platform to program Arduino boards. This cross-platform application is available on Windows, macOS and Linux under the GNU General Public License. Arduino IDE supports C and C++ code structuring. In order to program the ESP32 based PLCs in this environment, Industrial Shields provides a boards package with the necessary libraries and tools.

We recommend using the Legacy Arduino IDE (1.8.X) to program ESP32 based PLCs, although other ESP compatible software could be used. The Arduino 1.8.X IDE can be downloaded from this link. After downloading and installing the Arduino IDE, install the industrialshields-esp-32 boards package inside the IDE. This can be done by following this tutorial and selecting the industrialshields-esp-32 package in step number 6.

Power supply

The ESP32 based PLCs need to be powered with an external power supply, providing a voltage between 12 and 24Vdc. Caution! Although at first glance it may seem like the PLC works when powered with the USB port, this is not the case. The usage of an external power supply is mandatory for the PLC to perform properly. 

The consumption of ESP32 based PLCs range between 700 and 1500mA. Therefore, Industrial Shields recommends using a power supply capable of delivering at least 2A.

PSU specifications:

  • Voltage: between 12 and 24Vdc.
  • Intensity: at least 2A.

The diagram in this section illustrates the necessary connections to properly power a PLC.


Power Diagram

DIP Switches

The ESP32 based PLCs have some switches which can be used to configure certain functionalities of the PLC. This section explains how to use them properly. To differentiate between the different parts of the PLC and locate every switch accordingly, the following nomenclature will be used:

Zones Nomenclature

In each zone there are one or more switches, used to configure some of the PLC functionalities. The following tables indicate the purpose of each switch and how to configure them. 

A zone: bottom left switch

A zone switch

Switch

Off

On

1

X

X

2

RS232

EXP 2 or Serial 2 (depending on switch 4 state)

3

RS485

Serial 1 (TX1/RX1)

4

Serial 2 (TX2/RX2)

EXP2


  1. Not used.
  2. This switch is used to select between RS232, Serial2 and EXP2 (Expansion Shield 2), used together with switch 4. RS232 is selected when the switch is OFF. When ON, Serial2 or EXP2 will be active, depending on switch 4 value (see switch 4 configuration).
  3. This switch is used to select among RS485 (OFF) and Serial1 (ON).
  4. Used to select between EXP2 (ON) and Serial2 (OFF) when switch 2 is ON.


B, C and D Zone: Analog switch

Analog Switch

Switch

Off

On

1

AX.5

QX.5

2

AX.6

QX.6

3

AX.7

QX.7

4

X

X


These switches are used to choose between digital or analog output, according to the previous table. If it is set to OFF, only the corresponding analog output will be available. If it is set to ON, only the corresponding digital output will be available. The switches behave the same way in zones B, C and D, with the "X"  value being different depending on the zone:

  • Zone B: X = 0
  • Zone C: X = 1
  • Zone D: X = 2

Power consumption

This report explores how different ESP32 PLC models consume power during idle and high-output scenarios. Understanding these patterns is crucial for optimizing efficiency in industrial applications.

Resting

In this scenario, the ESP32 PLC is powered on, with all pins and communications turned off and utilizing a 24V power supply. This test measures the baseline power consumption when the device is idle and not actively engaged in any processing or output tasks.

Model

Current (mA)

Power (W)

21+902,16
42+89
2,136
58+77
1,848
19R+72
1,728
38R+73
1,752
57R+76
1,824
38AR+73
1,752
53ARR+75
1,8
57AAR+75
1,8
54ARA+78
1,872
50RRA+78
1,872

All outputs HIGH

For this test, the ESP32 PLC is configured to set all its output pins to a high state utilizing a 24V power supply. However, the outputs are not connected, which means that the power consumption will vary depending on the current drawn by the device connected to each output.

Model

Current (mA)

Power (W)

21+102
2,448
42+116
2,784
58+1202,88
19R+191
4,584
38R+304
7,296
57R+415
9,96
38AR+209
5,016
53ARR+3197,656
57AAR+221
5,304
54ARA+226
5,424
50RRA+328
7,872

Inputs & Outputs

Analog inputs

Analog input provides a way to read analog voltage levels, coding the value with an N-bit number. The analog inputs on the ESP32 based PLC use the internal GND for reference (the same as the power supply). The analog inputs on these PLCs have the following specifications:

  • Voltage range: from 0 to 10 Vdc.
  • Resolution: 11 bits, which means the read values can range between 0 and 2047. 

Additionally, the analog inputs can also be used as non isolated digital inputs tolerating up to 24Vdc. To do so, refer to the digital inputs section. The analog inputs are the ones between IX.7 and IX.12, with X being 0, 1 or 2 depending on the zone. You can identify the analog inputs on your device with the following symbol:

0V - 10Vdc Analog input

0V - 10Vdc Analog input

  

 The next diagram illustrates the necessary connections to properly use an analog input (when used as a digital, the input can tolerate up to 24V):

Analog Inputs Diagram

Software setup

In order to use them, the analog inputs must be configured in the set up part of the code, like it is usually done in common Arduino boards. Then they can be read using the "analogRead()" function, with the input name as its parameter. For example, I0.7 is read as I0_7:

void setup() {
  pinMode(I0_7, INPUT);
  Serial.begin(9600);
}

void loop() {
  Serial.println(analogRead(I0_7));
}

The following post might also be of interest: Learning the basics about analog inputs of an industrial PLC.


Digital inputs

Digital inputs are used to capture signals that exist in one of two states: high or low, true or false, etc. The ESP32 PLC digital inputs interpret as high values of 5 Vdc or higher, up to 24 Vdc, whereas values lower than 5V are interpreted as low. There are 2 types of inputs which can be used as digital input:

  • Digital isolated inputs (5 - 24 Vdc): these inputs are opto-isolated, which means they have an extra protection and they use an external ground pin for reference.  They are the pins from IX.0 to IX.6, where X is 0,1 or 2 depending on the zone. 
  • Digital non-isolated input (5 - 24 Vdc): these inputs are not opto-isolated, and they use the internal GND of the PLC as reference. They are the same as the analog inputs, going from IX.7 to IX.12, with X being 0, 1 or 2 depending on the zone.

You can identify them with the following symbols:

Isolated Input Symbol

5V - 24V isolated input

 

Non Isolated Input Symbol

5V - 24V non-isolated input

 

 The next diagrams illustrate the necessary connections to properly use both inputs as digital:

Digital Isolated Inputs Diagram

Digital Non Isolated Inputs Diagram

Software setup

In order to use them, the digital inputs must be configured in the set up part of the code, like it is usually done in common Arduino boards. Then they can be read using the "digitalRead()" function, with the input name as its parameter. For example, I0.0 is read as I0_0:

void setup() {
  pinMode(I0_0, INPUT);
  Serial.begin(9600);
}

void loop() {
  Serial.println(digitalRead(I0_0));
}

The following posts expand on this topic: Basics about digital inputs of an industrial controller, PNP Digital Inputs on industrial PLC.


Interrupt Inputs

Some of the digital inputs in the ESP32 PLC are interrupt capable, which means they can be used with ISRs (interrupt service routine) to trigger certain code execution when an event (a change of state in the pin) is detected. There are two pins of this type each zone: IX.5 and IX.6. They are used and connected as regular digital isolated inputs, and the interrupts are programmed through software.

Software setup

This is an example of how to use the interrupt pins. In this case, the function "isrI0_5()" is automatically called every time a change of state occurs on the I0.5 pin.

void setup() {
  // Begin serial port
  Serial.begin(9600);
  // Set input
  pinMode(I0_5, INPUT);
  //Initialize interrupt
  attachInterrupt(digitalPinToInterrupt(I0_5), isrI0_5, CHANGE);
}

void loop() {
  while(true);
}

void isrI0_5() {
  Serial.println("Interrupt activated");
}

To know more about interrupts inputs: How to use Interrupt Inputs with industrial Arduino boards

Analog Outputs

An analog output provides a voltage determined by a digital value with an N-bit number. The ESP32 PLCs can have between 3 and 9 analog outputs, depending on the model. These are labeled as AX.X,  and need to be selected via DIP switch to be used (check the hardware section on this page for more information.). Refer to the switch section in this page for more information about the switches. The analog outputs in the ESP32 PLC have the following specifications:

  • Voltage range: from 0 to 10 Vdc.
  • Resolution: 12 bits.

The analog outputs have a shared external GND pin, which needs to be connected to set the reference. This symbol identifies the analog outputs, and the following diagram illustrates how to connect:

Analog Output Symbol

0 - 10V analog output

Analog Output DiagramSoftware setup

The procedure to program the analog outputs is the same as regular Arduino: first, the pin mode must be set to "OUTPUT" in the setup of the code, and then the output can be written using "analogWrite()". The analog outputs can be referenced by its name and using a "_" instead of the ".". For example, A0.5 is used as A0_5:

void setup()
{
    pinMode(A0_0,OUTPUT);
}

// Loop function
void loop()
{  
    analogWrite(A0_5, 0);   
    delay(1000);  
    analogWrite(A0_5,200);
    delay(1000);
}

To know more about analog outputs: Basics about analog outputs of an industrial PLC.

Digital outputs

The ESP32 digital outputs can provide a low (0 Vdc) or high (up to 24 Vdc) value. These outputs are labeled as QX.X, and can be identified with the next symbol.

The output high value can range between 5 and 24 Vdc. This voltage needs to be set using two pins located next to the outputs: QVdc and COM(-). For instance, should you wanna set the output to 24V, the QVdc pin should be connected to 24V and the COM(-) pin to GND. The following diagram illustrates an example connection:

Digital output (PWM optional)

Digital output (PWM optional)


Digital Isolated Outputs Diagram

Software setup

The digital outputs must be configured in the setup part of the code like it is usually done in common Arduino boards, using the "pinMode()" first to set it as "OUTPUT", and "digitalWrite()" to change the output value. Check the following example:

void setup() {
  pinMode(Q0_0, OUTPUT);
}

void loop() {
  digitalWrite(Q0_0, HIGH);
  delay(1000);
  digitalWrite(Q0_0, LOW);
  delay(1000);
}

You can learn more about digital outputs in this post: Basics about digital outputs of an industrial PLC.


PWM output

In the ESP32 based PLCs, all the digital outputs can be used as PWM outputs.

The output high value can range between 5 and 24 Vdc. As when using them as simple digital outputs, this voltage needs to be set using two pins located next to the outputs: QVdc and COM(-). For instance, should you wanna set the output to 24V, the QVdc pin should be connected to 24V and the COM(-) pin to GND. The following diagram illustrates an example connection.

An example tutorial about how to program the PLC to use the PWM outputs can be found in this website.

Digital output (PWM)

PWM capable output



Digital PWM Output Diagram


Relay output

A relay is an electromagnetic switch controlled by an electric signal. In Industrial Shields units these devices are already integrated in their boards. The relays included in the ESP32 PLC have the following specifications:

  • Maximum DC current: 3A at 30Vdc.
  • Maximum AC current: 5A at 250Vac

Each relay output has two terminals, and is labelled as RX.X. The following diagram illustrates the connections:

Relay Output Diagram

Software setup

The relay output must be configured in the set up part of the code, using Arduino functions, and they are controlled as if they were digital outputs. The outputs can be referenced by the name shown in the serigraphy: R0.1 for instance is used as R0_1. Check the following example. When the output is set to "HIGH", the real i turned on, meaning the switch closes, whereas when it is set to "LOW" the switch is open.

void setup() {
  pinMode(R0_1, OUTPUT);
}

void loop() {
  digitalWrite(R0_1, HIGH);
  delay(1000);
  digitalWrite(R0_1, LOW);
  delay(1000);
}

To know more about the relay outputs, check out this post: Learning the basics about internal relays of an industrial PLC.

Communications

Ethernet

Ethernet is the most commonly used technology in wired local area networks ( LANs ). 

A LAN is a network of computers and other electronic devices that covers a small area such as a room, office, or building. It is used in contrast to a wide area network (WAN) , which spans much larger geographical areas. Ethernet is a network protocol that controls how data is transmitted over a LAN. Technically it is referred to as the IEEE 802.3 protocol. The protocol has evolved and improved over time to transfer data at the speed of a gigabit per second.

 The ESP32 PLCs incorporate an Ethernet port, using the W5500 controller, which communicates with the ESP32 using SPI. The W5500 is a Hardwired TCP/IP embedded Ethernet controller that provides easier Internet connection to embedded systems. This chip enables users to have Internet connectivity in their applications by using the single chip in which TCP/IP stack, 10/100 Ethernet MAC and PHY are embedded. With this chip users can integrate Ethernet into their applications.  

Software setup

The Industrial Shields boards package includes an "Ethernet" library, intended to facilitate the use of this protocol. Various examples are included with the library, you can check them out going to File > Examples > Ethernet inside the Arduino IDE.

Also take a look at the following program. Before running the code, ensure that your PLC is powered correctly, confirm that the Ethernet cable is securely connected to your device and make sure the "industrialshields-esp-32" board package is properly installed in your Arduino IDE. This code serves as a diagnostic tool to ensure the proper functioning of the Ethernet port. It establishes a connection to "www.google.com" through the W5500 controller using DHCP IP configuration. 

#include <Ethernet.h>

#define REMOTE "www.google.com"

const uint16_t port = 80;
uint8_t mac[] = {0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0x01};

EthernetClient c;

////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  Serial.begin(9600L);
  Serial.println("ethernet started");

  test();
}

////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  if (!c.connected()) {
    Serial.println("Disconnected");
    test();
  }
  delay(1000);
}

////////////////////////////////////////////////////////////////////////////////////////////////////
void test() {
  //if you need a DHCP IP use this configuration:
  Ethernet.begin(mac);
         
  switch (Ethernet.hardwareStatus()) {
    case EthernetW5100:
      Serial.println("W5100 found");
      break;

    case EthernetW5200:
      Serial.println("W5200 found");
      break;

    case EthernetW5500:
      Serial.println("W5500 found");
      break;

    default:
      Serial.println("Unknown hardware");
      break;
  }

  uint8_t MAC[6];
  Ethernet.MACAddress(MAC);
  for (int i = 0; i < 6; ++i) {
    if (i > 0) {
      Serial.print(':');
    }
    Serial.print(MAC[i], HEX);
  }
  Serial.println();

  //use this block with DHCP IP:
  Serial.println(Ethernet.localIP());
  if (Ethernet.localIP() == IPAddress({0,0,0,0})) {
    Serial.println("Local IP FAIL");
  } else {
    Serial.println("Local IP OK");
    if (c.connect(REMOTE, port)) {
      Serial.println("Remote connection OK");
    } else {
      Serial.println("Remote connection FAIL");
    }
   }
}

To know more about Ethernet communication:

RS-485

RS485, also known as TIA-485(-A), EIA-485, is a standard defining the electrical characteristics of drivers and receivers for use in serial communications systems.The ESP32 PLC includes half-duplex RS485 capabilites, thanks to the incorporated MAX485 transceiver chip.

The MAX485 is a low-power and slew-rate-limited transceiver used for RS-485 communication. It works at a single +5V power supply and the rated current is 300 μA. Adopting half-duplex communication to implement the function of converting TTL level into RS-485 level, it can achieve a maximum transmission rate of 2.5Mbps. MAX485 transceiver draws supply current of between 120μA and 500μA under the unloaded or fully loaded conditions when the driver is disabled.

If you want to know more about RS485, check out this post.

Hardware setup

In order to use the RS485 with the ESP32 PLCs, check the A zone bottom left switch: switch number 3 needs to be set to OFF in order to activate the RS485. For more information about the switches, check the "Initial installation - Hardware" section in this page.

The RS485 pins, A+ and B- need to be properly connected to the device the PLC is communicating with. Attention! Remember to properly power the PLC with a 12-24V power supply.

Software setup

Our boards package includes an RS485 library to make programming easier. This library is used as the Arduino Serial library, with methods such as "available()", "read()", etc.

Check out the following code, which establishes half duplex communication and allows the user to read or send messages from the terminal of the PC.

#include <RS485.h>

void setup() {
  // Begin Serial port
  Serial.begin(9600);
  // Begin RS485 port
  RS485.begin(9600, HALFDUPLEX);
}

void loop() {
  //Send one byte for the serial, receive this byte by rs485
  if (Serial.available()){
    read_from_serial();
  }
  if (RS485.available()){
    read_from_rs485();
  }
}

static void read_from_serial(void){
  char tx = Serial.read(); //Read byte
  if (tx != '\n') Serial.println(tx); //Print the byte
  RS485.write(tx); //Transmit by rs485
}

static void read_from_rs485(void){
  char rx = RS485.read(); //Receive the same byte
  if (rx != '\n') {
    Serial.println(rx); //Print the byte
  }
}

RS232

RS-232 is a standard for serial communication transmission of data. It formally defines the signals used in communication between DTE (Data Terminal Equipment) such as a computer terminal, and DCE (Data Circuit-terminating Equipment or Data Communication Equipment), such as a modem. The ESP32 PLC includes a MAX232 transceiver chip, allowing full-duplex communication through RS232. The MAX232 is a dual transmitter/dual receiver that is used to convert the RX, TX, CTS, RTS signals, converting signals from Serial TTL to TIA-232 (RS-232) serial port.

If you want to know more about RS232, check this post.

Hardware setup 

In order to use the RS232 with the ESP32 PLCs, check the A zone bottom left switch: switch number 2 needs to be set to OFF in order to activate the RS232. For more information about the switches, check the "Initial installation - Hardware" section in this page.

The RS232 pins, TX and RX need to be properly connected to the device the PLC is communicating with. Attention! Remember to properly power the PLC with a 12-24V power supply.

Software setup

Once the hardware configuration is done, it is possible to proceed with the software configuration and its usage. Firstly, it is necessary to include the RS232.h library provided by our boards package. Then, the communication must be initialized with "RS232.begin(<baudrate>);". After this RS232 can already be used with the functions "RS232.read();" and "RS232.write();". 

Check the following read and write examples:

// Include Industrial Shields libraries
#include <RS232.h>

//// IMPORTANT: check switches configuration

//////////////////////////////////////////////////////////////////////////////////////////////

void setup() {

  // Begin serial port
  Serial.begin(9600);
  // Begin RS232 port
  RS232.begin(38400);

}

///////////////////////////////////////////////////////////////////////////////////////////////

void loop() {

  // Wait bytes in the serial port
  if (Serial.available()) {
    byte tx = Serial.read();

    // Echo the byte to the serial port again
    Serial.write(tx);

    // And send it to the RS-232 port
    RS232.write(tx);

  }   
}

// Include Industrial Shields libraries
#include <RS232.h>

//// IMPORTANT: check switches configuration

//////////////////////////////////////////////////////////////////////////////////////////////

void setup() {
  // Begin serial port
  Serial.begin(9600);
  // Begin RS232 port
  RS232.begin(38400);

}

//////////////////////////////////////////////////////////////////////////////////////////////

void loop() {

  // Print received byte when available
  if (RS232.available()) {
    byte rx = RS232.read();

    // Hexadecimal representation
    Serial.print("HEX: ");
    Serial.print(rx, HEX);

    // Decimal representation
    Serial.print(", DEC: ");
    Serial.println(rx, DEC);

  }
}

Serial TTL

Serial TTL is a communication Interface between two devices with working at a low level voltage. Two signals are used: Tx (Transmit Data) and Rx (Receive Data), which allow full-duplex communication. The ESP32 PLCs have two external TTL ports, Serial 1 (RX1/TX1) and Serial 2 (RX2/TX2).

To know more about the serial TTL interface, visit this blog.

Hardware setup 

The ESP32 PLC features two serial ports, which need to be activated using the A zone bottom left switch (to know more about the switch configuration, check the "Initial installation - Hardware" section in this page):

  • Serial 1 (TX1, RX1): switch 3 needs to be set to ON.
  • Serial 2 (TX2, RX2): switch 2 needs to be set to ON and switch 4 needs to be set to OFF.

For the Serial communication to work, you need to make the following connections between the PLC and the other device:

  • TX -> RX
  • RX -> TX
  • GND, both devices need to share a common ground.

Attention! The ESP32 PLCs serial ports work at 3.3V levels. Higher voltage levels might damage the PLC. 

Also, remember to properly power the PLC with a suitable 12-24Vdc power supply.

Software setup

In order to use the Serial communication with the PLC, the Arduino "Serial" object can be used. Check the following example, which uses Serial 1, to send and receive byte using the USB serial port and the Serial 1. To use the Serial 2 instead of the 1, the "Serial2" object must be used.

void setup() {
  // Initialize serial connections
  Serial.begin(9600);
  Serial1.begin(9600);
}

void loop() {
  // Read byte from Serial and send it through Serial 1
  if (Serial.available()) { // Check if there is available byte to read
    Serial1.print(Serial.read());
  }

  // Read byte from Serial 1 and send it through Serial   
  if (Serial1.available()) {
    Serial.print(Serial1.read());
  }
}

I2C

I2C is a serial communications protocol. It is a master-slave synchronous protocol and 2 cables are used, one for the clock (SCL) and one for the data (SDA). The master controls the bus and creates the clock signal, and uses addressing to communicate with the slaves. It is a very used bus in the industry, mainly to communicate microcontrollers and their peripherals in integrated systems, normally located in the same PCB. The speed is 100 Kbit/s in standard mode.

Hardware setup

The ESP32 PLCs have one I2C port, with the SCL and SDA pins. Other devices can be connected to this bus as slaves. When connecting other devices, keep in mind the following specifications:

  • The I2C port works at 5V. Higher voltage levels might damage the PLC. 
  • The I2C pins, SCL and SDA, are pulled up to 5V.

Also, remember to properly power the PLC with a suitable 12-24Vdc power supply.

Software Setup

The I2C can be used with the library "Wire". Check the following example which implements an I2C scanner that searches the bus for any connected devices. When a device is detected, it will be reported to the serial monitor. Note that if you connect the I2C pins (SDA and SCL) to an other device, it should appear in the scan.

Before running the code, ensure that your PLC is powered correctly, verify that the "industrialshields-esp-32" board package is correctly installed in your Arduino IDE and that you have selected the correct PLC model inside your IDE.

#include "Wire.h"

void setup() {
  Serial.begin(115200);
  Wire.begin();
}

void loop() {
  byte error, address;
  int nDevices = 0;

  delay(5000);

  Serial.println("Scanning for I2C devices ...");
  for(address = 0x01; address < 0x7f; address++){
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if (error == 0){
      Serial.printf("I2C device found at address 0x%02X\n", address);
      nDevices++;
    } else if(error != 2){
      Serial.printf("Error %d at address 0x%02X\n", error, address);
    }
  }
  if (nDevices == 0){
    Serial.println("No I2C devices found");
  }
}

To know more about I2C communication:

SPI

The  Serial Peripheral Interface (SPI) is a synchronous serial communication interface specification used for short-distance communication, primarily in embedded systems. SPI devices communicate in full duplex mode using a master-slave architecture, usually with a single master. 3 pins are used with SPI communication: SCLK, MOSI, MISO. Additionally, one extra pin for each slave, called chip select (CS) or slave select (SS) is used to select the slave that is being talked to in the bus.

The ESP32PLCs feature one SPI port.

Hardware setup

In order to use the SPI, the 3 mention pins (SCLK, MISO, MOSI) must be properly connected:

Function

PLC Pin

ESP32 Pin

MISO

SO

GPIO 19

MOSI

SI

GPIO 23

CLOCK

SCK

GPIO 18

In addition, a chip select pin might need to be used for each slave in order to address it. The ESP32 PLC has some GPIO which can be used to fulfill this function. Check the GPIO function in this page to know more about the available pins.

Attention! The SPI works at 3.3V voltage levels, any higher voltage might damage the PLC.

Also, remember to properly power the PLC with a suitable 12-24Vdc power supply.

Software setup

The "industrialshields-esp32" boards package includes an SPI library, based on the Arduino SPI library. This library allows programming the ESP32 as an SPI master.

This program shows how to set up the ESP32 as a master in SPI communication, and send and receive data. In this case the character "0" is sent, and the received data is stored in the corresponding variable (SPI transfer is based on a simultaneous send and receive) and printed through the serial port.

#include <SPI.h>

// Set pin as the slave select:
const int slaveSelectPin = GPIO_0;
volatile byte receivedData;

void setup() {
  Serial.begin(9600);
  // Set the slaveSelectPin as an output:
  pinMode(slaveSelectPin, OUTPUT);
  // Initialize SPI:
  SPI.begin();
}

void loop() {

  SPI.beginTransaction(SPISettings(100000, MSBFIRST, SPI_MODE0));
  digitalWrite(slaveSelectPin, LOW); // Start of transmission: set chip select LOW
​  receivedData = SPI.transfer('0');
  digitalWrite(slaveSelectPin, HIGH); // End of transmission: set chip select HIGH
  SPI.endTransaction();​

Serial.println((char)receivedData);

  delay(100);

}

To know more about SPI check the following post: Bus SPI on PLC Arduino from Industrial Shields

Bluetooth

Bluetooth is a wireless technology standard. It was developed as a way to exchange data over a short range and it operates in the 2400-2483.5 MHz range within the ISM 2.4 GHz frequency band. Data is split into packets and exchanged through one of the 79 designed Bluetooth channels (each of which with a 1 MHz bandwidth). 

The ESP32 PLCs have Bluetooth capabilities thanks to the ESP32 microcontroller. No hardware setup is needed in order to use it, the only requirement is for the PLC to be properly powered using a 12-24Vdc power supply.

Software setup

This example shows how to read bytes and send bytes through Bluetooth using BluetootSerial. The Serial port is used to send and receive data from the PC. To communicate with the PLC through Bluetooth a mobile app like "Serial Bluetooth Terminal" can be used. To do so, establish the Bluetooth connection with the PLC and select the device on the app.

Remember to make sure you have the industrialshields-esp-3 board package properly installed in your Arduino IDE.

#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

void setup() {
  Serial.begin(115200);
  SerialBT.begin("ESP32test"); //Bluetooth device name
  Serial.println("The device started, now you can pair it with bluetooth!");
}

void loop() {
  if (Serial.available()) {
    SerialBT.write(Serial.read());
  }
  if (SerialBT.available()) {
    Serial.write(SerialBT.read());
  }
  delay(20);
}

To check more examples about Bluetooth: Interact with M-Duino WiFi/BLE industrial PLC via Bluetooth

Wi-Fi

Similarly to other wireless connection types like Bluetooth, Wi-Fi is a radio transmission technology built upon a set of standards to allow high-speed and secure communications between a wide variety of digital devices, access points and hardware. It makes it possible for Wi-Fi capable devices to access the internet without the need for wires and it can operate over short and long distances, be locked down and secured, or open and free. All this makes Wi-Fi really versatile and easy to use.

The ESP32 PLCs have Wi-Fi capabilities thanks to the ESP32 microcontroller. No hardware setup is needed in order to use it, the only requirement is for the PLC to be properly powered using a 12-24Vdc power supply.

Software setup

Check this example sketch to know how to setup a Wi-Fi connection. This code uses the "WiFi.h" library to connect the ESP32 to your desired Wi-Fi. It reports to the serial monitor the IP address used to connect. 

Remember to make sure you have the industrialshields-esp-3 board package properly installed in your Arduino IDE, and make sure to change the ssid and password variables to your desired Wi-Fi configurations.

#include "WiFi.h"

const char* ssid = "YOUR_SSID";
const char* password = "YOUR_PASSWORD";

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(WiFi.status());
  }
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void loop() {

}​​

To know more about the Wi-Fi communication: 

Extra features

RTC

RTC stands for Real Time clock, en electronic device that measures the passage of time. Although keeping time can be done without an RTC, using one has benefits such as:

  • Mantaining the time without needing to set ti again after a reboot, shutdown, etc.
  • Low power consumption (important when running from alternate power.
  • Frees the main control system for time-critical tasks.
  • Sometimes more accurate than other methods.

The ESP32 PLC include a DS1307 RTC module, which communicates with the ESP32 microcontroller using I2C. The DS1307 serial real-time clock is a lowpower, full binary-coded decimal (BCD) clock/calendar, including 56 bytes of NV SRAM. Iprovides seconds, minutes, hours, day, date, month, and year information. 

In order to power the RTC when the PLC is not  connected, the PLC includes a 3,3V lithium coin cell battery which can be used to supply the RTC.

No hardware setup is needed in order to use the RTC, the only requirement is for the PLC to be properly powered using a 12-24Vdc power supply, and to have a lithium coin cell battery to maintain the time when the PLC has no power.

Software setup

The RTC library, included with our boards package, can be used to interact with the RTC. Check the following code example where time is read from the RTC and printed to the serial monitor. 

Remember to make sure you have the industrialshields-esp-3 board package properly installed in your Arduino IDE.

// RTC library example
// by Industrial Shields
#include <RTC2.h>
////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
  Serial.begin(9600L);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
  if (!RTC.read()) {
    Serial.println("Read date error: is time set?");
    }
     else {
    Serial.print("Time: ");
    Serial.print(RTC.getYear());
    Serial.print("-");
    Serial.print(RTC.getMonth());
    Serial.print("-");
    Serial.print(RTC.getMonthDay());
    Serial.print(" ");
    Serial.print(RTC.getHour());
    Serial.print(":");
    Serial.print(RTC.getMinute());
    Serial.print(":");
    Serial.print(RTC.getSecond());
    Serial.print(" (");
    Serial.print(RTC.getTime());
    Serial.println(")");
  }
  delay(1000);
}

ESP32 Dual Core

The ESP32 programmable logic controller include 2 Xtensa 32-bit LX6 microprocessors. When we run code on Arduino IDE, by default, it runs on core 1, as we can check with this simple program:

void setup() {
​Serial.begin(115200);
​Serial.print("setup() running on core ");
​Serial.println(xPortGetCoreID());
}

void loop() {
​Serial.print("loop() running on core ");
​Serial.println(xPortGetCoreID());
}

However, we can also use the second core, for better performance and efficiency. In order to work with the second core, we just need to define a second loop function, called "loop1()". The code inside this function will be executed by core 0, whereas the code inside the usual "loop()" function is executed by core 1. This way we can define different tasks for each core:

void setup() {
  // Setup code
}
void loop() {
  // Core 1 tasks
}
void loop1() {
  // Core 0 tasks
}

Organizing the program like this we can take advantage of the 2 cores in the ESP32. Some considerations need to be made when using the dual core, though, as concurrency problems may appear: for example if both try to use the Serial at the same time. In order to avoid this problems mechanisms such as semaphores might be used.

Check this blog post to know more about the ESP32 dual core.

FreeRTOS

FreeRTOS is a popular open-source real-time operating system (RTOS) designed for microcontrollers and small embedded systems. It provides a lightweight, scalable, and portable operating system kernel, along with a range of software components and tools to support the development of embedded applications. FreeRTOS can be used with the Arduino IDE on ESP32 boards to add real-time operating system functionality to your projects.

With FreeRTOS, you can create multiple tasks in your sketch, each with its own priority, and use synchronization mechanisms like semaphores and mutual exclusion to coordinate the tasks. This can be useful for real-time applications that require precise timing and coordination of tasks.

There is no need to include any library to use FreeRTOS with ESP32 based PLCs, since it is integrated into ESP-IDF as a component (Arduino leverages ESP-IDF).

One of the most useful features of FreeRTOS are tasks, schedulables pieces of code. In order to create a task the function xTaskCreate() is used.

Softwares setup

This program creates 2 tasks to periodically set HIGH and LOW two digital outputs. The LEDs on the PLC

TaskHandle_t Task1;
TaskHandle_t Task2;

void setup() {
Serial.begin(115200);
pinMode(Q0_0,OUTPUT);
pinMode(Q0_1,OUTPUT);

xTaskCreate(Task1code,"Task1",10000,NULL,1,&Task1);
delay(500);

xTaskCreate(Task2code,"Task2",10000,NULL,1,&Task2);
delay(500);
}

void Task1code( void * parameter ){
Serial.print("Task1 is running on core ");
Serial.println(xPortGetCoreID());

for(;;){
digitalWrite(Q0_0, HIGH);
delay(500);
digitalWrite(Q0_0, LOW);
delay(500);
}
}

void Task2code( void * parameter ){
Serial.print("Task2 is running on core ");
Serial.println(xPortGetCoreID());

for(;;){
digitalWrite(Q0_1, HIGH);
delay(1000);
digitalWrite(Q0_1, LOW);
delay(1000);
}
}

void loop() {}

SD

Secure Digital (SD) cards are non-volatile memory storage devices that use flash memory technology. Designed for portable electronic devices, SD cards provide a reliable and compact solution for data storage.

The ESP32 PLC incorporates an SD card slot with the following specifications:

  • MicroSD slot.
  • Up to 32GB of storage (although higher capacity cards can be used, only the first 32GB will be accessible and usable).
  • FAT32 and FAT16 allowed as file system architectures.

The SD slot communicates with the ESP32 using SPI, and there is no hardware configuration needed. Remember to power the PLC with a proper 12-24Vdc power supply.

Software setup

The "industrialshields-esp32" boards package includes an SD library to facilitate its usage. Check the following example, which initializes the SD card and prints the contents of it root directory through the serial port.

#include <SD.h>

File root;

void setup() {
// Open serial communications and wait for port to open:
  Serial.begin(115200);
  // wait for Serial Monitor to connect. Needed for native USB port boards only:
  while (!Serial);

  Serial.print("Initializing SD card...");

  int SS = SD.begin() ;
  if (!SS) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("1. is a card inserted?");
    Serial.println("2. is your wiring correct?");
    Serial.println("3. did you change the chipSelect pin to match your shield or module?");
    Serial.println("Note: press reset or reopen this serial monitor after fixing your issue!");
    while (true);
  } else {
    Serial.println(SS, DEC);
   
  }

  Serial.println("initialization done.");

  root = SD.open("/");

  printDirectory(root, 0);

  Serial.println("done!");
}

void loop() {
  // nothing happens after setup finishes.
}

void printDirectory(File dir, int numTabs) {
  while (true) {

    File entry =  dir.openNextFile();
    if (! entry) {
      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) {
      Serial.print('\t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } else {
      // files have sizes, directories do not
      Serial.print("\t\t");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

GPIO

There are some GPIO pins of the ESP32 directly available in the PLC, which can be used for various tasks. Depending on the pin they can work at either 3.3V or 5V. Caution! Using a higher voltage than the tolerated by the pin might damage the PLC. Check the following tables to see each available pin.

3.3V Pins 

PLC​ Terminal
ESP32 Pin
TX1
  GPIO 17
RX1
  GPIO 16
VN
SENS VN (GPIO 39)
VP
SENS VP (GPIO 36)
SO
GPIO 19
SI
GPIO 23
SCK
GPIO 18
  • Serial 1 – RX1/TX1: The Serial1 pins can also work as a 3.3V pin.
  • Vp/Vn: These pins can work as 3.3V input only.
  • SPI – MISO/MOSI/SCK: These pins can also work as 3.3V pins, though only if the Ethernet protocol or SPI are not going to be used. As the Ethernet protocol uses the SPI to communicate with the ESP board, both the Ethernet connection and the pins as GPIO cannot be used at the same time.


Warning: in order to use the Serial pins as GPIO, the corresponding switches must be set up, so make sure the Serial 1 is selected (check the Hardware section for more details).


5V Pins 

PLC Terminal 
ESP32 Pin
SCL 
  GPIO 22
SDA 
  GPIO 21
 GPIO0
 GPIO 0
  • I2C Pins – SDA/SCL: The I2C protocol is meant to work in a pull-up configuration, which are included in the board. Therefore, they can only be used in pull-up configuration: it reads 5V when nothing is connected.
  • GPIO 0:The GPIO_0 pin works at 5Vdc, and can be used as a digital input or output.