Pages: [1]   Go Down
Author Topic: High speed read of bipolar signal, -> ADC (LTC1605)  (Read 2363 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,

I am starting experiments on a setup next week and was interested in using a standalone Arduino application next to the (overkill) Matlab dSpace interface. I really like Matlab and Simulink, but I am intrigued by the idea of implementing a control loop within the Atmega 328P.

Here's the setup;
Reference input, an audio signal, so both positive and negative voltages
Sensor output, an accelerometer, putting out both positive and negative voltages

Once I find a control loop, say, just an error times a transferfunction, it would be nice to implement it in an Arduino environment

Here's the issue;
I want a "sample 2 inputs -> substrackt -> run filter-> output"-time of say 1/10000 s = 100 us
Assume the filter to be quite "filled with dynamics". So no simple 1 zero 2 poles transfer function.

Do any of you have experience with similar implementations? I am not sure whether the Atmega can do this at ease or if it is impossible.

I read about implementing Simulink code on an Arduino. That would be awesome, but then again, I am not sure the (calculation)speed is high enough for my goals.

If it's impossible to do, so be it. However, if with little modifications something like this can be accomplished, that would be great!

http://www.mathworks.com/matlabcentral/fileexchange/35639
http://arduino.cc/forum/index.php/topic,6549.0.html
https://sites.google.com/site/measuringstuff/the-arduino#TOC-Sample-Rates

 
« Last Edit: February 24, 2013, 04:55:22 am by SuperR » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 221
Posts: 13848
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

\Can you give a glimpse of the complexity of the code you want to implement?
Logged

Rob Tillaart

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

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Something like this is the discretized transfer function;

>> c2d(C,0.0001)
 
Transfer function:
 
                                                                                   
 7.716 z^7 - 37.57 z^6 + 73.23 z^5 - 71.39 z^4 + 34.81 z^3 - 6.785 z^2 - 0.001332 z
                                                                                   
                                                                       - 1.96e-008 
                                                                                   
-------------------------------------------------------------------------------------
                                                                                     
z^7 - 3.882 z^6 + 5.648 z^5 - 3.652 z^4 + 0.8852 z^3 - 1.632e-005 z^2 + 1.002e-010 z
                                                                                     
                                                                     - 2.053e-016 
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 221
Posts: 13848
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


such a formula can be calculated quite well with an Arduino.

float x1 = ((((((7.716 * z - 37.57) * z + 73.23) * z  - 71.39) * z + 34.81) * z - 6.785) * z - 0.001332) * z - 1.96e-008 

This trick brings it down to 14 "simple" float operations instead of using power

Main problem might be that the Arduino only supports 32bit IEEE754 floats with ~7 significant digits.

Logged

Rob Tillaart

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

United Kingdom
Offline Offline
Tesla Member
***
Karma: 227
Posts: 6637
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

If you need to sample 2 inputs, you face an immediate problem which is that the Arduino in its default configuration takes about 100us to do a single ADC conversion. If you can tolerate reducing the number of bits resolution below 10, then you can increase the ADC clock frequency and achieve faster conversion times.

You will need to write the code something like this so that you are not waiting on the ADC conversions:

Start conversion of input A
Do half of the maths on the previous pair of samples
Wait for conversion to complete
Read the result of the conversion of input A
Start conversion of input B
Do the remaining half of the maths on the previous pair of samples
Wait for conversion to complete
Read the result of the conversion of input B
Repeat from start

What I don't know is whether you can do the maths fast enough on an Arduino, but you can measure that yourself.

You will be sampling the inputs at slight different times (maybe 50us apart). If that isn't acceptable, you will have to use an external ADC chip with faster conversion time.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I think 10bit resolution is fine. However, I have both positive and negative voltages. If it helps to use an external ADC and DAC, I think that's possible. And DC42, nice to know that code can be run while I wait for the ADC is running. I'll investigate further within the next couple weeks.
Logged

Offline Offline
Faraday Member
**
Karma: 62
Posts: 3077
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't understand how you plan to have output to an accelerometer.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From an accelerometer, not to. The accelerometer is my sensor
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I have been informed of the Arduino Due, which might solve my speed-problems. An order is pending so I should be up and running shortly. More to come smiley
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ok, there's an update on the situation;

Instead of using the analogread or shaping the analog signals so that they fit the requirements of the Arduino Due internal adc, I am going to implement a dedicated ADC. The one available at the lab is a LTC1605. Just the IC, I need to built a PCB so I am free to implement different/extra IC's.

http://cds.linear.com/docs/en/datasheet/1605fc.pdf

Therefore, the questions now turns into;
What is the fastest/best way to turn those 16 output pins of the IC into a value in my Arduino Due? And even worse, I would read two of these ADC's.

After studying the spec sheet my steps would be;
Put CS low, (initiate conversion of ADC)
Wait 8 uS, time it takes between CS low and valid data
Read 1 byte, (8 I/O pins) from ADC1
Read 1 byte, (8 different I/O pins), from ADC2
Put "Byte" high,
Read second byte from ADC1
Read second byte from ADC2

That would cost me around 20 pins for 2ADC's, leaving me plenty pins for the DAC, which uses around 20 too.
 

« Last Edit: February 24, 2013, 05:21:21 am by SuperR » Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ADC is up and running, at least, we receive data which matches the voltage on the multimeter smiley. I was planning on using a TXB0104 for the 5V to 3.3V conversion. That way, I can safely measure the 2 8bit streams. Since I have to wait for parts and we would like to keep our code-progress up, for today, a simple voltage divider will be attemped, 2 r's op 2k5 I thought were used. I'll keep you updated.

If someone has an idea on how to implement the discretized transferfunction, please inform me!

Code:
>> c2d(C,0.0001)
 
Transfer function:
 
                                                                                    
 7.716 z^7 - 37.57 z^6 + 73.23 z^5 - 71.39 z^4 + 34.81 z^3 - 6.785 z^2 - 0.001332 z
                                                                                    
                                                                       - 1.96e-008  
                                                                                    
-------------------------------------------------------------------------------------
                                                                                    
z^7 - 3.882 z^6 + 5.648 z^5 - 3.652 z^4 + 0.8852 z^3 - 1.632e-005 z^2 + 1.002e-010 z
                                                                                    
                                                                     - 2.053e-016
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hmmz, the ADC is taking around 30us. I was hoping it would be faster. I hope I can read the ports faster. I was hoping to simultaneously read all 8 bits instead of ready each one individually. Please comment

Code:
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);
}


byte RC = 40;
byte BYTE = 42;
byte b1_pin = 22, b2_pin = 24, b3_pin = 26, b4_pin = 28, b5_pin = 30, b6_pin = 32, b7_pin = 34, b8_pin = 36;

int b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16;

int output;
float outputV;
//long bit1, bit2, bit3, bit4, bit5, bit6, bit7, bit8;


void setup() {

pinMode(b1_pin, INPUT);
pinMode(b2_pin, INPUT);
pinMode(b3_pin, INPUT);
pinMode(b4_pin, INPUT);
pinMode(b5_pin, INPUT);
pinMode(b6_pin, INPUT);
pinMode(b7_pin, INPUT);
pinMode(b8_pin, INPUT);

pinMode(RC, OUTPUT);
pinMode(BYTE, OUTPUT);

digitalWriteDirect(RC,HIGH);
digitalWriteDirect(BYTE,LOW);

// Serial.begin(9600);
}

void loop() {
  digitalWriteDirect(BYTE,LOW);
  digitalWriteDirect(RC,LOW); 
  delayMicroseconds(1);
  digitalWriteDirect(RC,HIGH);
  delayMicroseconds(6);
 
  b9 = digitalReadDirect(b1_pin);
  b10 = digitalReadDirect(b2_pin);
  b11 = digitalReadDirect(b3_pin);
  b12 = digitalReadDirect(b4_pin);
  b13 = digitalReadDirect(b5_pin);
  b14 = digitalReadDirect(b6_pin);
  b15 = digitalReadDirect(b7_pin);
  b16 = digitalReadDirect(b8_pin);
  //bit_val = b8 + 10*b7 + 100*b6 + 1000*b5 + 10000*b4 + 100000*b3 + 1000000*b2 + 10000000*b1;
 
  digitalWriteDirect(BYTE,HIGH);
  delayMicroseconds(1);
  b1 = digitalReadDirect(b1_pin);
  b2 = digitalReadDirect(b2_pin);
  b3 = digitalReadDirect(b3_pin);
  b4 = digitalReadDirect(b4_pin);
  b5 = digitalReadDirect(b5_pin);
  b6 = digitalReadDirect(b6_pin);
  b7 = digitalReadDirect(b7_pin);
  b8 = digitalReadDirect(b8_pin);
 
  output = (b2 << 14) + (b3 << 13) + (b4 << 12) + (b5 << 11) + (b6 << 10) + (b7 << 9) + (b8 << 8) + (b9 << 7) + (b10 << 6) + (b11 << 5) + (b12 << 4) + (b13 << 3) + (b14 << 2) + (b15 << 1) + b16;
  if (b1 == 1) { outputV = (-32767 + output)/3276.8; } // 10V per 2^15 bit
  else {outputV = output/3276.8; } // 10V per 2^15 bit

Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 221
Posts: 13848
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
If someone has an idea on how to implement the discretized transferfunction, please inform me!

Whjat do you mean exactly, I posted a faster version of your function in reply 3 .
Have you measured the time difference?
Logged

Rob Tillaart

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

0
Offline Offline
Newbie
*
Karma: 0
Posts: 38
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, either I interpreted your code wrongly, or you did mine.
The z in the transferfunction is not some value but the "Z transform".

Imagine the following problem;

I need to store data from the past in some container/array;
Some "error", which stores values of the past 7 values of error
Some "u", which stores values of the past 7 values of u.

Define k to be the current sample. u(k) therefore will be the output of my equation.
Define (k-7) to be the data from a variable 7 samples ago. error(k-7) should be the value of error, 7 samples ago.

Now here comes the "fun";
To calculate u(k), I need to read all values, from error(k-7) to error(k) and u(k-7) to u(k-1). I then need to multiply those values by a certain set of 13 fixed values, say 7.7662, 2.34632 etc.
After that, I need to sum those values to get to u(k), which is send to the DAC.

Before the next calculation loop begins, I need to shift every "past value" one instance further away to the past. I only need to store the last x values so when the sample is too old, I can discard it.

I think the use of an array should be ideal. Is there a (dis)advantage of using 2 arrays for each value over storing the values in 1 "big" (14 value) array?

And inevitably, there's the float/integer issue again. Since I don't want to waste previous run-time, I was thinking of scaling up all values by 10, 100 of 1000 so that I can use 2byte integers for my calculations instead of the 4 byte floats. Will that help with the speed or is the difference negligible? I would think the calculation time would double, but I'm not the expert.

« Last Edit: March 01, 2013, 03:04:43 am by SuperR » Logged

Pages: [1]   Go Up
Jump to: