const byte analogPin = A0; // Analog pin connected to the Hall sensor
const byte pwmPin1 = 9; // PWM output pin 1
const byte pwmPin2 = 10; // PWM output pin 2
volatile unsigned long pulseStartTime = 0; // Start time for pulse measurement
volatile unsigned long pulseEndTime = 0; // End time for pulse measurement
volatile byte pulseCount = 0; // Counter for pulses
const int threshold = 716; // Analog threshold value for 3.5V
unsigned long previousMillis = 0; // Stores the last time the loop ran
const long interval = 10; // Desired interval in milliseconds
void setup() {
Serial.begin(9600);
pinMode(analogPin, INPUT);
pinMode(pwmPin1, OUTPUT);
pinMode(pwmPin2, OUTPUT);
}
void loop() {
unsigned long currentMillis = millis();
// Check if the desired interval has passed
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis; // Save the last time the loop ran
int sensorValue = analogRead(analogPin); // Read the analog value from the sensor
// Check for falling edge (voltage drop)
if (sensorValue < threshold) {
if (pulseCount == 0) {
pulseStartTime = micros(); // Start timing when the first pulse is detected
}
pulseCount++; // Increment pulse count
// Check if four pulses have been detected
if (pulseCount == 4) {
pulseEndTime = micros(); // End timing after the fourth pulse
unsigned long timeInterval = pulseEndTime - pulseStartTime;
// Calculate RPM from the time interval of four pulses
float crankshaftRPM = calculateCrankshaftRPM(timeInterval);
int pwmValue = mapRPMToPWM(crankshaftRPM);
analogWrite(pwmPin1, pwmValue);
analogWrite(pwmPin2, pwmValue);
// Print the RPM and the corresponding PWM percentage
float pwmPercentage = (pwmValue / 255.0) * 100.0;
Serial.print("RPM: ");
Serial.print(crankshaftRPM);
Serial.print(" | PWM: ");
Serial.print(pwmPercentage);
Serial.println("%");
pulseCount = 0; // Reset pulse count for the next measurement
}
// Wait until the signal rises above the threshold again
while (analogRead(analogPin) < threshold) {
delay(1); // Small delay to avoid busy-waiting
}
}
}
}
float calculateCrankshaftRPM(unsigned long interval) {
// Calculate RPM from the time interval for four pulses
// Multiply by 2 because the camshaft is at half the speed of the crankshaft
// 1,000,000 us in a second, 60 seconds in a minute, 4 pulses per revolution
// The previous correction factor was 980 / 365. Adjusting to 1000 / 850.
float currentCorrectionFactor = 980.0 / 365.0;
float adjustmentFactor = 1000.0 / 850.0;
float finalCorrectionFactor = currentCorrectionFactor * adjustmentFactor;
return (1000000.0 / interval) * 60 * 2 / 4 * finalCorrectionFactor;
}
int mapRPMToPWM(float rpm) {
if (rpm <= 2000) {
return 255; // 100% PWM for RPM <= 2000
} else if (rpm <= 4500) {
return mapRPMToPWM_FirstRange(rpm);
} else {
return mapRPMToPWM_SecondRange(rpm);
}
}
int mapRPMToPWM_FirstRange(float rpm) {
// Map RPM to PWM duty cycle for the first range (2000 to 4500 RPM)
float startPercentage = 100.0; // 100% PWM at 2000 RPM
float endPercentage = 50.0; // Ending PWM percentage at 4500 RPM
// Calculate the PWM value based on the percentage
float pwmPercentage = map(rpm, 2000, 4500, startPercentage, endPercentage);
int pwmValue = (pwmPercentage / 100.0) * 255.0; // Convert percentage to 0-255 scale
return pwmValue;
}
int mapRPMToPWM_SecondRange(float rpm) {
// Map RPM to PWM duty cycle for the second range (4500 RPM onwards)
float startPercentage = 50.0; // Starting PWM percentage at 4500 RPM
float endPercentage = 40.0; // Ending PWM percentage at 7000 RPM
// Calculate the PWM value based on the percentage
float pwmPercentage = map(rpm, 4500, 7000, startPercentage, endPercentage);
int pwmValue = (pwmPercentage / 100.0) * 255.0; // Convert percentage to 0-255 scale
return pwmValue;
}
[code]