speeduino icon indicating copy to clipboard operation
speeduino copied to clipboard

Strange basic distributor behavior, part 2 (videos)

Open runesmdk opened this issue 6 years ago • 16 comments

Like jmunkdk - i'm experiencing strange basic distributor behavior. (https://github.com/noisymime/speeduino/issues/169) The problem is not upon starting as such, nor is it running, but if the engine stalls, or the crank fails.

I have two videos, the first one here is the first plugin and crank of the speeduino i did, with the trigger timing ~25degrees too advanced so i get kickbacks. The issue comes when the key is released. Injector channels go absolutely nuts, and then turn off. https://www.youtube.com/watch?v=WqNttG-ftcI

The second video here, the trigger angle is adjusted and the car starts (no iac valve, so throttle pedal only). I then release the throttle and let the engine die. The injectors keep firing after the engine stops, but instead of doing alternating (2 channels in use), it starts going 1-1-2-2-1-1-2-1-1 in a very random pattern. Maybe helpful to play the clip in slowmotion to catch that. https://www.youtube.com/watch?v=C7yyKwu-o5c

I do not have any logs as my laptop ran out of power shortly after adjusting trigger angle unfortunatly. The car is no longer available to me, as it was a test mule i got to try in a scrapheap, but the speeduino is going in a car similar very soon - IF i am able to resolve this behavior only.

The tune is here

strange-basic.zip

runesmdk avatar Feb 12 '19 19:02 runesmdk

This speeduino went in a car. As long as we dont stall it, and when it finally syncs up and starts, it runs well.

Issue number 2 with basic trigger is sometimes long cranking, whilst the sync-light in TS is flashing, and the fuelpump is turning on and off with the synclight. When the synclight turns solid, car starts right up.

Also experienced by users Κωνσταντίνος Μπέλτσιος and Dorian Krok in facebook post: https://www.facebook.com/groups/191918764521976/851692965211216

runesmdk avatar Apr 29 '19 18:04 runesmdk

I have to wonder if the injectors firing causes the vr conditioner to trigger, causing a bit of a feedback loop.

Can you test with a scope on the output of the vr conditioner? Is the spark also firing when this happens? Is TS showing rpm?

ReubenHoona avatar May 05 '19 22:05 ReubenHoona

@noisymime I can confirm that the issue with basic distributor still exist. I'm able to reproduce it on my bench using ArduStim. Without filter, I'm getting sync almost immediatelly. With filter it is a random. Sometimes I need to wait even 10s to get sync. I see in TS that during that period sync indicator is constantly changing from sync to sync loss. For test purposes I changed: setFilter(curGap); to if( (currentStatus.hasSync == true) && (currentStatus.RPM > currentStatus.crankRPM) ) { setFilter(curGap); //Recalc the new filter value } else { setFilter(0); //Recalc the new filter value } in triggerPri_BasicDistributor() but this is more workaround that actual fix. The qeuestion is, why we can't get sync in perfect conditions (ArduStim, square wave, no noise). Could you take a look at this?

SomeStupidNickname avatar Oct 04 '19 18:10 SomeStupidNickname

I too have exactly this problem using basic distributor and I can reproduce it on the bench using a simple PWM generator. This generator produces a clean pulse train at selectable frequencies. With any filtering selected it can take many cycles to get sync, sometimes just 1 or 2 but often many seconds. Without filtering it syncs straight away. On the car I am using a Hall effect sensor in the distributor and have a schmitt trigger filter on the trigger input - this behaves the same - always slow to sync. Another anomaly perhaps is that when sync is established MAP reading goes to maximum pressure and then drops back to correct reading. Any comments please.

gilberninvader avatar Nov 08 '19 18:11 gilberninvader

I have analysed the basic distributor behaviour. The problem lies in the way the very first trigger pulse is handled after initialisation. It calculates the value of "curGap" based only on the current time which is free running. The effect is that "curGap" will have a randomly very large number on this first trigger causing subsequent triggers to be ignored and initial sparking only on every 2, 3 or 4 triggers. Eventually it syncs on every trigger but the engine stutters and fails to pick up when this is happening. The problem is compounded when filtering is enabled as it adds a large number of microseconds to an already large number of microseconds which is then detected as a stall condition. The stall re-initialises everything and the cycle repeats for a random number of times. I believe the same issue may also exist with "Fix timing with trigger" as this exhibited the same effects for me as well. The solution is to set "curGap" to a reasonable value after the first trigger is received. I picked on 50,000 microseconds as this represents 200rpm for a 6 cylinder engine. Smaller numbers work just as well. The following code change tests for sync and if false sets "curGap" to 50,000 microseconds:

void triggerPri_BasicDistributor() {

curTime = micros();
curGap = curTime - toothLastToothTime;
if ((currentStatus.hasSync == false))
{
  curGap = 50000;
}
if ( (curGap >= triggerFilterTime) )
{

It is probably worth noting that the variable "toothLastToothTime" is assigned 3 values in the initialisation code. The first 2 assignments can be commented out or deleted. I have tested this both on the bench and the car itself and starting is now as it should be.

gilberninvader avatar Mar 23 '20 19:03 gilberninvader

I have analysed the basic distributor behaviour. The problem lies in the way the very first trigger pulse is handled after initialisation. It calculates the value of "curGap" based only on the current time which is free running. The effect is that "curGap" will have a randomly very large number on this first trigger causing subsequent triggers to be ignored and initial sparking only on every 2, 3 or 4 triggers. Eventually it syncs on every trigger but the engine stutters and fails to pick up when this is happening. The problem is compounded when filtering is enabled as it adds a large number of microseconds to an already large number of microseconds which is then detected as a stall condition. The stall re-initialises everything and the cycle repeats for a random number of times. I believe the same issue may also exist with "Fix timing with trigger" as this exhibited the same effects for me as well. The solution is to set "curGap" to a reasonable value after the first trigger is received. I picked on 50,000 microseconds as this represents 200rpm for a 6 cylinder engine. Smaller numbers work just as well. The following code change tests for sync and if false sets "curGap" to 50,000 microseconds:

void triggerPri_BasicDistributor() {

curTime = micros();
curGap = curTime - toothLastToothTime;
if ((currentStatus.hasSync == false))
{
  curGap = 50000;
}
if ( (curGap >= triggerFilterTime) )
{

It is probably worth noting that the variable "toothLastToothTime" is assigned 3 values in the initialisation code. The first 2 assignments can be commented out or deleted. I have tested this both on the bench and the car itself and starting is now as it should be.

It seems your code is being commented inside your comment. Any way to post it so i'm sure i'm copy-pasting the right part? Thank you

runesmdk avatar Mar 30 '20 11:03 runesmdk

Sorry I wasn't very clear. After "curGap = curTime - toothLastToothTime" insert: if ((currentStatus.hasSync == false)) { curGap = 50000; } That's all that's needed, no other changes. Hope this helps.

gilberninvader avatar Mar 30 '20 14:03 gilberninvader

Another sorry for a confusing post, I'm afraid. My observation of the initialisation code should have referred to the variable "triggerFilterTime". It is assigned 3 values in succession, the final value being "0". The 2 earlier assignments can be deleted.

gilberninvader avatar Mar 31 '20 16:03 gilberninvader

Another sorry for a confusing post, I'm afraid. My observation of the initialisation code should have referred to the variable "triggerFilterTime". It is assigned 3 values in succession, the final value being "0". The 2 earlier assignments can be deleted.

Yeah, the first 2 were what was there originally, but were replaced with a simple assignment at some point. The others effectively do nothing, so commenting them out makes no real difference either way.

I've just pushed up a commit that I think should have the same outcome as the curGap = 50000; mentioned above. Can you please try this out and see if it resolves your issue?

noisymime avatar Apr 01 '20 01:04 noisymime

Another sorry for a confusing post, I'm afraid. My observation of the initialisation code should have referred to the variable "triggerFilterTime". It is assigned 3 values in succession, the final value being "0". The 2 earlier assignments can be deleted.

Yeah, the first 2 were what was there originally, but were replaced with a simple assignment at some point. The others effectively do nothing, so commenting them out makes no real difference either way.

I've just pushed up a commit that I think should have the same outcome as the curGap = 50000; mentioned above. Can you please try this out and see if it resolves your issue?

Will this also handle the stall issue?

runesmdk avatar Apr 01 '20 07:04 runesmdk

I've had a rethink on the best method to fix this issue. I am 100% sure that the issue is not filtering - the code looks great just as it is. The issue is the way the very first trigger pulse is handled due to its lack of any previous timing values. I have had a go at some code which can be applied universally to engines with any number of cylinders. It captures the timing history of the first trigger but then filters that trigger out. The second trigger to be received uses the timing history of the first trigger to correctly set curGap and hence go on to sync with the correct values. Filtering starts on the third trigger pulse received. I've made changes to the basic Distributor initialisation and decoder. Its not particularly elegant but it uses the available structure and resources and, most importantly, it works both off and on the car.

void triggerSetup_BasicDistributor() { triggerActualTeeth = configPage2.nCylinders; if(triggerActualTeeth == 0) { triggerActualTeeth = 1; } triggerToothAngle = 720 / triggerActualTeeth; //The number of degrees that passes from tooth to tooth //triggerFilterTime = 60000000L / MAX_RPM / configPage2.nCylinders; // Minimum time required between teeth //triggerFilterTime = triggerFilterTime / 2; //Safety margin if ((triggerFilterTime != 1)) //This prevents the Main Loop from resetting triggerFilterTime to 0 in the gap between the first and second trigger pulses { triggerFilterTime = 0; } secondDerivEnabled = false; decoderIsSequential = false; toothCurrentCount = 0; //Default value decoderHasFixedCrankingTiming = true; triggerToothAngleIsCorrect = true; if(configPage2.nCylinders <= 4) { MAX_STALL_TIME = (1851UL * triggerToothAngle); }//Minimum 90rpm. (1851uS is the time per degree at 90rpm). This uses 90rpm rather than 50rpm due to the potentially very high stall time on a 4 cylinder if we wait that long. else { MAX_STALL_TIME = (3200UL * triggerToothAngle); } //Minimum 50rpm. (3200uS is the time per degree at 50rpm).

}

void triggerPri_BasicDistributor() { curTime = micros(); if ((currentStatus.hasSync == false) && (triggerFilterTime == 0)) //This is to detect the first trigger pulse and to set a valid time for toothLastToothTime so that the next trigger can be proceesed using reasonable values. It takes two triggers to sync //Test is for the first trigger to be received. The second trigger will fail because triggerFilterTime will be equal to 1. Third and and subsequent triggers will fail //because sync will be true and will then proceed normally. Selected trigger filter level will be applied to the third and subsequent pulses { toothLastToothTime = curTime; //sets time for the first trigger triggerFilterTime = 1; //will cause the first trigger to fail the next test so that it will be filtered out. Also used to signify the second trigger in the test above
} curGap = curTime - toothLastToothTime; if ( (curGap >= triggerFilterTime) ) { if( (toothCurrentCount == triggerActualTeeth) || (currentStatus.hasSync == false) ) //Check if we're back to the beginning of a revolution { etc, etc, etc

It is critical that the first 2 assignments of triggerFilterTime in the initialisation code are commented out or deleted. I hope it can be seen that I've inserted a couple of lines of code to initialisation and 4 lines inserted after the first line of the decoder. Please let me know if unclear

gilberninvader avatar Apr 03 '20 15:04 gilberninvader

Another sorry for a confusing post, I'm afraid. My observation of the initialisation code should have referred to the variable "triggerFilterTime". It is assigned 3 values in succession, the final value being "0". The 2 earlier assignments can be deleted.

Yeah, the first 2 were what was there originally, but were replaced with a simple assignment at some point. The others effectively do nothing, so commenting them out makes no real difference either way.

I've just pushed up a commit that I think should have the same outcome as the curGap = 50000; mentioned above. Can you please try this out and see if it resolves your issue?

Not able to get to the workshop in these times, but what about the stall issue?

runesmdk avatar Apr 05 '20 18:04 runesmdk

This will have no effect on your stalling issue. Have you inhibited the RESET?? Lots of threads on this

gilberninvader avatar Apr 06 '20 08:04 gilberninvader

This will have no effect on your stalling issue. Have you inhibited the RESET?? Lots of threads on this

It doesn't stall while running, but there is a bug if stalling the engine, where the speeduino becomes quite irradic at times, sometimes it seems like a feedback loop of noise from the inj/ign into the trigger, but one more i know have reported the issue back to me as well. Issue is it continues firing outputs, but sometimes not in order, instead of going 1-2-1-2 on injectors, it might go 1-1-1-2-2-1-1-2-2-2 or something like that, meanwhile it seems to "rev up" and doing it in an ever increasing pace, until suddenly it just stops again.

My point is, we need some kind of stall rpm trigger, when its in running state, so if it is in running, and goes below for instance ~450rpm, kill all outputs for 1sec to allow the noise to die down.

The vr conditioner stopped blinking for input while this was happening as well, and i tried shunting the vr wires in an attempt to reduce noise to no avail.

runesmdk avatar Apr 10 '20 14:04 runesmdk

Try having a look at issue #169 by jmunkdk, he has a logic analyzer output trace of what it sometimes does during engine stall.

runesmdk avatar Apr 10 '20 14:04 runesmdk

I have the same issue with basic distributor. If the engine stalls, I belive the Max9926 will lower the threshold and noise will trigger the Max chip and the injectors will pulse spuriously. This floods the engine and makes for hard starting. This issue only happens when the engine stalls. Has there been any resolution to this?One fix maybe, is to use a circuit that is not so sensitive for a basic distributor with an input threshold around 0.5Volts

Keshwin108 avatar Oct 22 '23 16:10 Keshwin108