Запуск двух циклов одновременно на Arduino

Я не могу объединить два приведенных ниже скетча. Что мне нужно, так это либо запустить оба цикла вместе, либо найти способ запустить обе функции внутри одного цикла.

Скетч 1

#include <SevSeg.h>
#include <DS1307RTC.h>
#include <Time.h>
#include <TimeLib.h>
#include <Wire.h>

// Создаем экземпляр объекта
SevSeg sevseg;
bool militaryTime = false; // верно для 24-часового формата

void setup() {
  byte numDigits = 4;
  byte digitPins[] = {2, 3, 4, 5};
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
  bool resistorsOnSegments = false; // 'false' означает, что резисторы находятся на цифровых выводах
  byte hardwareConfig = COMMON_ANODE; // См. README.md для опций
  bool updateWithDelays = false; // По умолчанию. рекомендуемые
  bool leadingZeros = true; // Используйте 'true', если хотите сохранить ведущие нули

  sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros);
  sevseg.setBrightness(90);
}

void loop() {
  tmElements_t tm;
  int time;
  int dot;

  if (RTC.read(tm)) {
    time = tm.Hour * 100;
    if (time > 1200 && militaryTime == false) {
      time = time - 1200;
    }
    if (time == 0 && militaryTime == false) {
      time = 1200;
    }
    time += tm.Minute;
  }

  if ((tm.Second % 2) == 0) {
    dot = 4;
  } else {
    dot = 2;
  }

  //Производим вывод на дисплей
  sevseg.refreshDisplay();
  sevseg.setNumber(time, dot);
}

Скетч 2

// Измените это на выходной контакт, который вы используете
#define TICK_PIN A0

void setup()
{
  pinMode(TICK_PIN,OUTPUT);
  while (1) {
    tone(TICK_PIN,1000,2);
    delay(1000);
  }
}

void loop()
{
}

, 👍0

Обсуждение

@LookAlterno На самом деле второй «цикл» никогда не выполняется из-за «пока» в «настройке»., @Johnny Mopp

Второй цикл также может быть в функции цикла. В любом случае, я не могу объединить их, чтобы заставить это работать., @Ameer


4 ответа


Лучший ответ:

1

В основном вам нужно избавиться от задержки и любых других циклов блокировки. Вот как это сделать.

Определите эту переменную глобально.

unsigned long lastTime = 0;

Затем в первом цикле добавьте следующий код либо в начало, либо в конец:

if (millis() - lastTime >= 1000 || !lastTime) {
    lastTime = millis();
    tone(TICK_PIN,1000,2);
} 
,

Для чего нужен !lastTime?, @Jot

Это сработало очень хорошо, @Ameer

Это выглядит знакомо .... точно так же, как мой ответ, который был опубликован за 3 часа до вашего., @Johnny Mopp

@JohnnyMopp Ну, это обычный трюк для эмуляции многозадачности на Arduino. Посмотрев на ваш, он не решает первую проблему выполнения, описанную выше. Вы можете найти этот ответ почти везде, это не ракетостроение., @Ikbel

Это нормально, хотя я не читал ваш ответ заранее, но я могу удалить свой ответ, если это сделает вас счастливым;), @Ikbel

Отпусти ситуацию. Я пошел дальше ... и правильно было бы удалить ваш необоснованный DV в моем ответе., @Johnny Mopp

Не проблема. Ожидание одобрения редактирования, прежде чем я смогу снова проголосовать за вас. Кроме того, я не мог удалить этот ответ, потому что он был принят., @Ikbel

@LookAlterno, я никогда не использовал !lastTime. Возможно, мне никогда не нужно было что-то запускать при первом выполнении цикла. Через 50 дней это может вызвать сбой., @Jot


0

Один из способов — использовать обратный вызов таймера.

// Включить библиотеку timer1
#include "TimerOne.h"

// Здесь другой код...

void setup()
{
    // Другой код установки здесь....

    // Настройка таймера
    Timer1.initialize(1000000);          // 1 секунда
    Timer1.attachInterrupt(callback);    // Установить обратный вызов
}

void callback()
{
    tone(TICK_PIN, 1000, 2);
}

void loop()
{
    // Код из 1-го цикла здесь...
}

Если это не сработает (если что-то еще использует timer1), вы можете просто отслеживать время между звуковыми сигналами:

uint32_t last_beep = 0;
const int beep_timeout = 1000;

void loop() {
    // Здесь код из первого цикла

    uint32_t now = millis();
    if (now - last_beep >= beep_timeout) {
        tone(TICK_PIN, 1000, 2);
        last_beep = now;
    }
}
,

Не могли бы отрицатели объяснить?, @Johnny Mopp

Вы действительно прочитали и поняли мой вопрос лучше, чем принятый ответчик. Причина, по которой я не принял это, была просто из-за сложности. Я проголосовал за ваш ответ., @Ameer


-1

Одновременный запуск двух циклов на Arduino

в общем случае ответ зависит от вашего определения слова "одновременно".

Но в данном случае ответ "определенно да", так как другой цикл пуст.

общий подход к такого рода вопросам:

void setup(void) {
  setup1();  // запускаем настройку 1
  setup2();  // запускаем настройку 2
  ...
}

void loop(void) {
  loop1();  // запускаем цикл1
  loop2();  // запускаем цикл2
  ...
}

этот подход потерпит неудачу только в том случае, если исходные функции setup() и loop() написаны плохо.

,

Это может работать в некоторых случаях, но даже близко не для моего случая., @Ameer


1

Я считаю, что самый простой способ справиться с этой задачей, когда вам приходится иметь дело с большой задержкой и думать, что вам нужен второй цикл, — это создать счетчик в основном цикле, используя сантисекунды (10 миллисекунд), а затем запустить ваш требуемый ответ, когда счетчик достигает вашего времени, например недействительный цикл (пустой) { счетчик=счетчик +1; если (счетчик==100){ тон (TICK_PIN, 1000, 2); счетчик =0; } ....остальная часть кода

,