Переход от одного конечного автомата к другому

У меня есть проект, в котором мне нужно перейти от включения и выключения светодиодов к другому, в котором будут включены все светодиоды и отправляться данные, и мне было интересно, как мне это сделать, вот код, который у меня есть:

#include <CapacitiveSensor.h>

CapacitiveSensor cs_11_10 = CapacitiveSensor(11,10);

int state_s1 = 0;
int state_s2 = 0;
int state_s3 = 0;
int state_s4 = 0;
int state_prev_s1 =0;
int pin_s1 = 12;
int val_s1 = 0;

const unsigned int ledPins[]={2,3,4,5,6,7,8,9};
const unsigned int lenledPins=9; 

unsigned long t_s1 = 0;
unsigned long t_0_s1 = 0;
unsigned long t_s3 = 0;
unsigned long t_0_s3 = 0;
unsigned long t_0_s4 = 0;
unsigned long t_s4 = 0;
unsigned long t_s2_4 = 0;
unsigned long tiempo = 250;

unsigned long bounce_delay_s1 = 5;

long total = 0;

void setup() 
{
  pinMode(pin_s1, INPUT_PULLUP);
  Serial.begin(9600);

  for(int i=0; i<(9); i++)
  {
    pinMode(ledPins[i], OUTPUT);  
  }

  cs_11_10.set_CS_AutocaL_Millis(0xFFFFFFFF);
  Serial.begin(9600);

}

void loop()
{


  MBoton();          //MAQUINA DE ESTADO

 MaquinaGeneral();

  if(state_s2 == 1)
  {
    led(); 
  }

  if(state_s1 != state_prev_s1)
  {
    Serial.print("state =");
    Serial.println(state_s3);
  }

  if(state_s4 == 6)
  {
    for(int i=0; i<lenledPins; i++)
    {
      digitalWrite(ledPins[i],HIGH); 
    }
  }

  Serial.print("");

}

void MaquinaGeneral()
{
  switch(state_s2)
  {
    case 0:
    if(state_s1 == 4)
    { 
      state_s2 = 1;
    } 
    break;

    case 1:

    break;
  }
}  


void MBoton()
{
  state_prev_s1 = state_s1;
  switch(state_s1)
  {
    case 0:         //RESET
    state_s1 = 1;
    break;

    case 1:        //START
    val_s1 = digitalRead(pin_s1);
    if(val_s1 == LOW)
     {
      state_s1 = 2;
     }
    break;

    case 2:         // GO!
    t_0_s1 = millis();
    state_s1 = 3;
    break;

    case 3:         //WAIT
    t_s1 = millis();
    if(t_s1 - t_0_s1 >= bounce_delay_s1)
    {
      state_s1 = 5;
    }
    break;

    case 5:         //ARMED
    val_s1 = digitalRead(pin_s1);
    if(val_s1 == HIGH)
     {
      state_s1 = 4;
     }
    break;

    case 4:       //TRIGGERED
    state_s1 = 0;
    break;


  }
}

void led()
{

  switch(state_s3)
  {      
    case 0:         //OFF
    for(int i=0; i<lenledPins; i=i+2)
    {
      digitalWrite(ledPins[i],LOW);
    }
    for(int i=1; i<lenledPins; i=i+2)
    {
      digitalWrite(ledPins[i],HIGH);
    } 

    t_0_s3 = millis();
    state_s3 = 1;
    break;

    case 1:         //WAIT
    t_s3 = millis();
    if(t_s3 - t_0_s3 >= tiempo)
    {
      state_s3 = 2;
    }
    break;

    case 2:         // ON
     for(int i=0; i<lenledPins; i=i+2)
    {
      digitalWrite(ledPins[i],HIGH);
    }

     for(int i=1; i<lenledPins; i=i+2)
    {
      digitalWrite(ledPins[i],LOW);
    }

    t_0_s3 = millis();
    state_s3 = 3;
    break;

    case 3:         //WAIT   
    t_s3 = millis();
    if(t_s3 - t_0_s3 >= tiempo)  
    {
     state_s3 = 0;
    }
    break;


  }


  }

void Capacitor()
 {

  switch(state_s4)
  {

    case 0:         //RESET
    state_s4 = 1;
    break;

    case 1:        //START
    total = cs_11_10.capacitiveSensor(10);
    if(total >= 1000)
     {
      state_s4 = 2;
     }
    break;

    case 2:         // GO!
    t_0_s4 = millis();
    state_s4 = 3;
    break;

    case 3:         //WAIT
    total = cs_11_10.capacitiveSensor(10);
    if(total < 1000)
     {
      state_s4 = 0;
     }

    t_s4 = millis();

    if(t_s4 - t_0_s4 >= 2000)
    {
      state_s4 = 5;
    }

    break;

    case 5:         //ARMED & WAIT
    t_s2_4 = millis();
    total = cs_11_10.capacitiveSensor(10);
    if(total < 1000)
     {
      state_s4 = 4;
     }

     if(t_s2_4-t_s4 >= 1000)
     {  
      state_s4= 6;
     }
    break;

    case 4:       //TRIGGERED
    state_s4 = 0;
    break;


    case 6:     // ARMED 2  
    Serial.println("Entro al estado 6");
    total = cs_11_10.capacitiveSensor(10);
    break;

}
}

, 👍1

Обсуждение

Быстрое сканирование вашего кода показало бы, что у вас слишком много дел. Это или недостаточно комментариев, чтобы объяснить ваше решение использовать несколько конечных автоматов. Я бы начал все сначала только с 1 конечного автомата и придерживался только 1 конечного автомата., @st2000

Я не совсем понимаю, в чем ваша проблема. Вы написали все эти конечные автоматы. Таким образом, вы можете просто добавить состояния именно для того, что вам нужно (состояние, которое оставило бы светодиоды включенными и отправляло бы данные). Хотя я думаю, что st2000 прав в том, что вы должны тщательно проверить, будет ли достаточно использовать только 1 конечный автомат. Это было бы намного проще закодировать., @chrisl

Также используйте тип перечисления для состояний вместо "магических чисел" 1, 2, 3 и т. Д., @Michel Keijzers

Я настоятельно рекомендую вам создавать конечные автоматы с диаграммой состояний, показывающей события, переходы и действия. Их гораздо легче читать и понимать, чем любой код конечного автомата, который я когда-либо видел или писал. Когда у вас есть диаграмма, которая, по вашему мнению, делает то, что вы хотите, начните ее кодировать. Не забудьте сверить свой код конечного автомата с диаграммой, чтобы быть уверенным, что ваш код делает то, что говорит диаграмма. Диаграмма состояния должна быть вашим рабочим справочником. Когда вы отлаживаете, сначала отладьте/исправьте его на диаграмме, а затем используйте его для исправления кода. Вы получите работающий конечный автомат гораздо раньше., @JRobert


2 ответа


1

Если вы считаете, что вам нужны две конечные машины, где в любой момент времени работает только одна из них, то объединить их вместе тривиально: нарисуйте их рядом и добавьте необходимые переходы между ними. Набор состояний объединенного FSM будет представлять собой объединение состояний начальных FSMS. Например, если у вас есть:

  • FSM 1 состояния: STATE_A, STATE_B, STATE_C
  • FSM 2 этапа: STATE_D, STATE_E
  • глобальные состояния: FSM_1_RUNNING, FSM_2_RUNNING

Тогда объединенный FSM будет иметь состояния STATE_A, STATE_B, STATE_C, STATE_D и STATE_E, а также все переходы обеих начальных FSMS.

,

0

Подобно тому, что прокомментировали другие, это не лучшая реализация конечного автомата (FSM). Вы должны установить четкие состояния и определить, что происходит во время всех переходов вашей системы.

Следуйте советам Эдгара по использованию счетчиков для ваших штатов.

Руководство Ника Гэммона, несомненно, окажет большую помощь: https://www.gammon.com.au/statemachine

,