Sensor de Temperatura y control de motor por PWM con PIC18F4550

Saludos, espero que todos se encuentren bien, bueno el motivo de este post es para pedirles ayuda ya que me encuentro desarrollando un sistema que por medio del LM35 sensa la temperatura, cuando la temperatura es menor o igual a 20 grados centigrados el motor conectado al PIC18F4550 en el temporizador 0 se encuentra apagado, cuando la temperatura esta entre 20 y 30 grados el motor debe girar al 10 o 20% y cuando sobre pase los 30 grados debe estar entre 80 y 90% del ciclo de trabajo todo esto por PWM, el problema es que no logro hacer que esto ocurra, cuando caliento a proposito el LM35 el motor enciende pero jamas para, aun enfriandose el sensor y tampoco aumenta mas la velocidad, espero que me puedan ayudar, les dejo el codigo que tengo hasta ahora

Código:
#include <p18cxxx.h>

/****************  Bits de Configuracion *************************************/
#pragma config PLLDIV   = 5         // (20 MHz crystal on PICDEM FS USB board)
#pragma config CPUDIV   = OSC1_PLL2	
#pragma config USBDIV   = 2         // Clock source from 96MHz PLL/2
#pragma config FOSC     = HSPLL_HS
#pragma config FCMEN    = OFF
#pragma config IESO     = OFF
#pragma config PWRT     = OFF
#pragma config BOR      = ON
#pragma config BORV     = 3
#pragma config VREGEN   = ON		//USB Voltage Regulator
#pragma config WDT      = OFF
#pragma config WDTPS    = 32768
#pragma config MCLRE    = ON
#pragma config LPT1OSC  = OFF
#pragma config PBADEN   = OFF
#pragma config CCP2MX   = ON
#pragma config STVREN   = ON
#pragma config LVP      = OFF
#pragma config ICPRT    = OFF       // Dedicated In-Circuit Debug/Programming
#pragma config XINST    = OFF       // Extended Instruction Set
#pragma config CP0      = OFF
#pragma config CP1      = OFF
#pragma config CP2      = OFF
#pragma config CP3      = OFF
#pragma config CPB      = OFF
#pragma config CPD      = OFF
#pragma config WRT0     = OFF
#pragma config WRT1     = OFF
#pragma config WRT2     = OFF
#pragma config WRT3     = OFF
#pragma config WRTB     = ON       // Boot Block Write Protection
#pragma config WRTC     = OFF
#pragma config WRTD     = OFF
#pragma config EBTR0    = OFF
#pragma config EBTR1    = OFF
#pragma config EBTR2    = OFF
#pragma config EBTR3    = OFF
#pragma config EBTRB    = OFF


//*Este programa prueba el hardware de la tarjeta con el bootloader 
#define MOTOR           LATAbits.LATA4
#define ALERT			LATAbits.LATA5


/************************  Entradas Digitales ***********************************/
#define mInitAllSwitches()  TRISBbits.TRISB4=1;TRISBbits.TRISB5=1;
#define mInitSwitch2()      TRISBbits.TRISB4=1;
#define mInitSwitch3()      TRISBbits.TRISB5=1;
#define sw2                 PORTBbits.RB4
#define sw3                 PORTBbits.RB5


/*********************** V A R I A B L E S **************************************/
#pragma udata
int x=0;
int temperatura=0;  //Temperatura
int a;
int m1,c1,d1,u1;


//****************** DEFINICON DE ALGUNAS CONSTANTES ****************************/
#define TIMER0H_VAL         0xF4
#define TIMER0L_VAL         0x48
/*
#define NIVEL1  40
#define NIVEL2  44
#define NIVEL3  48
#define NIVEL4  52 
#define NIVEL5  56
#define NIVEL6  60
#define NIVEL7  64
#define NIVEL8  68
#define NIVEL9  72 
#define NIVEL10 76
#define NIVEL11 80
*/
#define NIVEL1  0
#define NIVEL2  201
#define NIVEL3  301


/*******************  DECLARACION DE LOS PROTOTIPOS *******************************/
void YourHighPriorityISRCode(void);
void YourLowPriorityISRCode(void);
void cfgPuertos(void);
void cfgtemp0(void);
void CfgADC(void);
int getADC1(void);
void configUSART(void);
void TXbyte(unsigned char data);
//void Mi_delay(void);
void EEPROM_Write(unsigned char address,unsigned char databyte);

/******************** VECTOR  REMAPPING *******************************************/
		#define REMAPPED_RESET_VECTOR_ADDRESS			0x1000
		#define REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS	0x1008
		#define REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS	0x1018

/*********************************************************************************/
extern void _startup (void);        // See c018i.c in your C18 compiler dir
#pragma code REMAPPED_RESET_VECTOR = REMAPPED_RESET_VECTOR_ADDRESS
void _reset (void)
{
    _asm goto _startup _endasm
}

/*********************************************************************************/
#pragma code REMAPPED_HIGH_INTERRUPT_VECTOR = REMAPPED_HIGH_INTERRUPT_VECTOR_ADDRESS
void Remapped_High_ISR (void)
{
     _asm goto YourHighPriorityISRCode _endasm
}

/*********************************************************************************/
#pragma code REMAPPED_LOW_INTERRUPT_VECTOR = REMAPPED_LOW_INTERRUPT_VECTOR_ADDRESS
void Remapped_Low_ISR (void)
{
     _asm goto YourLowPriorityISRCode _endasm
}

/*********************************************************************************/
#pragma code

//********************  VECTOR DE ALTA PRIORIDAD   *******************************/
#pragma interrupt YourHighPriorityISRCode
void YourHighPriorityISRCode()
{		
 if(INTCONbits.TMR0IF==1)
   {
 	x++;
	TMR0H=TIMER0H_VAL;
	TMR0L=TIMER0L_VAL;
	INTCONbits.TMR0IF=0;
   }
}	//This return will be a "retfie fast", since this is in a #pragma interrupt section 

//*****************  VECTOR DE INTERRUPCION BAJA PRORIDAD  ***********************/
#pragma interruptlow YourLowPriorityISRCode
void YourLowPriorityISRCode()
{
	//AGREGAR CODIGO
}	

/************************  PROGRAMA PRINCIPAL  ************************************/
/**********************************************************************************/
void main (void)
{
 CfgADC();
 configUSART();
 cfgPuertos();
 cfgtemp0();
 
 while(1)
 {
    temperatura=getADC1();
    m1=temperatura/1000;            //
    c1=(temperatura%1000)/100;      //
    d1=(temperatura%1000%100)/10;   //
    u1=temperatura%1000%100%10;	   //   Se manda el valor obtenido por el getADC1() (temperatura)
    TXbyte('t');                    //   hacia la PC y sea mostrado en la interfaz.
    TXbyte(m1+48);                  //
    TXbyte(c1+48);                  //
    TXbyte(d1+48);                  //
    TXbyte(u1+48);                  //

  if(temperatura==NIVEL1)                              //    
      { a=0; }                                         //    
  if((temperatura>NIVEL1)&&(temperatura<=NIVEL2))      //
	  { a=1; } 							                      //
  if((temperatura>NIVEL2)&&(temperatura<=NIVEL3))      //
	  { a=2; }		                                     //
  												      //
		                                                  //   Se realizan comparaciones con el valor obtenido en el getADC1() (lee
			 									      //   la señal obtenida del LM35) y los niveles definidos anteriormente;
	 		  					                      //   de esta manera se controla el valor del PWM estableciendole valores a
  												     //   la variable 'a'.


  //------------------------- Se realizan las operaciones para controlar el PWM -----------------------------------
  x=0;

     while(x<10)
	  	  {
		   if(x<a)
		      MOTOR=1;
		   else
			  MOTOR=0;
		  }

  if(a==0)
    {
     MOTOR=0;
    }
  //x=0;
  }
}

/*********************************************************************************/
void cfgPuertos(void)
{
 ADCON1 |= 0x0E; // RA0 se configura como la terminal analógica AN0.
 TRISA=0x01;  // RA0(AN0) es entrada y las demas son salidas.
 LATA=0x00; // Todos los leds estarán apagados.
 //TRISC=0x00;  // Puerto C, todos se utilizan como salida.
 LATC=0x00;  // Se inicializa todo el puerto C en 0.
 TRISB = 0b00110000;
}

/*********************************************************************************/
void cfgtemp0(void)
{
	INTCONbits.TMR0IF=0;
	TMR0H = TIMER0H_VAL;
	TMR0L = TIMER0L_VAL;
	T0CON = 0b10001000;
	INTCON = 0xA0; //habilita interrupciones
}

/*********************************************************************************/
void CfgADC(void)  //Configuración para el convertidor Analógico - Digital
{
 ADCON0=0x00;  // La señal de entrada del ADC se lee en AN0.
 ADCON2=0x8C;  // Configura el reloj del ADC y el tiempo de adquisición.
 ADCON0bits.ADON=1; // Enciende el ADC.
}

/*********************************************************************************/
int getADC1(void)  //Función que obtiene los datos de la señal analógica leida
{
 int resultado;  //Se declara la variable resultado de la funcion getADC();
 ADCON0bits.GO = 1;  // Inicio de conversión.
 while(ADCON0bits.NOT_DONE); // Espera se termine la conversión.
 resultado = (int)(ADRESH*256)+ADRESL;  // 
 return resultado;  //Se regresa el valor de la variable resultado
}

/*********************************************************************************/
void configUSART(void)
{
	unsigned char temp;
	SSPCON1 = 0;        // Asegura que el módulo SPI no esté habilitado
    TRISCbits.TRISC7=1; // Entrada de datos - terminal Rx
    TRISCbits.TRISC6=0; // Salida de datos - terminal Tx
    SPBRG = 103;		// Configura 9600 bauds para Fosc de 48 MHz     // SPBRG = 255;		// Configura 9600 bauds para Fosc de 48 MHz
    SPBRGH = 0;         // (SPBRG=103 y SPBRG=0 para 115 kbps)          //SPBRGH = 4;       // (SPBRG=103 y SPBRGH=0 para 115 kbps)
    TXSTA = 0x24;       // Habilita modo de 16 bits con BRGH=1
    RCSTA = 0x90;       // Recepción continua en Rx
    BAUDCON = 0x08;     // BRG16 = 1
    temp = RCREG;       // Limpia registro del receptor (hacerlo 2 veces)
    temp = RCREG;       //RCREG = buffer del receptor
}

/*********************************************************************************/
void TXbyte(unsigned char data)
{
    while(TXSTAbits.TRMT==0);
    TXREG = data;		//TXREG = buffer del transmisor
}

/*********************************************************************************/
void EEPROM_Write(unsigned char address,unsigned char databyte) //Función para escribir un databyte
{                                                               //en la localidad address de la EPROM
 EECON1bits.EEPGD=0;
 EECON1bits.CFGS=0;
 EEDATA=databyte;
 EEADR=address;
 EECON1bits.WREN=1;
 EECON2=0x55;
 EECON2=0xAA;
 EECON1bits.WR=1;
 while(EECON1bits.WR==1);
 EECON1bits.WREN=0;

como dato adicional el motor esta conectado a un IRF540 que esta conectado al temporizador 0 del pic
 
Creo que encontré algunos problemas, nose si serán todos.
Primero los niveles están en cualquier rango:
0
201
301
debería ser
algún 20 y algún 30
el cero no importa
Segundo las comparaciones:
if(temperatura<NIVEL2) //
{ a=0; } //
if((temperatura>=NIVEL2)&&(temperatura<=NIVEL3)) //
{ a=3; } //
if((temperatura>NIVEL3)) //
{ a=10; }

Tercero:
x=0;
while(x<10)
{
if(x<a)
MOTOR=1;
else
MOTOR=0;
}

SIN ESTO:if(a==0)
{
MOTOR=0;
}
 
Código:
     while(x<10)
	  	  {
		   if(x<a)
		      MOTOR=1;
		   else
			  MOTOR=0;
		  }
No me cerro tu control PWM. Primeo que en ese while se va a quedar hasta que se den 10 interrupciones del TMR0. Tampoco veo los % wque pones porque estas comparando 10 contra, 0, 1 y 2.
Yo lo haria diferente el control. El PWM lo generaria en el servicio de interrupcion.
De la siguiente forma:
Código:
void YourHighPriorityISRCode()
{		
 if(INTCONbits.TMR0IF==1)
   {
 	x++;

        if(a>x){
              MOTOR =1;
         
        }else{
              MOTOR = 0;
        
        }

	TMR0H=TIMER0H_VAL;
	TMR0L=TIMER0L_VAL;
	INTCONbits.TMR0IF=0;
   }
}

Y definira a x como unsigned char, y a, tambien como unsigned char, y en vez de los valores 0,1,y 2, los remplaria segun elñ %. Osea si queres un 100% de ciclo util a=255.

Asi te queda mas libre el micro para el programa principal, aunque te puede quedar una frecuencia baja en el PWM, fijate, de ultima la podes aumentar cambiando x, para que cuente menos.

Y otra forma mejor aun es usar alguno de los PWM que ya incorpora el micro.
 
muchas gracias por responder tan pronto, bueno, ya hice algunas de las correcciones que me dijeron, pero el problema sigue igual :S, Ars no entiendo muy bien a que te refieres con:
Y definira a x como unsigned char, y a, tambien como unsigned char, y en vez de los valores 0,1,y 2, los remplaria segun elñ %. Osea si queres un 100% de ciclo util a=255.
que diferencia hay y como puedo hacer la escala que necesito basado en lo que mencionas?, de nuevo muchas gracias por todo ; )



bueno, no sigue del todo mal, después de un buen rato (como 10 min.) el motor si se para, pero no puedo hacer que acelere al 80 o 90%, ¿como puedo bajar el tiempo de respuesta?
 
Última edición:
Si x es un unsigned char, vas a poder tomar valores de 0 a 255. Vos con a estas determinando el ciclo util de tu pwm, asi que 255 corresponderia al 100% de ciclo util.
El 20%seria 20*255/100=74.625=>75, osea que a=75, y asi calculas los otros.
Si queres lo podes hacer valer de 0 a 10 a x, pero tenes que chequear que cuando llegue a 10 ponerla a 0. De la otra forma autamticamente pasa a 0 porque llego al final de la cuenta.

De todos modos me parece mejor idea usar el modulo que ya incorpora el micro.
 
Última edición:
lo se, pero es muy necesario hacerlo con el temporizador, es que es un proyecto escolar :S, voy a intentar lo que me dices



sobre el tiempo que tarda en reaccionar al cambio de temperatura como lo controlo?
 
Última edición:
lo se, pero es muy necesario hacerlo con el temporizador, es que es un proyecto escolar :S, voy a intentar lo que me dices



sobre el tiempo que tarda en reaccionar al cambio de temperatura como lo controlo?
La respuesta va a ser ni bien se termina de realizar la lectura del nuevo valor de temperatura. Y se actualiza el valor de a.
 
Última edición:
Si queres lo podes hacer valer de 0 a 10 a x, pero tenes que chequear que cuando llegue a 10 ponerla a 0. De la otra forma autamticamente pasa a 0 porque llego al final de la cuenta.
Eso mismo es lo que hace el programa

Fijate si seteaste bien los valores de temperatura, y si pusiste bien las comparaciones y si cambiaste correctamente los valores de a.
El tiempo de reaccion es de el periodo de tu PWM, o 10 ciclos de tu timer. porque antes de cada ciclo de pwm realiza la lectura de cuanto tiene y setea el valor de a.
 
Atrás
Arriba