Hello ARDUINOLOVERS.
I'm presenting the following issue with my 20x4 LCD.
I'm using Arduino for a PID control, with a 4x4 keypad and an H-bridge.
The PID control is for a tank level.
The code seems to be correct, but the LCD doesn't display the menu or anything correctly. It just shows full contrast lines as if it were trying to plot something but not displaying anything.
I've already checked the connections, the screen, etc., but everything seems fine.
Could you help me? I would really appreciate it if you could provide a solution. Now, I'll provide the following code:
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <PID_v1.h>
/* Declarando pines */
const int trig = A0;
const int echo = A1;
const int velMotor = A2;
const int rs = A3;
const int en = A4;
const int d4 = A5;
const int d5 = 2;
const int d6 = 3;
const int d7 = 4;
/* Declarando variables */
int duracion;
double h_sensor = 40;
float distancia, distancia_suma;
byte z, y; // Variables para control de menu
/* Variables PID */
double distancia_actual, distancia_setpoint = 10, pid_salida, nuevo_setpoint;
double kp = 50, ki = 190, kd = 10;
PID pid_resultante(&distancia_actual, &pid_salida, &distancia_setpoint, kp, ki, kd, DIRECT);
/* Para el Keypad 4x4 */
const byte FILAS = 4;
const byte COLUMNAS = 4;
char keys[FILAS][COLUMNAS] = {
{'1', '2', '3', 'A'},
{'4', '5', '6', 'B'},
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'},
};
// Donde va conectado
byte pinesFilas[FILAS] = {A5, A4, A3, A2};
byte pinesColumnas[COLUMNAS] = {4, 3, 2, A1};
Keypad teclado = Keypad(makeKeymap(keys), pinesFilas, pinesColumnas, FILAS, COLUMNAS);
/* Variables del teclado numerico */
char TECLA;
char NUM[3];
byte INDICE = 0;
String NUMERO_VALOR;
/* DirecciĂłn I2C de la pantalla LCD */
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
/* Funcion para ver la distancia con el uso del sensor de proximidad */
double distancia_promedio(int n) {
digitalWrite(trig, HIGH);
delay(1);
digitalWrite(trig, LOW);
float distancia_previo = distancia;
duracion = pulseIn(echo, HIGH);
distancia = duracion / 58.2;
distancia_suma = 0;
for (byte i = 1; i <= n; i++) {
digitalWrite(trig, HIGH);
delay(1);
digitalWrite(trig, LOW);
duracion = pulseIn(echo, HIGH);
distancia = duracion / 58.2;
if (distancia < 0)
distancia = 0;
distancia_suma = distancia_suma + distancia;
delay(2);
}
float regreso = h_sensor - distancia_suma / n;
if (regreso <= 0)
regreso = distancia_actual;
return regreso;
}
/* Menu Setpoint */
void m_setpoint() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Setpoint=" + String(distancia_setpoint) + "cm ");
while (y < 1) {
TECLA = teclado.getKey();
if (TECLA) {
if (TECLA != 'A' and TECLA != 'B' and TECLA != 'C' and TECLA != 'D' and TECLA != '*' and TECLA != '#') {
if (INDICE == 0)
NUM[1] = ' ';
NUM[INDICE] = TECLA;
INDICE++;
lcd.setCursor(0, 0);
if (INDICE <= 2)
lcd.print("Setpoint=" + String(NUM) + "cm ");
if (INDICE == 2)
INDICE = 0;
NUMERO_VALOR = String(NUM);
nuevo_setpoint = NUMERO_VALOR.toDouble();
if (nuevo_setpoint < 4 or nuevo_setpoint > 27) {
lcd.setCursor(0, 1);
lcd.print("Rango 4<d<27");
} else {
lcd.setCursor(0, 1);
lcd.print("A)Aceptar ");
}
}
if (TECLA == 'A' and nuevo_setpoint > 4 and nuevo_setpoint < 27) {
distancia_setpoint = nuevo_setpoint;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Nuevo Setpoint");
lcd.setCursor(0, 1);
lcd.print("establecido:" + String(int(distancia_setpoint)) + "cm");
delay(4000);
lcd.clear();
INDICE = 0;
NUM[0] = ' ';
NUM[1] = ' ';
z = 1;
y = 1;
}
}
}
}
// Menu Variables
void m_variables() {
lcd.clear();
while (y < 1) {
lcd.setCursor(0, 0);
lcd.print("Kp=" + String(int(kp)));
lcd.setCursor(8, 0);
lcd.print("Kd=" + String(int(kd)));
lcd.setCursor(0, 1);
lcd.print("Ki=" + String(int(ki)));
lcd.setCursor(8, 1);
lcd.print("D)Salir");
TECLA = teclado.getKey();
if (TECLA) {
if (TECLA == 'D') {
lcd.clear();
z = 1;
y = 1;
}
}
}
}
// Menu Ver PID
void ver_pid() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Pulse D");
lcd.setCursor(0, 1);
lcd.print("para salir");
delay(2000);
lcd.clear();
while (y < 1) {
distancia_actual = distancia_promedio(100);
pid_resultante.Compute();
lcd.setCursor(0, 0);
lcd.print("PID=" + String(pid_salida) + " ");
lcd.setCursor(0, 1);
lcd.print("D = " + String(distancia_actual) + "cm ");
analogWrite(velMotor, pid_salida);
Serial.println(String(distancia_actual) + "," + String(pid_salida) + "," + String(distancia_setpoint));
TECLA = teclado.getKey();
if (TECLA) {
if (TECLA == 'D') {
z = 1;
y = 1;
lcd.clear();
}
}
}
}
// Menu Principal
void Menu() {
lcd.clear();
while (z < 1) {
lcd.setCursor(0, 0);
lcd.print("A)SP C)PlD ");
lcd.setCursor(0, 1);
lcd.print("B)Var. D)Salir");
TECLA = teclado.getKey();
if (TECLA) {
if (TECLA == 'A') {
m_setpoint();
}
if (TECLA == 'B') {
m_variables();
}
if (TECLA == 'C') {
ver_pid();
}
if (TECLA == 'D') {
lcd.clear();
z = 1;
}
}
}
}
/* Setup y Loop */
void setup() {
Serial.begin(9600);
pinMode(velMotor, OUTPUT);
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
pid_resultante.SetMode(AUTOMATIC);
lcd.begin(20, 4); // Iniciar pantalla LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Iniciando...");
delay(2000);
}
void loop() {
z = 0;
y = 0; // Variables para loop de menu
distancia_actual = distancia_promedio(100);
pid_resultante.Compute(); //Obtienes el valor de PID
lcd.setCursor(0, 0);
lcd.print("D = " + String(distancia_actual) + "cm ");
lcd.setCursor(0, 1);
lcd.print("A)Editar");
analogWrite(velMotor, pid_salida);
Serial.println(String(distancia_actual) + "," + String(pid_salida) + "," + String(distancia_setpoint));
TECLA = teclado.getKey();
if (TECLA) {
if (TECLA == 'A') {
digitalWrite(velMotor, LOW);
Menu();
}
}
}