Pregunta tonta: alguno de los valores de las variables dentro de ese bucle ¿cambia por alguna interrupción o un DMA o algo parecido?
En teoría no, don Diego, porque si miras el fuente, el cálculo sólo se hace cuando capturado=1, mientras que el array se modifica en la interrupción del Timer cuando capturado=0.
Además, si alguna interrupción fuera la responsable de modificar alguna de esas variables, lo sería más en tanto más tiempo durase el cálculo. Por tanto, quitar el delay_ms no sería una fuente de errores, sino todo lo contrario.
Pero no sé, lo mismo se me está escapando algo.
Dejo aquí abajo el código. No me lo critiquéis mucho que está lleno de "mierda" porque aún ando debuggeando.
¿Podés subir un bloque "compilable" donde haga el error?
Aquí va:
#include <18F1320.h>
#device ADC=10
#device HIGH_INTS=TRUE
#include "math.h"
#FUSES NOWDT //No Watch Dog Timer
#use delay(internal=8MHz)
#use rs232(baud=115200,parity=N,bits=8,stream=PORT1, xmit=PIN_B1, rcv=PIN_B4)
#define SALIDA PIN_B3
#define MUESTRASENCICLO 72
#define NUMMUESTRAS MUESTRASENCICLO*10 // Cada onda a 50Hz está dividida en 36 muestras. Cogemos 10 ondas
#define OFFSET 512.0 // Restamos 512 porque la señal tiene un offset de 2.5V
#define AJUSTAADC 5.0/1024.0 // 5V a 10bits de resolución
unsigned int16 muestras[50];
int16 buffer, objetivo;
float onda, consumo;
int16 potencia;
unsigned int8 capturado, calculado;
unsigned int8 contadorPWM, cortePWM;
unsigned int8 IndMuestra=0;
#INT_RDA HIGH
void intser()
{
char c;
if ((c>='0') && (c<='9'))
buffer = buffer*10 + c - '0';
if ((c == '\r')) {
objetivo = buffer;
buffer=0;
}
if (c=='0')
output_low(SALIDA);
if (c=='1')
output_high(SALIDA);
// Como la interrupción RDA habrá interrumpido la lectura de la onda, empezamos de nuevo
IndMuestra=0;
onda = 0;
}
#INT_EXT
void cruce_por_cero() {
output_low(SALIDA);
set_timer2(0);
contadorPWM=0;
if (!capturado) {
capturado=1;
}
if (calculado) {
calculado=0;
capturado=0;
IndMuestra=0;
}
}
#INT_TIMER2
void LeerADC() {
if (!capturado) {
muestras[IndMuestra]=read_adc();
IndMuestra++;
};
if (contadorPWM++ == cortePWM) {
output_high(SALIDA);
}
}
void main()
{
int8 i;
float corriente;
int16 SumaMuestras;
setup_adc_ports(sAN0, VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL | ADC_TAD_MUL_0);
output_low(SALIDA);
setup_timer_2 (T2_DIV_BY_1,198,2); // 187 para 36 ciclos
output_float(PIN_B0);
output_float(PIN_B4);
set_adc_channel(0);
onda = 0;
IndMuestra=0;
contadorPWM=0;
enable_interrupts(INT_TIMER2);
enable_interrupts(INT_RDA);
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
delay_ms(50);
objetivo = 0;
cortePWM=25;
while (1) {
if (capturado) {
onda=0;
SumaMuestras=0;
if (IndMuestra==50) {
for (i=0;i<IndMuestra;i++) {
delay_ms(10);
corriente = (muestras[i]-OFFSET)*AJUSTAADC * 4.6;
SumaMuestras+=muestras[i];
muestras[i]=0;
onda = onda + corriente*corriente;
}
if (!SumaMuestras) {// eliminamos el ruido
consumo=0.0;
potencia = 0;
} else {
consumo
= sqrt(2*onda
/IndMuestra
); potencia = (int16)(consumo * 181.0);
}
printf ("%u -> %6.2fA -> %4luW. Obj %lu - CortePWM %u\n", IndMuestra
, consumo
, potencia
, objetivo
, cortePWM
); }
if ((potencia<objetivo) && (cortePWM>0))
cortePWM--;
if ((potencia>objetivo) && (cortePWM<49))
cortePWM++;
calculado=1;
}
}
}