Hello,
I have been working on this project for a few days and quickly realized that the delay() function has its limits, especially considering the code relies on information being displayed on a 16x2 LCD for long periods of time (10 seconds). This means that the "read" button state function in the code has to wait upwards of 10-15 seconds before it is detected and any action is subsequently executed.
Basically, This code is intended to control a servo motor connected to a grille shutter mechanism in a car. The servo motor opens and closes the grille shutter at different angles to control the airflow and improve the aerodynamics of the vehicle. Therefore, the button state detection has to be snappy.
I researched about millis() function and how it can help the code run parallel processing instead of only sequential events. I have implemented the millis() function into the code but the delay has not changed. Just wondering if I am implementing this the wrong way and if there is a better alternative to tackle the issue.
Overall, the codes is fully functional with my prototype. The only issue is the pushbutton delay.
Code :
#include <Servo.h>
#include <ezButton.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // I2C address 0x27, 16 columns and 2 rows
byte arrow[8] = { //Custom arrow LCD character
0b00100,
0b01110,
0b11111,
0b00100,
0b00100,
0b00100,
0b00100,
0b00100
};
// Constants
const int BUTTON_PIN = 7; // Arduino pin connected to button's pin
const int SERVO_PIN = 9; // Arduino pin connected to servo motor's pin
const int LED_PIN = 2; // Green LED connected to digital pin 2
const int LED2_PIN = 3; // Red LED connected to digital pin 3
const int POS_SWITCH = 4; // State of position switch (HIGH = SHUT)
const int POS_ERROR = 8; // State of both position switches (HIGH = error)
const unsigned long buttonPeriod = 100;
Servo servo; // Create servo object to control a servo
// Variables
int angle = 0; // The current angle of servo motor
int posSwitchState = HIGH; // Variable to store the read value
int posErrorState = LOW; // Variable to store the read value
int buttonState = LOW;
unsigned long currentMillis = 0;
unsigned long buttonPreviousMillis = 0;
void Button() {
if (currentMillis - buttonPreviousMillis >= buttonPeriod) {
buttonPreviousMillis = currentMillis;
if (digitalRead(BUTTON_PIN) == LOW) {
buttonState = HIGH;
} else {
buttonState = LOW;
}
if (buttonState == HIGH) {
digitalWrite(LED_PIN, HIGH); // Turn the LED on (HIGH is the voltage level)
delay(500); // Wait for a second
digitalWrite(LED_PIN, LOW); // Turn the LED off (LOW is the voltage level)
delay(500); // Wait for 0.5 seconds
// Change the angle of the servo motor
if (angle == 0)
angle = 45;
else if (angle == 45)
angle = 90;
else
angle = 0;
servo.write(angle); // Control the servo motor according to the angle
}
}
}
void setup() {
Serial.begin(9600); // Initialize serial
pinMode(BUTTON_PIN, INPUT_PULLUP); // Set Arduino pin to input pull-up mode
pinMode(LED_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
pinMode(POS_SWITCH, INPUT); // Shutter grille status (open or shut)
pinMode(POS_ERROR, INPUT); // Detects position error
servo.attach(SERVO_PIN); // Attach the servo on pin 9 to the servo object
servo.write(angle);
lcd.init(); // Initialize the LCD
lcd.backlight();
lcd.createChar(0, arrow); // create a new custom character (index 1)
lcd.setCursor(0, 0);
lcd.print(" HONDA CR-Z ");
lcd.setCursor(1, 1);
lcd.print(" WELCOME ");
delay(5000);
}
void loop() {
currentMillis = millis(); // get the current time
Button(); // call the Button function
posSwitchState = digitalRead(POS_SWITCH); // Read the input pin
if (posSwitchState == HIGH) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" GRILLE SHUTTER");
lcd.setCursor(2, 1);
lcd.print(" [ SHUT ]");
delay(5000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("AERODYNAMIC MODE");
lcd.setCursor(2, 1);
lcd.print("[ LOW DRAG ]");
delay(5000);
} else {
}
if (angle == 45) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" GRILLE SHUTTER");
lcd.setCursor(0, 1);
lcd.print(" [ 50 % OPEN ] ");
delay(5000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" COOLING MODE 1");
lcd.setCursor(2, 1);
lcd.print("[ DRAG ] ");
lcd.setCursor(4, 1);
lcd.write(arrow);
lcd.setCursor(5, 1);
lcd.write(arrow);
lcd.setCursor(6, 1);
lcd.write(arrow);
delay(5000);
}
else if (angle == 90) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" GRILLE SHUTTER");
lcd.setCursor(0, 1);
lcd.print(" [ 100 % OPEN ] ");
delay(5000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" COOLING MODE 2");
lcd.setCursor(0, 1);
lcd.print(" [ DRAG ] ");
lcd.setCursor(3, 1);
lcd.write(arrow);
lcd.setCursor(4, 1);
lcd.write(arrow);
lcd.setCursor(5, 1);
lcd.write(arrow);
lcd.setCursor(6, 1);
lcd.write(arrow);
lcd.setCursor(7, 1);
lcd.write(arrow);
delay(5000);
} else {
}
posErrorState = digitalRead(POS_ERROR); // Read the input pin
if (posErrorState == HIGH && ((angle > 5 && angle < 45) || (angle > 45 && angle < 75))) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" GRILLE SHUTTER");
lcd.setCursor(1, 1);
lcd.print("[ POS. ERROR ]");
delay(5000);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" CHECK SYSTEM !");
lcd.setCursor(0, 1);
lcd.print("[ POSSIBLE JAM ]");
delay(5000);
digitalWrite(LED2_PIN, HIGH);
digitalWrite(SERVO_PIN, LOW);
} else {
}
}
Thank you !