DAC MCP4725 with Interrupt TImers

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
birdm3n
 
Posts: 3
Joined: Tue Mar 13, 2018 11:50 am

DAC MCP4725 with Interrupt TImers

Post by birdm3n »

Hi guys! I'm using an adafruit mcp4725 DAC and what I'm trying to achieve is the possibility to output an analogic value every time a clock interrupt occurs. The problem is that it is not working. The code I'm using is this one:

Code: Select all

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_MCP4725.h>

// Output 25kHz single slope PWM with timer TCC0 on D7
int i = 0;

Adafruit_MCP4725 dac;

#define DAC_RESOLUTION (10)

int sintable[256] PROGMEM = {
    512,524,537,549,562,574,587,599,611,624,636,648,660,672,684,696,707,719,730,741,753,764,774,785,796,806,816,826,836,846,855,864,873,882,890,899,907,915,922,930,
937,944,950,957,963,968,974,979,984,989,993,997,1001,1004,1008,1011,1013,1015,1017,1019,1021,1022,1022,1023,1023,1023,1022,1022,1021,1019,1017,1015,1013,1011,1008,1004,1001,997,993,989,
984,979,974,968,963,957,950,944,937,930,922,915,907,899,890,882,873,864,855,846,836,826,816,806,796,785,774,764,753,741,730,719,707,696,684,672,660,648,636,624,
611,599,587,574,562,549,537,524,512,499,486,474,461,449,436,424,412,399,387,375,363,351,339,327,316,304,293,282,270,259,249,238,227,217,207,197,187,177,168,159,
150,141,133,124,116,108,101,93,86,79,73,66,60,55,49,44,39,34,30,26,22,19,15,12,10,8,6,4,2,1,1,0,0,0,1,1,2,4,6,8,
10,12,15,19,22,26,30,34,39,44,49,55,60,66,73,79,86,93,101,108,116,124,133,141,150,159,168,177,187,197,207,217,227,238,249,259,270,282,293,304,
316,327,339,351,363,375,387,399,412,424,436,449,461,474,486,499
};


void setup()
{ 
  Serial.begin(9600);  
  dac.begin(0x62);
  
  Serial.println("MCP4725A found!");
   
  //analogWriteResolution(10);
  REG_GCLK_GENDIV = GCLK_GENDIV_DIV(1) |          // Divide the 48MHz clock source by divisor 1: 48MHz/1=48MHz
                    GCLK_GENDIV_ID(4);            // Select Generic Clock (GCLK) 4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  REG_GCLK_GENCTRL = GCLK_GENCTRL_IDC |           // Set the duty cycle to 50/50 HIGH/LOW
                     GCLK_GENCTRL_GENEN |         // Enable GCLK4
                     GCLK_GENCTRL_SRC_DFLL48M |   // Set the 48MHz clock source
                     GCLK_GENCTRL_ID(4);          // Select GCLK4
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Feed GCLK4 to TCC0 and TCC1
  REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN |         // Enable GCLK4 to TCC0 and TCC1
                     GCLK_CLKCTRL_GEN_GCLK4 |     // Select GCLK4
                     GCLK_CLKCTRL_ID_TCC0_TCC1;   // Feed GCLK4 to TCC0 and TCC1
  while (GCLK->STATUS.bit.SYNCBUSY);              // Wait for synchronization

  // Normal (single slope) PWM operation: timers countinuously count up to PER register value and then is reset to 0
  REG_TCC0_WAVE |= TCC_WAVE_WAVEGEN_NPWM;         // Setup single slope PWM on TCC0
  while (TCC0->SYNCBUSY.bit.WAVE);                // Wait for synchronization

  // Each timer counts up to a maximum or TOP value set by the PER register,
  // this determines the frequency of the PWM operation:
  REG_TCC0_PER = 1919;                            // Set the frequency of the PWM on TCC0 to 25kHz
  while(TCC0->SYNCBUSY.bit.PER);                  // Wait for synchronization
 
  // Set the PWM signal to output 50% duty cycle on D7
  REG_TCC0_CCB3 = 959;                            // TCC0 CCB3 - on output on D7 50% duty cycle
  while(TCC0->SYNCBUSY.bit.CCB3);                 // Wait for synchronization

  NVIC_SetPriority(TCC0_IRQn, 0);    // Set the Nested Vector Interrupt Controller (NVIC) priority for TCC0 to 0 (highest)
  NVIC_EnableIRQ(TCC0_IRQn);         // Connect TCC0 to Nested Vector Interrupt Controller (NVIC)

  REG_TCC0_INTENSET = TC_INTENSET_OVF;            // Enable TCC0 overflow interrupt

  // Divide the 48MHz signal by 1 giving 48MHz (20.83ns) TCC0 timer tick and enable the outputs
  REG_TCC0_CTRLA |= TCC_CTRLA_PRESCALER_DIV1 |    // Divide GCLK4 by 1
                    TCC_CTRLA_ENABLE;             // Enable the TCC0 output
  while (TCC0->SYNCBUSY.bit.ENABLE);              // Wait for synchronization

}

void loop() {}


// Interrupt handler called every time the TCC0 timer overflows
void TCC0_Handler()                              // Interrupt Service Routine (ISR) for timer TCC0
{ 
  // Check for overflow (OVF) interrupt
  if (TCC0->INTFLAG.bit.OVF && TCC0->INTENSET.bit.OVF)             
  {
    dac.setVoltage(pgm_read_word(&(sintable[i])), false);
    i++;
    if(i==256)
      i=0;   
    REG_TCC0_INTFLAG = TC_INTFLAG_OVF;         // Clear the OVF interrupt flag
  }
}
Why does it not work in your opinion? Thanks!

User avatar
adafruit_support_bill
 
Posts: 88136
Joined: Sat Feb 07, 2009 10:11 am

Re: DAC MCP4725 with Interrupt TImers

Post by adafruit_support_bill »

Interrupts are disabled on entry to an ISR. And you can't do i2c communication without interrupts.

Set a flag in the ISR and use it to trigger a read on the next pass through your loop.

User avatar
birdm3n
 
Posts: 3
Joined: Tue Mar 13, 2018 11:50 am

Re: DAC MCP4725 with Interrupt TImers

Post by birdm3n »

I have already tried that solution but I can't obtain a sinewave of 25kHz as I need. The code you are suggesting to use in the ISR is something like:

Code: Select all

flag = 1;
And in the loop:

Code: Select all

if(flag){
    dac.setVoltage(...)
    flag = 0;
}
Correct? This solution does not work in my case.

User avatar
adafruit_support_bill
 
Posts: 88136
Joined: Sat Feb 07, 2009 10:11 am

Re: DAC MCP4725 with Interrupt TImers

Post by adafruit_support_bill »

I can't obtain a sinewave of 25kHz as I need.
25KHz is going to be impossible with a 100KHz i2c clock. 40 microseconds on the wire doesn't even allow you to transmit the entire i2c address. You could try increasing the i2c clock to 400KHz. You might even get it to run at 800KHz.

User avatar
birdm3n
 
Posts: 3
Joined: Tue Mar 13, 2018 11:50 am

Re: DAC MCP4725 with Interrupt TImers

Post by birdm3n »

Have you got any idea on how to modify the clock frequency for the i2c communication?

User avatar
adafruit_support_bill
 
Posts: 88136
Joined: Sat Feb 07, 2009 10:11 am

Re: DAC MCP4725 with Interrupt TImers

Post by adafruit_support_bill »

The Wire library setClock() function will do that:

https://www.arduino.cc/en/Reference/WireSetClock

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”