Máquina de estados: Librería FSM

no puedo poner toooooodo el codigo porque es enorme, a ver si saco un rato y extraigo el codigo y creo un miniprograma que solo haga eso, mientras tanto...

  void performance_accel(){
        
      if (OBD_DATA == true)
        {
          unsigned long elapse_time;
          elapse_time = millis() - start_time_elapse;
          /*
          Serial.print("Last speed: ");        Serial.print(last_SPEED_rx_data);  
          Serial.print("\tCurrent speed: ");   Serial.print(SPEED_rx_data);
          Serial.print("\tStart Millis: ");    Serial.print(start_time_elapse);
          Serial.print("\tCurrent Millis: ");    Serial.print(millis());
          Serial.print("\tElapse Millis: ");   Serial.print(elapse_time);
          Serial.println();
          */
          // performance_status = 0 -> ready to start test (0 kmh)
          // performance_status = 1 -> test started...reading (V > 0 kmh y < 100 y no han habido deceleraciones)
          // performance_status = 2 -> test aborted por deceleracion  o   test finalizado, esperando V = 0 kmh
          
          // Check if car is stopped
          if ( SPEED_rx_data == 0)
          {
            start_time_elapse = millis();
            performance_status = 0; // ready to start test
          }
          
          
          // READY TO START TEST -           
          if ( (performance_status == 0) && (SPEED_rx_data > 0) )
                {
                    performance_status = 1;  // test started...recording
                    Serial.println("Performance timing STARTED !!!");
                }

          
          // RUNNING - 
          if (  (performance_status == 1)    &&    (SPEED_rx_data >= 100)    )
          {
                Serial.print("Performance timing COMPLETED"); Serial.print(" Time: "); Serial.println(elapse_time);
                  if (elapse_time < best_0_to_100)
                      {
                          Serial.println(" ******* NEW PERFORMANCE RECORD ***** ");
                          best_0_to_100 = elapse_time;
                      }
                performance_status = 2;
          }
          
          
          // RUNNING - Stop the test if deceleration before 100 kmh
          if (    (performance_status == 1)    &&    (SPEED_rx_data < last_SPEED_rx_data)    )
          {
              Serial.println("Performance timing STOPPED");
              performance_status = 2;
          }
         
        } // end if obd = true
        
      }

como he dicho luego lo pulo un poco y que quede mas presentable

ja,ja,ja. Está muy bien! Lo has creado con una máquina de estados.... tu performance_status no es más que una variable con el estado actual.
Hay muchas maneras de hacerlo: con if, con switch, con lockup tables, etc.

:wink:

Alguno podría indicarme si la máquina de estados es mas potente que el Grafcet.

El concepto es similar. Me acuerdo que cuando me explicaron Grafcet, como teníamos autómatas Omron que sólo tenía lenguaje ladder, nos dibujabamos el diagrama a mano y lo programábamos con biestables, que los usábamos para simular cada estado.

Me refiero con ésto, que al final que si Petri, Grafcet, UML, Mealy, Moore, etc son conceptos similares. Tampoco soy un experto, pero al final me parece un poco todo lo mismo. Actualmente me toca mirarme bastante código escrito en Stateflow (+ Simulink) de Matlab, y es más de lo mismo...

La librería FSM, simplemente es un paso más a tener un switch gigante, ya que en modo look up table, te queda más limpio y fácil de leer. Es una librería bastante básica... podrías ir ampliando cosillas ( un buen libro gratuito http://www.tte-systems.com/books/pttes ).

Has hecho algo con QP¿

No. Alguna vez he intentado leer algún capítulo de su libro, pero no aguanto más de 5 min...es un somnífero cojonudo!! :wink:

A mi me cuesta un poco digerir bien todo esto.

  • He estado viendo el código que puso Igor R al principio del hilo, me refiero a FSM_v5.pde, y veo, entre otras, una linea que no entiendo:
    mynumber=mynumber*10+(myByteRec-0x30);
    Perdonad mi ignorancia, pero no entiendo esa expresión, concretamente los de multiplicar por 10 y lo de 0x30, pues lo que yo pondría sería: mynumber=mynumber+myByteRec

. Refiriéndote a ese código, cita "El número debe ser enviado entre SxxxxE, donde S es de start y E de end. xxxx es un número (unsigned long)". Pero, si además de recoger el valor del sensor quisiera recoger otro tipo de valores o el valor de otros sensores, ¿habría que definir otra estructura de datos como, p.e., AxxxxB?

Hola,

mynumber=mynumber*10+(myByteRec-0x30);

El 0x30 es porque usando el terminal serie de Arduino, estas recibiendo los datos en ASCII. Es decir, un cero es 0x30, un uno es 0x31, etc Es decir, con la operacion (myByteRec-0x30) tienes tu numero decimal de 0 a 9.
Luego, acerca de por que multiplicas x10 lo que tenias.... Estas recibiendo los numeros en ASCII, es decir te llegan diferentes bytes (uno por cada caracter). Por lo que si mandas un 123, te llega "1" "2" y "3". Si solo los sumas, seria un 6 (previa conversion de Ascii a decimal).

Puedes ampliar el programa como quieras para recibir varias cosas separadas por coma, por otro caracter o por lo que quieras.... ese codigo es solo un ejemplo.

Salu2

Igor

Nota- ordenador ingles, ni acentos ni enyes.

Gracias Igor R, la rutina que yo empleaba sumaba los caracteres, y no sus valores, y después convertía la cadena en valor. Supongo que el resultado es el mismo. Pero aplicando tu expresión el código es interpreta mas fácilemente.

Por lo que me comentas, veo que el envio de datos en serie no tiene una programación standar, o sea, que el código que recibe el dato estará en función del código que los manda. Yo ya he conseguido hacer gráficos en processing con datos enviados en serie desde arduino, pero mis conocimientos son muy básicos, sin embargo creo que existen programas generadores de gráficos que también guardan los datos en ficheros. En este último caso, solo podremos enviar los datos si están correctamente "empaquetados" para un uso particular, ¿no?. ¿Existen diferencias en la forma de enviar datos a estos programas?¿podrías recomendar alguno? (mejor si son gratuitos)

Solo decir que mi interés es hacer un código propio, pero viendo como trabajan los demás voy enterándome de las cosas.

Puedes usar KST, mira esto que escribi => Tinkering with Electronics...: Arduino ADC: Muestreo alta velocidad

buenas tardes a todos!!

he estado instalando el nuevo ide de arduino 1.0 y las libreeias con las que trasteo y cuando intento cargar un ejemplo (FSM_V5) me sale un error.
a que puede ser devido??

os dejo el error que os comento

010.JPG

hola,
Estoy con el movil,pero en plan rápido busca la modificación q hay q hacer a las librerias para el Uno. Simplemente es un include,ya q han cambiado el nombre del fichero.
Salu2

hola Igor R,

haber si te he entendido: supongo que debo de ir a tu librería y cambiar el #include <avr/pgmspace.h> en el fichero FSM.h o el #include "WProgram.h" en el fichero FSM.cpp pero por cual??

gracias Igor R nuevamente.

lo tengo Igor R!!! gracias por la pista... me ha costado encontrarlo, pero google al final me lo soluciono, cambiar Wprogram.h por Arduino.h

Salu2

[quote author=Aritz R link=topic=75826.msg574723#msg574723 date=1319115326]
A nivel de cómputo son igual de potentes. [/quote]

Ya sé que esto es agitar un poco el avispero, pero eso no es estrictamente cierto. Ambas máquinas son capaces de resolver los mismos problemas, así que son igual de versátiles. Sin embargo un mismo problema puede requerir más estados en un tipo y viceversa ,hay problemas que se resuelven antes con Moore, otros que se resuelven antes con Mealy (y con antes me refiero a con menos estados). Esto, en casos extremos puede incidir en la velocidad a la que ejecutas el algoritmo, pero vamos, que son esos casos puntuales tan ajustados para los que hay que sacar el asembler a relucir y tal (lo que normalmente quiere decir subir la freq. del micro y mandar el asembler a la estantería otra vez xD)

pacoooh,me alegro que la tenas funcionando. Cuando vuelva para casa ya lo cambiaré(ahora estoy fuera y me conecto intermitentemente a internet con el móvil).
La tengo subida al github,ya pondré más detalles cuando vuelva.
Por cierto,las acciones a ejecutar las puedes hacer cuando quieras (estados,transiciones ó ambas) con una pequeñísima modificación...a gusto del consumidor! Como dije en su día es algo sencillo y básico. Se puede "complicar" todo lo que se quiera.
Yo la hice para el control de menus de una pantalla gráfica. Resulta muy fácil meterle cambios a los menus,botoneras,etc. con este tipo de programación. De momento, es lo que necesito, algo sencillito.

Saludos

Ya estoy de vuelta!! Dejo el link del repositorio:
GitHub - IgorReal/SECUduino (en la carpeta FSM)

Ahora si alguien quiere colaborar mejorándola, añadiéndole eventos en las transiciones o lo que sea....es posible.

:wink:

Genial @Igor R !

Que buena librería. Muchas gracias por compartirla, +1.
Un saludo.

hola estoy inentando usar la libreria para crear un menu y cuando le doy a compilar me sale este mensage

/mystates.h:33: error: invalid conversion from 'void (*)()' to 'unsigned char'

alguien intuye por donde puede ir el error gracias

Hola,

Mejor sube el código para poder echarle un vistazo.

Salu2,

Igor

aqui va el codigo lo subi a box
https://app.box.com/s/ghxkxfmnvai7ijzvk9sr

Hola,

Has usado paréntesis () en vez de {}

// Estructuras descriptivas de mi diagrama de flujo
const FSMClass::FSM_State_t FSM_State[] PROGMEM= {
// STATE,STATE_FUNC
{STATE1,func1},
{STATE2,func2},
{STATE3,func3},
(STATE4,func4),
};

Saludos,

Igor

Igor, la version en Github está actualizada?