I found a sine wave generator for the Arduino Due on this site how can this be used with an Uno or is there another similar link using Uno is there anything specific to the Due that prevents an Uno being used in this specific application.
The Uno (and most Arduino's) doesn't have a digital-to-analog converter, so there's no analog output. (There is an ADC.)
analogWrite() is [u]PWM[/u] which can "act like" analog to control motor speed or to make an LED appear to dim.
You can build a crude 8 bit DAC with a R2R ladder and an op amp to get a sine wave out of an Uno. The upper frequency limit will be in 20-30kHz range but that may be good enough for your needs, don’t know.
Google “Arduino function generator”, it’s been done a jillion-million times.
Or use an 8-bit DAC and load it with SPI data at 8 MHz.
If you have sine values in table, you can crank out the wave pretty quick.
https://www.digikey.com/product-detail/en/microchip-technology/MCP4801-E-P/MCP4801-E-P-ND/2332804
If you table integers that equal sine / 10000 for 0 to 90 degrees then you can cover the full circle. To multiply by sine you multiply by the table value then divide by 10000 and that needs to be done with longs when the table is ints. The results will be more accurate than float variables after a few operations.
The table goes into flash (using PROGMEM) where you have lots of space, 32K - size of the sketch (which if it's 8K then you wrote a Big Sketch).
The LAST thing you want to do is a series calculation for every value every time you use it.
Or you can use a Due or Zero.
The ARM chip Arduinos and compatibles have even more space in flash to store tables of pre-calculated values.
But if I wanted to generate trig on-chip, I'd want a board with an M4F like the latest Teensy's. The F is for FPU.
CrossRoads:
Or use an 8-bit DAC and load it with SPI data at 8 MHz.
If you have sine values in table, you can crank out the wave pretty quick.
MCP4801-E/P Microchip Technology | Integrated Circuits (ICs) | DigiKey
You mean something like this?
const int CS = 9;
const int SDI = 10;
//const int SCK_ = 11;
void setup() {
pinMode(CS, OUTPUT);
pinMode(SDI, OUTPUT);
pinMode(SCK, OUTPUT);
}
void loop() {
digitalWrite(CS, LOW); //initialize the chip
digitalWrite(SDI, LOW); // bit 15 - write to DAC
digitalWrite(SCK, HIGH); // trig bit 15
digitalWrite(SCK, LOW); // end trig bit 15
digitalWrite(SDI, LOW); // bit 14 - dont care
digitalWrite(SCK, HIGH); // trig bit 14
digitalWrite(SCK, LOW); // end trig bit 14
digitalWrite(SDI, LOW); // bit 13 - output gain selection
digitalWrite(SCK, HIGH); // trig bit 13
digitalWrite(SCK, LOW); // end trig bit 13
digitalWrite(SDI, HIGH); // bit 12 - output shutdown control bit
digitalWrite(SCK, HIGH); // trig bit 12
digitalWrite(SCK, LOW); // end trig bit 12
digitalWrite(SDI, HIGH); // bit 11 - D7
digitalWrite(SCK, HIGH); // trig bit 11
digitalWrite(SCK, LOW); // end trig bit 11
digitalWrite(SDI, LOW); // bit 10 - D6
digitalWrite(SCK, HIGH); // trig bit 10
digitalWrite(SCK, LOW); // end trig bit 10
digitalWrite(SDI, LOW); // bit 9 - D5
digitalWrite(SCK, HIGH); // trig bit 9
digitalWrite(SCK, LOW); // end trig bit 9
digitalWrite(SDI, LOW); // bit 8 - D4
digitalWrite(SCK, HIGH); // trig bit 8
digitalWrite(SCK, LOW); // end trig bit 8
digitalWrite(SDI, LOW); // bit 7 - D3
digitalWrite(SCK, HIGH); // trig bit 7
digitalWrite(SCK, LOW); // end trig bit 7
digitalWrite(SDI, LOW); // bit 6 - D2
digitalWrite(SCK, HIGH); // trig bit 6
digitalWrite(SCK, LOW); // end trig bit 6
digitalWrite(SDI, LOW); // bit 5 - D1
digitalWrite(SCK, HIGH); // trig bit 5
digitalWrite(SCK, LOW); // end trig bit 5
digitalWrite(SDI, LOW); // bit 4 - D0
digitalWrite(SCK, HIGH); // trig bit 4
digitalWrite(SCK, LOW); // end trig bit 4
digitalWrite(SDI, LOW); // bit 3 - X
digitalWrite(SCK, HIGH); // trig bit 3
digitalWrite(SCK, LOW); // end trig bit 3
digitalWrite(SDI, LOW); // bit 2 - X
digitalWrite(SCK, HIGH); // trig bit 2
digitalWrite(SCK, LOW); // end trig bit 2
digitalWrite(SDI, LOW); // bit 1 - X
digitalWrite(SCK, HIGH); // trig bit 1
digitalWrite(SCK, LOW); // end trig bit 1
digitalWrite(SDI, LOW); // bit 0 - X
digitalWrite(SCK, HIGH); // trig bit 0
digitalWrite(SCK, LOW); // end trig bit 0
digitalWrite(CS, HIGH); // de-initialize the chip
}
I was looking for a way to create a simple sine wave generator with an Arduino today and found the MCP4801 DAC. When I did a search on the forum I discovered this thread.
My code so far only contains the decimal value 128 in 8 bit mode so my code is intended for the MCP4801 but one could easily adapt it for the 10 and 12 bit DAC chips as well but I suspect the sine wave code will be very big.
I used the sine wave table generator found here to create a table of 127 steps with a maximum value of 255 and then I used the DEC2BIN function in google sheet to convert it to binary values.
When I transferred the code to my Uno and hooked it up to my logic analyzer it looked like really good so I think I will order a few DAC chips and start experimenting.
I realized I couldn't use SCK as integer name because it is already available/used for pin 13 so the clock will automatically be on pin 13 when using the name SCK.
The MCP4801 is about as cheap a DAC as can you buy. With that come some serious speed limitations and accuracy issues. Don’t expect more than audio frequency range output capability. You’ll also discover you can only generate a 0 to 2.048v or 0 to 4.096v output due to the internal reference and internal opamp gain.
Also, why bother with just 8 bits? The MCP4821 is fifty cents more and is a 12 bit device. You can always use it as an eight bit device if desired, you still write sixteen bits to the device regardless of output resolution so the 4801 is no faster.
If you want to generate a direct 0 to 5 volts out, I’d suggest using the MCP4921 since it allows for an external reference. Just use the Uno’s 5 volt rail for the vref, certainly good enough for general use.
As with most things Arduino, somebody’s already done the heavy lifting for you, here’s a library for 4821/4921:
Also of interest is Adafruits MCP4725 library. While not directly compatible since the part is I2C rather than SPI, check out the examples directory for a sine and triangle generator. It would be trivial to convert to the SPI version of the DAC.
On a final note, you said:
I used the sine wave table generator found here to create a table of 127 steps with a maximum value of 255 and then I used the DEC2BIN function in google sheet to convert it to binary values.
Totally unnecessary unless you just like looking at all those ones and zeros in your source code. It doesn’t matter if it’s hex, decimal, octal or binary, the compiler can handle it so long as the number format is correct. Have a look at the Adafruit code, they’re all decimal numbers, much easier to comprehend as a human. Binary is so 1950’s.
For my own project, audio frequencies is what I am hoping for. And as for libraries I know there are libraries for almost everything out there but I learn very little from using that, at least to start of with. With this approach I get a better understanding about how SPI communication works and how to properly utilize a logic analyzer to for trouble shooting. I also get a feel for serial communication in general.
There are plenty of devices that will allow one to generate a sin wave with the frequency being controlled by an Arduino. I use the AD9833 and AD9850 . Modules are available on Ebay at very reasonable price and Arduino libraries are available.
stowite:
There are plenty of devices that will allow one to generate a sin wave with the frequency being controlled by an Arduino. I use the AD9833 and AD9850 . Modules are available on Ebay at very reasonable price and Arduino libraries are available.
Those are probably very good IC's but they are more sophisticated than what is perhaps needed and also they are only available in SMD package which means you are more or less forced to buy a module on ebay. The MCP4801 and similar circuits are cheap, easy to work with and probably does the work depending on what you are trying to achieve. I am not sure what the thread starter was looking for but I believe my code is what CrossRoad meant but did not fully explain. There are probably better ways do to it than what I came up with but it seem to work properly and it is very easy to understand and also modify to suit other SPI interfaced circuits.
rogertee:
I found a sine wave generator for the Arduino Due on this site how can this be used with an Uno or is there another similar link using Uno is there anything specific to the Due that prevents an Uno being used in this specific application.
It might have been helpful to have provided a link to this generator you found on this site.
But, I see that DVDdoug has answered the question in the very first reply, so I'm not sure why I am writing this.
kamelryttarn: Trying to bit-bang SPI as you’ve attempted will result in extremely low output rates, a few kilohertz will be the limit on a 16MHz AVR.
To get the full audio range, you will need to learn how to use hardware based SPI transactions. Examine the libraries, they all use hardware based functions in the core Arduino SPI library. Hardware SPI is far easier to implement than crude, brute force bit-banging and several orders of magnitude faster.
PaulMurrayCbr:
It might have been helpful to have provided a link to this generator you found on this site.But, I see that DVDdoug has answered the question in the very first reply, so I'm not sure why I am writing this.
https://www.arduino.cc/en/Tutorial/DueSimpleWaveformGenerator
The problem with this thread is that the OP, rogertee, abandoned it and never replied. kamelryttarn resurrected it fours months later. I replied to his post in error before figuring out what had happened. Normally, I do not respond to otherwise dead threads that newbies resurrect. Mea culpa.
Not entirely sure if I should post this in this thread or start a new one, but here is an update.
I finished the bit banging code for the MCP4801 today and uploaded the sketch to a board and gave it a try but I can not explain the odd waveform in the oscilloscope.
const int CS = 9;
const int SDI = 10;
//const int SCK_ = 11;
void setup() {
pinMode(CS, OUTPUT);
pinMode(SDI, OUTPUT);
pinMode(SCK, OUTPUT);
}
void loop()
{
onetwoeight();
onethreefive();
onefourtwo();
onefivezero();
onefiveseven();
onesixfour();
onesevenone();
oneseveneight();
oneeightfive();
onenineone();
onenineeight();
twozerofour();
twozeronine();
twoonefive();
twotwozero();
twotwofive();
twothreezero();
twothreefour();
twothreeeight();
twofourone();
twofourfive();
twofourseven();
twofivezero();
twofivetwo();
twofivethree();
twofivefour();
twofivefive();
twofivefive();
twofivefive();
twofivefour();
twofivethree();
twofivetwo();
twofivezero();
twofourseven();
twofourfive();
twofourone();
twothreeeight();
twothreefour();
twothreezero();
twotwofive();
twotwozero();
twoonefive();
twozeronine();
twozerofour();
onenineeight();
onenineone();
oneeightfive();
oneseveneight();
onesevenone();
onesixfour();
onefiveseven();
onefivezero();
onefourtwo();
onethreefive();
onetwoeight();
onetwozero();
oneonethree();
onezerofive();
nineeight();
nineone();
eightfour();
sevenseven();
sevenzero();
sixfour();
fiveseven();
fiveone();
foursix();
fourzero();
threefive();
threezero();
twofive();
twoone();
oneseven();
onefour();
onezero();
eight();
five();
three();
two();
one();
zero();
zero();
zero();
one();
two();
three();
five();
eight();
onezero();
onefour();
oneseven();
twoone();
twofive();
threezero();
threefive();
fourzero();
foursix();
fiveone();
fiveseven();
sixfour();
sevenzero();
sevenseven();
eightfour();
nineone();
nineeight();
onezerofive();
oneonethree();
onetwozero();
}
void onetwoeight() //128
{
digitalWrite(CS, LOW); //initialize the chip
digitalWrite(SDI, LOW); // bit 15 - write to DAC
digitalWrite(SCK, HIGH); // trig bit 15
digitalWrite(SCK, LOW); // end trig bit 15
digitalWrite(SDI, LOW); // bit 14 - dont care
digitalWrite(SCK, HIGH); // trig bit 14
digitalWrite(SCK, LOW); // end trig bit 14
digitalWrite(SDI, LOW); // bit 13 - output gain selection
digitalWrite(SCK, HIGH); // trig bit 13
digitalWrite(SCK, LOW); // end trig bit 13
digitalWrite(SDI, HIGH); // bit 12 - output shutdown control bit
digitalWrite(SCK, HIGH); // trig bit 12
digitalWrite(SCK, LOW); // end trig bit 12
digitalWrite(SDI, HIGH); // bit 11 - D7
digitalWrite(SCK, HIGH); // trig bit 11
digitalWrite(SCK, LOW); // end trig bit 11
digitalWrite(SDI, LOW); // bit 10 - D6
digitalWrite(SCK, HIGH); // trig bit 10
digitalWrite(SCK, LOW); // end trig bit 10
digitalWrite(SDI, LOW); // bit 9 - D5
digitalWrite(SCK, HIGH); // trig bit 9
digitalWrite(SCK, LOW); // end trig bit 9
digitalWrite(SDI, LOW); // bit 8 - D4
digitalWrite(SCK, HIGH); // trig bit 8
digitalWrite(SCK, LOW); // end trig bit 8
digitalWrite(SDI, LOW); // bit 7 - D3
digitalWrite(SCK, HIGH); // trig bit 7
digitalWrite(SCK, LOW); // end trig bit 7
digitalWrite(SDI, LOW); // bit 6 - D2
digitalWrite(SCK, HIGH); // trig bit 6
digitalWrite(SCK, LOW); // end trig bit 6
digitalWrite(SDI, LOW); // bit 5 - D1
digitalWrite(SCK, HIGH); // trig bit 5
digitalWrite(SCK, LOW); // end trig bit 5
digitalWrite(SDI, LOW); // bit 4 - D0
digitalWrite(SCK, HIGH); // trig bit 4
digitalWrite(SCK, LOW); // end trig bit 4
digitalWrite(SDI, LOW); // bit 3 - X
digitalWrite(SCK, HIGH); // trig bit 3
digitalWrite(SCK, LOW); // end trig bit 3
digitalWrite(SDI, LOW); // bit 2 - X
digitalWrite(SCK, HIGH); // trig bit 2
digitalWrite(SCK, LOW); // end trig bit 2
digitalWrite(SDI, LOW); // bit 1 - X
digitalWrite(SCK, HIGH); // trig bit 1
digitalWrite(SCK, LOW); // end trig bit 1
digitalWrite(SDI, LOW); // bit 0 - X
digitalWrite(SCK, HIGH); // trig bit 0
digitalWrite(SCK, LOW); // end trig bit 0
digitalWrite(CS, HIGH); // de-initialize the chip
}
void onethreefive() //135
{
digitalWrite(CS, LOW); //initialize the chip
digitalWrite(SDI, LOW); // bit 15 - write to DAC
digitalWrite(SCK, HIGH); // trig bit 15
digitalWrite(SCK, LOW); // end trig bit 15
digitalWrite(SDI, LOW); // bit 14 - dont care
digitalWrite(SCK, HIGH); // trig bit 14
digitalWrite(SCK, LOW); // end trig bit 14
digitalWrite(SDI, LOW); // bit 13 - output gain selection
digitalWrite(SCK, HIGH); // trig bit 13
digitalWrite(SCK, LOW); // end trig bit 13
digitalWrite(SDI, HIGH); // bit 12 - output shutdown control bit
digitalWrite(SCK, HIGH); // trig bit 12
digitalWrite(SCK, LOW); // end trig bit 12
digitalWrite(SDI, HIGH); // bit 11 - D7
digitalWrite(SCK, HIGH); // trig bit 11
digitalWrite(SCK, LOW); // end trig bit 11
digitalWrite(SDI, LOW); // bit 10 - D6
digitalWrite(SCK, HIGH); // trig bit 10
digitalWrite(SCK, LOW); // end trig bit 10
digitalWrite(SDI, LOW); // bit 9 - D5
digitalWrite(SCK, HIGH); // trig bit 9
digitalWrite(SCK, LOW); // end trig bit 9
digitalWrite(SDI, LOW); // bit 8 - D4
digitalWrite(SCK, HIGH); // trig bit 8
digitalWrite(SCK, LOW); // end trig bit 8
digitalWrite(SDI, LOW); // bit 7 - D3
digitalWrite(SCK, HIGH); // trig bit 7
digitalWrite(SCK, LOW); // end trig bit 7
digitalWrite(SDI, HIGH); // bit 6 - D2
digitalWrite(SCK, HIGH); // trig bit 6
digitalWrite(SCK, LOW); // end trig bit 6
digitalWrite(SDI, HIGH); // bit 5 - D1
digitalWrite(SCK, HIGH); // trig bit 5
digitalWrite(SCK, LOW); // end trig bit 5
digitalWrite(SDI, HIGH); // bit 4 - D0
digitalWrite(SCK, HIGH); // trig bit 4
digitalWrite(SCK, LOW); // end trig bit 4
digitalWrite(SDI, LOW); // bit 3 - X
digitalWrite(SCK, HIGH); // trig bit 3
digitalWrite(SCK, LOW); // end trig bit 3
digitalWrite(SDI, LOW); // bit 2 - X
digitalWrite(SCK, HIGH); // trig bit 2
digitalWrite(SCK, LOW); // end trig bit 2
digitalWrite(SDI, LOW); // bit 1 - X
digitalWrite(SCK, HIGH); // trig bit 1
digitalWrite(SCK, LOW); // end trig bit 1
digitalWrite(SDI, LOW); // bit 0 - X
digitalWrite(SCK, HIGH); // trig bit 0
digitalWrite(SCK, LOW); // end trig bit 0
digitalWrite(CS, HIGH); // de-initialize the chip
}
void onefourtwo() //142
{
digitalWrite(CS, LOW); //initialize the chip
digitalWrite(SDI, LOW); // bit 15 - write to DAC
digitalWrite(SCK, HIGH); // trig bit 15
digitalWrite(SCK, LOW); // end trig bit 15
digitalWrite(SDI, LOW); // bit 14 - dont care
digitalWrite(SCK, HIGH); // trig bit 14
digitalWrite(SCK, LOW); // end trig bit 14
digitalWrite(SDI, LOW); // bit 13 - output gain selection
digitalWrite(SCK, HIGH); // trig bit 13
digitalWrite(SCK, LOW); // end trig bit 13
digitalWrite(SDI, HIGH); // bit 12 - output shutdown control bit
digitalWrite(SCK, HIGH); // trig bit 12
digitalWrite(SCK, LOW); // end trig bit 12
digitalWrite(SDI, HIGH); // bit 11 - D7
digitalWrite(SCK, HIGH); // trig bit 11
digitalWrite(SCK, LOW); // end trig bit 11
dac.ino (112 KB)
I put a 10 000 millisecond delay at the beginning of the loop to get a more clear picture of the problem but unfortunately it did not help much. I have attached a few different oscilloscope screenshots. I can't understand why the sine wave does not start at decimal value 128, continue with a rising wave, going down to zero and continue up again to decimal value 120.
Looks like something is hanging ..... or put on hold for a while, before continuing again. You should check out what happens.... like your functions seem to 'initialise' the chip at the beginning. Maybe associated with that kind of thing.
When your sine wave stops and resumes, it doesn't pick up where it left off, but where it would have been if it hadn't stopped. So it looks like your code keeps running, but the DAC output stops updating for a while.
Did you leave the /LDAC pin floating?
I finished the bit banging code for the MCP4801
No you didn’t, that code must get a prize for the absolute worst code ever posted here. Have you never come across a “for” loop or an array?
Basically it is a mess that it unreadable. Typical of the copy and paste generation. If you had to type all that at a terminal you would soon get the incentive to learn.