For function

Hi guys,

I am working on a traction control for my car.
The problem that i have is that i have an i pit from the engines crank sensor to read the rpm. There are 4 pulses per rotation.
What i want to do is that if the amount of traction loss is small i want the output to be on for 1 pulse every 8 , if the traction loss is bigger i want it to be on for 1pulse in 6. And so on.
I was focusing on the for function .

Can you give me some help?
Thanks all

I was focusing on the for function .

A for loop does not seem the right choice to do what you want.

Why not count the pulses, and if the traction loss is small turn on the power when the count reaches 8 but if it is larger turn on the power when the count reaches 6. In either case turn off the power when the next pulse is received and reset the count to zero.

Hi Ukhelibob,

right, I think thats good for me.

thanks

Hi with your help,
I managed to write this simple code.

pulseIn(frqeng,LOW); //reads crank rpm
sts2 = micros(); // start time stamp
for (uint32_t i=3; i>0; i--)
pulseIn(frqeng,HIGH);
ets2 = micros(); // end time stamp
EngRPM = ((3*1e6/(ets2-sts2))*convtorpm);

Serial.print ("rpm=");
Serial.print (EngRPM);

if (digitalRead(frqeng)==HIGH){
pls = (pls+1);}

Serial.print(" pulsenumber = ");
Serial.print(pls);

if (pls >= 5){
digitalWrite (optrac,HIGH) ;
Serial.println (" optrac High");}

else{
digitalWrite (optrac, LOW) ;
Serial.println (" optrac Low");
}

if (pls >= 4){
pls = 0;}

this 4 here was to disable this as i was crying in fuel gasses.
However, yes i managed to control it, but they system is not as fast a i want it to be, and this is just working on this few code, imagine when i will load all the code.
The crank sensor has 4 flags, so at 8000rpm that would be 533hz, which i believe is not alot for the arduino. Problem is that i didn't manage to make a misifire as a single . It makes misfires but it makes them as a batch i believe. I am not sure but tomorrow i will connect a spark gap on the coil and see what is happening.... ok i know whats happening, the crank signals must match that of the cam, and if one is lost the oem ecu will consider it as noise and it will have to see both signals to start from fresh....

pulseIn() returns a value. It is useless to call the function if you don't care what the value is.

I am using that because i use the rpm value somewhere else in the code.

cpur:
I am using that because i use the rpm value somewhere else in the code.

Then you better assign the return value to something, or that place somewhere else will get no data.

This counts 3 pulses...

     for (uint32_t i=3; i>0; i--)

pulseIn(frqeng,HIGH);

But it's a very poor way of doing that task. The Arduino can do nothing else during that time. It's also very poor writing a 2-line for() statement without using braces ({}). If your if() or for() goes over 1 line, you should always use braces for readability and future expansion.

Engine crank pulses are one of the very good reasons why the AVR designers included interrupt pins in their design. There's dedicated hardware inside the AVR chip which will do a lot of what you want to do. Look around for other projects. You have been given poor advice or you are reading the wrong blogs if this is the best design you have so far.

You always want to distribute misfires around the engine. If you consistently cause a miss on cylinder #1 then that cylinder gets cool while its neighbours are hot. This will warp the head and blow the head gasket, if it doesn't crack the block.

Dear MorganS,

But i think the expression you wrote;

for (uint32_t i=3; i>0; i--)
pulseIn(frqeng,HIGH);

will wait for 3 pulses then continue doing other code.
Please correct me if i am wrong , I never learnt programming, i am just learning.

And yes , i was trying to make it misfire the 9th , 7th, 5th, 3rd firings progressively dependant on how much traction loss was read in the previous code .

Thanks

Dear aarg,

It is assigned to EngRPM.

thanks

working it out in my mind,

i can never do a fully controlled misfire, since every cycle of the code i use up 3 pulses (as time) . not to mention that in the full program it reads 3 pulses from every wheel.

it needs to be like a small code running in parallel with the main code.

Can this be done?

It seems to me that you are going about this in the wrong way.

Why not check each time through loop() whether the pulse pin has changed state since the previous check and if so and its current state indicates that a pulse has occurred add 1 to the count. Take action when the count reaches a significant value.

The Arduino should easily be able to deal with pulses at 533hz using this method.

Hi,
When using loop does the remaining part of the program work?

regards

cpur:
Hi,
When using loop does the remaining part of the program work?

regards

I don't think that you have posted a complete program in this thread so I am not sure what the remaining

The simple "count the pulses" method does need expanding to record the start and end times of the count period to determine the RPM. I also don't understand how you are determining the amount of traction loss in order to determine whether action needs to be taken.

I am out and cannot send a paste of the whole code. However i managed to read traction loss . In a very good and reliable way. Problem is that if tracloss is 5% over want a misfire every 5 . If it os up to 15 i want a misfire every 3. And so on. When i tried it on the road it does sense and misfires. But the misfire is disabled when all code is run again and found to be within tracloss limits. But if the car is moving slow it takes time and fast takes less time but it still does not do it in a pattern. I think i will make another uno only for the misfire control. 4 digital pins will send the the level of misfire it needs and a crank and cam pulse to know the sequence. I will post the code later

here it is .

Please help me make it better, I am a self learner, I never learned any kind of programming. I tend to be very interested to do something but will only learn the things and ways that make the thing work. Maybe surely there will be a better or faster way to make this code work. Please teach me.

Thanks

AFTER_TOYOTA_AND_ELITE.ino (12.1 KB)

pulseIn() is a very bad function for things that need rapid response. It locks up the processor completely until the pulse arrives. You can't do anything else during that time. It's easy to write however, so it is not totally useless.

There's two ways you can go here. One is what HeliBob suggested: just read the pin often enough to detect the pulses. The second is much more complex to get your head around: using interrupts. For me, I've used interrupts often enough that I'm comfortable with the concept. For you, it may be too far away from what you have - keep doing what you're doing.

Think about the main loop running very fast. It should be able to complete all of its actions thousands of times per second. It can read all the inputs, do some calculation based on those inputs and its memory of what happened before and then it can set its outputs. Here's the main loop of a large program I wrote recently:

void loop {
  readMotorCurrent();
  readSerial();
  calculateMotorPercent();
  setMotorOutputs();
  sendSerialFeedback();
}

You would not know this was a 10,000-line program just by looking at that. But you can see everything that it does in just a few lines. This is a motor with tight real-time control of the voltage and current. It needs to react to fast changes in the current in milliseconds but it also needs to read and send serial commands that take hundreds of milliseconds to transmit.

None of those functions ever takes more than 1 millisecond to run. They each do a little bit of work and then return to the main loop so that the other functions can do their work.

Remember that the Arduino never gets bored asking "Are we there yet?" 10,000 times per second. It's good at that. You can check the state of your crank trigger at least that often and still have time to do other useful things like make a decision on which pulse to force a misfire. From that point of view, the crank is just an occasional input that probably doesn't need to be serviced very often.

So start by getting rid of the pulseIn() function. Write that little loop which is looking for 3 pulses with your own version that uses digitalRead() directly. Then you can add other work into that loop. Ultimately, you should remove that loop altogether and use the main loop() function to provide the looping and you keep your own counter in a variable to count up to 3.

Thanks for the suggestions,
but the 3 pulses from the crank are read in loop to compare to time, this gives me the reading for rpm.
Likewise the readings of all four wheels.

Did I understand correctly?

Thanks and regards

Yes, but using that function is preventing you from doing anything else during that time period. To make this work properly, you need to be able to cause misfires at the same time as you are reading RPM.

From the point of view of the Arduino, the engine is a very slow thing. The Arduino can do thousands of instructions in between each pulse from the crank. So you can actually do a lot of other inputs and outputs between each pulse.

I know that Arduino Is much faster then the engine, however using this expression was the only way i could make it work accurately.

If i would write:

1 read engine pulsein HIGH ,x= micros
2 (other code)
3 (other code)
4 (other code)
5 read engine pulsein HIGH , micros - x = t(time betweenpulses)

Is this what you suggesting MorganS?

Regards