Arduino Due DAC0 problem (not working)

I got an Arduino Due from a retailer in hopes of driving stereo sound from both DACs.

I'm well aware of the fragile DACs, so for testing I plugged both DAC0 and DAC1 to my oscilloscope (1Mohm inputs) with passive probes at 10× attenuation setting. At 3.3V this is well below the 3mA limit current for DAC lines.

Both seemed to work fine, but at some point DAC0 stopped working. This happened exactly after running code in which I accidentally passed a value > 4095 to analogWrite for DAC0. An example of what I did:

void setup() {
  analogWriteResolution(12);
}

void loop() {
  analogWrite(DAC0, (micros() % 4096) * 2);  // Bug, I intended to do "(micros() * 2) % 4096"
  analogWrite(DAC1, micros() % 4096);
}

Now DAC0 is mostly at GND level regardless of what I analogWrite. If I run the code above passing just "micros() % 4096" to both DACs, DAC1 shows a sawtooth wave as expected but DAC0 shows a short negative voltage (what?) when value == 0 and then goes back to GND level.

I'm not sure if the buggy code was the source of the problem, but I can't think of any other way I might have fried DAC0 since I didn't connect it to anything besides my oscilloscope.

It sure seems weird I was able to break the DAC from code and, if it was the case, protection against bad values in the library might be sensible. Though DAC1 is still working perfectly I don't have the guts to run the faulty code against it to test if it was the culprit for fear of breaking it too.

Is the DAC0 really broken or am I missing something? Is it possible that the buggy code was the source of the problem? Am I just incredibly unlucky and got a faulty unit? Any chances the warranty will cover this?

Is it possible that the buggy code was the source of the problem?

Absolutely no possibility.

My guess is that you shorted the adjacent pin some time when you connected it to your scope. Although it could have just gone.

but DAC0 shows a short negative voltage (what?) when value == 0 and then goes back to GND level.

You would get that if there is some AC coupling going on somewhere.

We had a very similar problem a few weeks ago and he replaced the Due and all was fine.

Any chances the warranty will cover this?

Possibly, ask your suppler.

Grumpy_Mike:
My guess is that you shorted the adjacent pin some time when you connected it to your scope. Although it could have just gone.

Hmmm... how could that happen? I tested directly in the DAC0 female pin header, so no short should have happened. I was specially careful not to scratch the header on the inside, carefully inserting the probe's tip was more than enough to get the signal shown in the oscilloscope.

Just to make sure my procedure is correct (I don't want to break anything else): I just attached the alligator clip in my probe to a GND pin in Arduino Due via a jumper cable and then inserted the probe's tip in DAC0.

Given how sensitive these pins seem to be I would recommend adding 1k series
resistance to them as a matter of routine to reduce the chance of damage...

Just to make sure my procedure is correct (I don't want to break anything else): I just attached the alligator clip in my probe to a GND pin in Arduino Due via a jumper cable and then inserted the probe's tip in DAC0.

Yes that procedure sounds safe enough.
Is your scope correctly grounded and is your ground a good connection to the earth ( the actual soil )?
On my scopes the probes would not reach inside the pins, but I have seen others that could.

I'm well aware of the fragile DACs, so for testing I plugged both DAC0 and DAC1 to my oscilloscope (1Mohm inputs) with passive probes at 10× attenuation setting. At 3.3V this is well below the 3mA limit current for DAC lines.

Now, I'm thinking its possible to exceed the max ratings of the DAC outputs even with 10x setting. Checking through the SAM3X datasheet for "pf" reveals that other than I2C, other outputs specified have 50 pF or much less max loading ... but I couldn't find anything specified for the DAC outputs.

Of course, changing the DAC output instantly from 0V to max or max to 0 are worst case scenarios (for impedance). From now on, I'll clip the probe to a 1K resistor in series (as MarkT suggested) the next time I test these (or any) outputs on the Due, even though I haven't had any problems so far.

Just to add to the confusion, I tried shunting the output of DAC1 through various low resistances for a few seconds whilst it was outputting a sine wave, before eventually shorting it to ground for a second. It still works! :~

Has anyone managed to blow DAC1? All the failures I've seen have been on DAC0. I am now convinced it's a problem with the SAM3X silicon rather than anything we are doing wrong.

Are the two signals routed differently on the PCB perhaps? Near the DC-DC converter IC?

MarkT:
Given how sensitive these pins seem to be I would recommend adding 1k series
resistance to them as a matter of routine to reduce the chance of damage...

Seems sensible to do, just in case. I'd actually add a resistance greater than 1.1k? (3.3v/1.1k? = 3mA, the maximum rating.)

Future DAC0 owners, add at least an 1.2k? series resistor!

Grumpy_Mike:
Is your scope correctly grounded and is your ground a good connection to the earth ( the actual soil )?

My scope is correctly grounded through "Schuko" sockets to the mains ground connection, which I assume is properly grounded (or at least I hope my building complies with safety regulations :P)

dlloyd:
Now, I'm thinking its possible to exceed the max ratings of the DAC outputs even with 10x setting.

My oscilloscope inputs are also labelled as 1M? + ?22pF which as far as I know should add to the probe's impedance. I might be wrong here, but even at ? frequency it should be safe because of the 1M? resistance, right?

MarkT:
Are the two signals routed differently on the PCB perhaps? Near the DC-DC converter IC?

Just checked Due's official PCB and both signals are routed side by side.

RE: DACC Analog Current Register (DACC_ACR)
Bits 9,8 (IBCTLDACCORE) Bias Current Control for DAC Core
Bits 3,2 (IBCTLCH1) Analog Output Current Control for channel 1
Bits 1,0 (IBCTLCH0) Analog Output Current Control for channel 0

I've checked the status of this register and found that several unused bits have changed when both outputs are off. Although these bits are undocumented or unused, shouldn't they always read 0?

DACC_ACR bit:                    9876543210
With any one or both outputs on:  100001010  <-- normal mode as per datasheet
With both outputs off:            110101010  <-- bits 7 and 5 are high

Code as above but with DACC_ACR status on serial monitor:

void setup() {
  analogWriteResolution(12);
  Serial.begin(115200);
}

void loop() {
  //analogWrite(DAC0, (micros() % 4096) * 2);  // Bug, I intended to do "(micros() * 2) % 4096"
  //analogWrite(DAC1, micros() % 4096);

  Serial.println (REG_DACC_ACR, BIN);
  delay (1000);
}

Note: IBCTLCHx Allows to adapt the slew rate of the analog output. (from datasheet).
It seems strange that the SAM3X's DAC outputs have slew rate control with 4 possibilities but the datasheet only documents "01" as being normal mode. I'm now wondering if bits 0 to 3 in the DACC_ACR register remain stable during enabling, disabling or writing to DAC0 and DAC1 channels.

EDIT (addendum): Re Section 45.7, Table 45-3
Reset of the DACC_ACR is 0x00000000 ... it is not held in this state when DAC channels are deactivated. Is this used or is this necessary? Just some questions ... I do not have the experience, debugging hardware, nor time to investigate further (sorry).

OK, so I investigated a "bit" further...

In the code below, a workaround is on line 3.
When line 3 is commented out, the DACC_ACR register will have binary status 110101010 until the user's sketch runs the analogWrite() command (for example when i = 3), upon which time the DACC_ACR register changes to and remains at 100001010 (as per datasheet).

void setup() {
  analogWriteResolution(12);
  //dacc_set_analog_control(DACC, DACC_ACR_IBCTLCH0(0x02) | DACC_ACR_IBCTLCH1(0x02) | DACC_ACR_IBCTLDACCORE(0x01));
  Serial.begin(115200);
}

void loop() {
  for (int i = 0; i <= 5; i++) {
    if (i == 3)
    {
      analogWrite(DAC0, (micros() % 4096) * 2);
      analogWrite(DAC1, micros() % 4096);
    }
    Serial.print ("When i = ");
    Serial.print (i);
    Serial.print (", REG_DACC_ACR = ");
    Serial.println (REG_DACC_ACR, BIN);
    delay (1000);
  }
}

The undefined/unused bits 7 and 5 in the DACC_ACR register are being set high after executing a software reset (REG_DACC_CR = 0x1). After checking all readable registers in the DACC software interface after software reset (SWRST), I've added the results to the register mapping table below for comparison:

[b][color=teal]Table 45-3. Register Mapping   (pg 1373)[/color]         Binary Reading
                                                          After
Register                       Name       Reset           SWRST
[/b]Mode Register                  DACC_MR    0x00000000          0
Channel Status Register        DACC_CHSR  0x00000000          0
Interrupt Mask Register        DACC_IMR   0x00000000          0
Interrupt Status Register      DACC_ISR   0x00000000       1100
Analog Current Register        DACC_ACR   0x00000000  110101010
Write Protect Mode Register    DACC_WPMR  0x00000000          0
Write Protect Status Register  DACC_WPSR  0x00000000          0

Is software reset working correctly on the ACR and ISR register?

Quite interesting. I decided to test software reset on my board, and here is result:

REG_DACC_MR = 43
REG_DACC_CHSR = 1
REG_DACC_IMR = 4
REG_DACC_ISR = 2
REG_DACC_ACR = 10A
REG_DACC_WPMR = 0
REG_DACC_WPSR = 0

REG_DACC_MR = 0
REG_DACC_CHSR = 0
REG_DACC_IMR = 0
REG_DACC_ISR = 0
REG_DACC_ACR = 1AA
REG_DACC_WPMR = 0
REG_DACC_WPSR = 0

REG_DACC_MR = 43
REG_DACC_CHSR = 1
REG_DACC_IMR = 4
REG_DACC_ISR = 2
REG_DACC_ACR = 10A
REG_DACC_WPMR = 0
REG_DACC_WPSR = 0

First block is normal status (function sine generator 1k), second block - after software reset, and third one after setting DACC back calling initializing subroutine. Nothing breaks , fortunately. My results slightly different on ISR, but the same regarding ACR register. IMHO, 1AA = 110101010 - is default configuration, and it's not clear what is the purpose of the bits 5 & 7.
May be good question for Atmel technical support team.

DAC_SW_reset_test_1a.ino (8.72 KB)

May be good question for Atmel technical support team.

I agree. Perhaps the Arduino developers are already aware of this.

I couldn't resist just directly writing 0x0 to the ACR register using REG_DACC_ACR = 0x0;
... this worked as the read back status would become 0x0 (unchartered territory).

On the DAC0 and DAC1 pins, I then confirmed full voltage swing with an external 100K resistor, so it looks like the outputs are now placed in high impedance mode.

Using REG_DACC_ACR = 0x0; to replace line 3 in the script I posted earlier worked OK. The only difference now is that the ACR register status will initially read 0x0 (reset) until the first analogWrite is run, then it becomes 0x10A as expected.

Arduino, which uses the software reset command of the control register (SWRST) never resets the ACR as per Table 45-3.

Arduino, which uses the software reset command of the control register (SWRST) never resets the ACR as per Table 45-3.

I agree on this, table clearly says reset status 0x0 , and obviously it's not.
My understanding, based on table 46-38,

Sleep Mode
Fast Wake Up
Normal Mode with 1 Output On (IBCTLDACCORE = 01,
IBCTLCHx =10)
Normal Mode with 2 Outputs On (IBCTLDACCORE =01,
IBCTLCHx =10)

that setting ACR to 0x0 you send all unit down to sleep mode. IBCTLHx most likely control reference current level for S/H circuitry, and daccore explains itself. I can't resist to drive all unit up, to 30F, setting max bias current for core and two S/H. My mini DSO shows no noticeable difference -).

//  dacc_set_analog_control(DACC, DACC_ACR_IBCTLCH0(0x02) | DACC_ACR_IBCTLCH1(0x02) | DACC_ACR_IBCTLDACCORE(0x01));
  dacc_set_analog_control(DACC, DACC_ACR_IBCTLCH0(0x03) | DACC_ACR_IBCTLCH1(0x03) | DACC_ACR_IBCTLDACCORE(0x03));

Will keep it working all night, mini-stress testing

Some differences regarding DAC0 ...

  • After SWRST, Channel 0 is selected in the MR for data requests (USER_SEL).
  • After SWRST, DAC0 is selected while ACR status is 0x1AA (bits 5 and 7 on with unknown purpose).
    By the time DAC1 is selected, ACR status would be 0x10A as per datasheet.
  • The DAC0 pin serves as a wake-up source for the supply controller (DAC0/WKUP12). By default, DAC1 would not be selected during any wake-up event.
    Note from datasheet (29.2.10 Fast Startup):
    Important: Prior to asserting any WFE instruction to the processor, the internal sources of
    wakeup provided by RTT, RTC and USB must be cleared and verified too, that none of the
    enabled external wakeup inputs (WKUP) hold an active polarity.

Will keep it working all night, mini-stress testing

With ACR at 30F ... could be unchartered slew rate. If it passes, I think it deserves getting some sleep :wink:

10 hours test pass. Probably, writing 0x3 (DACC_ACR_IBCTLCH0(0x03)) instead of 0x2 has no difference.
I checked what is arduino IDE using inside analogWrite - it's 0x2.