Supongamos que tenemos un circuito RC con la función de transferencia continua: \ $ G (s) = \ frac {1} {RCs + 1} \ $ con R = 1.6k, y C = 2uF. Usando la transformación bilineal (o mejor conocido como método de Tustin) \ $ s = \ frac {2} {T_s} \ frac {z-1} {z + 1} \ $ con el período de muestreo siendo \ $ T_s = 0.5ms \ $, Llego a la siguiente función de transferencia discreta:
\ $ G (z) = \ frac {z + 1} {13.8z-11.8} = \ frac {X (z)} {U (z)} \ $
En términos de una ecuación de diferencia (relación de recurrencia) el sistema discreto se describe así como \ $ u_n + u_ {n-1} = 13.8x_n-11.8x_ {n-1} \ $, donde \ $ x_n \ $ es la variable de salida actual, \ $ x_ {n-1} \ $ es la salida anterior. De manera similar, \ $ u_n \ $ es la variable de entrada actual, y \ $ u_ {n-1} \ $ es la entrada anterior. La salida de este sistema obviamente será discreta, a diferencia de la respuesta real del circuito RC.
El código que he escrito para el arduino (modelo Uno) está aquí:
#include "Wire.h"
#define PCF8591 (0x90 >> 1)
void AnalogOut(uint8_t value)
{
sei(); //enable interrupts
Wire.beginTransmission(PCF8591); // turn on the PCF8591
Wire.write(0x40); // control byte
Wire.write(value);
Wire.endTransmission();
}
int preload;
void setup()
{
pinMode(A0, INPUT);
Wire.begin();
// timer2 initialization
noInterrupts();
TCCR2A = 0;
TCCR2B = 0;
preload = 6;
TCNT2 = preload; //setting the preload
TCCR2B = (0<<CS22) | (1<<CS20)| (1<<CS21); //and the prescaler for a 0.5ms sampling time
TIMSK2 |= (1 << TOIE2);
interrupts();
}
uint8_t x_n_1=0; //x[n-1]=0; initial value of the output
uint8_t u_n; //u[n] current value of the input
uint8_t x_n; //x[n] current value for the ouptut
uint8_t u_n_1; //u[n-1] previous value for the input
//interrupt routine
ISR(TIMER2_OVF_vect)
{
TCNT2 = preload;
u_n=analogRead(A0); //reading the current input value, a/d conversion takes up about 0.15ms
x_n=uint8_t(0.07246*u_n+0.07246*u_n_1+0.855*x_n_1); //x[n]=1/13.8(u[n]+u[n-1]+11.8x[n], also converting it to a 8bite integer
AnalogOut(x_n); //writing to the PC8591 d/a converter
x_n_1=x_n ; //x[n-1] for the next sampling interval becomes the current x[n]
u_n_1=u_n; //u[n-1] for the next sampling interval becomes the current u[n]
}
void loop()
{
TCNT2=preload;
u_n_1=analogRead(A0); //getting an initial value for u[n-1]
while(1);
}
Tenga en cuenta que he usado una rutina de interrupción para generar un retraso de 0.5 ms. Además, la parte del código en la función loop () se explica mejor a continuación:
TCNT2=preload; //the timer starts ticking at its inital value
u_n_1=analogRead(A0); //we are doing this a/d conversion before even one interrupt has happened.
Aquí está el circuito que armé en proteus:
Enproteus,estoyenviando\$y=3+\sin(314t)voltios\$alaentradaanalógicaA0.Además,establezcoelvoltajedereferenciaparaelcovnertera/da5V(ennuestrolaboratoriorealpodemosconfigurarVrefusandounpotenciómetro).Estoesloqueobtuveenelosciloscopioenproteusalejecutarlasimulación: