Autor Tema: Pwm por software  (Leído 5153 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Byakuya

  • PIC10
  • *
  • Mensajes: 38
Pwm por software
« en: 14 de Junio de 2015, 08:32:08 »
Hola que tal, quien me echa una mano para traducir esto a CCS... yo no entiendo mucho ensambler. :(...Saludos excelente dia.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Pwm por software
« Respuesta #1 en: 14 de Junio de 2015, 16:05:00 »
traducir no .. pero te puedo decir masomenos lo que hace.. es mas... el tipo ese la complico en grande.. no se cual fue su objetivo.

Deberias buscar por el foro sobre PWM por soft... Hay miles de ejemplo, creo que yo hasta lo explique como 3/4 veces
Aca un ejemplo http://www.todopic.com.ar/foros/index.php?topic=44604.0

esta en XC8, pero es C, y por lo tanto deberia ser mucho mas facil de portar.

PD: tambien te adjunto el programa qie pasaste en ASM pero con comentarios en C. Lo unico que no comente tanto es el tema de la configuracion de puertos.

« Última modificación: 14 de Junio de 2015, 17:55:57 por KILLERJC »

Desconectado Byakuya

  • PIC10
  • *
  • Mensajes: 38
Re: Pwm por software
« Respuesta #2 en: 14 de Junio de 2015, 22:53:54 »
Gracias amigo por tu pronta respues desde luego que sí el tipo se complica  :-/ . Realmente lo que realiza el programa si lo montas en algun simulador o protoboard son pwms por software, yo no uso mucho ensambler y por ende me es un poco dificil seguir el programa, me llamo la atencion!. De echo mi desafio es demultiplexar pwm (El tal llamado shift_pwm como lo hace esta libreria que aqui dejo un buen trabajo  http://www.elcojacobs.com/shiftpwm/   :5] Demasiada teoria a mi para llegar hacer algo como esto. en fin me gustaria llevarlo a CCS Algo de ayuda no me caeria nada mal ), gracias y un saludo. KILLERJC  ((:-))

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Pwm por software
« Respuesta #3 en: 14 de Junio de 2015, 23:38:11 »
En si.. la teoria no es grande...

Lo que se hace es primero definir la frecuencia del PWM para saber el periodo de la onda.. suponete que la onda sea de 1 segundo es decir 1Hz

Luego tenes que buscar la cantidad de pasos que va a tener tu PWM, lo ideal es que sean valores de 2^n , es decir 8,16,32,64,128,256,etc

Entonces lo que haces es dividir ese segundo por la cantidad de pasos y usar un timer para que en ese tiempo entre a la interrupcion. Ej: siguendo con el de 1 segundo y 128 pasos, 1s /128 = 7.8125ms

Una ves que tenes eso podes agregarlo 50 PWM siempre y cuando pueda activar todo en el tiempo ese.
Entonces tu interrupcion del timer va a entrar, comenzando de 0 y va a sumar 1 cada ves que entre, cuando llegue a 128 se pone a 0 ( es decir va de 0 a 127 que es lo mismo que 128 posiciones)

Tus pwm luego vas a preguntar por cada uno... lo explico con un codigo y 2 pwm

//Aca cargo de nuevo mi timer asi se produce la interrupcion nuevamente a ese valor
pwm1=50;
pwm2=100;
timer++;
if (timer == 128 ) {timer=0;}

if ( pwm1<timer ) {salidapwm1 = 1;} else {salidapwm1 = 0;}
if ( pwm2<timer ) {salidapwm2 = 1;} else {salidapwm2 = 0;}


Ese seria todo el codigo es decir de 0 a pwm va a estar en 1 y luego se pone a 0, asi hasta que comienza de nuevo


Ahora entendiendo lo que acabo de explicar arriba. podes hacer algo parecido con un shift register como el del link.
En cada interrupcion transmitis cada una de esas salidas por 1 solo pin y luego actuara otro pin para que no cambie el valor del shif register ( latch )
Pero el concepto es el mismo, lo unico que puede cambiar es la frecuencia ya que debe necesitar un poco mas de tiempo para enviarlo, lo cual te limita a que el periodo del PWM sea mas largo, o que es lo mismo una frecuencia mas baja

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re: Pwm por software
« Respuesta #4 en: 14 de Junio de 2015, 23:47:05 »
CCS ya tiene un PWM por software, hay que escribir muy poco... :mrgreen: :mrgreen:

Tech Note: Software PWM - A Simple and Effective Alternative to CCP For PCM and PCH Compilers
Thursday 04 December, 2014
The CCS C Compiler pulse width modulation (PWM) library (#use pwm()) has been improved to provide software, bit-banged PWM control over any I/O pin without limitations. This new feature provides accurate PWM as well as customizable setup for period, frequency, duty cycle, and more... There are three unique features that make it versatile; setting it apart from using the hardware PWM peripheral:
The ability to assign multiple output pins to the same signal
The ability to explicitly set logic level of the output (or outputs) when the PWM is inactive
The tristate operating mode

Setting up the software PWM is simple and easy. Any desired options for duty cycle, period, frequency, etc. may be set while only using one line of code. Below is an example that illustrates the setup of a typical PWM with two outputs, a frequency of 1 kHz, and a duty cycle of 75%.

#use pwm(output=pin_a4, output=pin_b3, timer=1, frequency=1kHz, duty=75)

The signal will now output on both pins A4 and B3. Adding or removing more output pins is as simple as adding or removing output=X options.

Once running, the function pwm_set_duty_percent() may be used to change duty cycle. A stream identifier may be used in the #use pwm(), and other PWM functions, which allow multiple PWM pins to operate at the same time.

When disabled, the output pins of the Software PWM are capable of holding specific logic levels: high, low, and input. These options make the software PWM dependable even while disabled. The option to designate a specific disable level, may be added to the setup. Below is an example that designates a disable level using the PWM which was set up previously.

#use pwm(output=pin_a4, output=pin_b3, timer=1, frequency=1 kHz, duty=75, disable_level=low)

Now, whenever the built-in function pwm_off() is called, both pins a4 and b3 will be driven low.

An alternate operating mode for the software PWM is the tristate mode. In tristate mode, the compiler will force all output pins, associated with the PWM signal, to become inputs during the duty high time - instead of forcing them high. Activating tristate mode requires that only one simple option, 'tristate', be added to the setup.

The CCS C-Aware IDE will display a message indicating the output of the software PWM just as it does with hardware PWM. This feature is useful since the compiler may not be able to hit the exact frequency desired due to speed or processing limits of the target microcontoller used. Using the code from the examples above, the following is the message displayed by the IDE at compile time as well as the actual output as observed using a logic analyzer:


IDE message containing information on the Software PWM output


The actual output of the Software PWM


La nota esta aqui:
https://www.ccsinfo.com/newsdesk_info.php?newsPath=ALL&newsdesk_id=182
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado Byakuya

  • PIC10
  • *
  • Mensajes: 38
Re: Pwm por software
« Respuesta #5 en: 15 de Junio de 2015, 00:47:37 »
Probando mas sin embargo eh realizado esto por el momento gracias a la teoria descrita del amigo KILLER Reporto codigo realizado hasta ahora si algo se me pasa.  :shock: disculpar tengo mucho sueño  :mrgreen: , aqui EN MEXICO ya es demasiado tarde :) adjunto codigo hasta el momento.. mi ambicion el pwm con 74HC595. saludos colegas, y si alguien me puede ayudar gracias..

#include <12f629.h>
#use     delay(clock = 4mhz) 
#fuses   intrc_io,nowdt,noprotect,noput,nomclr,nobrownout,nocpd

#define rojo   pin_a0
#define verde pin_a1
#define azul   pin_a4

int8 contador,red,green,blue,i,red1,green1,blue1;
                     
#int_timer0
void timer0_isr()
{
   contador = contador + 5;
   if (contador > 254)
   {contador = 0;}
   if( contador < red1   )   output_high(rojo)   else output_low(rojo);   
   if( contador < green1 )  output_high(verde) else output_low(verde);
   if( contador < blue1  )    output_high(azul)   else output_low(azul);
}

void main (void)
{
setup_timer_0(rtcc_internal | rtcc_div_1 | rtcc_8_bit);
enable_interrupts (int_rtcc);           
enable_interrupts (global);             
set_timer0(255);                    //interrupcione
for(;;)
 {
   red1     = 100;
   green1   = 5;
   blue1    = 250;
 }
 while(1);
}
« Última modificación: 15 de Junio de 2015, 07:52:39 por Byakuya »

Desconectado Byakuya

  • PIC10
  • *
  • Mensajes: 38
Re:Pwm por software
« Respuesta #6 en: 03 de Noviembre de 2015, 20:38:18 »
Hola amigos del foro disculpar que les interrumpra de sus actividades. un poco apagado yo,, desde hace unos dias para aca. echarle una leidita sugerencias, ideas sera bien aceptadas.  :-/ 
Este codigo funciona bien cuando se trata pin a pin dentro del microcontrolador pero cuando se agrega un registro desplazamiento serial a paralelo no funciona del todo bien :( Alguna idea? 

 http://www.elcojacobs.com/shiftpwm/ 


Código: [Seleccionar]

#INCLUDE <12F629.h>
#FUSES   INTRC_IO,NOWDT,NOPUT,MCLR,NOBROWNOUT,NOCPD,NOPROTECT
#USE     DELAY(CLOCK = 4MHZ)

#DEFINE  DATA   PIN_A1     //PIN_14
#DEFINE  CLOCK  PIN_A2     //PIN_11   
#DEFINE  STROBE PIN_A4     //PIN_12

#INCLUDE "SECUENCIA.h"

UNSIGNED INT8 BUFFER[8] = {0};
UNSIGNED INT8 FILA1 = 1,FILA2 = 0,VECES,Y,TEMP;

#INT_TIMER0
VOID ISR_TIMER0 (VOID)
{
 SIGNED INT8 W;
 FOR(W = 8; W >= 0; W--)     //SERAN DOS REGISTROS
 {
  IF(BUFFER[W] & FILA1)       //SI ESTA AND SE CUMPLE SE ENVIA DATO POR PIN
    OUTPUT_HIGH(DATA);
  ELSE
    OUTPUT_LOW(DATA);
   OUTPUT_LOW(CLOCK);          //EL DATO SE CARGARA DE BAJO A ALTO DATO VALIDO
  OUTPUT_HIGH(CLOCK);
 }
 OUTPUT_HIGH(STROBE);         //SE MUESTRA EL DATO ALMACENADO EN EL REGISTRO
  OUTPUT_LOW(STROBE);          //NO SE MUESTRA DATO ALMACENADO EN EL REGISTRO
 FILA1 <<= 1;                 //EL DATO SE DESPLAZA AHACIA LA IZQUIERDA
 FILA2 += 1;
 IF(FILA2 > 8)             
 {
  FILA2 = 0;
  FILA1 = 1;
 }
 SET_TIMER0(248);                 
}

UNSIGNED INT8 CONTADOR;
#INT_TIMER1
VOID ISR_TIMER1 (VOID)
{
   IF (CONTADOR < BUFFER[0]) { BUFFER[0] = 1;} ELSE BUFFER[0] = 0;
   IF (CONTADOR < BUFFER[1]) { BUFFER[1] = 1;} ELSE BUFFER[1] = 0;
   IF (CONTADOR < BUFFER[2]) { BUFFER[2] = 1;} ELSE BUFFER[2] = 0;
   IF (CONTADOR < BUFFER[3]) { BUFFER[3] = 1;} ELSE BUFFER[3] = 0;
   IF (CONTADOR < BUFFER[4]) { BUFFER[4] = 1;} ELSE BUFFER[4] = 0;
   IF (CONTADOR < BUFFER[5]) { BUFFER[5] = 1;} ELSE BUFFER[5] = 0;
   IF (CONTADOR < BUFFER[6]) { BUFFER[6] = 1;} ELSE BUFFER[6] = 0;
   IF (CONTADOR < BUFFER[7]) { BUFFER[7] = 1;} ELSE BUFFER[7] = 0;
   CONTADOR++;
   SET_TIMER1(10036);
}

VOID WRITE_DUTY(CH,VALUE)
{
  SWITCH(CH)
   {
   CASE 0: BUFFER[0] = VALUE; BREAK;  //LED0
   CASE 1: BUFFER[1] = VALUE; BREAK;
   CASE 2: BUFFER[2] = VALUE; BREAK;
   CASE 3: BUFFER[3] = VALUE; BREAK;
   CASE 4: BUFFER[4] = VALUE; BREAK;
   CASE 5: BUFFER[5] = VALUE; BREAK;
   CASE 6: BUFFER[6] = VALUE; BREAK;
   CASE 7: BUFFER[7] = VALUE; BREAK;  //LED7
   }
}   


VOID EFECTO3(VOID)
{
FOR(VECES=0;VECES<4;VECES++)                 //REPETIR EFECTO 0 E INCREMENTAR
    {
     FOR(Y=0;Y<15;Y++) {    //15*8 = 120 EFECTO3
         TEMP = Y * 8;
         WRITE_DUTY(0,SECUENCIA3[TEMP+0]);
         WRITE_DUTY(1,SECUENCIA3[TEMP+1]);
         WRITE_DUTY(2,SECUENCIA3[TEMP+2]);
         WRITE_DUTY(3,SECUENCIA3[TEMP+3]);
         WRITE_DUTY(4,SECUENCIA3[TEMP+4]);
         WRITE_DUTY(5,SECUENCIA3[TEMP+5]);
         WRITE_DUTY(6,SECUENCIA3[TEMP+6]);
         WRITE_DUTY(7,SECUENCIA3[TEMP+7]);
         DELAY_MS(50);
         }
      }
}


VOID MAIN (VOID)
{
 SETUP_TIMER_0(T0_INTERNAL | T0_DIV_128 | T0_8_BIT);   //ENVIO REGISTRO
 SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_4);     
 ENABLE_INTERRUPTS(INT_TIMER0);
 ENABLE_INTERRUPTS(INT_TIMER1);
 ENABLE_INTERRUPTS(GLOBAL);      //HABILITA INTERRUPCION GLOBAL
 SET_TIMER0(248); //T0 = 2MS
 SET_TIMER1(10036);  //4MS
 FOR(Y=0; Y<8; Y++) { BUFFER[Y] = 255 - BUFFER[Y]; WHILE(FILA2 == 0);}
 FOR(;;) {
  EFECTO3();
 }
}

#RESERVE 0x03FF
#ROM 0x03FF = {0x3420}


ARchivo secuencia

CONST UNSIGNED INT8 SECUENCIA3[120]={
                      250,  1,  1,  1,  1,  1,  1,  1,       //0
                       40,250,  1,  1,  1,  1,  1,  1,       //1
                        1, 40,250,  1,  1,  1,  1,  1,        //2
                        1,  1, 40,250,  1,  1,  1,  1,        //3
                        1,  1,  1, 40,250,  1,  1,  1,        //4
                        1,  1,  1,  1, 40,250,  1,  1,        //5
                        1,  1,  1,  1,  1, 40,250,  1,        //6
                        1,  1,  1,  1,  1,  1, 40,250,     //7
                        1,  1,  1,  1,  1,  1,250, 40,    //8
                        1,  1,  1,  1,  1,250, 40,  1,    //9
                        1,  1,  1,  1,250, 40,  1,  1,   //10
                        1,  1,  1,250, 40,  1,  1,  1,  //11
                        1,  1,250, 40,  1,  1,  1,  1,  //12
                        1,250, 40,  1,  1,  1,  1,  1,  //13
                      250, 40,  1,  1,  1,  1,  1,  1,  //14
                        };



« Última modificación: 03 de Noviembre de 2015, 20:42:54 por Byakuya »

Desconectado AcoranTf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1093
Re: Pwm por software
« Respuesta #7 en: 02 de Mayo de 2016, 09:30:42 »
CCS ya tiene un PWM por software, hay que escribir muy poco... :mrgreen: :mrgreen:

#use pwm(output=pin_a4, output=pin_b3, timer=1, frequency=1kHz, duty=75)

The signal will now output on both pins A4 and B3. Adding or removing more output pins is as simple as adding or removing output=X options.

La nota esta aqui:
https://www.ccsinfo.com/newsdesk_info.php?newsPath=ALL&newsdesk_id=182

Hola Marcos, estoy intentando utilizar el PWM por software para unas pruebas que estoy haciendo.  Pertenecen a un proyecto que estoy estudiando poco a poco. Pero me encuentro un problema y es que NO duplica las salidas, como, entiendo por las lineas que he dejado de tu comentario, deberia hacer.
Funciona todo correctamente, pero no duplica la señal del PWM y me hace falta, ya que pretendo controlar el puente H, con cuatro pines del PIC18F1220. Dos de esos pines activaran los transistores altos del puente, uno en cada semiciclo de la señal de 50 Hz. Y los otros dos, que son los que sacan el PWM, controlaran los dos transistores bajos del puente, aplicandoles precisamente la señal PWM a cada uno segun corresponda. (Mientras escribia acabo de darme cuenta que es igual tener dos pines con la misma señal, que poner las dos entradas LIN de los dos 2110 en paralelo y por tanto habria un conflicto, ya que se activarian a la vez los dos transistores de una misma rama del puente H, provocando un cortocircuito entre ellos y su destruccion). Ya habia realizado otras pruebas, consistentes en agregar dos puertas and, de modo que cada una tenga una entrada a la señal que controla el transistor alto contrario y la otra entrada ambas puenteadas a la señal PWM y cada una de las salidas a la entrada LIN de cada 2110. Pero esto me da otro "extraño" problema, la señal PWM es de 50 Hz directamente y no de 5000 Hz como deberia. A esto ultimo le he dado mil vueltas y no consigo ver donde esta el problema.
Bueno a ver si cualquiera de vosotros que tenga mas experiencia con este tema me puede echar una manita. Voy a subir los archivos tanto de Proteus, como de CCS de ambos casos a mi servidor, para que asi lo entendais mejor.

Aqui: www.yaitana.es/temp/pwm.zip estan.

Saludos.

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7912
Re:Pwm por software
« Respuesta #8 en: 02 de Mayo de 2016, 11:44:15 »
Si lo que quieres es manejar un motor de pasos, lo mejor es usar los micros que ya los tienen, o un driver especializado, de otro modo si se superponen las señales, vas a tener problemas de cortocircuitos que harán volar la electrónica de potencia.
Hay DSPIC Y PICs con esas caracteristicas y tambien driver de potencia para esa aplicación en el catalogo de Microchip.
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado AcoranTf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1093
Re:Pwm por software
« Respuesta #9 en: 02 de Mayo de 2016, 21:16:23 »
Si lo que quieres es manejar un motor de pasos, lo mejor es usar los micros que ya los tienen, o un driver especializado, de otro modo si se superponen las señales, vas a tener problemas de cortocircuitos que harán volar la electrónica de potencia.
Hay DSPIC Y PICs con esas caracteristicas y tambien driver de potencia para esa aplicación en el catalogo de Microchip.

No es para motores Marcos, es para un inversor DC/AC con salida senoidal pura. El PIC18F1220, que es el que quiero utilizar tiene la posibilidad de manejar un puente H directamente, pero por lo que he podido ver leyendo y probando en el Proteus, creo que no vale para lo que yo necesito. Aunque le voy a echar otro vistazo a ver si ahora que he estudiado mejor el tema, puedo ponerlo a funcionar con ese sistema.
Ya comentare como me va.

Saludos.