PWM y motor lavadora.

No es buena idea medir la tensión de salida de un triac sin carga: lo normal es que no conduzca. Necesitarás ponerle una lámpara incandescente o una resistencia y además de una potencia respetable, con una de 1W tampoco se cebará el triac

Enviado desde algún aparato usando algún programa, ¡o yo que se!
 
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 :cry:, 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 :rolleyes: ), 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 :oops: , 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 :apreton:
 

Adjuntos

  • Velocidad.jpg
    Velocidad.jpg
    133.6 KB · Visitas: 23
  • control motor universal.rar
    18.4 KB · Visitas: 17
  • Frecuencia erronea SE SUMAN LOS ERRORES.jpg
    Frecuencia erronea SE SUMAN LOS ERRORES.jpg
    108.8 KB · Visitas: 24
  • prueba frecuencimetro.rar
    34.2 KB · Visitas: 11
Hola meta, hace un tiempo me hiciste una pregunta y por esas cosas que no entraba seguido no te la respondi.
Trabajo con motores universales alimentados a CA y CC he utilizado el TCA785.
Arreglo maquinaria industrial, reparamos lavarropas, y los hemos utilzado en pequeños y grandes motores.
Uno de los últimos que vi era para el avance de una mesa de fresadora, donde se ponen cargas pesadas y era un motor de 10HP y con un pote común se agustaba la velocidad requerida el motor tiene tacogenerador para mantener la velocidad constante y evitar daño a la pieza y a la herramienta
 
Hola Meta, no, esa es la parte de detección de cruce por cero, viene después del trafo que voy.a usar para alimentar el pic, utilizo ese pulso que viene del optoacoplador para sincronizar el pic, el tacometro no se como usarlo, supongo que saca una senoidal y podría limitar la tensión con unos diodos clamping o algo, pero son solo suposiciones, y también caería de nuevo en el tema de medición de frecuencia para la.realimentacion.

Vos tenes algún progreso en el tema? Estuve mirando tu Blogg y no hay na nuevo al respecto.
 
Para que usaríamos un spwm? A mi parecer seria un gasto inecesario, sería como hacer un inversor.

Si meta el tacometro con el que vino mi motor también ronda por esos valores (que serían correctos si la onda es senoidal, o si dispongo es de un multietro true rms, pero usando o no el tacometro, creo que siempre se reduce a medir frecuencia y ancho de pulso, y es ahí donde tengo problemas, al cerrar el lazo.
 
ok, como que me respondo a mi mismo :LOL:, en fin , ya pude solucionar lo de medir la frecuencia, aprendi a las malas que el pic tarda de 12 a 13 ciclos, incluso mas dependiendo de donde este el pc, para atender la peticion de interrupcion, por lo que las mediciones siempre me daban mayores, con el programa que hice ahora, soy capaz de medir de 100Hz a 30kHz con una precision aceptable :D.

Código:
#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     _XTAL_FREQ  20000000
#include <xc.h>
#include <stdlib.h>
#include <pic16f877a.h>
#include "LCD_20x4_PIC16.h"

unsigned int tiempo;
unsigned int t1;
int timer=0;
char flag;
char hayDato;
//uint8_t STATUS_TEMP;
//uint8_t W_TEMP;
//uint8_t PCLATH_TEMP;

void interrupt global(){
    
    if (PIR1bits.CCP1IF){
        if (flag!=0){
            PORTCbits.RC0=0;
            TMR1ON=0;
            tiempo=CCPR1-t1;
            //CCPR1=0;
            TMR1=0;
            flag=0;                 //segundo flanco de subida
            //PIE1bits.CCP1IE=0;
            hayDato=1;              //se guardo el periodo
            PIR1bits.CCP1IF=0;
        }else {
            PORTCbits.RC0=1;
            t1=CCPR1;
            flag=1;                 // se detecto flanco de subida
            PIR1bits.CCP1IF=0;      
        }
    }
}

void configurarPuertos();
void configurarCaptura();

void main(void) {
    LCDInit();
    configurarPuertos();
    configurarCaptura();
    flag=0;
    tiempo=0;
    hayDato=0;
    
    while(1){
        if (hayDato){
            //GIE=0;
            PIE1bits.CCP1IE=0;
            tiempo=(unsigned int)(5000000/tiempo);
            LCD_String("Frecuencia: ");
            LCD_escribeInt(tiempo);
            hayDato=0;
            //LCD_String("             ");
            TMR1ON=1;
            __delay_ms(300);
            LCD_Clr();
            PIE1bits.CCP1IE=1;
            //GIE=1;
        }
       
    }

    return;
}

void configurarPuertos(){
    ADCON1=0B00000101;
    TRISCbits.TRISC0=0;
}

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
    PIE1bits.TMR1IE=0;
    INTCONbits.PEIE=1;
    TMR1=0;
    T1CONbits.TMR1ON=1;
    INTCONbits.GIE=1;           //habilita interrupciones globales
    
}

el truco estaba en hacer correr el timer 1 al inicio, asi cuando se produzca la primera interrupcion por ccp1 guardamos el valor de ccpr1, no paramos el mismo y dejamos que corrra hasta la 2da interrupcion y guardamos el valor de ccpr1 de nuevo asi, solo nos queda restar el ultimo valor con el primero para obtener el periodo. Cuando junte este con el control de velocidad subire ctos, programa, y alguna que otra foto.(y)
 

Adjuntos

  • Sin título.jpg
    Sin título.jpg
    134.7 KB · Visitas: 28
¿Como se llama este modulo? gracias
No lo se, solo que controla la velocidad del motor, es decir, que depende del peso entre ropa y agua, mantiene la velocidad del motor en la misma a pesar que la placa detecta variaciones al girar el tambor, lo que hace el integrado es que si detecta lentitud acelera y su es muy rápido desacelera, lo mismo pasaba con los motores cabezales de los vídeos VHS de antes, esto se le conocía como Sincronización de fase (PLL).
 
Meta , vos que andabas desarrollando un control de motor de lavadora , sobre la inversión de giro , que generalmente se hace con relé , yo te había comentado de un circuito con semiconductores , aqui lo encontré :


DirectionSpeedSeriesMotor.png


Si bien es un circuito medio antiguo que emplea transformadores de disparo , se pueden reemplazar por Moc's para manejar directamente desde un Pic

Saludos !
 
Hola:

Gracias DOSMETROS. El que uso y me va bien, es este:
Esquema%2BLavadora.gif


Ver zoom
.

La velocidad se consigue con un potenciómetro digital como este DS1804-100.
Hay que usar por lo menos 4 en serie de ese tipo para conseguir los 470 KΩ.


Lo que quiero saber en estos momentos, es controlar el tacómetro analógido de los motores de lavadoras.

0.42.46.91-0_1.png


Tengo un motor que si alcanza su velocidad máxima, llega a los 98 VAC. El microcontrolador debe ser capaz de detectarlo. Se puede hacer pruebas rápidas con Arduino, es decir, de alguna manera hacer un circuito de electrónica para que me lee de 0 a 1023 de entrada analógica en el Arduino. Con eso creo que ya podré usar el tacómetro. Lo queno se su electrónica para capturar los 5V que se conecta a Arduino, de 0 VDC a 5 VDC, ya que suelta de 0 a 98 VAC.

Hace tiempo en www.youtube.com vi unalavadora con un tacómetro digital y más nunca lo he vuelto a encontrar.

Un truco que se me ocurre es poner uncuenta vueltas de una bicicleta, conectarlo a Arduino, también debe vale.

1.JPG


Saludos.
 
Última edición:
No te compliques con el tacómetro de bicicleta :no:

Ese tacómetro es un elemental "alternador" monofásico , así que deberías leerle la frecuencia.

Los dos cables salen de la bobina construida sobre un nucleo de varios polos y dentro gira ese imán negro también de varios polos.

Probá de conectarle un tester de aguja en miliampers y girarlo despacio , debería dar varios agujazos por rpm
 
Yo había pensado en dos zeners antiparalelo o dos leds antiparalelo o 3 1N4148 con otros 3 1N4148 en antiparalelo , más alguna resistencia serie limitadora :oops:

A bajas vueltas se vería el led parapadear :p :LOL:
 
Atrás
Arriba