Foros de Electrónica

Comunidad de discusión sobre Automatización, Electrónica industrial, Microcontroladores y electrónica digital, Robótica, Domótica, Telemática, Tecnologías móviles, y muchos temas más.




Usando PWM - mini tutorial


       



#1  Usando PWM - mini tutorial
Marcelo
Colaborador
Registrado: 27 Jul 2005
Mensajes: 362
Ubicación: Venezuela
citar
Usando PWM (Pulse with Modulation).

Casi todos los que lean este post, habrán hecho en algún momento, un proyecto para prender un led o accionar un motor mediante un microcontrolador o por medio de cualquier otro circuito.

Pero que sucede si queremos controlar la luminosidad del led que estamos encenciendo o deseamos regular la velocidad del motor?.

Pudiéramos pensar que si prendemos y apagamos la señal de alimentación de la carga (led o motor) lo suficientemente rápido como para que el parpadeo no se note, podríamos “simular” la variación de luminosidad de un led o el cambio en la velocidad del motor:



Esto funciona siempre y cuando no hagamos este “switcheo” más allá de 30 veces por segundo. A partir de allí. El "blink" del led se empezará a notar y El ojo humano captará ese parpadeo. En el caso de un motor, éste se moverá en una forma pulsante.

La idea general del PWM es esta, solo que soluciona este problema de tiempo.

La forma de lograrlo es dejar el pulso fijo en el tiempo y variar su amplitud.

Supongamos que logramos ajustar el período T a su valor óptimo mínimo en el cual un led no parpadee y un motor no salte.

Esto es aproximadamente a una frecuencia de 30 pulsos o ciclos por segundos para el caso de un led. En el caso del motor habrá que determinarlo empíricamente ya que depende de sus características eléctricas y mecánicas,

Volviendo al led, quiere decir que trabajamos con un período de tiempo de:

f= 30 cps ==> T=1/f ==> T=1/30 ==> T= 0.0333 s ==> T=33.3 ms



El esquema anterior representa un pulso con un “duty cycle” o ciclo de servicio igual al 50% es decir, la mitad del período está a 0 y la otra mitad está a Vcc.

Lo que se hace con PWM es variar dinámicamente el “duty cycle” de manera que el tiempo de alta disminuya o aumente y en proporción inversa, el de baja aumente o disminuya dependiendo de si queremos una led más atenuado o más brillante, o un motor más lento o más rápido, respectivamente.



LED MENOS ILUMINADO



LED MAS ILUMINADO

Recuerden que este período se repite constantemente en el tiempo:



De esta forma tenemos 2 formulitas muy sencillas para el cálculo de los tiempos:

1) Si variamos, fijamos o controlamos t alta entonces: t baja= T- t alta
2) Si variamos, fijamos o controlamos t baja entonces: t alta= T- t baja
Y el ciclo de servicio o “Duty Cycle” lo calculamos así:

DT= t alta / (t alta + t baja)

En una próxima entrega codificaremos esto en Assembler para PIC.

Saludos,
Marcelo.


Ultima edición por Marcelo el Dom Sep 11, 2005 12:40 am, editado 1 vez

#2  Manejando los tiempos (Parte2 de PWM Mini-Tutorial)
Marcelo
Colaborador
Registrado: 27 Jul 2005
Mensajes: 362
Ubicación: Venezuela
citar
1) Manejo de los tiempos

Ahora que sabemos como es la teoría básica del PWM, vamos a programarlo en un PIC 16F84A. Para simplificar un poco la explicación y no hacerla tan larga, supondremos que se poseen conocimientos básicos de cómo funciona un PIC.

La forma de aplicación con la que podemos usar las rutinas PWM son básicamente 2:

1) “Stand Alone” o programas que corren sin instrucciones de comando externos. Estos se utilizan normalmente en sistemas autómata, los cuales reaccionan a estímulos externos como por ejemplo un robot que choca contra un obstáculo o el seguimiento por parte del robot de una línea guía en el suelo, pero el programa en si se autocontrola y toma sus propias decisiones (bueno, las que le programamos).

2) Modo Maestro - Esclavo, que utiliza un controlador externo que le dice a un aparato que es lo que debe hacer. Por ejemplo, un circuito que controla un motor que a la vez es comandado desde un computador bien sea por el puerto serial, paralelo, usb, infrarrojo o cualquier otro. En estos casos, el computador “conversa” con el circuito, decide que se debe hacer e instruye al esclavo para que lo haga.

Para empezar recordemos que PWM en realidad controla TIEMPO. Por consiguiente es necesario tener un conocimiento relativamente alto de cómo se manejan los tiempos en un PIC 16F84A.
En otros integrados de esa familia de semiconductores, ya existen librerías programadas para manejar PWM.
Este no es el caso del 16x84, por lo que el control de tiempo hay que hacerlo “a mano”.

La frecuencia de trabajo de un microcontrolador es un parámetro primordial a la hora de determinar a que velocidad se ejecutan las instrucciones dentro de él.
En estos PICs cada instrucción consume 4 ciclos de reloj que llamaremos Q1, Q2, Q3 y Q4.

1) Con el pulso Q1 se incrementa el “contador de programa”.
2) Con los pulsos Q2 y Q3 se decodifica la instrucción y se ejecuta
3) Durante Q4 se busca el código que corresponde a la próxima instrucción en la memoria del PIC y se carga en el “registro de instrucciones”.



Las instrucciones que generan un “salto” se llevan dos ciclos de instrucciones. Fíjense que pareciera que no cuadra lo de los pulsos y esto se debe a que las dos fases que comprenden las instrucciones se realizan en paralelo y en realidad cada instrucción toma 2 ciclos en ejecutarse. Esto se denomina técnica de segmentación y se le llama “pipeline”; ya la deben de haber escuchado más de una vez.



Las instrucciones de salto llevan 2 ciclos porque no se conoce la instrucción que sigue luego de cada salto, por consiguiente el ciclo en el cual el procesador debería buscar la próxima instrucción secuencial, es sustituido por un ciclo sin operación. (vean la figura anterior)

Si la instrucción es de salto condicional es decir, salta si se cumple una condición como decfss o decfsc por ejemplo, la instrucción puede durar 1 ciclo, si no se cumple la condición o 2 ciclos si la condición de salto se cumple. Para el cálculo tomamos 2 ciclos que es el peor de los casos.

La frecuencia fundamental de operación del PIC viene dada por el oscilador que utilizamos para su configuración.

Así por ejemplo, un programa que tiene 500 instrucciones de las cuales 120 son de saltos y se configura con una frecuencia típica de 4 Mhz, tardará en ejecutarse el siguiente tiempo (recuerden que el 16F84A se puede manejar hasta con 20Mhz):

Tiempo del Ciclo de reloj (Qi) = 1/f = 1/4.000.000 = 250 ns (nano segundo)
Tiempo del Ciclo de Instrucción = 4 veces Ciclo de reloj = 4 * 250ns = 1.000 ns = 1 us (micro segundo)

Tiempo del programa = Instrucciones de 1 ciclo * Ciclo de Instrucción + Instrucciones de 2 ciclos * 2 veces Ciclo de Instrucción

Tiempo del programa = (500 – 120) * 1 + 120 * 2 = 620 us

Nuestro programa tardará en ejecutarse 620 micro segundos.

En la próxima entrega vamos a entrar en la lógica que usaremos para la rutina y su codificación.

Saludos.
Marcelo.


Ultima edición por Marcelo el Dom Sep 11, 2005 12:42 am, editado 1 vez

#3  La lógica en la programación
Marcelo
Colaborador
Registrado: 27 Jul 2005
Mensajes: 362
Ubicación: Venezuela
citar
La lógica en la programación del PWM

Muchas son las formas, algoritmos e ideas que podemos aplicar para programar nuestra rutina y este no es un caso particular.

A cada uno de nosotros se nos ocurrirán formas más o menos complicada, más o menos largas de codificar y más o menos eficientes para escribir nuestro programa. pero todas igual de válidas.

Como la idea de este tutorial no es demostrar nada sino retransmitir lo poco que se sabe a fin de que se mejore el conocimiento medio de todos nosotros, lo que trataremos de hacer es reducir al máximo la complejidad sin hacerle mucho caso a la eficiencia, a fin de que cualquiera que lo lea lo pueda entender, aplicar y mejorar.
A ustedes les dejo el perfeccionamiento del firmware del PIC.

Tampoco consideraremos cual debería ser el tiempo óptimo del pulso, sino que ustilizaremos un tiempo bastante corto en el cual el motor no salte y además tenga tiempo suficiente para responder a la solicitud de movimiento.

De igual manera y a fin de simplificar aun más las cosas, trataremos de no utilizar en la rutina de PWM interrupciones, watch dog ni TMR0.

Antes de empezar a diseñar la rutina deberemos establecer como vamos a conectar nuestro PIC con el mundo exterior y de que manera lo vamos a controlar.

Como circuito de práctica y lineamientos generales haremos que nuestro PIC cumpla con estas condiciones:

1 ) Controlaremos un motor DC
2 ) Usaremos una frecuencia de 4 Mhz
3 ) Usaremos la puerta B
4 ) Pin de control del motor RB4 (SALIDA)
5 ) Pin de control del motor RB5 (SALIDA)
6 ) El pin RB6 indicará con un LED uno de los dos sentidos de giro (SALIDA)
7 ) El pin RB7 indicará con un LED el otro sentido de giro (SALIDA)
8 ) Haremos que el control sea externo es decir, desde un computador. Para esto usaremos los siguientes pines (ojo, porque a veces esto confunde un poco):
a. RB1: Recepción DESDE el Puerto Serial. (Deberá conectarse a la pata Tx del serial – pin 2 DB9). Este pin como ENTRADA.
b. RB2: Transmisión HACIA el Puerto Serial. (Debera conectarse a la pata Rx del serial – pin 3 DB9). Este pin como SALIDA.
9) RB0/INT la dejamos en standby a ver si la usamos luego para indicar o producir algún evento.

Lógica de la rutina, el algoritmo:

Supongamos que tenemos una palabra de 8 bits para indicar el Duty Cycle de nuestros pulsos es decir, un byte. Por consiguiente tendríamos 2^8 posibles valores = 256 (desde 0 hasta 255)

Lo que vamos a hacer es normalizar a 1 nuestra temporización. Esto quiere decir que si consideramos que 1 es el tiempo total de un pulso completo, podemos afirmar que:

TALTA= CICLO/256
TBAJA=1-TALTA

Donde CICLO varía desde 0 hasta 255. (El 256 del divisor indica los 256 posibles valores)

CICLO es una variable que usaremos al enviar el valor para la determinación del tiempo de alta.

La idea es contar desde 0 hasta CICLO manteniendo la alimentación del motor encendida y el tiempo restante, hasta llegar a 256 se colocará la salida en 0.

Usemos el acumulador del PIC (W) como contador, teniendo entonces que:

W=W + CICLO con CICLO = 0, 1, 2, 3, …. 255 y conteniendo el valor deseado por nosotros.

Habíamos dicho que no usaríamos interrupciones ni desbordes de temporizadores, pero necesitamos una forma de saber cuando el contador llegó a 256 o mejor dicho, cuando terminó de dar una vuelta completa.

Una forma de hacerlo es utilizando la bandera de CARRY (bit de acarreo) del registro de ESTADO del PIC.

Con esto en mente:

1) Si CICLO vale 0, nunca ocurrirá un carry y la salida siempre estará a 0.
2) Si CICLO vale 1 el carry se activará cuando el acumulador W, luego de haber empezado a contar desde 0, llegue a 0xFF y pase de nuevo a 0x00 (de 255 a 0). Entonces la salida estará alimentando al motor la 1/256ava parte del tiempo total.
3) Si CICLO vale 2, W hará un rollover (giro sobre si mismo o vuelta) dos veces es decir, ocurrirán 2 carries y el tiempo de alimentación será la 2/256ava parte del tiempo total.
4) Etc. Etc.

Vemos que el carry ocurre siempre excepto cuando CICLO vale 0 en donde el motor está apagado. Si se quiere el motor “siempre” excitado entonces enviaremos CICLO=255, en donde el tiempo de alta será 255/256.

No por casualidad se usaron los valores 0 a 255 que corresponden a la codificación de caracteres ASCII. Esto va a servirnos de mucho cuando programemos nuestro software principal en el PC pues deberemos mandar códigos ASCII a nuestra interfaz.

Como debemos comunicarnos con nuestro motor, utilizaremos unos número de códigos que reservaremos del rango 0 a 255.
Dependiendo de como desarrollemos nuestro "firmware", habrá que tener cuidado de no usar esos caracteres específicos para definir un valor de velocidad para el PWM desde nuestro programa de computador, pues se utilizarán para conocer el estado de nuestro circuito y enviar comandos y recibir respuestas.
En nuestro caso, si podremos usar los 256 valores posible porque las comparaciones de comunicación las haremos antes de enviar el caracter de velocidad.

Por ejemplo:
1) Envio del carácter 100 desde el computador: Solicita estado de la conexión.
2) Envío de carácter 102 para dirección de giro 1
3) Envío de carácter 104 para dirección de giro 1
4) El PIC responderá: con 100, indicando que la interfaz está conectada y comunicada.
5) El PIC enviará el código 104 para indicar que se está moviendo en cada bucle de 256.
6) El PIC enviará el código 102 para indicar que el motor paró su movimiento


En la próxima, el listado del programa.


Ultima edición por Marcelo el Dom Sep 11, 2005 12:42 am, editado 4 veces

#4  El programa para el PIC
Marcelo
Colaborador
Registrado: 27 Jul 2005
Mensajes: 362
Ubicación: Venezuela
citar
Aca estamos de vuelta.

Ahora que ya tuve tiempo para hacer el circuito de prueba y terminar el programa, se los voy a pasar.

Si lo quieren bajar hagan click en estos links (botón derecho del mouse y luego "guardar destino como"). Recuerden bajar también el Rs232low.inc que lo van a necesitar cuando quieran hacer un cambio en el programa y tengan que reensamblarlo.

MyPWM - assembler : http://www.forosdeelectronica.com/upload/MarceloFiles/PWM/MiPWM.asm

MyPWM - código HEX : http://www.forosdeelectronica.com/upload/MarceloFiles/PWM/MiPWM-HEX.zip

rs232low.inc : http://www.forosdeelectronica.com/upload/MarceloFiles/PWM/rs232low.zip

Palabra de configuración para el PIC16F84A:
OSCILADOR: XT
WDT: Off
Power Up Timer: Off (Si usan 16C84 ponganlo en On)
CodeProtect: Off

Aqui les voy a dar una breve explicación de lo que hace el programa pues creo que el código está lo suficientemente comentado como para que se entienda paso a paso.

Recuerden que la intención de este tutorial es aprender así, paso a paso; por lo que muchísimas cosas en el programa se pueden realizar con menos instrucciones de las que tienen e inclusive omitir algunas.

También tiene como idea, alentar a aquellos que le tienen algo de miedo al assembler y hacerles ver que es relativamente fácil programarlo.

La forma en que se estructura la codificación está hecha de la manera más secuencial posible para que podamos entenderlo a cabalidad.

En resumen el programa hace lo siguiente:

1) Cuando desde el computador enviamos el caracter "d" (ASCII Decimal 100 - Hexadecimal 64), le preguntamos a nuestro circuito: ¿TIENES COMUNICACIÓN?, a lo que la interfaz (es decir, el PIC) reaccionará enviando un 100 al computador como respuesta. Esto sirve para poder comprobar que la interfaz está interconectada al PC. Si no tienen respuesta es que hay algún problema.

2) Cuando queremos decirle a la interfaz que mueva el motor en la dirección A, enviaremos el caracter "f" (ASCII Decimal 102 - Hexadecimal 66). La interfáz quedará en standby esperando que le enviemos el valor de la velocidad que deseamos. En este punto debemos enviar cualquier caracter desde 0 a 255, siendo 0=Parado y 255=Full Velocidad. Cuando enviamos el valor de velocidad, la interfaz mandará el caracter "h" (ASCII Decimal 104 - Hexadecimal 68) para decirle al computador "ME ESTOY MOVIENDO" y cuando termine el ciclo de movimiento la interfaz mandará el caracter "f" (ASCII Decimal 102 - Hexadecimal 66) para informar "ME DETUVE".

3) Si queremos mover el motor en el sentido contrario (Dirección B), deberemos enviarle a la interfaz el caracter "h" (ASCII Decimal 104 - Hexadecimal 68) y las respuestas serán iguales a las explicada en el punto 2.

Si esto les pareció complicado, monten el circuito en un protoboard y utilicen un programa terminal como el Comm Port Toolkit o cualquier otro (inclusive el Hyperterminal de Windows) para enviar los carateres y ver como responde.

Este envio y recepción de caracteres le permitirá saber que está haciendo el motor y actuar en consecuencia desde el programa de su PC.

Este tipo de programas y controladoras (me refiero al circuito) son muy comunes en robótica y control asistido por computadora, por lo que es muy interesante ponerse a experimentar y realizar infinidades de cosas con ellas.

El código va a quedar un poco descuadrado en la pantalla por lo de cortar y pegar, pero sigue siendo bastante legible.

Para la próxima... El circuitito.

Bueno, aqui les va... y Saludosl
Código: Seleccionar todo

;++++++++++++ PROGRAMA PARA CONTROLAR UN MOTOR DC
;++++++++++++ INCLUYE RUTINA PWM
;++++++++++++ INCLUYE RUTINA DE COMUNICACIÓN SERIAL
;++++++++++++ Marcelo Saavedra - 06/09/2005

      List   p=16F84A;Tipo de procesador
      include   "P16F84A.INC"   ;Definiciones de registros internos

;
;Declaración de Variables.
;
CICLO      equ   0x21      ;Duración del tiempo de servicio
RECIBIDO   equ   0x22      ;Guarda el carácter recibido por el serial
M1      equ   0x23      ;Bandera del motor. Con un solo pin podemos controlar.
BANDERA   equ   0x24      ;Contador de bucle
NVECES      equ   0x25      ;Variable de control de bucle para reenviar a PWM
Rs232_var   equ   0x0C      ;Inicio de las variables para rutinas RS232low.inc para comunicación

;
;Parámetros de la rutina de comunicación
;
CLKIN   equ   .4000000   ;Frecuencia
BAUDIOS   equ   .9600      ;Velocidad de comunicación
T_MODO   equ   1      ;Transmite primero bit LSB
R_MODO   equ   1      ;Recibir primero bit LSB
T_Nbit   equ   8         ;Transmite caracteres de 8 bits
R_Nbit   equ   8         ;Recibe caracteres de 8 bits
Sbit   equ   1         ;Transmite 2 bits de stop
               
      org   0   
      goto   INICIO
      org 4         ;La Interrupción comienza aquí.
      nop      
               
   include   "RS232LOW.INC"   ;Incluir rutinas de comunicación
;
;********Rutina de Inicio
;
INICIO
                  ;Desabilita e impide todas las interrupciones
         bcf   INTCON,GIE   ;GIE=0
         bcf   INTCON,EEIE   ;EEIE=0
         bcf   INTCON,T0IE   ;T0IE=0
         bcf   INTCON,INTE   ;INTE=0
         bcf   INTCON,RBIE   ;RBIE=0
         bcf   INTCON,T0IF   ;T0IF=0
         bcf   INTCON,INTF   ;INTF=0
;
;********Configuración de los BYTES de STATUS y OPTION
   bsf   STATUS,RP0         ;Pone el RP0 a 1 - Seleccionando BANCO 1 de datos
   movlw   b'11010000'         ;Coloca el Byte de OPTION en W
                  ;- Prescaler en 000
                  ;- Prescaler al TMR0 - 0
                  ;- Incremento TMR0 con flanco ascendente - 1
                  ;- Pulsos por Fosc/4 - 0
                  ;- Flanco ascendente para la interrupción - 1
                  ;- Pull-up desactivadas - 1
   movwf   OPTION_REG      ;Coloca el valor anterior de W en el literal OPTION_REG

   movlw   b'00000011'         ;Establece en W, el Byte de configuración para PORTB
                  ;RB0=Sensor (ENTRADA) - 1
                  ;RB1= Recibir desde TX del serial(ENTRADA) – 1
                  ;RB2= Enviar hacia RX del serial  (SALIDA)  - 0
                  ;RB3=Sin conexión (SALIDA) - 0
                  ;RB4=MOTOR 1 (SALIDA) - 0
                  ;RB5= MOTOR 2 (SALIDA) - 0
                  ;RB6= LED para indicar sentido 1 (SALIDA) - 0
                  ;RB7= LED para indicar sentido 2 (SALIDA) - 0
   movwf   TRISB            ;Se asignan los puertos RBi salvando W en TRISB
   bcf   STATUS,RP0         ;Pone el RP0 a 0 para regresar al BANCO 0 de datos.
;
;********Inicialización pines de Rx y Tx
      bsf   Txd_pin      ;Línea de transmisión a "1" en RS232Low.Inc
      bsf   Rxd_pin      ;Línea de recepción a "1" en RS232Low.Inc
;
;********Motor parado
      bcf   M1,0      ;Inicializamos la bandera del motor a 0 (Solo usamos el bit 0)
      movlw   0xAA      ;Número de veces que vamos a reenviar a PWM - Esto es para Compensación
               ;y pueden ajustarlo para que el encendido total sea mayor o menor (de 0 a ff)
      movwf   NVECES      ;Cargamos la variable.
;
;********Rutina de recepción de datos
RECEPCION
;
;*************Apagamos todo
      bcf   PORTB,4      ;Apagamos pin RB4 de PORTB
      bcf   PORTB,5      ;Apagamos pin RB5 de PORTB   
      bcf   PORTB,6      ;Apagamos el led 1
      bcf   PORTB,7      ;Apagamos el led 2
;
;*************Transmitimos "Motor Parado"
      movlw   0x66      ;Coloca 102 (0x66) en W – Señal de motor parado
      movwf   Txdreg      ;Carga W en Txdreg para transmitirlo
      call   TxD      ;y lo transmite indicando que los motores están parados.
;
;*************Escuchamos el puerto serial
ESCUCHAR
      call   RxD      ;Llama la rutina de recepción en RS232Low.Inc
      movf   Rxdreg,W   ;Coloca el caracter recibido por Rxdreg en W
      movwf   RECIBIDO   ;y lo salva en RECIBIDO
;
;*********Rutina de comparación del caracter recibido
                     ;Empieza la comparación.
      movlw   0x66      ;Coloca 102 (h66) en W – Es el sentido de giro 1?
      subwf   RECIBIDO,0   ;Resta W (h66) del caracter recibido y el resultado lo almacena en W
      btfss   STATUS,Z   ;Está a 1 el bit ZERO de STATUS? (Si está a 1 la resta anterior es 0)
      goto   SALTAR1   ;No, no está a 1, vete a SALTAR1
      bsf   M1,0      ;Si, Z está a 1, entonces pon M1 a 1
      goto   MOVIMIENTO   ;y luego ve a MOVIMIENTO para seguir con el programa.
SALTAR1            
      movlw   0x68      ;Coloca 104 (h68) en W – Es el sentido de giro 2?
      subwf   RECIBIDO,0   ;Resta W (h68) del caracter recibido y el resultado lo almacena en W
      btfss   STATUS,Z   ;Está a 1 el bit ZERO de STATUS? (Si está a 1 la resta anterior es 0)
      goto   SALTAR2   ;No, no está a 1, vete a SALTAR2
      bcf   M1,0      ;Si, Z está a 1, entonces pon M1 a 0
      goto    MOVIMIENTO   ;y luego ve a MOVIMIENTO para seguir con el programa.
SALTAR2
      movlw   0x64      ;Coloca 100 (h64) en W – Me preguntan si hay conexión?
      subwf   RECIBIDO,0   ;Resta W (h64) del caracter recibido y el resultado lo almacena en W
      btfss   STATUS,Z   ;Está a 1 el bit ZERO de STATUS? (Si está a 1 la resta anterior es 0)
      goto   ESCUCHAR   ;No,ZERO esta a 0 entonces se va a buscar otro BYTE VÁLIDO.
;
;*********Rutina de enviar confirmación de LINK de la interfaz
               ;Si llega aquí se recibió el 100, solicitando la confirmación de LINK
      movlw   0x64      ;y comienza el ECO del caracter 100 (0x64) para decir SI, HAY LINK.
               ;Carga 100 en W
      movwf   Txdreg      ;Carga W en Txdreg para transmitirlo
      call   TxD      ;lo transmite.
      goto   ESCUCHAR   ;y regresa a RECEPCION a esperar otro carácter.
;
;*********Rutina de MOVIMIENTO / PARO
MOVIMIENTO
               ;ESPERAMOS EL VALOR DE CICLO. Ya tenemos el sentido de giro.
      call   RxD      ;Llama la rutina de recepción en RS232Low.Inc
      movf   Rxdreg,W   ;Coloca el caracter recibido por Rxdreg en W
      movwf   CICLO      ;y lo salva en CICLO
      btfsc   STATUS,Z   ;Si se activo el bit Z de STATUS no se ha recibido nada (W está en 0)
      goto    MOVIMIENTO   ;y esperamos el caracter de CICLO. Si Z=0 entonces saltamos este paso.
;      
               ;Enviamos el caracter 104 para indicar que el motor se va a mover.
      movlw   0x68      ;Coloca 104 (0x68) en W – Señal de motor en movimiento
      movwf   Txdreg      ;Carga W en Txdreg para transmitirlo
      call   TxD      ;y lo transmite indicando que los motores se están moviendo.
;
;*********Encendido del LED
      btfsc   M1,0      ;Si M1 es 0, salta el próximo paso
      goto    LED2      ;Si M1 es 1 salta a LED2
      bsf   PORTB,6      ;Prendemos el led 1
      bcf   PORTB,7      ;Apagamos el led 2
      goto    ARRANCAR
LED2         
      bcf   PORTB,6      ;Apagamos el led 1
      bsf   PORTB,7      ;Prendemos el led 2
;
;*********Comienzo del bucle
ARRANCAR
      clrf   BANDERA   ;Borrar contador de bucle para recorrer 256 veces el bucle   
      call    PWM      ;llamamos la rutina PWM
      decfsz   NVECES,f   ;Decrementamos la rutina de compensación
      goto    ARRANCAR   ;Mientras no llegue a 0, nos mantenemos en el bucle
      goto    RECEPCION   ;Cuando NVECES sea 0 regresamos a esperar otro character.
;
;*********Rutina PWM
PWM
;
;*********Chequeo del CARRY y suma de W
      addwf   CICLO, w       ; W=W+CICLO
      btfss   STATUS, C      ;Chequeamos el CARRY
      goto   APAGAR         ;Si no hay CARRY apagamos el motor
      btfsc    STATUS, C      ;Chequeamos el CARRY      
      goto   PRENDER         ;Si hay CARRY prendemos el motor (pasamos de 255 a 0)
      goto   SEGUIR
;
;*********
PRENDER                  ;ENCENDIDO DE MOTOR
      btfsc   M1,0      ;Si M1 es 0, salta el próximo paso
      goto    REVERSA      ;Si M1 es 1 se va a REVERSA
      nop               ;Los nop están para compensar los tiempos de la comparación y los saltos
                     ;COMO EJERCICIO CALCULEN LOS TIEMPOS DE LA RUTINA PWM!!!.
      bcf      PORTB,4      ;Apagamos pin RB4 de PORTB      
      bsf      PORTB,5      ;Prendemos pin RB5 de PORTB
      goto   SEGUIR      ;y se va a SEGUIR
REVERSA         
      bsf      PORTB,4      ;Prendemos pin RB4 de PORTB
      bcf      PORTB,5      ;Apagamos pin RB5 de PORTB
      goto   SEGUIR
APAGAR      
      nop
      nop
      nop               ;APAGADO DE MOTOR
      bcf      PORTB,4      ;Apagamos pin RB4 de PORTB
      bcf      PORTB,5      ;Apagamos pin RB5 de PORTB
      nop
      nop
SEGUIR
                     ;Si es necesario un Delay colcarlo aquí
      decfsz   BANDERA,f   ;Decrementamos BANDERA y saltamos si es cero. Hacerlo 256 veces.
      goto   PWM
      return
;**********Fin
      end



Ultima edición por Marcelo el Vie Nov 18, 2005 3:47 pm, editado 3 veces

#5  Montando el circuito
Marcelo
Colaborador
Registrado: 27 Jul 2005
Mensajes: 362
Ubicación: Venezuela
citar
Montando el circuito:

Ahora que ya tenemos diseñado nuestro firmware, vamos a montar el circuito para probarlo.

La alimentación de la etapa lógica y de comunicaciones (PIC16F84 y MAX232) será a 5 voltios.

Con respecto al control del motor hay que tener algunas consideraciones. Si alguien se está preguntando si puede conectar directamente las patas del motor a las salidas del PIC la respuesta es NO!.

Las señales de salidas (Motor1 y Motor2) del PIC se usarán como control para el circuito de potencia del motor. Aunque yo les voy a dar un esquema sugerido para un motor DC de 9-12V de alimentación y corriente de armadura de 250 mA (lo pueden forzar hasta 1,5 A pero disipen el calor en los transistores BD135), diseñado con elementos discretos (transistores, resistencias, condensadores, etc), queda en sus manos el desarrollo de esta etapa.
Para ello podrán emplear un buen número de integrados diseñados para el manejo de motores DC o basarse en cualquiera de los circuitos que podrán encontrar dedicados a eso (pregunten en este foro).

Para los que son un poco más avanzados en electrónica:
“Deberán poner atención en el diseño del circuito para el control de motores, pues tendrán que verificar que las salidas M1 y M2 deberán estar amortiguadas (con un buffer) mediante un circuito cuya ganancia sea igual a 1, a fin de evitar que las salidas (o los pines mejor dicho) se mantengan en régimen permanente afectando el voltaje entregado por el PWM.
Esto debió evitarse cambiando el firmware de manera tal que las salidas de PWM (Motor1 y Motor2) se coloquen como SALIDAS al momento de llamar a la rutina de movimiento y conmutándolas a ENTRADAS (estado de alta impedancia) inmediatamente después de que la rutina PWM haya terminado de realizar sus labores. Esto no está implementado. Aquí el “buffering” lo hice utilizando los optoacopladores en el puente H.”

Fin de la cita.

Siguiendo con lo anterior, si desean probar el circuito sin utilizar un motor, podrán conectar (aquí si directamente) un LED en cada una de las salidas correspondientes al motor.

En los siguientes LINKS se pueden bajar los esquemas en EAGLE para que los modifiquen, los integren y realicen su circuito impreso.

Fuente de poder - Input AC: PowerSupply-DC.sch

Fuente de poder - Input DC: PowerSupply.sch

Esquema Parte Lógica: PWM.sch

Esquema Parte de Potencia del Motor: PuenteH.SCH

y aquí van los circuitos (discúlpenme si quedaron algo grandes):

Si disponen de un transformador DC (corriente contínua) de 12 voltios pueden utilizar la siguiente FUENTE DE PODER:



Si en cambio poseen un transformador de 12 voltios AC (corriente alterna), la pueden diseñar así:



El Circuito Lógico, que comprende el PIC y la comunicación, es el siguiente:



En el circuito anterior, el PIN 5 del PIC debe ir a tierra y el PIN 14 a Vcc (5 voltios). OJO: No aparecen en el esquema.

Y para controlar el motor, pueden usar algo como esto:



Ahora bien, lo único que falta para terminar el proyecto es construirnos un cable serial pin a pin para conectarlo al computador y escribir nuestro software de control. Para esto pueden utilizar este esquema:



Bueno amigos “Foristas” creo que esto concluye el mini tutorial de PWM y de todo un poco en realidad, pues hemos podido abarcar desde la teoría hasta la práctica, pasando por la lógica, la diagramación, el desarrollo y la construcción de nuestro proyecto, así es que también hemos podido ver una forma de diseño. Como escribí aquí en más de una oportunidad, mucho se puede hacer para mejorar este trabajo y es lo que deseo que hagamos todos. Espero que se animen a estudiar este y a escribir otros tutoriales, yo por mi parte los estaré esperando.

Saludos y hasta la próxima,

Marcelo.

 El tema está cerrado y no puedes editar mensajes o responder





 Temas de interés 
No hay mensajes nuevos Conmutador electronico 10 pulsos x seg
No hay mensajes nuevos Contador de pulsos unido al microcontrolador DLP-245PB
El tema está cerrado y no puedes editar mensajes o responder 555 como divisor de frecuencias en un tren de pulsos
No hay mensajes nuevos Control de pulsos sincronizados con la red electrica
No hay mensajes nuevos Contador de pulsos

Foros de Electronica
|| Cuestiones Elementales de Electrónica || Fuentes de alimentacion || Circuitos de radio || Diseño de circuitos en general ||
|| Sistemas de Audio: Preamplificadores, Ecualizadores || Amplificadores || Reparación || Discusión ||
|| Microcontroladores y sistemas embebidos || Circuitos logicos combinacionales y secuenciales || Interfaces y Programacion || Dudas en general || Sistemas de Video || PC Hardware || Telematica y comunicaciones || Tecnologias moviles || Software Electronico || Robotica, Domotica y Mecatronica || Autotrónica || Automatizacion, Electronica industrial y de Potencia || Documentacion, circuitos y esquemas || Donde Las Ideas Convergen... || Tutoriales y Manuales || Proyectos Prácticos ||