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:
No estoy seguro de si esto funcionaría en el dispositivo real ya que lo haremos en nuestro laboratorio en un par de días como parte de un curso de sistemas de control digital. ¿Es la señal de mierda solo el resultado de una simulación deficiente o hay otro error? He intentado generar una onda de diente de sierra (discreta) usando este mismo circuito (pero sin ninguna entrada o función de transferencia, solo salida de señal simple) y funcionó bien.