I want to measure phase difference of two sine waves using arduino uno, the waves that will be given as analog i/p are voltage and current waveform respectively of 50hz both. I am trying to do so by zero crossing method as I think this is simplest one. Can any one help me with the code as soon as possible.
What size are these signals?
That is how much voltage peak to peak?
What sort of accuracy are you looking for?
Have you biased the analogue inputs?
You could use the Input Capture Register of Timer1. Have one zero crossing cause an interrupt that clears TCNT1 and have the other zero crossing trigger the input capture. The value of TCNT1 gets saved in ICR1 and an interrupt occurs. The value in ICR1 is the phase time difference in 16000000ths of a second. There will be a zero crossing 100 times a second (every 90°) so you have 160000 ticks in 90°. That gives you 0.0005625° resolution
Grumpy_Mike:
What size are these signals?
That is how much voltage peak to peak?
What sort of accuracy are you looking for?
Have you biased the analogue inputs?
the voltage that will be used is 230V 50Hz Ac, I am not bothering about accuracy and I am using a 230v/6v transformer and a devider cicuit to make the voltage 3v before giving it to the analog pin of arduino.
int led=13; //select the pin for led//
volatile unsigned long time1;
volatile unsigned long time2;
volatile float ps=0;
void setup()
{
Serial.begin(9600);
Serial.println();
pinMode(A2,INPUT); //voltage signal as analog input
pinMode(A3,INPUT); //current signal as analog input
pinMode(led,OUTPUT);
digitalWrite(led,HIGH);
noInterrupts(); //disable interrupts
attachInterrupt(A2,in1,RISING); //enable ISR1 for voltage signal at rising from zero crossing
attachInterrupt(A3,in2,RISING); //enable ISR2 for current signal at rising from zero crossing
noInterrupts();
ps = (((time2-time1)*360.0)/20000);
//calculate the phase shift from measured time difference
interrupts(); //enable interrupts
Serial.print("\t Phase Shift = ");
Serial.println(ps,6);
Serial.print("degree");
}
void in1()
{
detachInterrupt(A4);
time1=micros(); //measure time in micro second for first zero crossing ISR1
}
void in2()
{
detachInterrupt(A5);
time2=micros(); //measure time in micro second for first zero crossing ISR2
}
void loop()
{
;
}
I don't know if this code will work. Please tell me where should I modify the code
Please use code tags </> to present code.
The Arduino inputs only accept voltages in the range 0-5V, no negative voltages as occur in an AC signal. The voltage divider may happen to protect the inputs, depending on its resistance.
Don't use Serial in an ISR. Set a flag instead, and do the output inside loop() when the flag was set.
Actually your program will crash, when the next interrupt exceeds the array bounds (j>0).
For exact timing a positive square wave signal is required on the interrupt pins, not an AC sine wave.
Also consider that a transformer or wave shaper (schmitt trigger...) will introduce a phase shift. You have to determine the phase shift of your sensor circuits, and adjust the output value accordingly. And handle negative phase shifts properly.
are you trying to monitor phase difference for 3-phase ? this is something you can find on openenergymonitor.
Also in addition to the above, there is a lot more wrong with that code.
Time variables should not be floats but unsigned long types. You should not disable and enable interrupts inside an ISR, that happens automatically in a much better way than you can do it yourself.
If both signals go through the same processing circuits any shift will be cancled.
am not bothering about accuracy
Yes you are, otherwise don't bother measuring it just say it is 10 degrees, that is accurate +/- 180 degrees.
Is that alright now?
No.
-
The code is not in code tags. I will not post again on this thread until you address that problem.
-
Why are the time variables arrays of length one? Makes no sense at all.
-
You have been told not to do a serial print inside an ISR. You are still doing it.
-
Your calculation of the phase is not in any function and so will not be called. It won't even compile will it?
Grumpy_Mike:
No.
The code is not in code tags. I will not post again on this thread until you address that problem.
Why are the time variables arrays of length one? Makes no sense at all.
You have been told not to do a serial print inside an ISR. You are still doing it.
Your calculation of the phase is not in any function and so will not be called. It won't even compile will it?
I got the point you are trying to tell....calculation of phase shift should be within the main function and the serial print should be outside the ISR and it should be also in main function.
I want to know will it work if i use variable instead of array for measuring the time by micros??
- The code is not in code tags. I will not post again on this thread until you address that problem.
Grumpy_Mike:
No.
- The code is not in code tags. I will not post again on this thread until you address that problem.
now I have included code tags in the just above code...please check sir
@Sudi please reduce your quotes to the really required information. Quoting code is not normally required.
Where did you include code in code tags? Look at your reply #7, where no code tags are noticeable. Don't edit inside quoted text, instead add your comments and code outside quoted passages.
As an exercise you can go back to your reply #5, click More and Modify, to open the reply for editing. Then select the contained code and click </>, to enclose the selected code in code tags.
I have modified the code using code tag. Now please check where I need to modify the code itself for measuring the phase difference. I am using a 230V/9V transformer and divider circuit to reduce the peak to peak within 5V(safe limit for arduino analog pin input). I can't use any other device as for zero crossing detector device or opamps for biasing. What I have to do is modify the code as much as possible. Thanks in advance.
A negative voltage is not good for the Arduino inputs. AC does not only have positive peeks, but also negative peaks of the same amplitude.
Yeah I know but...would it damage the arduino if the rms voltage is 3V as input?? Any other way you suggest for the phase shift measurement...main problem is that I can not afford to buy any other device for the project.
Code won't compile:
Arduino: 1.6.12 (Mac OS X), Board: "Arduino/Genuino Uno"
/var/folders/cs/p6yz0z1m8xj9lf0059b_lzw00000gn/T/untitled1462896525.tmp/sketch_nov20b/sketch_nov20b.ino: In function 'void setup()':
sketch_nov20b:22: error: invalid types 'volatile long unsigned int[int]' for array subscript
ps = (((time2[0] - time1[0]) * 360.0) / 20000);
^
sketch_nov20b:22: error: invalid types 'volatile long unsigned int[int]' for array subscript
ps = (((time2[0] - time1[0]) * 360.0) / 20000);
^
exit status 1
invalid types 'volatile long unsigned int[int]' for array subscript
This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.
You can't expect your code to work if it does not compile. Please get your code to compile before you ask if it will work.
I don't see any Arduino that has external interrupts on pins A4 and A5. If you have an Arduino UNO you must use pins 2 and 3, the only pins with external interrupt capability.
I would allow a little time between enabling interrupts and assuming both interrupts had triggered.
I would detach the interrupts before reading the saved time values since they will be changing 50 times per second as long as those interrupts are enabled.
Sudi:
Yeah I know but...would it damage the arduino if the rms voltage is 3V as input?
Yes.
Any other way you suggest for the phase shift measurement...main problem is that I can not afford to buy any other device for the project.
Then you can not complete your project. How much would two resistors and a diode cost anyway?
Grumpy_Mike:
Yes.
Then you can not complete your project. How much would two resistors and a diode cost anyway?
Yes I can afford those things..then what to do please suggest sir..I have already resistors of 1 kohm and 2 kohm.
johnwasser:
You can't expect your code to work if it does not compile. Please get your code to compile before you ask if it will work.I would allow a little time between enabling interrupts and assuming both interrupts had triggered.
I would detach the interrupts before reading the saved time values since they will be changing 50 times per second as long as those interrupts are enabled.
now the code is compilimg.....but to detach the interrupt to read the saved time value can I disable interrupt or enable it again within the ISR s??
Sudi:
but to detach the interrupt to read the saved time value can I disable interrupt or enable it again within the ISR s??
I would not recommend enabling interrupts inside an ISR.
If you want to disable interrupts when reading the time values rather than detaching the interrupts when you are done with them, that would work.