Переход от одного конечного автомата к другому
У меня есть проект, в котором мне нужно перейти от включения и выключения светодиодов к другому, в котором будут включены все светодиоды и отправляться данные, и мне было интересно, как мне это сделать, вот код, который у меня есть:
#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;
}
}
@Paola, 👍1
Обсуждение2 ответа
Если вы считаете, что вам нужны две конечные машины, где в любой момент времени работает только одна из них, то объединить их вместе тривиально: нарисуйте их рядом и добавьте необходимые переходы между ними. Набор состояний объединенного 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.
Подобно тому, что прокомментировали другие, это не лучшая реализация конечного автомата (FSM). Вы должны установить четкие состояния и определить, что происходит во время всех переходов вашей системы.
Следуйте советам Эдгара по использованию счетчиков для ваших штатов.
Руководство Ника Гэммона, несомненно, окажет большую помощь: https://www.gammon.com.au/statemachine
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Быстрое сканирование вашего кода показало бы, что у вас слишком много дел. Это или недостаточно комментариев, чтобы объяснить ваше решение использовать несколько конечных автоматов. Я бы начал все сначала только с 1 конечного автомата и придерживался только 1 конечного автомата., @st2000
Я не совсем понимаю, в чем ваша проблема. Вы написали все эти конечные автоматы. Таким образом, вы можете просто добавить состояния именно для того, что вам нужно (состояние, которое оставило бы светодиоды включенными и отправляло бы данные). Хотя я думаю, что st2000 прав в том, что вы должны тщательно проверить, будет ли достаточно использовать только 1 конечный автомат. Это было бы намного проще закодировать., @chrisl
Также используйте тип перечисления для состояний вместо "магических чисел" 1, 2, 3 и т. Д., @Michel Keijzers
Я настоятельно рекомендую вам создавать конечные автоматы с диаграммой состояний, показывающей события, переходы и действия. Их гораздо легче читать и понимать, чем любой код конечного автомата, который я когда-либо видел или писал. Когда у вас есть диаграмма, которая, по вашему мнению, делает то, что вы хотите, начните ее кодировать. Не забудьте сверить свой код конечного автомата с диаграммой, чтобы быть уверенным, что ваш код делает то, что говорит диаграмма. Диаграмма состояния должна быть вашим рабочим справочником. Когда вы отлаживаете, сначала отладьте/исправьте его на диаграмме, а затем используйте его для исправления кода. Вы получите работающий конечный автомат гораздо раньше., @JRobert