#1 2017-07-16 22:03:36

navernjaka
Участник
Зарегистрирован: 2017-07-16
Сообщений: 1

Помогите новичку понять логику выполнения параллельных процессов

Всем привет. Я новичок, поэтому прошу не сильно пинать.
Решил сделать часы на 6 газоразрядных индикаторах и ардуино. Микросхема часов DS1307. При написании кода столкнулся со следующей проблемой. Если ардуина работает только с часами, то часы выдают нужную информацию без проблем. Цифры выводятся динамически, с помощью таймера MsTimer2.h тоже  без проблем. Но  одновременно и опрос часов раз в 1 секунду и вывод цифр не работает корректно. Проявляется проблема в том, что часть сигналов от часов  приходят корректно, а часть нет. Пробовал различные варианты: в Loop делал опрос часов. Данные не всегда приходили корректные. Как я понимаю в момент общения с часами срабатывало прерывание по таймеру и данные не обрабатывались, пока выполнялось прерывание. Потом сделал опрос часов в самом прерывании, данные тоже не всегда приходят корректные.
Подскажите пожалуйста ответ на следующие вопросы:
1) Как правильно должна быть реализована логика работы микроконтроллера, который опрашивает различные датчики по различным шинам данных (SPI,I2C.1-Wire и т.д.) и при этом делает динамический вывод данных на дисплей с частотой например 100Гц каждого сегмента. То есть как обеспечить качественный опрос датчиков и одновременный вывод данных на индикаторы по прерыванию? Меня интересует именно последовательность выполнения кусков кода и в каких частях программы (Loop, прерывание) они должны быть реализованы. Скетч не прикладываю, потому-что пока необходимо понять саму логику и последовательность опроса датчиков.

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

3) Как определить величину времени, необходимого на вывод информации в СОМ порт. То есть например есть строка  Serial.println(unitsecond);  СОМ порт работает на скорости 9600. Сколько времени потратит микроконтроллер на вывод int-ой переменной unitsecond? Как определить это время?

#2 2017-07-29 08:04:15

Green
Участник
Зарегистрирован: 2015-11-08
Сообщений: 522

Re: Помогите новичку понять логику выполнения параллельных процессов

Вариантов всегда несколько. Один из.
Формируете системный тик. Не менее частоты динамической индикации.
По тику формируете временные интервалы для работы с датчиками.
Важно (для индикации!) что бы главный цикл не превышал время системного тика.

Редактировался Green (2017-07-29 08:05:21)

#3 2017-07-29 08:23:47

vvr
Участник
Зарегистрирован: 2015-04-12
Сообщений: 493

Re: Помогите новичку понять логику выполнения параллельных процессов

а зачем MsTimer2 для опроса часов ?
и без него всё прекрасно работает

#4 2017-07-29 18:22:44

qwone
Участник
Зарегистрирован: 2016-07-25
Сообщений: 128

Re: Помогите новичку понять логику выполнения параллельных процессов

Что бы мне не писать долго, то прочтите это.http://rsdn.org/article/baseserv/RUThreadingMethodology.xml

#5 2017-07-29 18:33:59

lkj
Участник
Зарегистрирован: 2016-02-03
Сообщений: 87

Re: Помогите новичку понять логику выполнения параллельных процессов

Микропроцессор - не мощный процессор для которых написана та статья.

#6 2017-07-29 19:11:22

qwone
Участник
Зарегистрирован: 2016-07-25
Сообщений: 128

Re: Помогите новичку понять логику выполнения параллельных процессов

lkj пишет:

Микропроцессор - не мощный процессор для которых написана та статья.

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

#7 2017-07-29 19:26:26

lkj
Участник
Зарегистрирован: 2016-02-03
Сообщений: 87

Re: Помогите новичку понять логику выполнения параллельных процессов

qwone пишет:
lkj пишет:

Микропроцессор - не мощный процессор для которых написана та статья.

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

Автоматическое распараллеливание (функция предварительного анализа)
Компилятор Intel C++ 7.1 включает функцию автоматического распараллеливания циклов. Эта функция производит поиск циклов, которые можно безопасно выполнять параллельно, и автоматически генерирует для них многопоточный код. Автоматическое распараллеливание освобождает разработчика от необходимости вникать в детали разбиения циклов, совместного использования данных, планирования потоков и синхронизации.

Хотя бы полистайте документацию на Atmega328

#8 2017-07-29 20:46:28

Green
Участник
Зарегистрирован: 2015-11-08
Сообщений: 522

Re: Помогите новичку понять логику выполнения параллельных процессов

Бедный navernjaka. Называется, задал первый вопрос.)) Молчит, даже слова сказать не может... Хотя да, есть такой метод обучения плаванию - сразу на глубину. А там, если выплывет - молодец, не выплывет - значит не пловец...

Редактировался Green (2017-07-29 20:50:51)

#9 2017-08-28 21:25:35

rf68
Гость

Re: Помогите новичку понять логику выполнения параллельных процессов

//Подключаем библиотеки для работы часов реального времени

#include <DS3231.h>
#include <Wire.h>

// выводы для дешифратора
  int out1 = A3;
  int out2 = A1;
  int out4 = A0;
  int out8 = A2;
// выводы для транзисторных ключей
  int key1= 4;
  int key2 = 6;
  int key3 = 7;
  int key4 = 8;

  int led1=11;// вывод светодиода
  int keyb=A6;// пин для клавиатуры


  int keynum=0; //номер нажатой кнопки
  int mode =0; //0 - отображение текущего времени 1- установка времени
  int currentdigit = 0; //0 - установка часов 1- установка минут
  bool blinkflag = 0; // флаг для мигания цифр при установке времени
  bool timeout=false; // таймаут после нажатия кнопки (для устраниния дребезга)
  unsigned long startTime; //для мигания светодиода
  unsigned long startTime2; // для опроса нажатых кнопок
  int sec; //переменная увеличивается каждые 500мс на единицу. Нужна для мигания секундных светодиодов, бывает в двух значениях 0 - светодиоды не горят, 1 - горят, если больше 1, то сбрысывается в 0
    //переменные для счетчиков
    int v = 0, p = 7, k = 0, lock = 0;
  // переменные, необходимые для работы ds3231
  DS3231 Clock;
  bool Century=false;
  bool h12;
  bool PM;
  byte ADay, AHour, AMinute, ASecond, ABits;
  bool ADy, A12h, Apm;

  //определяем глобальные переменные для различных параметров часов
  int second,minute,hour,date,month,year,temperature;


void setup() {
  // put your setup code here, to run once:
  // задаем частоту ШИМ на 9 выводе 30кГц
  TCCR1B=TCCR1B&0b11111000|0x01;
  analogWrite(9,130);

    // Start the I2C interface
  Wire.begin();
  // Start the serial interface
  Serial.begin(9600);
 
  //задаем режим работы выходов микроконтроллера
  pinMode(out1,OUTPUT);
  pinMode(out2,OUTPUT);
  pinMode(out4,OUTPUT);
  pinMode(out8,OUTPUT);

  pinMode(key1,OUTPUT);
  pinMode(key2,OUTPUT);
  pinMode(key3,OUTPUT);
  pinMode(key4,OUTPUT);

  pinMode(led1,OUTPUT);

  startTime = millis();
  startTime2=startTime;
  sec = 0;
  // считываем текущее вермя
  ReadDS3231();
}

void ReadDS3231()   //функция считывает в глобальные переменные minute и hour текущие значения
{
  minute=Clock.getMinute();
  hour=Clock.getHour(h12, PM);
}


void loop() {
  // put your main code here, to run repeatedly:
   
  k++;//счетчик для мигания цифрами
  v++;//счетчик для пебора всех цифр

  if (v >= 32760) {//делам прогон всех цифр во избежание "Отравление" катодов ламп
    scroll(25);
    v = 0;
  }
  int digits[3]; // массив для текущего значения времени на четыре цифры
  int keyval= analogRead(keyb); // считываем значение с клавиатуры
 
  unsigned long currentTime = millis(); //текущее время с момента запуска рограммы
   if (currentTime>=(startTime2+200)) // если прошло 200мс посмотрим какая кнопка была нажата
   {
      timeout=false;
     //проверим нажатие кнопок
      if (keynum==3) // кнопка переключения между режимами "время" и "настройка"
      {
        timeout=true; // запрещаем считывать нажатия кнопок
        if (mode==0) mode=1; // если отображалось время, переходим в режим настроек
        else
          if (mode==1) mode=0; //если был режим настроек, переключаемся на текущее время
      }
      if (keynum==2) // кнопка переключения между часами и минутами
      {
        timeout=true; // запрещаем считывать нажатия кнопок
        // currentdigit либо 0 - настройка часов, либо 1 - настройка минут
        currentdigit++;
        if (currentdigit==2) currentdigit=0;
      }
      if (keynum==1) // кнопка увеличения количества часов или минут(при настройке)
      {
        blinkflag=true; // прекращаем мигать цифрами
        startTime=millis();
        timeout=true;  // запрещаем считывать нажатия кнопок
        if (currentdigit==0) // если меняем часы
        {
          if (hour<=22) hour++;
          else
            hour=0;
          Clock.setHour(hour);
        }
        if (currentdigit==1) // если меняем минуты
        {
          if (minute<=58) minute++;
          else
            minute=0;
         Clock.setMinute(minute);//Set the minute
         Clock.setSecond(0);
        }
      }
      keynum=0; //сбрасываем нажатую кнопку
      startTime2=millis();
   }

  if (currentTime>=(startTime+500)) // если прошло 500мс
  {
    blinkflag=!blinkflag; // инвертируем флаг мигающей цифры
     
    if(sec<1) // светодиоды не горят
    {
      // зажечь светодиоды
      digitalWrite(led1,HIGH);
      Serial.println(blinkflag);
     
    }
    if(sec>=1) // светодиоды горят
    {
      // потушить светодиоды
      digitalWrite(led1,LOW);
    }
    startTime = currentTime;
    ReadDS3231();
    sec = (sec+1);
    if(sec>=2) sec=0;

  }
    digits[0] = hour/10;
    digits[1] = hour%10;
    digits[2] = minute/10;
    digits[3] = minute%10;

    show(digits); // вывести цифры на дисплей

  //проверяем нажатые кнопки
  if(!timeout) //если разрешено, считываем нажатую кнопку
  {
    /*keyval - значение функции analogread
     * если нажата первая кнопка, то принимает значение около 200
     * если нажата вторая кнопка то значение около 700
     * если третяя кнопка, то значение будет около 1000
     * эти значения зависят от выбранных резисторов в клавиатуре
    */
    if (keyval>150 && keyval<400) keynum=1;
    if (keyval>700 && keyval<900) keynum=2;
    if (keyval>960) keynum=3;
  }

}
//пебора всех цифр
void scroll(int pause) {
  for (int i = 0; i < 9; i++) {
    int a[] = {i, i, i, i, i, i};
    show(a);
    delay(pause);
  }}
void show(int a[])
{
    //выведем цифру a[0] на первый индикатор
  setNumber(a[0]);
  if (!(mode==1&&currentdigit==0&&blinkflag==false)) //если мы в режиме настройки и происходит настройка часов, то в первая цифра будет мигать
  {
    digitalWrite(key1,HIGH);
    delay(2);
    //потушим первый индикатор
    digitalWrite(key1,LOW);
    delay(1);
  }
 
  //цифра a[1] на второй индикатор
  setNumber(a[1]);
  if (!(mode==1&&currentdigit==0&&blinkflag==false))
  {
  digitalWrite(key2,HIGH);
  delay(2);
  //потушим второй индикатор
  digitalWrite(key2,LOW);
  delay(1);
  }

  //цифра a[2] на третий индикатор
  setNumber(a[2]);
  if (!(mode==1&&currentdigit==1&&blinkflag==false))
  {
  digitalWrite(key3,HIGH);
  delay(2);
  //потушим третий индикатор
  digitalWrite(key3,LOW);
  delay(1);
  }

  //выведем цифру a[3] на четвертый индикатор
  setNumber(a[3]);
  if (!(mode==1&&currentdigit==1&&blinkflag==false))
  {
  digitalWrite(key4,HIGH);
  delay(2);
  //потушим четвертый индикатор
  digitalWrite(key4,LOW);
  delay(1);
  }
}
// передача цифры на дешифратор
void setNumber(int num)
{
  switch (num)
  {
    case 0:
    digitalWrite (out1,LOW);
    digitalWrite (out2,LOW);
    digitalWrite (out4,LOW);
    digitalWrite (out8,LOW);
    break;
    case 1:
    digitalWrite (out1,HIGH);
    digitalWrite (out2,LOW);
    digitalWrite (out4,LOW);
    digitalWrite (out8,LOW);
    break;
    case 2:
    digitalWrite (out1,LOW);
    digitalWrite (out2,HIGH);
    digitalWrite (out4,LOW);
    digitalWrite (out8,LOW);
    break;
    case 3:
    digitalWrite (out1,HIGH);
    digitalWrite (out2,HIGH);
    digitalWrite (out4,LOW);
    digitalWrite (out8,LOW);
    break;
    case 4:
    digitalWrite (out1,LOW);
    digitalWrite (out2,LOW);
    digitalWrite (out4,HIGH);
    digitalWrite (out8,LOW);
    break;
    case 5:
    digitalWrite (out1,HIGH);
    digitalWrite (out2,LOW);
    digitalWrite (out4,HIGH);
    digitalWrite (out8,LOW);
    break;
    case 6:
    digitalWrite (out1,LOW);
    digitalWrite (out2,HIGH);
    digitalWrite (out4,HIGH);
    digitalWrite (out8,LOW);
    break;
    case 7:
    digitalWrite (out1,HIGH);
    digitalWrite (out2,HIGH);
    digitalWrite (out4,HIGH);
    digitalWrite (out8,LOW);
    break;
    case 8:
    digitalWrite (out1,LOW);
    digitalWrite (out2,LOW);
    digitalWrite (out4,LOW);
    digitalWrite (out8,HIGH);
    break;
    case 9:
    digitalWrite (out1,HIGH);
    digitalWrite (out2,LOW);
    digitalWrite (out4,LOW);
    digitalWrite (out8,HIGH);
    break;
  }
}
https://youtu.be/CXWt-Is_Eo8
схема надо?

Быстрое сообщение

Введите сообщение и нажмите Отправить

Подвал раздела