/*********************************************************************
**Control analógico de un horno de reflujo para soldadura SMD y **
**BGA, este código está implementado para el componente MAX6675 y **
**un microcontrolador PIC16F876A, utilizando el protocolo SPI por **
**hardware + la entrada analógica digital del micro, donde conectamos**
**un potenciómetro con el cuál regularemos el ancho de pulso de **
**una señal en PWM **
**El autor y propietario del código Thulsa_Doom autoriza su libre **
**distribución, copia y modificación del mismo siempre y cuando se **
**mencione al autor **
**********************************************************************
-------------------------------PATILLAJE-------------------------------------
--PIN-2;A0 = Entrada analógica donde conectamos el potenciómetro --
--PIN-6;A4 = Donde conectamos el pulsador por medio de resistencias Pull-UP--
--PIN-7;A5 = Señal CS o bit-select hacia el MAX6675 PIN-6 --
--PIN-13;C2 = Salida de la señal PWM --
--PIN-14;C3 = Salida de reloj para el MAX6675 PIN-5 --
--PIN-15:C4 = Entrada de dato de temperatura que proviene PIN-7 MAX6675 --
-----------------------------------------------------------------------------
*/
// Declaraciones de Post-Procesado
#include <16f876a.h>
#device adc=10
#FUSES xt,nowdt,noprotect
#USE delay(clock=4000000)
#define use_portb_lcd TRUE
#include <LCD.C>
#use standard_io (A)
#use standard_io (B)
#use standard_io (C)
#use SPI(MASTER,FORCE_HW,MODE=0,BITS=16)
//****************************Definición de pines**********************************
#define CS PIN_A5
//******************************Variables Globales***********************************
long ad,buffer; //Variable que proviene del modulo analógico/digital
//con el dato del potenciómetro y lo cargamos la función PWM
int msec=0,sec=0,min=0;
int swicht;
float temperatura=0;
//***************************Interrupciones de los timers**************************
#int_TIMER1
void imprimir_cronometro(){
set_timer1(55661);
if(swicht==1){ //Si la variable swicht es igual a 1, se ejecuta el cronómetro
if(msec++>99){ //incrementa el valor de msec y si es mayor a 99
msec=0; //pone msec a 0.
if(sec++>58){ //incrementa el valor de sec y si es mayor de 59
sec=0; //ponesec a 0.
if(min++>60){
min=0;
}
}
}
}
else{ //Si la variable siwcht no es igual a 1 se pone a 0 mse, sec, min
msec=0;
sec=0;
min=0;
}
}
//****************************Inicialización**************************************
void inicializar(){ //Ejecutamos una rutina de inicialización para que
//los valores se estabilizan antes de mostrarlo en pantalla
printf(lcd_putc,"\fInicializando\n Sistema");
delay_ms(500);
}
//******************************Subprogramas************************************
void leer_termocupula(){
int16 temp;
int cadena1,cadena2; //declaramos las variables donde se guardaran el dato que viene del max6675
//el dato viene en dos paquetes separados de 8 bits, por eso se guardan en dos cadenas
delay_ms(200);
output_low(CS); //Se activa la señal de bit_select(CS) a 0 para que el max se active
cadena1 = spi_read(0); //Lee el primer byte que viene del max6675
cadena2 = spi_read(0); //Lee el segundo byte, con eso ya tenemos los 16bits de la lectura del max7765
output_high(CS); //Se pone a 1 la señal de bit_select(CS) para que el max tome otra lectura
// buffer = ((cadena1 * 256) + cadena2); //Se unen las dos cadenas de 1 byte que viene del max6675 y se
//guardan en una variable int16 llamada buffer de 16 bits
buffer = cadena2; // Cargo Byte LB
*((char *)&buffer+1)=cadena1; // Cargo Byte HB. y los uno los dos en una palabra de 16 bits que se llama buffer
temp = (buffer & 0b0111111111111000)>>3; //Seleccionamos los bits que nos interesan haciéndole lo que se llama
//Una máscara, se le hace un AND al dato con un número en binario, los unos significan los bits que queremos utilizar y los 0 los que desechamos
//Luego le hacemos un >>3 que significa que rodamos los 1 a la derecha 3 posiciones para eliminar los 0 del final
temperatura = (temp * 0.25); //12 bits en decimal equivalen a 4095, para que de los 1023,75 ºC se tiene que multiplicar por 0.25 que es la resolución de cada bit del MAX6675
}
void modulo_AD(){ //Rutina del módulo analógico digital
ad = 0; //Inicializamos la variable del dato del potenciómetro y la limpiamos para una nueva lectura
delay_us(30); //Retraso necesario para la medida
ad = read_adc(); //Captura del valor transformado a digital que entra por AN0 que viene del valor del potenciómetro
}
float modulacion(float pwm){ //Rutina para la modulación de un pulso
pwm=0; //inicializamos la variable
if(swicht==1){
setup_timer_2(T2_DIV_BY_16,255,1); //configuración del timer_2 para la señal PWM
setup_ccp1(CCP_PWM); //Activamos el CCP ósea PWM por hardware
set_pwm1_duty(ad); //función donde cambiaremos el ancho del pulso, se cambiará en función del valor de ad que luego se pasa a dato
pwm=(ad/10.23); //al dividir el entero por esto, hacemos que en pantalla aparezca 100.0 cuando la PWM esté a tope
}
else{ //Si swicht no es igual a 1
setup_timer_2(T2_DISABLED,255,1); //Desactivamos el timer2
setup_ccp1(CCP_OFF); //Apagamos el módulo ccp1
}
return pwm;
}
void pulsador (void){ //Rutina para transformar un pulsador en un pulsador con enclavamiento
int limite=2;
if(input(PIN_A4)==0){ //Si la entrada A4 está a 0
swicht++; //Se incrementa la variable swicht
delay_ms(20); //Un retraso para evitar rebotes del pulsador
}
if(swicht > (limite-1)){ //Si la variable swicht es mayor que límite -1
swicht = 0; // se pone la variable swicht a 0
}
}
//******************************Función Principal*********************************
main(){
float pwm,pwm1; //Variables locales para la señal pwm
lcd_init();
inicializar(); //Llamamos a la función inicializar y ejecutamos el código de la función
port_b_pullups(TRUE); //Seleccionamos la resistencias de pull-ups internas para el puerto B
setup_spi(SPI_MASTER | SPI_L_TO_H); // Configuramos el SPI por hardware del micro, sin esto no rula
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); //Configuración del timer1 para el cronómetro
set_timer1(55661); //Carga del buffer del timer1 para que el salto sea a 1 ms
setup_adc_ports(AN0); //Seleccionamos que pin estará tomando las muestras
setup_adc(ADC_CLOCK_INTERNAL); //Configuración del módulo A/D por hardware
set_adc_channel(0); //Canal del micro o pin de entrada en el micro para la conversión A/D
enable_interrupts(INT_TIMER1); //Activamos las interrupciones del timer1
enable_interrupts(global); //Activamos las interrupciones globales
do{
leer_termocupula(); //Llamamos al la rutina para leer la temperatura
pulsador(); //Llamamos a la función pulsador
termocupula_error = (buffer & 0b0000000000000100)>>2; //Seleccionamos el bit D2, nos indica si el termopar está
//conectado o no
if(bit_test(buffer,2)){ // Si el bit D2 es igual a 1, se ejecutan las sentencias siguientes
lcd_putc('\f'); //Limpiamos la pantalla LCD
lcd_gotoxy(5,1); //Posición del LCD para imprimir el siguiente comando
printf(lcd_putc,"Termopar"); //Se muestra en pantalla que el termopar está desconectado
lcd_gotoxy(3,2);
printf(lcd_putc,"Desconectado"); //Se muestra en pantalla, en la posición 3,2
setup_timer_2(T2_DISABLED,255,1); //Desactivamos el timer2
setup_ccp1(CCP_OFF); //Apagamos el módulo ccp1
}
else{ // si no está pulsado - modulamos la señal PWM, medimos le resistencia del potenciómetro y medimos temperatura
pwm1 = modulacion(pwm); //Llamamos a la rutina de PWM y guardamos el dato en pwm1
modulo_AD(); //Llamamos a la rutina de modulación A/D para capturar el valor del potenciómetro
lcd_putc('\f'); //Limpiamos la pantalla LCD para una nueva escritura
lcd_gotoxy(1,1);
printf(lcd_putc,"Temp=%f C",temperatura); //mostramos en pantalla la temperatura en la posición 1,1
if(swicht==1){ //Si el pulsador está activado
lcd_gotoxy(1,2); //Designamos la posición en el display
printf(lcd_putc,"%02u:%02u",min,sec);//y mostramos el tiempo
lcd_gotoxy(6,2); //Designamos la posición del valor PWM
printf(lcd_putc," PWM=%3.1f",pwm1);//mostramos en pantalla el valor de la señal PWM
}
else{ //Si NO
lcd_gotoxy(1,2); //designamos la posición en pantalla
printf(lcd_putc,"TimeStop"); //mostramos stop, y paramos el tempo
lcd_gotoxy(9,2);
printf(lcd_putc," PwmStop"); //así como paramos la PWM
}
}
}
while(TRUE);
}