Frequency Modulator

Well after 2 days of googling looking for a way to make a frequency modulator I ended up here. I am just not sure how I can use a Arduino for this project. I am looking for any information you all can share. What I am working on is a speed sensor that outputs a variable frequency that I need to capture and modify based on another input like a variable resistor. The frequency varies from 0-250hz. I need to be able to re-generate the signal like 15% faster or whatever I set the modifier to that will be a resistance input. I have searched here but everything seems to be pwm or if it is frequency is fm or audio related. Can someone help with this?

Thanks

Is the input signal a sine wave, square wave, a pulse train... what?

If you need an output other than square wave or pulse train you will need a real D/A converter.

I am pretty sure it is square. I haven't had a chance to scope it.

If I read your post correctly, you need your Arduino to be able to output a frequency in the range of 0-250Hz.
Keep in mind an Arduino can only output a square wave frequency without external components. The Arduino core has a build in function called Tone that can certainly generate square waves in that range, although I don't know the minimum frequency it can geneate, it can certainly reach well beyond 250Hz.

Here is a link to a web page showing how to use the Tone function.
http://itp.nyu.edu/physcomp/Labs/ToneOutput

Good luck;

Lefty

retrolefty, thanks for the example, I will take the time to read through it. Yes I need a square wave out, however it needs to be a function of a square wave input +- % of another input like a analog volt from a potentiometer.

engrjhnsn:
retrolefty, thanks for the example, I will take the time to read through it. Yes I need a square wave out, however it needs to be a function of a square wave input +- % of another input like a analog volt from a potentiometer.

Understood, that is all possible and all under your control as the programmer. :wink:

Lefty

Seems like you need to determine the frequency coming in, maybe by using interrupts to capture the times of 2 rising edges in microseconds.
Then 1/time = frequency
output frequency is than input * your percent change.
Start toggling an output at the new frequency, you've got 4000uS between edges at the 250hZ rate.

crossroads, that is right. Do you have a code example on doing this. I have never programmed one of these. I can program vb and php and did a basic stamp about 10yrs ago so I think with some examples I can catch on. Also, is there another way with hardware to achieve the same thing? like a 555 or something. I would rather go this route as I like to program and think I would have better control.

A hardware route, now that would be fun.
I'm thinking use a frequency to voltage converter (really just a rectifier/smoothing filter), add in the voltage from your offset source (potentiometer), then run that into a voltage controlled oscillator.
Maybe a part like this for the VCO, looks like it could be tuned to run at the low audio frequencies you want.
http://www.goldmine-elec-products.com/prodinfo.asp?number=G4971A&variation=
Uou could get close to 0 frequency difference with some tuning of components.

Doing it in software? Take it in stages. This may take some adjusting, thinking on the fly here.
Write yourself a little program to start with an Interrupt Service Routine that sets a flag.
In the main loop, keep checking when the flag is set, every time it is do a read of micros() (microseconds).
Compare to the previous read and calculate the difference. That's the period of your incoming frequency.
At the same time, you will use micros() in a blink without delay loop to toggle an output hi/lo with the time duration (or period) set by the ISR timed incoming frequency and the offset from your potentiometer.
So with 0 offset, your output frequency should be pretty darn close to your input frequency, especially since you are 250 Hz or less.
Go read up on interrupts, write the ISR to set a flag, give it at try.

  // start timing interval

  currentMicros = micros();  // sample the time
  if (currentMicros - previousMicros >= period_interval) // more than our interval?
  {
    // save the last time we okayed time updates 
    previousMicros = currentMicros; // save the current time for next comparison
    toggle = 1-toggle;  // results in 0 1 0 1 ...

if (period_flag == 1){ // flag is set by the ISR
incoming_time = micros();  // capture the time
period_interval = incoming_time - oldtime; // find the difference from prior time
old_time = incoming_time; // set the prior to the current time for the next comparison
}

  }  // end of time interval
} // end of void loop

Don't forget to clear period_flag at the end of the if(period_flag == 1).

oh yeah, good catch. Had that in mind and forgot about as I cut & pasted the other one together.

Thinking now the incoming period checking should probably be outside the frequency generating loop also so as not to add delays to it, since most of the time the code will be outside of this section:

if (currentMicros - previousMicros >= period_interval) // more than our interval?
{
:
}

well I finally got my uno working. here is one of my current sketches. however can someone tell me why the print out line shows the frequency varying? it jumps from 57, 28, 56, 60, 57. I am using a good 5MHz function generator for my input. I don't have a scope until next week to verify. I also get strange results if I use the tone function to output from one pin and input it to my input pin. The tone seems to work better however it wont run under 31hz. I was only using for testing when I didn't have the generator hooked up.

int vssPin = 0;        // VSS input pin 0 = irq2
int testPin = 7;       // tone output for testing as virtual input
int period_flag;
unsigned long incoming_time;
unsigned long old_time;
long period_interval;
unsigned long currentMicros;
unsigned long  previousMicros;
int toggle;
float freq;

void setup()
{ 
 pinMode(testPin, OUTPUT);
   Serial.begin(115200);
   attachInterrupt(vssPin, timing, RISING);  // VSS interrupt attached to IRQ 0 = pin2
   //tone(testPin, 30);
}

void loop()
{
  // start timing interval
  if (period_flag == 1) // flag is set by the ISR
  {
    incoming_time = micros();  // capture the time
    period_interval = incoming_time - old_time; // find the difference from prior time
    old_time = incoming_time; // set the prior to the current time for the next comparison
    period_flag = 0;
    
    //freq = 1000000.0 / period_interval; 
    //Serial.println(freq); 
  }
  
  currentMicros = micros();  // sample the time
  if (currentMicros - previousMicros >= period_interval) // more than our interval?
  {
    long per = currentMicros-previousMicros;
    // save the last time we okayed time updates 
    previousMicros = currentMicros; // save the current time for next comparison
    toggle = 1-toggle;  // results in 0 1 0 1 ...
     
     float freq2 = 1000000.0 / per;
     Serial.println(freq2); 
  }  // end of time interval
} // end of void loop

void timing()
{
  period_flag = 1;
}

5 MHz? What happened to 0 to 250 Hz?