Hello,
First off, I want to declare that I'm not an electrical or computer engineer, so I apologize ahead of time if some of this doesn't make sense or if I get things wrong. I'm just trying to make light of a minor bump in an exciting adventure with Arduino and electronics to solve a dilemma.
I have been working at this project where we are trying to generate signals to input into some main hardware. I'd like one sinusoidal signal as the main input and one square signal as the clock signal. At the moment, I'm using a DAQ for this, but it’s a bulky and expensive device to transport. Thus, I instead plan to use an Arduino to generate these signals.
I have an Arduino DUE, which has two DAC ports that can output the sinusoidal and square signals. I've written a code (in Arduino IDE that I'd like to convert to MATLAB later but that's another step in the project) to generate these signals using the Arduino.
For the most part my program produces the signals as they should but there is an offset where I can adjust the frequency, amplitude, and sampling rate respectively for each signal. Although the problem is that these DAC ports have an output range of 0.55V-2.75V. I need to thus adjust this so that the signals oscillate around a baseline of 0. This gave rise to another problem though...I believe Arduino assumes that the baseline of the signals are at their troughs though, is this correct? If so, how do I go about correcting this baseline offset so that it meets my purpose for different combinations of amplitudes, offsets, etc.?
I've included my program for generating these signals as well as a LTspice design to potentially solve this problem as I believe I may need to make hardware to fix this software problem. It solves it but only in the perfect combination of amplitude and offset voltages delivered by the "DAC" port (noted with the SINE() or V3). Let me know also if it is just something with my program...that could very well be it as well.
Thank you so much for any help at all as I am a bit lost at this point,
Jesse
// Variables for configuring the sinusoidal signal
int amplitudeSinus_mV = 1000; // peak-to-peak amplitude for sinus signal in millivolts, can be changed
int frequencySinus = 10; // frequency of the sinus signal in Hz, can be changed
// Variables for square signal configuration
int amplitudeSquare_mV = 1000; // amplitude for square signal in millivolts, can be changed
int frequencySquare = 10; // frequency for square signal in Hz, can be changed
int samplingRate = 1000; // Sampling rate in Hz
// Constants for DAC output voltage range
const float minVoltage_mV = 550; // Minimum voltage output of DAC port in millivolts
const float maxVoltage_mV = 2750; // Maximum voltage output of DAC port in millivolts
const int dacResolution = 4095; // Resolution of the DAC (12 bits)
// Constants and variables for timing
const float pi = 3.14159;
unsigned long previous_time_Sinus = 0; // Store the previous time (in microseconds) when the sinusoidal signal was generated
const unsigned long intervalSin = 1000000 / samplingRate; // Calculates the interval between each sample of the sinusoidal signal based on the sampling rate in microseconds
unsigned long previous_time_Square = 0; // Stores the previous timestamp for square wave generation
unsigned long intervalSquare = 0; // Interval for the square signal in microseconds, will be calculated based on frequency
// Variables for the sinusoidal signal generation
int sampleIndex = 0; // Used to keep track of the current sample index for the sinusoidal signal generation
const int numSamples = 100; // Number of samples per cycle
int offset = (amplitudeSinus_mV * 0.9365) + 0.4487; // Adjust for the offset anomaly to keep the trough at 0.55V (550 mV)
void setup() {
// Initialize the DAC pins
analogWriteResolution(12); // Set the DAC resolution to 12 bits
// Calculate interval for the square signal
intervalSquare = 1000000 / (2 * frequencySquare); // The interval is calculated to achieve the desired frequency. It's divided by 2 because the square wave has two states (high and low)
}
void loop() {
// Convert peak-to-peak amplitude from mV to bits
int amplitudeSinus_bits = calculatedacValue_Square(amplitudeSinus_mV); // Converts amplitude from mV to DAC bits
// Calculate the time period of one cycle based on the desired frequency
int period = 1000000 / frequencySinus; // Convert frequencySinus to period in microseconds
// Generate the sinusoidal signal
unsigned long current_time_Sinus = micros(); // Get the current time in microseconds
if (current_time_Sinus - previous_time_Sinus >= period / numSamples) { // Check if the time interval for the next sample has passed
previous_time_Sinus = current_time_Sinus; // Update the previous time to the current time
float angle = 2 * pi * sampleIndex / numSamples; // Calculate the angle for the current sample
int dacValue_Sinus = offset + amplitudeSinus_bits / 2 * sin(angle); // Calculate the DAC value for the sinusoidal signal, adjusting peak-to-peak amplitude to fit DAC range
analogWrite(DAC0, dacValue_Sinus); // Write the DAC value to the DAC pin
sampleIndex = (sampleIndex + 1) % numSamples; // Increment the sample index, wrapping around after one cycle
}
// Generate the square signal
unsigned long current_time_Square = micros(); // Get the current time in microseconds
if (current_time_Square - previous_time_Square >= intervalSquare) { // If statement to check if the interval has passed
previous_time_Square = current_time_Square; // Update the previous time to the current time
// Calculate the DAC value for the square wave and toggle between high and low values
int dacValue_Square = (current_time_Square / intervalSquare) % 2 == 0 ? calculatedacValue_Square(amplitudeSquare_mV) : calculatedacValue_Square(0); // Toggle between high and low with 0 mV offset
analogWrite(DAC1, dacValue_Square); // Write the calculated DAC value to the DAC1 pin
}
}
// Function to calculate DAC value from amplitude in millivolts with offset correction for sinusoidal signal
int calculatedacValue_Sinus(float amplitudeSinus_mV) {
float amplitudeFraction = amplitudeSinus_mV / (maxVoltage_mV - minVoltage_mV); // Calculate the fraction of the amplitude relative to the DAC range
return amplitudeFraction * dacResolution; // Convert the amplitude fraction to a DAC value based on the DAC resolution
}
// Function to calculate DAC value from amplitude in millivolts with offset correction for square signal
int calculatedacValue_Square(float amplitude_mV) {
float amplitudeFraction = amplitude_mV / (maxVoltage_mV - minVoltage_mV); // Calculate the fraction of the amplitude relative to the DAC range
return amplitudeFraction * dacResolution; // Convert the amplitude fraction to a DAC value based on the DAC resolution
}









