Autor Tema: Programación con maquinas de estado FSM para microcontroladores PIC  (Leído 7180 veces)

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

Desconectado joserafa83

  • PIC10
  • *
  • Mensajes: 4
Hola  a todos,

Hace muchos años no programaba los microcontroladores PIC (2006 aprox), por eso decide adquirir el PIC SIMULATOR IDE de www.oshonsoft.com el cual lo maneje en la universidad, pero al parecer ya no es tan popular este software  :shock:. La idea es agilizar la programación ( vengo del mundo del assembler  :? ).

Quiero compartir con ustedes una metodologia de programacion que se utiliza en la industria de los PLC, llamada Grafcet o SFC (depende del fabricante). Lo que permite esta metodología es dividir y ordenar tu programa para hacerlo mas fácil de depurar y codificar, esta basado en la lógica de maquinas de estado FSM.

Les comparto el siguiente ejemplo super básico:

encender y apagar un led de acuerdo al estado de un pulsador



La idea de esta metodología de programación es cambiar de estado a estado, mediante una señal de transición, en este caso la he llamado m0 (marca o memoria)

En este link de Omron, pueden entender mas a fondo el uso de esta metodología
http://www.edata.omron.com.au/eData/Software/CX-One/R149-E1-03.pdf

El código de programa en Basic seria el siguiente

Código: [Seleccionar]
'PIC12F675

Dim m0 As Byte
Symbol led_pin = GPIO.0
Symbol pulsador = GPIO.1

inicio:
m0 = 0
CMCON = 7
ANSEL = 0
TRISIO = %00000010
m0 = 1
If m0 = 1 Then
Goto led_off
Else
Goto inicio
Endif
led_off:
led_pin = 0
If pulsador = 1 Then
m0 = 2
Endif
If m0 = 2 Then
Goto led_on
Else
Goto led_off
Endif
led_on:
led_pin = 1
If pulsador = 0 Then
m0 = 1
Endif
If m0 = 1 Then
Goto led_off
Else
Goto led_on
Endif


Ahora estoy haciendo otros ejemplos de programación con SFC, que mas adelante les ire compartiendo









Desconectado dogflu66

  • Moderador Local
  • DsPIC30
  • *****
  • Mensajes: 3549
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #1 en: 05 de Enero de 2018, 14:11:08 »
Realmente el Pic Simulator es una buena herramienta que tiene un entorno que permite la simulación y depuración del código, tanto en lenguaje Basic como lenguaje maquina, y como las licencias son de bajo coste muchos centros lo utilizan en la enseñanza. Aparte de todo esto quedamos a la espera de nuevos ejemplos.  :-)

Nunca he tenido que hacer una maquina de estado, a ver que te parece esta versión:

'PIC12F675
'__Inicialización
Symbol led_pin = GPIO.0
Symbol pulsador = GPIO.1
CMCON = 7
ANSEL = 0
TRISIO = %00000010
'__Rutina principal
main:
   If pulsador = 0 Then  'Si no esta pulsado apaga led
      Gosub led_off
   Else  'Si esta pulsado enciende led
      Gosub led_on
   Endif
Goto main  'Bucle principal infinito
End                                               
'__Subrutinas
'Apaga led
led_off:
   led_pin = 0  'Led apagado
   While pulsador = 0  'Mientras no este pulsado
   Wend
Return                                           
'Enciende led
led_on:
   led_pin = 1  'Led encendido
   While pulsador = 1  'Mientras este pulsado
   Wend
Return     
« Última modificación: 05 de Enero de 2018, 14:53:42 por dogflu66 »
Saludos desde Granada, España.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #2 en: 05 de Enero de 2018, 17:10:37 »
Esos códigos no son correctos.

Hay varios puntos a tener en cuenta para hacer un Grafcet y programarlo.

Primero se dibuja el Grafcet y luego se programa (obligatorio)

2º El Grafcet está basado en estados. Cada etapa (cuadrado) puede estar activada o no (es un bit que está a uno o a cero)

3º Las etapas siempre cambian al final del programa (prohibido cambiarlas en medio)
Para conseguir esto siempre hay 2 bit por etapa. Un bit del estado actual y otro bit del próximo estado.
Al final del programa se copia el segundo sobre el primero.

4º Las salidas se agrupan de manera que solo pueden aparecer en un lugar del programa.

5º El Grafcet es multitarea. Ninguna instrucción ni ninguna etapa pueden quedarse con todo el tiempo del procesador (prohibido instrucciones del tipo while(input==0); )

Sin estas condiciones no es un Grafcet (será otra cosa)

Un saludo.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #3 en: 05 de Enero de 2018, 17:36:23 »
Ejemplo:


* Secuencial_GRAFCET.PNG
(5.75 kB, 316x324 - visto 1944 veces)


Programar en c el grafcet:

Código: C
  1. int estados;
  2. int estados_siguiente;
  3.  
  4. #define ESTADO_1   (1<<0)
  5. #define ESTADO_2   (1<<1)
  6. #define ESTADO_3   (1<<2)
  7. #define ESTADO_4   (1<<3)
  8.  
  9. void main() {
  10.  
  11.    // Estado inicial
  12.    estados = estados_siguiente = ESTADO_1;
  13.  
  14.    // Bucle principal
  15.    while(1) {
  16.  
  17.       // Etapa 1
  18.       if (estados & ESTADO_1)  {
  19.          if (Condicion_1) {
  20.             estados_siguiente= ESTADO_2;
  21.          }
  22.       }
  23.  
  24.       // Etapa 2
  25.       if (estados & ESTADO_2)  {
  26.          if (Condicion_2) {
  27.             estados_siguiente= ESTADO_3;
  28.          }
  29.       }
  30.  
  31.       // Etapa 3
  32.       if (estados & ESTADO_3)  {
  33.          if (Condicion_3) {
  34.             estados_siguiente= ESTADO_4;
  35.          }
  36.       }
  37.  
  38.       // Etapa 4
  39.       if (estados & ESTADO_4)  {
  40.          if (Condicion_4) {
  41.             estados_siguiente= ESTADO_1;
  42.          }
  43.       }
  44.  
  45.  
  46.       // Salidas
  47.       Accion_1 = ((estados & ESTADO_2) > 0);
  48.       Accion_2 = ((estados & ESTADO_3) > 0);
  49.       Accion_3 = ((estados & ESTADO_4) > 0);
  50.       Accion_4 = ((estados & ESTADO_4) > 0);
  51.  
  52.  
  53.       // Cambia estados
  54.       estados = estados_siguiente;
  55.  
  56.       // Hacer otras cosas antes de volver a comenzar el ciclo
  57.  
  58.  
  59.    }
  60. }

Un saludo.
« Última modificación: 05 de Enero de 2018, 17:38:57 por Picuino »

Desconectado joserafa83

  • PIC10
  • *
  • Mensajes: 4
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #4 en: 05 de Enero de 2018, 17:40:29 »
Hola,

La idea de programar por estados es ayudarte con la programación multitarea (sin recurrir a un RTOS), cuando tienes que realizar muchos procesos y evitar que tu programa quede en un bucle infinito esperando alguna señal o condición. Puedes mirar el siguiente articulo, aunque se encuentra en ingles, es muy claro.

https://www.allaboutcircuits.com/technical-articles/finite-state-machines-microcontrollers/


Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #5 en: 05 de Enero de 2018, 17:52:55 »
Ok, pero un Grafcet no es exactamente como una máquina de estados.
En tu caso el código tiene varios errores a la hora de implementar el grafcet.
Por ejemplo uno de ellos es que las transiciones sólo se pueden evaluar cuando estás en la etapa anterior de la transición.
Otro error es el de colocar Gotos. Las secuencias evolucionan gracias a los estados, no evolucionan con la lógica del programa que debe ser lineal y pasar siempre por todas las etapas.


Artículos grafcet:
https://es.wikipedia.org/wiki/GRAFCET
Curso de Grafcet y Gemma
« Última modificación: 05 de Enero de 2018, 17:55:39 por Picuino »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #6 en: 05 de Enero de 2018, 17:59:03 »
Si quieres te ayudo a implementar el programa del grafcet que has puesto en el primer post (que habría que corregir también).

De todas formas ese grafcet no hace nada, sería mejor hacer un grafcet para encender un led al pulsar un botón y apagar el led al volver a pulsar el botón. Todo hecho con Grafcet y estados, sin detectar flancos.

Un saludo.

Desconectado joserafa83

  • PIC10
  • *
  • Mensajes: 4
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #7 en: 05 de Enero de 2018, 18:16:50 »
Hola Picuino,

Yo no estoy tratando de generar grafcet puro el cual esta basado en la norma IEC  608048, sino que trato de implementar programación SCF como la que utilizan los PLC basado en la norma IEC 61131-3, son parecidos pero no igual  :D :D.

Si quieres te ayudo a implementar el programa del grafcet que has puesto en el primer post (que habría que corregir también).

De todas formas ese grafcet no hace nada, sería mejor hacer un grafcet para encender un led al pulsar un botón y apagar el led al volver a pulsar el botón. Todo hecho con Grafcet y estados, sin detectar flancos.

Un saludo.

Sin detectar flancos  :-/ !!! es un reto muy bueno. Si puedes mostrarnos como lo haces y lo posteas. Seria muy interesante de ver  ((:-)).

Sería algo similar a este diagrama, puse entre paréntesis la detección de flancos porque en realidad no se como hacerlo sin detección de flancos.


Esta es la simulación en Proteus, de mi placa de desarrollo para PIC12F675  :D


Y este seria el código en PSI Basic

Código: [Seleccionar]
Dim m0 As Byte
Dim last_button_state As Bit
Dim button_state As Bit
Dim flag_debounce As Bit
Dim rising_flag As Bit
Symbol key1 = GPIO.2
Symbol key2 = GPIO.5
Symbol led1 = GPIO.0
Symbol led2 = GPIO.1
Symbol adc_vr1 = GPIO.4

inicio:
m0 = 0
CMCON = 7
ANSEL = 0
TRISIO = %11111100
last_button_state = 0
button_state = 0
flag_debounce = 0
rising_flag = 0
m0 = 1
If m0 = 1 Then
Goto led_off
Else
Goto inicio
Endif
led_off:
led1 = 0
Gosub rising_edge
'si existe un flanco positivo m0=2
If rising_flag = 1 Then
rising_flag = 0
m0 = 2
Endif
If m0 = 2 Then
Goto led_on
Else
Goto led_off
Endif
led_on:
led1 = 1
Gosub rising_edge
'si existe un flanco positivo m0=1
If rising_flag = 1 Then
rising_flag = 0
m0 = 1
Endif
If m0 = 1 Then
Goto led_off
Else
Goto led_on
Endif

End                                               

'RUTINA PARA DETECTAR FLANCO POSITIVO
'SE INCLUYE RETARDO 20ms PARA ELIMINAR REBOTE
rising_edge:
button_state = key1
If last_button_state <> button_state Then
WaitMs 20  'RETARDO PARA ELIMNAR REBOTE
button_state = key1
If last_button_state <> button_state Then
flag_debounce = 1
Endif
If flag_debounce = 1 Then
If button_state = 1 Then
flag_debounce = 0
last_button_state = button_state
rising_flag = 1
Endif
Endif
Endif
last_button_state = button_state
Return








« Última modificación: 05 de Enero de 2018, 23:44:52 por joserafa83 »

Desconectado joserafa83

  • PIC10
  • *
  • Mensajes: 4
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #8 en: 06 de Enero de 2018, 01:05:27 »
Aquí les traigo otro ejercicio  :-/, con el mismo pulsador vamos a encender y apagar los LED1 Y LED2 secuencialmente.

El diagrama SFC de control sería el siguiente:


La simulación en Proteus seria la siguiente:


EL código en PSI Basic:

Código: [Seleccionar]
Dim m0 As Byte
Dim last_button_state As Bit
Dim button_state As Bit
Dim flag_debounce As Bit
Dim rising_flag As Bit
Symbol key1 = GPIO.2
Symbol key2 = GPIO.5
Symbol led1 = GPIO.0
Symbol led2 = GPIO.1
Symbol adc_vr1 = GPIO.4


inicio:
m0 = 0
CMCON = 7
ANSEL = 0
TRISIO = %11111100
last_button_state = 0
button_state = 0
flag_debounce = 0
rising_flag = 0
m0 = 1
If m0 = 1 Then
Goto led1_2_off
Else
Goto inicio
Endif
led1_2_off:
led1 = 0
led2 = 0
Gosub rising_edge
If rising_flag = 1 Then
rising_flag = 0
m0 = 2
Endif
If m0 = 2 Then
Goto led1_on
Else
Goto led1_2_off
Endif
led1_on:
led1 = 1
Gosub rising_edge
If rising_flag = 1 Then
rising_flag = 0
m0 = 3
Endif
If m0 = 3 Then
Goto led1_off
Else
Goto led1_on
Endif
led1_off:
led1 = 0
Gosub rising_edge
If rising_flag = 1 Then
rising_flag = 0
m0 = 4
Endif
If m0 = 4 Then
Goto led2_on
Else
Goto led1_off
Endif
led2_on:
led2 = 1
Gosub rising_edge
If rising_flag = 1 Then
rising_flag = 0
m0 = 5
Endif
If m0 = 5 Then
Goto led2_off
Else
Goto led2_on
Endif
led2_off:
led2 = 0
Gosub rising_edge
If rising_flag = 1 Then
rising_flag = 0
m0 = 2
Endif
If m0 = 2 Then
Goto led1_on
Else
Goto led2_off
Endif



End                                               

'RUTINA PARA DETECTAR FLANCO POSITIVO
'SE INCLUYE RETARDO 20ms PARA ELIMINAR REBOTE
rising_edge:
button_state = key1
If last_button_state <> button_state Then
WaitMs 20  'RETARDO PARA ELIMNAR REBOTE
button_state = key1
If last_button_state <> button_state Then
flag_debounce = 1
Endif
If flag_debounce = 1 Then
If button_state = 1 Then
flag_debounce = 0
last_button_state = button_state
rising_flag = 1
Endif
Endif
Endif
last_button_state = button_state
Return



Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #9 en: 06 de Enero de 2018, 06:18:22 »
Vamos por pasos.
El grafcet genérico para encender y apagar un led cada vez que se presione un pulsador.



Saludos.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #10 en: 06 de Enero de 2018, 10:18:07 »
Ahora se debería dibujar el grafcet con las entradas y salidas exactas que se van a utilizar para cada elemento (Led y pulsador).
Como este grafcet es sencillo, simplemente voy a utilizar variables que representen las entradas y salidas con este mismo nombre.


A continuación hay que programar el Grafcet. Esta es la forma genérica del programa basado en http://recursos.citcea.upc.edu/grafcet/implem/

--------------------------------------------------

1º Inicializar todas las variables y todas las salidas a cero

2º Activar todas las etapas iniciales de los Grafcet

REPETIR siempre

   3º Leer todas las entradas físicas y copiarlas en variables   E(i) = I(i)       
   
   REPETIR hasta estable = True

      4º Copìar actividad de las etapas en un vector de backup  V(i) = X(i)

      5º Evaluar todas las transiciones  R(i) = ....

      6º  Desactivar las etapas activas en las que la transición esté validada 
            If ( R(i) · V(i) )  then  X(i) = 0

      7º  Activar las etapas siguientes a las activas en las que la transición esté validada
            If ( R(i) · V(i) )  then  X(i+1) = 1

      8º Comprobar si el estado del grafcet es estable
           If ( V(i) == X(i) ) then estable = True

   FIN REPETIR

   9º Calcular las salidas de tipo mantenido S(i) = X(i) ....

   10º Calcular las salidas de tipo impulso o las operaciones que se ejecutan una sola vez
         If (M(i) == X(i))  Then
            S(i) = 0
         Else
            M(i) = X(i)
            S(i) = 1
            Op = Op + 1
         End If

   11º Escribir todas las variables de salida en las salidas físicas  O(i) = S(i)

FIN REPETIR

--------------------------------------------------

Es la forma más compleja, pero funciona siempre bien. Se puede simplificar para Grafcets más sencillos y se puede complicar más todavía para Grafcets forzados.
« Última modificación: 06 de Enero de 2018, 10:20:19 por Picuino »

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #11 en: 06 de Enero de 2018, 10:42:58 »
Ahora el programa de verdad escrito en c.
Las variables no están optimizadas. El programa no espera a que el grafcet sea estable. Las transiciones se activan y desactivan en la misma instrucción. Esto no es ortodoxo, pero el programa será más sencillo y la mayoría de Grafcets funcionará bien.
Estas simplificaciones no valdrán si el grafcet tiene varias etapas activadas en la misma secuencia o si la activación debe saltar varias etapas seguidas antes de quedarse estable (que no es este caso)

Código: C
  1. unsigned char E, S;  // Entradas y salidas
  2. unsigned char X[4];  // Estados del Grafcet
  3. unsigned char V[4];  // Copia de los estados del Grafcet
  4.  
  5. void main() {
  6.  
  7.    // Inicializar estados y salidas
  8.    S = 0;
  9.    X[0] = X[1] = X[2] = X[3] = 0;
  10.  
  11.    // Activar estados iniciales
  12.    X[0] = 1;
  13.  
  14.    // Bucle principal
  15.    while(1) {
  16.  
  17.       // Leer entradas
  18.       E = GPIO.5; // Pulsador
  19.  
  20.       // Guardar valor de los estados
  21.       V[0] = X[0]; V[1] = X[1]; V[2] = X[2]; V[3] = X[3];
  22.  
  23.       // Calcular la evolución del Grafcet
  24.       if (V[0] && E==1) {
  25.          X[0] = 0;
  26.          X[1] = 1;
  27.       }
  28.       if (V[1] && E==0) {
  29.          X[1] = 0;
  30.          X[2] = 1;
  31.       }
  32.       if (V[2] && E==1) {
  33.          X[2] = 0;
  34.          X[3] = 1;
  35.       }
  36.       if (V[3] && E==0) {
  37.          X[3] = 0;
  38.          X[0] = 1;
  39.       }
  40.  
  41.       // Calcular las variables de salida
  42.       if ( X[1] + X[2] )
  43.          S = 1;
  44.       else
  45.          S = 0;
  46.      
  47.       // Copiar las variables de salida en las Salidas físicas
  48.       GPIO.2 = S;
  49.  
  50.    }
  51. }

Y ya está.

Un saludo.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #12 en: 06 de Enero de 2018, 10:55:33 »
Aquí les traigo otro ejercicio  :-/, con el mismo pulsador vamos a encender y apagar los LED1 Y LED2 secuencialmente.

Hola joserafa83.
El "Grafcet" que has programado está mal implementado. Tiene varios errores, pero me voy a centrar solo en un error que se repite con mucha frecuencia y es muy grave:

Está prohibido utilizar GOTO


Tu rutina puede que funcione, pero en un automatismo suele haber varios grafcet y varias cosas que hacer y tu rutina solo sirve para una cosa. Si quieres hacer otra a la vez no podrás porque tu rutina no suelta al procesador, se queda todo el tiempo haciendo lo mismo.

Esto es completamente incompatible con la multitarea y los Grafcet son multitarea (es una de las mayores razones por las que se utilizan)

Un saludo.

Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #13 en: 06 de Enero de 2018, 13:19:33 »
Por supuesto, en ensamblador y ciertas versiones basic es imposible evitar el GOTO

En esos casos hay que limitarlo de manera que el GOTO siempre vaya hacia delante (en las instrucciones IF) y solo vaya hacia atrás para implementar el bucle REPETIR que aparece al final de la implementación de todos los Grafcet de la máquina.

En ningún caso debe aparecer un bucle que retenga la ejecución del programa, como en este ejemplo:

Código: [Seleccionar]
led2_off:
led2 = 0
Gosub rising_edge
If rising_flag = 1 Then
rising_flag = 0
m0 = 2
Endif
If m0 = 2 Then
Goto led1_on
Else
Goto led2_off   ; <<<<<<<<<<< BUCLE PROHIBIDO
Endif


Desconectado Picuino

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 5892
    • Picuino
Re:Programación con maquinas de estado FSM para microcontroladores PIC
« Respuesta #14 en: 06 de Enero de 2018, 13:23:21 »
Pongo un ejercicio interesante para demostrar este problema:

Que el led 1 se encienda y que se apague cada vez que se presione el pulsador 1
Que el led 2 se encienda y que se apague cada vez que se presione el pulsador 2

Igual que mi grafcet anterior, pero con dos pulsadores y dos led independientes, con las transiciones validadas por niveles (no por flancos)

Ambos funcionamientos independientes el uno del otro y sin retardos (tan rápido como se pueda).

Saludos.
« Última modificación: 06 de Enero de 2018, 13:29:33 por Picuino »


 

anything