need the fasts response as i can get

i need to get fast response,

as we see while ( ! pin + mask ) wait to signal, set HIGH two pins.

i want to get faster response from

// A Signal
while ( ! (PIND & B00000100) );
PORTD = B00110000;

is there faster way to do it ? ( its ignition controller, so on high rpm each 50 micros is 1.8/360 ...

unsigned long st = 0;
int rpm = 3950;

unsigned int table[] = {
  3950, 3945, 3940, 3935, 3930, 3925, 3920, 3915, 3910, 3905,
  3895, 3885, 3875, 3865, 3855, 3845, 3835, 3825, 3815, 3805,
  3790, 3775, 3760, 3745, 3730, 3715, 3700, 3685, 3670, 3655,
  3635, 3615, 3595, 3575, 3555, 3535, 3515, 3495, 3475, 3455,
  3425, 3395, 3365, 3335, 3305, 3275, 3245, 3215, 3185, 3155,
  3110, 3065, 3020, 2975, 2930, 2880, 2830, 2780, 2730, 2680,
  2630, 2580, 2530, 2480, 2430
};


void setup () {
  DDRD = B11110010;
  PORTD = B00000000;

  // Static ignition time
  int i;
  for (i = 750; i >= 0; i--) {
    while ( ! (PIND & B00000100) );
    PORTD = B00110000;
    delayMicroseconds( 4100 );
    PORTD = B00000000;
    // B Signal
    while ( ! ( PIND & B00001000) );
    PORTD = B11000000;
    delayMicroseconds( 4100 );
    PORTD = B00000000;
  }

  digitalWrite(13, HIGH);


}

void loop () {
  // Float ignition time
  for ( ; ; ) {

    // A Signal
    while ( ! (PIND & B00000100) );
    PORTD = B00110000;
    st = micros();
    delayMicroseconds( rpm );
    PORTD = B00000000;

    // B Signal
    while ( ! ( PIND & B00001000) );
    PORTD = B11000000;
    delayMicroseconds( rpm );
    PORTD = B00000000;

    rpm = table[ int ( 300000 / float ( micros() - st ) ) ];

  }
}

No, there is no faster way to do it in code. To get faster than that you will need a faster microprocessor. A Due is 84MHz and the Teensy 3.6 goes up to 180MHz. Remember that delayMicrosecond() only has a resolution of 4us on the 16MHz Arduinos.

However, your code will have a delay of much less than a microsecond. If you are measuring delays longer than that then it's not the little while(); loop which is the problem. You do have a way of measuring it, don't you?

using DSO5027P i measure electric delay time of 4-8us on the analog side of the device ( VW coils, driven by tl4427 chip, opto isolated with pc817 from the arduino ).

i cannot measure all the build, the is no socket around the car to put the DSO.

but, if i use direct ecu - driver - coil build i can hear valve knock, if i use ecu - arduino - driver - coil there is no knock, so i think the arduino is the slowest part.

while ( ! (PIND & B00000100) );
PORTD = B00110000;

is ! (PIND & B00000100) is the best way to wait for the digital signal ?

( sorry for my english, im working on it )

No experience with this but you can consider using an interrupt (for an Uno on pins 2 and 3) to detect the the signal(s), set the pins and start a timer for desired number microseconds; when the timer interrupt triggers, reset the pins.

Sounds to me that that will be the fastest that you can get.

Is this an EDIS system (i.e. - using PIP and SAW signals)? What is driving those PIND inputs, and what is the timing you're trying to achieve?

You have other issues that will affect timing....

Regards,
Ray L.

mrserii:
i need to get fast response,

That is meaningless. You need to tell us how fast it needs to be in millisecs or microsecs.

I see int rpm = 3950; in your program. That is not at all fast by Arduino standards.

It would be much easier to help if you tell what you are trying to make.

...R

This busy-wait loop is faster than an interrupt. If it isn't fast enough according to your measurements then you will make it quicker with a faster processor. Of course anything faster doesn't have a PORTD, so your code must change to suit the new hardware.

Without more information on what you're doing, it's impossible to suggest meaningful alternatives.

The code segment you provided does:

   0:    4a 9b           sbis    0x09, 2
   2:    00 c0           rjmp    .-1
   4:    80 e3           ldi    r24, 0x30
   6:    8b b9           out    0x0b, r24

You could make that SLIGHLY faster (62.5ns) by moving the "ldi" instruction before the spin loop.
There may be input synchronization delay (between the time that the input signal changes, and the time the AVR actually notices that it has changed) slowing things down as well.

But that's pretty fast.

If you really need it to be faster, and depending on what else the program has to do, this is an obvious place to use external hardware. A simple flipflop (like a 74hc74) can set an output "instantly" on reception of the input signal, and the AVR can come along more slowly and perform the calculations needed to determine when to turn things off, or whatever.

When I compiled the sketch I got this code:

 1aa:   4a 9b           sbis    0x09, 2 ; 9
 1ac:   fe cf           rjmp    .-4             ; 0x1aa <setup+0x16>
 1ae:   0b b9           out     0x0b, r16       ; 11

The 3 was preloaded into R16.

So each "look" for the bit in i/o port is 3 cycles, and once the bit is "seen" it is another 3 cycles to write to the output port.

You never said what "fast" means, but this is pretty darn fast.
Worst case the chip just missed seeing the bit the first look, and then has to look again so it is a maximum of 6 cycles.
or 375ns That is WAY under 1us.

Some of what you may be experiencing may be latency from the other portions of the code.
That for loop could use some re-doing. ints on the AVR kind of suck since the part is actually only 8 bits so any loop variable needs to be only 8 bits rather than 16 if you want maximum speed.
Since 750 is larger than 8 bits, you can't do that with an 8 bit value; however, you would be better off from a looping speed perspective to have two loops that use 8 bit variables.

--- bill

I still reckon an Arduino would have time to eat a sandwich and wipe its lips with a serviette between revolutions at 3950 RPM.

...R

rpm variable is not an rpm count, it's the delay time.

the sketch is look for signal A and then B. each signal is the trigger for two pins that drive coils.

the time is COIL ON time.

first, when motor starts i use static time 4100, then variable from the table, on high rpm i cant use 3950 micros ON time, the coil wont fire, on lower rpm with 3950 micros i got great power.

the ecah item in the table array is motor rpm /100, so table[7] is the delay time on 700 rpm ... table[21] is the delay time on 2100 rpm ... its alway's between 3900 - 2400 depend on rpm calculation.

the main issue is the time between signal A/B to COIL ON time ( i want hear the knock ! )

maybe i need to use "prediction" algorithm, it will earl the ignition trigger by 340 micros ( the minimum coil fire time in open air without any fuel, as tested on table ) - in case of accelerating.

mrserii:
rpm variable is not an rpm count, it's the delay time.

Perhaps my assumption will convince you of the value of using meaningful names for your variables.

Can you describe a complete cycle of the engine from one spark to the next with all the necessary timings given so that I can understand the context of your problem.

...R

It seems like maybe the Arduino is part of a larger system here. A schematic would also be useful to understand how it's connected to everything else.

im using ej16 ( subaru impreza 1.6 ) engine, part of the car was stolen ( coil - waste spark type, ignition wires )

the engine has 4 cylinders, each driven by one signal ( i call it A/B ), one wire fire 1-2 the second 3-4.

as i saw in the data-sheet the replacement coils (06E905115E), that actually chosen because they fit the cylinder bore must get 5v ignition trigger or 1500 up to 4000 micros.

the sckech,

for ( ; ; ) {

// A Signal
while ( ! (PIND & B00000100) );
PORTD = B00110000;
st = micros();
delayMicroseconds( rpm );
PORTD = B00000000;

// B Signal
while ( ! ( PIND & B00001000) );
PORTD = B11000000;
delayMicroseconds( rpm );
PORTD = B00000000;

rpm = table[ int ( 300000 / float ( micros() - st ) ) ];

}

fire exactly as the original waste-fire system, two coils each signal ( due the difficult of synchronize the engine position if fire two coils each time, in the future ill write code that will cause and catch misfire, to synchronize ).

the problem is that the signal A/B is shorter than 1500 micros, so on cold engine, cant start.

one hour ago i found that the new coil fire only on RELEASE so my problem is that i need long ON ( coil charging time ) but this time means late ignition.

so now i need to charge the coil by "prediction", that means in need to calculate the last cycle, than fire before A/B signal ... than RELEASE after the signal ... due the changes in rpm it's difficult

the principal

Image from Reply #14 so we don't have to download it. See this Image Guide

...R

mrserii:
im using ej16 ( subaru impreza 1.6 ) engine, part of the car was stolen ( coil - waste spark type, ignition wires )

the engine has 4 cylinders, each driven by one signal ( i call it A/B ), one wire fire 1-2 the second 3-4.

as i saw in the data-sheet the replacement coils (06E905115E), that actually chosen because they fit the cylinder bore must get 5v ignition trigger or 1500 up to 4000 micros.

What you are trying to explain is far too complex to be described in a few words like that. I think I would need to see the workshop manual for the car before I could even start to understand the complexities, (or simplicities) of what you are trying to do.

And, to avoid any confusion, even if you do post a link to the workshop manual I am not prepared to study it. I'm lazy, and no longer interested in cars. Sorry.

...R

The way most wasted spark systems work (and this one sounds no different), is the ECU receives a signal that is derived from the crankshaft position sensor. One edge of that signal provides a timing reference for the ECU, that tells it, effectively, when a specific cylinder is at top dead center (though the actual signal edge may be offset from actual TDC). The point is, when this edge occurs, the ECU knows where the crankshaft is. The ECU then starts timing a delay. At the end of this delay, it output a signal which fires the spark plug. The delay determines the spark advance - shorter delay means more advance (i.e. - spark occurs further BEFORE TDC). For most engines, advance will be on the order of 10 degrees before TDC at idle, and will get up to anywhere from 30-45 degrees by 4000 RPM. In nearly all modern systems, advance is also modified based on other factors, like coolant temperature, manifold vacuum (which is a measure of engine load), and other factors. So, low RPM ==> long delay, high RPM ==> short delay. The delay is calculated on each cycle using a (usually multi-dimensional) lookup table and linear interpolation.

The OP is running a 4-cylinder engine. A wasted spark system always fires two spark plugs at the same time, on two cylinders which are 180 degrees out of phase. For each spark, one cylinder of the pair will be approaching TDC on the compression stroke, while the other will be approaching TDC on the exhaust stroke. So, he apparently gets one input signal which indicates timing for one pair of cylinders, and a separate signal which indicates timing for the other pair of cylinders.

If I understand the OP correctly, his confusion is due to the fact that the timing of these signal is such that the two delays he must implement overlap. This means he cannot simply wait for one "trigger" signal, do the delay, and fire the first spark, then wait for the second trigger, do that delay, and fire the second spark. Instead, it sounds to like he must watch for the first trigger, start the first delay, then simultaneously watch for the second trigger, and start that delay, etc.

OP - Do I understand this correctly?

Regards,
Ray L.

i cant find the exact solution.

4gas reading gives me : 0.17 co (good) and 853 HC ppm (BAD) need more burn time

i think i need to calculate the time from signal to signal, than take part of the coil charge time before the signal. ( will be some % of error )
the problem is that rpm rapidly changes, but in 1/2rev precision i think it shuld be good.

for exp:

if from a to b takes 10,000 micros ( i thin its 3,000 rpm ) - lets say the charge time for is 2000 micros.

after b fires i wait 10000 - 2000/2 micros ( 9000 ) than charge the coil, after something like 1000 see signal a ... wait more 1000 than fire up ( HIGH time is charge, when LOW it fire ).

so if each for signal to signal is 180* ( 1/2rev ) and i will charge the coil 18* before the signal, and fire it 18* sooner

mrserii:
i cant find the exact solution.

Have a look at how understandable @RayLivingston's Reply #17 is. if you can match that then maybe progress can be made.

...R