# [Aporte] Mezclador de luz RGB



## dinoelectro (Oct 23, 2011)

Este controlador es sencillo, económico y divertido realizar, se trata de un mezclador de colores primarios RGB (Red, Green, Blue) para obtener distintas tonalidades resultantes de la mezcla; entre las aplicaciones que se puede dar a este circuito tenemos; llamador de atención en una tienda de barrio, bañador de luz para la pared para tu cuarto, lámpara decorativa para un bar o discoteca, iluminaria para cuartos de baño, piscinas, piletas, catedrales, autos, plantas,.. etc.

trabaja con el PIC16F628A en dos modos; Fijo y Aleatorio, fijo: cuando el usuario hace uso de los pulsantes de mando para obtener el color deseado, Aleatorio: cuando cierra los interruptores para que el espectro de luz cambie aleatoriamente entre una gama de 255 colores distintos

incluyo todo lo necesario; instrucciones, código fuente y diseño de pcb


----------



## DJ DRACO (Oct 24, 2011)

Está muy bueno, quisiera saber si se puede hacer con otro PIC, ya que no tengo el 628...


----------



## Lord Chango (Oct 24, 2011)

DJ DRACO dijo:


> Está muy bueno, quisiera saber si se puede hacer con otro PIC, ya que no tengo el 628...



A simple vista parece que si, se pueden utilizar otros PICs, siempre y cuando tenga PWM, y tal vez con alguna modificacion de codigo. Habria que revisar la hoja de datos.

Saludos.


----------



## dinoelectro (Oct 24, 2011)

puede utilizar un cualquier PIC, para reemplazar al 16F628A. no necesita que tenga modulo PWM, ya que la generacion de las ondas se hace por software, utilizando la libreria PWM.h que he creado.
Es necesario interrupcion por timer0_ (casi todo PIC tiene, incluso los de 8 pines)_

gracias Fogonazo, me alegro que te haya gustado


----------



## XeRo21lp (Oct 24, 2011)

excelente amigo gracias por el aporte ahora mismo quiero ver la simulación y bueno solo veré eso mientras busque los leds RGB que en mi pais no puedo encontrar a la venta  bueno si alguien me diera referencias para comprarlo en algun lugar de mi pais le estaré agradecido y soy de bolivia ^_^ jejeje

Nuevamente muchas gracias, y fogonazo una pregunta hay algun articulo en el foro donde pueda aprender a programar?  gracias a los usuarios que comparten sus experimentos y experienciaaaas ^_^


----------



## dinoelectro (Oct 24, 2011)

No es necesario leds RGB, el led RGB no es mas que tres leds rojo, verde y azul en una sola capsula,... el mismo resultado obtienes si compras tres leds individuales de alto brillo y te haces una capsula con silicona


----------



## virytut (Nov 7, 2011)

la simulacion no me Habre!!!.... alguien pudo abrirla cOn proteus???


----------



## dinoelectro (Nov 7, 2011)

virytut dijo:


> la simulacion no me Habre!!!.... alguien pudo abrirla cOn proteus???



tienes que cargar el archivo RGB_LED.cof en el microcontrolador virtual...  si aun asi no funciona, tienes que volver a compilar, todo el codigo esta en la pagina 7. pero recuerda tambien debes incluir la libreria PWM.h en la misma carpeta donde ensambles tu proyecto. el codigo de la libreria PWM.h esta en la pagina 5. 

programe en PIC CCS v4.114 y simule en Proteus 7.7 SP2... saludos


----------



## RUIZ13 (Nov 7, 2011)

Hola a todos
 yo hice uno muy parecido dejame abrirlo para ver la degradacion y voy a ver cuando lo puedo construir para detallarlo, ya que el gran problema de estos circuitos es que parpadean los colores al aumentar y disminuir el color

voy a verlo hasta pronto


----------



## dinoelectro (Nov 7, 2011)

RUIZ13 dijo:


> Hola a todos
> yo hice uno muy parecido dejame abrirlo para ver la degradacion y voy a ver cuando lo puedo construir para detallarlo, ya que el gran problema de estos circuitos es que parpadean los colores al aumentar y disminuir el color
> 
> voy a verlo hasta pronto



Para evitar el parpadeo debes aumentar la frecuencia de la onda PWM; el que aqui expongo no tiene ese problema,...  no te olvides estaremos esperando tu aporte.. jeje


----------



## virytut (Nov 7, 2011)

dinoelectro dijo:


> tienes que cargar el archivo RGB_LED.cof en el microcontrolador virtual...  si aun asi no funciona, tienes que volver a compilar, todo el codigo esta en la pagina 7. pero recuerda tambien debes incluir la libreria PWM.h en la misma carpeta donde ensambles tu proyecto. el codigo de la libreria PWM.h esta en la pagina 5.
> 
> programe en PIC CCS v4.114 y simule en Proteus 7.7 SP2... saludos



Muchas gracias dino...


----------



## dinoelectro (Nov 8, 2011)

virytut dijo:


> Muchas gracias dino...



De nada viruyut... se me olvido decirte que use MPLab 7.8 como IDE;... pero si tu vas a compilar puedes usar tranquilamente el IDE de PICC CCS


----------



## virytut (Nov 9, 2011)

dinoelectro dijo:


> De nada viruyut... se me olvido decirte que use MPLab 7.8 como IDE;... pero si tu vas a compilar puedes usar tranquilamente el IDE de PICC CCS



Ok..ps uso mikroc...la verdad no me ha funcionado en proteus yo creo q es el mikroc o algo en la compilacion


----------



## dinoelectro (Nov 11, 2011)

tienes que compilar en PIC C; aunque no es necesario porque yo subi el proyecto compilado


----------



## 4leks (Nov 22, 2011)

Gracias por el aporte dino, habrá que probarlo y ver si lo aprueban como proyecto final. Saludos


----------



## dinoelectro (Nov 22, 2011)

4leks dijo:


> Gracias por el aporte dino, habrá que probarlo y ver si lo aprueban como proyecto final. Saludos



... que bueno que te jaya gustado... ahi estare listo para ayudarte en lo que pueda...  el sistema funciona te lo aseguro


----------



## 4leks (Nov 29, 2011)

Que tal dino, una duda enorme, no he podido conseguir el pic 16f628a, ¿se podra remplazar con un 16f84a (tambien de 18 pines) sin ningun problema ni necesidad de modificaciones?


----------



## dinoelectro (Nov 30, 2011)

no creo que tengas ningun problema 4leks... ya que los dos tienen TIMER0, ademas la configuracion de pines del 16F628 es la misma del 16F84A... en realidad no lo he probado pero casi te puedo asegurar que funciona con este PIC!!! 

eso si no te olvides de volver a compilar el programa especificando el microcontrolador 16F84A y comprueba con la simulacion para descartar cualquier duda

¡suerte!


----------



## Ericktronik (Jul 13, 2012)

hola Dinoelectro.

yo tambien quiero hacer el mezclador pero la verdad me es un poco dificil entender el codigo y la libreria.

el mezclador es para poder ponerselo a mi bici(_quiero controlar estos leds que puse en los rines_).
pero quiero hacerlo con el 12F675, se que hay uno en picprojects, pero mi intencion mas que todo es la de aprender.

y la idea es basicamente es que las luces tengan una secuencia predeterminada y otra que sea aleatoria que puedan ser seleccionadas por un interruptor.
la secuiencia predeterminada seria:



```
//antes o despues de cada delay se testea de nuevo la posicion del interruptor 
y si cambia se envia de nuevo al testeo principal para decidir si ejecuta la secuencia 
predeterminada o la aleatoria, de igual manera se hace en la aleatoria, 
despues de cada transicion se testea de nuevo la posicion del interruptor.

while(interruptor ==1){
rojo;
          delay_ms(1000);
encendido suave de verde(transición de 1 segundo);
          delay_ms(1000);    //en este punto el color es amarillo
apagado suave de rojo(transición de 1 segundo);
          delay_ms(1000);   //en este punto el color es verde
encendido suave de azul(transición de 1 segundo);
          delay_ms(1000);   //en este punto el color es cyan
apagado suave de verde(...);
          delay_ms(1000);   //en este punto el color es azul
encendido suave de rojo(...);
          delay_ms(1000);   //en este punto el color es purpura
encendido suave de verde(...);
          delay_ms(1000);   //en este punto el color es blanco
apagado suave de verde(...);
          delay_ms(1000);   //en este punto el color es purpura
apagado suave de rojo(...);
          delay_ms(1000);   //en este punto el color es azul
encendido suave de verde(...);
          delay_ms(1000);   //en este punto el color es cyan
apagado suave de azul(...);
          delay_ms(1000);   //en este punto el color es verde
encendido suave de rojo(...);
          delay_ms(1000);   //en este punto el color es amarillo
apagado suave de verde(...); //vuelve a ser rojo
}
```


espero que puedas guiarme y enseñarme para poder desarrollar este pequeño proyecto.
desde ya, gracias.
saludos


----------



## dinoelectro (Jul 14, 2012)

hola ericktronik, te comento que he mejorado esa libreria para generacion de señales PWM, pero ahora estoy fuera de casa y no puedo enviarte el archivo... por el momento lo unico que puedo sugerirte que revices la nota de aplicacion AN1074 de microchip ya que yo me base en ese documento para realizar este proyecto

Software PWM, LED Dimming, RGB Color, PIC® Microcontroller, PIC12HV615
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1824&appnote=en524189

saludos!!


----------



## dinoelectro (Jul 17, 2012)

lo importante no es entender la libreria PWM.h sino saber como utilizarla.. 

al inicio de tu programa utiliza la funcion Función *INIT_PWM()* para habilitar el Timer0 e inicializar otras variables, luego de esto ya puedes utilizar la funcion *WriteDuty(CH, VALUE)* que escribe el ciclo util ya sea en el canal 0, 1 o 2

CH es el canal 
VALUE es un numero entre 0 y 255, el ciclo útil del canal indicado

Saludos!!


----------



## kovian (Sep 30, 2012)

gracias por tu aporte, yo quiero implementar tu proyecto, pero como no se nada de pics, apenas empiezo a verlos....y se me dificulta entender codigo...bueno tengo unas preguntas que ojala puedas contestar....en el codigo, estas utilizando un oscilador externo? o es para qeue trabaje el pic o para generar pwm?...
esto en el codigo esta asi :
#use delay(clock = 20000000)	//libreria para generar retardos con un cristal de 20 mhz

no puedo utilizar el oscilador interno del pic?...

algo como esto?

#fuses INTRC			//oscilador interno
#use delay(clock = 4000000)	//libreria para generar retardos con un cristal de 4 mhz
 es necesario tener un oscilador externo para que funcione circuito?...otra duda es que como lo mandaste no me jala en proteus...lo corro y no hace nada....gracias


----------



## nicolasantoci (Oct 1, 2012)

Muy bueno está, lo voy a guardar para un futuro, gracias.


----------



## dinoelectro (Oct 1, 2012)

este lo programe en lenguaje PIC CCS con vsm studio,... trabaja con un cristal externo de 20Mhz esta compilado para el pic18F4550,... sin embargo se lo puede compilar para el pic 16F877 16F871 16F84 16F628...

incluyo simulacion en ISIS 

este tiene mayor resolucion y mejor control,..





kovian dijo:


> gracias por tu aporte, yo quiero implementar tu proyecto, pero como no se nada de pics, apenas empiezo a verlos....y se me dificulta entender codigo...bueno tengo unas preguntas que ojala puedas contestar....en el codigo, estas utilizando un oscilador externo? o es para qeue trabaje el pic o para generar pwm?...
> esto en el codigo esta asi :
> #use delay(clock = 20000000)	//libreria para generar retardos con un cristal de 20 mhz
> 
> ...



el cristal interno del PIC te da como maximo 8Mhz.. lo que influiria en el tiempo del desborde del timer0.. lo que afectaria directamente en la resolucion .. tendrias que hacer algunas modificaciones en el codigo tambien.. mas seguro comprate un crystal de 20Mhz. saludos


----------



## txarlie2010 (Oct 2, 2012)

Lo que observo es que en el PCB es que utiliza un uC de serie 12fxxx y que es de 8 pines el 16f628 tiene 18 pines


----------



## dinoelectro (Oct 2, 2012)

txarlie2010 dijo:


> Lo que observo es que en el PCB es que utiliza un uC de serie 12fxxx y que es de 8 pines el 16f628 tiene 18 pines



si desea construir el rgb para pic de 8 pines tendras que realizar alguno cambios en el firmware.. mas informacion tendras en la pagina de pic projects


----------



## kovian (Oct 4, 2012)

Gracias por contestar pero tengo el problema de que al simularlo con proteus y con el pic16f877a no tiene la misma resolución o frecuencia. No se a que se deba.
Esto es lo que cambie del código. Solo lo adapte para el pic....


```
////////////////////////////////////////////////////////////////////////
//Control de 3 canales PWM por software                               //
//se utiliza para mesclar el brillo de tres leds;rojo,verde,azul      //
//Funcionamiento;                                                     //
//         PIN_B0=0 Aumenta o disminuye ciclo util canal0    PIN_A0   //
//         PIN_B1=0 Aumenta o disminuye ciclo util canal0    PIN_A1   //
//         PIN_B2=0 Aumenta o disminuye ciclo util canal0    PIN_A2   //
//         PIN_B3=0 disminuye ciclo util, caso contrario aumenta      //
////////////////////////////////////////////////////////////////////////
#include <16f877a.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock = 20000000)   //libreria para generar retardos con un cristal de 20 mhz
#Define LED1 PIN_B5            //ROJO
#Define LED2 PIN_B6            //VERDE
#Define LED3 PIN_B7            //AZUL
#include <PWM.h>               //libreria para generar PWM por software
void main (void)
{
unsigned byte i=0,j=0,k=0;
BYTE CONST SINE_WAVE[200] = {
128,132,136,139,143,147,150,154,158,161,165,169,172,176,179,
182,186,189,192,195,199,202,204,207,210,213,215,218,220,223,
225,227,229,231,233,235,237,238,240,241,242,243,244,245,246,
247,247,247,248,248,248,248,248,247,247,247,246,245,244,243,
242,241,240,238,237,235,233,231,229,227,225,223,220,218,215,
213,210,207,204,202,199,195,192,189,186,182,179,176,172,169,
165,161,158,154,150,147,143,139,136,132,128,124,120,117,113,
109,106,102,98,95,91,87,84,80,77,74,70,67,64,61,57,54,52,49,
46,43,41,38,36,33,31,29,27,25,23,21,19,18,16,15,14,13,12,11,
10,9,9,9,8,8,8,8,8,9,9,9,10,11,12,13,14,15,16,18,19,21,23,
25,27,29,31,33,36,38,41,43,46,49,52,54,57,61,64,67,70,74,77,
80,84,87,91,95,98,102,106,109,113,117,120,124};
BYTE sine_index=0;
BYTE sine_index1=66;
BYTE sine_index2=132;
Init_Pwm();                    //Inicia MACRO para generar PWM por software
set_tris_b(0x0F);              //B0,B1,B2,B3 Entradas botones, B4,B5,B6 Salidas LED RGB
port_b_pullups(true);          //Habilita resistencias de pullup


while(true)
    {
    while(!input(Pin_B4))
        {
        Write_Duty(0,SINE_WAVE[sine_index]);
        Write_Duty(1,SINE_WAVE[sine_index1]);
        Write_Duty(2,SINE_WAVE[sine_index2]);
        if(++sine_index>=200)sine_index=0;
        if(++sine_index1>=200)sine_index1=0;
        if(++sine_index2>=200)sine_index2=0;
        delay_ms(500);
        }
     if (!input(PIN_B3))
     {
     if (!input(PIN_B0)){i++;if(i==0)i=255;Write_Duty(0,i);}
     if (!input(PIN_B1)){j++;if(j==0)j=255;Write_Duty(1,j);}
     if (!input(PIN_B2)){k++;if(k==0)k=255;Write_Duty(2,k);}
     }
    else
     {
     if (!input(PIN_B0)){i--;if(i==255)i=0;Write_Duty(0,i);}
     if (!input(PIN_B1)){j--;if(j==255)j=0;Write_Duty(1,j);}
     if (!input(PIN_B2)){k--;if(k==255)k=0;Write_Duty(2,k);}
     }
     delay_ms(10);
    }
}
```


----------



## kovian (Oct 4, 2012)

ademas me aparecen en la simulacion de proteus errores:

pc=0x016d adc conversion started before wait......
pc=0x016d porta<0> is not configurated as  analog input
pc=0x016d voltaje reference for adc conversion yield a 0 v range....
alguna sugerecia?


----------



## dinoelectro (Oct 4, 2012)

segun veo los errores de simulacion ocurren porque al puerto a lo toma como analogico

coloca al principio justo debajo de 
#use delay(clock = 20000000)   //libreria para generar retardos con un cristal de 20 mhz

las siguientes instrucciones..

#use fast_io(a)
#use fast_io(b)


luego configura el puerto a como salidas digitales

set_tris_a(0);


----------



## kovian (Oct 4, 2012)

SIGUE igual...marca errores....y al implementarlo fisicamnente ,,,me di cuenta que parpadean o mas bien titilan (se nota cuando se apagan y prenden ) las luces al bajar intensidad...como incremento frecuencia o como soluciono esto?

gracias


----------



## matrix01 (Oct 5, 2012)

Buenas, ¡¡¡¡¡¡¡¡¡¡tiene buena pinta!!!!!!!!!!!!, 
ya me lo voy a hacer. jejejejejeje  
Un saludo Matrix01


----------



## kovian (Oct 5, 2012)

sigue igual ...alguien tiene alguna ide ade problema?...yo puse asi el codigo que me digiste....


```
////////////////////////////////////////////////////////////////////////
//Control de 3 canales PWM por software                               //
//se utiliza para mesclar el brillo de tres leds;rojo,verde,azul      //
//Funcionamiento;                                                     //
//         PIN_B0=0 Aumenta o disminuye ciclo util canal0    PIN_A0   //
//         PIN_B1=0 Aumenta o disminuye ciclo util canal0    PIN_A1   //
//         PIN_B2=0 Aumenta o disminuye ciclo util canal0    PIN_A2   //
//         PIN_B3=0 disminuye ciclo util, caso contrario aumenta      //
////////////////////////////////////////////////////////////////////////
#include <16f877a.h>
//#fuses XT,NOWDT,NOPROTECT,PUT,NOLVP,BROWNOUT
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock = 20000000)   //libreria para generar retardos con un cristal de 20 mhz
#use fast_io(a)
#use fast_io(b)
#Define LED1 PIN_B5            //ROJO
#Define LED2 PIN_B6            //VERDE
#Define LED3 PIN_B7            //AZUL
#include <PWM.h>              //libreria para generar PWM por software


void main (void)
{
unsigned byte i=0,j=0,k=0;
BYTE CONST SINE_WAVE[200] = {
128,132,136,139,143,147,150,154,158,161,165,169,172,176,179,
182,186,189,192,195,199,202,204,207,210,213,215,218,220,223,
225,227,229,231,233,235,237,238,240,241,242,243,244,245,246,
247,247,247,248,248,248,248,248,247,247,247,246,245,244,243,
242,241,240,238,237,235,233,231,229,227,225,223,220,218,215,
213,210,207,204,202,199,195,192,189,186,182,179,176,172,169,
165,161,158,154,150,147,143,139,136,132,128,124,120,117,113,
109,106,102,98,95,91,87,84,80,77,74,70,67,64,61,57,54,52,49,
46,43,41,38,36,33,31,29,27,25,23,21,19,18,16,15,14,13,12,11,
10,9,9,9,8,8,8,8,8,9,9,9,10,11,12,13,14,15,16,18,19,21,23,
25,27,29,31,33,36,38,41,43,46,49,52,54,57,61,64,67,70,74,77,
80,84,87,91,95,98,102,106,109,113,117,120,124};
BYTE sine_index=0;
BYTE sine_index1=66;
BYTE sine_index2=132;
Init_Pwm();                    //Inicia MACRO para generar PWM por software
set_tris_a(0); 
set_tris_b(0x0F);              //B0,B1,B2,B3 Entradas botones, B4,B5,B6 Salidas LED RGB
port_b_pullups(true);          //Habilita resistencias de pullup


while(true)
    {
    while(!input(Pin_B4))
        {
        Write_Duty(0,SINE_WAVE[sine_index]);
        Write_Duty(1,SINE_WAVE[sine_index1]);
        Write_Duty(2,SINE_WAVE[sine_index2]);
        if(++sine_index>=200)sine_index=0;
        if(++sine_index1>=200)sine_index1=0;
        if(++sine_index2>=200)sine_index2=0;
        delay_ms(500);
        }
     if (!input(PIN_B3))
     {
     if (!input(PIN_B0)){i++;if(i==0)i=255;Write_Duty(0,i);}
     if (!input(PIN_B1)){j++;if(j==0)j=255;Write_Duty(1,j);}
     if (!input(PIN_B2)){k++;if(k==0)k=255;Write_Duty(2,k);}
     }
    else
     {
     if (!input(PIN_B0)){i--;if(i==255)i=0;Write_Duty(0,i);}
     if (!input(PIN_B1)){j--;if(j==255)j=0;Write_Duty(1,j);}
     if (!input(PIN_B2)){k--;if(k==255)k=0;Write_Duty(2,k);}
     }
     delay_ms(10);
    }
}
```

me sigue diciendo que la puerto a no esta configurado como analogica input y que el tiempo de adc conversion es menor que min TAd=1....


----------



## dinoelectro (Oct 5, 2012)

hola kobian, el error respecto a entradas analogicas no deberia ser problema ya que todo se realiza en el puerto B, que es digital solamente.

sin embargo te mando el codigo compilado para el PIC16F877A, sin errores, espero te sirva. Revisa tambien la libreria PWM.H ahi comente algunas lineas para que puedas cambiar la frecuencia con la que desborda el timer0.

Suerte!!


----------



## Puncx (Oct 5, 2012)

dinoelectro dijo:


> sin embargo te mando el codigo compilado para el PIC16F877A, sin errores, espero te sirva. Revisa tambien la libreria PWM.H ahi comente algunas lineas para que puedas cambiar la frecuencia con la que desborda el timer0.
> Suerte!!



Podrias ayudarme a pasarlo al pic16f84a, lo he estado intentando pero no funciona como deberia, saludos..


----------



## kovian (Oct 6, 2012)

gracias ....lo voy a revisar....un saludo


----------



## dinoelectro (Oct 9, 2012)

Puncx dijo:


> Podrias ayudarme a pasarlo al pic16f84a, lo he estado intentando pero no funciona como deberia, saludos..



aqui lo tienes companero, compilado para el 16F84A... funcionando, en simualcion espero que tambien funcione en la realidad.

incluyo codigo y simulacion, dentro de la carpeta Release esta el .hex


----------



## kitt2000 (Oct 10, 2012)

Un PicAxe (un 08/08m/08m2 quizá no) que tengo 3 entradas analógicas, también puede hacer algo parecido verdad? Suponiendo que el pic interpretase la resistencia de un potecniómetro con valores 0-255, sería técnicamente posible no?


----------



## dinoelectro (Oct 11, 2012)

kitt2000 dijo:


> Un PicAxe (un 08/08m/08m2 quizá no) que tengo 3 entradas analógicas, también puede hacer algo parecido verdad? Suponiendo que el pic interpretase la resistencia de un potecniómetro con valores 0-255, sería técnicamente posible no?




claro, que es factible de echo yo lo hice asi tambien, lo que te recomiendo que los potenciometros sean de muy buena calidad, para tener una señal analogica lineal.



----------------------------------------------------------------

tengo que informarles que los códigos para pic 16FXXXX no están funcionando bien, esto me di cuenta al tratar de ensamblarlo yo mismo; pasa que yo lo probé con un PIC18F4550 y que utilice la configuracion PLL5 y la directiva #use delay(clock=48000000). esto no es posible hacer con un pic de la familia 16FXXX

.. asi que la unica forma de ver funcionando a este sistema es utilizado ya sea un PIC18F2550 o PIC18F4550, lamento la confusion..


----------



## nestoriano (Oct 11, 2012)

Hola dinoelectro, muchas gracias por el aporte. 
Hace un tiempito a mi tambien se me ocurrio armar una libreria para PWM por software, pero lo plantee un poquito y me parecio demaciado trabajo y consumidor de recursos asi que me resigne sin siquiera intentar jeje. 

Programo en Jalv2 y recien hice una prueba armando un codigo simple para cambiar el duty de entre 50% y 90% y funciona. 

Dos preguntas, a
A que frecuencia te trabaja el PWM? 
Porque usas el valor 128 como valor maximo duty?

A mi en el simulador ISIS usando un 16f877a a 20MHz el PWM me trabaja a 70Hz con una sola salida. Solo hice una prueba en el simulador, no se como se vera en la realidad.


----------



## dinoelectro (Oct 11, 2012)

nestoriano dijo:


> Hola dinoelectro, muchas gracias por el aporte.
> Hace un tiempito a mi tambien se me ocurrio armar una libreria para PWM por software, pero lo plantee un poquito y me parecio demaciado trabajo y consumidor de recursos asi que me resigne sin siquiera intentar jeje.
> 
> Programo en Jalv2 y recien hice una prueba armando un codigo simple para cambiar el duty de entre 50% y 90% y funciona.
> ...



hola nestor, respondiendo a tus preguntas

en los nuevos códigos que publique puedes revizar que la libreria PWM.h esta bastante mejorada; ahora el DUTY cambia de 0-255.. con eso logramos mejor resolucion. fue un error mio haberla truncado hasta 128.

con esta nueva libreria podes tambien elejir la frecuencia de trabajo, revisala.. 

este dimmer lo hice funcionar con el 18F4550 y funciona de maravilla... con los pics 16F funciona pero se puede notar un lijero pero fastidioso parpadeo, la razon es que con estos pic no tienes la opción PLL5 y #use delay(clock=48000000)

espero tus sugerencias saludos!!


----------



## nestoriano (Oct 11, 2012)

Ahi descargue 2 archivos con 16f877 y otro con 16f84. La simulacion del 16f84 me dice que el parpadeo de los leds es de 10Hz. Creo que algo anda mal. La simulacion del 16f877 parece que anda bien mandando pulsos de 38Hz. 
Un par de ideas que tengo en mente es armar una rutina al estilo:

pwm_max_resolution(1~255)

pwm_set_percent_dutycycle(0~100)

Lo que noto es que si se aumenta la resolucion, baja la frecuencia, y eso con un cristal de menor velocidad que 20Mhz seria un problema. Yo le agregaria una funcion para sacrificar resolucion y ganar frecuencia. 
Tambien que el ajuste del ancho se pueda hacer tambien por porcentaje. Para mi es mas comodo usando % y de paso uno se olvida de la resolucion maxima.

---EDIT
Pude sacar 200Hz con resolucion de 255 a 20Mhz. El codigo en Jalv2 es este por ahora.


```
const timer0_isr_rate = 80000
const DELAY_SLOTS = 2

var byte pwm_soft_duty0=0

var byte contador=255

alias   led      is pin_A0
pin_A0_direction =  output

include timer0_isr_interval
timer0_isr_init()

procedure timer0() is
pragma interrupt
	
	if (contador==pwm_soft_duty0) then
	pin_a0=0
	end if
	
	if (contador==0) then
	contador=255
	porta=255
	end if
	
	contador=contador-1
	
end procedure

	pwm_soft_duty0=0

forever loop
		
	if (pin_b0==1) then
	pwm_soft_duty0=pwm_soft_duty0+10

	   while(pin_b0==1) loop
	   end loop

	end if
	
end loop
```

Me da un par de warning pero igual parece que anda. Apreto el pulsador y me va bajando el duty. Esto se esta poniendo bueno, mas tarde voy a probar con un par de LEDs RGB que tengo por ahi para hacer pruebas.


----------



## dinoelectro (Oct 13, 2012)

nestoriano dijo:


> Lo que noto es que si se aumenta la resolucion, baja la frecuencia, y eso con un cristal de menor velocidad que 20Mhz seria un problema. Yo le agregaria una funcion para sacrificar resolucion y ganar frecuencia.



Hola nestoriano, sabes que estube analizando, y no fue necesario sacrificar la resolucion para aumentar la frecuencia. Lo que hice fue cargar un valor al timer0 para que se desborde mas rapido y obtube una frecuencia de 170Hz con la misma resolucion de 8 bits.  

es buena idea eso de controlar el ciclo util mediante porcentaje de 0-100%. en la proxima version de la libreria talvez incluya esa opcion.  

----------------------------------------------------------------------------------------

Aporto con este Mezclador RGB , utiliza tres potenciometros para controlar el brillo de cada LED.  ademaqs un pequeño tutorial de como utilizar la libreria PWM.h que esta bastante optimizada. espero sus comentarios y sujerencias


----------



## dinoelectro (Oct 18, 2012)

aporto este mezcaldor de luz, controlado por computador , metodo de comunicacion USB HID.. la simulacion con Proteus no funciona.. pero al armarlo todo anda bien.. 


adjunto tambien un programa en visual basic que envia tres valores entre 0 y 255, que controlan el brillo cada LED Rojo, verde y azul..


saludos!!


----------



## olinqui (Oct 24, 2012)

Hola Dino excelente aporte pero tengo una duda como cargas el valor al TIMER0 para apresurar el desborde para obtener los 170Hz?

Saludos.


----------



## dinoelectro (Oct 25, 2012)

hola olinqui,  respondiendo a tu pregunta, 

si quieres 150Hz................................................ PWM_init(200);
para alcanzar 170Hz.......................................... PWM_init(225);
si quieres 180Hz................................................ PWM_init(250);

etc,... con esta libreria alcanzaras frecuencia maxima 180Hz.. puedes revisar el archivo en pdf donde explico como utilizar las libreria PWM.h.. se encuentra en el archivo PWM con POTS.rar



la instruccion set_timer0(offset).. , te permite cargar al timer0, mientras mayor es el valor de öffset¨ mas rapido se desbordara el timer0


----------



## kiyero (Oct 27, 2012)

hola dino, estuve revisando el proyecto y me parece excelente, pero tengo una duda: quiero añadirle un canal adicional para trabajar cuatro canales, y aumentar de 3 a 10 leds por canal, que programas utilizaste para compilar y simular? quedo atento, ya que quiero implementarlo para la decoración navideña, tan pronto lo haga (con tu ayuda en respuesta a este mensaje) postearé fotos y video, gracias y saludos!


----------



## dinoelectro (Oct 29, 2012)

holA KIYERO, CON TRANsistores 2n3904 Y Una fuente de +12V podras conectar hasta 6 LEDs por canal, con una de fuente de 24V conectarías hasta unos diez calculo yo...

solo con tres canales puedes obtener toda la gama de colores RGB, espero postees tu trabajo, saludos!


----------



## kiyero (Oct 29, 2012)

dinoelectro dijo:


> holA KIYERO, CON TRANsistores 2n3904 Y Una fuente de +12V podras conectar hasta 6 LEDs por canal, con una de fuente de 24V conectarías hasta unos diez calculo yo...
> 
> solo con tres canales puedes obtener toda la gama de colores RGB, espero postees tu trabajo, saludos!



ok Dino, pero con que programa puedo simularlos? me gustaría hacerlo de cuatro canales para ubicar un canal por cada lado del salón donde tengo pensado instalarlos, gracias, saludos


----------



## dinoelectro (Oct 29, 2012)

esta simulado con Proteus 7.10; puedes utilizar PIC C Compiller para compilar el programa.

para aumentar un canal necesitaras hacer cambios en la libreria pwm.H


----------



## kiyero (Oct 30, 2012)

dinoelectro dijo:


> esta simulado con Proteus 7.10; puedes utilizar PIC C Compiller para compilar el programa.
> 
> para aumentar un canal necesitaras hacer cambios en la libreria pwm.H



Hola dinoelectro, hice las modificaciones según tus recomendaciones y me tira error de compilación, podrías ayudarme echando una ojeada? me defiendo mucho con picbasic, de c, muy poco, agradezco tu ayuda, subo los archivos esperanhttp://c3.forosdeelectronica.net/attach.gifdo tu ayuda al revisarlos, gracias


----------



## dinoelectro (Oct 31, 2012)

estas utilizando la libreria PWM.h antigua.. descargate la ultima version esta en el archivo: PWMconPOTS.rar
inteta con esa que es mucho mejor y mas optimizada, ademas incluye un manual de como utilizarla, saludos!


----------



## kiyero (Nov 11, 2012)

dinoelectro dijo:


> estas utilizando la libreria PWM.h antigua.. descargate la ultima version esta en el archivo: PWMconPOTS.rar
> inteta con esa que es mucho mejor y mas optimizada, ademas incluye un manual de como utilizarla, saludos!



Hola Dino, hice lo que me dijiste, bajé la nueva librería (la cual dejé tal cual) y modifiqué el código, pero al compilar me bota el error del archivo adjunto, podrías por favor indicarme en que he fallado? recuerda que soy novel con programación en c, gracias por tu ayuda y paciencia


----------



## jerry101 (Nov 13, 2012)

> al compilar me bota el error



El error que te aparece es porque para inicializar la libreria PWM debes utilizar Pwm_init y el otro error se debe a que para asignar el valor del ciclo util debes utilizar Write_Duty0(i); Write_Duty1(j); Write_Duty2(k); segun sea el caso. Espero haberte ayudado, este proyecto se me hizo interesante y lo he estado estudiando, tambien soy nuevo en programacion en c


----------



## kiyero (Nov 13, 2012)

jerry101 dijo:


> El error que te aparece es porque para inicializar la libreria PWM debes utilizar Pwm_init y el otro error se debe a que para asignar el valor del ciclo util debes utilizar Write_Duty0(i); Write_Duty1(j); Write_Duty2(k); segun sea el caso. Espero haberte ayudado, este proyecto se me hizo interesante y lo he estado estudiando, tambien soy nuevo en programacion en c



mi estimado jerry, muchas gracias por tu orientación, he hecho como dijiste y efectivamente compiló al 100% sin errores, y obviamente vas mas aventajado que yo en la programación en C, podrías orientarme si estás estudiando C a través de algún libro o manual específico? creo que me paso a c y dejo basic a un lado, gracias, voy a simular el resultado y postearé como me fué, saludos!!!


----------



## jerry101 (Nov 14, 2012)

Pues he estado leyendo algunos articulos en la red, apenas baje un libro que se llama ´"Compilador C CCS y simulador Proteus para controladores pic". No voy para nada aventajado, empece a leer sobre C hace 2 dias


----------



## dinoelectro (Nov 14, 2012)

kiyero dijo:


> creo que me paso a c y dejo basic a un lado, gracias



eso esta muy bien, C es un compilador mucho mas potente que basic.. a mi me ayudo mucho los tutoriales que hay en elas paginas de UControl y PICmania, tambien existe un muy buen tema aqui es forosdeelectronica, saludos


----------



## josb86 (Nov 19, 2012)

tengo una pregunta uno toma como si fueran tres leds diferentes,  entonces uno puede encenderlos al mismo tiempo (mirar imágenes adjuntas)? o tiene que esperar  apagar uno para encender otro? con respecto a las corrientes de el led,  se tiene que manejar una corriente para cada led o la corriente máxima  de todos los led es la misma?


----------



## dinoelectro (Nov 19, 2012)

josb86 dijo:


> tengo una pregunta uno toma como si fueran tres leds diferentes,  entonces uno puede encenderlos al mismo tiempo (mirar imágenes adjuntas)? o tiene que esperar  apagar uno para encender otro? con respecto a las corrientes de el led,  se tiene que manejar una corriente para cada led o la corriente máxima  de todos los led es la misma?




puedes encender todos los leds al mismo tiempo. toda la corriente se divide para tres.
yo maneje tres metros de cinta rgb con 12V, 800mA utilizando transistores MOSFET y trabaja fenomenal!


----------



## GNM (Nov 19, 2012)

me gusto mucho tu aporte la pregunta es esta, veo que estas manejando el pwm sin utilizar este modulo del pic es decir utilizas una salida digital, requiero acer algo parecido pero para controlar unos servos desde labview me podrias orientar al respecto porfavor.........


----------



## dinoelectro (Nov 20, 2012)

mira en el archivo PWMconPOTS.rar que subi anteriormente, ahi esta explicado como utilizar la libreria PWM.. te cuento que ahora estoy trabajando en esa libreria para poder generar has 12PWM simultaneamente, de seguro te servira para controlar al servo.

tratare de ayudarte en lo que este mi alcance GNM, saludos!!


----------



## GNM (Nov 20, 2012)

Gracias ahora mismo estoy bajando los correspondientes archivos, la verdad lo que requiero esque mediante una tarjeta de adquisición de datos controlar un brazo robotico, pensaba en utilizar moto reductores pero la verdad da mucha lata tener que poner etapas de potencia puentes h el doble de salidas, tu sabes un relajo total, así que me decidí por servos pero nunca e manejado servos con el método que tu *h*aces es decir PWM por software y me tenia que limitar a los 2 módulos q*ue* traen los pic comunes pero este método que tu realizaste me parece magnifico, te cuento que la tarjeta ya la tengo, maneja el estándar de comunicación USB- BULK mediante labview la dote con 8 OUT digitales 5 IN digitales 3 In análogas y 2 PWM como veras las  8 salidas *qu*edan mas que perfectas para controlar servos, el diseño del brazo robotico lo are en solid edge ya que es el que me están enseñando en la escuela y si para ese tiempo averiguo como incluir la animación en labview la incluire para que se asimile al brazo en al vida real, o tal-vez una cámara la verdad este proyecto es a largo plazo ya que planeo entregarlo como proyecto final para ingeniería en mecatrónica... iré posteando los avan*c*es q*ue* tenga contigo ya que me serviría de mucha ayuda tu asesoria ya que por lo que veo eres un genio con pic c y labview, y pues no sabre mucho de esto pero si algun dia requieres mi ayuda o nesesitas algo ya sabes en lo que podamos ayudar aquí estamos.


----------



## GNM (Nov 21, 2012)

Hola amigo otra vez por a*qu*í estu*v*e analizando tu código de la librería lo probé con unos leds y un motor ya en la vida real con el pic 18f2550 y funciona perfecta pero me metí a la hoja de datos de los servos y veo que funcionan con un tiempo de 20 ms es decir utilizando la formula f=1/t  nos daría como resultado 50 hz cre*e*s q*ue* tu librería sea capas de generar esos 50 para controlar servos?? algo mas veo q*ue* tu librería PWM controla 3 salidas es posible modificarla para controlar 5 salidas es decir 5 servos? un saludo amigo y disculpa las molestias. de antemano gracias

http://www.roboticapy.com/servo.asp

ahí es donde revise la información de los servos y sus po*s*iciones


----------



## dinoelectro (Nov 21, 2012)

GNM dijo:


> Hola amigo otra vez por aki estube analizando tu codigo de la libreria lo probe con unos leds y un motor ya en la vida real con el pic 18f2550 y funciona perfecta pero me meti a la hoja de datos de los servos y veo que funcionan con un tiempo de 20 ms es decir utilizando la formula f=1/t  nos daria como resultado 50 hz cres q tu libreria sea capas de generar esos 50 para controlar servos?? algo mas veo q tu libreria PWM controla 3 salidas es posible modificarla para controlar 5 salidas es decir 5 servos?? un saludo amigo y disculpa las molestias.... de antemano gracias
> 
> http://www.roboticapy.com/servo.asp
> 
> ahi es donde revise la info de los servos y sus pociciones



Hola GNM, la libreria puede ser configurada para generar ondas cuya frecuencia esta entre 0 y 180Hz, asi que trabajara perfecto con lo servos de 50Hz.
desde luego puedes modificar para que funcione con mas ondas PWM... uno de estos días me pongo a la tarea, cuidate


----------



## GNM (Nov 23, 2012)

si amigo me di cuenta de eso y logre modificar la libreria para que me diera 50hz en proteus anda de maravilla pongo el indicador de hz y me da de 47 a 46 hz y el servo se mueve de maravilla el problema es cuando lo paso al circuito mi servo no responde no hace nada y pues le conecte un led.... pero no me hace el efecto de cambio de brillo tan solo parpadea muy lentamente..... y es raro ya que con frecuencias mas altas como el primer ejemplo que tu pusiste me jalaba perfecto el cambio de brillo pero era una frecuencia muy alta para el servo.... Saludos amigos y gracias por tus consejos y apoyos con estos programas me han sido de gran utilidad


----------



## dinoelectro (Nov 27, 2012)

GNM dijo:


> si amigo me di cuenta de eso y logre modificar la libreria para que me diera 50hz en proteus anda de maravilla pongo el indicador de hz y me da de 47 a 46 hz y el servo se mueve de maravilla el problema es cuando lo paso al circuito mi servo no responde no hace nada y pues le conecte un led.... pero no me hace el efecto de cambio de brillo tan solo parpadea muy lentamente..... y es raro ya que con frecuencias mas altas como el primer ejemplo que tu pusiste me jalaba perfecto el cambio de brillo pero era una frecuencia muy alta para el servo.... Saludos amigos y gracias por tus consejos y apoyos con estos programas me han sido de gran utilidad




Para no percibir el parpadeo del led debes generar una onda PWM con frecuencia minima de 60Hz.  Frecuencias menores a 60Hz el ojo humano ya es capas de percibir.

si el fabricante de los servos que tu compraste te recomienda trabajar con 40hz , hazlo, aunque el led sea intermitente...


----------



## GNM (Nov 28, 2012)

A ok muchas gracias seguire tu consejo lo probare y despues te dire que tal anda muchas gracias amigo


----------



## GNM (Dic 2, 2012)

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 


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


----------



## dinoelectro (Dic 3, 2012)

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


----------



## GNM (Dic 3, 2012)

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???


----------



## dinoelectro (Dic 4, 2012)

GNM dijo:


> 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!!


----------



## GNM (Dic 5, 2012)

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??


----------



## dinoelectro (Dic 8, 2012)

GNM dijo:


> 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.


----------



## GNM (Dic 8, 2012)

Muchas gracias dino en esta semana comprare los servos y lo calare fisicamente gracias por tu ayuda estamos en contacto


----------



## GNM (Dic 14, 2012)

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....


```
#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


----------



## dinoelectro (Dic 17, 2012)

GNM dijo:


> 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!!


----------



## GNM (Dic 17, 2012)

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.


----------



## quetzal (Ene 29, 2013)

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


```
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
```


----------



## quetzal (Ene 29, 2013)

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


----------



## dinoelectro (Feb 1, 2013)

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!


----------



## GNM (Mar 12, 2013)

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


----------



## alberto0265 (Mar 29, 2013)

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.

```
//////////////////////////////////////////////////////////////////////////
////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


```
/////////////////////////////////////////////////////////////////////////////////////////////////////////////      
////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


----------



## dinoelectro (Mar 30, 2013)

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?


----------



## alberto0265 (Mar 30, 2013)

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


----------



## dinoelectro (Abr 1, 2013)

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


----------



## alberto0265 (Abr 1, 2013)

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.


----------



## alberto0265 (Abr 4, 2013)

Encontré la solución a mi caso, y porque digo esto, porque no todas las versiones de los compiladores ccs funcionan exactamente igual (referencia http://www.todopic.com.ar/foros/index.php?topic=23135.80).
Allí se discutio bien a fondo este tema y al navegar por alli encontre esta solucion a mi caso.                (Soy reiterativo,todo depende de la version del  ccs con el que compilemos el archivo fuente de aplicacion que en mi caso es PWM y aclaro que yo uso un bootloader compilado en c18 y el PWM esta compilado en ccs OK)
Este es el código y funciona


```
//////////////////////////////////////////////////////////////////////////
////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
#use delay(clock = 48000000)   
#define CH0 PIN_B5             //led ROJO conectado a rb5, cambie de pin si desea
#define CH1 PIN_B6             //led VERDE conectado a rb6, cambie de pin si desea
#define CH2 PIN_B7             //led AZUL conectado a rb7, cambie de pin si desea
#include <PWM.h>           //libreria para generar PWM de 8 bit por software 

#build(reset=0x1000,interrupt=0x1008)  //ACA ESTA EL TRUCO QUE NO ES 
#org 0x0000,0x0FFF {}                      //MIO, SOLO LO BUSQUE.Esta es una forma de remapear el 
                                                     // reset y las interrupciones para mi caso.


void main (void) 
{  
unsigned byte value;
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(AN0_TO_AN2);        //A0,A1,A2 entradas analogicas
set_tris_b(0x00);
//set_tris_d(0x03);
PWM_init(225);                    //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

    set_adc_channel(1);
    delay_us(50);  
    value=read_adc();  //lee canal AN1
    write_duty1(value);//escribe canal PWM1  
    
    set_adc_channel(2);
    delay_us(50);
    value =read_adc(); //lee canal AN2
    write_duty2(value);//escribe canal PWM2
    
    
   // output_toggle(PIN_D3); 
   // delay_ms(140); 
     }
}
```

Seguiré probando con otros códigos para ver si funciona


----------



## dinoelectro (Abr 4, 2013)

Gracias Alberto aprecio mucho tu aporte  

como tu mismo dijiste el problema esta en el vector de interrupciones


----------



## alberto0265 (Abr 10, 2013)

Aca les dejo el programa fuente para el pic12F629 que yo arme con ayuda de varios programas ajenos.
El pulsador es para buscar un color y al soltarlo quedara el color elejido por el usuario,tambien se puede 
lo puede reemplazar por un interruptor y si esta accionado se genera la secuencia de colores prefijada 
en la tabla longitud  SINE_WAVE [210].
Creo que con este pic12F629 es con el mas pequeño que podemos trabajar .



Enlace pic12F629 https://www.forosdeelectronica.com/f11/programa-pic-12f629-86129/index2.html


----------



## andresenez (Oct 27, 2013)

realice con pic un mezclador de color  automático con diodos de colores RGB se colocaron dos macros uno que cambia de rojo hasta azul, y otro que cambia de azul hasta rojo los dos macros están sincronizados y se colocaron en el puerto A de un pic 16f877 desde A0 hasta A5. espero les guste


----------



## kiyero (Sep 15, 2014)

cordial saludo estimados, he probado el código de alberto0265 y funciona a las mil maravillas, podrían por favor indicarme como lo traslado para un pic 16f628a? he tratado de hacerlo modificando el programa pero siempre me bota error, gracias de antemano :=)


----------



## damarcrazy (Mar 1, 2015)

Hola estuve mirando tu post y quisiera hacerte un par de preguntas tu nueva libreria pwm.h  funciona con pic16f628a? y con esta puedo hacer que genere colores aleatorios ?
Gracias por tu gran aporte y por la ayuda que me puedas brindar


----------



## dinoelectro (Mar 2, 2015)

Claro qu*e *se puede sin ningún problema.
Debes utilizar PINA o PINB, nunca PINC. Recuerda que el PIC16F628 no tiene puerto C.


----------



## pauloski (Mar 24, 2015)

he buscado información para la genereaciòn de pwm para controlar rgb gracias me sirvio los programas que encontre en el foro ahora no se si me puedes ayudar necesito que en vez de un pulsador o potenciometro se cambia el pwm con una orden que llegue mediante comunicacion serial por ejempli si es 1 subir pwm si es 2 bajar pwm tiene alguna idea?


----------



## SunLight (May 7, 2015)

Hola no se si este tema este obsoleto o ya nadie resuelva preguntas pero me gustaría saber si con ese código es posible obtener frecuencias mayores y de no ser así ¿creen que sea posible?


----------



## danirexa (Jun 13, 2017)

Hola, hay alguien atendiendo en este post? Quería hacer este mismo mezclador RGB pero con mi pic 16F690. Al momento de implementar el código me tira errores en varios fuses y no funciona...ayuda!


----------



## DOSMETROS (Jun 13, 2017)

Sube lo que llevas hecho : ¿Cómo *subo* imágenes y archivos?


----------



## danirexa (Jun 13, 2017)

Gracias por la respuesta DOSMETROS!

Ya no me salen esos errores con los #FUSES y me funciona. Sin embargo el problema que tengo es que después de ajustar los 3 dutys, no sale de la función nunca. Además me sale que hay excesiva carga de CPU, no se si a la hora de implementarlo me dará problema. Te adjunto el código y el diseño de proteus para ver si me puedes ayudar. Gracias!

NOTA: lo que quiero es poder enviarle desde un pc los 3 datos de RGB (de 0 a 255), y después que ajuste mediante PWM cada uno de los leds (tengo un módulo RGB) y que después salga de la función para volver a pedir otro dato.


----------



## dinoelectro (Jun 13, 2017)

Hola ya hace mucho tiempo que he dejado de programar en PIC... sin embargo aquí te dejo un ejemplo que hace exactamente lo que tu deseas pero con ARDUINO:

http://dinoelectro.blogspot.com/2017/06/dimmer-rgb-con-arduino.html?m=1

Espero te sirva, Saludos!



Hola ya hace mucho que no programo PIC; sin embargo tengo un ejemplo que hace justamente lo que tu deseas, lamentablemente es para ARDUINO utilizando el puerto serie y processing

Te dejo el enlace por si te sirve;

http://dinoelectro.blogspot.com/2017/06/dimmer-rgb-con-arduino.html?m=1


----------



## danirexa (Jun 13, 2017)

Gracias dinoelectro, creo que tu eres el que creaste la libreria PWM.h para PIC C, revisaste el código que envié para ver por qué el programa nunca sale de la función cambiar_color?
Vi la página del proyecto en arduino y la verdad te agradezco el aporte pero no me sirve de mucho...no conozco nada de arduino y el lenguaje que usa, parece más sencillo pero recién estoy empezando con picc y no entiendo nada...

Saludos y ojalá alguien pueda ayudarme.


----------

