variable phase delay calculation

I need to know how to take my calculation and put it into code to delay signal

input 1 = A (always changing frequency)
input 2= B (always changing frequency)

(A/60)/1000=Z
Z/(Z*Z)=Y
Y/360=X

B+ [X*(set constant)]=required phase delay in mil-seconds

is this possible with Arduino? ive gone through lots of other projects and math DIY but i have never come across somthing like this please give me some direction

What frequencies are these signals? What values will they range over?
You have two inputs but no output? Or is one of those inputs actually an output? Where is your output.

Basically this is difficult. You have to digitize your signal, store it in memory in a circular buffer and pull out a sample n memory locations before the current buffer pointer and then output that sample to a digital to analogue converter.
The value of n is calculated from the sample rate and the phase angle delay you want.
You are limited by the rate you can sample, the resolution on the sample and the limited amount of memory you have. This will affect the maximum frequency and the frequency spread you can get.

Thank you for the quick response

sorry the output was= B+ [X*(set constant)]=required phase delay in mil-seconds

input 1 frequency vary's from 200 signals per minute to 8000 signals per minute
input 2 is directly half 100 signals per minute to 4000 signals per minute

both these signals are digital signals, all the calculations i made broke everything into milsecond units, which to my understanding is what arduino works in. does the arduino loop quickly? do you feel that this would be good for my application?
can you guide me to an example where a sample rate is used.

Thank you!

I think the term phase delay is wrong in this situation. You do not define phase in terms of time but in terms of an angle. You can not apply a phase delay until you know the exact time period of the wave.

Can you explain more about the nature of the signals, what is the duty cycle? Is it always the same? Will the delay ever be greater than one duty cycle period?

Hi, what are you measuring at A and B, amplitude or frequency, or when they zero cross?

Tom..... :slight_smile:

I please ask for your patience with this topic, i have no experience with this at all. here is the full explanation of what i am trying to accomplish or even to determine if arduino will be appropriate for this application.

what i want to do is take a injector pulse and delay it so that i have a signal delayed injection pulse( I DO NOT WANT TO DELAY THE ACTUAL INJECTOR I JUST WANT THE DELAYED SIGNAL). a Injection pulse happens once every 2 revolutions, for these of you who are familiar with a 4 stroke engine it is because fuel is add to once four piston strokes (2 revolutions) in industry it is explained like this, stroke one power stroke piston moves down after fuel has been ignited (180 degrees) stroke 2 exhaust stroke piston moves up exhaust valve opens pushing all exhaust out form cylinder (360 degrees 1 revolution) stroke 3 intake stoke intake valve open allowing new air and fuel to travel into the cylinder (540 degrees)stoke four compression stroke valves close squeezing the air and fuel to magnify the energy of the ignition (720 degrees 2 revolutions).
At the moment most modern vechicals have there injector pulse around the 420 degree area during the intake stroke. i want to take that signal and delay it till around the 700 degree area using the math below.

INPUT 1(value A)=revolutions per minute RPM
[(value A)/60]/1000=revolutions per mil second (value B)
(value B)/(value B x value B)=1 revolution in a mil second (value C)
(value C)/360= 1 degree of rotation in mil seconds (value D)

INPUT 2(value Z)=injector pulse
constant number of my choosing=preset degree delay(value E)
(value Z)+(value D x value E)=OUTPUT 1 IS THE VALUE I WANT!!!!!!!!!

things that concern me, will arduino be able to work in that small fractions of seconds in real time (as engine is running) and will i be able to power a Arduino from a 12V A/C source without damaging it? finally these injection pulse have different (widths) as in how long the signal actually is, the equation above was just to alter the frequency of the pulse but not the length in time the signal is (or how long the injector will stay open) because that value not change.

like i mentioned this is all new to me and probably way over my head, but i want to learn the operation of an arduino if it will help me in my project. PLEASE NOTE I DO NOT WANT TO DELAY THE ACTUAL INJECTION PULSE I JUST WANT THE SIGNAL AS STATED ABOVE>

Thank you smiley-small

First do the algebra, s/deg = 1 / (6 x rpm)
ms/deg = 1000 / (6 x rpm) = 166.7 / rpm

  float ms_per_deg = 166.7 / rpm ;
  float delay_in_ms = degrees * ms_per_deg ;

For speed using fixed-point representations can win big, for instance
with integral microseconds:

  long us_per_deg = 166667 / rpm ;
  long delay_in_us = degrees * us_per_deg ;

  .. 
  delayMicroseconds (delay_in_us) ;

Haven't you already asked this question on another thread? What was wrong with the advice you were given there?

Thank you for noticing, if you read that thread i was not getting the answer i needed, which is probably because i needed PROGRAMMING HELP. thus why i posted in the PROGRAMMING section.

so the program i am looking for looks like;

void setup() {
float ms_per_deg = 166.7 / rpm ;
float delay_in_ms = 550 * ms_per_deg;

long us_per_deg = 16667 / rpm ;
long delay_in_us = 550 * us_per_deg
}

void loop() {

int sensorVale = delay_in_us ;

}

all i need to do is define RPM?

Thank you with all your assistance

so the program i am looking for looks like;

No it is not.

You want a program that detects each edge of the incoming signal.
When the rising edge is detected you make a note of the millis timer call it say riseTime, the same for the falling edge, fallTime.
Then when the value of the millis timer exceeds the rise time plus your delay in milliseconds set the output high and riseTime to -1 ( to show it has been completed ), do the same with fallTime only this time put the output LOW,

Look at the techniques of the blink without delay example.

could you please show me an example of what your referring to

There are different ways to measure the phase delay. For clock signals it's usually referred to as phase and expressed in degrees, however in this case it's the time interval between both rising edges (or both falling edges) is what you'll need to measure. Note that with both inputs varying at different rates, the pulse on signal A may lead or lag the pulse on signal B at any time.

As, GM suggests, you'll need to check the edges. You could measure the time interval between both rising edges or both falling edges. However, if the duty cycle isn't 50% (as shown in the diagram), then you'll get different answers for each method.

Note that Arduino's pulseIn() function measures the period of 1 signal. So what you need is to measure the period (interval) between similar edges of 2 signals.

Forgot to mention - it's very similar to the way quadrature encoders work, where the "direction" would determine if a given signal leads or lags the other.

From reply #2

input 1 frequency vary's from 200 signals per minute to 8000 signals per minute
input 2 is directly half 100 signals per minute to 4000 signals per minute

Therefore there is no drifting, the signals are synchronous. The 1/2 rate signal (B) would make a good reference, measurements could be made while its high as there will be a full cycle of A within B's HIGH period.
So, to measure any existing phase shift, here is some pseudo code to look at (untested):

  inputA = digitalRead(pinA);
  inputB = digitalRead(pinB);

  if ((inputB == 1) && (inputBprevious == 0)) {                    // if risingB
    periodB = micros() - startTime;                                // inputB period
    startTime = (micros();                                         // get new start time
  }
  if ((inputB == 1) && (inputA == 1) && (inputAprevious == 0)) {   // if risingA and B is HIGH
    finishTime = (micros();                                        // get new finish time
    timeIntervalBA = finishTime - startTime;                       // measured delay (microseconds)
    phaseBA = (timeIntervalBA/periodB)*360.0;                      // phase shift B to A (degrees)
    phaseAB = 360-phaseBA;                                         // phase shift A to B (degrees)
  }

THANK YOU SOOOOOOOO MUCH, i will being and keep this thread posted with my progress.

Hi, sounds like you are trying DIRECT fuel injection, injecting fuel on the compression stroke, directly into the cylinder, instead of the inlet manifold.
That is SIDI used here in Australia by Generous Motors(sic) (sorry FORD Fan "Fix Or Repair Daily", not a " Just Holden " together fan.)

http://www.themotorreport.com.au/41843/2010-holden-ve-commodore-sidi-first-drive-review

Hope you have all the high-pressure injectors and pumps to carry it out.

I watch with interest, Tom....... :slight_smile:

yes that is exactly what i am doing.

Update: I got my Arduino board in the mail last week and pulled out my bread board and made the light blink, so now its time to hammer out this program

this what i got
int A= 12; //A is RPM
int B = 10; //B is injector pulse
int C = 8; //C is injector delay

void setup() {
// put your setup code here, to run once:
pinMode(A, INPUT);
pinMode(B, INPUT);
pinMode(C, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:

if ((B == 1) && (Bprevious == 0)) { // if risingB
periodB = micros() - startTime; // inputB period
startTime = (micros(); // get new start time
}
if ((B == 1) && (A == 1) && (Aprevious == 0)) { // if risingA and B is HIGH
finishTime = (micros(); // get new finish time
timeIntervalBA = finishTime - startTime; // measured delay (microseconds)
phaseBA = (timeIntervalBA/periodB)*360.0; // phase shift B to A (degrees)
phaseAB = 360-phaseBA; // phase shift A to B (degrees)
}
}

These are my errors

master_sketch_14_05_03.ino: In function 'void loop()':
master_sketch_14_05_03:16: error: 'Bprevious' was not declared in this scope
master_sketch_14_05_03:17: error: 'periodB' was not declared in this scope
master_sketch_14_05_03:17: error: 'startTime' was not declared in this scope
master_sketch_14_05_03:18: error: expected )' before ';' token master_sketch_14_05_03:20: error: 'Aprevious' was not declared in this scope master_sketch_14_05_03:21: error: 'finishTime' was not declared in this scope master_sketch_14_05_03:21: error: expected )' before ';' token
master_sketch_14_05_03:22: error: 'timeIntervalBA' was not declared in this scope
master_sketch_14_05_03:22: error: 'startTime' was not declared in this scope
master_sketch_14_05_03:23: error: 'phaseBA' was not declared in this scope
master_sketch_14_05_03:23: error: 'periodB' was not declared in this scope
master_sketch_14_05_03:24: error: 'phaseAB' was not declared in this scope

How to i "declare" all these items?

And where is the output defined in this program?

If you pre-select your code, then click the # button, it will get posted correctly.
You'll need to do some experimentation, trial & error, checking other references, etc. as you develop your code.
Using the print functions and print monitor is a good tool for general debugging.

In your code, the compiler was complaining that certain variables were not declared. Its a good idea to avoid variable types that include -ve numbers in their range if you're not using them. I've assigned the variables in the code below. This is completely untested and will take lots of debugging and development ... but its a starting point.

unsigned long A = 12;      //A is RPM
unsigned long B = 10;      //B is injector pulse
unsigned long C = 8;       //C is injector delay

unsigned long Aprevious, Bprevious;    //previous input status
unsigned long startTime, finishTime;   //timing
unsigned long periodB, timeIntervalBA, phaseBA, phaseAB; //results

void setup() {
  // put your setup code here, to run once:
  pinMode(A, INPUT);
  pinMode(B, INPUT);
  pinMode(C, OUTPUT);
}
void loop() {
  // put your main code here, to run repeatedly:

  if ((B == 1) && (Bprevious == 0)) {                // if risingB
    periodB = micros() - startTime;                  // inputB period
    startTime = micros();                            // get new start time
  }
  if ((B == 1) && (A == 1) && (Aprevious == 0)) {    // if risingA and B is HIGH
    finishTime = micros();                           // get new finish time
    timeIntervalBA = finishTime - startTime;         // measured delay (microseconds)
    phaseBA = (timeIntervalBA / periodB) * 360.0;    // phase shift B to A (degrees)
    phaseAB = 360 - phaseBA;                         // phase shift A to B (degrees)
  }
}

Thank you dlloyd, i am in debut to you, the code is now not showing any errors and i am just about ready to take my bread board out to the motor, but i just want to be clear to where the out put C is defined?

master_sketch_14_05_04.ino (1.22 KB)

Thank you dlloyd, i am in debut to you, the code is now not showing any errors and i am just about ready to take my bread board out to the motor, but i just want to be clear to where the out put C is defined?

I think it would be a better idea to get more comfortable with programming in Arduino with your board. There are lots of examples to try. Why not try creating your own reference signals for input (similar to how blink without delay controls the led)? In this case, you would be using these signals to test and verify your code (motor not needed yet).