Hi guys, have project, so only Arduino can help.
Need to transfer HIGH to the pin for control starter relay with 4 if's, started write sketch, but too many questions came straight away.
Sorted only 1st step, it's rpm counter, switching relay off if rpm is higher than 14HZ.
Cannot connect another inputs.
What I need:
After switching ignition on, delay 2 sec, then checking engine rpm, brake pedal position, gearbox park position. If all signals are HIGH, turn on relay, after rpm is more than 14HZ relay off.
What I did:
int rpm = 3;
int brake = 2;
int park = 4;
int ign = 5;
int start = 12;
int rpmStat = 0;
int brakeStat = 0;
int parkStat = 0;
int ignStat = 0;
int on = 0;
void setup() {
pinMode(3, INPUT); //rpm input up to 14HZ(engine running = 18HZ))
pinMode(2, INPUT); //brake switch +
pinMode(4, INPUT); //park/neutral switch +
pinMode(5, INPUT); //15 terminal IGNITION +
pinMode(12, OUTPUT); //Starter relay control
}
void loop()
{ int Speed;
Speed = 500000/pulseIn(3, HIGH);
{
if (Speed > 7)
{
digitalWrite(12, HIGH);
}
else
{
digitalWrite(12, LOW);
}
}
}
Hi, @keturi
Welcome to the forum and thank you for using code tags.
You could improve the readability of you code by using the variable names you have given you I/O pins.
I have edited it to make it easier to read, including pressing [ CTRL ] [ T } in the IDE to auto format the structure.
Also there were an extra set of { } that weren't needed.
int rpmPin = 3;
int brakePin = 2;
int parkPin = 4;
int ignPin = 5;
int startPin = 12;
int rpmStat = 0;
int brakeStat = 0;
int parkStat = 0;
int ignStat = 0;
int on = 0;
void setup()
{
pinMode(rpmPin, INPUT); //rpm input up to 14HZ(engine running = 18HZ))
pinMode(brakePin, INPUT); //brake switch +
pinMode(parkPin, INPUT); //park/neutral switch +
pinMode(ignPin, INPUT); //15 terminal IGNITION +
pinMode(startPin, OUTPUT); //Starter relay control
}
void loop()
{
int Speed;
Speed = 500000 / pulseIn(rpmPin, HIGH);
if (Speed > 7)
{
digitalWrite(startPin, HIGH);
}
else
{
digitalWrite(startPin, LOW);
}
}
You might be worth drawing a flow chart. or a check list table to sort out what you outputs can be with different combinations of input.
Is your "14 Hz" supposed to represent 14 pulses per second (7 RPS = 420 RPM) or 14 RPS (840 RPM)?
Speed = 500000 / pulseIn(rpmPin, HIGH);
WARNING: Depending on the source of your pulses, the HIGH time may not be proportional to the speed. Usually it's the time between pulses that is of interest. You can get close with (pulseIn(rpmPin, HIGH) + pulseIn(rpmPin, LOW)) but that still leaves the possibility of timeout where the value ZERO is returned. You don't get good answers when you divide by zero.
I recommend something like this for measuring revolutions per second:
// No need to wait longer than 1/10th second.
const unsigned long timeout = 100000ul;
unsigned long highTime = pulseIn(rpmPin, HIGH, timeout);
unsigned long lowTime = pulseIn(rpmPin, LOW, timeout);
if (highTime != 0 && lowTime != 0)
{
rps = MsecPerSec / PulsePerRev / (highTime + lowTime);
}
else // Timeout on one or both samples
rps = 0;
Thanks for everybody, I have made some modifications and it started work.
Now can work for mods which can make project more stable, about counting rpm's as well.
Sketch now:
const int rpmPin = 3;
const int brakePin = 2;
const int parkPin = 4;
const int ignPin = 5;
const int startPin = 12;
int rpmState = 0;
int brakeState = 0;
int parkState = 0;
int ignState = 0;
void setup() {
Serial.begin(9600);
pinMode(rpmPin, INPUT); //rpm input up to 15HZ(engine running = 18HZ)
pinMode(brakePin, INPUT); //brake switch +
pinMode(parkPin, INPUT); //park/neutral switch +
pinMode(ignPin, INPUT); //15 terminal IGNITION +
pinMode(startPin, OUTPUT); //Starter relay control
digitalWrite(startPin, LOW);
}
void loop(){
int Speed;
Speed = 500000/pulseIn(rpmPin, HIGH);
rpmState = digitalRead(rpmPin);
brakeState = digitalRead(brakePin);
ignState = digitalRead(ignPin);
parkState = digitalRead(parkPin);
if (Speed <= 7 && brakeState == HIGH && ignState == HIGH)
{
digitalWrite(startPin, HIGH);
}
else
{
digitalWrite(startPin, LOW);
}
}type or paste code here
it's very hard to comment on this approach, not a state machine or sequencer
clearly there is a state where if the ignition is off, the motor should be turned off and nothing else done.
for your 2 sec delay, there needs to be the recognition of when the ignition changes from off to on, possibly in the OFF state (not ignition off), a 2 sec delay occurs and then setting the state to ON
and then after the delay, there is a state where normal processing occurs.
That's how you wrote it. That's how you said it should work: "After switching ignition on, delay 2 sec, ". Did you mean "After turning starter relay on, wait two seconds and check engine RPM...".
Why the delay? Why not: When the ignition is on, and the "Speed" is below 8, and the, brake is on, and the transmission is in Park, then turn on the starter relay.
void loop()
{
brakeState = digitalRead(brakePin);
ignState = digitalRead(ignPin);
parkState = digitalRead(parkPin);
// If everything is ready for starting
if (ignState == HIGH && brakeState == HIGH && parkState == HIGH)
{
unsigned long pulseWidth = pulseIn(rpmPin, HIGH);
// If the engine is not running
if (pulseWidth == 0 || (500000ul / pulseWidth) <= 7)
{
// Turn on the starter
digitalWrite(startPin, HIGH);
}
else
{
// Engine running. Turn off the starter
digitalWrite(startPin, LOW);
}
}
else
{
// NOT READY TO START. Make sure the starter is off
digitalWrite(startPin, LOW);
}
}
I mean that starter motor relay control should be ON after 2 sec when ign, rpm, brake and park are HIGH and immediately OFF when one of the functions is LOW. Now it works ok, but after engine is started, starter motor spins 2 sec extra.
Because after press ignition button, for a while all car systems running check and if to run starter relay straight away, some warning lights coming on. With 2 sec delay all is good only damaging starter motor while keeping on 2 sec extra.
it would be easier to implement this (or at least discuss it in terms of) three states: OFF, ON, STARTED
the ignition switch off forces the state to OFF, tuning the ignition switch on sets the state of ON and after a 2 sec delay the state is set to STARTED
Here is a version with a timer to turn on the starter after everything has been ready for two seconds:
const int rpmPin = 3;
const int brakePin = 2;
const int parkPin = 4;
const int ignPin = 5;
const int startPin = 12;
unsigned long LastTimeNotReady = 0;
void setup()
{
// Serial.begin(9600); // Not using any Serial I/O
pinMode(rpmPin, INPUT); //rpm input up to 15HZ(engine running = 18HZ)
pinMode(brakePin, INPUT); //brake switch +
pinMode(parkPin, INPUT); //park/neutral switch +
pinMode(ignPin, INPUT); //15 terminal IGNITION +
digitalWrite(startPin, LOW);
pinMode(startPin, OUTPUT); //Starter relay control
}
void loop()
{
int brakeState = digitalRead(brakePin);
int ignState = digitalRead(ignPin);
int parkState = digitalRead(parkPin);
// If everything is ready for starting
if (ignState == HIGH && brakeState == HIGH && parkState == HIGH)
{
unsigned long pulseWidth = pulseIn(rpmPin, HIGH);
// If the engine is not running
if (pulseWidth == 0 || (500000ul / pulseWidth) <= 7)
{
// Turn on the starter if everything has been ready for at least 2 seconds
if (millis() - LastTimeNotReady >= 2000)
digitalWrite(startPin, HIGH);
}
else
{
// Engine running. Turn off the starter
digitalWrite(startPin, LOW);
LastTimeNotReady = millis();
}
}
else
{
// NOT READY TO START. Make sure the starter is off
digitalWrite(startPin, LOW);
LastTimeNotReady = millis();
}
}
This can be simplified to: 500000ul <= 7 * pulseWidth 500000ul / 7 <= pulseWidth
'71429ul <= pulseWidth'
pulseWidth >= 71429ul
You can make the pulseIn() more responsive by setting a timeout below the default of a million microseconds:
const unsigned long maxPulseWidthRunning = 71429ul;
unsigned long pulseWidth = pulseIn(rpmPin, HIGH, maxPulseWidthRunning * 2);
// If the engine is not running
if (pulseWidth == 0 || pulseWidth >= maxPulseWidthRunning)
{
This will get an answer in under 0.15 seconds rather than waiting a whole second to find out that the motor isn't turning.
Thanks guys for the help. all working, tested on the car, only increased rpm from value 7 to 8, as well changed inputs to LOW, because for 5V inputs from 12V used optocouplers.
//Range Rover TDV8 2013 starter relay control
const int rpmPin = 3;
const int brakePin = 2;
const int ignPin = 5;
const int parkPin = 4;
const int startPin = 12;
const unsigned long maxPulseWidthRunning = 30000ul; // 15HZ
unsigned long LastTimeNotReady = 0;
void setup()
{
pinMode(rpmPin, INPUT); //rpm input up to 15HZ(engine running = 18HZ)
pinMode(brakePin, INPUT); //brake switch +
pinMode(parkPin, INPUT); //park/neutral swith +
pinMode(ignPin, INPUT); //15 terminal IGNITION +
digitalWrite(startPin, LOW);
pinMode(startPin, OUTPUT); //Starter relay control
}
void loop()
{
int brakeState = digitalRead(brakePin);
int ignState = digitalRead(ignPin);
int parkState = digitalRead(parkPin);
// If everything is ready for starting
if (ignState == LOW && brakeState == LOW && parkState == LOW)
{
unsigned long pulseWidth = pulseIn(rpmPin, LOW, maxPulseWidthRunning * 2);
// If the engine is not running
if (pulseWidth == 0 || pulseWidth >= maxPulseWidthRunning)
{
// Turn on the starter if everything has been ready for at least 2 seconds
if (millis() - LastTimeNotReady >= 2000)
digitalWrite(startPin, HIGH);
}
else
{
// Engine running. Turn off the starter
digitalWrite(startPin, LOW);
LastTimeNotReady = millis();
}
}
else
{
// NOT READY TO START. Make sure the starter is off
digitalWrite(startPin, LOW);
LastTimeNotReady = millis();
}
}
Have problem, every time when engine started and running and pressed brake pedal, after 2 seconds starter relay working again.
if (pulseWidth == 0 || pulseWidth >= maxPulseWidthRunning)
{
// Turn on the starter if everything has been ready for at least 2 seconds
if (millis() - LastTimeNotReady >= 2000)
digitalWrite(startPin, HIGH);
}
else
{
// Engine running. Turn off the starter
digitalWrite(startPin, LOW);
LastTimeNotReady = millis();
}
I understand, that pulseWidth higher than nominal, stops starter relay, so stop is really working, but should to avoid of start when engine is running. This point not understand why not working.