I've hooked up the MCP4725 to my Arduino and can get it to output a sinewave using the example code. But how do I change the frequency?
I (think) that changing the number of steps in the waveform lookup table changes the frequency: more values in the array = longer wavelength = lower pitch. And I think changing the TWBR clock speed in the library changes how quickly the array is read? But I can't figure out how to use these values to set a specific frequency.
How, for example, might I create a 440Hz sinewave?
Change frequency for MCP4725
Moderators: adafruit_support_bill, adafruit
Please be positive and constructive with your questions and comments.
- adafruit_support_mike
- Posts: 67485
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Change frequency for MCP4725
The technically correct answer is "emit the complete set of samples every 2,273 microseconds."
There are two mutually-constrained values there: the number of samples you have, and the delay between emitting samples. The more samples you have, the less time you can wait between one and the next. "Number of samples" times "delay between samples" has to equal 2.273uS to hit 440Hz though.
In practical terms, you usually want a maximum delay between samples so the output looks/sounds smooth. Dividing the period of the frequency you want by that maximum delay tells you the minimum number of samples you'll need. The maximum number of samples is limited by how fast you can send values out, so the size of your sample set will be somewhere between those two numbers.
As a technical trick, make the number of samples a multiple of 2^n where n is the number of octaves you want to play. Going up an octave simply doubles the frequency, so instead of emitting samples [1,2,3,...] once, emit samples [2,4,6,...] with the same delay, and play them twice. That way you get good resolution on your low frequencies, and good speed on your high frequencies.
There are two mutually-constrained values there: the number of samples you have, and the delay between emitting samples. The more samples you have, the less time you can wait between one and the next. "Number of samples" times "delay between samples" has to equal 2.273uS to hit 440Hz though.
In practical terms, you usually want a maximum delay between samples so the output looks/sounds smooth. Dividing the period of the frequency you want by that maximum delay tells you the minimum number of samples you'll need. The maximum number of samples is limited by how fast you can send values out, so the size of your sample set will be somewhere between those two numbers.
As a technical trick, make the number of samples a multiple of 2^n where n is the number of octaves you want to play. Going up an octave simply doubles the frequency, so instead of emitting samples [1,2,3,...] once, emit samples [2,4,6,...] with the same delay, and play them twice. That way you get good resolution on your low frequencies, and good speed on your high frequencies.
- JeffThompson
- Posts: 42
- Joined: Mon Jun 14, 2010 3:05 pm
Re: Change frequency for MCP4725
Thanks Mike! Whew – I know that your reply makes sense, but my head is swimming a bit.
- How did you come up with a delay time of 2.273uS for 440Hz?
- How do you set that delay?
- "Period of the frequency you want" is not the same thing as the frequency?
- Is the speed of the MCP4725 = the 200kHz listed on the product page?
- adafruit_support_mike
- Posts: 67485
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Change frequency for MCP4725
If you want 440 of something to happen in 1 second, each one has to take 1/440th of a second. 1/440=0.002272727, which can also be written 2,272.727/1,000,000. 1 microsecond is 1/1,000,000 seconds, and a bit of rounding gives us 2,273uS.JeffThompson wrote:How did you come up with a delay time of 2.273uS for 440Hz?
With an Arduino, you'd probably use the delayMicroseconds() function to get a short interval.JeffThompson wrote:How do you set that delay?
Period and frequency are inverses of each other. Period (usual symbol 'T') means "how long it takes". Frequency (usual symbol F), means "how often it happens".JeffThompson wrote:"Period of the frequency you want" is not the same thing as the frequency?
The mathematical formula is T=1/F
Kind of.JeffThompson wrote:Is the speed of the MCP4725 = the 200kHz listed on the product page?
200kHz output means you change the DAC's output value 200,000 times per second. That puts the period for each output value at 1/200,000th of a second, or 5uS. The main limit on update frequency is how long it takes to get the new settings into the chip, so the values above say it's possible to update the chip's output every 5uS if you have a microcontroller that can talk fast enough.
To make that happen, the microcontroller has to send data to the chip at 3.4 million bits per second, or 3.4MHz.
An Arduino normally transmits I2C data at 100kHz, about 34 times slower than the maximum data frequency. That means it will take about 5uS x 34 = 170uS per update. That's the update period, so the update frequency will be about 5.9kHz.
You can make an Arduino send I2C data at 400kHz, which would take the update rate up to about 23.5kHz.
That doesn't mean you get a 23.5kHz sine wave. It means you get 23,500 (or 5,900) different output values per second. If you want 440 copies of a sine wave, you can't have more than 23,500/440=53.47 or 5,900/440=13.36 different output values per sine wave.
In practice, handling fractional sample values makes things too complicated, so you just use the integers 53 or 13, then figure out how long each output value will need to last if you're setting that many values in the period of the output frequency you want (2,273uS for 440Hz).
- JeffThompson
- Posts: 42
- Joined: Mon Jun 14, 2010 3:05 pm
Re: Change frequency for MCP4725
Thank you! This was not super intuitive, but I think I understand the frequency-to-period and sample rate.
It doesn't seem to be working as expected, though.
My Arduino code:
And the Adafruit MCP4725 library, changed to run either 400 or 100kHz:
Weirdly, I get the right pitch (or pretty close to it) with the 14-item array, which (as I understand it) should be for the 100kHz clock, not 400...
Am I close? Thank you!
It doesn't seem to be working as expected, though.
My Arduino code:
Code: Select all
#include <Wire.h>
#include <Adafruit_MCP4725.h>
// 100kHz clock
const PROGMEM uint16_t sineLookup[14] = {
2048, 3000, 3733, 4081, 3963, 3406, 2538, 1558,
690, 133, 15, 363, 1096, 2048
};
const int wavelength = 14;
// 400kHz clock
//const PROGMEM uint16_t sineLookup[54] = {
// 2048,2290,2529,2761,2983,3192,3385,3559,
// 3712,3842,3946,4024,4074,4095,4088,4052,
// 3988,3897,3780,3638,3475,3291,3089,2874,
// 2646,2410,2169,1927,1686,1450,1222,1007,
// 805,621,458,316,199,108,44,8,
// 1,22,72,150,254,384,537,711,
// 904,1113,1335,1567,1806,2048
//};
//const int wavelength = 54;
Adafruit_MCP4725 dac;
void setup(void) {
dac.begin(0x62);
}
void loop(void) {
for (uint16_t i=0; i<wavelength; i++) {
dac.setVoltage(pgm_read_word(&(sineLookup[i])), false);
}
}
Code: Select all
#ifdef TWBR
uint8_t twbrback = TWBR;
TWBR = ((F_CPU / 400000L) - 16) / 2; // Set I2C frequency to 400kHz
// TWBR = ((F_CPU / 100000L) - 16) / 2; // Set I2C frequency to 100kHz
#endif
Am I close? Thank you!
- adafruit_support_mike
- Posts: 67485
- Joined: Thu Feb 11, 2010 2:51 pm
Re: Change frequency for MCP4725
You're sending all the samples through the DAC as fast as they can go.
Try this:
Try this:
Code: Select all
int period = 1000000 / 440; // period of 440hz in microseconds
int rate = period / wavelength; // length of time between samples
int sample = 0;
void loop(void) {
dac.setVoltage(pgm_read_word(&(sineLookup[ sample ])), false);
sample = ( sample < wavelength ) ? sample + 1 : 0;
delayMicroseconds( rate );
}
- abdullahhinaidi
- Posts: 1
- Joined: Mon Mar 26, 2018 1:43 am
Re: Change frequency for MCP4725
I need to change the output frequency up to 1000 HZ. I did not understand what should I change, and how can I change it to any other frequency.
- JeffThompson
- Posts: 42
- Joined: Mon Jun 14, 2010 3:05 pm
Re: Change frequency for MCP4725
I think you would change the in the code directly above to .
Code: Select all
440
Code: Select all
1000
- salmo
- Posts: 1
- Joined: Tue May 01, 2018 2:41 pm
Re: Change frequency for MCP4725
Hello,
The delay time for 440Hz is 2,273ms (millisecond), not 2,273us (microsecond) ?
The delay time for 440Hz is 2,273ms (millisecond), not 2,273us (microsecond) ?
- petrepa
- Posts: 1
- Joined: Mon Jul 09, 2018 7:00 am
Re: Change frequency for MCP4725
Hi, guys!
Did you figure this out? Working on a project where I need to be able to set the frequency, but can not find out how to do it.
Did you figure this out? Working on a project where I need to be able to set the frequency, but can not find out how to do it.
Please be positive and constructive with your questions and comments.