-1

Good Morning to everyone, I am a PhD Student in experimental fluid mechanics at the University of Naples "Federico II", Italy. I am working on Arduino Due card and i am novel in applications using it. First, I need to generate a sine wave with variable frequency and amplitude. I tried to download several codes which are able to generate sine waves with a pre-defined frequency, but I would like to change this value of frequency at the beginning of the execution of the code. How could i do this ? Second, I would like to change, in real-time, the output voltage of Arduino DAC0 or DAC1 at high speed to generate an arbitrary waveshape.. Is it possible? Thank you in advance for your answers.

Dr. Alessandro Scala

1 Answers1

1

The formula commonly used to represent a sinusoidal signal is

V = A cos(ωt)

where A is the amplitude and ω is the angular frequency. This formula should cope well with a variable amplitude. It is, however, not suitable for a signal with variable frequency, because a discontinuity of the frequency is not supposed to create a discontinuity in the signal.

The correct formula for a signal where both the amplitude and the frequency can vary is

V = A(t) cos(φ(t))

where the phase is computed as

φ(t) = ∫ ω(t)dt

In terms of code, this means you need a static variable to keep track of the current phase, and you have to update it periodically in order to perform the numerical integration.

Here is a tentative implementation. I have qualified some variables as extern only to hint that you are responsible for managing them. You can remove the qualifier if you integrate this into your own code:

// Defined and updated elsewhere.
extern const uint8_t output_channel;
extern float angular_frequency;  // in rad/us
extern float amplitude, offset;  // in ADC steps

// Call this as often as practical. void update_output() { // Compute the time delta. static uint32_t time_of_last_update; uint32_t now = micros(); uint32_t dt = now - time_of_last_update; time_of_last_update = now;

// Update the phase.
static float phase;
phase += angular_frequency * dt;
while (phase >= 2 * M_PI) phase -= 2 * M_PI;  // unwrap

// Output the signal.
float output = offset + amplitude * cos(phase);
analogWrite(output_channel, round(output));

}

Regarding the second part of the question (about arbitrary waveshapes), it is, of course, feasible. You just have to pass arbitrary values to analogWrite().

Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81