Go Down

Topic: 16bit DAC parallel bits, AD669 (Read 2 times) previous topic - next topic

Grumpy_Mike

Quote
Once here I was warned that TRUE/FALSE and HIGH/LOW might some day not be 1/0 so my code should not assume that and won't be compatible. I had to LOL since hey, I should live so long! But then that person advocates using C++ Strings on UNO's and not being hardware-centered.

Yes but two things, one that is rubbish, two he was talking about a chip outputting something, so that means a physical output. Lets see the guardians of C redefine a TTL output.

Quote
In the digitalWrite help it says explicitly it want either HIGH or LOW so I was under the assumption that those two inputs were the only ones accepted.


As an engineer once told be assumption is the mother of all **** ups.

Quote
For the ADC I will be implementing I will use this code,

Won't that only work with 8 bits?

SuperR

I have not tried it yet with more than 4 pins. For the ADC I will read 1 byte per ADC. When I put "byte" high, the lowbyte and highbyte flip so per ADC I can read the 16 bits with "just" 8 inputs. Therefore I can use 2 ADC's and a DAC without running out of pins.

GoForSmoke


Quote
Once here I was warned that TRUE/FALSE and HIGH/LOW might some day not be 1/0 so my code should not assume that and won't be compatible. I had to LOL since hey, I should live so long! But then that person advocates using C++ Strings on UNO's and not being hardware-centered.

Yes but two things, one that is rubbish, two he was talking about a chip outputting something, so that means a physical output. Lets see the guardians of C redefine a TTL output.


I'm not sure that person is a he but was talking about source code. I called it garbage too. But perhaps that person doesn't recognize the relation of bits to wire states as anything but incidental or thinks that code now should be compatible to some future age where binary logic is outdated and the crass obfuscation of using tricky operations like XOR will die with the ancient ones who lived close to the metal.
I've seen it in new compsci degree holders back since 87 but we're still here and LOW is still 0 and HIGH is still 1 without any sign of a big change, and XOR is still useful and used!
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

SuperR

Ok, now the loop takes 12.5 us. So every 12.5us, a new value is put into the dac and outputted. I think I can reduce this period by smarter bitsetting, but I don't know how to do best. Ideally I want to stick to the pins I use now, 30-45, so not an unique port. I expect the for loop to take most of the time.

Code: [Select]

//Definieer digitalwrite en digitalread-direct

inline void digitalWriteDirect(int pin, boolean val){
  if(val) g_APinDescription[pin].pPort -> PIO_SODR = g_APinDescription[pin].ulPin;
  else    g_APinDescription[pin].pPort -> PIO_CODR = g_APinDescription[pin].ulPin;
}

inline int digitalReadDirect(int pin){
  return !!(g_APinDescription[pin].pPort -> PIO_PDSR & g_APinDescription[pin].ulPin);


}


int update = 8;

//trim DC output to 0, depends on resistor specs and board layout
int offset = 23;

//Halfway ideal value 2^16 / 2 + the offset adjustment
int zero = 32768+offset;

//2^16 / 20 volts is value per volt
float scale = 3276.8;

//DAC reference, what should the output be? In volts.
float input = 0.1;

//Define the value which is send to the DAC, with scaling and offset.
int value = 0; //Value to DAQ;

void setup() {               
 
 
  //Define DAC PINS
  pinMode(update, OUTPUT);
  digitalWrite(update, LOW);
  pinMode(A0, INPUT);
  pinMode(30, OUTPUT);
  pinMode(31, OUTPUT);
  pinMode(32, OUTPUT);
  pinMode(33, OUTPUT);
  pinMode(34, OUTPUT);
  pinMode(35, OUTPUT);
  pinMode(36, OUTPUT);
  pinMode(37, OUTPUT);
  pinMode(38, OUTPUT);
  pinMode(39, OUTPUT);
  pinMode(40, OUTPUT);
  pinMode(41, OUTPUT);
  pinMode(42, OUTPUT);
  pinMode(43, OUTPUT);
  pinMode(44, OUTPUT);
  pinMode(45, OUTPUT);
                         
 
}

// the loop routine runs over and over again forever:
void loop() {

//Put value out to DAC

//Determine integer to DAC
value = round(zero+input*scale);

//Put DAC pins high 
for(int x = 30; x < 46; x++){digitalWriteDirect(x, bitRead(value,x-30)); }

//Update DAC output value
digitalWriteDirect(update, HIGH);
digitalWriteDirect(update, HIGH);
//Fix outpur value
digitalWriteDirect(update, LOW);
   
}

GoForSmoke

Get rid of the floats and it will speed up.

scaling integers ---- scaled_value = value x scale_numerator / scale_denominator

don't forget to use an integer type that will hold intermediate results.


Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

SuperR

I took apart the for loop and gained another us. After that, I tested the time it actually takes to put the pins high by copying the 16 lines of code and pasted it below. The loop now takes 5 us more time. So that is the most amount of time I can gain by smarted output writing.

Concerning the float;
The signal that will be output by the DAC will be the outcome of some equations which may vary anywhere between -10 V and +10 V. If using integers really speeds up the progress I will keep that in mind when I built de code which does the calculations.

I think the DAC is going to be ok. Now it's time for the ADC, but I am waiting for some logc level converters before I can use the DUE for that purpose.

robtillaart

Quote
Get rid of the floats and it will speed up.
scaling integers ---- scaled_value = value x scale_numerator / scale_denominator
don't forget to use an integer type that will hold intermediate results.


biggest step can be gained by removing float divisions as these are the worst.

Volts = analogRead(A0) * 5.0/1024;
performs worse than
Volts = analogRead(A0) * 0.004882812;

but yes removing floats completely gains even more.

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

GoForSmoke

Integer scaling is done completely with integers. The order of operations, * before / preserves the most accuracy.
If I want to ensure 3 places extra accuracy I might multiply by an extra 1000 that I don't divide by and treat the result as 1000x bigger. Like in printing I would insert a decimal point before the last 3 digits in text.

Pick your working units to suit your methods and leave what the humans see have it's own routines.





Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Go Up