#include <16F877A.h>
#device ADC=10
#fuses XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#fuses NOWDT //No Watch Dog Timer
#fuses NOPUT //No Power Up Timer
#fuses NOBROWNOUT //No brownout reset
#fuses NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used FOR I/O
#fuses NOCPD //No EE protection
#fuses NOWRT //Program memory not write protected
#fuses NODEBUG //No Debug mode FOR ICD
#fuses NOPROTECT //Code not protected from reading
#use delay(crystal=4000000)
#include <lcd.c>
#include <math.h>
#use standard_io(A)
#use standard_io(B)
#use standard_io(C)
#use standard_io(D)
#use standard_io(E)
int8 Y[10]; //Vector Y[] por lo tanto cuando la etapa 4 esté activa, lo estará Y[4].
int8 Re[14]; //Vector Re[] por tanto cuando la transición 3 tenga cierta su receptividad, estará activo Re[3].
int8 Va[14]; //El vector Va tendrá sus componentes activas cuando las transiciones que les correspondan estén validadas.
//int8 Tiempo[]; //El vector T contiene el tiempo transcurrido desde la última activación de cada una de las etapas.
//int8 I[]; //Los vectores I y Q contienen las entradas (I) y salidas (Q) físicas
//int8 Q[]; //
//int8 E[]; //Los vectores E y S guardan los estados de las entradas (E) y salidas (S) hasta que se acaba un ciclo.
//int8 S[]; //
int8 freidos=0,dispensados=0,listo;
int16 X,desbordes0=0;
float32 T,V,R,discriminante;
float32 A=0.0039083;
float32 B=-0.000000577;
//*****************************************************************************
//Funciones auxiliares*********************************************************
void posicion_inicial(){ //funcion para posicionar los mecanismos de dispensado y extraccion
setup_timer_2(T2_DIV_BY_16,155,1); //seleccion de la frecuencia para PWM *********OJO********* aqui se modifica la velocidad de los motores pap
setup_ccp1(CCP_PWM);
set_pwm1_duty(64);
output_low(PIN_E0); //habilita el motor de dispensado
output_high(PIN_E1); //deshabilita el motor de corte
output_high(PIN_E2); //deshabilita el motor de extraccion
output_low(PIN_A4); //gira contrario al las agujas de reloj
while(input(PIN_C0)==0){ //mover el motor de dispensado hasta la posicion inicial
}
output_high(PIN_E0); //una vez que toca el final de carrera superior el motor de dispensado se deshabilita
output_high(PIN_E1); //deshabilita el motor de corte
output_low(PIN_E2); //habilita el motor de extraccion
output_high(PIN_A5); //gira con las agujas de reloj
while(input(PIN_C7)==0){ //mover el motor de extraccion hasta la posicion inicial
}
output_high(PIN_E2); //una vez que toca el final de carrera inferior el motor de extraccion se deshabilita
set_pwm1_duty(0);
setup_ccp1(CCP_OFF);
}
//*****************************************************************************
void lectura_pt100(){ //funcion para leer el valor de resistencia de la PT100 y activar o desactivar la resistencia de coccion
X=read_adc();
V=(X*(0.0048828125));
R=((150*V)/(5-V));
discriminante=(((100*A)*(100*A))-(4*100*B*(100-R)));
discriminante
=sqrt(discriminante
); T=(((-100*A)+discriminante)/(2*100*B));
if(T<200){
output_high(PIN_B1);
}else{
output_low(PIN_B1);
}
}
//*****************************************************************************
void setup(){ //configuracion de puertos, ADC y LCD
output_A(0); //Configuracion de puertos
input(PIN_A0);
output_B(0);
output_C(0);
output_D(0);
output_E(0);
delay_ms(10);
lcd_init(); //inicializacion de la LCD
SETUP_ADC(ADC_CLOCK_DIV_32); //configuracion del ADC
SETUP_ADC_PORTS(AN0);
SET_ADC_CHANNEL (0);
delay_us(50);
}
//*****************************************************************************
void pantalla_bienvenida(){ //muestra la bienvenida y las instrucciones
lcd_putc("\f BIENVENIDO "); //pantallas de bienvenida
delay_ms(2000);
lcd_putc("\f MAQUINA DE \n CHURROS ");
delay_ms(2000);
lcd_putc("\fINSTRUCCIONES");
delay_ms(2000);
lcd_putc("\fPRESIONE 1 O 2\nPARA SELECCION");
delay_ms(2000);
}
//*****************************************************************************
void lectura_T(){ //funcion para leer el valor de resistencia de la PT100 y temperatura
X=read_adc();
V=(X*(0.0048828125));
R=((150*V)/(5-V));
discriminante=(((100*A)*(100*A))-(4*100*B*(100-R)));
discriminante
=sqrt(discriminante
); T=(((-100*A)+discriminante)/(2*100*B));
}
//*****************************************************************************
void activar_dispensar(){ //habilita el proceso de dispensado y corte de churros
printf(lcd_putc
,"\fDISPENSANDO\nCHURROS T:%3.0lf %cC",T
,223); delay_ms(10);
output_low(PIN_E0); //habilita el motor de dispensado
output_low(PIN_E1); //habilita el motor de corte
output_high(PIN_E2); //deshabilita el motor de extraccion
output_high(PIN_A4); //gira con las agujas de reloj
setup_timer_2(T2_DIV_BY_16,155,1); //seleccion de la frecuencia para PWM *********OJO********* aqui se modifica la velocidad de los motores pap
setup_ccp1(CCP_PWM);
set_pwm1_duty(64);
setup_ccp2(CCP_PWM);
set_pwm2_duty(64);
while((input(PIN_C5)==0)&&(desbordes0<1000)){ //mover el motor de dispensado hasta el 25% por tiempo, y verifica si se toco el final de carrera bajo (seguridad)
delay_ms(1);
lectura_pt100();
desbordes0++;
}
desbordes0=0;
}
//*****************************************************************************
void desactivar_dispensar(){ //deshabilita el proceso de dispensado y corte de churros
output_high(PIN_E0); //una vez que toca el final de carrera superior el motor de dispensado se deshabilita
output_high(PIN_E1); //una vez que toca el final de carrera superior el motor de corte se deshabilita
setup_ccp1(CCP_OFF);
setup_ccp2(CCP_OFF);
}
//*****************************************************************************
void freir_churros(){ //activa el proceso de freido de churros, haciendo lecturas constantes de la temperatura
printf(lcd_putc
,"\fFRIENDO\nESPERE T:%3.0lf %cC",T
,223); while(desbordes0<10000){ //espera de t para que los churros se cocinen correctamente
delay_ms(1);
lectura_pt100();
desbordes0++;
}
desbordes0=0;
}
//*****************************************************************************
void extraer_churros(){ //proceso de extraccion de churros
output_high(PIN_E0); //deshabilita el motor de dispensado
output_high(PIN_E1); //deshabilita el motor de corte
output_low(PIN_E2); //habilita el motor de extraccion
output_low(PIN_A5); //gira con las contrario a las agujas de reloj
setup_timer_2(T2_DIV_BY_16,155,1); //seleccion de la frecuencia para PWM *********OJO********* aqui se modifica la velocidad de los motores pap
setup_ccp1(CCP_PWM);
set_pwm1_duty(64);
printf(lcd_putc
,"\fEXTRAYENDO\nCHURROS T:%3.0lf %cC",T
,223); while(input(PIN_C6)==0){ //mover el motor de extraccion hasta arriba, y verifica si se toco el final de carrera superior
}
output_high(PIN_E2); //una vez que toca el final de carrera superior el motor de extraccion se deshabilita
setup_ccp1(CCP_OFF);
lcd_putc("\fPOR FAVOR RETIRE\n Y PRESIONE 1 ");
while(input(PIN_C3)==0){
}
lcd_putc("\f PREPARANDO \nSIGUIENTE RONDA");
output_high(PIN_E0); //deshabilita el motor de dispensado
output_high(PIN_E1); //deshabilita el motor de corte
output_low(PIN_E2); //habilita el motor de extraccion
output_high(PIN_A5); //gira con las agujas de reloj
setup_ccp1(CCP_PWM);
set_pwm1_duty(64);
while(input(PIN_C7)==0){ //mover el motor de extraccion hasta abajo, y verifica si se toco el final de carrera inferior
}
output_high(PIN_E2); //una vez que toca el final de carrera inferior el motor de dispensado se deshabilita
setup_ccp1(CCP_OFF);
dispensados++;
}
//*****************************************************************************
void main(){
setup();
pantalla_bienvenida();
lcd_putc("\f1-INICIAR");
delay_ms(10);
while(input(PIN_C3)==0){ //pregunta si se quiere iniciar
}
while(T<200){ //se enciende la resistencia hasta alcanzar los 200°C
lectura_pt100();
printf(lcd_putc
,"\f CALENTANDO \n T:%3.1lf %cC ",T
,223); delay_ms(1000);
}
//ENABLE_INTERRUPTS (INT_RB);
//ENABLE_INTERRUPTS (GLOBAL); //se habilitan las interrupciones globales
lectura_pt100();
printf(lcd_putc
,"\fPOSICIONANDO\nMECANISMOS T:%3.0lf %cC",T
,223); posicion_inicial();
printf(lcd_putc
,"\fLISTO...\n T:%3.0lf %cC",T
,223); delay_ms(2000);
lectura_pt100();
printf(lcd_putc
,"\f TEMPERATURA \n T:%3.1lf %cC ",T
,223); delay_ms(2000);
lcd_putc("\f SELECCION DE \n MODO "); //seleccion del modo de trabajo
delay_ms(2000);
dispensados=0;
//**********************Inicializacion de grafcet
Y[0]=1;
Y[1]=0;
Y[2]=0;
Y[3]=0;
Y[4]=0;
Y[5]=0;
Y[6]=0;
Y[7]=0;
Y[8]=0;
Y[9]=0;
//**********************Programa principal
while(1){ //El ciclo de programa se debe repetir indefinidamente.
Va[0]=Y[0]; //Ahora vamos a validar las transiciones. Una transición es válida cuando todas las etapas inmediatamente anteriores son activas.
Va[1]=Y[0];
Va[2]=Y[0];
Va[3]=Y[1];
Va[4]=Y[2];
Va[5]=Y[5];
Va[6]=Y[3];
Va[7]=Y[3];
Va[8]=Y[6];
Va[9]=Y[9];
Va[10]=Y[4];
Va[11]=Y[7];
Va[12]=Y[7];
Va[13]=Y[8];
//****************************************************************************************************************
//Después programaremos las acciones asociadas a las etapas.
if(Y[0]==1){ //Reposo
printf(lcd_putc
,"\f1-FREIDO\n2-DRENAJE T:%3.0lf %cC",T
,223); //freido o drenaje lectura_pt100();
listo=0;
}
if(Y[1]==1){ //Recomendacion de drenaje
lcd_putc("\fSE RECOMIENDA\nDRENAR ACEITE");
delay_ms(2000);
listo=1;
}
if(Y[2]==1){ //Llenado de extrusora
printf(lcd_putc
,"\fMODO FREIDO\n T:%3.0lf %cC",T
,223); delay_ms(2000);
printf(lcd_putc
,"\fINSERTE MASA DE\nCHURROS T:%3.0lf %cC",T
,223); delay_ms(2000);
lcd_putc("\fPRESIONE 1 PARA\nINICIAR PROCESO"); //espera a que el usuario presione 1 para iniciar el proceso
lectura_pt100();
while(input(PIN_C3)==0){
}
}
if(Y[3]==1){ //Dispensado
activar_dispensar();
desactivar_dispensar();
}
if(Y[4]==1){ //Freido
freir_churros();
}
if(Y[5]==1){ //Enfriado de aceite
output_low(PIN_B1);
printf(lcd_putc
,"\fMODO DRENAJE\n T:%3.0lf %cC",T
,223); delay_ms(2000);
lcd_putc("\fENFRIANDO ACEITE");
delay_ms(2000);
while(T>50){ //se apaga la resistencia hasta alcanzar los 50°C, para proceder a drenar el aceite
lectura_T();
printf(lcd_putc
,"\f ENFRIANDO \n T:%3.1lf %cC ",T
,223); delay_ms(1000);
}
}
if(Y[6]==1){ //Drenaje de aceite
printf(lcd_putc
,"\fDRENANDO ACEITE\n T:%3.0lf %cC",T
,223); delay_ms(2000);
output_high(PIN_B2); //enciende valvula de drenaje
delay_ms(10000); //tiempo de activacion de valvula de drenaje
output_low(PIN_B2); //apaga valvula de drenaje
freidos=0;
printf(lcd_putc
,"\f SIN ACEITE \n T:%3.0lf %cC",T
,223); delay_ms(2000);
listo=1;
}
if(Y[7]==1){ //Extraccion
extraer_churros();
}
if(Y[8]==1){ //Tanda de churros lista
lectura_pt100();
dispensados=0;
printf(lcd_putc
,"\fTANDA DE CHURROS\nLISTA T:%3.0lf %cC",T
,223); delay_ms(2000);
lcd_putc("\fPOSICIONANDO\nMECANISMOS");
posicion_inicial();
freidos++;
}
if(Y[9]==1){ //Freido y extraccion de emergencia
freir_churros();
extraer_churros();
}
//****************************************************************************************************************
Re[0]=((input(PIN_C3)==1)&&(input(PIN_C4)==0)&&(input(PIN_B7)==0)&&(freidos>=3)); //Continuamos con las condiciones de transición.
Re[1]=((input(PIN_C3)==1)&&(input(PIN_C4)==0)&&(input(PIN_B7)==0)&&(freidos<3));
Re[2]=((input(PIN_C3)==0)&&(input(PIN_C4)==1)&&(input(PIN_B7)==0));
Re[3]=(Listo==1);
Re[4]=((input(PIN_C3)==1));
Re[5]=(T<=50);
Re[6]=((input_state(PIN_E0)==1)&&(input_state(PIN_E1)==1)&&(input(PIN_C5)==1));
Re[7]=((input_state(PIN_E0)==1)&&(input_state(PIN_E1)==1)&&(input(PIN_C5)==0));
Re[8]=(Listo==1);
Re[9]=(input_state(PIN_E2)==1);
Re[10]=(desbordes0==0);
Re[11]=((input_state(PIN_E2)==1)&&(dispensados>=4));
Re[12]=((input_state(PIN_E2)==1)&&(dispensados<4));
Re[13]=((input_state(PIN_E2)==1));
//****************************************************************************************************************
if ((Re[0]*Va[0])||(Re[1]*Va[1])||(Re[2]*Va[2])){Y[0]=0;} //Seguidamente programamos las desactivaciones de etapas. Cuando una transición es válida y la receptividad correspondiente es cierta se deben desactivar todas las etapas precedentes.
if ((Re[3]*Va[3])){Y[1]=0;}
if ((Re[4]*Va[4])){Y[2]=0;}
if ((Re[6]*Va[6])||(Re[7]*Va[7])){Y[3]=0;}
if ((Re[10]*Va[10])){Y[4]=0;}
if ((Re[5]*Va[5])){Y[5]=0;}
if ((Re[8]*Va[8])){Y[6]=0;}
if ((Re[12]*Va[12])||(Re[11]*Va[11])){Y[7]=0;}
if ((Re[13]*Va[13])){Y[8]=0;}
if ((Re[9]*Va[9])){Y[9]=0;}
//****************************************************************************************************************
if ((Re[13]*Va[13])||(Re[3]*Va[3])||(Re[8]*Va[8])){Y[0]=1;} //Y, a continuación, las activaciones. Cuando una transición es válida y la receptividad es cierta se deben activar todas las etapas posteriores.
if ((Re[0]*Va[0])){Y[1]=1;}
if ((Re[1]*Va[1])){Y[2]=1;}
if ((Re[4]*Va[4])||(Re[12]*Va[12])){Y[3]=1;}
if ((Re[7]*Va[7])){Y[4]=1;}
if ((Re[2]*Va[2])){Y[5]=1;}
if ((Re[5]*Va[5])){Y[6]=1;}
if ((Re[10]*Va[10])){Y[7]=1;}
if ((Re[11]*Va[11])||(Re[9]*Va[9])){Y[8]=1;}
if ((Re[6]*Va[6])){Y[9]=1;}
//****************************************************************************************************************
}
}