10 years, 10 months ago.

AnalogOut and maths probleme?

Hello,

I do sawtooth wave ramps with my mbed and his DAC and during my experiment i see a probleme.

if you take this two codes with the only change is the maths opperator you don't have the same ramps.

doesn't work

for(i=0;i<terminal;i++)  sawtooth  = sawtooth - 0.001;

doesn't work

for(i=0;i<terminal;i++)  sawtooth  = sawtooth + 0.001;

I do the test with the AnalogOut.write_u16 function and it work but not with float type.

it work

int sawtooth_u16 = sawtooth.read()*65535;
if(flag)  sawtooth_u16 = sawtooth_u16 - 65;
else  sawtooth_u16 = sawtooth_u16 + 65;
sawtooth.write_u16(sawtooth_u16);

i hope a good result!

Thx, YSI

Question relating to:

3 Answers

10 years, 10 months ago.

The specification for AnalogOut says that the write method accepts a float parameter representing a percentage. That is a bit confusing since the valid range is between 0.0 and 1.0 (and not between 0.0 and 100.0 as you might expect).

Did you declare sawtooth as float in your first example? You will get a constant value of '0' when declaring sawtooth as int because of rounding,

10 years, 10 months ago.

Hi, YSI

Try this:

   for(int i=0; i<1000; i++) {
      signal = signal + 0.001;
      wait_us(1);
   }

How did you declare i at first, when it didn't work?

-=-=-=-=-=-=-=-=

thenoble66

Y SI
poster
10 years, 10 months ago.

Hi,

@Wim Huiskamp and Gyozo Nemes thx for answers.

sawtooth is my AnalogOut so it's accepts a float parameter between 0.0 and 1.0 i am agree.

My probleme isn't my AnalogOut, it work! The bug is on opperator '+' and '-' on floating signal. For my two first code i try to illustrate that when you do '+' or '-' you dont have the same result.

i take picture of my scope for illustrate the sawtooth wave generate by the two first code.

opperator +

for(i=0;i<terminal;i++)  sawtooth  = sawtooth + 0.001;

/media/uploads/YSI/wp_000608.jpg

opperator -

for(i=0;i<terminal;i++)  sawtooth  = sawtooth - 0.001;

/media/uploads/YSI/wp_000609.jpg

YSI

#include "mbed.h"

DigitalOut L1(LED1);
DigitalIn  sawtooth(p9); // this is a control line for rampup (left unconnected) or rampdown (on GND)
AnalogOut signal(p18); // DAC output

float   justAFloat; // temporary variable for math operations

int main() {
   sawtooth.mode(PullUp); // pullup mode for control line
   while(1) {
      if (sawtooth) {    // this is the part for ramp-up
         justAFloat = 0.0;
         for(int i=0; i<1000; i++) {
            L1 = 1;
            justAFloat = justAFloat + 0.001;   // do not use the signal directly
            L1 = 0;
            signal = justAFloat;   // new value to DAC signal
            wait_us(1);
         };
      }
      else {                   // this is the part for ramp-down
         justAFloat = 1.0;
         for(int i=0; i<1000; i++) {
            L1 = 1;
            justAFloat = justAFloat - 0.001;
            L1 = 0;
            signal = justAFloat;
            wait_us(1);
         };
      }
   }
}

At first sight it seems, that if you work on DAC output directly by some math operations, subtracting and adding work with different steps, that is why decrementing finishes faster, than incrementing. If you use a different variable for math and only the result will go to DAC, everything goes well. I'll have to read the datasheet of the 1768 and some library source to find a better explanation on this.

Regards.

posted by Gyozo Nemes 24 Jun 2013

Hi Gyozo Nemes,

Sorry for time to answer and my bad english level. Thanks for your help, your code works because you work always on different variable and never controle your DAC result. So the only difference beetwen our code is i use DAC read() function, if you take your code and put a read function beetwen each decrementing or incrementing you can see the bug.

code buged

#include "mbed.h"
 
DigitalOut L1(LED1);
DigitalIn  sawtooth(p9); // this is a control line for rampup (left unconnected) or rampdown (on GND)
AnalogOut signal(p18); // DAC output
 
float   justAFloat; // temporary variable for math operations
 
int main() {
   sawtooth.mode(PullUp); // pullup mode for control line
   while(1) {
      if (sawtooth) {    // this is the part for ramp-up
         justAFloat = 0.0;
         for(int i=0; i<1000; i++) {
            L1 = 1;
            justAFloat = justAFloat + 0.001;   // do not use the signal directly
            L1 = 0;
            signal = justAFloat;   // new value to DAC signal
            wait_us(1);
            justAFloat = signal.read();
         };
      }
      else {                   // this is the part for ramp-down
         justAFloat = 1.0;
         for(int i=0; i<1000; i++) {
            L1 = 1;
            justAFloat = justAFloat - 0.001;
            L1 = 0;
            signal = justAFloat;
            wait_us(1);
            justAFloat = signal.read();
         };
      }
   }
}

But where i am lost and i don't understand, that is in my first post i give a working code with DAC read function but write_u16 fonction and it work ...

it work

int sawtooth_u16 = sawtooth.read()*65535;
if(flag)  sawtooth_u16 = sawtooth_u16 - 65;
else  sawtooth_u16 = sawtooth_u16 + 65;
sawtooth.write_u16(sawtooth_u16);
posted by Y SI 02 Jul 2013

Best is to use a seperate variable and write that to the analogOut. Problem by incrementing the analogout is that you read the rounded previously written value, so you get rounding errors continiously, and apparantly that is slightly different for incrementing an decrementing. Even if it would be the same, it still is a better idea to prevent that rounding altogether: just increment/decrement a variable and write that to AnalogOut.

posted by Erik - 02 Jul 2013

Like Erik said: use a separate variable. In your working code you've just used a separate variable, namely sawtooth_u16, that is the reason why your code is working. So, don't be lost ;-)

BTW: even the documentation page says for the AnalogOut.read():

Quote:

This value may not match exactly the value set by a previous write()

Regards.

posted by Gyozo Nemes 02 Jul 2013