Reputation: 23
I am working on a Recorder and Player Project. I want to implement both ADC (Analog to Digital) and DAC (Digital to Analog) Convertors. The code should be implemented in Arduino - Atmega 2560 (Atmel Microcontroller). I have tried to implement the ADC and I found the following code:
void setup()
{
Serial.begin (9600);
ADCSRA |= ((1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0));
ADMUX |=(1<<REFS0);
ADCSRA |= (1<<ADEN);
ADCSRA |= (1<<ADSC);
}
int read_adc( int channel )
{
ADMUX &=0xE0;
ADMUX |= channel & 0x07l;
ADCSRB = channel & (1<<ADSC);
ADCSRA |= (1<<ADSC);
while (ADCSRA & (1<<ADSC))
{
return ADCW;
}
}
void loop()
{
int w = read_adc(0);
Serial.write(w);
}
Here I am sending the digitized signal to the serial port. I have two Questions: 1- How can I modify this code to work as 8-bit ADC? 2- How to implement DAC the same way as before ? I mean how to read digital signal from the serial and then convert it to Analog signal like alorithm above?
Thank you for your help.
Upvotes: 1
Views: 11164
Reputation: 146
There are a number of DAC devices that work using SPI bus inputs on the market, ranging from 8 bit to 16 bit (and greater) resolution. I've looked at all of the alternatives, and IMHO the best compromise between price and resolution is the MCP4xxx series.
Adafruit has a MCP4921 breakout board that is readily available to provide 12 bit single channel. I've chosen to use the MCP4822 to provide 12 bit dual channel resolution. The MCP48xx series also has an internal voltage reference, which ensures a stable output voltage in the face of variable supply voltage. This is less flexible than the MCP49xx series, where an external Vref is used.
Because of the digital noise on the AVR (Arduino) power supplies which typically exceeds 20mV, using more than 12 bit of resolution (1mv LSB) doesn't seem to get greater accuracy. Also 16 bit DACs cost significantly more than the MCP4xxx range.
If you need a DC capable output, it makes sense to use an OpAmp to buffer the DAC. Alternatively, if AC is all you need (audio) then there are cheap headphone amplifiers available that do a great job as a buffer.
If you need to use the AVR SPI bus as a source for the data (uSD card for example) and the source is slow, then you can use a USART port on the ATmega2560 in MSPI Mode to drive the DAC using an interrupt without disturbing the main SPI interface.
Here's a snapshot of an analogue interface implemented on an ATmega1284p platform, which I happen to have handy.
The DAC.h code can be found on sourceforge in AVRfreeRTOS.
Upvotes: 0
Reputation: 93476
The ATMega2560 has no DAC peripheral, however if your bandwidth requirements are relatively low, you can use a PWM output with suitable external analogue filtering to produce a variable output voltage (proportional to the pulse width).
The higher the PWM frequency, the higher the bandwidth, but the lower the resolution, so there is a trade-off. A simple low-pass RC filter may suffice. In some cases - such as LED or DC motor drive for example, you do not need any filtering at all, and a PWM is the more efficient method of driving such loads in any case. For audio applications however you will generally need filtering, unless directly driving a Class D ampifier.
To implement an 8 bit DAC you need to configure the PWM for 256 counts-per-cycle, then simply set the pulse width from zero to 255 counts. When adequately filtered, this will result in an analogue voltage. To make the filtering as simple as possible, the PWM frequency should be as high as possible and the filter cut-off frequency set to at least half that frequency, and better less that f/5 or more. This will determine your audio bandwidth. For speech, 3Khz is about adequate (telephone quality); 4.5KHz is AM radio quality, while 15KHz is FM radio/HiFi quality.
There are a number of on-line resources an papers on using PWM as a DAC and the necessary filtering; for example http://ltwiki.org/images/8/82/PWM_Filters.pdf
Upvotes: 4
Reputation: 1
If your board does not have a DAC then you can use an additional DAC IC and simply interface it with the GPIO port. I have done this in a project where I used CortexM0 microcontroller's GPIO and a DAC to generate analog output for a DC motor. You may also need an opAmp to amplify the DAC output depending on your application type.
Upvotes: 0