buenas, hace un tiempo estoy con el tema del control de velocidad de motores universales, y lo que logre hasta ahora fue "controlar la velocidad" sin realimentacion, por lo que a cualquier variacion de carga etc etc, la velocidad no es la fijada, estos motores como ya comentaron por aca, traen una bobina tacometrica (los de lavadoras al menos), no le encontre la vuelta para utilizar este sensor, ya que me varia en frecuencia y en amplitud la señal de salida, a parte no cuento ni con osciloscopio
, asi que me arme un sensor por efecto hall, usando los mismos imanes que traia el eje del motor, (midiendo con el sensor hall me di cuenta que tiene 8 polos), en fin, ahora mi dilema esta en la programacion (creo
), tendria que medir la frecuencia de la señal que me entrega el sensor de efecto hall, estuve experimentando con distintos metodos para medir frecuencia con pic (uso el 16f877a corriendo a 20Mhz), por ccp1, e interrupcion por cambio de estado en rb4, ninguno de estos metodos me dieron resultado
, no veo como manejar bien los recursos del pic, ya que para el control de velocidad estoy usando el TMR0 e interrupciones por Rb0 (control por amngulo de disparo creo que se llama), alguien puede ILUMINARME? de que forma deberia de encarar esto para cerrar el lazo de control?
adjunto imagenes y simulacion de proteus, ademas del codigo, la parte de regulacion y contador de frecuencia las tengo separadas aun ya que no consigo medir la frecuencia de manera eficiente y mostrarlo en el lcd a la vez.
Código:
// CODIGO DEL CONTROL DE VELOCIDAD MEDIANTE PULSADORES
#define _XTAL_FREQ 20000000 // cristal (XT) de 20MHz
#include <xc.h>
#include <stdio.h>
#include <pic16f877a.h>
#include "LCD_20x4_PIC16.h"
// CONFIG
#pragma config FOSC = HS // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled)
#pragma config BOREN = ON // Brown-out Reset Enable bit (BOR enabled)
#pragma config LVP = OFF // Low-Voltage (Single-Supply) In-Circuit Serial Programming Enable bit (RB3 is digital I/O, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off)
#pragma config WRT = OFF // Flash Program Memory Write Enable bits (Write protection off; all program memory may be written to by EECON control)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
#define interrupcion PORTBbits.RB0
#define aumentarVelocidad PORTBbits.RB1
#define disminuirVelocidad PORTBbits.RB2
#define btnOnOff PORTBbits.RB3
#define salidaMotor PORTBbits.RB4
// Variables Globales
char reg_vel=97;
char cargaTimer0=0;
bit isOn=0;
// Cabecera de Funciones
void configTimer0();
void inicioPuertos();
void inteConfig();
// Funcion de Interrupcion
void interrupt global(){
if (INTCONbits.INTF){ // ¿se produjo una interrupcion por RB0INT?
salidaMotor=0;
TMR0=cargaTimer0;
INTCONbits.INTF=0; //Limpia flag de interrupcion RB0INT
}
if (INTCONbits.TMR0IF){ // ¿se produjo una interrupcion por TMR0?
salidaMotor=1;
INTCONbits.TMR0IF=0; //Limpia flag de interrupcion por desbordamiento del TMR0
}
}
void main(void) {
inicioPuertos();
configTimer0();
while(1){
if (!btnOnOff){
__delay_ms(20);
if (!btnOnOff){
while (!btnOnOff){}
__delay_ms(20);
if (isOn){
INTCONbits.GIE=0; //deshabilita las interrupciones globales
isOn=0;
salidaMotor=0;
}else {
// rutina de cruce por cero y angulo de disparo
cargaTimer0=256-2*reg_vel;
inteConfig();
}
}
}
/******************************************************************************
* Para aumentar y disminuir velocidad se tiene en cuenta solo T/2 de la señal*
* senoidal de linea, ya que ésta se rectifica antes de RB0 y es simetrica, se*
* dividió éste semiperiodo en 100 pasos, lo que da un total de 100us por *
* paso, asi la formula que se aplico para hallar el valor de carga del timer *
* fue la sgte: TMR0=256-(reg_vel/10000)/(256*200x10-9), de esta forma reg_vel*
* queda multiplicado por el factor 1/10000, y solo queda ir aumentando y *
* disminuyendo esta variable para obtener los pasos de 100us. *
******************************************************************************/
if (!aumentarVelocidad){ //aumentar velocidad
__delay_ms(40);
if (!aumentarVelocidad){
while (!aumentarVelocidad){
__delay_ms(100);
if (reg_vel>1){
reg_vel--;
cargaTimer0=256-2*reg_vel;
}
}
}
}
if (!disminuirVelocidad){ //disminuir velocidad
__delay_ms(40);
if (!disminuirVelocidad){
while (!disminuirVelocidad) {
__delay_ms(100);
if (reg_vel<97){
reg_vel++;
cargaTimer0=256-2*reg_vel;
}
}
}
}
}
}
void configTimer0(){
OPTION_REGbits.PS0=1;
OPTION_REGbits.PS1=1;
OPTION_REGbits.PS2=1;
OPTION_REGbits.PSA=0; //prescaler de 1/256 al timer 0
OPTION_REGbits.T0CS=0; //Modo temporizador
}
void inicioPuertos(){
TRISB=0b00001111;
OPTION_REGbits.nRBPU=0; //Pull up del puerto B activadas
ADCON1=0B00000101; //todos los pines e/s digitales
PORTB=0;
TRISC=0;
PORTC=0;
}
void inteConfig(){
TMR0=0;
INTCON=0;
OPTION_REGbits.INTEDG=1; //Interrupcion con flancos ascendentes
INTCONbits.INTE=1; //habilita RB0/INT
INTCONbits.TMR0IE=1; //Interrupcion por desbordamiento de TMR0
INTCONbits.GIE=1; // interrupciones globales
INTCONbits.PEIE=1; // interrupciones de perifericos
}
Código:
//CODIGO DEL "¿FRECUENCIMETRO?"
#define _XTAL_FREQ 20000000
#include <xc.h>
#include <stdlib.h>
#include <pic16f877a.h>
#include "LCD_20x4_PIC16.h"
int tiempo=0;
int timer=0;
char flag=0;
void interrupt global(){
if (PIR1bits.CCP1IF){
if (flag!=0){
tiempo=CCPR1;
CCPR1=0;
TMR1H=0;
TMR1L=0;
PIR1bits.CCP1IF=0;
}else {
flag=1;
TMR1H=TMR1L=0;
CCPR1=0;
PIR1bits.CCP1IF=0; //se desecha la primera medicion
}
}
}
void configurarPuertos();
void configurarCaptura();
void main(void) {
LCDInit();
configurarPuertos();
configurarCaptura();
while(1){
LCD_String("Frecuencia: ");
GIE=flag=0;
tiempo=(int)(5000000/tiempo);
LCD_escribeInt(tiempo);
// LCD_String(" ");
__delay_ms(1000);
LCD_Clr();
GIE=1;
}
return;
}
void configurarPuertos(){
ADCON1=0B00000101;
}
void configurarCaptura(){
TRISCbits.TRISC2=1;
T1CON=0b00000000;
CCP1CON=0b00000101; //Capture mode, every rising edge
PIE1bits.CCP1IE=1; //habilita interrupciones por CCP1
PIR1bits.CCP1IF=0; //coloca a cero bandera de interrupcion por CCP1
INTCONbits.PEIE=1;
TMR1H=0;
TMR1L=0;
INTCONbits.GIE=1; //habilita interrupciones globales
T1CONbits.TMR1ON=1;
}
Gracias de ante mano