sábado, 22 de octubre de 2011

"Chrono Starts": Measure your 0 to 100 kph time

.

 




You can find an example using our FSM (Finite State Machine) library to create an Arduino program to measure the time to achieve 0 to 100 kph. The speed is read from the CAN bus and we are using the SetFilters() function, which uses the HW feature to only allows receive the messages with a specific ID (where the car speed is sent).

You can download the FSM library for Arduino022 from:




You need to copy it into the libraries folder.


Below, the state machine diagram of the "Chrono Starts" sketch:

(click to enlarge the diagram)







Arduino sketch:

 // -------------------------------------------------------------------------------------
// SECUduino: Chrono 0 to 100 kph
// By Igor Real
// 23/10/2011
// -------------------------------------------------------------------------------------

#include <FSM.h>
#include <LiquidCrystal.h>
#include <CAN.h>
#include "myStates.h"

#define delayShowData  7000
#define SpeedTarget    100

//VARIABLES
unsigned char myEvent;
char myByteRec;
unsigned long my0to100;
unsigned long t0;
unsigned long t_prev;
float Speed;
char bUpdateLCD;

LiquidCrystal LCD(13,12, 11, 10, 9, 8, 7);

void setup()
{
  
  LCD.begin(20,4);
  bUpdateLCD=1;
  func1();  //Print Initial screen
  
  CAN.begin(100);
  uint16_t  Filters[6];
  uint16_t Masks[2];
  Masks[0]=0x3FF;
  Masks[1]=0x3FF;
  Filters[0]=0x351;  //Buffer0
  Filters[2]=0x351;  //Buffer1
  CAN.SetFilters(Filters,Masks);  //Only messages with ID=0x351 are allowed in both Rx buffers
  
  FSM.begin(FSM_NextState,nStateMachine,FSM_State,nStateFcn,STATE1);
}

void loop()
{
  ReadEvents();
  FSM.Update();
}


void ReadEvents(void)
{
  
  if (CAN.CheckNew() )
  {
    CAN.ReadFromDevice(&CAN_RxMsg);
    Speed=0.005*(256*CAN_RxMsg.data[2]+CAN_RxMsg.data[1]);
    //Speed=CAN_RxMsg.data[0];
    LCD.setCursor(0,1);
    LCD.print("Speed= ");
    LCD.print((int)Speed);
  }
  
  if (Speed<=0){
    FSM.AddEvent(EV_Stop);
  }else if (Speed>=SpeedTarget){
    FSM.AddEvent(EV_100);
  }else if ( (Speed>0) && (Speed<SpeedTarget) ){
    FSM.AddEvent(EV_Start);    
  }
  
}

void func1(void)
{
  if (bUpdateLCD)
  {  
    LCD.clear();
    LCD.setCursor(0,0);
    LCD.print("  *- SECUduino -*");
  
    LCD.setCursor(0,2);
    LCD.print("State 1");
    
    bUpdateLCD=0;
  }
}
void func2(void)
{
  LCD.setCursor(0,2);
  LCD.print("State 2");
  bUpdateLCD=1;
}

void func3(void)
{
  t0=millis();
  LCD.setCursor(0,2);
  LCD.print("State 3");
  FSM.AddEvent(0);
}

void func4(void)
{
  LCD.setCursor(0,2);
  LCD.print("State 4");
}

void func5(void)
{
  my0to100=millis()-t0;
  t_prev=millis();
  LCD.setCursor(0,2);
  LCD.print("State 4");
  
  LCD.setCursor(0,3);
  LCD.print((float)my0to100/(float)1000.0);
  LCD.print(" s");
  
  while(millis()-t_prev<=delayShowData);
  FSM.AddEvent(EV_Wait);  
}





Code myStates.h:

//-----------------------------------------------------
//ESTE ES EL ÚNICO FICHERO QUE HAY QUE MODIFICAR
//-----------------------------------------------------

#ifndef myStates_H
#define myStates_H


//Declaracion de las funciones
extern void func1(void);
extern void func2(void);
extern void func3(void);
extern void func4(void);
extern void func5(void);

//Declaracion del nombre de ESTADOS y de EVENTOS
#define STATE1   0x01
#define STATE2   0x02
#define STATE3          0x03
#define STATE4          0x04
#define STATE5          0x05

#define EV_Start      0x01
#define EV_100     0x02 
#define EV_Stop     0x03
#define EV_Wait     0x04


// 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},
{STATE5,func5},
};

const FSMClass::FSM_NextState_t FSM_NextState[] PROGMEM= {
// STATE,EVENT,NEXT_STATE
{STATE1,EV_Stop,STATE2},
{STATE2,EV_Start,STATE3},
{STATE3,0,STATE4},
{STATE4,EV_100,STATE5},
{STATE4,EV_Stop,STATE1},
{STATE5,EV_Wait,STATE1},
};


//Macros para el cálculo de los tamaños de las estructuras
//NO MODIFICAR
#define nStateFcn  sizeof(FSM_State)/sizeof(FSMClass::FSM_State_t)
#define nStateMachine  sizeof(FSM_NextState)/sizeof(FSMClass::FSM_NextState_t)

#endif



No hay comentarios:

Publicar un comentario