Реализация двух потоков

magals
Offline
Зарегистрирован: 17.09.2014

из данного источника http://wiki.perexy.com/doku.php?id=articles:%D0%BC%D0%BD%D0%BE%D0%B3%D0%BE%D0%BF%D0%BE%D1%82%D0%BE%D1%87%D0%BD%D0%BE%D1%81%D1%82%D1%8C хотел взять пример в реализации двух потоков. 

 

#include <MirmPS.h>
 
int led = 13;
 
void setup() {  
    Serial.begin(9600);
    pinMode(led, OUTPUT);
    TIMSK2 = 1;						// настройка второго
}							// таймера прерываний
 
void loop2() {						// второй поток,
    Serial.println("HelloWorld loop2");	                // который мигает 
    digitalWrite(led, HIGH);	  		        // светодиодом и
    delay(500);						// выводит в порт
    digitalWrite(led, LOW);			        // приветствие
    delay(500);
}
 
void loop1() {						// первый поток,
    Serial.println("HelloWorld loop1"); 	        // который просто
    delay(2000);					// выводит приветствие
}

но как и ожидалась компилятор ругается если в программе нет стандартного "loop". как быть?

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

Почитать инструкцию к библиотеке? Поизучать примеры?

magals
Offline
Зарегистрирован: 17.09.2014

Puhlyaviy пишет:
Почитать инструкцию к библиотеке? Поизучать примеры?

некоторых примерах говорится что меняется main но как до неё добраться не говорят и что там менять тоже.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Я не очень понимаю, зачем вообще нужна такая "многозадачность".  Все равно два потока одновременно без вытесняющей многозадачности выполняться не будут. То что реализовано в этой библиотеке выглядит так: "пока первый поток не окончен, второй не запустится". С таким же успехом можно по таймингам запускать подпрограммы, будет ровно то же самое, а ресурсов потребуется меньше. Вытесняющую многозадачность на ардуино получить не получится, ее железо не позволяет этого делать всерьез.

magals
Offline
Зарегистрирован: 17.09.2014

brokly пишет:

Я не очень понимаю, зачем вообще нужна такая "многозадачность".  Все равно два потока одновременно без вытесняющей многозадачности выполняться не будут. То что реализовано в этой библиотеке выглядит так: "пока первый поток не окончен, второй не запустится". С таким же успехом можно по таймингам запускать подпрограммы, будет ровно то же самое, а ресурсов потребуется меньше. Вытесняющую многозадачность на ардуино получить не получится, ее железо не позволяет этого делать всерьез.

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

inspiritus
Offline
Зарегистрирован: 17.12.2012

Если кнопки заведены отдельными пинами их все можно объединить по "или" например 531ЛЕ7 и итоговый сигнал о нажатии завести на прерывание. В таком случае всякое нажатие будет генерировать аппаратное прерывание и переход к обработчику.

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

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

magals пишет:

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

Это вы описали неграмотное решение вопроса. Есть такое понятие как семафоры. Смысл такой, есть некая, ну пусть логическая, переменная которая проверяется в основном цикле. При нажатии на кнопку происходит прерываение, у ардуино можно отлавливать эвенты с нескольких входов в одно прерывание, в прерывании фиксируется на какой конкретно ножке произошло событие. Если это ножка соответствующая данной переменной, то изменяется ее (переменной) значение. По выходу из прерывания рано или поздно основной цикл проверит значение переменной, найдя изменение выполнит нужную подпрограмму и вернет значение переменной в прежнее состояние (вот эта переменная носит гордое название семафор). Оченно рекомендую использовать именно такие решения при написании программ для ардуино. Поскольку многопоточность - удел специализированых процессоров, которые умеют сохранять в стеке целый контент потока, которые могут переключаться между задачами аппаратно, а не так калечно(програмно) как это может быть реализовано на Атмелах используемых в ардуино. К тому же отходя от семафоров в поисках многозадачности вы наступаете на грабли одновременного изменения переменных двумя и более потоками, что отладить в среде ардуино практически невозможно. В общем не так вы решаете свою задачу.... А ведь при многозадачности имеют обязательное место еще и мьютексы и критические секции и специальные приемы програмирования... Там прикольная фигня :) Вот вы знаете, что такое критическая секция и зачем она ? :) 

А есть еще и приоритезация :))) Без нее совсем никак.

magals
Offline
Зарегистрирован: 17.09.2014

не увы не сталкивался. задачу уже решил с прерыванием. 

int PinRed = 11;
int PinGreen = 12;
int PinBlue = 13;

int PinMode = 10;
int Mode = 0;

int value;

void setup()
{
attachInterrupt(PinMode, ChangeMode, RISING);  
  
pinMode(PinRed,   OUTPUT);
pinMode(PinGreen, OUTPUT);
pinMode(PinBlue,  OUTPUT);

pinMode(PinMode,  INPUT);
}

void loop()
{
  switch(Mode)
  {
   case 0: SelectAll(); break;
   
   case 1: SelectOne(PinRed);   break; 
   case 2: SelectOne(PinGreen); break; 
   case 3: SelectOne(PinBlue);  break;
  }
}

void ChangeMode()
{
Mode++;
if(Mode>=7)
  {
    Mode=0;
  }
}

 

leon_3
Offline
Зарегистрирован: 15.05.2015

По поводу первого поста, я делал все как в статье, но ардуина ругается:

/media/HDS/Process/Arduino/libraries/MirmPS/main2.cpp: In function 'void branching()':
/media/HDS/Process/Arduino/libraries/MirmPS/main2.cpp:44:39: error: cannot convert 'programm1' from type 'volatile void()' to type 'void*'
  if (Taskcount==0) {Taskcount++;goto *programm1;}
                                       ^
/media/HDS/Process/Arduino/libraries/MirmPS/main2.cpp:45:39: error: cannot convert 'programm2' from type 'volatile void()' to type 'void*'
  if (Taskcount==1) {Taskcount++;goto *programm2;}
                                       ^
Ошибка компиляции.

Куда копать?

Arduino IDE 1.6.4, OS Kubuntu 14.04

Папка для библиотек: /media/HDS/Process/Arduino/libraries/