Проблемы с многозадачностью

Zimax
Offline
Зарегистрирован: 29.03.2015

Здравствуйте!

Сразу прошу прощения, если что-то не так, я в первый раз на вашем форуме :)

А теперь к делу. Начал я делать своего роюота, пока с минимальными задачами (объезд препятствий). Все шло хорошо до тех пор, пока я не решил, что неплохо было бы исполнять несколько действий одновременно. В моем случае это моргание двумя светодиодами, движение сервопривода, снятие показаний с HC-SR04 и последующее управление двигателей.

Из всего перечисленного работает все (по примеру BlinkWithoutDelay с использованием классов для определенного действия), но проблема появилась тогда, когда нужно было управлять двигателями. Суть в том, что при получении данных с сонара мы проверяем, больше ли это значение, чем 20 и в зависимости от этого определяем положение серво и едем в нужную сторону.

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

Заранее спасибо!

class Sweeper
{
  Servo myservo; //Создание объекта myservo

  int pos; //позиция сервопривода

  int i; //счетчик массива

  int increment; //на сколько переместится серво с каждой итерацией цикла

  int updateInterval; //время между обновлениями

  
  public:
  Sweeper(int interval, int S)
  {
    updateInterval = interval;
    increment = S;
  }
  
  void Attach(int pin)
  {
    myservo.attach(pin);
    myservo.write(0);
  }
  
  void Detach()
  {
    myservo.detach();
  }
  
  void Update()
  {
    if((millis() - lastUpdate) > updateInterval)  //время обновить!
    {
      lastUpdate = millis();
      if(i < 9)
      distance[i] = sonar.ping_cm();
      
      if (distance[i] <= 20)
      {
        switch(i) {
         case 0: {Stop(); go_left(60); }; //в функцию передается ШИМ для двигателей
         case 1: {Stop(); go_left(60); };
         case 2: {Stop(); go_back(60); };
         case 3: {Stop(); go_right(60); };
         case 4: {Stop(); go_right(60); };
         case 5: {Stop(); go_right(60); };
         case 6: {Stop(); go_back(60); };
         case 7: {Stop(); go_left(60); };
         case 8: {Stop(); go_left(60); };
         }
        
      }
      
      i += 1;
      pos += increment;
      myservo.write(pos);
      if((pos >= 180) || (pos <= 0)) //вращать некуда - меняем направление
      {
        increment = -increment; // изменение направления
      }
      /*if(i == 11)
      {
       i = 0; 
      }*/
    }
  }
};

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Сам вопрос не задан, что именно не так работает?

1. Код с 37 строки "подозрительный".
2. Массив distance внешний, индекс может легко выйти за пределы, кто его знает как он там снаружи описан.
3. i в Update не ограничен. Кстати, называть таким именем переменную - член класса - плохой обычай. Называйте переменные нормальными именами, не экономьте на спичках.
4. С 43 по 51 строки нет ни одного break в switch, почитайте теорию. Фигурные скобки не означают конец case, это в Паскале так было, а в C не так.

UPD: И, да, не называйте это многозадачностью, здесь ОС никакой нет, плоский код, плюс обработчики прерываний - это не многозадачность.

 

Zimax
Offline
Зарегистрирован: 29.03.2015

Вопрос как раз был в том, что не так. Спасибо, за break, про него совсем забыл! Про переменные учту. Сейчас исправлю.

Спасибо за подсказку.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Еще есть совет, чтобы не ошибаться, не пишите так, как написано в строках 37-38, заключите 38 строку в фигурные скобки. Компилятору пофиг, а у Вас будет меньше шансов нарваться на ошибку. Например, так:

if(i < 9)
{
      distance[i] = sonar.ping_cm();
}

будет четко видно, что if распространяется только на distance[i] = sonar.ping_cm();, а не на последующие строки.

Zimax
Offline
Зарегистрирован: 29.03.2015

Т.е. проблема в том, что двигатели не реагируют либо реагируют неверно

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Смысл в том, что вопрос понятен только Вам. Вы привели кусочек кода и при этом говорите "двигатели не реагируют либо реагируют не верно", а как они должны реагировать, мы можем только догадываться. Если уже нашли ошибку, то можете и не писать, в чем вопрос.

Это я к тому, что часто люди пишут, что программа "работает не так" и приводят исходник из которого далеко не всегда видно, как она должна работать, плюс нам приходится копаться в скетче (а они порой бывают и по 900 строк), чтобы попытаться понять в чем ошибка.

Это всего лишь советы, чем точнее опишете проблему, тем больше шансов получить корректный ответ ;) А нет - так нет, дело Ваше.

 

Zimax
Offline
Зарегистрирован: 29.03.2015

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

Еще раз прошу прощения за свою неясность ;)

Zimax
Offline
Зарегистрирован: 29.03.2015

Все, спасибо за подсказки, разобрался! Теперь все работает!

sharp-news
Offline
Зарегистрирован: 22.01.2015

Друзья, решил не пестрить схожими темами, вопрос:

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

Не всегда отправляет смс, как бы замирает (судя по монитору порта).

Может ли быть такое, что контроллер просто не может выполнить такое количество команд одновременно. И что с этим делать.

#include <SoftwareSerial.h>
#include "DHT.h"
#define DHTPIN 11    // pin на котором висит датчик температуры
#define DHTTYPE DHT22  // DHT 22 тип датчика
//Отсылается смс в формате: влажность;температура;устройство1;устройство2;устройство3;устройство4;Контроль периметра;Состояние периметра;Контроль автотемпературы;Установленная температура;STEWARD;
int greenLed = 13; //Зеленый светодиод на PIN13
int powerGSM = 9; //Пин включения GSM
int unit1 = 3; //Управляемое устройство 1
int unit2 = 4; //Управляемое устройство 2
int unit3 = 5;//Управляемое устройство 3
int unit4 = 6;//Управляемое устройство 4
int perimetr = 10;// Датчик периметра
String statusHome;
int t=0;
 
unsigned long currentTime;
unsigned long loopTime;
 
boolean unit1status = false; //Управляемое устройство 1
boolean unit2status = false; //Управляемое устройство 2
boolean unit3status = false;//Управляемое устройство 3
boolean unit4status = false;//Управляемое устройство 4
 
boolean isPerimetr = false; //Контроль периметра
boolean sendSMS = false; //Для проверки что смс отсылаем только один раз
boolean isAuto = false; //Автоматическое управление температурой
int autoTemp = 0;
int delta=2;
 
DHT dht(DHTPIN, DHTTYPE);
int five_volts_Pin=12; 
SoftwareSerial gprsSerial(7, 8);
 
boolean prevBtn = LOW;
String currStr = "";
// Переменная принимает значение True, если текущая строка является сообщением
boolean isStringMessage = false;
 
void setup()
{
    pinMode(unit1, OUTPUT);
    pinMode(unit2, OUTPUT);
    pinMode(unit3, OUTPUT);
    pinMode(unit4, OUTPUT);
    pinMode(powerGSM, OUTPUT);
    pinMode(perimetr, INPUT);
    pinMode(greenLed, OUTPUT);
    pinMode(five_volts_Pin, OUTPUT);
 
    digitalWrite(unit1, HIGH);
    digitalWrite(unit2, HIGH);
    digitalWrite(unit3, HIGH);
    digitalWrite(unit4, HIGH);
    digitalWrite(powerGSM, LOW);
    digitalWrite(greenLed, LOW);
    digitalWrite(five_volts_Pin, HIGH);
 
    //Включаю GSM Модуль
    digitalWrite(powerGSM, HIGH);
    delay(1000);
    digitalWrite(powerGSM, LOW);
    delay(5000);
    gprsSerial.begin(19200);
    delay(300);
    // Настраиваем приём сообщений с других устройств
    // Между командами даём время на их обработку
    gprsSerial.print("AT+CMGF=1\r");
    delay(300);
    gprsSerial.print("AT+IFC=1, 1\r");
    delay(300);
    gprsSerial.print("AT+CPBS=\"SM\"\r");
    delay(300);
    gprsSerial.print("AT+CNMI=1,2,2,1,0\r");
    delay(500);
 
    //Инициализация температурного датчика
    Serial.begin(9600);
    Serial.println(dht.readTemperature());
 
    dht.begin();
    delay(3000);
// ParseSMS("1;20;0;1;1;1;1");
  currentTime = millis();
  loopTime = currentTime;
}
 
 
 
void GetDatchik() {
  // Пол
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();
 
  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } else {
    statusHome = int(h)+String(";")+int(t)+String(";")+int(unit1status)+String(";")+int(unit2status)+String(";")+int(unit3status)+String(";")+int(unit4status)+String(";")+int(isPerimetr)+String(";")+digitalRead(perimetr)+String(";")+int(isAuto)+String(";")+int(autoTemp)+String(";STEWARD");
    sendTextMessage(statusHome);
//  Serial.print("H"); //Влажность
//  Serial.print(h);
//  Serial.print(";");
//  Serial.print("T"); //Температура
//  Serial.print(t);
//  Serial.println(";");
//  Serial.println(statusHome);
 
  }
}
 
 
 
 
 
 
void loop()
{
// delay(5000);
// GetDatchik();
int sostPerimetr; //Состояние периметра
  if (gprsSerial.available()){
  char currSymb = gprsSerial.read();
Serial.print(currSymb);// для просмотра через монитор
 
      //  return;
  //  char currSymb = gprsSerial.read();
  //  Serial.println(currSymb);
    if ('\r' == currSymb) {
        if (isStringMessage) {
            //если текущая строка - SMS-сообщение,
            //отреагируем на него соответствующим образом
            if (!currStr.compareTo("STATUS"))
            {
              GetDatchik();
            }
            else if (currStr.startsWith("0#todo#")||currStr.startsWith("1#todo#")) {
              ParseSMS(currStr);
            }
         
            isStringMessage = false;
        } else {
            if (currStr.startsWith("+CMT")) {
                //если текущая строка начинается с "+CMT",
                //то следующая строка является сообщением
                isStringMessage = true;
            }
        }
        currStr = "";
    } else if ('\n' != currSymb) {
        currStr += String(currSymb);
    }
  }
//  Контроль периметра!!!
  if (isPerimetr) { //Проверка Включен ли контроль периметра
      digitalWrite(greenLed, HIGH);
      sostPerimetr = digitalRead(perimetr);
        if (sostPerimetr==LOW) { //Проверка на разомкнутый периметр
          digitalWrite(greenLed, LOW);
          delay(2000);
          digitalWrite(greenLed, HIGH);
          delay(200);
          //и отсылаем СМС
          if (sendSMS==false){
            sendTextMessage("WARNING! ACHTUNG! ALARM");
            sendSMS=true;
          }
      }
 
  } else {
    digitalWrite(greenLed, LOW);
  }
//  Контроль температуры!!!
  if (isAuto==true) { //Проверка Включен автоуправление батареями
  //Замер температуры можно проводить не чаще раз в 5 минут
      currentTime = millis();
  if(currentTime >= (loopTime + 60000)){
  t = int(dht.readTemperature());
  loopTime = currentTime;
  }
//
//  Serial.print("t=");
//  Serial.println(t);
//  Serial.print("autoTemp+delta=");
//  Serial.println(autoTemp+delta);
    if (t > autoTemp+delta) {
        if ( unit1status==true){
        digitalWrite(unit1, HIGH);
        unit1status=false;
        }
        if ( unit2status==true){
        digitalWrite(unit2, HIGH);
        unit2status=false;
        }
        if ( unit3status==true){
        digitalWrite(unit3, HIGH);
        unit3status=false;
        }
        if ( unit4status==true){
        digitalWrite(unit4, HIGH);
        unit4status=false;
        }
        } else if (t < autoTemp-delta) {
        if ( unit1status==false){
        digitalWrite(unit1, LOW);
        unit1status=true;
        }
        if ( unit2status==false){
        digitalWrite(unit2, LOW);
        unit2status=true;
        }
        if ( unit3status==false){
        digitalWrite(unit3, LOW);
        unit3status=true;
        }
        if ( unit4status==false){
        digitalWrite(unit4, LOW);
        unit4status=true;
        }
        }
 
  }
}
 
 
 
 
void ParseSMS(String currStr) {
  int firstSemicolon;
  //Распарсиваем SMS
  firstSemicolon = 1;//находим первую ;
  //Получаем значение Автоматического режима контроля температуры
  // if (currStr.substring(firstSemicolon+1,currStr.indexOf(';', firstSemicolon + 1 )) == "0"){
    if (currStr.substring(0,1) == "0"){
    isAuto=false;
  }
    else{
      isAuto=true;
    }
  //  Serial.println(currStr.substring(0,1));
//  Serial.print("isAuto=");
//  Serial.println(isAuto);
  firstSemicolon = currStr.indexOf(';');
  //Получаем значение Автоматического уровня температуры
  autoTemp = stringToNumber(currStr.substring(firstSemicolon+1,currStr.indexOf(';', firstSemicolon + 1 )));
  firstSemicolon = currStr.indexOf(';',firstSemicolon + 1 );
// Serial.println(autoTemp);
  //Получаем значение Контроля периметра
  if (currStr.substring(firstSemicolon+1,currStr.indexOf(';', firstSemicolon + 1 )) == "0"){
    isPerimetr=false;
  } else {
      isPerimetr=true;
    }
//  Serial.println(isPerimetr);
  firstSemicolon = currStr.indexOf(';',firstSemicolon + 1 );
 
  //Получаем значение Устройства 1
if ((currStr.substring(firstSemicolon+1,currStr.indexOf(';', firstSemicolon + 1 )) == "0")&&(isAuto==false)){
    unit1status=false;
    digitalWrite(unit1, HIGH);
//  Serial.println("Устройство 1 ВЫКЛ");
  } else{
      unit1status=true;
      digitalWrite(unit1, LOW);
  //    Serial.println("Устройство 1 ВКЛ");
    }
firstSemicolon = currStr.indexOf(';',firstSemicolon + 1 );
 
  //Получаем значение Устройства 2
if ((currStr.substring(firstSemicolon+1,currStr.indexOf(';', firstSemicolon + 1 )) == "0")&&(isAuto==false)){
    unit2status=false;
    digitalWrite(unit2, HIGH);
  } else {
      unit2status=true;
      digitalWrite(unit2, LOW);
    }
  firstSemicolon = currStr.indexOf(';',firstSemicolon + 1 );
 
  //Получаем значение Устройства 3
if ((currStr.substring(firstSemicolon+1,currStr.indexOf(';', firstSemicolon + 1 )) == "0")&&(isAuto==false)){
    unit3status=false;
    digitalWrite(unit3, HIGH);
  } else {
      unit3status=true;
      digitalWrite(unit3, LOW);
    }
  firstSemicolon = currStr.indexOf(';',firstSemicolon + 1 );
 
  //Получаем значение Устройства 4
if ((currStr.substring(firstSemicolon+1,currStr.indexOf(';', firstSemicolon + 1 )) == "0")&&(isAuto==false)){
    unit4status=false;
    digitalWrite(unit4, HIGH);
  } else {
      unit4status=true;
      digitalWrite(unit4, LOW);
    }
 
 
 
  }
 
/*
* Функция отправки SMS-сообщения
*/
void sendTextMessage(String text) {
    // Устанавливает текстовый режим для SMS-сообщений
    gprsSerial.print("AT+CMGF=1\r");
    delay(100); // даём время на усваивание команды
    // Устанавливаем адресата: телефонный номер в международном формате
    gprsSerial.println("AT + CMGS = \"+7913\""); //Телефон 
    delay(100);
    // Пишем текст сообщения
    gprsSerial.println(text);
    delay(100);
    // Отправляем Ctrl+Z, обозначая, что сообщение готово
    gprsSerial.println((char)26);
}
 
 
//Функция преобразовангия STRING в INT
int stringToNumber(String thisString) {
  int i, value = 0, length;
  length = thisString.length();
  for(i=0; i<length; i++) {
    value = (10*value) + thisString.charAt(i)-(int) '0';;
  }
  return value;
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sharp-news пишет:

Контроллер поддерживает постоянную температуру и охраняет объект.

Охрана объекта и параллельно управление самогонным аппаратом? :))))) Круто!

sharp-news пишет:

В момент поддержания температуры, замеры производятся каждые пять минут (одна задача), к примеру происходит разрыв периметра охраны (вторая задача). Контроллер должен отправить смс (третья задача) и начать мигать индикацией (четвертая задача).

Может ли быть такое, что контроллер просто не может выполнить такое количество команд одновременно. 

Не может. Такие задачи для контроллера - вообще не нагрузка. Он может ещё параллельно футбольным роботом управлять.

sharp-news пишет:

И что с этим делать.

Что делать?

Прекратите издеваться над котроллером - он у Вас по 10 секунд сидит в делэях ни хрена при этом не делая. При таком программировании у него и на "помигать 13-м пином" времени не останется.

А если по шагам, то:

1. Забудьте нахрен слово delay - вычеркните его из всех своих файлов-описаний языка. Нет такого слова! Оно противоречит концепции программирования МК

2. Перепишите код так. чтобы не заставлять МК торчать в никому не нужных пустых циклах по пять секунд и он Вас ещё удивит. На Ваших задачах он будет просто простаивать.

Ещё раз - функция delay недопустима ни в каком проекте сложнее, чем помигать 13-м пином. Просто недопустима. Ни в каком контексте. Она отжирает время МК на совершенно ненужный цикл. И отжирает она у Вас тысячами миллисекунд.

 

 

sharp-news
Offline
Зарегистрирован: 22.01.2015

ЕвгенийП пишет:

А если по шагам, то:

1. Забудьте нахрен слово delay - вычеркните его из всех своих файлов-описаний языка. Нет такого слова! Оно противоречит концепции программирования МК

2. Перепишите код так. чтобы не заставлять МК торчать в никому не нужных пустых циклах по пять секунд и он Вас ещё удивит. На Ваших задачах он будет просто простаивать.

Ещё раз - функция delay недопустима ни в каком проекте сложнее, чем помигать 13-м пином. Просто недопустима. Ни в каком контексте. Она отжирает время МК на совершенно ненужный цикл. И отжирает она у Вас тысячами миллисекунд.

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Нет, ну задержки-то Вам нужны, так? Занчит, нужно переписывать код, чьобы эти задержки отрабатывались без блокирования контроллера на всё время задержки. Идея самой просто реализации такого подхода (не самой лучшей, но самой простой) представлена в скетче-примере на этом сайте "блинк без делэй".

sharp-news
Offline
Зарегистрирован: 22.01.2015
/* Blink without Delay
 2005
 by David A. Mellis
 modified 8 Feb 2010
 by Paul Stoffregen
 */

const int ledPin =  13;      // номер выхода, подключенного к светодиоду
// Variables will change:
int ledState = LOW;             // этой переменной устанавливаем состояние светодиода 
long previousMillis = 0;        // храним время последнего переключения светодиода

long interval = 1000;           // интервал между включение/выключением светодиода (1 секунда)

void setup() {
  // задаем режим выхода для порта, подключенного к светодиоду
  pinMode(ledPin, OUTPUT);      
}

void loop()
{
  // здесь будет код, который будет работать постоянно
  // и который не должен останавливаться на время между переключениями свето
  unsigned long currentMillis = millis();
 
  //проверяем не прошел ли нужный интервал, если прошел то
  if(currentMillis - previousMillis > interval) {
    // сохраняем время последнего переключения
    previousMillis = currentMillis;  

    // если светодиод не горит, то зажигаем, и наоборот
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // устанавливаем состояния выхода, чтобы включить или выключить светодиод
    digitalWrite(ledPin, ledState);
  }
}

Посмотрел я на это и окончательно подзавис, delay все таки сильно упрощало задачу, а из этого я даже не знаю как взять нужное....

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

.........Забудьте нахрен слово delay - вычеркните его из всех своих файлов-описаний языка. Нет такого слова! Оно противоречит концепции программирования МК........

Не факт.

delay   ( 1 )  как  и nop   иногда очень полезная комманда.

Ну-ка напишите мне её на миллисе?
Главно - знать меру.

sharp-news
Offline
Зарегистрирован: 22.01.2015

Затык в ответе системы начинается с выполнения этой команды

Код (text):
//и отсылаем СМС
          if (sendSMS==false){
            sendTextMessage("WARNING! ACHTUNG! ALARM");
            sendSMS=true;

может достаточно убрать delay из этого куска

 

Код (text):
}
//  Контроль периметра!!!
  if (isPerimetr) { //Проверка Включен ли контроль периметра
      digitalWrite(greenLed, HIGH);
      sostPerimetr = digitalRead(perimetr);
        if (sostPerimetr==LOW) { //Проверка на разомкнутый периметр
          digitalWrite(greenLed, LOW);
          delay(2000);
          digitalWrite(greenLed, HIGH);
          delay(200);
          //и отсылаем СМС
          if (sendSMS==false){
            sendTextMessage("WARNING! ACHTUNG! ALARM");
            sendSMS=true;
          }
      }

  } else {
    digitalWrite(greenLed, LOW);
  }

и наиболее вероятно из этого

 

Код (text):
* Функция отправки SMS-сообщения
*/
void sendTextMessage(String text) {
    // Устанавливает текстовый режим для SMS-сообщений
    gprsSerial.print("AT+CMGF=1\r");
    delay(100); // даём время на усваивание команды
    // Устанавливаем адресата: телефонный номер в международном формате
    gprsSerial.println("AT + CMGS = \"+7913504\""); //Телефон нужно указать свой
    delay(100);
    // Пишем текст сообщения
    gprsSerial.println(text);
    delay(100);
    // Отправляем Ctrl+Z, обозначая, что сообщение готово
    gprsSerial.println((char)26);
}
//Функция преобразовангия STRING в INT
int stringToNumber(String thisString) {
  int i, value = 0, length;
  length = thisString.length();
  for(i=0; i<length; i++) {
    value = (10*value) + thisString.charAt(i)-(int) '0';;
  }
  return value;
}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

trembo пишет:

.........Забудьте нахрен слово delay - вычеркните его из всех своих файлов-описаний языка. Нет такого слова! Оно противоречит концепции программирования МК........

Не факт.

delay   ( 1 )  как  и nop   иногда очень полезная комманда.

Ну-ка напишите мне её на миллисе?
Главно - знать меру.

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

А delay(1) - зачем? Заказываешь таймеру прервать тебя через 1 ms и всего делов. Так за эту миллисекунду котроллер столько делов наделает - всё же 16 тысяч тактов. Я никогда не использую делэй - незачем.

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

Ну а в данном скетче. где делэи местами по 5-10 секунд, ... говорить не о чем.

Arhat109
Offline
Зарегистрирован: 26.05.2015

А попродробней, можете?

"прервать меня через 1мс" - в смысле поднять прогу обработки прерывания - не проблема. Проблема в том, что в ней ничего толкового сделать нельзя. Через 1 мс таймер сработать должен...

А вот именно "прервать", то бишь переключить весь контекст выполнения ... или есть иной способ?

Joiner
Offline
Зарегистрирован: 04.09.2014

На вопросы многозадачности натыкался много раз, но так и не понял что это такое. Когда несколько светодиодиков смотрят на миллисы и думают не пора ли мне загореться или погаснуть, многозадачностью не считаю. И работа по прерываниям, как мне кажется, это тоже не многозадачность. Похоже на многозадачность, когда я на своем компе, купленном на замену старому, лет 15 назад с какой-то крутой материнкой со встроенной видеокартой, запускал одновременно 5-6 фильмов, и они демонстрировались в 5-6-ти окошках и хором бубнили. Вот это многозадачность. А если по какому-то прерыванию все остановить нахрен....какая это многозадачность?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Joiner пишет:

лет 15 назад с какой-то крутой материнкой со встроенной видеокартой, запускал одновременно 5-6 фильмов, и они демонстрировались в 5-6-ти окошках и хором бубнили. Вот это многозадачность. А если по какому-то прерыванию все остановить нахрен....какая это многозадачность?

А у Вас там тоже всё по останавливалось и в каждый конкретный момент выполнялось что-то одно (15 лет назад - наверняка одно ядро было), просто Вы этого не замечали, так как переключалось быстро между задачами и каждая на глаз работала постоянно.

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109 пишет:

А попродробней, можете?

"прервать меня через 1мс" - в смысле поднять прогу обработки прерывания - не проблема. Проблема в том, что в ней ничего толкового сделать нельзя. Через 1 мс таймер сработать должен...

А вот именно "прервать", то бишь переключить весь контекст выполнения ... или есть иной способ?

Нет, ну, что Вы. Переключать контекст - т.е. по сути делать мультизадачную ОС для AVR'ки  ... в принципе можно, но во-первых это займёт недопустимо много ресурсов, а во вторых - зачем такие сложности для компютера в котором всё равно "много задач" не поместится. Есть очень много других подходов, которые здесь более приемлемы.

Отличный пример - "таблицы решений". Контроллер превращается по сути в конечный автомат, а вся логика программы зашита в матрице переходов между состоянниями. При таком подходе от обработчика прерываний нужно только изменить состояние автомата (че-нить присвоить чему-нибудь). А функция loop - просто длинный case по состояниям и в зависимости от состояния должна что-то сделать и поменять состояние. 

При таком подходе нет никакой необходимости ждать чего-то. Достаточно взвести соответсвующее состояние. lopp будет понимать, что ждём (по состоянию). Когда прерывание случится, обработчик поменяет состояниею И ближайший loop начнёт что-то делать уже исходя из нового состояния.

Это не единственный подход, есть другие, но Вы просили пример.

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

Есть прекрасная книга Хамби. Древняя, но вполне актуальная). Там всё очень понятно изложено. Почитайте, Вам понравится. И наверняка почуствуете, что создавалась эта техника программирования специально для контроллеров - http://www.twirpx.com/file/366454/

 

sharp-news
Offline
Зарегистрирован: 22.01.2015

ЕвгенийП пишет:

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

А delay(1) - зачем? Заказываешь таймеру прервать тебя через 1 ms и всего делов. Так за эту миллисекунду котроллер столько делов наделает - всё же 16 тысяч тактов. Я никогда не использую делэй - незачем.

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

Ну а в данном скетче. где делэи местами по 5-10 секунд, ... говорить не о чем.

[/quote]

Сжальтесь, не все такие сообразительные, вы можете просто рассказать, что сделать с этим скетчем. Не взлетая в теории к "парадигмам программирования", и лифтам манхетена.

Joiner
Offline
Зарегистрирован: 04.09.2014

ЕвгенийП пишет:

А у Вас там тоже всё по останавливалось и в каждый конкретный момент выполнялось что-то одно (15 лет назад - наверняка одно ядро было), просто Вы этого не замечали, так как переключалось быстро между задачами и каждая на глаз работала постоянно.

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

Полностью согласен. Но нужно еще и расставить приоритеты. Что-то безболезненно можно прервать, а для чего-то -катастрофа.

Arhat109
Offline
Зарегистрирован: 26.05.2015

Да, пасибки. С конечными автоматами - знаком и ваще, их разработка - мое любимое занятие и по сей день. Самый "крутой" делал в 2012году для задачи распознавания "тот же самый товар". Конечный автомат со стековой памятью контекста перехода и программируемым "блоком микропрограммного управления" с автосборкой запроса в Мускуль, по контексту: "как искать похожие товары в БД"... в некоторых ситуациях, даже мне, автору, было не совсем понятно КАК эта зараза принимала решения. :)

Arhat109
Offline
Зарегистрирован: 26.05.2015

Есть что-то готовое на эту тему? Хотя, сваять "ещё один" таблично-управляемый автомат - не проблема. Вот как раз тут, мне кажется что "расширитель SRAM будет ой как к месту. Нарисовал себе страничный контроллер на 7 окон с 8-битным номером страницы (upto 2Mb) ... а мне пишут, что оно "нафиг никому не надо". :)

Arhat109
Offline
Зарегистрирован: 26.05.2015

Кстати, если делать КА с динамически изменяемыми "весами переходов" и целевой функцией "успещно/промах", то получится "самообучаемый" автомат. :)

Помнится у меня, такой играть в "крестики-нолики" учился на уровне "профи" всего ... за около 300 итераций. Ещё на IBM360. А прообраз биржевого бота - делать ставки ... ещё в 1986году ... как раз на "микроконтроллере" (Д3-28, оно же "бортовой вычислитель МИГ-17") :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109 пишет:

Кстати, если делать КА с динамически изменяемыми "весами переходов" и целевой функцией "успещно/промах", то получится "самообучаемый" автомат. :)

Ну, да, так и есть - самообучаемый автомат. Другими словами - искусственная нейронная сеть.

А что до табличных процессоров, я не делаю универсального процессора для AVR'ки. Просто при программировании придерживаюсь этой техники. В итоге программа (функция loop) получается как несколько вложенных switch'ей.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sharp-news пишет:

вы можете просто рассказать, что сделать с этим скетчем. Не взлетая в теории к "парадигмам программирования", и лифтам манхетена.

Я разве не рассказал? Вы просто пропустили. Скетч нужно выбросить и переписать более адекватно архитектуре используемого вычислительного устройства. 

Кстати, и ссылка на книгу парой постов выше имеется.

sharp-news пишет:

Не взлетая в теории к "парадигмам программирования", и лифтам манхетена.

Вы слышали песню "Наутилуса" "Прогулки по воде"? ( http://get-tune.net/song/11335460-Progulki-Po-Vod/ ). Там апостол Андрей спросил у Христа, как ходить по воде. Тот ему ответил, "пойди, повиси на кресте, потом возвращайся и будем ходить". А Андрей не понимал и всё требовал научить его по воде ходить, а крест, мол подождёт.

Вот так и здесь с новичками. Спрашивает как программиировать. Пытаешься объяснить, а тебе в ответ: "не надо философии, просто скажи какую букву где написать". Но программирование - это не писание букв. Если понимать смысл, то можно написать сотней способов, практически любыми "буквами".

Ну, напишу я скрипт за Вас, и что? Вам будет легче писать следующий?

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

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

Я давно использую библиотеку Timer.h оттуда

Там есть пример использования запуском подпроцессов с разнной периодичностью запуска. Удобно, что при выходе из процесса нужно задать интервал, после которого он должен перезапуститься. При работе возможны погрешности, и весьма приличные, если в процессе глухие циклы , или delay, тк процесс запускается из лупа вызовом t.update, и , пока текущий процесс не завершится, новый не запустится, несмотря на наступление момента запуска. 

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

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

можно еще посмотреть библиотеку Timerone.h но мнеона не пришлась, из-за периодических (раз в нсколько суток) глюков. Однако, если мк живет в цикле ресета, то это не принципиально.

sharp-news
Offline
Зарегистрирован: 22.01.2015

ЕвгенийП пишет:

sharp-news пишет:

вы можете просто рассказать, что сделать с этим скетчем. Не взлетая в теории к "парадигмам программирования", и лифтам манхетена.

Я разве не рассказал? Вы просто пропустили. Скетч нужно выбросить и переписать более адекватно архитектуре используемого вычислительного устройства. 

Кстати, и ссылка на книгу парой постов выше имеется.

sharp-news пишет:

Не взлетая в теории к "парадигмам программирования", и лифтам манхетена.

Вы слышали песню "Наутилуса" "Прогулки по воде"? ( http://get-tune.net/song/11335460-Progulki-Po-Vod/ ). Там апостол Андрей спросил у Христа, как ходить по воде. Тот ему ответил, "пойди, повиси на кресте, потом возвращайся и будем ходить". А Андрей не понимал и всё требовал научить его по воде ходить, а крест, мол подождёт.

Вот так и здесь с новичками. Спрашивает как программиировать. Пытаешься объяснить, а тебе в ответ: "не надо философии, просто скажи какую букву где написать". Но программирование - это не писание букв. Если понимать смысл, то можно написать сотней способов, практически любыми "буквами".

Ну, напишу я скрипт за Вас, и что? Вам будет легче писать следующий?

Нет у меня сейчас времени разбираться, давай брат перенесем объяснение в другую плоскость, комерческую.

Мое мыло: Sharp-news@rambler.ru

Обсудим, ответ нужен "чем быстрее, тем лучше".

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sharp-news пишет:

давай брат перенесем объяснение в другую плоскость, комерческую.

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

А программировать лучше научиться, раз уж хотите работать с контроллерами.

Удачи Вам!

Arhat109
Offline
Зарегистрирован: 26.05.2015

Подниму тему.

Вчера, совершенно случайно наткнулся на эту ссылку:

http://ru.wikipedia.org/wiki/%D0%90%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%...

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

Админам форума настоятельно рекомендую выложить содержимое этой ссылки где-то в теории программирования Ардуин.

Я не знаю причин почему типовой Wiring не содержит даже намека на этот подход .. толи по неграмотности толи ещё по каким причинам - не суть в общем-то, но ИМЕННО ТАК и должны программироваться все скетчи, начиная с примитивного blink.ino. И никаких вопросов про "тормознутость проца" возникать не будет... впрочем как и delay() исчезнет "сама собою".

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

Клапауций 999
Offline
Зарегистрирован: 06.06.2015

так и не въехал, вкуда delay() исчезает сама собою?

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

Arhat109 пишет:

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

ДУмаю что, сразу как выложишь свою новую ИДЕ для AVR камней, там и опубликуем первым делом.

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

Клапауций 999 пишет:

так и не въехал, вкуда delay() исчезает сама собою?

она это.. дизентегрируется :)

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Arhat109, Вы правильно поняли, что я имел в виду. Собственно, таблицы решений (одна из реализаций автоматного подхода) - наиболее адекватная вещь для контроллеров. Используется интуитивно и совершенно естественно. Ну, а delay при таком подходе действительно не нужен.

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Нда.... А вот мне как-то по барабану есть у меня делэй в скетче или нет. Если мой прототип или законченная игрушка работает так как мне надо. Без тормозов и заскоков. Вы собрались использовать Ардуино в промышленных целях? Нет? И на кой тогда вся эта оптимизация? Ну а если собрались - то Вам в изготовители шлема.

Есть у меня одна поделка, так там ардуина при определенных условиях сама себе питание обрывает перед этим мигая светиком. И зачем мне там менять делэй на что-то?

Arhat109
Offline
Зарегистрирован: 26.05.2015

Не обращайте внимания. Эта школота ничего слаще морковки никогда не видела. Отсюда, от непонимания темы и весь троллизм. :)

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

Arhat109 пишет:

Не обращайте внимания. Эта школота ничего слаще морковки никогда не видела. Отсюда, от непонимания темы и весь троллизм. :)

ну куда уж нам то... до вас.. великих переписывателей ИДЕ и разоблачителей разработчиков ардуино.. :) мы так.. белим, красим..

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Arhat109 пишет:

Не обращайте внимания. Эта школота ничего слаще морковки никогда не видела. Отсюда, от непонимания темы и весь троллизм. :)

А у Вас видимо от старческого маразма и глубокого понимания темы твердая увернность в возможности параллельных процессов на ардуине? Нюню

Клапауций 999
Offline
Зарегистрирован: 06.06.2015

Arhat109 пишет:

Не обращайте внимания. Эта школота ничего слаще морковки никогда не видела. Отсюда, от непонимания темы и весь троллизм. :)

а, я щитаю, что вся эта херня от русофобии.

Клапауций 999
Offline
Зарегистрирован: 06.06.2015

JollyBiber пишет:

А у Вас видимо от старческого маразма и глубокого понимания темы твердая увернность в возможности параллельных процессов на ардуине? Нюню

вроде многозадачность и параллельные процессы - это не одно и тоже.

Arhat109
Offline
Зарегистрирован: 26.05.2015

Дополню.

Собственно эта ссылка - должно быть ПЕРВОЕ, с чем надо знакомится новичку, взявшему в руки Ардуино. И пример с моргалкой светодиодом надо вложить в это описание, переработав его. И delay() -- "всего лишь" одно из состояний автомата-моргалки.

 

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Клапауций 999 пишет:

JollyBiber пишет:

А у Вас видимо от старческого маразма и глубокого понимания темы твердая увернность в возможности параллельных процессов на ардуине? Нюню

вроде многозадачность и параллельные процессы - это не одно и тоже.

Он себя пяткой в грудь колотил что ему на ардуине распараллелить процессы (причем не "псевдо", а по настоящему!) раз чихнуть. Он типа это постоянно делает но никому не показывает - так как тайна сия великая.

Arhat109
Offline
Зарегистрирован: 26.05.2015

Нет там никакой ни многозадачности ни параллелизму в классическом понимании этих терминов... я ж не зря написал "от непонимания" ... читайте пример по ссылке. Там всё разжевано, специально для вас. :)

Arhat109
Offline
Зарегистрирован: 26.05.2015

Да, и не надо приписывать мне свои фантазии от безграмостности... а ежели пишете, то приводите цитаты. :)

Клапауций 999
Offline
Зарегистрирован: 06.06.2015

Arhat109 пишет:

Дополню.

Собственно эта ссылка - должно быть ПЕРВОЕ, с чем надо знакомится новичку, взявшему в руки Ардуино. И пример с моргалкой светодиодом надо вложить в это описание, переработав его. И delay() -- "всего лишь" одно из состояний автомата-моргалки.

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

Клапауций 999
Offline
Зарегистрирован: 06.06.2015

Arhat109 пишет:

Да, и не надо приписывать мне свои фантазии от безграмостности... а ежели пишете, то приводите цитаты. :)

приведи цитаты нашей безграмотности - или звездун.

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

Arhat109 пишет:

Да, и не надо приписывать мне свои фантазии от безграмостности... а ежели пишете, то приводите цитаты. :)

пока кроме ваших сексуальных фантазий, в большинстве случаев далеких от реальности, мы ничего не слышали и не видели...

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

JollyBiber
JollyBiber аватар
Offline
Зарегистрирован: 08.05.2012

Да где уж нам до Вашего лексикона опускаться. Вам напомнить? Да не вопрос! Все ниже перечисленной с ОДНОЙ(!) ветки.

Цытата от Архата, совсем без плагиата:

"А вот так - это просто тупо позорить Русскую Школу Программистов"

"На иных ресурсах, таких, как ваш бот-троль "пухлявый", банят навсегда на третьем посту, а вы поставили его троллить, типа "круть". Чмошники."

"а после ТАКОГО приема - усретесь!"

"В противном случае, начну заносить ваш форум в известные мне блек-листы. Не надо засорять мне почту."

"он вас "порвет как Тузик грелку""

"Ткак я и попросил ОТПИСАТЬ меня от вашего флуда и говнофорума"

 

Arhat109
Offline
Зарегистрирован: 26.05.2015

Так вот, прямо тут в этой теме - весь флуд ОТ НЕПОНИМАНИЯ вопросу. :)

пишите исчё, с вами и правда весело. :)

Arhat109
Offline
Зарегистрирован: 26.05.2015

Ну и где тут про "многозадачность", звездун? :)