I'd really like to use one timer to control multiple signals, but I'm not sure if that's possible. From what I know, even if I put all the signal outputs on the same timer (pins controlled by that timer), I couldn't get phase shifts. By that I mean that the signal is sent on the 0 count no matter what, and I can set a multi-phase output. See below:
Signal sent at the normal time (on the vertical)
Timer 1: --|-------|-------|-------|-------|-------|-------|-------|-------|--
Timer 2: -----|-------|-------|-------|-------|-------|-------|-------|-------|--
Timer 3: ------|-------|-------|-------|-------|-------|-------|-------|-------|--
I would like:
Timer : |-o--vr-|-o--vr-|-o--vr-|-o--vr-|-o--vr-|-o--vr-|-o--vr-|-o--vr-|-o--vr-|
I already have the timer configured to reset at the correct time. It resets based on the Hall being activated. For now, we'll just assume that the engine is at constant rpm because it is easier. RPM won't actually change the underlying idea anyway, because phase shifts are independent of period. I hope my ASCII (or maybe Unicode) drawing helps you all to understand what I mean.
Fun with timings
(49 posts) (7 voices)-
Posted 5 years ago #
-
I guess the math wasn't as hard as I thought it would be. What do you think?
/* *ECU/EFI for Maple V1.0 *Copyright (c) 2010 Hari Ganti *More stuff will go here later... */ //Pins in use: 15- pot, 17- pressure, 19- temp, 2- pulse, 3- intake valve, 4-corr_state, 5- exhaust valve, 6- corr_deg, 7- corr_injector, 8- corr_PWM, 9- kill, 11- injector, 12- spark volatile int delta_t; //Period of the engine volatile bool fire = false; int corr_deg = 0; //Correction factor for spark timing- calibrated in degrees int corr_injector = 0; //Correction factor for injection length- calibrated in counts (100us) int corr_PWM = 0; //Correction factor for phase- calibrated in 100us int exhaustDelay; //Delay after exhaust opens for intake to open (and exhaust to close) int intakeDelay; //Delay after intake opens for injector to fire (and intake to close) int a; int b; int c; int p; //Manifold Absolute Pressure int t; //Manifold Air Temp int pulseDelay; //Pulse length time (in microseconds) int sparkDelay; //Delay after injector fires (in microseconds) int tach; //Tachometer void setup() { pinMode(15, INPUT_ANALOG); pinMode(17, INPUT_ANALOG); pinMode(19, INPUT_ANALOG); pinMode(2, INPUT_PULLDOWN); pinMode(4, INPUT_PULLDOWN); pinMode(6, INPUT_PULLDOWN); pinMode(7, INPUT_PULLDOWN); pinMode(8, INPUT_PULLDOWN); pinMode(9, INPUT_PULLDOWN); pinMode(3, PWM); pinMode(5, PWM); pinMode(11, PWM); pinMode(12, OUTPUT); Timer2.setPeriod(6553500); //Pin 3- Intake Timer4.setPeriod(6553500); //Pin 5- Exhaust Timer3.setPeriod(6553500); //6.5535 sec, 65535 counts/cycle, 10986496 clocks/cycle Timer3.setChannel2Mode(TIMER_OUTPUTCOMPARE); Timer3.attachCompare2Interrupt(spark); attachInterrupt(0, pulse, RISING); //Trigger void pulse when sensor is deactivated (digital pin 2)- can be changed if needed attachInterrupt(8, corrDeg, RISING); //Trigger void corrDeg when button is pushed attachInterrupt(9, corrInjector, RISING); //Trigger void corrInjector when button is pushed attachInterrupt(6, corrPWM, RISING); //Trigger void corr3 when button is pushed } void loop() { //The fun stuff goes on here if (digitalRead(9) == LOW) { delta_t = 50*delta_t; // exhaustDelay = delta_t/200; pwmWrite(5, exhaustDelay); //Exhaust valve control b = 65536-exhaustDelay; //65535 or 65536? // intakeDelay = (analogRead(15)*150)/4096; //Servo PWM duty cycle a = (delta_t*intakeDelay)/36000; pwmWrite(3, a); //Intake valve control c = b-a; // p = ((analogRead(17)-164)*230)/3850+20; //MAP actual (kPa) // t = (analogRead(19)*500)/4096; //MAT actual (K) //The following is no longer accurate- D (evacuation) must be a function of intakeDelay pulseDelay = ((100*2029712256)/2478997185)*(p/t); //Injector delay length //pulseDelay = (818763437/10000000)*(p/t); //Simplified, less accurate- compare graphs later pulseDelay = pulseDelay + corr_injector; pwmWrite(11, pulseDelay); // sparkDelay = ((77+corr_deg)*delta_t)/36000; //Delay before spark fires Timer3.setCompare2(sparkDelay); // tach = 60000000/delta_t; } else { delayMicroseconds(5); if (digitalRead(9) == LOW) { delay(1000); } } } void pulse() { //Synchronize the PWM for the fuel injector if (fire == false) { delta_t = Timer3.getCount(); //Get twice the period in microseconds if (corr_3 == 0) { //Reset the timer Timer3.setCount(c); Timer2.setCount(b); Timer4.setCount(0); } else { //"Reset" the timer Timer3.setCount(c-corr_PWM); Timer2.setCount(b-corr_PWM); Timer4.setCount(65536-corr_PWM); //65535 or 65536? } fire = true; } else { fire = false; } } void spark() { //Ignite the spark plug digitalWrite(12, HIGH); delayMicroseconds(3); //Check if it's necessary digitalWrite(12, LOW) } void corrDeg() { //Diagnostic spark timing utility delayMicroseconds(5); if (digitalRead(6) == HIGH) { if (digitalRead(4) == HIGH) { corr_deg++; } else { core_deg--; } } } void corrInjector() { //Diagnostic injector length utility delayMicroseconds(5); if (digitalRead(7) == HIGH) { if (digitalRead(4) == HIGH) { corr_injector++; } else { corr_injector--; } } } void corrPWM() { //Diagnostic PWM phase utility delayMicroseconds(5); if (digitalRead(8) == HIGH) { corr_PWM++; } }
The code is much more complicated than before. I am actually changing timer count values even more than before. Basically, the timers are all synchronized to the same pulse. The synchronization happens once every TWO pulse signals though (twice the period). Below is a phase diagram of the PWMs (represented by their timers) and the spark interrupt in order of occurrence:
Engine: |----------|----------|----------|----------|----------|----------| Timer4: /-----\---------------/-----\---------------/-----\---------------- Timer2: ------/-----\---------------/-----\---------------/-----\---------- Timer3: ------------/-----\---------------/-----\---------------/-----\---- Spark: -------------------/-\-------------------/-\-------------------/-\-
Hopefully that illustrates the timings a little better.
Posted 5 years ago # -
Hi,
Interesting thread - I wish I understood it all!Earlier this year I played with hall effect sensor and an Arduino, I was looking at wheel speed but this would apply to crank shaft speed as well : it is possible to mount the magnet behind the hall sensor (i.e. static) and the sensor will trigger when some metal passes through the magnetic field, this metal could be a nut on a fly wheel and means that you don't have to fix the magnet to the crank shaft. It is suppose to be possible to count the teeth on the starter ring as they pass the sensor.
best wishes
Simon
Posted 5 years ago # -
The flywheel actually has a magnet, as all current Briggs engine, AFAIK, use magneto ignition systems. Mine does at any rate.
Posted 5 years ago #
Reply
You must log in to post.