In the example tutorial simple waveform generator with Arduino Due found on the Arduino.cc website, it has been shown how one can produce different types of waveform using Arduino Due DAC. Here the circuit is demonstrated and the waveform plotted in real time in Matlab Simulink scope and Arduino Mega.
There is one difference between that provided in the arduino.cc tutorial and here. In the arduino.cc tutorial, two buttons are used to select waveform and send out one of four types of waveform on the two DAC of Arduino Due(DAC0 and DAC1). Here we will output waveform from DAC0 only so we will use only one button. Using that button we can select one of the four types of waveform- sine wave, triangle wave, sawtooth wave and square wave. So the code shown here is the same as that from the arduino site but it is modified to work only with one button.
Also to visualize the waveform on Simulink Time Scope, we will use Arduino Mega 2560 analog channel 0 to acquire the waveform generated from Arduino Due DAC0 pin.
Actual Circuit
Below is picture of the actual circuit.
Circuit Schematic
Following is the circuit setup schematic.
The schematic was drawn in Proteus Professional software. In the schematic, a 10KOhm POT is connected to Arduino Due. The middle pin of the POT is connected to the analog channel A0 pin of Arduino Due, while the other two ends are connected to the 3.3V pin and the GND pin of the Arduino Due. Also, a push button is connected to the digital pin 2 of the Arduino Due. The digital pin 2 is pulled down to GND using 10KOhm resistor. The other side of the push button is connected to the 3.3V pin of the Arduino Due.
When the wave generator program runs in Arduino Due, it outputs analog waveform signal from its DAC0 pin. The output from DAC0 is connected to the analog A0 pin of the Arduino Mega 2560. The ground pins of both Arduino Due and Arduino Mega are interconnected.
Matlab/Simulink with Arduino Mega
The Arduino Mega 2560 is configured from within Matlab Simulink to receive signal from A0 and plot it on the Time Scope graph. Below is the simulink block schematic.
Here we have used Simulink Support Package for Arduino Hardware. You can learn how to setup Arduino to work with Simulink in the previous tutorials Programming Arduino using Matlab/Simulink Setup. See also another tutorial Generate Sine Wave using Arduino PWM and Simulink to get idea of how to setup block and block parameters.
Waveform Graph
The waveform graph obtained from the time scope is shown below.
In the graph we can see the four types of waveform(sine wave, sawtooth, triangle and square wave) plotted by pressing the push button.
Video Demonstration
In the following video you can these waveform graph in real time. Also in the video we can see the effect of turning the POT. By increasing the resistance via potentiometer, the frequency increases and as the frequency increases the waveform starts to distort. This is due to failure of adequate sampling rate using the simulink.
Code & Programming
The code is provided below. There are two files. One is a header file called waveforms.h and the other is called FunctionGenertor.ino which is the arduino sketch.
The arduino sketch FunctionGenerator.ino is below.
#include "waveforms.h"
#define oneHzSample 1000000/maxSamplesNum // sample for the 1Hz signal expressed in microseconds
const int button0 = 2;
volatile int wave0 = 0;
int i = 0;
int sample;
void setup() {
analogWriteResolution(12); // set the analog output resolution to 12 bit (4096 levels)
analogReadResolution(12); // set the analog input resolution to 12 bit
attachInterrupt(button0, wave0Select, RISING); // Interrupt attached to the button connected to pin 2
}
void loop() {
// Read the the potentiometer and map the value between the maximum and the minimum sample available
// 1 Hz is the minimum freq for the complete wave
// 170 Hz is the maximum freq for the complete wave. Measured considering the loop and the analogRead() time
sample = map(analogRead(A0), 0, 4095, 0, oneHzSample);
sample = constrain(sample, 0, oneHzSample); //Constrains a number to be within a range
analogWrite(DAC0, waveformsTable[wave0][i]); // write the selected waveform on DAC0
i++;
if(i == maxSamplesNum) // Reset the counter to repeat the wave
i = 0;
delayMicroseconds(sample); // Hold the sample value for the sample time
}
// function hooked to the interrupt on digital pin 2
void wave0Select() {
wave0++;
if(wave0 == 4)
wave0 = 0;
}
The wavforms.h code is below.
#ifndef _Waveforms_h_
#define _Waveforms_h_
#define maxWaveform 4
#define maxSamplesNum 120
static int waveformsTable[maxWaveform][maxSamplesNum] = {
// Sin wave
{
0x7ff, 0x86a, 0x8d5, 0x93f, 0x9a9, 0xa11, 0xa78, 0xadd, 0xb40, 0xba1,
0xbff, 0xc5a, 0xcb2, 0xd08, 0xd59, 0xda7, 0xdf1, 0xe36, 0xe77, 0xeb4,
0xeec, 0xf1f, 0xf4d, 0xf77, 0xf9a, 0xfb9, 0xfd2, 0xfe5, 0xff3, 0xffc,
0xfff, 0xffc, 0xff3, 0xfe5, 0xfd2, 0xfb9, 0xf9a, 0xf77, 0xf4d, 0xf1f,
0xeec, 0xeb4, 0xe77, 0xe36, 0xdf1, 0xda7, 0xd59, 0xd08, 0xcb2, 0xc5a,
0xbff, 0xba1, 0xb40, 0xadd, 0xa78, 0xa11, 0x9a9, 0x93f, 0x8d5, 0x86a,
0x7ff, 0x794, 0x729, 0x6bf, 0x655, 0x5ed, 0x586, 0x521, 0x4be, 0x45d,
0x3ff, 0x3a4, 0x34c, 0x2f6, 0x2a5, 0x257, 0x20d, 0x1c8, 0x187, 0x14a,
0x112, 0xdf, 0xb1, 0x87, 0x64, 0x45, 0x2c, 0x19, 0xb, 0x2,
0x0, 0x2, 0xb, 0x19, 0x2c, 0x45, 0x64, 0x87, 0xb1, 0xdf,
0x112, 0x14a, 0x187, 0x1c8, 0x20d, 0x257, 0x2a5, 0x2f6, 0x34c, 0x3a4,
0x3ff, 0x45d, 0x4be, 0x521, 0x586, 0x5ed, 0x655, 0x6bf, 0x729, 0x794
}
,
// Triangular wave
{
0x44, 0x88, 0xcc, 0x110, 0x154, 0x198, 0x1dc, 0x220, 0x264, 0x2a8,
0x2ec, 0x330, 0x374, 0x3b8, 0x3fc, 0x440, 0x484, 0x4c8, 0x50c, 0x550,
0x594, 0x5d8, 0x61c, 0x660, 0x6a4, 0x6e8, 0x72c, 0x770, 0x7b4, 0x7f8,
0x83c, 0x880, 0x8c4, 0x908, 0x94c, 0x990, 0x9d4, 0xa18, 0xa5c, 0xaa0,
0xae4, 0xb28, 0xb6c, 0xbb0, 0xbf4, 0xc38, 0xc7c, 0xcc0, 0xd04, 0xd48,
0xd8c, 0xdd0, 0xe14, 0xe58, 0xe9c, 0xee0, 0xf24, 0xf68, 0xfac, 0xff0,
0xfac, 0xf68, 0xf24, 0xee0, 0xe9c, 0xe58, 0xe14, 0xdd0, 0xd8c, 0xd48,
0xd04, 0xcc0, 0xc7c, 0xc38, 0xbf4, 0xbb0, 0xb6c, 0xb28, 0xae4, 0xaa0,
0xa5c, 0xa18, 0x9d4, 0x990, 0x94c, 0x908, 0x8c4, 0x880, 0x83c, 0x7f8,
0x7b4, 0x770, 0x72c, 0x6e8, 0x6a4, 0x660, 0x61c, 0x5d8, 0x594, 0x550,
0x50c, 0x4c8, 0x484, 0x440, 0x3fc, 0x3b8, 0x374, 0x330, 0x2ec, 0x2a8,
0x264, 0x220, 0x1dc, 0x198, 0x154, 0x110, 0xcc, 0x88, 0x44, 0x0
}
,
// Sawtooth wave
{
0x22, 0x44, 0x66, 0x88, 0xaa, 0xcc, 0xee, 0x110, 0x132, 0x154,
0x176, 0x198, 0x1ba, 0x1dc, 0x1fe, 0x220, 0x242, 0x264, 0x286, 0x2a8,
0x2ca, 0x2ec, 0x30e, 0x330, 0x352, 0x374, 0x396, 0x3b8, 0x3da, 0x3fc,
0x41e, 0x440, 0x462, 0x484, 0x4a6, 0x4c8, 0x4ea, 0x50c, 0x52e, 0x550,
0x572, 0x594, 0x5b6, 0x5d8, 0x5fa, 0x61c, 0x63e, 0x660, 0x682, 0x6a4,
0x6c6, 0x6e8, 0x70a, 0x72c, 0x74e, 0x770, 0x792, 0x7b4, 0x7d6, 0x7f8,
0x81a, 0x83c, 0x85e, 0x880, 0x8a2, 0x8c4, 0x8e6, 0x908, 0x92a, 0x94c,
0x96e, 0x990, 0x9b2, 0x9d4, 0x9f6, 0xa18, 0xa3a, 0xa5c, 0xa7e, 0xaa0,
0xac2, 0xae4, 0xb06, 0xb28, 0xb4a, 0xb6c, 0xb8e, 0xbb0, 0xbd2, 0xbf4,
0xc16, 0xc38, 0xc5a, 0xc7c, 0xc9e, 0xcc0, 0xce2, 0xd04, 0xd26, 0xd48,
0xd6a, 0xd8c, 0xdae, 0xdd0, 0xdf2, 0xe14, 0xe36, 0xe58, 0xe7a, 0xe9c,
0xebe, 0xee0, 0xf02, 0xf24, 0xf46, 0xf68, 0xf8a, 0xfac, 0xfce, 0xff0
}
,
// Square wave
{
0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff, 0xfff,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
}
};
#endif
Much of the code is explained in the arduino.cc website:
https://www.arduino.cc/en/Tutorial/DueSimpleWaveformGenerator
For other similar tutorial see:
- Generate Sine Wave using Arduino DAC and RC Low Pass Filter