Diseñemos entre todos un frecuencimetro DIY.

Exelente el metodo, se nota que la tenes clara con esto, esta noche lo pruebo y te cuento.

La pregunta seria, si uso un cristal de 20MHZ y un 16f873. Entonces tengo 20 MIPS? O me baso en los datos de microchip: http://www.microchip.com/wwwproducts/devices.aspx?ddocname=en010235

Donde figuran 5 MIPS

Muchas gracias nuevamente.

Dije una ganzada porque 20MIPS tiene los 24F para arriba. el mio tiene 5 MIPS.
 
Última edición:
Jajaja si los MIPS vendrían a ser Millones de instrucciones por segundo que se toma de acuerdo a la velocidad real de reloj a la que trabaja el PIC, los PIC dividen por 4 la frecuencia del cristal y con eso trabajan por lo tanto si vos tenes tu cristal de 20MHz/4 = 5MHz = 5MIPS como bien dijiste.
Hay un pequeño error disculpame ese número no está para trabajar con 10MIPS no recuerdo bien como lo dejé yo lo calibraba con el Proteus variando el numero hasta que se demorara 1 segundo por eso es algo impresiso pero daba lecturas muy buenas sin embargo, voy a estar probando usando el timer y si funciona lo subo aquí.

Saludos
 
jaja, ok esto no seria dificil de calcular si supieramos el numero de instrucciones que consume el while:


WHILE(cycles != 399810){ //con este bucle demoro 1 segundo para tomar la frecuencia
IF(t1_overflow){ t1_overflow = 0; ++OVER; } //testeo si desborda el TIMER 1
++cycles; //incremento cycles para ir contando 1 segundo
}

para que el numero sea 399810 el bucle deberia consumir algo asi como 12.5 instrucciones. dado que 12.5 * 399816 es aprox 5MI y eso nos demora un segundo.

Estoy bien con las cuentas?
 
Intenté hacer ese calculo pero fallo porque no siempre entra en los IF por lo tanto dependiendo de si entra mas o menos demora mas o menos de acuerdo con la frecuencia. Además no puede haber media instrucción (12.5). Estoy probando con el método del timer pero estoy teniendo una demora de extra de 1ms, estoy intentando saber de donde sale.

Saludos
 
Claro y es justamente lo que me falta jaja. Estuve probando con el timer y no tengo idea de por qué me está generando unos ms de más no tiene lógica no se si será el simulador tal vez, me parece que sigo con la idea anterior que a pesar de todo era bastante preciso. Éste es el código que estoy probando:

Código:
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32);
int time = 0;
set_timer0(6);

while(true){
if(t0_overflow){
   ++time;
   if(time==125){
      break;
   }
   else{
      t0_overflow = 0;
      set_timer0(6);
   }
}
}

En esta configuración el timer desborda cada 8ms por lo que si desborda 125 veces se demoró 1000ms exactamente, toda la comprobación del IF le toma unos pocos uS por lo que en teoría no debería afectar la temporización porque el timer no llega a desbordar en esos uS, lógico. Pero aún así no estoy teniendo un retardo exacto de 1000mS sino que tengo 1 o 2mS de más no se si será el simulador o algun error del programa. Todo corriendo a 4MHz para la prueba.

Saludos

Edito: no se de donde salen esos 2ms extras de acuerdo a un cálculo que hice el peor retardo que podría tener en caso de no detectar el overflow justo sería de 0.6uS que es un tiempo considerable para mi gusto, por lo que voy a continuar con el método anterior y calcular a partir de la frecuencia que mido una aproximación a la cantidad de veces que pude entrar en el IF, de este modo puedo calcular cuanto se demoró de más y restarlo al tiempo corrigiendo la frecuencia, esto daría una lectura muchos mas exacta, sin embargo un error de 300Hz a 10MHz no lo considero nada mal.
 
Última edición:
Bueno aver

**
Para tratar de saber cuantas instrucciones tiene el while hice lo siguente: arme este programita:
Código:
#include <16f873.h>
#bit t1_overflow = 0xF9E.0            //bit de desbordamiento del TIMER 1 se pone a 1 cuando se desborda el TIMER 1
INT32 FRECC;
INT32 cycles;
INT over = 0;
void main (){
setup_timer_1 (T1_EXTERNAL | T1_DIV_BY_1);       //activo el TIMER 1 
      WHILE(cycles != 399810){                        //con este bucle demoro 1 segundo para tomar la frecuencia                  
         IF(t1_overflow){ t1_overflow = 0; ++OVER; }  //testeo si desborda el TIMER 1
         ++cycles;                                    //incremento cycles para ir contando 1 segundo
      }
      setup_timer_1(T1_DISABLED);                     //desactivo el TIMER 1
FRECC = make32(OVER,get_timer1());                    //uno el valor del TIMER y los OVERFLOW en un INT32 para tener la frecuencia
}
**
Lo compile y luego abri el lst (que es el archivo que genera CCS con el paso de C a assembler ) y busque la parte del while esto es lo que encontre.


*****
Código:
.................... setup_timer_1 (T1_EXTERNAL | T1_DIV_BY_1);       //activo el TIMER 1  
*
000E:  MOVLW  87
000F:  MOVWF  10
....................       WHILE(cycles != 399810){                        //con este bucle demoro 1 segundo para tomar la frecuencia                   
0010:  MOVF   29,W
0011:  SUBLW  C2
0012:  BTFSS  03.2
0013:  GOTO   01F
0014:  MOVF   2A,W
0015:  SUBLW  19
0016:  BTFSS  03.2
0017:  GOTO   01F
0018:  MOVF   2B,W
0019:  SUBLW  06
001A:  BTFSS  03.2
001B:  GOTO   01F
001C:  MOVF   2C,F
001D:  BTFSC  03.2
001E:  GOTO   034
....................          IF(t1_overflow){ t1_overflow = 0; ++OVER; }  //testeo si desborda el TIMER 1 
001F:  BSF    03.5
0020:  BSF    03.6
0021:  BTFSS  1E.0
0022:  GOTO   029
0023:  BCF    1E.0
0024:  BCF    03.5
0025:  BCF    03.6
0026:  INCF   2D,F
0027:  BSF    03.5
0028:  BSF    03.6
....................          ++cycles;                                    //incremento cycles para ir contando 1 segundo 
0029:  MOVLW  01
002A:  BCF    03.5
002B:  BCF    03.6
002C:  ADDWF  29,F
002D:  BTFSC  03.0
002E:  INCF   2A,F
002F:  BTFSC  03.2
0030:  INCF   2B,F
0031:  BTFSC  03.2
0032:  INCF   2C,F
....................       } 
0033:  GOTO   010
*****
en total de la 0010 a 0032 tenemos 36 instrucciones pero no siempre van a ejecutar todas hay 7 (las del if que solo ejecutan cuando desvorda el bit de overflow).

Entonces podriamos decir que con 33 instricciones por ciclos vamos a estar bastante precisos??? y en ese caso el tope seria 5MI / 33 = 151515.

Estoy bien encaminado ???


Gracias a todos.
 
Pero no solo en el IF, al testear el cycles e incrementarle hace unos btfss y btfsc que son saltos condicionales en donde de acuerdo al valor de cycles actual va a saltar o no y eso varía el número de instrucciones. Leé lo que edite en el post anterior.

Saludos
 
luego te paso unos delays para pic muy exactos que calculan asta lo que tarda cada instrucion en ejucatarse,de todas maneras manipulando el osc con un trimer se logra precicion ,no ay otro modo ,pues cada pic de alguna manera son distintos y no todos trabajan iguales,es decir al menos los que yo e probado y siempre tienen algo,ya sea pot los componentes o el pic mismo,,,vaaa que se yo
PD:
yo los programo en assembler,en c todos los programas son mas largos y no se tiene el control total del pic,es decir en assembler te puedo llenar un pic increiblemente y en c nunca me alcansa para hacer lo que yo quiero que haga el condenado pic
 
Última edición:
El problema no es generar un delay eso se hace facilmente con un poco de asm, el problema es que hay que generar el delay a la vez que se testean los pulsos, en este caso el desbordamiento del timer1, ese es el mayor inconveniente en el frecuencímetro.

Saludos
 
Joya dragon veo que encontraste una forma muy piola por lo que el codig quedaria asi no??


***
Código:
#bit t1_overflow = 0xF9E.0            //bit de desbordamiento del TIMER 1 se pone a 1 cuando se desborda el TIMER 1

INT32 FRECC;
INT32 cycles;
INT over = 0;

setup_timer_0(RTCC_INTERNAL | RTCC_DIV_32);
int time = 0;
set_timer0(6);

while(true){
if(t0_overflow){ 
   ++time; 
   if(time==125){
      break;
   }
   else{
      t0_overflow = 0;
      set_timer0(6);
   }
}

setup_timer_1(T1_DISABLED);                     //desactivo el TIMER 1

FRECC = make32(OVER,get_timer1());                    //uno el valor del TIMER y los OVERFLOW en un INT32 para tener la frecuencia
***


Y 300 HZ en 10M no es nada.

ahora dragon llegaste a simular con troteus una frec de 10M como hiciste??
 
Nono me malinterpretaste ese método no sirve, con le método anterior voy a continuar mcaco. Para generar los 10M con el proteus lo tenes que dejar una o dos horas simulando para que pase 1 segundo y te muestre la frecuencia jaja pero así podes ver bien el error ya que son 10M exactos.

Saludos
 
Última edición:
haaa, jajajaja, mi imaginaba lo de proteus.
Ok bien, pero entonces como calculas el limite de ciclos del while? 399810 es para un cristal de 4MHZ? Por lo que para uno de 20 como en mi caso deberia quintuplicar este numero?
 
Código:
setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);       //activo el TIMER 1
      WHILE(cycles != 45422){                        //con este bucle demoro 1 segundo para tomar la frecuencia                  
         IF(t1_overflow){ t1_overflow = 0; ++OVER; }  //testeo si desborda el TIMER 1
         ++cycles;                                    //incremento cycles para ir contando 1 segundo
      }
      setup_timer_1(T1_DISABLED);                     //desactivo el TIMER 1

Ése es el número para 1 segundo a 4MHz (1 MIPS) eso es sin entrada de señal por lo que al insertar frecuencia variaría aumentaría 2-3uS por cada 65535 pulsos que entren, por lo que nos daría un error de 2 a 3uS por cada 65KHz a 1MIPS. Entre más frecuencia menor el error.

Saludos
 
Muchas Gracias Dragon, ahora si no tengo mas que multiplicar este tope (45422) por 5 y listo, adaptado para mis 5MIPS.


Mil gracias nuevamente, esta noche lo pruebo y les cuento.
 
Dragon, no pude hacer funcionar la simulacion en proteus, te molestaria pasarme la tuya con los sources de c que estas usando. Desde ya muchas gracias.
El problema que tengo es que el printf al LCD me muesta un numero fijo po mas que los valores del contador esten cambiendo.
 
mcaco pasame tu programa acá te paso como lo tengo yo para 20MHz pero funcionando en un 18F por alguna razón en los 16F se comporta de forma extraña el programa, no se si será la simulación. Lo tengo funcionando en un 18F4520 a 20MHz (5 MIPS)

Código:
#bit t1_overflow = 0xF9E.0

setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);       //activo el TIMER 1
      WHILE(cycles != 293913){                        //con este bucle demoro 1 segundo para tomar la frecuencia                  
         IF(t1_overflow){ t1_overflow = 0; ++OVER; }  //testeo si desborda el TIMER 1
         ++cycles;                                    //incremento cycles para ir contando 1 segundo
      }
      setup_timer_1(T1_DISABLED);                     //desactivo el TIMER 1

FRECC = make32(OVER,get_timer1());

Saludos

Por alguna razón ya no funciona, por qué? No se :S no tiene sentido. Me parece que debe estar fallando el proteus.
 
Última edición:
Dragon, realmente te agradezco el interes y la ayuda que me estas dando. Te comento que lo logre hacer funcionar ;) este es el codigo:
***
Código:
#include "frec1.h"
#define use_portb_lcd TRUE
#include <LCD.C>
#bit t1_overflow = 0xC.0            //bit de desbordamiento del TIMER 1 se pone a 1 cuando se desborda el TIMER 1

INT32 FRECC;
INT32 cycles;
INT over = 0;




void main(){

   t1_overflow = 0;
   lcd_init();   
   lcd_putc("Frecuencimetro");    
      setup_timer_1(T1_EXTERNAL | T1_DIV_BY_1);
      while (1){
      lcd_gotoxy(1,0);      
      set_timer1(0);      
       WHILE(cycles != 277535){                        //con este bucle demoro 1 segundo para tomar la frecuencia                  
         IF(t1_overflow){ t1_overflow = 0; ++OVER; }  //testeo si desborda el TIMER 1
         ++cycles;                                    //incremento cycles para ir contando 1 segundo
      }
      FRECC = make32(OVER,get_timer1());      
      if ((FRECC>1000)&& (FRECC<1000000)){
       printf(lcd_putc, "F=%3.3w KHz   ",FRECC);
       }
         else if (FRECC>1000000){
       printf(lcd_putc, "F=%3.6w MHz   ",FRECC);
         }
            else {printf(lcd_putc,"F=%Lu Hz        ",FRECC);}     
      OVER=0;
      cycles=0;
      FRECC=0;
      t1_overflow = 0;      
      }
   }
***
y frec 1.h tiene:
**
Código:
#include <16F873.h>

#FUSES NOWDT                      //Watch Dog Timer
#FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading

#use delay(clock=20000000)
**
opte por poner a 0 el timer en lugar de deshabilitar la interrupcion ya que con esta ultima no me funcionaba.


Ahora para que me funcione bien en proteus tengo que poner la señal a medir en el pin 12, pero en la vida real al 11. Eso creo que un mambo del proteus.
Otra cosa que me pasa es que el pic tarda como 60 segundos (si no mas) en arrancar a medir, no se porque sera, ya que en el dispay solo me aparece fracuencimetro, para mi debe ser algun fusible que tengo que configurar o algo por el estilo.

Edito:
El problema de la demora en arrancar era que no inicialice las variables se ve que cycles arranca con un valor aleatorio y como la condicion del while es != xxxxx hasta que no desbordaba y arrancaba a contar nuevamete no se mostraba nada.
Solucion, como siempre me decian en la facu "inicialicen las variables", jajajaja.


Saludos.
 
Última edición:
Jajajaja si incializar las variables es algo muy importante. Hasta que frecuencia lo pudiste hacer andar? El mío anda bien hasta eso de 400KHz y luego a frecuencias de por ejemplo 800KHz el timer solo se incrementa 14 veces en 1 segundo que no tiene sentido alguno así que supongo que será un error de PROTEUS.
El problema de no deshabilitar el timer al salir del bucle while es que mientras haces la función make32() para sacar la frecuencia el timer se sigue incrementando y a frecuencias mas altas ésto genera un error.

Saludos
 
Con el proteus simule hasta 1M y tengo un error de 8 hz (que para mi esta bien), luego lo monte en el protoboard y con el generador de funciones que tengo (que como maximo llega a 2M) medi 2M sin problemas. ahroa tengo que tratar de encontrar un osilador variable que de VHF alfo como de 100M hasta 600M. pero no se como armarlo, estaba pensando en probar con los modulos TWS RWS de 439 MHZ que tengo para un projecto de radiocontrol.

El error que estas teniendo con frecuencias altas te pasa en proteus o en la vida real. Porque a mi me paso lo mismo en el protoboard y el problema es que a mayor fracuencia menor es la amplitud de la misma, pasa generalmente en los generadores que nos armamos, para eso lo que hice fue amplificar la señal para los rangos altos de fracuencias. Pero en proteus siempre simule bien .

Saludos.
 
Última edición:
Atrás
Arriba