If I want to sync something so that it happens exactly 1 time every 20 ms in sync with a 50Hz device, what do I need to consider incorporating into an Arduino project?
I have many R3 Uno's, one R4 Uno, Leonardo's and Mega 2560's. I have many electronic components, including some crystals in the MHz, but I wouldn't have thought they would be useful.
I am attempting to check if the beam of a 50Hz CRT TV is in a certain place on screen (the place is constantly having light drawn to it at 50Hz (always on in regards to CRT)). I have a phototransistor pointing at a certain point (connected to digitalRead(3)), and just want to know that I can rely on the program to test the same point each loop.
I have some naive code that does it like this (just to see what will happen):
What I get a s a result is around 6 seconds worth of Serial results saying 1 and after that around 6 seconds worth of Serial results saying 0.
This is using micros() which suggests that the micros() usage is 'rolling' as a badly synced screen would on a display, rolling up the picture.
I understand that I should have a start point set, for example, once the digitalRead(1)=1 then sync from there, and I will do that afterwards. I would just like to get consistent results from this setup before I change it to a sync start method.
What the results currently show is that my method of waiting 20ms is not accurate.
Please suggest a method to amend my program with that will at least result in the Serial data being the same result (wether 0 or 1) for a few minutes.
I'm sure we all know what CRT's are and what I am describing, but this makes it easier, the light beam that is slowed down in this video is passing the phototransistor 50 times every second: https://bit.ly/47oNocX
If the timing went off a little bit, then the phototransistor would report "0". If the beam is around the front of it, it will report "1".
If the timing of the program was EXACTLY 50 times per second (20ms (or 20000us) delay) then the phototransistor would report the SAME number each loop.
Although the phototransistor does report the same number for 6 full seconds (6x50 times) - after that it reports the other number, and that suggests that half the time it is not near the beam at that time.
I am experimenting at the minute, and what I want is consistent results with this simple setup. Gaining an understanding along the way.
If you think my timing method is bad, then please suggest another way.
I want to use this phototransistor (BPY-62 3/4) as described, to read a consistent result of:
Is the beam lit around the front of the Phototransistor during a 20000 microsecond interval?
So far my results are as I described, and not consistent, although, I thought that the timing of the Arduino Uno R3 I am using would have allowed for reading not changing on a 6-10 second basis - I thought it might report different results every few minutes or hours, not 6-10 seconds.
So, "exact" means +/- 7us, every 20ms?
That seems like it could be done in SW using a Pin Change interrupt and micros() (micros() is "close", since it's resolution is 4us), or more accurately (and less portable) setting up a timer in capture mode (or set up a timer to count every microsecond instead of every 4us, and use that with an ISR.)
Keeping the Arduino's clock well synchronized with an external timing source (50hz mains) is a second problem, maybe. Presumably it would help to implement a Zero-crossing detector on the same mains, and use a crystal-based clone.
For a simple experiment to see what the frequency of the photo transistor trigger, I would use the FreqMeasure library. It will be available through the library manager.
That library will use the input capture method(as @westfw mentions) on one of the hardware timers of the Arduino for an accurate measure of frequency.
If you think your system is stable at 50Hz, and you want to do some thing when you capture a rising edge from the photo transistor we can continue with the discussion.
Well, I have had some incredible results from that suggestion!
There are times that the frequency of the FreqMeasure will be 50.27, and the can be for a long time, and that's good enough for me, if I know that.
But, I think the main problem has been suggested, if not exposed.
The closer I have the phototransistor to the TV the worse the signal varies, I mean wildly varies, from 50.27 to 136.78 in 2 seconds, and 1027.44 in 8 seconds, and loops around.
I remember the Static electricity I could feel from the front of a CRT as a child, and assume that has something to do with it.
There was a similar problem when I was holding the wire the Phototransistor is connected to with my hand and the 0's and 1's were very unpredictable.
If is it not static, then it is something else caused by the static.
If I hold the hand of the little helping hands magnifying glass soldering helper that is holding the Phototransistor, it manages to drain the static, and keeps the frequency at 50.27 again, so I can do that, but if there is a better way to manage an over-sensitive input to an Arduino Uno, please let me know.
I still think my setup is stable at around 50Hz, and shouldn't have gone out of sync so quick (actually how long would 50.27Hz last assuming it was 50Hz?) but I can change it to 50.27 anyway :-).
The code I am using to create the results I mentioned is:
/* FreqMeasure - Example with serial output
* http://www.pjrc.com/teensy/td_libs_FreqMeasure.html
*
* This example code is in the public domain.
*/
#include <FreqMeasure.h>
void setup() {
Serial.begin(115200);
FreqMeasure.begin();
}
double sum=0;
int count=0;
void loop() {
if (FreqMeasure.available()) {
// average several reading together
sum = sum + FreqMeasure.read();
count = count + 1;
if (count > 30) {
float frequency = FreqMeasure.countToFrequency(sum / count);
Serial.println(frequency);
sum = 0;
count = 0;
}
}
}
Just the example Serial Out code suggested by FreqMeasure.
Something is causing interference with the Arduino, and I cannot actuallt pinpoint it down to distance from the TV either with the Arduino, or the Sensor, or distance from me.
What might be at play? It will behave very well at 50.27ms consistently for a long time according to FreqMeasure.
OK, now that we know that you know the rising edge from the photo transistor can be a consistent signal with emi/static control, how are you presently capturing that in your code, and what are you trying to sync with that signal.
I apologize, but I do not understand the bigger picture of what you are trying to achieve.
Honestly, I would like to see some consistent results from each test at the minute.
I assume that the results of FreqMeasure being 50.27 could have something to do with it.
I have just tested and using:
unsigned long Told = 0; //some global variables available anywhere in the program
unsigned long Tnew = 0;
void setup()
pinMode(8, INPUT);
}
void loop()
{
Told = Tnew;
do{Tnew = micros();
} while((Tnew-Told)<19892); 1000000/50.27=19892.5801
Serial.println( digitalRead(8));
}
Results in much a much longer time settled on one result from digitalRead(3). More than 29 seconds settled on each result.
That will give me enough time to re-sync.
If I wanted to get this perfect, as it is not, but when no other outside forces are acting upon it, this stream settles around 50.27 times per second. Is there any way to make that simple "Fully Sync With My Sync Or Lose Sync" method better? Just to experiment with various periods somewhere around 19892 to see?
Is there any way to help towards the CRT TV itself not messing with the times?
Honestly, I would like to see some consistent results from each test at the minute.
You might have better result is you start the "am I in sync" timing from 10 ms after the trigger.
I'm not certain if this code will do that, but you can give it a try and see if it extends the timing you are in sync.
unsigned long Told = 0; //some global variables available anywhere in the program
unsigned long Tnew = 0;
void setup()
pinMode(8, INPUT);
}
void loop()
{
while(digitalRead(8)==LOW); //hang out until pin goes HIGH
delayMicroseconds(10000);
Told = Tnew;
do{Tnew = micros();
} while((Tnew-Told)<19892); 1000000/50.27=19892.5801
Serial.println( digitalRead(8));
}
One of the things that may be tripping you up - the Arduino clock itself has an accuracy. Let's say it's +/- 1%. If your code measures 50 Hz, that means it measured 50Hz +/-1% - so the frequency you measured could be 50.5 Hz, or 49.5Hz, you have no way of knowing to anything better than that without an external device.
Now, I don't know the actual % for the crystal used on whichever Arduino it is you're using right now(don't think you've said, just said you have several), but that possible error has to be considered when you're looking for problems.
How do we know that the source of the video signal is synchronised with the mains frequency?
Couldn't they be entirely independent, and the video frequency just nominally 50Hz?