If it were my project, I would read the digital output with the interrupt.
it cant do anything past just reading rpm
i add in the bare minimum to map both outputs and it start reading 10,000 rpm. with out any outputs it reads pretty true
The interaction of the solenoid outputs (VVT1, VVT2) on 9 and 10 with the interrupt input sound like a hardware issue to me. EMI can certainly generate a false interrupt signal. Depending on how fast the interrupts occur at max rpm, it might be possible to use a RC filter on the input.
Defeating interrupt noise by switching to analog input is not dealing with the root cause, but if all else fails, it may be a way to go. I would certainly try and work out the digital issues before going down that route.
Please provide some documentation on the solenoids.
Are the solenoids connected through opto isolators?
Can they work at analogWrite frequencies?
Are they configured with flyback diodes?
Are the solenoid output and signal input wires in one bundle?
No opto isolators
No idea on the frequency. Just throwing some science at it to see what happens.
Yes on diodes. Measured about 70 volt flyback
Not really in a bundle. Loose at the moment
There are definitely libraries to use, but you say your rpm reading is solid without any output. Counting the number of interrupts, or pulses sensed by analog or digital read in a period of time is one of the standard methods.
There are other methods which look at the time gap between two pulses.
I do not think that your issue is measuring the rpm generated by the PT4 tach output of the megasquirt. As you say, it is a very good signal. Have you configured PT4 to activate based on rpm? How many pulses per rotation.
The main issue that I see is that the output is interactive with the input. That is not a software issue, but rather hardware. You maybe able to filter some of the noise in software with lockout or debounce techniques, but it is better to get to the root cause.
An automotive environment is very difficult.
the mega might have some advantage to run this project?
I don't see how it would be different. The advantage of the Mega is lots of I/O pins and additional hardware serial ports. I don't think that either of these features is useful for your application.
EDIT:
It is a nice even signal.
What does the signal look like when you turn on the outputs?
first thing i going to do after coffee is test for rpm levels to make sure it looks clean while driving
const byte analogPin = A5; // Analog pin connected to the Hall sensor
const float threshold = 4.5; // Voltage threshold for detection
const int numCycles = 4; // Number of cycles to count for RPM calculation
unsigned long cycleStartTimes[numCycles]; // Store start times for each cycle
unsigned long cycleEndTimes[numCycles]; // Store end times for each cycle
int cycleCount = 0;
bool aboveThreshold = false;
void setup() {
Serial.begin(115200);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
}
void loop() {
float voltage = analogRead(analogPin) * (5.0 / 1023.0); // Read and convert the voltage
// Detect voltage threshold crossing
if (!aboveThreshold && voltage > threshold) {
aboveThreshold = true;
} else if (aboveThreshold && voltage < threshold) {
aboveThreshold = false;
cycleEndTimes[cycleCount] = millis(); // Record end time
cycleCount++;
if (cycleCount >= numCycles) {
// Calculate average cycle time and RPM
unsigned long totalTime = 0;
for (int i = 0; i < numCycles; i++) {
totalTime += (cycleEndTimes[i] - cycleStartTimes[i]);
}
float averageTime = totalTime / (float)numCycles;
float rpm = 60000.0 / averageTime; // Convert time to RPM
// Reset for next reading
cycleCount = 0;
cycleStartTimes[0] = millis();
// Output to Serial for debugging
Serial.print("RPM: ");
Serial.println(rpm);
// Set output pins based on RPM thresholds
digitalWrite(3, rpm > 500 ? HIGH : LOW);
digitalWrite(5, rpm > 1200 ? HIGH : LOW);
digitalWrite(6, rpm > 2000 ? HIGH : LOW);
digitalWrite(9, rpm > 3000 ? HIGH : LOW);
digitalWrite(10, rpm > 4000 ? HIGH : LOW);
digitalWrite(11, rpm > 5000 ? HIGH : LOW);
} else {
cycleStartTimes[cycleCount] = millis(); // Start time for next cycle
}
}
}
when it cools down a little outside i am going to try out the new code my dad helped with. he suggested a Schmitt trigger. i never heard of it but like the strategy. so far it reads accurate with the /3 added in for the rpm and smooth
const byte analogPin = A5; // Analog pin connected to the Hall sensor
float highThreshold = 4.0; // High voltage threshold
float lowThreshold = 2.0; // Low voltage threshold
const int numCycles = 4; // Number of cycles to count for RPM calculation
unsigned long totalTime; // Total ms from first cycle start to last start
unsigned long cycleStartTimes[numCycles]; // Store start times for each cycle
int cycleCount = 0;
bool aboveThreshold = false;
float currentThreshold = highThreshold; // Start with high threshold
const int fadeStartRPM = 2600; // RPM threshold to start the fade
const int fadeStopRPM = 1600; // RPM threshold to stop the fade and turn off
// Adjustable RPM thresholds and PWM map values
// Idle Range
const int idleRangeRPMMin = 1300; // Minimum RPM for the idle range
const int idleRangeRPMMax = 1800; // Maximum RPM for the idle range
const int idleRangeStartPWM = 100; // Start PWM percentage for the idle range
const int idleRangeEndPWM = 255; // End PWM percentage for the idle range
// Torque Range
const int torqueRangeRPMMin = 2001; // Minimum RPM for the torque range
const int torqueRangeRPMMax = 4000; // Maximum RPM for the torque range
const int torqueRangeStartPWM = 255; // Start PWM percentage for the torque range
const int torqueRangeEndPWM = 150; // End PWM percentage for the torque range
// Peak Range
const int peakRangeRPMMin = 4001; // Minimum RPM for the peak range
const int peakRangeRPMMax = 5500; // Maximum RPM for the peak range
const int peakRangeStartPWM = 150; // Start PWM percentage for the peak range
const int peakRangeEndPWM = 0; // End PWM percentage for the peak range
bool TCCEnabled = false; // Track the state of TCC
// Define pins
const int TCC = 3;
const byte VVT1 = 9;
const byte VVT2 = 10;
const int controlPin = 4; // Digital input pin for controlling TCC
void setup() {
Serial.begin(115200);
// Initialize the PWM output pins
pinMode(VVT1, OUTPUT);
pinMode(VVT2, OUTPUT);
pinMode(TCC, OUTPUT);
// Initialize the control pin as an input
pinMode(controlPin, INPUT);
}
void loop() {
// Check TCC control state
int controlState = digitalRead(controlPin);
if (controlState == LOW) {
stopTCC(); // If pin is LOW, stop TCC
} else if (controlState == HIGH) {
startTCC(); // If pin is HIGH, start TCC
}
float voltage = analogRead(analogPin) * (5.0 / 1023.0); // Read and convert the voltage
if (aboveThreshold && voltage < lowThreshold) { // Just reset threshold flag
aboveThreshold = false; // When it goes low
}
// Detect voltage threshold crossing, save time, increment cycle count
if (!aboveThreshold && voltage > highThreshold) {
aboveThreshold = true; // Set upper threshold flag
cycleStartTimes[cycleCount] = millis(); // Record start time of high threshold
cycleCount++; // Increment Cycle Count
}
if (cycleCount >= numCycles) { // Calculate average cycle time and RPM
// Total Time is time from cyclesStartTimes[0] to cyclesStartTimes[numCycles-1]
// That is, one cycle is start time to start time
// Just like a day is midnight to midnight
totalTime = cycleStartTimes[numCycles - 1] - cycleStartTimes[0];
float averageTime = totalTime / (float)(numCycles - 1); // Average for one cycle
// Four start times is three full cycles
float rpm = 60000.0 / averageTime / 3; // Convert time to RPM
// Reset for next reading
cycleCount = 0;
// Output to Serial for debugging
Serial.print("RPM: ");
Serial.println(rpm);
// Variable to store PWM value
int pwmValue = 0;
// Map the RPM value to the desired PWM range based on the idle range
if (rpm >= idleRangeRPMMin && rpm <= idleRangeRPMMax) {
pwmValue = map(rpm, idleRangeRPMMin, idleRangeRPMMax, idleRangeStartPWM, idleRangeEndPWM);
}
// Map the RPM value to the desired PWM range based on the torque range
else if (rpm >= torqueRangeRPMMin && rpm <= torqueRangeRPMMax) {
pwmValue = map(rpm, torqueRangeRPMMin, torqueRangeRPMMax, torqueRangeStartPWM, torqueRangeEndPWM);
}
// Map the RPM value to the desired PWM range based on the peak range
else if (rpm >= peakRangeRPMMin && rpm <= peakRangeRPMMax) {
pwmValue = map(rpm, peakRangeRPMMin, peakRangeRPMMax, peakRangeStartPWM, peakRangeEndPWM);
}
// Set the PWM output
analogWrite(VVT1, pwmValue);
analogWrite(VVT2, pwmValue);
// Check if the RPM is greater than the fade start threshold and TCC is enabled
if (TCCEnabled && rpm > fadeStartRPM) {
fadeTCC(0, 255, 500); // start, end, time
}
// Check if the RPM is below the fade stop threshold
if (rpm < fadeStopRPM) {
analogWrite(TCC, 0); // Turn off the PSI output
}
// Reset for next measurement
cycleStartTimes[0] = millis(); // Record the new initial start time
} else {
// Record the start time for the next cycle
cycleStartTimes[cycleCount] = millis();
}
}
// Handles stopping TCC by setting it to 0 and disabling TCC control
void stopTCC() {
analogWrite(TCC, 0); // Immediately set TCC value to 0
TCCEnabled = false; // Disable TCC
}
// Handles starting TCC by enabling TCC control
void startTCC() {
TCCEnabled = true; // Enable TCC
}
// Non-blocking fade function for TCC, with a final set to 255 after fade completes
void fadeTCC(int startValue, int endValue, int duration) {
static int currentStep = 0;
static unsigned long previousMillis = 0;
static int steps = 255; // Number of steps for the fade
static int delayTime = duration / steps;
static float stepValue = (endValue - startValue) / float(steps);
static bool fading = false;
// Start the fading process if it's not already started
if (!fading) {
currentStep = 0;
previousMillis = millis();
fading = true;
}
// Continue the fading process
if (fading) {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= delayTime) {
previousMillis = currentMillis; // Reset the timer
int value = startValue + (stepValue * currentStep);
analogWrite(TCC, value);
currentStep++;
// Check if fade is complete
if (currentStep > steps) {
fading = false; // Stop the fading
analogWrite(TCC, 255); // Ensure TCC is set to 255 after fade completes
}
}
}
}