desktop

[Aporte] Mezclador de luz RGB

A ok muchas gracias seguire tu consejo lo probare y despues te dire que tal anda muchas gracias amigo
 
Saludos dino gracias a tu libreria PWM ya pude cotrolar 8 salidas PWM desde labview ahora mi pregunta es la siguiente: en la libreria que tu creaste esta esta linea de codigo

void PWM_init(load)
{
if (load >240) load=240;
Reload = load;
setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
}

que me imagino que es donde tu configuras que frecuencua quieres para el PWM no me podrias orientar para poder hacer los calculos para una frecuencia a 50hz con un cristal de 20Mhz pero bien sabemos que el modulo USB trabaja a 48Mhz de antemano gracias por tu colaboracion :D


O si fueras tan amable de explicarme como generar PWM por software asi como tu lo hiciste en tu libreria PWM.


Me interesa saber como calcular la frecuencia exacta ya que los servos son muy delicados ase rato conecte uno y se barrieron los engranes y al simularlo en proteus no me da el valor exacto ya que se sobresatura el CPU y da mensajes erroneos.... por eso me interesaria saber como calcularlo y despues medirlo en un osiloscopio para ya no echarme otro servo gracias amigo.

PIC18f2550
cristal 20mhz
pero con la configuracion a usb queda a 48Mhz
Servos a controlar 8
 
Última edición:
con una simple regla de tres lo solucionas

con 255 -------- 170Hz
con X -------- 50Hz

de donde resulta que; X=(255*50)/170> 75



PWM_init(75);

te dejo un programa generando una onda de 50Hz para que lo revices
 

Adjuntos

  • PWM 50Hz.rar
    352.4 KB · Visitas: 134
Última edición:
Gracias por tu pronta respuesta anteriormente ya lo habia realizado asi pero con un cristal de 20 pero sin conexion a USB pero ahora mi pregunta es la siguiente que no se supone que los calculos estan basados en la frecuencia del cristal pero ya ves que el modulo USB trabaja asta 48Mhz o nadamas se toma la frecuencia del cristal externo sin tomar en cuenta el PLL del pic modulo USB???
 
Gracias por tu pronta respuesta anteriormente ya lo habia realizado asi pero con un cristal de 20 pero sin conexion a USB pero ahora mi pregunta es la siguiente que no se supone que los calculos estan basados en la frecuencia del cristal pero ya ves que el modulo USB trabaja asta 48Mhz o nadamas se toma la frecuencia del cristal externo sin tomar en cuenta el PLL del pic modulo USB???

los 48Mhz son para el USB nada mas.. el timer trabajara con los 20Mhz del cristal externo, saludos!!
 
Última edición:
Muchas gracias por aclararme esa duda en el transcurso de la semana lo pruebo y te comento que tal jala, oye amigo una pregunta mas influye el numero de salidas pwm que tengo es decir es la misma frecuencia para 3 salidas que para 8???

Esque pude modificar tu libreria para que me diera 8 salidas pwm y me las da sin ningun problema pero mi pregunta es si no afecta en la frecuencia que era para 3??
 
Última edición:
Muchas gracias por aclararme esa duda en el transcurso de la semana lo pruebo y te comento que tal jala, oye amigo una pregunta mas influye el numero de salidas pwm que tengo es decir es la misma frecuencia para 3 salidas que para 8???

Esque pude modificar tu libreria para que me diera 8 salidas pwm y me las da sin ningun problema pero mi pregunta es si no afecta en la frecuencia que era para 3??

no creo que influya, ya que 40 Hz es una frecuencia despreciable frente a los 20Mhz con la que trabaja el PICmicro.
 
Hola que tal dino ya pudo calarlo, es que acá es difícil conseguir servos y tuve que ir a otro estado por el, lo cale y funciona bien bueno se siente un poco de vibración pero es mínimo, ahora el problema que surgió es que al momento de comandar 8 salidas PWM desde labview estas funcionan de maravilla gracias al apoyo de tu librería PWM pero las entradas análogas no funcionan, no se si falte alguna interrupción para las entradas análogas o para la conexión a usb espero puedas darle una checada a mi código y decirme en que estoy fallando de antemano gracias....

Código:
#include <18F2550.h>                                                            //pic utilizado en este caso el 18f2550 
#DEVICE ADC=8                                                                   //Bits del modulo convertidor analógico
#fuses HSPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN      //Fuses utilizados para este proyecto
                                                                                /*
                                                                                  HSPLL: utilizamos un cristal HS de alta velocidad, 
                                                                                  en conjunto con el PLL para generar los 48Mhz.
                                                                                  MCLR: Utilizamos reset por Hadware.
                                                                                  NOWDT: No utilizamos el perro guardían.
                                                                                  NOPROTECT: Desactivamos la protección de código.
                                                                                  NOLVP: Desactivamos la programación a bajo voltaje.
                                                                                  NODEBUG: No entramos al modo debug.
                                                                                  USBDIV: signfica que el clock del usb se tomará del 
                                                                                          PLL/2 = 96Mhz/2 = 48Mhz.
                                                                                  PLL5: significa que el PLL prescaler dividirá en 5 la frecuencia 
                                                                                        del cristal. para HS = 20Mhz/5 = 4Mhz.
                                                                                  CPUDIV1: El PLL postscaler decide la división en 2 de la 
                                                                                           frecuencia de salida del PLL de 96MHZ, si queremos 
                                                                                           48MHZ, lo dejamos como está.
                                                                                  VREGEN: habilita el regulador de 3.3 volts que usa el módulo USB
                                                                                */
#use delay(clock=48000000)                                                      //Frecuencia de relog a 48MHz
#define USB_HID_DEVICE     FALSE                                                //Desactivamos el modulo HID ya que trabajaremos en modo Bulk
#define USB_EP1_TX_ENABLE  USB_ENABLE_BULK                                      //Habilitamos el modo TX en Bulk
#define USB_EP1_RX_ENABLE  USB_ENABLE_BULK                                      //Habilitamos el modo RX en Bulk
#define USB_EP1_TX_SIZE    4                                                    //Tamaño del TX para nuestro Bulk
#define USB_EP1_RX_SIZE    8                                                    //Tamaño del RX para nuestro Bulk
#Define CH0 PIN_C0                                                              //Asignación del canal 0 para el PWM
#Define CH1 PIN_C6                                                              //Asignación del canal 1 para el PWM
#Define CH2 PIN_C7                                                              //Asignación del canal 2 para el PWM
#Define CH3 PIN_B0                                                              //Asignación del canal 3 para el PWM
#Define CH4 PIN_B1                                                              //Asignación del canal 4 para el PWM
#Define CH5 PIN_B2                                                              //Asignación del canal 5 para el PWM
#Define CH6 PIN_B3                                                              //Asignación del canal 6 para el PWM
#Define CH7 PIN_B4                                                              //Asignación del canal 7 para el PWM
#include <pic18_usb.h>                                                          //Mandamos llamar a la librería para poder controlar este pic
#include "daqDescriptor.h"                                                      /*Mandamos llamar la librería para que esta informe a la computadora 
                                                                                  sobre el vendedor y producto esta librería es llamada como 
                                                                                  descriptores y es la que conecta a la pc con el pic*/
#include "PWM.h"                                                                //Mandamos llamar la libreria del PWM por software
#include <usb.c>                                                                //Mandamos llamar la librería de las funciones del modulo USB
#use fast_io(b)
#use fast_io(c)

int8 datoRX[8], datoTX[4];                                                      //Variables del programa
int8 count=0;


void main( void )                                                               //Programa principal
{ 
 PWM_init(80);                                                                  //Numero de conteo del timer para esta librería en base a la frecuencia
 setup_port_a(AN0_TO_AN2);                                                      //Configuramos las entradas análogas
 setup_adc(ADC_CLOCK_INTERNAL);                                                 //Con una señal de reloj interna
 set_tris_a(0xFF);                                                              //Puerto A de la siguiente manera(11111111) 1=entradas, 0=salidas     
 set_tris_b(0xE0);                                                              //Puerto B de la siguiente manera(11100000) "                   " 
 set_tris_c(0x00);                                                              //Puerto C de la siguiente manera(00000000) "                   "    
 output_a(0); output_b(0); output_c(0);                                         //Reseteamos el puerto A,B,C
 write_duty0(255);                                                              //Reseteamos las salidas PWM
 write_duty1(255);
 write_duty2(255);
 write_duty3(255);
 write_duty4(255);
 write_duty5(255);
 write_duty6(255);
 write_duty7(255);

 usb_init();                                                                    //Iniciamos el modulo USB
 usb_task();
 output_low(PIN_A3);                                                            //Led indicador de estado
 usb_wait_for_enumeration();                                                    //Espera a que el USB sea enumerado por la PC
 output_high(PIN_A3);                                                           //Led indicador de estado
 delay_ms(100);                                                                 //Milipausa para estabilidad
                                                        
 While(TRUE)                                                                    //Bucle infinito para envió y recepción de datos al buffer 
 {
  if(usb_enumerated())                                                          //Si el dispositivo a sido enumerado
  {  
   if (usb_kbhit(1))                                                            //Si llegan nuevos caracteres en el buffer de recepcion
   { 
    usb_get_packet(1,datoRX,8);                                                 //Leer buffer de ingreso
    write_duty0(datoRX[0]);                                                     //El valor del write duty x es igual a el dato que llega del vector datoRX[x]
    write_duty1(datoRX[1]);
    write_duty2(datoRX[2]);
    write_duty3(datoRX[3]);
    write_duty4(datoRX[4]);
    write_duty5(datoRX[5]);
    write_duty6(datoRX[6]);
    write_duty7(datoRX[7]);
   }
   for(count=0;count<=2;count++)                                                //Ciclo for para enviar datos de entradas analogicas 
   {
    set_adc_channel(count);                                                     //Lee los valores de ADC según sea el contador
    delay_us(80);                                                               //Micro pausa para estabilidad en la lectura
    datoTX[count]=read_adc();                                                   /*Igualamos nuestro buffer de salida a la lectura  
                                                                                  adc mediante el vector que indique nuestro for*/                  
   }
   usb_put_packet(1,datoTX,4,USB_DTS_TOGGLE);                                   /*Enviamos nuestro paquete de datos almacenados en nuestros 
                                                                                  vectores a la PC*/
  }
 }
}
Te explico un poco el problema la primer entrada si me da todos los bits pero no concuerdan es decir a 5v serían 255 bits y se supone que a 2.5v serian 127bits pero no concuerdan, la segunda entrada no jala solo da uno o cero, y el tercero jala como el primero aparte tienen mucho ruido, a ver si podrías orientarme con ese problema gracias
 
Última edición por un moderador:
Te explico un poco el problema la primer entrada si me da todos los bits pero no concuerdan es decir a 5v serian 255 bits y se supone que a 2.5v serian 127bits pero no concuerdan, la segunda entrada no jala solo da uno o cero, y el tercero jala como el primero aparte tienen mucho ruido, a ver si podrías orientarme con ese problema gracias

talves estes algo confundido, el microcontrolador siempre mandara un numero de 8 bits (entre 0 y 255).

voy ha revisar tu codigo y quiza para la tarde tenga una resuesta, saludos!!
 
De eso si entiendo pero mira el problema es el siguiente que las entradas analogas no responden bien y pienso que es por las interrupciones del Timer para la libreria de PWM tal ves el usb ocupe alguna interrupcion, o alamejor ocupe alguna interrupcion la entrada analoga.
 
yo uso el pic16f877 y logre mover 4 servo motores para hacer una especie de brazo robot y todo bien. pero ahora quiero usar el pwm para controlar un led rgb, aun no empieso con los 3 solo e intentado con uno pero el led solo se pone a parpadear creo que es mas dificil que los servos. el codigo es el siguiente, solo para ver si puedes decirme que esta mal o alguna forma de hacerlo mejor me tiene loco esto

Código:
	AllDigital
	Dim pwm1 As Word
	Dim contador As Word
	Dim x As Word
	OPTION_REG = %10000000  'pre 128 (110) - 2 (000)
	INTCON = %10100000  'Activa int globales(bit7) e int Tmr0(bit5)
	T1CON = %00000000  'Activa Tmr1(bit0)
	PIE1 = %00000000  'Activa int de Tmr1 (bit0)
	TRISB = %01111111
	PORTB.7 = 0
	contador = 0
	pwm1 = 0
	TMR0 = 0
	
ciclo:
	If pwm1 = 0 Then PORTB.7 = 0

	pwm1 = 0
	x = 0
While x < 255
	x = x + 1
	pwm1 = pwm1 + 1
	WaitMs 20
Wend
	pwm1 = 255
	x = 0
While x < 255
	x = x + 1
	pwm1 = pwm1 - 1
	WaitMs 20
Wend

	Goto ciclo

End                                               

	On Interrupt

	contador = contador + 1

	If pwm1 >= contador Then
	PORTB.7 = 1
	Else
	PORTB.7 = 0
	Endif

	If contador = 255 Then
	contador = 0
	Endif

	INTCON.2 = 0  'borro bandera int tmr0
	Resume
 
ya resolvi lo del parpadeo estatico los comandos "WaitMs" de basic creo utilizan el Tmr0 para los retrasos elimine esos comandos y el led comenso a cambiar de brillo pero parpadea un poco, ahora para eso cada interrupcion llenaba el Tmr0 a mas de la mitad asi aumente la frecuencia del ciclo a mas del doble y ya no noto parpadeos. aun asi me gustaria probar tu codigo que programa usas para compilarlo ? y que tengo que cambiar para usarlo con el 16f877 tengo un cristal de 12Mhz no e encontrado mas
 
hola quetzal, la frecuencia ideal para eliminar el parpadeo de los LED es 50Hz... (revisa el programa que subi anteriormete PWM 50Hz)...- yo programo en PIC CCS 4.1

Cambia #include <p16F877.h> y #use delay(clock =12000)


suerte!
 
Hola dino que tal ya mucho sin pasar por aqui oye una pregunta abra alguna forma de crear esta misma libreria pero para 376Hz ya que esta solo da como maximo 180Hz verdad bueno espero puedas ayudarme gracias :D
 
Yo quiero hacer algunas preguntas sobre este tema no se si ya está agotado,si es así consultare por mail



Va la pregunta ejemplo cargo el fuente .c PWM con POTS en un 18F4550 por medio de un bootloader y no funciona, cambie de salidas,etc, bueno dejo el programa que cargo.
Código:
//////////////////////////////////////////////////////////////////////////
////Control de 3 canales PWM por software                               //
////se utiliza para mesclar el brillo de tres leds;rojo,verde,azul      //
////utilizando potenciometro conectados a puerto AN0,AN1 y AN2          //
////recuerde que la libreria PWM.h debe estar en la misma carpeta       //
////donde se encuentre su codigo fuente                                 //
//////////////////////////////////////////////////////////////////////////
#include <18F4550.h>       
#device ADC=8  
#fuses HSPLL,MCLR,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#include "usb_bootloader.h"
#use delay(clock = 48000000)   
#Define CH0 PIN_D0             //led ROJO conectado a rb5, cambie de pin si desea
#Define CH1 PIN_D1             //led VERDE conectado a rb6, cambie de pin si desea
#Define CH2 PIN_D3             //led AZUL conectado a rb7, cambie de pin si desea
#include <PWM.h>           //libreria para generar PWM de 8 bit por software 
#use fast_io(d)
//#use fast_io(a)
void main (void) 
{  
unsigned byte value;
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(AN0_TO_AN2);      //A0,A1,A2 entradas analogicas
set_tris_d(0xF0);
output_d(0); 
//output_a(0);
delay_ms(20);
PWM_init(150);                    //Inicia MACRO para generar PWM por software, RTCC_DIV_2       
while(true)    
    { 
    
    set_adc_channel(0);
    delay_us(50);
    value=read_adc();  //lee canal AN0
    write_duty0(value);//escribe canal PWM0
    output_high(CH0);

    set_adc_channel(1);
    delay_ms(150);  
    value=read_adc();  //lee canal AN1
    write_duty1(value);//escribe canal PWM1
    output_low(CH0);
    output_high(CH1);
    
    set_adc_channel(2);
    delay_ms(150);
    value =read_adc(); //lee canal AN2
    output_low(CH1);
    write_duty2(value);//escribe canal PWM2
    }
}
este es el PWM_init

Código:
/////////////////////////////////////////////////////////////////////////////////////////////////////////////      
////libreria PWM.h, version 8Bit                                                                           //                    
////author: dinoelectro                                                                                    //
////www.forosdeelectronica.com                                                                             //
////dino_barreto@hotmail.com                                                                               //
////Con esta libreria podra generar ondas PWM con una resolucion de 8bit.                                  //
////Por defecto las ondas generadas salen por los pines B0, B1 y B2, pero cualquier otro PIN puede ser     //
////configurado como salida PWM; Por ejemplo: para generar las ondas en los pines A0,A1 y A2 usted deberia //     
////hacer la definicion de los canales como sigue:                                                         //
////                    #define CH0 PIN_A0                                                                 //
////                    #define CH1 PIN_A1                                                                 //
////                    #define CH2 PIN_A2                                                                 //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CH0 #define CH0 PIN_D0 #endif //si no ha definido, PIN_B0 sera canal0 PWM por defecto
#ifndef CH1 #define CH1 PIN_D1 #endif //si no ha definido, PIN_B1 sera canal1 PWM por defecto
#ifndef CH2 #define CH2 PIN_D3 #endif //si no ha definido, PIN_B2 sera canal2 PWM por defecto
unsigned byte intcount =0;
unsigned byte dutycycle0=0;
unsigned byte dutycycle1=0;
unsigned byte dutycycle2=0;
unsigned byte Reload;
///////////////////////////////////////////////////////////////////////////////////////////////////////
////Funcion PWM_init(load)                                                                         //
////USO:                                                                                             //
////      Esta funcion inicia y habilita interrupcion por timer0                                     //
////      el timer0 es necesario para generar la onda PWM cuya                                       //
////      frecuencia esta directamente realacionada con el cristal                                   //     
////      que haya elejido y con el valor que carga en el timer0                                     //
////Parametros:                                                                                      //
////      load: puede tomar un valor de 0... 255                                                   // 
////      mientras mayor sea el valor de load, mayor sera la frecuencia de la onda PWM             //                              //
////VALOR DE RETORNO:                                                                                //
////      ninguno                                                                                    //
///////////////////////////////////////////////////////////////////////////////////////////////////////
void PWM_init(load)                                                                                    
{
    if (load >240) load=240;
    Reload = load;
    setup_timer_0(RTCC_INTERNAL|RTCC_8_BIT); 
    enable_interrupts(INT_TIMER0);
    enable_interrupts(GLOBAL);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////
////Funciones Write_Duty0, Write_Duty1, Write_Duty2                                                  //
////USO:                                                                                             //
////      Estas funciones escriben el valor del ciclo util en los canales 0, 1 y 2; respectivamente  //
////PARAMETROS:                                                                                      //
////      value, es el ciclo util, puede tomar un valor entre 0 y 255                                //
////VALOR DE RETORNO:                                                                                //
////      ninguno                                                                                    //
///////////////////////////////////////////////////////////////////////////////////////////////////////
void write_duty0(value) {dutycycle0=value;}
void write_duty1(value) {dutycycle1=value;}
void write_duty2(value) {dutycycle2=value;}
///////////////////////////////////////////////////////////////////////////////////////////////////////
#int_timer0
void timer0_isr() 
{   set_timer0(Reload);
      if (intcount--==0)
   {
   output_high(CH0); 
    output_high(CH1); 
    output_high(CH2);  
   }
   if (intcount==dutycycle0)output_low(CH0); 
   if (intcount==dutycycle1)output_low(CH1); 
   if (intcount==dutycycle2)output_low(CH2); 
}
Alguien podría dar una mano. Muchas gracias
 
Última edición por un moderador:
no encuentro ningún error en el código,.. lo único que te puedo sugerir es asegurarte de estar trabajando con un cristal de 20Mhz en la librería PWM.h no es necesario hacer ningún cambio (al menos que desees ampliarla)

otra duda que tengo es ¿El bootloader funciona, es decir te deja descargar el programa?
 
Gracias por contestar dinoelectro,creo que funciona bien por que des cargue dos programas para titilar un led uno compilado en c18 y el otro en ccs y los dos funcionaron, inclusive si miras el codigo yo agregue output_high(CH0); anule los write_duty;PWM_init(150);#include <PWM.h> modifique tiempos en delay_ms(150);y demas camdios en otro delay,y el programa se cargo ,se ven los led prenderse y apagarce.
Creo que esto cofirma que se carga.
Puede haber algun problema con las interrupciones al hacerlo con el booloader, el remapeo.
Por ahora no se me ocurre nada.



Te comento que estoy trabajando con cristal de 20 mhz.
Tambien esta reforma que yo ise para que titilaran dos led (las comente anteriormente)las cargue con #use delay(clock = 48000000)
20000000 y 4000000, y funcionaron todas en el pic y se variaba la frecuencia de titilar los led
 
Última edición:
tienes razon, el remapeo de interrupciones a las direcciones 0x8 y 0x16 puede ser la solucion habria que probrar...

si utilizas el bootloader de CCS tambien existe la opcion de colocar el bootloader en las ultimas direcciones de memoria, evitandote eso del remapeo
 
Cuando tenga un tiempo le pongo mano si lo descubro lo comento,lo tengo funcionando en est momento con un pic16f877A.
Muchas gracias



Estoy usando el hid bootloader en c18.
 
Última edición:
Atrás
Arriba