TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: hurtadoluisalex en 20 de Diciembre de 2019, 15:53:48

Título: Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 20 de Diciembre de 2019, 15:53:48
Buenos dias compañeros, llevo algo de tiempo aca en el foro y recurro a ustedes de nuevo a ver si alguien me puede sacar de este bache que tengo con un asunto de mi proyecto final

Bueno procedo a explicar para que estemos en el mismo contexto. Estoy realizando un maquina que dispensa por extrusion y frie dulces (churros, asi se le conoce aca en venezuela  :mrgreen:), bueno la cosa es que el "cerebro" de la maquina es el PIC 16F877A, que debe hacer lo siguiente: encargarse del manejo, velocidad y la posicion de un par de motores de paso por medio de sensores final de carrera, debe realizar una medicion de temperatura por medio de una PT100 para un control on/off, debe mostrar el paso a paso en una pantalla LCD y finalmente sensar unos botones que seran nuestra interfaz de usuario junto con la pantalla.

He realizado la programacion en lenguaje C (la alternativa era assembler  :5] ), tengo dos versiones del codigo, una nueva y una vieja que adjuntare. El proceso en general es el siguiente:

Los problemas que tengo son los siguientes:

He estado revisando el codigo desde hace unas semanas y creo que he encontrado algunas cosas extrañas que me gustaria si alguien me puede aclarar si en realidad esto puede afectar el funcionamiento o no.

*NOTA IMPORTANTE: el PIC tiene cargado el programa en su version vieja, por razones de tiempo y disponibilidad del quemador solo puedo acceder a el nuevamente en enero  :oops: para cargar la nueva version

 1- Originalmente realize la programacion para utilizar un cristal de 20Mhz pero al no conseguirlo (bendita crisis en este pais) tuve que cambialo por uno de 4Mhz, pero hay un detalle que no me fije en la programacion vieja, es el siguiente: tengo el modo HS con 4Mhz y creo que deberia ser XT para 4Mhz, segun lo indica CCS C compiler (PIC C compiler), ¿esto podria afectar el funcionamiento en algun punto? adjunto codigos:

Viejo:
Código: C
  1. #include <16F877A.h>
  2. #device ADC=10
  3. #fuses HS          //High speed Osc (> 4mhz FOR PCM/PCH) (>10mhz for PCD)
  4. #fuses NOWDT       //No Watch Dog Timer
  5. #fuses NOPUT       //No Power Up Timer
  6. #fuses NOBROWNOUT  //No brownout reset
  7. #fuses NOLVP       //No low voltage prgming, B3(PIC16) or B5(PIC18) used FOR I/O
  8. #fuses NOCPD       //No EE protection
  9. #fuses NOWRT       //Program memory not write protected
  10. #fuses NODEBUG     //No Debug mode FOR ICD
  11. #fuses NOPROTECT   //Code not protected from reading
  12. #use delay(crystal=4000000)
  13. #include <lcd.c>
  14. #include <math.h>
  15. #use standard_io(A)
  16. #use standard_io(B)
  17. #use standard_io(C)
  18. #use standard_io(D)
  19. #use standard_io(E)

Nuevo:
Código: C
  1. #include <16F877A.h>
  2. #device ADC=10
  3. #fuses XT          //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
  4. #fuses NOWDT       //No Watch Dog Timer
  5. #fuses NOPUT       //No Power Up Timer
  6. #fuses NOBROWNOUT  //No brownout reset
  7. #fuses NOLVP       //No low voltage prgming, B3(PIC16) or B5(PIC18) used FOR I/O
  8. #fuses NOCPD       //No EE protection
  9. #fuses NOWRT       //Program memory not write protected
  10. #fuses NODEBUG     //No Debug mode FOR ICD
  11. #fuses NOPROTECT   //Code not protected from reading
  12. #use delay(crystal=4000000)
  13. #include <lcd.c>
  14. #include <math.h>
  15. #use standard_io(A)
  16. #use standard_io(B)
  17. #use standard_io(C)
  18. #use standard_io(D)
  19. #use standard_io(E)

2- Una posible fuente de reinicio creo que puede ser la siguiente pero me gustaria orientacion para confirmar la solucion que creo haberle dado

Basicamente se realiza la bienvenida, chequeo de temperatura y posicion inicial de motores y mecanismos, despues de eso se pregunta por el modo de trabajo siempre y cuando no se hayan realizado 5 o mas dispensados o el pin C5 este en bajo, ya que este indica el final de del recorrido de la parte de extrusion (es una especie de seguridad, de no tenerlo se podria causar un daño mecanico a la maquina), entonces si este PIN por alguna razon (ruido o algo asi tiene un alto no se ejecutaria la funcion while que da paso a los modos de trabajo, adjunto codigo viejo y nuevo (posible correccion para orientacion):

Viejo:
Código: C
  1. void main()
  2. {
  3.    output_A(0); //Configuracion de puertos
  4.    input(PIN_A0);
  5.    output_B(0);
  6.    output_C(0);
  7.    output_D(0);
  8.    output_E(0);
  9.    delay_ms(10);
  10.    lcd_init(); //inicializacion de la LCD
  11.    SETUP_ADC(ADC_CLOCK_DIV_32); //configuracion del ADC
  12.    SETUP_ADC_PORTS(AN0);
  13.    SET_ADC_CHANNEL (0);
  14.    delay_us(50);
  15.    lcd_putc("\f   BIENVENIDO   "); //pantallas de bienvenida
  16.    delay_ms(2000);
  17.    lcd_putc("\f   MAQUINA DE   \n    CHURROS     ");
  18.    delay_ms(2000);
  19.    lcd_putc("\fINSTRUCCIONES");
  20.    delay_ms(2000);
  21.    lcd_putc("\fPRESIONE 1 O 2\nPARA SELECCION");
  22.    delay_ms(2000);
  23.    lcd_putc("\f1-INICIAR");
  24.    delay_ms(5);
  25.    while(input(PIN_C3)==0){ //pregunta si se quiere iniciar  
  26.    while(T<200){ //se enciende la resistencia hasta alcanzar los 200°C ******ACA hay una funcion de lectura de pt100 y on/off de rele
  27.    ENABLE_INTERRUPTS (INT_AD); //se habilitan las interrupciones por AD, cambio de estado rb4-rb7
  28.    ENABLE_INTERRUPTS (INT_RB);
  29.    ENABLE_INTERRUPTS (GLOBAL); //se habilitan las interrupciones globales
  30.    X=read_adc();
  31.    lcd_putc("\fPOSICIONANDO\nMECANISMOS");
  32.    posicion();
  33.    lcd_putc("\fLISTO...");
  34.    delay_ms(2000);
  35.    X=read_adc();
  36.    printf(lcd_putc,"\f   TEMPERATURA  \n    T:%3.1lf %cC    ",T,223);
  37.    delay_ms(2000);
  38.    lcd_putc("\f  SELECCION DE  \n      MODO      "); //seleccion del modo de trabajo
  39.    delay_ms(2000);
  40.    
  41.    while((dispensados<5)&&(input(PIN_C5)==0)){ //*********ACA es donde planteo que si hay ruido o algo en el PIN no se ejecutario el while e iria de nuevo a la pantalla bienvenida y configuracion
  42.    lcd_putc("\f1-FREIDO\n2-DRENAJE"); //freido o manual
  43.    delay_ms(10);
  44.    X=read_adc();
  45.    if(input(PIN_C3)==1){ //aca se ejecutara el modo freido
  46.    if(input(PIN_C4)==1){ //aca se ejecutara el modo drenaje
  47.    }
  48. }

Nuevo:
Código: C
  1. void main()
  2. {
  3.    output_A(0); //Configuracion de puertos
  4.    input(PIN_A0);
  5.    output_B(0);
  6.    output_C(0);
  7.    output_D(0);
  8.    output_E(0);
  9.    delay_ms(10);
  10.    lcd_init(); //inicializacion de la LCD
  11.    SETUP_ADC(ADC_CLOCK_DIV_32); //configuracion del ADC
  12.    SETUP_ADC_PORTS(AN0);
  13.    SET_ADC_CHANNEL (0);
  14.    delay_us(50);
  15.    lcd_putc("\f   BIENVENIDO   "); //pantallas de bienvenida
  16.    delay_ms(2000);
  17.    lcd_putc("\f   MAQUINA DE   \n    CHURROS     ");
  18.    delay_ms(2000);
  19.    lcd_putc("\fINSTRUCCIONES");
  20.    delay_ms(2000);
  21.    lcd_putc("\fPRESIONE 1 O 2\nPARA SELECCION");
  22.    delay_ms(2000);
  23.    lcd_putc("\f1-INICIAR");
  24.    delay_ms(5);
  25.    while(input(PIN_C3)==0){ //pregunta si se quiere iniciar  
  26.    while(T<200){ //se enciende la resistencia hasta alcanzar los 200°C ******ACA hay una funcion de lectura de pt100 y on/off de rele
  27.    ENABLE_INTERRUPTS (INT_AD); //se habilitan las interrupciones por AD, cambio de estado rb4-rb7
  28.    ENABLE_INTERRUPTS (INT_RB);
  29.    ENABLE_INTERRUPTS (GLOBAL); //se habilitan las interrupciones globales
  30.    X=read_adc();
  31.    lcd_putc("\fPOSICIONANDO\nMECANISMOS");
  32.    posicion();
  33.    lcd_putc("\fLISTO...");
  34.    delay_ms(2000);
  35.    X=read_adc();
  36.    printf(lcd_putc,"\f   TEMPERATURA  \n    T:%3.1lf %cC    ",T,223);
  37.    delay_ms(2000);
  38.    lcd_putc("\f  SELECCION DE  \n      MODO      "); //seleccion del modo de trabajo
  39.    delay_ms(2000);
  40.   while(TRUE){ //***********************************************************AQUI he puesto un while para crear un bucle donde si por ruido o algo se pone en alto el PIN C5 pues no se ira a la pantalla de bienvenida ni configuraciones
  41.    while((dispensados<5)&&(input(PIN_C5)==0)){ //*********ACA es donde planteo que si hay ruido o algo en el PIN no se ejecutario el while e iria de nuevo a la pantalla bienvenida y configuracion
  42.    lcd_putc("\f1-FREIDO\n2-DRENAJE"); //freido o manual
  43.    delay_ms(10);
  44.    X=read_adc();
  45.    if(input(PIN_C3)==1){ //aca se ejecutara el modo freido
  46.    if(input(PIN_C4)==1){ //aca se ejecutara el modo drenaje
  47.    }
  48.   }
  49. }


3- Los otros problemas creo que podrian ser por ruido o algo por el estilo, lo estoy haciendo en Protoboard (es mas economico y no es requisito hacerlo en placa PCB)

Tengo un montaje viejo y nuevo, ambos realizados en proteus, aqui corre muy bien el programa nuevo y va 10/10 pero en la vida real no he probado porque como comente antes, no tengo acceso al programador por el momento

He realizado el montaje con el programa viejo y el circuito viejo y pasa todo lo que les comente, tambien probe realizando el circuito nuevo pero con el programa viejo y me sigue dando problemas, adjunto fotos de los circuitos en proteus:

Viejo: esto es solo una porcion de todo el circuito

(https://i.imgur.com/zyHI3au.jpg)

Nuevo: esto es solo una porcion de todo el circuito

(https://i.imgur.com/bRDLF3x.jpg)


He investigado acerca del ruido y trate de implementarlo como esta en el circuito nuevo, pero al tener la programacion vieja no se si sera efectivo, creo que eso es todo, agradezco toda la ayuda posible en cuanto al tema y estare gustoso de proporcionar mas informacion en caso de que alguien la requiera. Adjuntare el codigo viejo y nuevo en forma de archivo .c y el circuito con su respectivo en proteus para que lo puedan visualizar mejor

*PD: He probado colocando capacitores en la zona de la fuente de poder, en VDD y VSS del Pic, tambien quiero que sepan que estoy utilizando drivers Pololu A4988 para los motores, aun no he conectado ni encendido los motores, solo sus drivers, ya que aun estoy estancado esto que les mencione (reinicios, activacion de interrupciones, medicion erronea de temperatura y congelamiento)

Gracias por tomarse el tiempo de leer, y por sus respuestas. Espero tengan un buen dia :lol:

*Pido disculpas si el tema no va en esta seccion y por lo largo del post
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 20 de Diciembre de 2019, 17:59:22
Te vendría muy bien dibujar varias máquinas de estados para diseñar el funcionamiento.

Tendrás que hacer un sistema multitarea basado en los estados anteriores.

https://es.m.wikipedia.org/wiki/M%C3%A1quina_de_Moore
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 20 de Diciembre de 2019, 18:26:17
El programa podría tener este aspecto:

Código: C
  1. void setup(void) {
  2.    output_A(0); //Configuracion de puertos
  3.    ...
  4. }
  5.  
  6.  
  7. void lcd_mensajes() {
  8.    lcd_putc("\f   BIENVENIDO   "); //pantallas de bienvenida
  9.    ...
  10. }
  11.  
  12. void main() {
  13.  
  14.    int estado_mecan = 1;
  15.  
  16.    setup();
  17.  
  18.    lcd_mensajes();
  19.  
  20.    // Bucle principal
  21.    while(1) {
  22.  
  23.       // Control de temperatura
  24.       T = sonda_temperatura_read();
  25.       if (T < 200) {
  26.          calefactor_on();
  27.       }
  28.       else {
  29.          calefactor_off();
  30.       }
  31.  
  32.       // Lectura de entradas
  33.       push_button_1 = read_pushbutton(1);
  34.       ...
  35.  
  36.       // Transiciones de la máquina de estados
  37.       if (estado_mecan == 1  && condición1) {
  38.          estado_mecan = 2;
  39.       }
  40.       ...
  41.  
  42.  
  43.       // Escritura de salidas
  44.       if (estado_mecan == 1)   salida1();
  45.       if (estado_mecan == 2)   salida2();
  46.       ...
  47.    }
  48.  
  49. }


Pero lo que de verdad es importante es que tengas claro qué es lo que quieres que haga la máquina en cada momento:
   cuántos estados diferentes hay para la máquina
   cómo se pasa de un estado a otro
   qué hay que hacer en cada estado

Por ejemplo cuando se llegue al final de la extrusión y se pulse el final de carrera. En ese estado (extrusión terminada) ¿Qué hay que hacer? ¿Cuál es el siguiente estado y cómo llegamos a él?

Un saludo.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 20 de Diciembre de 2019, 18:53:55
El programa podría tener este aspecto:

Código: C
  1. void setup(void) {
  2.    output_A(0); //Configuracion de puertos
  3.    ...
  4. }
  5.  
  6.  
  7. void lcd_mensajes() {
  8.    lcd_putc("\f   BIENVENIDO   "); //pantallas de bienvenida
  9.    ...
  10. }
  11.  
  12. void main() {
  13.  
  14.    int estado_mecan = 1;
  15.  
  16.    setup();
  17.  
  18.    lcd_mensajes();
  19.  
  20.    // Bucle principal
  21.    while(1) {
  22.  
  23.       // Control de temperatura
  24.       T = sonda_temperatura_read();
  25.       if (T < 200) {
  26.          calefactor_on();
  27.       }
  28.       else {
  29.          calefactor_off();
  30.       }
  31.  
  32.       // Lectura de entradas
  33.       push_button_1 = read_pushbutton(1);
  34.       ...
  35.  
  36.       // Transiciones de la máquina de estados
  37.       if (estado_mecan == 1  && condición1) {
  38.          estado_mecan = 2;
  39.       }
  40.       ...
  41.  
  42.  
  43.       // Escritura de salidas
  44.       if (estado_mecan == 1)   salida1();
  45.       if (estado_mecan == 2)   salida2();
  46.       ...
  47.    }
  48.  
  49. }


Pero lo que de verdad es importante es que tengas claro qué es lo que quieres que haga la máquina en cada momento:
   cuántos estados diferentes hay para la máquina
   cómo se pasa de un estado a otro
   qué hay que hacer en cada estado

Por ejemplo cuando se llegue al final de la extrusión y se pulse el final de carrera. En ese estado (extrusión terminada) ¿Qué hay que hacer? ¿Cuál es el siguiente estado y cómo llegamos a él?

Un saludo.

Hola, gracias por tomarte el tiempo de leer. En cuanto a lo que quiero que la maquina haga, ya esta todo definido paso a paso, de hecho tengo el diagrama de flujo para guiarse un poco mas. Por ejemplo, el final de carrera de extrusion es mas que todo de seguridad, de alli segun algunas variables, regresa a su posicion inicial la extrusion y repite o simplemente vuelve y el proceso total concluye.

Por ahora estoy en una etapa de prototipo, y estoy realizando los primeros montajes y pruebas con respecto a la electronica. Todos los procesos a realizar por la maquina estan ya definidos (incluso hay planos y simulaciones  :-/ )  pero me esta dando un verdadero dolor de cabeza los problemas que mencione al principio del tema, que no logro saber si es el ruido, el montaje o la programacion lo que me esta causando el malfuncionamiento.

Queria aclarar tambien que el montaje en la protoboard lo he realizado tal cual se muestra en la imagen de proteus nueva, que se muestra en el post principal, con los mismos valores de capacitores, resistencias, etc.

PD: me diste una idea muy buena con el ejemplo que me diste para ordenar un poco mas el codigo y que se mas entendible, gracias  ;-)
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 20 de Diciembre de 2019, 19:21:04
Creo que el problema está en el programa.

¿Puedes poner los diagramas de flujo para compararlos con el programa y entender mejor el funcionamiento?
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 20 de Diciembre de 2019, 23:20:33
Creo que el problema está en el programa.

¿Puedes poner los diagramas de flujo para compararlos con el programa y entender mejor el funcionamiento?

Claro, aca esta el diagrama, perdon por lo largo o si esta algo desordenado  :lol: :oops:
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 21 de Diciembre de 2019, 05:31:13
Lo primero, hurtadoluisalex, felicitarte por el trabajo tan detallado que has hecho y por preparar el diagrama antes de ponerte a programar.
Eso es algo que muy pocos programadores hacen y sin embargo es necesario.

Pero un diagrama de flujo debe comenzar como un diagrama sin detalles, con pocas etapas. Piensa que debes presentar tu proyecto a un tribunal. Si le enseñas ese diagrama de flujo no van a entender nada. Si es necesario se pueden hacer varios diagramas pequeños, cada uno explicando una pequeña etapa o tarea. Te intentaré ayudar con eso después.

Lo primero es entender la máquina (el hardware) antes de entender cómo se comporta (el software).
Yo por ahora entiendo que tiene 4 acciones:
   1.- Motor de extrusora, para que salga masa de churros a la freidora. Con 2 finales de carrera, uno arriba y otro abajo.
   2.- Motor de corte. Va cortando la masa de los churros cada cierto tiempo.
   3.- Motor de extracción de churros. Retira los churros cuando están hechos. Tiene 2 finales de carrera asociados ¿dentro y fuera?
   4.- Resistencia calentadora del aceite, con un sensor de temperatura asociado.

Me falta alguna más que no entiendo bien ¿Puedes explicármelo?
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 21 de Diciembre de 2019, 05:39:38
En cuanto al diagrama, a este tipo de máquinas le viene muy bien utilizar un diagrama de máquina de estados. El más conocido para programación de autómatas y que utilizan mucho los franceses es el Grafcet. https://es.wikipedia.org/wiki/GRAFCET

Si quieres te puedo ayudar para que hagas un Grafcet de tu proceso (creo que quedaría más profesional) o seguimos con el diagrama de flujo.

Un saludo.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 21 de Diciembre de 2019, 09:58:49
Lo primero, hurtadoluisalex, felicitarte por el trabajo tan detallado que has hecho y por preparar el diagrama antes de ponerte a programar.
Eso es algo que muy pocos programadores hacen y sin embargo es necesario.

Pero un diagrama de flujo debe comenzar como un diagrama sin detalles, con pocas etapas. Piensa que debes presentar tu proyecto a un tribunal. Si le enseñas ese diagrama de flujo no van a entender nada. Si es necesario se pueden hacer varios diagramas pequeños, cada uno explicando una pequeña etapa o tarea. Te intentaré ayudar con eso después.

Gracias, tengo una version un poco mas simple pero esta incompleta (le falta el modo drenaje), para el proyecto final nos pidieron algo mas detallado por eso lo tengo tan largo y detallado el diagrama de flujo  :oops:


Citar
Lo primero es entender la máquina (el hardware) antes de entender cómo se comporta (el software).
Yo por ahora entiendo que tiene 4 acciones:
   1.- Motor de extrusora, para que salga masa de churros a la freidora. Con 2 finales de carrera, uno arriba y otro abajo.
   2.- Motor de corte. Va cortando la masa de los churros cada cierto tiempo.
   3.- Motor de extracción de churros. Retira los churros cuando están hechos. Tiene 2 finales de carrera asociados ¿dentro y fuera?
   4.- Resistencia calentadora del aceite, con un sensor de temperatura asociado.

Me falta alguna más que no entiendo bien ¿Puedes explicármelo?

Exacto, tal cual como colocaste los dos primeros puntos asi funciona, se carga la masa en la extrusora que cuenta con dos finales de carrera (uno para indicar la posicion inicial y el otro marca el fin del recorrido). El motor de corte solo se activa cuando se activa la extrusion.

Para extraccion, se cuenta tambien con dos finales de carrera (arriba y abajo), uno para indicar que la cesta que tiene los churros esta afuera del aceite y pueden ser retirados por el operador, y otro para indicar que la cesta esta dentro del recipiente que contiene el aceite.

Tambien estas en lo correcto con respecto a la resistencia, tiene un sensor de temperatura que indicara al microcontrolador si debe activar o desactivar la resistencia segun la medicion. Si quieres me puedes indicar que si hay algo que me falta por explicar y con gusto lo explicare  :o

Honestamente, la poca experiencia que tengo es con diagramas de flujo pues es basicamente lo que utilizamos aca casi todo el tiempo (el resto del tiempo ni se hace un diagrama  :? ) estuve leyendo la pagina con la informacion que me posteaste y se hace algo complicada o por lo menos asi lo percibo ya que nunca he trabajado con ese tipo de diagramas
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 21 de Diciembre de 2019, 12:19:46
Creo que ese diagrama es un poco complejo y no se ven bien los estados de la máquina.

Yo pondría los siguientes estados resumidos:

   1.- REPOSO
   2.- CALENTANDO
   3.- EXTRUDIENDO
   4.- FRIENDO
   5.- SACANDO CHURROS

Luego hay que meter ahí el llenado de la churrera. Yo lo haría desde reposo con otro camino alternativo:

   1.- REPOSO
   7.- ABRIENDO EXTRUSORA
   8.- LLENANDO EXTRUSORA

Otro camino alternativo para drenar aceite:

   1.- REPOSO
   9.- ENFRIANDO ACEITE PARA DRENAJE
   10.- DRENAR ACEITE

Ahora hay que unir los estados mediante condiciones (pulsadores, tiempos, finales de carrera, temperaturas, etc)

¿Qué opinas?

Un saludo.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 21 de Diciembre de 2019, 12:24:27
Acabo de darme cuenta de que después del llenado de la extrusora no sabes cuánto hay que mover el motor para que empiece a extrudir. Debería ser una operación manual:

   1.- REPOSO
   7.- ABRIENDO EXTRUSORA
   8.- LLENANDO EXTRUSORA
   11.- CERRANDO EXTRUSORA EN MODO MANUAL
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 21 de Diciembre de 2019, 12:40:39
Honestamente, la poca experiencia que tengo es con diagramas de flujo pues es basicamente lo que utilizamos aca casi todo el tiempo (el resto del tiempo ni se hace un diagrama  :? ) estuve leyendo la pagina con la informacion que me posteaste y se hace algo complicada o por lo menos asi lo percibo ya que nunca he trabajado con ese tipo de diagramas

No son complicados, al contrario para este tipo de máquinas resulta más natural dibujar una máquina de estados que un diagrama de flujo. Son muy parecidos entre sí y te puedo echar una mano.
El diagráma de flujo queda muy raro, lleno de líneas que van hacia atrás para esperar a que salgas de cada estado.

Lo único que hay que hacer es dibujar los 11 estados anteriores de arriba a abajo y unirlos con líneas. En cada línea de unión se coloca una rayita horizontal y la condición que permite pasar de un estado a otro.

Un ejemplo:

(https://upload.wikimedia.org/wikipedia/commons/3/3d/Secuencial_GRAFCET.PNG)
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Eduardo Rodas en 21 de Diciembre de 2019, 12:45:35
No es buena idea conectar directamente el sensor de temperatura al PIC; debería haber algún circuito de adaptación como por ejemplo un amplificador operacional en modo seguidor de tensión. No creo que este midiendo bien la temperatura ... puede que funcione en Proteus, pero no en la realidad.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 21 de Diciembre de 2019, 12:48:55
Creo que ese diagrama es un poco complejo y no se ven bien los estados de la máquina.

Yo pondría los siguientes estados resumidos:

   1.- REPOSO
   2.- CALENTANDO
   3.- EXTRUDIENDO
   4.- FRIENDO
   5.- SACANDO CHURROS

Luego hay que meter ahí el llenado de la churrera. Yo lo haría desde reposo con otro camino alternativo:

   1.- REPOSO
   7.- ABRIENDO EXTRUSORA
   8.- LLENANDO EXTRUSORA

Otro camino alternativo para drenar aceite:

   1.- REPOSO
   9.- ENFRIANDO ACEITE PARA DRENAJE
   10.- DRENAR ACEITE

Ahora hay que unir los estados mediante condiciones (pulsadores, tiempos, finales de carrera, temperaturas, etc)

¿Qué opinas?

Un saludo.

Hola, me gusta la estructura que le has dado. Hay procesos que me falto explicar con mas detalle que pense que no serian relevantes por el problema que tenia, pero ya veo que todo hay que tenerlo en cuenta, procedo a aclarar algunas cosas:

El proceso de llenado para la extrusion (cargar la masa) es completamente manual por parte del operador, cuando se coloca la masa el operador presiona el boton 1 y comienza el dispensado.

Con respecto a esto:
Citar
Acabo de darme cuenta de que después del llenado de la extrusora no sabes cuánto hay que mover el motor para que empiece a extrudir. Debería ser una operación manual:

   1.- REPOSO
   7.- ABRIENDO EXTRUSORA
   8.- LLENANDO EXTRUSORA
   11.- CERRANDO EXTRUSORA EN MODO MANUAL

Es una operacion manual eso que dices, nunca lo habia contemplado pero practicamente se habia hecho y planteado hacerlo manual solo que sin darme cuenta  :lol:
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 21 de Diciembre de 2019, 12:50:49
No es buena idea conectar directamente el sensor de temperatura al PIC; debería haber algún circuito de adaptación como por ejemplo un amplificador operacional en modo seguidor de tensión. No creo que este midiendo bien la temperatura ... puede que funcione en Proteus, pero no en la realidad.

Estaba pensando eso, pero aun no tenia la seguridad de si deberia hacerlo o no, porque en ocasiones mide correctamente pero en otras arroja un resultado erroneo, voy a tratar de implementarlo para dejar menos espacio a errores e inconvenientes
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 21 de Diciembre de 2019, 12:56:32
Honestamente, la poca experiencia que tengo es con diagramas de flujo pues es basicamente lo que utilizamos aca casi todo el tiempo (el resto del tiempo ni se hace un diagrama  :? ) estuve leyendo la pagina con la informacion que me posteaste y se hace algo complicada o por lo menos asi lo percibo ya que nunca he trabajado con ese tipo de diagramas

No son complicados, al contrario para este tipo de máquinas resulta más natural dibujar una máquina de estados que un diagrama de flujo. Son muy parecidos entre sí y te puedo echar una mano.
El diagráma de flujo queda muy raro, lleno de líneas que van hacia atrás para esperar a que salgas de cada estado.

Lo único que hay que hacer es dibujar los 11 estados anteriores de arriba a abajo y unirlos con líneas. En cada línea de unión se coloca una rayita horizontal y la condición que permite pasar de un estado a otro.

Un ejemplo:

(https://upload.wikimedia.org/wikipedia/commons/3/3d/Secuencial_GRAFCET.PNG)

Voy a investigar un poco acerca de esto, por alli encontre un par de software para realizar este diagrama.

Queria comentarte que estoy ordenando el codigo, añadiendo funciones para que el programa principal no sea tan incomodo y enredado de leer y entender, y asi sacar los diagramas mas sencillos
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 21 de Diciembre de 2019, 15:33:21
Es una operacion manual eso que dices, nunca lo habia contemplado pero practicamente se habia hecho y planteado hacerlo manual solo que sin darme cuenta  :lol:

La primera razón por la que se deben hacer diagramas es para entender bien la máquina y el proceso. Para que salgan los detalles de qué se debe hacer.


En cuanto al software, te recomiendo que comiences por hacer los diagramas con papel y lápiz. El software es para pasar a limpio lo que sepas que ya está bien.
En cuanto al programa se puede utilizar cualquiera. Yo he utilizado en ocasiones algo tan simple como Word o LibreOffice Draw.
Título: Re: Proyecto Máquina de Churros
Publicado por: Picuino en 21 de Diciembre de 2019, 15:41:18
Te recomiendo este libro que es una maravilla para aprender a programar bien:
Código limpio.    Robert C. Martin (Autor).

  - Tienes que ingresar para ver archivos adjuntos -  

https://www.amazon.es/C%C3%B3digo-Limpio-desarrollo-software-Programaci%C3%B3n/dp/8441532109/ref=sr_1_1?keywords=CODIGO+LIMPIO+Martin%2C+C.+Robert&qid=1576953596&s=books&sr=1-1

No te costará encontrar el epub.
https://www.epublibre.org/libro/detalle/38147
Título: Re: Proyecto Máquina de Churros
Publicado por: hurtadoluisalex en 21 de Diciembre de 2019, 15:58:39
Te recomiendo este libro que es una maravilla para aprender a programar bien:
Código limpio.    Robert C. Martin (Autor).

  - Tienes que ingresar para ver archivos adjuntos -  

https://www.amazon.es/C%C3%B3digo-Limpio-desarrollo-software-Programaci%C3%B3n/dp/8441532109/ref=sr_1_1?keywords=CODIGO+LIMPIO+Martin%2C+C.+Robert&qid=1576953596&s=books&sr=1-1

No te costará encontrar el epub.
https://www.epublibre.org/libro/detalle/38147

Gracias, voy a buscarlo, no esta demas aprender algo nuevo  :mrgreen:

He organizado el codigo, lo he dividido en funciones haciendo simplemente llamados y he implementado antirrebotes por software en todos los pulsadores que creo que me podrian ayudar con el tema del ruido y la activacion de las interrupciones donde tenia problemas
Título: Re: Proyecto Máquina de Churros
Publicado por: Picuino en 21 de Diciembre de 2019, 16:20:13
Si el software está bien programado, no creo que los rebotes te den problemas.

En cuanto a las interrupciones, creo que por ahora no las necesitas. Quizá más adelante para hacer temporizaciones basadas en un timer.
Título: Re: Proyecto Máquina de Churros
Publicado por: hurtadoluisalex en 21 de Diciembre de 2019, 17:31:19
Si el software está bien programado, no creo que los rebotes te den problemas.

En cuanto a las interrupciones, creo que por ahora no las necesitas. Quizá más adelante para hacer temporizaciones basadas en un timer.

Si, cuando lo estaba orgnizando me di cuenta que en las interrupciones tenia algunos errores que aproveche de corregir. Por ahora las interrupciones que tengo son para una parada de emergencia (nunca se sabe) y para monitorear la temperatura actual, ambas con dos botones conectados a RB.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 21 de Diciembre de 2019, 17:50:01
Si programas la máquina por estados no te harán falta las interrupciones. Podrás hacer varias tareas a la vez sin necesidad de interrupciones. Esto se llama concurrencia.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 21 de Diciembre de 2019, 18:51:48
 :shock: esto no lo sabia, voy a investigar mas acerca todo este tema
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 21 de Diciembre de 2019, 19:02:22
Te puedo ir ayudando, pero lo primero es tener claros los estados de la máquina y el diagrama de funcionamiento.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 22 de Diciembre de 2019, 00:59:15
Te puedo ir ayudando, pero lo primero es tener claros los estados de la máquina y el diagrama de funcionamiento.

Una pregunta, aca en tu anterior respuesta cuando planteaste estos estados:
Citar
Creo que ese diagrama es un poco complejo y no se ven bien los estados de la máquina.

Yo pondría los siguientes estados resumidos:

   1.- REPOSO
   2.- CALENTANDO
   3.- EXTRUDIENDO
   4.- FRIENDO
   5.- SACANDO CHURROS

Luego hay que meter ahí el llenado de la churrera. Yo lo haría desde reposo con otro camino alternativo:

   1.- REPOSO
   7.- ABRIENDO EXTRUSORA
   8.- LLENANDO EXTRUSORA

Otro camino alternativo para drenar aceite:

   1.- REPOSO
   9.- ENFRIANDO ACEITE PARA DRENAJE
   10.- DRENAR ACEITE

Ahora hay que unir los estados mediante condiciones (pulsadores, tiempos, finales de carrera, temperaturas, etc)

¿Qué opinas?

Un saludo.

Lo estabas haciendo basado en un diagrama de GRAFCET? lo estuve leyendo y se me hizo bastante interesante y muy entendible
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 22 de Diciembre de 2019, 03:32:07
Si, eran estados de un grafcet
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 22 de Diciembre de 2019, 10:21:32
Si, eran estados de un grafcet

Ah perfecto, me animé a hacer el diagrama e implementarlo en la programación, me pareció muy interesante. Lo que me hubiese ahorrado si me hubiese enterado antes de este diagrama  :D
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 22 de Diciembre de 2019, 11:21:53
Si subes el grafcet puedo ayudarte a pulirlo y a hacer el programa.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 22 de Diciembre de 2019, 15:26:31
Si subes el grafcet puedo ayudarte a pulirlo y a hacer el programa.

Hola, aca esta lo que he hecho, aun tengo algunas dudas pero hice lo mejor que pude  :oops:

Estados:


Entradas:

Salidas:


Pagina 1 grafcet:
(https://i.imgur.com/mzGYu6n.jpg)
Pagina 2 grafcet:
(https://i.imgur.com/5vhF3xN.jpg)

Aun tengo dudas de como colocar, los pulsadores para la parada de emergencia y mostrar temperatura, creo que seria con alguna conexion en paralelo pero no se  :lol:
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 22 de Diciembre de 2019, 17:50:20
Todavía lo veo demasiado complicado. Estoy pensando que lo mejor sería dividir el grafcet en dos diferentes.

Voy a hacer el dibujo y lo subo.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 22 de Diciembre de 2019, 18:58:57
También he pensado que sería mejor tener algunos pulsadores más:
   Botón de subir extrusora
   Botón de bajar extrusora

Adjunto los 3 grafcets:

  - Tienes que ingresar para ver archivos adjuntos -
  - Tienes que ingresar para ver archivos adjuntos -  
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 22 de Diciembre de 2019, 19:33:14
La parada de emergencia debe parar todo. Va aparte. Se puede añadir cuando lo demás funcione.

En el display yo mantendría una línea para temperatura y otra para el estado en el que está la máquina.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 22 de Diciembre de 2019, 20:42:28
También he pensado que sería mejor tener algunos pulsadores más:
   Botón de subir extrusora
   Botón de bajar extrusora

Adjunto los 3 grafcets:

  - Tienes que ingresar para ver archivos adjuntos -
  - Tienes que ingresar para ver archivos adjuntos -

Me agrada la idea de mostrar la temperatura constantemente en la pantalla junto al estado en que este la maquina, asi me "ahorraria" un boton dedicado solo a mostrar la temperatura, pienso implementar eso.

Por otro lado, si me di cuenta que el mio se ve complicado comparado con tus diagramas  :mrgreen:  ... en tus diagramas por ejemplo en el de extrusion hay una condicion luego de la etapa 0 ( boton inicio.grafcet de reposo), a que te refieres con grafcet de reposo?

Otra duda que tengo es que no veo las condiciones por ejemplo que se deben hacer 4 rondas de dispensados  extrusiones de churros para contar un freido, ya que los freidos indican cuando se debe drenar el aceite usado. Tambien si la extrusora toca el final de carrera bajo deberia proseguir a colocar todo en su estado inicial, ya que no se podria hacer mas extrusiones.


Asi con tus diagramas ya se podria comenzar a programar? o se requiere de un diagrama mas complejo? claro todo despues que se haya entendido completamente el funcionamiento de la maquina  :D
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 23 de Diciembre de 2019, 05:25:52
... en tus diagramas por ejemplo en el de extrusion hay una condicion luego de la etapa 0 ( boton inicio.grafcet de reposo), a que te refieres con grafcet de reposo?
boton inicio y resto de grafcets en reposo (en la etapa cero)

Esto es porque son grafcets independientes. De esta manera se puede drenar a la vez que se carga la extrusora (acciones a la vez o concurrentes).
Sin embargo no se puede extrudir y freir a la vez que se carga la extrusora o a la vez que se drena. Por eso hay que poner la condición de que no se esté drenando o llenando la extrusora para empezar a extrudir.

Otra duda que tengo es que no veo las condiciones por ejemplo que se deben hacer 4 rondas de dispensados  extrusiones de churros para contar un freido, ya que los freidos indican cuando se debe drenar el aceite usado. Tambien si la extrusora toca el final de carrera bajo deberia proseguir a colocar todo en su estado inicial, ya que no se podria hacer mas extrusiones.
Si, esas condiciones falta completarlas. He tenido en cuenta que la extrusora se vaciaría en mitad de la extrusión, por lo que esa ronda de churros se deja friendo y luego habría que saltar a la etapa cero y no dejar que comience la extrusión de nuevo hasta que no se llene la extrusora.

Asi con tus diagramas ya se podria comenzar a programar? o se requiere de un diagrama mas complejo? claro todo despues que se haya entendido completamente el funcionamiento de la maquina  :D
Se puede empezar a programar, sólo hace falta poner en el diagrama las entradas y salidas (grafcet de nivel III):

  - Tienes que ingresar para ver archivos adjuntos -  
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 23 de Diciembre de 2019, 10:58:33
... en tus diagramas por ejemplo en el de extrusion hay una condicion luego de la etapa 0 ( boton inicio.grafcet de reposo), a que te refieres con grafcet de reposo?
boton inicio y resto de grafcets en reposo (en la etapa cero)

Esto es porque son grafcets independientes. De esta manera se puede drenar a la vez que se carga la extrusora (acciones a la vez o concurrentes).
Sin embargo no se puede extrudir y freir a la vez que se carga la extrusora o a la vez que se drena. Por eso hay que poner la condición de que no se esté drenando o llenando la extrusora para empezar a extrudir.

Otra duda que tengo es que no veo las condiciones por ejemplo que se deben hacer 4 rondas de dispensados  extrusiones de churros para contar un freido, ya que los freidos indican cuando se debe drenar el aceite usado. Tambien si la extrusora toca el final de carrera bajo deberia proseguir a colocar todo en su estado inicial, ya que no se podria hacer mas extrusiones.
Si, esas condiciones falta completarlas. He tenido en cuenta que la extrusora se vaciaría en mitad de la extrusión, por lo que esa ronda de churros se deja friendo y luego habría que saltar a la etapa cero y no dejar que comience la extrusión de nuevo hasta que no se llene la extrusora.

Asi con tus diagramas ya se podria comenzar a programar? o se requiere de un diagrama mas complejo? claro todo despues que se haya entendido completamente el funcionamiento de la maquina  :D
Se puede empezar a programar, sólo hace falta poner en el diagrama las entradas y salidas (grafcet de nivel III):

  - Tienes que ingresar para ver archivos adjuntos -

Ahhhh ahora si me quedo un poco mas claro esas condiciones del principio de cada grafcet (luego de la etapa 0), ahora mi duda es como se plasman esas concurrencias, me siento ciego con respecto a esto, tendras por alli algun programa de ejemplo? para echarle un vistazo de como se ve, porque he buscado en internet ejemplos de programas en C a partir de Grafcet y solo encuentro de grafcet a ladder o asm.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 23 de Diciembre de 2019, 12:27:31
https://web.archive.org/web/20110905182033/http://edison.upc.edu/curs/grafcet/implem/general.html
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 23 de Diciembre de 2019, 15:03:55
Cuando tenga tiempo pondré algo más.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 23 de Diciembre de 2019, 17:44:53
Cuando tenga tiempo pondré algo más.

Perfecto, muchas gracias amigo. Por lo pronto ire leyendo y analizando el link anterior  :mrgreen:
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 23 de Diciembre de 2019, 19:00:07
Debería ser algo así:

Código: C
  1. typedef union  {
  2.   struct {
  3.     unsigned char estado0: 1;
  4.     unsigned char estado1: 1;
  5.     unsigned char estado2: 1;
  6.     unsigned char estado3: 1;
  7.     unsigned char estado4: 1;
  8.     unsigned char estado5: 1;
  9.     unsigned char estado6: 1;
  10.     unsigned char estado7: 1;
  11.   };
  12.   unsigned char estados;
  13. } tipo_grafcet;
  14.  
  15. tipo_grafcet grafcet[3], grafcet_siguiente[3];
  16.  
  17. unsigned char entradas[6], salidas[6];
  18.  
  19. main() {
  20.    grafcet_inicializar();
  21.  
  22.    while(1) {
  23.       leer_entradas();
  24.       grafcets();
  25.       escribir_salidas();
  26.       otros_controles();    
  27.    }
  28. }
  29.  
  30. leer_entradas() {
  31.    entrada[BOTON_INICIO] = read(PIN1);
  32.    ...
  33. }
  34.  
  35. escribir_salidas() {
  36.    write(PIN3, salidas[VALVULA_DRENAJE]);
  37.    ...
  38. }
  39.  
  40. grafcet_inicializar() {
  41.    grafcet_siguiente[0].estados = 0;
  42.    grafcet_siguiente[0].estado0 = 1;
  43. }
  44.  
  45.  
  46. grafcets() {
  47.    grafcets_copiar_transiciones();
  48.    grafcets_calcular_transiciones();
  49.    grafcets_calcular_acciones();
  50. }
  51.  
  52. grafcets_copiar_transiciones() {
  53.    grafcet[0].estados = grafcet_siguiente[0].estados;
  54.    grafcet[1].estados = ...
  55. }
  56.  
  57.  
  58. grafcets_calcular_transiciones() {
  59.    if (grafcet[0].estado0 && pulsador_inicio() && otras_condiciones()) {
  60.       grafcet_siguiente[0].estado0 = 0;
  61.       grafcet_siguiente[0].estado1 = 1;
  62.    }
  63.  
  64.    if (...)
  65. }
  66.  
  67. grafcets_calcular_acciones() {
  68.    if (grafcet[0].estado4 == 1) {
  69.       salidas[MOTOR_EXTRUSION] = 1;
  70.    }
  71.  
  72.    if (...)
  73.  
  74. }

Creo que por ahora tienes bastante.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 24 de Diciembre de 2019, 05:20:20
Voy a limpiar un poco el código para cambiar los números por constantes que tengan un nombre.

Código: C
  1. #define  NUMERO_DE_GRAFCETS   3
  2. #define  NUMERO_DE_ENTRADAS   6
  3. #define  NUMERO_DE_SALIDAS   8
  4.  
  5. enum NOMBRE_GRAFCETS {
  6.         EXTRUSION,
  7.         LLENADO,
  8.         DRENAJE };
  9.  
  10. enum ENTRADAS_FISICAS {
  11.         BOTON_INICIO,
  12.         BOTON_PARADA,
  13.         ... };
  14.  
  15. enum SALIDAS_FISICAS {
  16.         VALVULA_DRENAJE,
  17.         ... };
  18.  
  19. typedef union  {
  20.   struct {
  21.     unsigned char etapa0: 1;
  22.     unsigned char etapa1: 1;
  23.     unsigned char etapa2: 1;
  24.     unsigned char etapa3: 1;
  25.     unsigned char etapa4: 1;
  26.     unsigned char etapa5: 1;
  27.     unsigned char etapa6: 1;
  28.     unsigned char etapa7: 1;
  29.   };
  30.   unsigned char etapas;
  31. } tipo_grafcet;
  32.  
  33. tipo_grafcet grafcet[NUMERO_DE_GRAFCETS], grafcet_siguiente[NUMERO_DE_GRAFCETS];
  34.  
  35. unsigned char entradas[NUMERO_DE_ENTRADAS], salidas[NUMERO_DE_SALIDAS];
  36.  
  37. main() {
  38.    grafcet_inicializar();
  39.  
  40.    while(1) {
  41.       leer_entradas();
  42.       grafcets();
  43.       escribir_salidas();
  44.       otros_controles();
  45.    }
  46. }
  47.  
  48. leer_entradas() {
  49.    entrada[BOTON_INICIO] = read(PIN1);
  50.    ...
  51. }
  52.  
  53. escribir_salidas() {
  54.    write(PIN3, salidas[VALVULA_DRENAJE]);
  55.    ...
  56. }
  57.  
  58. grafcet_inicializar() {
  59.    grafcet_siguiente[EXTRUSION].etapas = 0;
  60.    grafcet_siguiente[EXTRUSION].etapa0 = 1;
  61. }
  62.  
  63.  
  64. grafcets() {
  65.    grafcets_copiar_transiciones();
  66.    grafcets_calcular_transiciones();
  67.    grafcets_calcular_acciones();
  68. }
  69.  
  70.  
  71. grafcets_copiar_transiciones() {
  72.    grafcet[EXTRUSION].etapas = grafcet_siguiente[EXTRUSION].etapas;
  73.    grafcet[LLENADO].etapas = ...
  74. }
  75.  
  76.  
  77. grafcets_calcular_transiciones() {
  78.    if (grafcet[EXTRUSION].etapa0 && pulsador_inicio() && otras_condiciones()) {
  79.       grafcet_siguiente[EXTRUSION].etapa0 = 0;
  80.       grafcet_siguiente[EXTRUSION].etapa1 = 1;
  81.    }
  82.  
  83.    if (...)
  84. }
  85.  
  86. grafcets_calcular_acciones() {
  87.    if (grafcet[EXTRUSION].etapa4 == 1) {
  88.       salidas[MOTOR_EXTRUSION] = 1;
  89.    }
  90.  
  91.    if (...)
  92.  
  93. }
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 26 de Diciembre de 2019, 07:04:14
Hola hurtadoluisalex. Imagino que necesitas ayuda... No dudes en pedirla.

Un saludo.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 26 de Diciembre de 2019, 14:32:57
Hola hurtadoluisalex. Imagino que necesitas ayuda... No dudes en pedirla.

Un saludo.

Hola, muchas gracias por los ejemplos y todo lo que me has ayudado. Estos ultimos dos dias no he podido trabajar en el tema porque estaba ocupado con lo de las fiestas de esta epoca... a partir de mañana empezare a trabajar con todas las guias que me facilitaste, no dudare en pedir ayuda cualquier cosa  :-/  gracias de nuevo
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 30 de Diciembre de 2019, 23:35:51
Código: C
  1. void setup(void) {
  2.    output_A(0); //Configuracion de puertos
  3.    ...
  4. }
  5.  
  6.  
  7. void lcd_mensajes() {
  8.    lcd_putc("\f   BIENVENIDO   "); //pantallas de bienvenida
  9.    ...
  10. }
  11.  
  12. void main() {
  13.  
  14.    int estado_mecan = 1;
  15.  
  16.    setup();
  17.  
  18.    lcd_mensajes();
  19.  
  20.    // Bucle principal
  21.    while(1) {
  22.  
  23.       // Control de temperatura
  24.       T = sonda_temperatura_read();
  25.       if (T < 200) {
  26.          calefactor_on();
  27.       }
  28.       else {
  29.          calefactor_off();
  30.       }
  31.  
  32.       // Lectura de entradas
  33.       push_button_1 = read_pushbutton(1);
  34.       ...
  35.  
  36.       // Transiciones de la máquina de estados
  37.       if (estado_mecan == 1  && condición1) {
  38.          estado_mecan = 2;
  39.       }
  40.       ...
  41.  
  42.  
  43.       // Escritura de salidas
  44.       if (estado_mecan == 1)   salida1();
  45.       if (estado_mecan == 2)   salida2();
  46.       ...
  47.    }
  48.  
  49. }

Saludos, bueno por aca nuevamente para revivir el tema ya que he tenido cierto progreso con esto de los diagramas grafcet y su forma de implementarlos, hoy por fin tuve tiempo de terminar el programa utilizando el diagrama y ayudandome con el link que publicaste,  https://web.archive.org/web/20110905182033/http://edison.upc.edu/curs/grafcet/implem/general.html (https://web.archive.org/web/20110905182033/http://edison.upc.edu/curs/grafcet/implem/general.html) , tambien ayudandome de otras publicaciones aca del foro que consegui y un video de youtube donde explican un poco como usar grafcet con lenguaje c. Bueno en fin, he tratado de hacer lo mejor posible, sinceramente el nuevo programa se parece a algo como el codigo citado ya que, siendo honesto no entendi mucho como implementar varios grafcet en un solo codigo, supongo que me hace falta practica pero como no he tenido mucho tiempo aun no he podido entrar de lleno a todo el contenido de esta metodologia de grafcet, pero bueno lo importante es que pude comenzar con algo y ciertamente es mas eficiente y sencillo de entender trabajar de esta forma que como lo venia haciendo anteriormente :-/

Me gustaria que le pudieras echar un vistazo @Picuino , si no es mucha molestia claro esta  :oops: , aun me falta agregarle cosas como el boton de parada de emergencia, tambien queria acotar que he "eliminado" el boton para ver la temperatura y decidi mostrarla a un lado en la pantalla en cada etapa de proceso, asi siempre sera visible para el operador. Bueno procedo a adjuntar el nuevo codigo y el diagrama de grafcet de nivel III , el I y II los perdi por problemas en la red electrica que hicieron que mi computadora se apagara sin previo aviso, el diagrama es algo parecido al primer diagrama que publique solo que con algunas modificaciones y siendo mas detallado.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 31 de Diciembre de 2019, 10:14:42
Copio tu programa para que se pueda ver:

Código: C
  1. #include <16F877A.h>
  2. #device ADC=10
  3. #fuses XT          //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
  4. #fuses NOWDT       //No Watch Dog Timer
  5. #fuses NOPUT       //No Power Up Timer
  6. #fuses NOBROWNOUT  //No brownout reset
  7. #fuses NOLVP       //No low voltage prgming, B3(PIC16) or B5(PIC18) used FOR I/O
  8. #fuses NOCPD       //No EE protection
  9. #fuses NOWRT       //Program memory not write protected
  10. #fuses NODEBUG     //No Debug mode FOR ICD
  11. #fuses NOPROTECT   //Code not protected from reading
  12. #use delay(crystal=4000000)
  13. #include <lcd.c>
  14. #include <math.h>
  15. #use standard_io(A)
  16. #use standard_io(B)
  17. #use standard_io(C)
  18. #use standard_io(D)
  19. #use standard_io(E)
  20.  
  21. int8 Y[10]; //Vector Y[] por lo tanto cuando la etapa 4 esté activa, lo estará Y[4].
  22. int8 Re[14]; //Vector Re[] por tanto cuando la transición 3 tenga cierta su receptividad, estará activo Re[3].
  23. int8 Va[14]; //El vector Va tendrá sus componentes activas cuando las transiciones que les correspondan estén validadas.
  24. //int8 Tiempo[]; //El vector T contiene el tiempo transcurrido desde la última activación de cada una de las etapas.
  25. //int8 I[]; //Los vectores I y Q contienen las entradas (I) y salidas (Q) físicas
  26. //int8 Q[]; //
  27. //int8 E[]; //Los vectores E y S guardan los estados de las entradas (E) y salidas (S) hasta que se acaba un ciclo.
  28. //int8 S[]; //
  29. int8 freidos=0,dispensados=0,listo;
  30. int16 X,desbordes0=0;                            
  31. float32 T,V,R,discriminante;
  32. float32 A=0.0039083;
  33. float32 B=-0.000000577;
  34. //*****************************************************************************
  35. //Funciones auxiliares*********************************************************
  36. void posicion_inicial(){ //funcion para posicionar los mecanismos de dispensado y extraccion
  37.    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
  38.    setup_ccp1(CCP_PWM);
  39.    set_pwm1_duty(64);
  40.    output_low(PIN_E0); //habilita el motor de dispensado
  41.    output_high(PIN_E1); //deshabilita el motor de corte
  42.    output_high(PIN_E2); //deshabilita el motor de extraccion
  43.    output_low(PIN_A4); //gira contrario al las agujas de reloj
  44.    while(input(PIN_C0)==0){ //mover el motor de dispensado hasta la posicion inicial            
  45.    }
  46.    output_high(PIN_E0); //una vez que toca el final de carrera superior el motor de dispensado se deshabilita
  47.    output_high(PIN_E1); //deshabilita el motor de corte
  48.    output_low(PIN_E2); //habilita el motor de extraccion
  49.    output_high(PIN_A5); //gira con las agujas de reloj
  50.    while(input(PIN_C7)==0){ //mover el motor de extraccion hasta la posicion inicial
  51.    }
  52.    output_high(PIN_E2); //una vez que toca el final de carrera inferior el motor de extraccion se deshabilita
  53.    set_pwm1_duty(0);
  54.    setup_ccp1(CCP_OFF);
  55. }
  56. //*****************************************************************************
  57. void lectura_pt100(){ //funcion para leer el valor de resistencia de la PT100 y activar o desactivar la resistencia de coccion
  58.     X=read_adc();
  59.     V=(X*(0.0048828125));
  60.     R=((150*V)/(5-V));
  61.     discriminante=(((100*A)*(100*A))-(4*100*B*(100-R)));
  62.     discriminante=sqrt(discriminante);    
  63.     T=(((-100*A)+discriminante)/(2*100*B));
  64.     if(T<200){
  65.        output_high(PIN_B1);      
  66.     }else{
  67.        output_low(PIN_B1);
  68.     }
  69. }
  70. //*****************************************************************************
  71. void setup(){ //configuracion de puertos, ADC y LCD
  72.     output_A(0); //Configuracion de puertos
  73.     input(PIN_A0);
  74.     output_B(0);
  75.     output_C(0);
  76.     output_D(0);
  77.     output_E(0);
  78.     delay_ms(10);
  79.     lcd_init(); //inicializacion de la LCD
  80.     SETUP_ADC(ADC_CLOCK_DIV_32); //configuracion del ADC
  81.     SETUP_ADC_PORTS(AN0);
  82.     SET_ADC_CHANNEL (0);
  83.     delay_us(50);
  84. }
  85. //*****************************************************************************
  86. void pantalla_bienvenida(){ //muestra la bienvenida y las instrucciones
  87.    lcd_putc("\f   BIENVENIDO   "); //pantallas de bienvenida
  88.       delay_ms(2000);
  89.       lcd_putc("\f   MAQUINA DE   \n    CHURROS     ");
  90.       delay_ms(2000);
  91.       lcd_putc("\fINSTRUCCIONES");
  92.       delay_ms(2000);
  93.       lcd_putc("\fPRESIONE 1 O 2\nPARA SELECCION");
  94.       delay_ms(2000);
  95. }
  96. //*****************************************************************************
  97. void lectura_T(){ //funcion para leer el valor de resistencia de la PT100 y temperatura
  98.    X=read_adc();
  99.    V=(X*(0.0048828125));
  100.    R=((150*V)/(5-V));
  101.    discriminante=(((100*A)*(100*A))-(4*100*B*(100-R)));
  102.    discriminante=sqrt(discriminante);    
  103.    T=(((-100*A)+discriminante)/(2*100*B));
  104. }
  105. //*****************************************************************************
  106. void activar_dispensar(){ //habilita el proceso de dispensado y corte de churros
  107.    printf(lcd_putc,"\fDISPENSANDO\nCHURROS    T:%3.0lf %cC",T,223);
  108.    delay_ms(10);
  109.    output_low(PIN_E0); //habilita el motor de dispensado
  110.    output_low(PIN_E1); //habilita el motor de corte
  111.    output_high(PIN_E2); //deshabilita el motor de extraccion
  112.    output_high(PIN_A4); //gira con las agujas de reloj
  113.    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
  114.    setup_ccp1(CCP_PWM);
  115.    set_pwm1_duty(64);
  116.    setup_ccp2(CCP_PWM);
  117.    set_pwm2_duty(64);
  118.    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)
  119.       delay_ms(1);
  120.       lectura_pt100();
  121.       desbordes0++;        
  122.    }
  123.    desbordes0=0;  
  124. }
  125. //*****************************************************************************
  126. void desactivar_dispensar(){ //deshabilita el proceso de dispensado y corte de churros
  127.    output_high(PIN_E0); //una vez que toca el final de carrera superior el motor de dispensado se deshabilita
  128.    output_high(PIN_E1); //una vez que toca el final de carrera superior el motor de corte se deshabilita
  129.    setup_ccp1(CCP_OFF);
  130.    setup_ccp2(CCP_OFF);
  131. }
  132. //*****************************************************************************
  133. void freir_churros(){ //activa el proceso de freido de churros, haciendo lecturas constantes de la temperatura
  134.    printf(lcd_putc,"\fFRIENDO\nESPERE     T:%3.0lf %cC",T,223);                  
  135.    while(desbordes0<10000){ //espera de t para que los churros se cocinen correctamente
  136.       delay_ms(1);
  137.       lectura_pt100();
  138.       desbordes0++;
  139.    }
  140.    desbordes0=0;
  141. }
  142. //*****************************************************************************
  143. void extraer_churros(){ //proceso de extraccion de churros
  144.    output_high(PIN_E0); //deshabilita el motor de dispensado
  145.    output_high(PIN_E1); //deshabilita el motor de corte
  146.    output_low(PIN_E2); //habilita el motor de extraccion
  147.    output_low(PIN_A5); //gira con las contrario a las agujas de reloj
  148.    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
  149.    setup_ccp1(CCP_PWM);
  150.    set_pwm1_duty(64);            
  151.    printf(lcd_putc,"\fEXTRAYENDO\nCHURROS    T:%3.0lf %cC",T,223);
  152.    while(input(PIN_C6)==0){ //mover el motor de extraccion hasta arriba, y verifica si se toco el final de carrera superior
  153.    }
  154.    output_high(PIN_E2); //una vez que toca el final de carrera superior el motor de extraccion se deshabilita
  155.    setup_ccp1(CCP_OFF);
  156.    lcd_putc("\fPOR FAVOR RETIRE\n  Y PRESIONE 1  ");
  157.    while(input(PIN_C3)==0){
  158.    }
  159.    lcd_putc("\f   PREPARANDO   \nSIGUIENTE RONDA");
  160.    output_high(PIN_E0); //deshabilita el motor de dispensado
  161.    output_high(PIN_E1); //deshabilita el motor de corte
  162.    output_low(PIN_E2); //habilita el motor de extraccion
  163.    output_high(PIN_A5); //gira con las agujas de reloj
  164.    setup_ccp1(CCP_PWM);
  165.    set_pwm1_duty(64);
  166.    while(input(PIN_C7)==0){ //mover el motor de extraccion hasta abajo, y verifica si se toco el final de carrera inferior
  167.    }
  168.    output_high(PIN_E2); //una vez que toca el final de carrera inferior el motor de dispensado se deshabilita
  169.    setup_ccp1(CCP_OFF);
  170.    dispensados++;
  171. }
  172. //*****************************************************************************
  173.  
  174. void main(){
  175.       setup();
  176.       pantalla_bienvenida();
  177.       lcd_putc("\f1-INICIAR");
  178.       delay_ms(10);
  179.       while(input(PIN_C3)==0){ //pregunta si se quiere iniciar  
  180.       }
  181.       while(T<200){ //se enciende la resistencia hasta alcanzar los 200°C
  182.          lectura_pt100();
  183.          printf(lcd_putc,"\f   CALENTANDO   \n    T:%3.1lf %cC    ",T,223);
  184.          delay_ms(1000);
  185.       }
  186.       //ENABLE_INTERRUPTS (INT_RB);
  187.       //ENABLE_INTERRUPTS (GLOBAL); //se habilitan las interrupciones globales
  188.       lectura_pt100();
  189.       printf(lcd_putc,"\fPOSICIONANDO\nMECANISMOS T:%3.0lf %cC",T,223);
  190.       posicion_inicial();
  191.       printf(lcd_putc,"\fLISTO...\n           T:%3.0lf %cC",T,223);
  192.       delay_ms(2000);
  193.       lectura_pt100();
  194.       printf(lcd_putc,"\f   TEMPERATURA  \n    T:%3.1lf %cC    ",T,223);
  195.       delay_ms(2000);
  196.       lcd_putc("\f  SELECCION DE  \n      MODO      "); //seleccion del modo de trabajo
  197.       delay_ms(2000);
  198.       dispensados=0;
  199.       //**********************Inicializacion de grafcet
  200.       Y[0]=1;
  201.       Y[1]=0;
  202.       Y[2]=0;
  203.       Y[3]=0;
  204.       Y[4]=0;
  205.       Y[5]=0;
  206.       Y[6]=0;
  207.       Y[7]=0;
  208.       Y[8]=0;
  209.       Y[9]=0;
  210.      
  211.       //**********************Programa principal
  212.       while(1){ //El ciclo de programa se debe repetir indefinidamente.
  213.          Va[0]=Y[0]; //Ahora vamos a validar las transiciones. Una transición es válida cuando todas las etapas inmediatamente anteriores son activas.
  214.          Va[1]=Y[0];
  215.          Va[2]=Y[0];
  216.          Va[3]=Y[1];
  217.          Va[4]=Y[2];
  218.          Va[5]=Y[5];
  219.          Va[6]=Y[3];
  220.          Va[7]=Y[3];
  221.          Va[8]=Y[6];
  222.          Va[9]=Y[9];
  223.          Va[10]=Y[4];
  224.          Va[11]=Y[7];
  225.          Va[12]=Y[7];
  226.          Va[13]=Y[8];
  227.          //****************************************************************************************************************
  228.          //Después programaremos las acciones asociadas a las etapas.
  229.          if(Y[0]==1){ //Reposo
  230.             printf(lcd_putc,"\f1-FREIDO\n2-DRENAJE  T:%3.0lf %cC",T,223); //freido o drenaje
  231.             lectura_pt100();
  232.             listo=0;
  233.          }
  234.          if(Y[1]==1){ //Recomendacion de drenaje
  235.             lcd_putc("\fSE RECOMIENDA\nDRENAR ACEITE");
  236.                delay_ms(2000);
  237.             listo=1;
  238.          }
  239.          if(Y[2]==1){ //Llenado de extrusora
  240.             printf(lcd_putc,"\fMODO FREIDO\n           T:%3.0lf %cC",T,223);
  241.                delay_ms(2000);
  242.                printf(lcd_putc,"\fINSERTE MASA DE\nCHURROS    T:%3.0lf %cC",T,223);
  243.                delay_ms(2000);
  244.                lcd_putc("\fPRESIONE 1 PARA\nINICIAR PROCESO"); //espera a que el usuario presione 1 para iniciar el proceso
  245.                lectura_pt100();
  246.                while(input(PIN_C3)==0){
  247.                }
  248.          }
  249.          if(Y[3]==1){ //Dispensado
  250.             activar_dispensar();                  
  251.                desactivar_dispensar();
  252.          }
  253.          if(Y[4]==1){ //Freido
  254.             freir_churros();            
  255.          }
  256.          if(Y[5]==1){ //Enfriado de aceite
  257.             output_low(PIN_B1);
  258.                printf(lcd_putc,"\fMODO DRENAJE\n           T:%3.0lf %cC",T,223);
  259.                delay_ms(2000);
  260.                lcd_putc("\fENFRIANDO ACEITE");
  261.                delay_ms(2000);
  262.                while(T>50){ //se apaga la resistencia hasta alcanzar los 50°C, para proceder a drenar el aceite
  263.                   lectura_T();
  264.                    printf(lcd_putc,"\f   ENFRIANDO   \n    T:%3.1lf %cC    ",T,223);
  265.                    delay_ms(1000);
  266.                }
  267.          }
  268.          if(Y[6]==1){ //Drenaje de aceite
  269.             printf(lcd_putc,"\fDRENANDO ACEITE\n           T:%3.0lf %cC",T,223);
  270.             delay_ms(2000);
  271.             output_high(PIN_B2); //enciende valvula de drenaje
  272.             delay_ms(10000); //tiempo de activacion de valvula de drenaje
  273.             output_low(PIN_B2); //apaga valvula de drenaje
  274.             freidos=0;
  275.             printf(lcd_putc,"\f   SIN ACEITE   \n           T:%3.0lf %cC",T,223);
  276.             delay_ms(2000);
  277.             listo=1;
  278.          }
  279.          if(Y[7]==1){ //Extraccion
  280.             extraer_churros();
  281.          }
  282.          if(Y[8]==1){ //Tanda de churros lista
  283.             lectura_pt100();
  284.                dispensados=0;
  285.                printf(lcd_putc,"\fTANDA DE CHURROS\nLISTA   T:%3.0lf %cC",T,223);
  286.                delay_ms(2000);
  287.                lcd_putc("\fPOSICIONANDO\nMECANISMOS");
  288.                posicion_inicial();
  289.                freidos++;
  290.          }
  291.          if(Y[9]==1){ //Freido y extraccion de emergencia
  292.             freir_churros();
  293.                extraer_churros();
  294.          }
  295.          //****************************************************************************************************************
  296.          Re[0]=((input(PIN_C3)==1)&&(input(PIN_C4)==0)&&(input(PIN_B7)==0)&&(freidos>=3)); //Continuamos con las condiciones de transición.
  297.          Re[1]=((input(PIN_C3)==1)&&(input(PIN_C4)==0)&&(input(PIN_B7)==0)&&(freidos<3));
  298.          Re[2]=((input(PIN_C3)==0)&&(input(PIN_C4)==1)&&(input(PIN_B7)==0));
  299.          Re[3]=(Listo==1);
  300.          Re[4]=((input(PIN_C3)==1));
  301.          Re[5]=(T<=50);
  302.          Re[6]=((input_state(PIN_E0)==1)&&(input_state(PIN_E1)==1)&&(input(PIN_C5)==1));
  303.          Re[7]=((input_state(PIN_E0)==1)&&(input_state(PIN_E1)==1)&&(input(PIN_C5)==0));
  304.          Re[8]=(Listo==1);
  305.          Re[9]=(input_state(PIN_E2)==1);
  306.          Re[10]=(desbordes0==0);
  307.          Re[11]=((input_state(PIN_E2)==1)&&(dispensados>=4));
  308.          Re[12]=((input_state(PIN_E2)==1)&&(dispensados<4));
  309.          Re[13]=((input_state(PIN_E2)==1));
  310.          //****************************************************************************************************************
  311.          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.
  312.          if ((Re[3]*Va[3])){Y[1]=0;}
  313.          if ((Re[4]*Va[4])){Y[2]=0;}
  314.          if ((Re[6]*Va[6])||(Re[7]*Va[7])){Y[3]=0;}
  315.          if ((Re[10]*Va[10])){Y[4]=0;}
  316.          if ((Re[5]*Va[5])){Y[5]=0;}
  317.          if ((Re[8]*Va[8])){Y[6]=0;}
  318.          if ((Re[12]*Va[12])||(Re[11]*Va[11])){Y[7]=0;}
  319.          if ((Re[13]*Va[13])){Y[8]=0;}
  320.          if ((Re[9]*Va[9])){Y[9]=0;}
  321.          //****************************************************************************************************************
  322.          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.
  323.          if ((Re[0]*Va[0])){Y[1]=1;}
  324.          if ((Re[1]*Va[1])){Y[2]=1;}
  325.          if ((Re[4]*Va[4])||(Re[12]*Va[12])){Y[3]=1;}
  326.          if ((Re[7]*Va[7])){Y[4]=1;}
  327.          if ((Re[2]*Va[2])){Y[5]=1;}
  328.          if ((Re[5]*Va[5])){Y[6]=1;}
  329.          if ((Re[10]*Va[10])){Y[7]=1;}
  330.          if ((Re[11]*Va[11])||(Re[9]*Va[9])){Y[8]=1;}
  331.          if ((Re[6]*Va[6])){Y[9]=1;}
  332.          //****************************************************************************************************************
  333.  
  334.          
  335.              
  336.      }
  337.      
  338.  
  339. }
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 31 de Diciembre de 2019, 10:31:19
... siendo honesto no entendi mucho como implementar varios grafcet en un solo codigo,

Es sencillo. Solo tienes que programar las transiciones y las salidas del segundo grafcet después de las del primero y ya está.




Una cosa que falta es programar los temporizadores para que no bloqueen el programa. En este tipo de programa no se puede poner un delay porque se para todo lo demás.

Tienes que comenzar por hacer una rutina de interrupción que cuente milisegundos en una variable que se llame por ejemplo "milisegundos".
Luego tienes que contar los milisegundos de 100 en 100 para actualizar otra variable que se llame decisegundos.

Hay varias formas de programar los temporizadores. Adjunto una como ejemplo.


Código: C
  1. unsigned int decisegundos;  // Décimas de segundo. Actualizado por interrupciones
  2.  
  3.  
  4. typedef struct {
  5.    unsigned int contador;
  6.    unsigned char estado;
  7. } tipo_temporizador;
  8.  
  9. #define TEMPORIZADOR_REPOSO      0
  10. #define TEMPORIZADOR_CONTANDO  1
  11. #define TEMPORIZADOR_TERMINADO 2
  12. #define TEMPORIZADOR_UN_MINUTO  600
  13.  
  14. tipo_temporizador temp1, temp2;
  15.  
  16.  
  17. // Inicialización de temporizador. Reset inicial al comenzar el programa.
  18.    temp1.estado = TEMPORIZADOR_REPOSO;
  19.  
  20.  
  21. // Inicio de cuenta de tiempo. Se debe programar cuando se encuentre en el estado correspondiente
  22.    if (temp1.estado == TEMPORIZADOR_REPOSO) {
  23.       temp1.contador = decisegundos + TEMPORIZADOR_UN_MINUTO;
  24.       temp1.estado = TEMPORIZADOR_CONTANDO;
  25.    }
  26.  
  27.  
  28. // Comprobación de que el contador ha llegado al final de la cuenta
  29.  
  30.    if ((decisegundos - temp1.contador) < TEMPORIZADOR_UN_MINUTO) {
  31.       temp1.estado = TEMPORIZADOR_TERMINADO;
  32.    }
  33.  
  34.  
  35. // En la transición donde se utilice el temporizador o en otro estado, es necesario resetear de nuevo el temporizador
  36.    temp1.estado = TEMPORIZADOR_REPOSO;
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 31 de Diciembre de 2019, 10:42:55
Pero creo que deberías comenzar por hacer un programa muy sencillito de tipo encender y apagar una luz para entender cómo funciona el grafcet y luego comienzas con tu programa.

Aquí te dejo un grafcet sencillo que enciende y apaga una luz con un solo pulsador.

(http://www.todopic.com.ar/foros/index.php?action=dlattach;topic=48415.0;attach=28765)

Te propongo que hagas un programa para manejar 2 grafcet, cada uno con un led y con un pulsador diferente y así puedes comprobar cómo pueden trabajar dos grafcet a la vez.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 01 de Enero de 2020, 14:38:29
Si tengo algo de tiempo lo programaré para que veas cómo se hace.

Otra idea es hacer las tareas que hace el grafcet con un RTOS, pero tal y como van las cosas hoy en día con los PIC antes te recomendaría que te pasaras a los microcontroladores ATmega (Los que traen las placas Arduino). Con un Arduino es muy sencillo utilizar un RTOS que es un sistema operativo en tiempo real con el que puedes programar varias tareas que se ejecutan todas al mismo tiempo.

En los PIC también hay sistemas operativos en tiempo real (RTOS) pero parece que están algo desfasados hoy en día.
El SALVO es de pago aunque tiene una versión gratuíta que permite hasta 3 tareas.
El RTOS OSA es libre pero igual que el anterior está un poco desfasado y hay que compilarle con compiladores antiguos.

Un saludo.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 02 de Enero de 2020, 08:28:27
Adjunto un programa para Arduino, en C, que implementa dos grafcets para encender y apagar dos ledes con dos pulsadores. Cada grafcet es independiente uno del otro y se ejecutan en paralelo.

Código: C
  1. /*
  2.  * Implementación de Grafcet
  3.  * para encender dos ledes con dos pulsadores
  4.  */
  5.  
  6. // Definiciones
  7. #define NUMERO_DE_GRAFCETS  2
  8. #define NUMERO_DE_ENTRADAS  2
  9. #define NUMERO_DE_SALIDAS   2
  10.  
  11. #define PIN_LED_VERDE   2
  12. #define PIN_LED_ROJO    3
  13. #define PIN_PULSADOR_1  8
  14. #define PIN_PULSADOR_2  9
  15.  
  16. #define PULSADOR_PRESIONADO  0
  17. #define PULSADOR_REPOSO      1
  18. #define LED_ENCENDIDO        1
  19. #define LED_APAGADO          0
  20.  
  21.  
  22. enum NOMBRE_GRAFCETS {
  23.    GRAFCET_LED_VERDE,
  24.    GRAFCET_LED_ROJO,
  25. };
  26.  
  27. enum ENTRADAS_FISICAS {
  28.    PULSADOR_1,
  29.    PULSADOR_2,
  30. };
  31.  
  32. enum SALIDAS_FISICAS {
  33.    LED_VERDE,
  34.    LED_ROJO,
  35. };
  36.  
  37. typedef union  {
  38.   struct {
  39.     unsigned char etapa0: 1;
  40.     unsigned char etapa1: 1;
  41.     unsigned char etapa2: 1;
  42.     unsigned char etapa3: 1;
  43.     unsigned char etapa4: 1;
  44.     unsigned char etapa5: 1;
  45.     unsigned char etapa6: 1;
  46.     unsigned char etapa7: 1;
  47.   };
  48.   unsigned char etapas;
  49. } tipo_grafcet;
  50.  
  51.  
  52. // Declaración de variables
  53. tipo_grafcet grafcet[NUMERO_DE_GRAFCETS];
  54. tipo_grafcet grafcet_siguiente[NUMERO_DE_GRAFCETS];
  55. unsigned char entradas[NUMERO_DE_ENTRADAS];
  56. unsigned char salidas[NUMERO_DE_SALIDAS];
  57.  
  58.  
  59. // Programa principal
  60. void setup(void) {
  61.    setup_pines();
  62.    grafcet_inicializar();
  63.    while(1) {
  64.       print_estado();
  65.       leer_entradas();
  66.       grafcets_evoluciona();
  67.       escribir_salidas();
  68.       temporizadores();
  69.    }
  70. }
  71.  
  72. void loop(void) {
  73. }
  74.  
  75.  
  76. //
  77. // Funciones del programa principal
  78. //
  79.  
  80. void setup_pines(void) {
  81.    pinMode(PIN_LED_VERDE, OUTPUT);
  82.    pinMode(PIN_LED_ROJO, OUTPUT);
  83.    pinMode(PIN_PULSADOR_1, INPUT_PULLUP);
  84.    pinMode(PIN_PULSADOR_2, INPUT_PULLUP);
  85.  
  86.    Serial.begin(9600);
  87. }
  88.  
  89. void grafcet_inicializar(void) {
  90.    grafcet_siguiente[GRAFCET_LED_VERDE].etapas = 0;
  91.    grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;
  92.  
  93.    grafcet_siguiente[GRAFCET_LED_ROJO].etapas = 0;
  94.    grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
  95. }
  96.  
  97.  
  98. void leer_entradas(void) {
  99.    entradas[PULSADOR_1] = digitalRead(PIN_PULSADOR_1);
  100.    entradas[PULSADOR_2] = digitalRead(PIN_PULSADOR_2);
  101. }
  102.  
  103.  
  104. void escribir_salidas(void) {
  105.    digitalWrite(PIN_LED_VERDE, salidas[LED_VERDE]);
  106.    digitalWrite(PIN_LED_ROJO, salidas[LED_ROJO]);
  107. }
  108.  
  109.  
  110. void grafcets_evoluciona(void) {
  111.    grafcets_copiar_transiciones();
  112.    grafcets_calcular_transiciones();
  113.    grafcets_calcular_acciones();
  114. }
  115.  
  116.  
  117. void grafcets_copiar_transiciones(void) {
  118.    grafcet[GRAFCET_LED_VERDE].etapas = grafcet_siguiente[GRAFCET_LED_VERDE].etapas;
  119.    grafcet[GRAFCET_LED_ROJO].etapas = grafcet_siguiente[GRAFCET_LED_ROJO].etapas;
  120. }
  121.  
  122.  
  123. void grafcets_calcular_transiciones(void) {
  124.  
  125.    // GRAFCET_LED_VERDE
  126.    if (grafcet[GRAFCET_LED_VERDE].etapa0 == 1 &&
  127.        entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
  128.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 0;
  129.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 1;
  130.    }
  131.  
  132.    if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 &&
  133.        entradas[PULSADOR_1] == PULSADOR_REPOSO) {
  134.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 0;
  135.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 1;
  136.    }
  137.  
  138.    if (grafcet[GRAFCET_LED_VERDE].etapa2 == 1 &&
  139.        entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
  140.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 0;
  141.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 1;
  142.    }
  143.  
  144.    if (grafcet[GRAFCET_LED_VERDE].etapa3 == 1 &&
  145.        entradas[PULSADOR_1] == PULSADOR_REPOSO) {
  146.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 0;
  147.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;
  148.    }
  149.  
  150.    // GRAFCET_LED_ROJO
  151.    if (grafcet[GRAFCET_LED_ROJO].etapa0 == 1 &&
  152.        entradas[PULSADOR_2] == PULSADOR_PRESIONADO) {
  153.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 0;
  154.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 1;
  155.    }
  156.  
  157.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 &&
  158.        entradas[PULSADOR_2] == PULSADOR_REPOSO) {
  159.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 0;
  160.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa2 = 1;
  161.    }
  162.  
  163.    if (grafcet[GRAFCET_LED_ROJO].etapa2 == 1 &&
  164.        entradas[PULSADOR_2] == PULSADOR_PRESIONADO) {
  165.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa2 = 0;
  166.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa3 = 1;
  167.    }
  168.  
  169.    if (grafcet[GRAFCET_LED_ROJO].etapa3 == 1 &&
  170.        entradas[PULSADOR_2] == PULSADOR_REPOSO) {
  171.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa3 = 0;
  172.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
  173.    }
  174. }
  175.  
  176.  
  177. void grafcets_calcular_acciones(void) {
  178.    if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 ||
  179.        grafcet[GRAFCET_LED_VERDE].etapa2 == 1 ) {
  180.       salidas[LED_VERDE] = LED_ENCENDIDO;
  181.    }
  182.    else {
  183.       salidas[LED_VERDE] = LED_APAGADO;  
  184.    }
  185.  
  186.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 ||
  187.        grafcet[GRAFCET_LED_ROJO].etapa2 == 1 ) {
  188.       salidas[LED_ROJO] = LED_ENCENDIDO;
  189.    }
  190.    else {
  191.       salidas[LED_ROJO] = LED_APAGADO;  
  192.    }
  193. }
  194.  
  195.  
  196. void temporizadores(void) {
  197.  
  198. }
  199.  
  200. void print_estado(void) {
  201.    Serial.print("Etapas:");
  202.    Serial.print("  Grafcet led verde=");
  203.    Serial.print(grafcet[GRAFCET_LED_VERDE].etapas);
  204.    Serial.print("  Grafcet led rojo =");
  205.    Serial.print(grafcet[GRAFCET_LED_ROJO].etapas);
  206.    Serial.println();
  207. }

Esquema:

  - Tienes que ingresar para ver archivos adjuntos -


Protoboard:

  - Tienes que ingresar para ver archivos adjuntos -
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 02 de Enero de 2020, 16:55:23
Otro programa más.

El primer led (VERDE) se enciende y se apaga al presionar el pulsador 1.

El segundo led (ROJO) se enciende durante 10 segundos cuando se presiona el pulsador 2.

Código: C
  1. /*
  2.  * Implementación de Grafcet
  3.  * para encender dos led con dos pulsadores
  4.  *
  5.  * El primer led verde se enciende y se apaga
  6.  * al presionar el pulsador 1.
  7.  *
  8.  * El segundo led rojo se enciende durante
  9.  * 10 segundos al presionar el pulsador 2
  10.  *
  11.  */
  12.  
  13. // Definiciones
  14. #define NUMERO_DE_GRAFCETS  2
  15. #define NUMERO_DE_ENTRADAS  2
  16. #define NUMERO_DE_SALIDAS   2
  17.  
  18. #define PIN_LED_VERDE   2
  19. #define PIN_LED_ROJO    3
  20. #define PIN_PULSADOR_1  8
  21. #define PIN_PULSADOR_2  9
  22.  
  23. #define PULSADOR_PRESIONADO  0
  24. #define PULSADOR_REPOSO      1
  25. #define LED_ENCENDIDO        1
  26. #define LED_APAGADO          0
  27.  
  28.  
  29. enum ENTRADAS_FISICAS {
  30.    PULSADOR_1,
  31.    PULSADOR_2,
  32. };
  33.  
  34. enum SALIDAS_FISICAS {
  35.    LED_VERDE,
  36.    LED_ROJO,
  37. };
  38.  
  39. enum NOMBRE_GRAFCETS {
  40.    GRAFCET_LED_VERDE,
  41.    GRAFCET_LED_ROJO,
  42. };
  43.  
  44. enum TEMPORIZADOR_ESTADOS {
  45.    TEMPORIZADOR_REPOSO,
  46.    TEMPORIZADOR_CONTANDO,
  47.    TEMPORIZADOR_TERMINADO,
  48. };
  49.  
  50. typedef union  {
  51.   struct {
  52.     unsigned char etapa0: 1;
  53.     unsigned char etapa1: 1;
  54.     unsigned char etapa2: 1;
  55.     unsigned char etapa3: 1;
  56.     unsigned char etapa4: 1;
  57.     unsigned char etapa5: 1;
  58.     unsigned char etapa6: 1;
  59.     unsigned char etapa7: 1;
  60.   };
  61.   unsigned char etapas;
  62. } tipo_grafcet;
  63.  
  64. typedef struct {
  65.    unsigned char estado;
  66.    unsigned int tiempo;
  67. } tipo_temporizador;
  68.  
  69.  
  70. // Declaración de variables
  71. unsigned char entradas[NUMERO_DE_ENTRADAS];
  72. unsigned char salidas[NUMERO_DE_SALIDAS];
  73. tipo_grafcet grafcet[NUMERO_DE_GRAFCETS];
  74. tipo_grafcet grafcet_siguiente[NUMERO_DE_GRAFCETS];
  75. tipo_temporizador temporizador_1;
  76. unsigned int decisegundos;
  77. unsigned long cien_milisegundos;
  78.  
  79. // Programa principal
  80. void setup(void) {
  81.    setup_pines();
  82.    inicializar_grafcets();
  83.    inicializar_temporizadores();
  84.    
  85.    while(1) {
  86.       print_estado();
  87.       leer_entradas();
  88.       grafcets_evoluciona();
  89.       escribir_salidas();
  90.       temporizadores();
  91.    }
  92. }
  93.  
  94. void loop(void) {
  95. }
  96.  
  97.  
  98. //
  99. // Funciones del programa principal
  100. //
  101.  
  102. void setup_pines(void) {
  103.    pinMode(PIN_LED_VERDE, OUTPUT);
  104.    pinMode(PIN_LED_ROJO, OUTPUT);
  105.    pinMode(PIN_PULSADOR_1, INPUT_PULLUP);
  106.    pinMode(PIN_PULSADOR_2, INPUT_PULLUP);
  107.  
  108.    Serial.begin(9600);
  109. }
  110.  
  111.  
  112. void inicializar_grafcets(void) {
  113.    grafcet_siguiente[GRAFCET_LED_VERDE].etapas = 0;
  114.    grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;
  115.  
  116.    grafcet_siguiente[GRAFCET_LED_ROJO].etapas = 0;
  117.    grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
  118. }
  119.  
  120.  
  121. void inicializar_temporizadores(void) {
  122.    temporizador_1.estado = TEMPORIZADOR_REPOSO;
  123.  
  124.    cien_milisegundos = millis() + 100;
  125.    decisegundos = 0;
  126. }
  127.  
  128.  
  129. void leer_entradas(void) {
  130.    entradas[PULSADOR_1] = digitalRead(PIN_PULSADOR_1);
  131.    entradas[PULSADOR_2] = digitalRead(PIN_PULSADOR_2);
  132. }
  133.  
  134.  
  135. void escribir_salidas(void) {
  136.    digitalWrite(PIN_LED_VERDE, salidas[LED_VERDE]);
  137.    digitalWrite(PIN_LED_ROJO, salidas[LED_ROJO]);
  138. }
  139.  
  140.  
  141. void grafcets_evoluciona(void) {
  142.    grafcets_copiar_transiciones();
  143.    grafcets_calcular_transiciones();
  144.    grafcets_calcular_acciones();
  145. }
  146.  
  147.  
  148. void grafcets_copiar_transiciones(void) {
  149.    grafcet[GRAFCET_LED_VERDE].etapas = grafcet_siguiente[GRAFCET_LED_VERDE].etapas;
  150.    grafcet[GRAFCET_LED_ROJO].etapas = grafcet_siguiente[GRAFCET_LED_ROJO].etapas;
  151. }
  152.  
  153.  
  154. void grafcets_calcular_transiciones(void) {
  155.  
  156.    // GRAFCET_LED_VERDE
  157.    if (grafcet[GRAFCET_LED_VERDE].etapa0 == 1 &&
  158.        entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
  159.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 0;
  160.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 1;
  161.    }
  162.  
  163.    if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 &&
  164.        entradas[PULSADOR_1] == PULSADOR_REPOSO) {
  165.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 0;
  166.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 1;
  167.    }
  168.  
  169.    if (grafcet[GRAFCET_LED_VERDE].etapa2 == 1 &&
  170.        entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
  171.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 0;
  172.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 1;
  173.    }
  174.  
  175.    if (grafcet[GRAFCET_LED_VERDE].etapa3 == 1 &&
  176.        entradas[PULSADOR_1] == PULSADOR_REPOSO) {
  177.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 0;
  178.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;
  179.    }
  180.  
  181.    // GRAFCET_LED_ROJO TEMPORIZADO
  182.    if (grafcet[GRAFCET_LED_ROJO].etapa0 == 1 &&
  183.        entradas[PULSADOR_2] == PULSADOR_PRESIONADO) {
  184.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 0;
  185.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 1;
  186.    }
  187.  
  188.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 &&
  189.        temporizador_1.estado == TEMPORIZADOR_TERMINADO) {
  190.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 0;
  191.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
  192.    }
  193. }
  194.  
  195.  
  196. void grafcets_calcular_acciones(void) {
  197.    if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 ||
  198.        grafcet[GRAFCET_LED_VERDE].etapa2 == 1 ) {
  199.       salidas[LED_VERDE] = LED_ENCENDIDO;
  200.    }
  201.    else {
  202.       salidas[LED_VERDE] = LED_APAGADO;  
  203.    }
  204.  
  205.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 ) {
  206.       salidas[LED_ROJO] = LED_ENCENDIDO;
  207.    }
  208.    else {
  209.       salidas[LED_ROJO] = LED_APAGADO;  
  210.    }
  211. }
  212.  
  213.  
  214. void temporizadores(void) {
  215.    // Temporizador 1
  216.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 0) {
  217.       temporizador_1.estado = TEMPORIZADOR_REPOSO;
  218.    }
  219.  
  220.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 &&
  221.        temporizador_1.estado == TEMPORIZADOR_REPOSO) {
  222.       temporizador_1.tiempo = decisegundos + 100;
  223.       temporizador_1.estado = TEMPORIZADOR_CONTANDO;
  224.    }
  225.  
  226.    if (temporizador_1.estado == TEMPORIZADOR_CONTANDO &&
  227.        decisegundos - temporizador_1.tiempo < 500 ) {
  228.       temporizador_1.estado = TEMPORIZADOR_TERMINADO;  
  229.    }
  230.  
  231.    // Actualizar decisegundos
  232.    if (millis() - cien_milisegundos < 10000 ) {
  233.       cien_milisegundos += 100;
  234.       decisegundos += 1;
  235.    }
  236. }
  237.  
  238.  
  239. void print_estado(void) {
  240.    Serial.print("Grafcet led verde=");
  241.    Serial.print(grafcet[GRAFCET_LED_VERDE].etapas);
  242.    Serial.print(" Grafcet led rojo=");
  243.    Serial.print(grafcet[GRAFCET_LED_ROJO].etapas);
  244.    Serial.print(" Temporizador=");
  245.    Serial.print(temporizador_1.estado);
  246.    Serial.print(" ");
  247.    Serial.print(temporizador_1.tiempo);
  248.    Serial.println();
  249. }

Adjunto grafcet del segundo led (ROJO).
  - Tienes que ingresar para ver archivos adjuntos -  
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 02 de Enero de 2020, 18:26:45
Otro programa más.

El primer led (VERDE) se enciende y se apaga al presionar el pulsador 1.

El segundo led (ROJO) se enciende durante 10 segundos cuando se presiona el pulsador 2.

Código: C
  1. /*
  2.  * Implementación de Grafcet
  3.  * para encender dos led con dos pulsadores
  4.  *
  5.  * El primer led verde se enciende y se apaga
  6.  * al presionar el pulsador 1.
  7.  *
  8.  * El segundo led rojo se enciende durante
  9.  * 10 segundos al presionar el pulsador 2
  10.  *
  11.  */
  12.  
  13. // Definiciones
  14. #define NUMERO_DE_GRAFCETS  2
  15. #define NUMERO_DE_ENTRADAS  2
  16. #define NUMERO_DE_SALIDAS   2
  17.  
  18. #define PIN_LED_VERDE   2
  19. #define PIN_LED_ROJO    3
  20. #define PIN_PULSADOR_1  8
  21. #define PIN_PULSADOR_2  9
  22.  
  23. #define PULSADOR_PRESIONADO  0
  24. #define PULSADOR_REPOSO      1
  25. #define LED_ENCENDIDO        1
  26. #define LED_APAGADO          0
  27.  
  28.  
  29. enum ENTRADAS_FISICAS {
  30.    PULSADOR_1,
  31.    PULSADOR_2,
  32. };
  33.  
  34. enum SALIDAS_FISICAS {
  35.    LED_VERDE,
  36.    LED_ROJO,
  37. };
  38.  
  39. enum NOMBRE_GRAFCETS {
  40.    GRAFCET_LED_VERDE,
  41.    GRAFCET_LED_ROJO,
  42. };
  43.  
  44. enum TEMPORIZADOR_ESTADOS {
  45.    TEMPORIZADOR_REPOSO,
  46.    TEMPORIZADOR_CONTANDO,
  47.    TEMPORIZADOR_TERMINADO,
  48. };
  49.  
  50. typedef union  {
  51.   struct {
  52.     unsigned char etapa0: 1;
  53.     unsigned char etapa1: 1;
  54.     unsigned char etapa2: 1;
  55.     unsigned char etapa3: 1;
  56.     unsigned char etapa4: 1;
  57.     unsigned char etapa5: 1;
  58.     unsigned char etapa6: 1;
  59.     unsigned char etapa7: 1;
  60.   };
  61.   unsigned char etapas;
  62. } tipo_grafcet;
  63.  
  64. typedef struct {
  65.    unsigned char estado;
  66.    unsigned int tiempo;
  67. } tipo_temporizador;
  68.  
  69.  
  70. // Declaración de variables
  71. unsigned char entradas[NUMERO_DE_ENTRADAS];
  72. unsigned char salidas[NUMERO_DE_SALIDAS];
  73. tipo_grafcet grafcet[NUMERO_DE_GRAFCETS];
  74. tipo_grafcet grafcet_siguiente[NUMERO_DE_GRAFCETS];
  75. tipo_temporizador temporizador_1;
  76. unsigned int decisegundos;
  77. unsigned long cien_milisegundos;
  78.  
  79. // Programa principal
  80. void setup(void) {
  81.    setup_pines();
  82.    inicializar_grafcets();
  83.    inicializar_temporizadores();
  84.    
  85.    while(1) {
  86.       print_estado();
  87.       leer_entradas();
  88.       grafcets_evoluciona();
  89.       escribir_salidas();
  90.       temporizadores();
  91.    }
  92. }
  93.  
  94. void loop(void) {
  95. }
  96.  
  97.  
  98. //
  99. // Funciones del programa principal
  100. //
  101.  
  102. void setup_pines(void) {
  103.    pinMode(PIN_LED_VERDE, OUTPUT);
  104.    pinMode(PIN_LED_ROJO, OUTPUT);
  105.    pinMode(PIN_PULSADOR_1, INPUT_PULLUP);
  106.    pinMode(PIN_PULSADOR_2, INPUT_PULLUP);
  107.  
  108.    Serial.begin(9600);
  109. }
  110.  
  111.  
  112. void inicializar_grafcets(void) {
  113.    grafcet_siguiente[GRAFCET_LED_VERDE].etapas = 0;
  114.    grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;
  115.  
  116.    grafcet_siguiente[GRAFCET_LED_ROJO].etapas = 0;
  117.    grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
  118. }
  119.  
  120.  
  121. void inicializar_temporizadores(void) {
  122.    temporizador_1.estado = TEMPORIZADOR_REPOSO;
  123.  
  124.    cien_milisegundos = millis() + 100;
  125.    decisegundos = 0;
  126. }
  127.  
  128.  
  129. void leer_entradas(void) {
  130.    entradas[PULSADOR_1] = digitalRead(PIN_PULSADOR_1);
  131.    entradas[PULSADOR_2] = digitalRead(PIN_PULSADOR_2);
  132. }
  133.  
  134.  
  135. void escribir_salidas(void) {
  136.    digitalWrite(PIN_LED_VERDE, salidas[LED_VERDE]);
  137.    digitalWrite(PIN_LED_ROJO, salidas[LED_ROJO]);
  138. }
  139.  
  140.  
  141. void grafcets_evoluciona(void) {
  142.    grafcets_copiar_transiciones();
  143.    grafcets_calcular_transiciones();
  144.    grafcets_calcular_acciones();
  145. }
  146.  
  147.  
  148. void grafcets_copiar_transiciones(void) {
  149.    grafcet[GRAFCET_LED_VERDE].etapas = grafcet_siguiente[GRAFCET_LED_VERDE].etapas;
  150.    grafcet[GRAFCET_LED_ROJO].etapas = grafcet_siguiente[GRAFCET_LED_ROJO].etapas;
  151. }
  152.  
  153.  
  154. void grafcets_calcular_transiciones(void) {
  155.  
  156.    // GRAFCET_LED_VERDE
  157.    if (grafcet[GRAFCET_LED_VERDE].etapa0 == 1 &&
  158.        entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
  159.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 0;
  160.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 1;
  161.    }
  162.  
  163.    if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 &&
  164.        entradas[PULSADOR_1] == PULSADOR_REPOSO) {
  165.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa1 = 0;
  166.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 1;
  167.    }
  168.  
  169.    if (grafcet[GRAFCET_LED_VERDE].etapa2 == 1 &&
  170.        entradas[PULSADOR_1] == PULSADOR_PRESIONADO) {
  171.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa2 = 0;
  172.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 1;
  173.    }
  174.  
  175.    if (grafcet[GRAFCET_LED_VERDE].etapa3 == 1 &&
  176.        entradas[PULSADOR_1] == PULSADOR_REPOSO) {
  177.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa3 = 0;
  178.       grafcet_siguiente[GRAFCET_LED_VERDE].etapa0 = 1;
  179.    }
  180.  
  181.    // GRAFCET_LED_ROJO TEMPORIZADO
  182.    if (grafcet[GRAFCET_LED_ROJO].etapa0 == 1 &&
  183.        entradas[PULSADOR_2] == PULSADOR_PRESIONADO) {
  184.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 0;
  185.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 1;
  186.    }
  187.  
  188.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 &&
  189.        temporizador_1.estado == TEMPORIZADOR_TERMINADO) {
  190.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa1 = 0;
  191.       grafcet_siguiente[GRAFCET_LED_ROJO].etapa0 = 1;
  192.    }
  193. }
  194.  
  195.  
  196. void grafcets_calcular_acciones(void) {
  197.    if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1 ||
  198.        grafcet[GRAFCET_LED_VERDE].etapa2 == 1 ) {
  199.       salidas[LED_VERDE] = LED_ENCENDIDO;
  200.    }
  201.    else {
  202.       salidas[LED_VERDE] = LED_APAGADO;  
  203.    }
  204.  
  205.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 ) {
  206.       salidas[LED_ROJO] = LED_ENCENDIDO;
  207.    }
  208.    else {
  209.       salidas[LED_ROJO] = LED_APAGADO;  
  210.    }
  211. }
  212.  
  213.  
  214. void temporizadores(void) {
  215.    // Temporizador 1
  216.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 0) {
  217.       temporizador_1.estado = TEMPORIZADOR_REPOSO;
  218.    }
  219.  
  220.    if (grafcet[GRAFCET_LED_ROJO].etapa1 == 1 &&
  221.        temporizador_1.estado == TEMPORIZADOR_REPOSO) {
  222.       temporizador_1.tiempo = decisegundos + 100;
  223.       temporizador_1.estado = TEMPORIZADOR_CONTANDO;
  224.    }
  225.  
  226.    if (temporizador_1.estado == TEMPORIZADOR_CONTANDO &&
  227.        decisegundos - temporizador_1.tiempo < 500 ) {
  228.       temporizador_1.estado = TEMPORIZADOR_TERMINADO;  
  229.    }
  230.  
  231.    // Actualizar decisegundos
  232.    if (millis() - cien_milisegundos < 10000 ) {
  233.       cien_milisegundos += 100;
  234.       decisegundos += 1;
  235.    }
  236. }
  237.  
  238.  
  239. void print_estado(void) {
  240.    Serial.print("Grafcet led verde=");
  241.    Serial.print(grafcet[GRAFCET_LED_VERDE].etapas);
  242.    Serial.print(" Grafcet led rojo=");
  243.    Serial.print(grafcet[GRAFCET_LED_ROJO].etapas);
  244.    Serial.print(" Temporizador=");
  245.    Serial.print(temporizador_1.estado);
  246.    Serial.print(" ");
  247.    Serial.print(temporizador_1.tiempo);
  248.    Serial.println();
  249. }

Adjunto grafcet del segundo led (ROJO).
  - Tienes que ingresar para ver archivos adjuntos -

Gracias por los ejemplos  :-/ hace rato empece a analizar los otros programas y mas informacion que he ido encontrando, en un rato tratare de hacer estos que has compartido para entenderlos completamente, me intereso mucho el tema porque tambien se aplica en otras tecnologias. Muchas gracias de nuevo  :mrgreen:
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 05 de Enero de 2020, 10:33:41
¿Cómo vas con el programa?
No puse en el programa la forma de hacer los cálculos. Hay que añadir una variable para que se ejecuten una sola vez.

Algo así como esto:
Código: C
  1. #define OPERACION_SIN_REALIZAR 0
  2. #define OPERACION_REALIZADA    1
  3.  
  4. // Declaración de variables
  5. unsigned char operacion1;
  6.  
  7.  
  8.  
  9. void grafcets_calcular_acciones(void) {
  10.  
  11.    if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1) {
  12.       if (operacion1 == OPERACION_SIN_REALIZAR) {
  13.          // Aquí se realizan los cálculos asociados a la etapa1 del grafcet del LED verde.
  14.          // Este código se ejecutará una sola vez, cada vez que se active la etapa1 del grafcet.
  15.       }
  16.       operacion1 = OPERACION_REALIZADA;
  17.    }
  18.    else  {
  19.       operacion1 = OPERACION_SIN_REALIZAR;
  20.    }
  21.  
  22.  
  23.  
  24. }
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 06 de Enero de 2020, 17:58:45
¿Cómo vas con el programa?
No puse en el programa la forma de hacer los cálculos. Hay que añadir una variable para que se ejecuten una sola vez.

Algo así como esto:
Código: C
  1. #define OPERACION_SIN_REALIZAR 0
  2. #define OPERACION_REALIZADA    1
  3.  
  4. // Declaración de variables
  5. unsigned char operacion1;
  6.  
  7.  
  8.  
  9. void grafcets_calcular_acciones(void) {
  10.  
  11.    if (grafcet[GRAFCET_LED_VERDE].etapa1 == 1) {
  12.       if (operacion1 == OPERACION_SIN_REALIZAR) {
  13.          // Aquí se realizan los cálculos asociados a la etapa1 del grafcet del LED verde.
  14.          // Este código se ejecutará una sola vez, cada vez que se active la etapa1 del grafcet.
  15.       }
  16.       operacion1 = OPERACION_REALIZADA;
  17.    }
  18.    else  {
  19.       operacion1 = OPERACION_SIN_REALIZAR;
  20.    }
  21.  
  22.  
  23.  
  24. }

Saludos, ahi voy aprendiendo, realice los ejemplos que compartiste aca en el tema, han funcionado bien. Incluso hize otros que encontre por alli en internet, tambien intente implementar eso de la concurrencia, dos grafcet al mismo tiempo, y va de maravilla.

Si me di cuenta que al hacer el de el led temporizado habia que implementar una forma para que se realizara una sola vez. Tambien utilize los timers para ayudarme con el tema del tiempo y evitar el uso de los delays (cosa que hize mucho en la maquina de churros  :oops: ) Pero bueno con la practica he ido aprendiendo como se debe aplicar correctamente el Grafcet.

Queria acotar que este libro me ayudo mucho a entender mas a fondo esta forma de trabajar por si a alguien le interesa: Automatización de Procesos Mediante la Guía GEMMA - Pere Ponsa, Ramon Vilanova - se encuentra facil en internet si alguien lo quiere, trae informacion util y ejemplos muy buenos para iniciar (cosa que me cayo perfecto  :-/)

Mas tarde en la noche seguire practicando para pulirme un poco mas, y ver si finalmente puedo hacer de nuevo la programacion de la maquina implementando correctamente los diagramas
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 08 de Enero de 2020, 14:31:13
Gracias por el aporte. Es un libro interesante.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 14 de Enero de 2020, 22:13:24
Saludos, para actualizar el tema, he realizado ya el programa completo de la maquina de churros solo con grafcet (digamos que una version mas apegada a la programacion por medio de diagramas de grafcet). En la simulacion funciona muy bien, aparte de eso tendria que esperar esta semana que viene para poder probarlo en protoboard.  :lol:

He separado cada etapa del proceso en un diagrama de grafcet diferente para cada uno, asi solo tendria que "saltar" entre grafcet segun ciertas condiciones, haciendo que el programa sea mas entendible y si hay algun error en la parte fisica, si es un problema de programacion, se pueda identificar casi directamente sin empezar a buscar en cada parte del codigo, sino yendo direnctamente al grafcet y etapa correspondiente. De verdad que he aprendido mucho al trabajar de esta forma y me sera muy util para el futuro. Adjunto cada grafcet y el codigo completo por si alguien lo quiere ver y quiza dar un feedback  ;-)
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 15 de Enero de 2020, 14:52:48
Me alegro de que todo vaya bien.

Por otro lado, a los grafcet les falta la transición en todas las etapas de abajo. Hay que poner una transición a otra etapa.

Fíjate en otros grafcet de ejemplo y verás que son circulares, la última etapa vuelve a enlazar con la primera.

Un saludo.
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: hurtadoluisalex en 24 de Enero de 2020, 12:15:33
Bueno, para actualizar el tema y finiquitar el area de la programacion, informo que el programa funciono en protoboard casi perfecto, un par de errores que ya fueron corregidos y funciona muy bien, sin reinicios no se queda pegado como me pasaba con el primer codigo. Definitivamente los diagramas grafcet son una herramienta muy util para este tipo de maquinas   ((:-))

Solo me falta implementar un mejor arreglo para la pt100 ya que con el divisor de tension es muy inestable y da lugar a lecturas erroneas, lo hare con un puente de wheatstone, un par de buffers y un amplificador diferencial, ya que da lecturas mucho mas exactas y facilitan la lectura de la temperatura en la programacion  :-/  , cuando este terminada la maquina colocare un video en funcionamiento  :mrgreen: pero sera un unas semanas  :oops:
Título: Re:Ayuda | Proyecto Final problema con maquina y PIC16F877A
Publicado por: Picuino en 24 de Enero de 2020, 13:08:37
Enhorabuena.