Приостановка цикла для запуска другого в Arduino

#arduino

#arduino

Вопрос:

Я работаю над схемой, которая имеет два отдельных 4-разрядных двоичных счетчика со светодиодами. Я нажимаю кнопку, и один счетчик начинает отсчет до 15 в двоичном формате. Я нажимаю вторую кнопку, и первый счетчик останавливается там, где он есть, а вторая группа светодиодов начинает отсчет до 15 в двоичном формате. У меня работают оба счетчика, но я не могу заставить первую группу приостановить, а вторую начать. Я пытался использовать операторы if с логическим флагом, но это испортило первую группу светодиодов. Как я могу заставить ledPins1 [] сделать паузу при нажатии кнопки 2, а затем возобновить, когда ledPins2 [] завершится?

 int ledPin1[] = {2,3,4,5};
int ledPin2[] = {7,8,9,10};
int button1 = 11;
int button2 = 12;
boolean button1Last = LOW;
boolean button1Current = LOW;
boolean button2Last = LOW;
boolean button2Current = LOW;


void setup() 
{
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  for(int i=0; i<4; i  )
  {
    pinMode(ledPin1[i], OUTPUT);
  }
  for(int i=0; i<4; i  )
  {
    pinMode(ledPin2[i], OUTPUT); 
  }
}

boolean waitForButtonPush1 (boolean lastStartSwitchState1)
{
  boolean currentStartSwitchState1 = digitalRead(button1);
  if(lastStartSwitchState1 != currentStartSwitchState1) delay(20);
  currentStartSwitchState1 = digitalRead(button1);
  return currentStartSwitchState1;
}

boolean waitForButtonPush2 (boolean lastStartSwitchState2)
{
  boolean currentStartSwitchState2 = digitalRead(button2);
  if(lastStartSwitchState2 != currentStartSwitchState2) delay(20);
  currentStartSwitchState2 = digitalRead(button2);
  return currentStartSwitchState2;
}

void loop() 
{
  button1Current = waitForButtonPush1(button1Last);
  if(button1Last == LOW amp;amp; button1Current == HIGH)
  {
    for (byte counter =0;counter<=15; counter  )
  {
    displayBinary(counter);
    delay(500);
  }
  }
  button2Current = waitForButtonPush2(button2Last);
  if(button2Last == LOW amp;amp; button2Current == HIGH)
  {
    for (byte counter =0;counter<=15; counter  )
  {
    displayBinary2(counter);
    delay(500);
    
  }
  }
}

void displayBinary(byte numToShow)
{
  for (int i =0;i<4;i  )
  {
    if (bitRead(numToShow, i)==1)
    {
      digitalWrite(ledPin1[i], HIGH);
    }
    else
    {
      digitalWrite(ledPin1[i], LOW);
      
    }
  }

}

void displayBinary2(byte numToShow)
{
  for (int i =0;i<4;i  )
  {
    if (bitRead(numToShow, i)==1)
    {
      digitalWrite(ledPin2[i], HIGH);
    }
    else
    {
      digitalWrite(ledPin2[i], LOW);
    }
  }

}
 

Ответ №1:

Добро пожаловать в мир встроенных устройств!

Заставить небольшой микропроцессор выполнять несколько задач одновременно немного сложно.

Ключ в том, чтобы никогда не блокировать. Нет вызовов delay(), нет отправки больших буферов на последовательный порт со скоростью 9600 бод за один раз и т. Д…

Для этого есть несколько простых методов, один из наиболее часто используемых — конечные автоматы.

Давайте немного проанализируем ваше приложение.

  • 2 похожих счетчика dssplay с задержкой
  • 2 кнопки, кнопки обычно необходимо отключить, что также связано с задержкой.

Некоторый код, с которым вам нужно повозиться:

 // ****************************
// pinout

static const byte ledPin1[] = { 2, 3, 4, 5 };
static const byte ledPin2[] = { 7, 8, 9, 10 };

constexpr byte button1 = 11;   // using constexpr for these saves 2 bytes of RAM.
constexpr byte button2 = 12;

// ****************************
// Counter data 

static constexpr unsigned int led_delay = 500;  // 500 ms, for all counters.

// constexpr ??  arduino supports c  17.  Not all features in the main .ino 
// module and all features in .cpp modules.  

// Hint: you could have a member variable in the structure below for delay, 
// this would allow for counters running at different speeds, or add buttons
// to increase/decrease speed.

// we have only 2 states, but you could add more, like running
// backwards, or run a different chase pattern maybe?

enum class led_counter_state : byte
{
    stopped,
    running,
};

struct led_counter_data_t
{
    led_counter_state state; // STATE
    byte counter;            // counter current value 
    unsigned int timestamp;  // used for timing.
    const byte* leds;        // LED pins.
};

static led_counter_data_t led_counter[2];

void led_display_init()
{
    for (byte i = 0; i < 2;   i)
    {
        led_counter[i].state     = led_counter_state::stopped;
        led_counter[i].counter   = 0;
        led_counter[i].timestamp = 0;
    }
   led_counter[0].leds = ledPin1;
   led_counter[1].leds = ledPin2;   
}

// ****************************
// LED cotrrol

static void leds_display_value(const led_counter_data_tamp; cntr)
{
    for (byte i = 0, val = cntr.counter; i < 4;   i, val >>= 1)
         digitalWrite(cntr.leds[i], val amp; 0x01);
}

static void leds_control(led_counter_data_tamp; cntr)
{
    const auto now = (unsigned int)millis();   // keep track of time.

    switch(cntr.state)
    {
    default:   // something is wrong.. stop.
        cntr.state = led_counter_state::stopped;

        // fall through ...

    case led_counter_state::stopped:
        return;                       // if not running, do nothing

    case led_counter_state::running:
        if (now - cntr.timestamp >= led_delay) // check delay
        {
            if (  cntr.counter > 15)           // advance counter.
                cntr.counter = 0;

            leds_display_value(cntr);           // show value.
            cntr.timestamp = now;              // keep track of time.
        }
        break;
    }
}

static void leds_start(led_counter_data_tamp; cntr)
{
    if (cntr.state != led_counter_state::stopped)
        return;

    cntr.state = led_counter_state::running;

    if (  cntr.counter > 15)  // advance counter.
        cntr.counter = 0;

    led_display_value(cntr);  // show value.

    cntr.timestamp = (unsigned int)millis();
}

static void leds_stop(led_counter_data_tamp; cntr)
{
    cntr.state = led_counter_state::stopped;
}

// ****************************
//  switch inputs data

static constexpr byte switch_debounce_delay = 30;  // 30ms is a good value for
                                                   // debouncing
struct switch_data_t
{
    byte sw1_state : 1;  // no need to waste more than 1 bit per switch 
    byte sw2_state : 1;
    byte timestamp;      // we'll only count to 30 ms, so 1 byte timestamp will do
};

static switch_data_t switch_data;

// ****************************
//  switch inputs code

static void control_inputs()
{
    const auto now = (byte)millis();

    if (now - switch_data.timestamp < switch_debounce_delay)
        return;

    switch_data.timestamp = now;

    // All switch control logic is regrouped here, and isolated 
    // form other control code, this makes the logic easier to
    // write, read, and debug.  

    bool b = digitalRead(button1);
    if (b amp; !switch_data.sw1_state)   // button was pushed right now.
    {
        if (led_counter[0].state == led_counter_state::stopped)
        {
            leds_start(led_counter[0]);   // start counter 1
            leds_stop(led_counter[1]);    // stop counter 2
        }
        else
        {
            leds_stop(led_counter[0]);    // stop counter 1
        }
    }
    switch_data.sw1_state = b;

    b = digitalRead(button2);
    if (b amp; !switch_data.sw2_state)   // button was pushed right now.
    {
        if (led_counter[1].state == led_counter_state::stopped)
        {
            leds_start(led_counter[1]);   // start counter 2
            leds_stop(led_counter[0]);    // stop counter 1
        }
        else
        {
            leds_stop(led_counter[1]);    // stop counter 2
        }
    }
    switch_data.sw2_state = b;
}

// ****************************

void setup()
{
    pinMode(button1, INPUT);
    pinMode(button2, INPUT);
 
    for (byte i = 0; i < 4;   i)
    {
        digitalWrite(ledPin1[i], LOW);
        pinMode(ledPin1[i], OUTPUT);

        digitalWrite(ledPin2[i], LOW);
        pinMode(ledPin2[i], OUTPUT);
    }

    led_display_init();
}

// ****************************
// The goal, always, is to exit loop() as fast as possible, so 
// everything will run smoothly, and appear to run simultaneously.

void loop()
{
    control_inputs();
    leds_control(led_counter[0]);
    leds_control(led_counter[1]);
}
 

У меня нет с собой arduino, поэтому я не компилировал и не запускал это, но это должно быть довольно близко. Дайте мне знать, если у вас возникли проблемы или есть какие-либо вопросы.