Help with using DAC [ATtiny816]

Go To Last Post
16 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I am using an Attiny816 microcontroller and I'm trying to use the DAC.

 

In my code, I have the function DAC_init, as shown in the code below.

 

What I have done so far:

 

1. Set PortA, Pin 6 as output (for the DAC output)

2. Chosen a voltage reference (VREF) of 2.5V

3. Enabled DAC to a pin

4. Did some calculation to determine the binary input that I wanted (hopefully using right formula) in order to get the voltage I wanted on output

5. Wrote the value from step 4 into the data register for DAC and it should if I am right, then do the conversion and I see the voltage I wanted on output.

 

Am I missing anything in using the DAC? On my project board that I have, There's two test points, one was set up for the analog comparator output and one was set up for

the DAC output. I wanted DAC output to be used as input to analog comparator. On one of the pins, multimeter reads about~0.5 V, and when I switch to the other, it reads 0, I am assuming the test point for 0 is the AC.

 

Would like a 1.667 or so output on the DAC so we can use that as input to the AC.  Can anybody advise on where I may have gone wrong or missing something? Thanks!

 

 

 

void DAC_init(void)
{
	// DAC output pin
	PORTA.DIRSET |= (1<<6); // PA6 for DC Output

	// DAC reference of 2.5V (???)
	VREF.CTRLA |= VREF_DAC0REFSEL_2V5_gc;

	// Enable DAC output to pin
	DAC0.CTRLA = DAC_OUTEN_bm;

	/* Use the DAC Data to get the voltage that you want to see on the DAC output
		DAC on tiny816 is 8 bit, therefore 2^8 = 256
		then in that case,
		DAC output = DAC DATA input / 2^N * Vref
		if we wanted 1.667 as the DAC out to the comparator,
		then 1.667 = DAC DATA input / 256 * 2.5 (let's assume that Vref chosen is 2.5)
		then DAC DATA INPUT = (decimal) 170.7008  = (binary) 10101010 = 0xAA  

		So we will now feed into the DAC DATA the value 0xAA
	 */	

	// Ready to write the 0xAA data in and then fire the conversion
	DAC0.DATA = 0xAA;	

 

Last Edited: Fri. Feb 23, 2018 - 05:01 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can you disconnect the DAC output pin from the AC input pin?  If so what is the voltage on the DAC output pin?

 

Jim

 

Click Link: Get Free Stock: Retire early!

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The datasheet says you need to enable the DAC (bit 0 of CTRLA).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@Jim

 

Like I have mentioned previously, on the project board that I have, there is a test point for which I can measure DAC output. I have another test point which I can use to measure analog comparator output.

 

In the code that I attempted to write as shown in original post #1, I only have the DAC attempt and I have not wrote anything to configure the analog comparator yet.

 

Therefore, I am thinking that the ~0.5 V I am seeing should be the DAC output voltage.

 

 

 

@El Tangas, ok thank you for the information, I will attempt to add the enable bit of DAC. That is probably why I'm not seeing what I should see. Will keep you guys updated when I get more stuff in.

 

 

Thanks, I appreciate all the help.

 

 

 

Last Edited: Thu. Feb 22, 2018 - 11:59 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

 

I am back to looking at my DAC. Not seeing output on oscilloscope that makes sense for DAC output so far, don't know why.

 

Also, the Analog comparator seems to be working, when set neg input of analog comparator to use the DAC output. But that doesn't make sense either.

 

Below is my functions that I wrote that I am using to try to get DAC / AC working.  DAC intialization, Analog comparator initialization and the Analog comparator ISR. What could be going wrong? Could it be some hardware issue if my code below is valid?

 

void DAC_init(void)
{
	
	// Set PA6 as output 
	PORTA.DIRSET = DAC_OUT ;
	  
	// DAC reference of 2.5V
	VREF.CTRLA |= DAC_VREF;
	
	// Enable DAC output to pin
	DAC0.CTRLA = DAC_OUTEN_bm;
	
		
	/*	Use the DAC Data to get the voltage that you want to see on the DAC output
		DAC output = DAC DATA input / 2^N * Vref
		DAC on tiny816 is 8 bit, therefore 2^N = 2^8 = 256
		
		For example:
			If we wanted 1 V as the DAC out to the comparator, 
			then 1 = DAC DATA input / 256 * 2.5 (let's assume that Vref chosen is 2.5)
			then DAC DATA INPUT = (decimal) 102.4  = (binary) ?01100110? = 0x66
		
		So DAC DATA will get the value 0x66
	 */	
	
	// Ready to write the DAC data in and then fire the conversion
	
	DAC0.DATA = DAC_INPUT;	
	
	// Enable DAC
	DAC0.CTRLA |= DAC_ENABLE_bm; 	
}


/*---------------------------------------------------------------------------------------------------------
ANALOG COMPARATOR:
Vo = 1 if V+ > V-, else 0 

Compares the voltage from PA6 (pin 6 DAC output), which is connected to - input of comparator with 
the voltage from  PA7 (pin 7 MD output [ref AINP0 of AC]), which is connected to the + input of 
comparator.
		  
Once the voltage on the + goes below the voltage on the -, the comparator output goes low 
and triggers the interrupt to run. The ISR sets a flag, for which the STS LED will be turned on (see MAIN). 
*/

void AC_init (void)
{
	// Set pin 5 as output (AC Out)
	PORTA.DIRSET = PIN5_bm; 

	// DAC output on negative input of AC
	AC0.MUXCTRLA = AC_MUXNEG_DAC_gc;	

	// Input signal to positive pin0 of AC (AINP0)
	AC0.MUXCTRLA = AC_MUXPOS_PIN0_gc;		

	// Comparator interrupt request is triggered on falling (negative) edge
	AC0.INTCTRL = AC_INTMODE_NEGEDGE_gc;
	
	// Enable the AC
	AC0.CTRLA = AC_ENABLE_bm;
	
	// Enable analog comparator interrupt
	AC0.INTCTRL = AC_CMP_bm;
}


//---------------------------------------------------------------------------------------------------------
// Analog comparator interrupt
volatile bool triggered; 

ISR(AC0_AC_vect)
{	
	// Clear the interrupt flag
	AC0.STATUS = AC_CMP_bm;

	// Set 'motion detected' flag
	triggered = true;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Is the DAC driving any kind of load? The datasheet shows a minimum load impedance of 5k, if it's lower I suppose you will get errors.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi El Tangas,

 

 

Yes, I see in the datasheet it says "The DAC has one continuous time output with high drive capabilities, which is able to drive 5kΩ and/or 30pF load"

 

 

But I am just using the DAC output as input to the Analog comparator. That is all that the DAC is supposed to do. The Analog comparator is as part of motion detection and a flag is set to indicate when triggered and in the main code (not shown), when triggered, blue led would turn on when that happens.

 

I'm sure that I've got the oscilloscope leads on the correct location on the board I am using (not an xplained board of any sort)

 

Getting the DAC to work shouldn't be that complicated or so I think :(

 

 

 

Last Edited: Tue. Feb 27, 2018 - 10:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mc0134 wrote:
Getting the DAC to work shouldn't be that complicated or so I think :(

 

You're right, it shouldn't... It's getting late around here, but tomorrow maybe I'll test some of your code to see if I can find any problem.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks El Tangas. Hopefully we'll figure out why it's not doing what it's supposed to do.

 

EDIT:

 

FYI, I did have defines for stuff such as the DAC_INPUT as shown below

DAC0.DATA = DAC_INPUT;	
Last Edited: Wed. Feb 28, 2018 - 02:22 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I used ATtiny 1616 and the DAC worked fine.

 

#include <avr/io.h>

int main(void) {

    // PORT init ------------------------------------------------------------------------------
    for (uint8_t i = 0; i < 8; i++) {
        *((uint8_t *)&PORTA.PIN0CTRL + i) |= PORT_PULLUPEN_bm;
        *((uint8_t *)&PORTB.PIN0CTRL + i) |= PORT_PULLUPEN_bm;
        *((uint8_t *)&PORTC.PIN0CTRL + i) |= PORT_PULLUPEN_bm;
    }

    // VREF init ------------------------------------------------------------------------------
    VREF.CTRLA |= VREF_DAC0REFSEL_2V5_gc;
    VREF.CTRLB |= VREF_DAC0REFEN_bm;

    // DAC_init------------------------------------------------------------------------------
    DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm;
    DAC0.DATA = 0xAA;

    while (1) {}
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok, based on #10 this seems to be the minimum code needed to get the DAC output:

 

#include <avr/io.h>

int main(void) {

    // DAC output pin
    // PORTA.DIRSET |= (1<<6); // PA6 for DC Output (not needed)

    // VREF init ------------------------------------------------------------------------------
    VREF.CTRLA |= VREF_DAC0REFSEL_2V5_gc;

    // DAC_init------------------------------------------------------------------------------
    DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm;
    DAC0.DATA = 0xAA;

    while (1) {}
}

You don't need to set the port as output, the DAC overrides the port settings.

I got this on my scope:

 

 

As you can see, there is a noise of about 100mV amplitude superimposed on the output, with a frequency of 3.33MHz (the CPU clock). This may be because I don't have a decoupling cap between VCC and GND for this test.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you add this one line please try to see how the waveform will change.

VREF.CTRLB |= VREF_DAC0REFEN_bm;
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It doesn't change. I had that like in the beginning because I copied your code, then I removed it to see what happens. Nothing different.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks for the replies everyone! This morning I got something working after having read through El Tangas and kabsan's replies and I am happy so far smiley 

 

I had a tiny817 xplained mini board and did a test  (with the IDE obviously set to use tiny817). I removed everything related to analog comparator at this time and  used the code on post #10 by kabasan (see below for code)

 

I am able to get the set the dac input to whatever value I wish and get the correct value showing up on the multimeter! (both tiny816 abd 817 have dac out on PA6 and both are using 8 bit DAC)  The following is the scope output that I connected to my tiny817 xplained board and below the scope screen capture is the code that I currently am running on the xplained 817 board.

 

I am able to change the input values to the DAC and get the multimeter to read apropriate values (i.e., with 2.5 Vref set for the DAC, 0xAA into Dac input shows me 1.66 approx on multimeter like image shown below, 0x66 into dac, 1v shows , 0x33 gives me 0.5V on multimeter, etc.) 

 

Now, I believe it's a hardware issue on my non-xplained board that is using the attiny816 mcu because I cannot get the good values that my xplained board happily shows me (and I'm pretty sure that I am measuring the correct test point on the non-xplained board)

 

Will let you know about updates on the non-xplained board later, but if anybody got any more comments or wish to add a helpful reply, Id appreciate it too.

 

Hopefully getting  DAC to work on my tiny816 board should be as simple as my official xplained mini board indicates! indecision

 

 

 

 

#include <avr/io.h>

int main(void)
{

    // Set PA6 to output (still included anyway just in case, even though El Tangas has mentioned not necessary)
    PORTA.DIRSET |= (1 << 6);

   // Set VREF
   VREF.CTRLA |= VREF_DAC0REFSEL_2V5_gc;

  // ENABLE DAC and SEND OUTPUT TO PIN
  DAC0.CTRLA = DAC_ENABLE_bm | DAC_OUTEN_bm;

  // WRITE DAC DATA AND FIRE THE CONVERSION
  DAC0.DATA = 0xAA;
}

 

Last Edited: Wed. Feb 28, 2018 - 04:46 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

mc0134 wrote:
, I believe it's a hardware issue on my non-xplained board

 

A picture of your board would be next, look it over for possible short to gnd or to an adjacent pin, or water based flux that has not been washed off...

 

Jim

 

Click Link: Get Free Stock: Retire early!

share.robinhood.com/jamesc3274

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

El Tangas wrote:

This may be because I don't have a decoupling cap between VCC and GND for this test.

 

I will reply to myself in post #11: Indeed it was the absence of a decoupling capacitor that caused the ripple. Soldering a 100nF cap directly to the MCU pins I get:

 

 

Now the ripple is barely detectable with about 5mV amplitude instead of 100mV (I marked it with arrows). Just goes to show, don't omit the decoupling caps even in your quick breadboard prototypes.