FRDM KL25Z DAC Overshooting

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

FRDM KL25Z DAC Overshooting

Jump to solution
3,387 Views
nick92
Contributor II

Hey guys,

I was testing the DAC on my KL25Z earlier today and found something that's not supposed to be there:

http://imgur.com/yZPgXjV

What you are seeing there is me cranking up the amplitude of the DAC (0 to 1000, increasing 100 a step, then back down to 0 again, decreasing by 100 each step).

The DAC is 12 bits.

This is causing me problems because it eventually causes something like this:

http://imgur.com/FfWkJk0

You can clearly see those spikes ruining my sine wave!

http://imgur.com/wnfqoKT

(This is the spikes zoomed in)

I am following this tutorial to make the sine wave in case someone is wondering; you can find the code there as well:

http://mcuoneclipse.com/2013/02/23/dac-example-with-the-freedom-board/

I'm open to all ideas and suggestions guys.

Cheers!

1 Solution
2,053 Views
paulmartin
Contributor III

Hey Nick,

I want you to try to write the 12bit data in a single write instead of 2 separate ones.

For testing purposes, replace the call to DA1_SetValue with this:

uint16_t * buffer_array_base_pointer = (uint16_t * ) (0x4003F000u);

buffer_array_base_pointer[0] = data;

If this does not work you can alternatively use the DAC buffer array. That way you output one value, write to the next cell in the buffer and switch to that next value with the software trigger. This is a bit more complicated, because i dont know if PE has a module to do that right away. If not you have to keep track of which cell is the current output and so on.

But it effectively means that you switch values with a single write operation as well.

Martin

View solution in original post

12 Replies
2,053 Views
paulmartin
Contributor III

Hi,

I think i know what is happening. I think you are writing the 12 bit DAC value in the wrong order. There is a high byte and a low byte. THe values in your step function are:

100 = 0x64

200 = 0xC8

300 = 0x12C this goes wrong

400 = 0x190

500 = 0x1F4

600 = 0x258 this goes wrong

whenever the high byte increases or decreases your algorithm fails.

In the case of 300 you dont get 0x12C but you get 0x2C = 44.

in the case of 600 you dont get 0x258 but you get 0x158 = 344.

basically for a short period of time you only update the low byte and this can be seen on the scope.

If you can, try switching the order in which you write low and high byte.

Best regards Martin

0 Kudos
2,053 Views
nick92
Contributor II

Hey Martin,

I suspect my SetData function is not set up correctly by PE: http://imgur.com/oHaFR8C

Shouldn't Data high start at 4003F001 (according to Datasheet).

If so how can I correct this?

Thanks in advance,

Nick.

EDIT:

I tried writing High byte first then Low byte; it seemed to invert the direction of the spikes. Before the spikes shoot down on the way up of the sine wave then shoot up on the way down. Now, they shoot up on the way up and shoot down on the way down.

This is how I tried to invert the writing method:

#define DAC_PDD_SetData(PeripheralBase, Data, RegIndex) ( \

      (DAC_DATH_REG(PeripheralBase,(RegIndex)) = \

       (uint8_t)(( \

        (uint8_t)(( \

         DAC_DATH_REG(PeripheralBase,(RegIndex))) & ( \

         (uint8_t)(~(uint8_t)DAC_DATH_DATA1_MASK)))) | ( \

        (uint8_t)((uint16_t)(Data) >> 8U)))), \

        (DAC_DATL_REG(PeripheralBase,(RegIndex)) = \

       (uint8_t)(Data)) \

    )

0 Kudos
2,053 Views
paulmartin
Contributor III

Hey Nick,

Yeah my original thought was that the DAC registers were synchronized but after reading the manual I know that they are not. (Some registers only affect the actual hardware once a specific register is written to.)

Also the addresse (4003F000) is correct because the offset is added to in case of DATH.

The problem with the PE implementation is just that it takes ages to run. basically there is a long delay between the first write and the second.

You can speed up the proccess but you will loose some of the comfort of reusability and generality.

What the original macro does is:

write the low byte to the low register

read the high register

keep the "reserved" bits intact and add the new high byte

write the high register

This assumes that freescale could at some point use the reserved bits for some other purpose and this code leaves them unaffected.

But this will probably never happen.

Try this definition and report if the spikes have changed:

#define DAC_PDD_SetData(PeripheralBase, Data, RegIndex) ( \

      (DAC_DATH_REG(PeripheralBase,(RegIndex)) = \

        (uint8_t)((uint16_t)(Data) >> 8U)), \

      (DAC_DATL_REG(PeripheralBase,(RegIndex)) = \

       (uint8_t)(Data)) \

    )

Martin

0 Kudos
2,053 Views
nick92
Contributor II

Hey Martin,

Thanks for the reply; I have tried your configuration suggestion and it inverted the direction of the spikes again: Shooting up on the way up and shooting down on the way down.

I'm really stumped.

Regards,

Nick.

0 Kudos
2,053 Views
paulmartin
Contributor III

Did the spikes get shorter in terms of time?

What bus frequency are you running on the MCU?

Each write to a peripheral can take multiple bus cycles. Maybe it cannot get any faster.

0 Kudos
2,053 Views
nick92
Contributor II

Hey Martin,

- The spikes seems to be constant. The only change to the spikes that I have noticed is only when I set to write the High Byte before the Low Byte with the code you have suggested. The spikes return to correct level faster but they are still there.

- I did not change the Bus and Core clock so they are at 20.97152 MHz. I have tried running it at different speeds but the spikes still persists. I have also tried adding a wait command before setting the DAC value but this also makes no difference.

It doesn't really make sense, I mean all configurations are default from PE and it doesn't work correctly.

Regards,

Nick.

0 Kudos
2,054 Views
paulmartin
Contributor III

Hey Nick,

I want you to try to write the 12bit data in a single write instead of 2 separate ones.

For testing purposes, replace the call to DA1_SetValue with this:

uint16_t * buffer_array_base_pointer = (uint16_t * ) (0x4003F000u);

buffer_array_base_pointer[0] = data;

If this does not work you can alternatively use the DAC buffer array. That way you output one value, write to the next cell in the buffer and switch to that next value with the software trigger. This is a bit more complicated, because i dont know if PE has a module to do that right away. If not you have to keep track of which cell is the current output and so on.

But it effectively means that you switch values with a single write operation as well.

Martin

2,053 Views
randylee
Contributor V

Yep, this is clearly a bug in PE code.  It shouldn't be doing this sort of thing on a 12bit DAC.  8, yes.  But this is a bug for sure.

0 Kudos
2,053 Views
nick92
Contributor II

Dear Martin,

I have tried you suggestion and it works! I really appreciate all your help. Do you perhaps know how to get the KL25Z to output data to a text file?

Thanks in advance,

Nick.

0 Kudos
2,053 Views
paulmartin
Contributor III

If you mean output debug information to your PC, then the usual approach is to use a terminal application on the PC side and some kind of serial communication, mostly UART. You should be able to find something like that in PE. You can then save this data stream to a file.

Martin

0 Kudos
2,053 Views
nick92
Contributor II

Hey Martin,

Thank you for your suggestion, I have tried to set up a UART interface to view the values I get from the ADC but it seems like I am not putting the values in the buffer correctly. If you really don't mind, can you take a look at the code please?

Thanks again,

Nick.

0 Kudos
2,053 Views
Paul_Tian
NXP Employee
NXP Employee

Hi, Nicola

If possible, please send your project to me. I would like to check it for you. Thanks.

Best Regards

Paul

0 Kudos