#include <LiquidCrystal.h>
// Pin Definitions
const int startButtonPin = A0; // START button input from A0
const int upButtonPin = A2; // UP button input from A2
const int downButtonPin = A3; // DOWN button input from A3
const int stopButtonPin = A4; // STOP button input from A4
const int potPin = A1; // Potentiometer input from A1
const int crankPin = 2; // Crank signal output
const int camPin = 3; // Cam signal output
// Pin setup for the LCD (4-bit mode)
const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // Initialize LCD using the pins defined
// Variables
int currentRPM = 0;
bool systemRunning = false; // Flag to control system state (running or not)
int vehicleIndex = 0; // Index of the selected vehicle
// Button state variables
bool lastUpButtonState = LOW;
bool lastDownButtonState = LOW;
bool lastStartButtonState = LOW;
bool lastStopButtonState = LOW;
unsigned long lastButtonPressTimeUp = 0; // Debounce for UP button
unsigned long lastButtonPressTimeDown = 0; // Debounce for DOWN button
unsigned long lastButtonPressTimeStart = 0; // Debounce for START button
unsigned long lastButtonPressTimeStop = 0; // Debounce for STOP button
const unsigned long debounceDelay = 50; // Debounce delay in milliseconds
// List of vehicles and their corresponding frequencies (Hz)
String vehicles[] = {
"Mahindra 60 - 2 cranks & cam", "Toyota 4AGE", "Toyota 4AGZE", "Daihatsu 3+1", "Mitsubishi 4g6",
"Mitsubishi 3A92", "Mazda FE3 36-1", "Mazda 36-2-2-2", "Mazda 323 AU", "Mazda CAS 24-2",
"BMW boxer (+)", "BMW boxer (-)", "Nissan 360 6 slo", "Volvo d12", "40 - 1 (Ford V10)",
"36 - 1 crank only", "24 - 1 crank only", "12 - 1 crank & cam", "12 - 3 oddball",
"60 - 2 & half moon", "60 - 3 cranks only", "Mahindra 60 - 2 cranks & cam",
"Fiat 1.8 16V c/c", "Ford ST170", "Honda 25 2ch 180", "Honda 25 2ch 90", "Honda 25 2ch 60",
"Honda CG 150", "Honda RC51 w/cam", "Honda D17 C/12+1", "Yamaha 60 2ch", "Yamaha R1 02-03",
"4 - 1 crank & cam", "Kawasaki ZX-6", "Kawasaki ZXR-250", "Suzuki DRZ400", "Suzuki Bandit",
"4 - 1 crank & cam", "Simple 40deg 180", "4 cylinder dizzy", "6 cylinder dizzy", "Dis 4 cyl 50/40"
};
int frequencies[] = {
200, 300, 400, 6000, 6000, 3600, 400, 800, 600, 1200, 4000, 200, 0, 18000, 1200, 3600, 0,
3600, 300, 400, 0, 3600, 1200, 3600, 3600, 800, 0, 1800, 1200
};
// Variables to store the previous time for the signals
unsigned long lastCrankToggleTime = 0;
unsigned long lastCamToggleTime = 0;
int crankState = LOW; // Initial state of the crank pin
int camState = LOW; // Initial state of the cam pin
// Function declaration for getCamFrequency
int getCamFrequency(int vehicleIndex, int crankFrequency);
// Setup
void setup() {
lcd.begin(16, 2);
lcd.print("Md Alamgir");
lcd.setCursor (0, 1);
lcd.print("Mob. 8641951536");
delay(3000);
lcd.clear();
// Set output pins for crank and cam to LOW initially
pinMode(crankPin, OUTPUT);
pinMode(camPin, OUTPUT);
digitalWrite(crankPin, LOW); // Ensure crank is LOW at start
digitalWrite(camPin, LOW); // Ensure cam is LOW at start
// Set button input pins
pinMode(startButtonPin, INPUT);
pinMode(upButtonPin, INPUT);
pinMode(downButtonPin, INPUT);
pinMode(stopButtonPin, INPUT);
displayVehicleInfo();
}
// Main loop
void loop() {
// Read button states using digitalRead (high or low)
bool upButtonState = digitalRead(upButtonPin) == HIGH;
bool downButtonState = digitalRead(downButtonPin) == HIGH;
bool startButtonState = digitalRead(startButtonPin) == HIGH;
bool stopButtonState = digitalRead(stopButtonPin) == HIGH;
// Handle UP button press (only change if rising edge is detected)
if (upButtonState && lastUpButtonState == LOW && (millis() - lastButtonPressTimeUp) > debounceDelay) {
increaseVehicleIndex();
lastButtonPressTimeUp = millis(); // Update last press time
}
// Handle DOWN button press (only change if rising edge is detected)
if (downButtonState && lastDownButtonState == LOW && (millis() - lastButtonPressTimeDown) > debounceDelay) {
decreaseVehicleIndex();
lastButtonPressTimeDown = millis(); // Update last press time
}
// Handle START button press
if (startButtonState && lastStartButtonState == LOW && (millis() - lastButtonPressTimeStart) > debounceDelay) {
startSystem();
lastButtonPressTimeStart = millis(); // Update last press time
}
// Handle STOP button press
if (stopButtonState && lastStopButtonState == LOW && (millis() - lastButtonPressTimeStop) > debounceDelay) {
stopSystem();
lastButtonPressTimeStop = millis(); // Update last press time
}
// Update button states for the next iteration
lastUpButtonState = upButtonState;
lastDownButtonState = downButtonState;
lastStartButtonState = startButtonState;
lastStopButtonState = stopButtonState;
// Read potentiometer for RPM control
currentRPM = map(analogRead(potPin), 0, 1023, 50, 5000); // Adjust RPM range from 50 to 5000 RPM
// Update display based on system status
if (systemRunning) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("RPM: ");
lcd.print(currentRPM);
lcd.setCursor(0, 1);
lcd.print("Vehicle: ");
lcd.print(vehicles[vehicleIndex]);
} else {
displayVehicleInfo();
}
// Generate crank and cam signals only when the system is running
if (systemRunning) {
generateSensorSignals();
} else {
// Ensure LEDs are off when system is stopped
digitalWrite(crankPin, LOW);
digitalWrite(camPin, LOW);
}
delay(100); // Update every 100ms (faster than the 500ms before)
}
// Function to display vehicle info
void displayVehicleInfo() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Select Vehicle");
lcd.setCursor(0, 1);
lcd.print(vehicles[vehicleIndex]);
}
// Function to start the system
void startSystem() {
if (!systemRunning) {
systemRunning = true;
lcd.clear();
lcd.print("System Started");
}
}
// Function to stop the system
void stopSystem() {
systemRunning = false;
lcd.clear();
lcd.print("System Stopped");
}
// Function to increase vehicle index
void increaseVehicleIndex() {
if (vehicleIndex < (sizeof(vehicles) / sizeof(vehicles[0])) - 1) {
vehicleIndex++;
} else {
vehicleIndex = 0;
}
displayVehicleInfo();
}
// Function to decrease vehicle index
void decreaseVehicleIndex() {
if (vehicleIndex > 0) {
vehicleIndex--;
} else {
vehicleIndex = sizeof(vehicles) / sizeof(vehicles[0]) - 1;
}
displayVehicleInfo();
}
// Function to generate crank and cam sensor signals
void generateSensorSignals() {
// Get the crank frequency based on the selected vehicle and RPM
int vehicleFrequency = frequencies[vehicleIndex];
int crankFrequency = map(currentRPM, 50, 5000, vehicleFrequency / 2, vehicleFrequency * 2);
if (crankFrequency > 0) {
// Calculate period for crank signal (in milliseconds)
int crankPeriod = 1000 / crankFrequency;
// Generate crank signal (square wave) on crankPin using millis()
if (millis() - lastCrankToggleTime >= crankPeriod / 2) {
crankState = (crankState == LOW) ? HIGH : LOW; // Toggle the state
digitalWrite(crankPin, crankState); // Output the crank signal
lastCrankToggleTime = millis(); // Update the last toggle time
}
// Adjust cam signal frequency or timing based on vehicle
int camFrequency = getCamFrequency(vehicleIndex, crankFrequency);
// Calculate period for cam signal (in milliseconds)
int camPeriod = 1000 / camFrequency;
// Generate cam signal (square wave) on camPin using millis()
if (millis() - lastCamToggleTime >= camPeriod / 2) {
camState = (camState == LOW) ? HIGH : LOW; // Toggle the state
digitalWrite(camPin, camState); // Output the cam signal
lastCamToggleTime = millis(); // Update the last toggle time
}
}
}
// Function to calculate cam signal frequency based on vehicle index
int getCamFrequency(int vehicleIndex, int crankFrequency) {
// Adjust cam signal frequency based on vehicle type
return crankFrequency / 2; // Assuming cam signal is half the crank signal frequency for most vehicles
}