Panel Mountable ESP32 Industrial Controller | Norvi AGENT-AP01-BC1

by NORVI Controllers in Circuits > Microcontrollers

502 Views, 3 Favorites, 0 Comments

Panel Mountable ESP32 Industrial Controller | Norvi AGENT-AP01-BC1

Agent-2_color_edit.png

Norvi AGENT-AP01-BC1 is a panel mountable industrial controller in the Norvi lineup.

The features of this device are,

  • 4 Digital Inputs 24V
  • 4 Analog inputs (0-10V)
  • RS-485 Communication
  • WIFI & Bluetooth
  • Built-in OLED Display with 1 button

Check more about the model here - Norvi AGENT-AP01-BC1

To check the Norvi lineup - www.norvi.lk

In this instructable, We show how to read the analog inputs and display the status of the digital inputs & the push button using this device.

About the Display

IMG_20210707_151520.jpg
  • The device has a built-in 0.96 OLED SSD1306 display of 128 x 64 resolution. Its address is 03xC. The GPIOs 21(SDA) and 22(SCL)of Esp32 in the device are used for I2C communication with this display.

About the Analog Inputs

  • The device has an ADS1115 module of address 0x49. Same GPIOs, 21(SDA) and 22(SCL) of ESP32 in the device are used for I2C communication with the ADC.

To understand more about the working of the Analog inputs, check step 2 of this instructable.

GPIO Pins of Digital Inputs

IMG_20210707_152334.jpg
  • GPIO pins detail of Digital Inputs are as follows,
I.0 = 13    I.1 = 14   I.2 = 27    I.3 = 26
  • Here, the digital inputs are normally kept on/high (digital logic state "1") by using pull-up resistors inside the device. So when the connection is made the state changes to off/low(digital logic state "0").

To know more about how to work with the digital input side - Getting started with Norvi devices

Analog Inputs and GPIO Pins of RS-485 & Button

IMG_20210707_152109.jpg
  • There are 4 analog input pins starting from A0-A3 which are capable of measuring 0-10V industrial level voltages. The four inputs (A0-A3) are connected to the four channels of the ADS1115 module of address 0x49.
  • The Device has a built-in MAX485 driver with RX connected with GPIO3, TX connected with GPIO1 and RE & DE are connected with the GPIO2 (for flow control) of the Norvi device.
  • The GPIO4 pin is used for operation of the button.

Programming the Device to Measure the Voltage and Displaying It on the OLED Screen

  • Install the Adafruit SSD1306, Adafruit GFX, and Adafruit ADS1015 libraries in your Arduino IDE and upload the below sketch.
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_ADS1015.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

#define FC   2

int  buttonState = 0;
const int buttonPin = 4;

Adafruit_ADS1115 ads1(0x49);

float Voltage1 = 0.0;
float Voltage2 = 0.0;
float Voltage3 = 0.0;
float Voltage4 = 0.0;


Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

void setup() {
 
  pinMode(FC , OUTPUT);                            // Declare FLOW CONTROL pin as output
  Serial.begin(9600);                              // set serial communication baudrate
  ads1.begin();

  pinMode(13, INPUT);
  pinMode(14, INPUT);
  pinMode(27, INPUT);
  pinMode(26, INPUT);
  
  pinMode(buttonPin, INPUT);

  Wire.begin(21, 22);                            // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.display();

}

void loop()
{
  display.clearDisplay();
  update();
}

void update()
{
  float adc0;
  float adc1;
  float adc2;
  float adc3;
  
  adc0 = ads1.readADC_SingleEnded(0);
  adc1 = ads1.readADC_SingleEnded(1);
  adc2 = ads1.readADC_SingleEnded(2);
  adc3 = ads1.readADC_SingleEnded(3);  

  Voltage1 = (adc0 * 0.1875) / 1000;
  Voltage2 = (adc1 * 0.1875) / 1000;
  Voltage3 = (adc2 * 0.1875) / 1000;
  Voltage4 = (adc3 * 0.1875) / 1000;

  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 15);
  display.println("V1");
  display.setCursor(0, 25);
  display.println("V2");
  display.setCursor(0, 35);
  display.println("V3");
  display.setCursor(0, 45);
  display.println("V4");

  
  display.setCursor(55, 10);
  display.println("Inputs State");
  display.setCursor(70, 22);
  display.println(digitalRead(13));
  display.setCursor(80, 22);
  display.println(digitalRead(14));
  display.setCursor(90, 22);
  display.println(digitalRead(27));
  display.setCursor(100, 22);
  display.println(digitalRead(26));

  
  display.setCursor(55, 45);
  display.println("Button State");
  buttonState = analogRead(buttonPin);
  delay(50);
  display.setCursor(75, 55);
  display.println(analogRead(buttonPin));
  
  display.setCursor(20,15);
  display.println(Voltage1 * 2.5);
  display.setCursor(20,25);
  display.println(Voltage2 * 2.5);
  display.setCursor(20,35);
  display.println(Voltage3 * 2.5);
  display.setCursor(20,45);
  display.println(Voltage4 * 2.5);
  display.display();
  display.clearDisplay();
  
  digitalWrite(FC , HIGH);                      // Make FLOW CONTROL pin HIGH
  Serial.println("RS485 SUCCESS");              // Send RS485 SUCCESS serially
  Serial.flush();                               // Wait for transmission of data
  digitalWrite(FC , LOW) ;                      // Receiving mode ON
  delay(500);

}<br>

Installing ESP32 Board in Arduino IDE and Booting the Device

agent22.PNG
  • Select "ESP32 Dev Module" in your Arduino IDE to start programming the device as shown in the image.
  • ESP32 board must be installed under board manager, it is recommended to use the latest version of ESP32 board driver for Arduino. Due to the installation of different drivers and older versions of libraries, Arduino fails to upload the program to the controller.
  • In most cases, it is due to failure to enter the boot mode of the device. After uploading the program the device can be booted by pressing the boot hole using a pin.

Understanding the Code

  • The necessary libraries are imported to use I2C (Wire library), to write the display (Adafruit_SSD1306, and Adafruit_GFX libraries) and to read the analog value by the ADCs. (Adafruit_ADS1015 library)

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_ADS1015.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
  • Next, the flow control and the button pins are defined
#define FC   2
int  buttonState = 0;
const int buttonPin = 4;
  • The below line define the addres of the ADC.

Adafruit_ADS1115 ads1(0x49);
  • Then Float variables are defined to store the voltage value.

float Voltage1 = 0.0;
float Voltage2 = 0.0;
float Voltage3 = 0.0;
float Voltage4 = 0.0;<br>
  • Next, with the I2C communication protocol (&Wire), a display object with the width and height defined earlier is initialized.

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
  • Next, in setup(), we initialize the Serial Monitor at a baud rate of 9600.

Serial.begin(9600);          
  • Now the respective pin modes of digital input, flow control & button pin are defined.

  pinMode(FC , OUTPUT);                            // Declare FLOW CONTROL pin as output
  pinMode(13, INPUT);
  pinMode(14, INPUT);
  pinMode(27, INPUT);
  pinMode(26, INPUT);
  pinMode(buttonPin, INPUT);
  • In the following line, you initialize I2C by setting the sda and scl GPIOs to communicate with the display.

 Wire.begin(21, 22);          
  • Then the first ADS1115 module is initialized to begin its operation.

 ads1.begin();<br>
  • Next, the display is initialized using its address.

display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  • Using below lines, we can ensure whether our display is working correctly. Here the display check is done for 1s (1000ms) and this can be varied.

  display.clearDisplay();
  delay(1000);
  display.display();
  • Finally, Inside the loop() function, the function that is required to display the voltage readings, digital input & button status and the RS-485 communication is called.
 display.clearDisplay();
 update();
void update()
{
  float adc0;
  float adc1;
  float adc2;
  float adc3;

  adc0 = ads1.readADC_SingleEnded(0);
  adc1 = ads1.readADC_SingleEnded(1);
  adc2 = ads1.readADC_SingleEnded(2);
  adc3 = ads1.readADC_SingleEnded(3);  

  Voltage1 = (adc0 * 0.1875) / 1000;
  Voltage2 = (adc1 * 0.1875) / 1000;
  Voltage3 = (adc2 * 0.1875) / 1000;
  Voltage4 = (adc3 * 0.1875) / 1000;

  
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0, 15);
  display.println("V1");
  display.setCursor(0, 25);
  display.println("V2");
  display.setCursor(0, 35);
  display.println("V3");
  display.setCursor(0, 45);
  display.println("V4");

  
  display.setCursor(55, 10);
  display.println("Inputs State");
  display.setCursor(70, 22);
  display.println(digitalRead(13));
  display.setCursor(80, 22);
  display.println(digitalRead(14));
  display.setCursor(90, 22);
  display.println(digitalRead(27));
  display.setCursor(100, 22);
  display.println(digitalRead(26));

  
  display.setCursor(55, 45);
  display.println("Button State");
  buttonState = analogRead(buttonPin);
  delay(50);
  display.setCursor(75, 55);
  display.println(analogRead(buttonPin));
  
  display.setCursor(20,15);
  display.println(Voltage1 * 2.5);
  display.setCursor(20,25);
  display.println(Voltage2 * 2.5);
  display.setCursor(20,35);
  display.println(Voltage3 * 2.5);
  display.setCursor(20,45);
  display.println(Voltage4 * 2.5);
  display.display();
  display.clearDisplay();
  
  digitalWrite(FC , HIGH);                      // Make FLOW CONTROL pin HIGH
  Serial.println("RS485 SUCCESS");              // Send RS485 SUCCESS serially
  Serial.flush();                               // Wait for transmission of data
  digitalWrite(FC , LOW) ;                      // Receiving mode ON
  delay(500);
  
}