I got a project and will take ideas from a programing point of view as well as from an electronics.
I have a device which only has 2 wires connected to it, the device powers it self and also feeds back data from the same 2 wires. The data is just a sine-wave of around 5k-6k running on top of the 24V. The sine-wave it self is roughly about 5V from top to bottom.
I like to interface the Arduino to this "data" or sine-wave riding on top of the 24V, all I need to know is the Frequency of this Sine-Wave at least once a second.
So far for what I have read, I can read a frequency with a frequency counter library on pin 5 of the Arduino.
I also need some electronics help or ideas figuring out how to get the sine-wave to be read on the Arduino.
As it is sitting on top of 24V you need to AC couple it, that means putting it through a capacitor. Then you need to turn the AC into DC with a rectifying diode. This will give you half a sin wave with a peak of 2.5V so next you need to square it up. Use a transistor, feed the base through a 1K resistor to your rectified signal, emitter to ground and collector to arduino input pin.
Finally turn on the internal pull up resistors by setting the pin as an input then writing high to it.
OK, thanks to your input, I managed to get a +2.5V to -2.5 volt sine-wave with a 100uf capacitor and a 10kOhm resistor to ground. I will update as I go ..
Ok, I now have a good TTL Low to High signal 0 - 5V going into Pin 5 of my Arduino, I need to read the frequency of this TTL pulse, I don't seem to find the right coding....is the frequency counter library a part of Arduino 18? Any tips...?
#include <FreqCounter.h>
void setup() {
Serial.begin(9600); // connect to the serial port
Serial.println("Frequency Counter");
}
long int frq;
void loop() {
FreqCounter::f_comp= 8; // Set compensation to 12
FreqCounter::start(100); // Start counting with gatetime of 100ms
while (FreqCounter::f_ready == 0) // wait until counter ready
frq=FreqCounter::f_freq; // read result
Serial.println(frq); // print result
delay(1000);
}
And what I get is a 1 a second read. The read out is about 3.5Khz when it should be about 5 Khz or so, every reading is about 100Hz off from the last second so it doesn't seem accurate, I wonder what f_comp and f_ready do, also the 100ms one...
The readings are very precise, yet I have a issue...
I need to provide a 1 a second reading to a serial port, this is crucial.
Now, I see there is a certain fluctuation on the readings that affect my readings, enough to be a problem.
It is roughly about 5+ and then 5- almost all the time...
I'm guessing that the issue lies on the micro being halted/busy transmitting over the slower serial port and while it does it looses some of the changing state readings on Pin 5. Is there a better approach to this ???
After lots of filtering I got it more stable, yet it still jumps exactly 6Hz up and down constantly...I really think is related to the micro being busy during the reading...I tried a 500ms intead of 1000ms but I still got the same issue...ideas?
I've done something somewhat similar.. I had to take readings from an anemometer for a school project. The anemometer output a sine wave with about 1.5V p-p. Converted it to a TTL square wave and used an interrupt to record the time elapsed between pulses and calculated the frequency an thus the wind speed from there. Worked very well.
I apologize in advance for my crappy programming. This was one of my first big projects and it was done out of necessity. There is a lot more to it, but I tried to scrape away all of the irrelevant stuff. The "void measure()" part is what you want.
int hz;
int mph;
unsigned long startTime;
unsigned long stopTime;
unsigned long pulseHigh;
unsigned long pulseLow;
unsigned long period;
unsigned long periodOld;
void setup() {
Serial.begin(9600);
attachInterrupt( 1, measure, CHANGE);
}
void loop() {
if (period != periodOld) {
if( period > 20000 && period < 1500000) { //effort to eliminate false(ridiculous) readings
hz = 1000000 / period; //converts the period into freq.(hz)
}
else
{
hz = 0;
}
mph = (hz * 1.711) + 0.78; //converts freq. to mph for NRG-40 anemometer
if(mph < 1) //for displaying purposes
{
mph = 0;
}
else
{
mph = mph;
}
periodOld = period;
}
if (micros() - startTime > 750000 || micros() - stopTime > 750000) //I think I did this to ignore measurement if the period was > 3.5seconds(which happens with anemometers)
{
period = 0;
}
//measuring wind speed
}
void measure() { //measures the period of the signal in microseconds
if(digitalRead(3) == HIGH) {
startTime = micros();
pulseLow = startTime - stopTime;
}
if(digitalRead(3) == LOW) {
stopTime = micros();
pulseHigh = stopTime - startTime;
}
period = pulseLow + pulseHigh;
}
I'm not trying to be critical as a teacher, but these two lines in your code need to be swapped orders. By having them the order they're in now, you're counting the communication time in your calculations.
timer = millis(); //Resets Time
Serial.println(frq); //Prints Frequency
By the way, use 115200 baud rate if you want to save time. It's 12 times quicker than 9600.
You should really put the timer=millis() right around when the signal becomes high for the first time. From what you're doing now, you could miscount half of a cycle. BTW, use microsecond(). One millisecond off means 5 more pulses.
This works flawlessly! Just make sure you wait time is less than a second, for me 3000 pulses was less than a second but for other applications other numbers should be used.