Как создать несколько запущенных потоков?

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

Один поток ожидает внешнего устройства, а также мигает светодиод в другом потоке.

49 голосов | спросил Bja 18 FebruaryEurope/MoscowbTue, 18 Feb 2014 19:11:41 +0400000000pmTue, 18 Feb 2014 19:11:41 +040014 2014, 19:11:41

7 ответов


41

В Arduino нет многопроцессорной или многопоточной поддержки. Однако вы можете сделать что-то близкое к нескольким потокам с некоторым программным обеспечением.

Вы хотите посмотреть Protothreads :

  

Protothreads - это чрезвычайно легкие стековые нити, предназначенные для   сильно ограниченные памятью системы, такие как небольшие встроенные системы или   беспроводные сенсорные узлы сети. Прототипы обеспечивают линейный код   выполнение для управляемых событиями систем, реализованных в C. Прототипы могут   использоваться с базовой операционной системой или без нее для обеспечения   блокировка обработчиков событий. Прототипы обеспечивают последовательный поток   управление без сложных состояний машин или полная многопоточность.

Конечно, есть пример Arduino здесь с пример кода . Этот вопрос SO также может быть полезен.

ArduinoThread тоже хорош.

ответил sachleen 18 FebruaryEurope/MoscowbTue, 18 Feb 2014 21:23:17 +0400000000pmTue, 18 Feb 2014 21:23:17 +040014 2014, 21:23:17
17

Arduino, основанный на AVR, не поддерживает (аппаратное) потокование, я не знаком с ARdu на базе Arduino. Одним из способов ограничения этого ограничения является использование прерываний, особенно прерываний с временной задержкой. Вы можете запрограммировать таймер для прерывания основной процедуры каждые столько микросекунд, чтобы запустить определенную другую процедуру.

http://arduino.cc/ru/Reference/Interrupts

ответил jippie 18 FebruaryEurope/MoscowbTue, 18 Feb 2014 22:14:37 +0400000000pmTue, 18 Feb 2014 22:14:37 +040014 2014, 22:14:37
14

В Uno можно выполнить многопоточность со стороны программного обеспечения. Не поддерживается нить уровня оборудования.

Чтобы добиться многопоточности, потребуется выполнение базового планировщика и ведение списка процессов или задач для отслеживания различных задач, которые необходимо выполнить.

Структура очень простого неуправляемого планировщика будет выглядеть так:

//псевдокод
void loop ()
{

для (i = o; i <n; i ++)
run (tasklist [i] для timelimit):

}

Здесь tasklist может быть массивом указателей на функции.

tasklist [] = {function1, function2, function3, ...}

С каждой функцией вида:

int function1 (long time_available)
{
   Вверх:
   //Выполняем короткую задачу
   if (run_time <time_available)
   goto top;
}

Каждая функция может выполнять отдельную задачу, такую ​​как function1, выполняющая светодиодные манипуляции, и function2 выполняет вычисления с плавающей запятой. Каждая задача (функция) несет ответственность за соблюдение назначенного ей времени.

Надеюсь, этого должно быть достаточно, чтобы вы начали.

ответил asheeshr 18 FebruaryEurope/MoscowbTue, 18 Feb 2014 19:36:32 +0400000000pmTue, 18 Feb 2014 19:36:32 +040014 2014, 19:36:32
9

В соответствии с описанием ваших требований:

  • один поток, ожидающий внешнего устройства
  • один поток мигает светодиодом

Кажется, вы могли использовать одно прерывание Arduino для первого «потока» (я бы скорее назвал его «задачей»).

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

Однако важно помнить о прерываниях, что вызываемая функция должна быть как можно быстрее (обычно не должно быть никакого вызова delay () или любого другого API, который будет зависеть на delay ()).

Если у вас есть длинная задача для активации при запуске внешнего события, вы можете потенциально использовать совместный планировщик и добавить к нему новую задачу из своей функции прерывания.

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

ответил jfpoilpret 19 FebruaryEurope/MoscowbWed, 19 Feb 2014 00:58:55 +0400000000amWed, 19 Feb 2014 00:58:55 +040014 2014, 00:58:55
5

Простое решение - использовать Планировщик . Существует несколько реализаций. Это кратко описывает тот, который доступен для плат AVR и SAM. В принципе, один вызов запустит задачу; «эскиз в эскизе».

#include <Scheduler.h>
....
void setup ()
{
  ...
  Scheduler.start (taskSetup, taskLoop);
}

Scheduler.start () добавит новую задачу, которая будет запускать taskSetup один раз, а затем повторно вызывает taskLoop, как работает эскиз Arduino. Задача имеет свой собственный стек. Размер стека является необязательным параметром. Размер стека по умолчанию - 128 байт.

Чтобы разрешить переключение контекста, необходимо вызвать yield () или delay () . Существует также макрос поддержки для ожидания состояния.

ждут (Serial.available ());

Макрос синтаксический сахар для следующего:

while (! (Serial.available ())) yield ();

Ожидание также может использоваться для синхронизации задач. Ниже приведен пример фрагмента:

volatile int taskEvent = 0;
#define signal (evt) do {wait (taskEvent == 0); taskEvent = evt; } while (0)
...
void taskLoop ()
{
  ждут (taskEvent);
  switch (taskEvent) {
  Дело 1:
  ...
  }
  taskEvent = 0;
}
...
void loop ()
{
  ...
  сигнал (1);
}

Подробнее см. примеры . Есть примеры из нескольких светодиодных миганий для кнопки debounce и простой оболочки с неблокирующей командной строкой. Шаблоны и пространства имен могут использоваться для структурирования и сокращения исходного кода. Ниже эскиз показывает, как использовать функции шаблона для multi-blink. Для стека достаточно 64 байта.

#include <Scheduler.h>

template <int pin> void setupBlink ()
{
  pinMode (pin, OUTPUT);
}

template <int pin, unsigned int ms> void loopBlink ()
{
  digitalWrite (pin, HIGH);
  Задержка (мс);
  digitalWrite (pin, LOW);
  Задержка (мс);
}

void setup ()
{
  Scheduler.start (setupBlink 11, loopBlink <11,500 & gt ;, 64);
  Scheduler.start (setupBlink 12, loopBlink <12, 250, 64);
  Scheduler.start (setupBlink 13, loopBlink <13,1000 & gt ;, 64);
}

void loop ()
{
  Уступать();
}

Существует также тест дать представление о производительности, то есть время запуска задачи, контекстный переключатель и т. д.

Наконец, существует несколько классов поддержки для синхронизации и коммуникации на уровне задач; Очередь и Семафор .

ответил Mikael Patel 21 Jpm1000000pmThu, 21 Jan 2016 15:34:10 +030016 2016, 15:34:10
3

Из предыдущего заклинания этого форума следующий вопрос /ответ был перенесен на электротехнику. Он имеет пример кода arduino для мигания светодиода с использованием прерывания таймера при использовании основного цикла для последовательного ввода-вывода.

https: //electronics.stackexchange .com /вопросы /67089 /как-кан-я-контроль-вещи-без использования задержки /67091 # 67091

Repost:

Прерывания - это распространенный способ добиться успеха, когда происходит что-то еще. В приведенном ниже примере светодиод мигает без использования delay (). Когда срабатывает Timer1, вызывается процедура обслуживания прерываний (ISR) isrBlinker (). Он включает /выключает светодиод.

Чтобы показать, что одновременно могут происходить другие вещи, loop () многократно записывает foo /bar в последовательный порт, не зависящий от светодиода.

#include "TimerOne.h"

int led = 13;

void isrBlinker ()
{
  static bool on = false;
  digitalWrite (led, on? HIGH: LOW);
  on =! on;
}

void setup () {
  Serial.begin (9600);
  Serial.flush ();
  Serial.println («Последовательный инициализирован»);

  pinMode (led, OUTPUT);

  //инициализировать мигание ISR
  Timer1.initialize (1000000);
  Timer1.attachInterrupt (isrBlinker);
}

void loop () {
  Serial.println ( "Foo");
  Задержка (1000);
  Serial.println ( "бар");
  Задержка (1000);
}

Это очень простая демонстрация. ISR могут быть намного сложнее и могут запускаться таймерами и внешними событиями (контакты). Многие из общих библиотек реализованы с использованием ISR.

ответил walrii 4 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 04 Sep 2015 00:57:26 +0300 2015, 00:57:26
3

Я также пришел к этой теме при реализации матричного светодиодного дисплея.

В одном слове вы можете создать планировщик опроса, используя функцию millis () и прерывание таймера в Arduino.

Я предлагаю следующие статьи от Билла Эрла:

https://learn.adafruit.com/multi- многозадачности-The-Arduino-часть-1 /Обзор

https://learn.adafruit.com/multi- многозадачности-The-Arduino-часть-2 /Обзор

https://learn.adafruit.com/multi- многозадачности-The-Arduino-часть-3 /Обзор

ответил intelliarm 4 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 04 Sep 2015 12:22:55 +0300 2015, 12:22:55

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132