Попытка одолеть delay()

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Всем привет! Столкнулся с типичной, как я понял проблемой для новичка - как обойтись без delay()?

Много есть в инете на эту тему, но в моём случае всё усложняет динамическая индикация, которой постоянно нужен ресурс МК.  Вопрос показался интересным, ведь решив его, можно , по аналогии решать другие подобные. Итак, на преобразование температуры датчиком DS18B20 уходит 750мс, пусть 800мс с запасом.

Как сделать, чтобы индикация при этом не прекращалась?

Проблему-то я решил, всё работает, но сильно пришлось усложнить код.

От этого сомнения, и вопросы

//======== попытка избавится от delay =============
//==== с сохранением динамической индикации ))) ==

void loop() {

  for (int i = 0; i < 8; i++) {

    digitalWrite(RAZR[i], HIGH); // выбор разряда

    PORTD = CIFRY[a[i]]; // вывод на индикатор цифры из таблицы CIFRY по адресу [a] в текущий разряд [i]
    if (i == 2)
      PORTD = PORTD | 0b10000000; // зажигаем точку

    delayMicroseconds(500);      // задержка для индикатора

    digitalWrite(RAZR[i], LOW); // гасим разряд для динамической индикации
  }
  switch (key) {                              // key это ключ для выполнения выбранной части программы (одной из трёх)
    case 0:                                   // ключ в положении 0 (индикацию теряем только на время работы шины и расчёты)
      if ((millis() - last_millis) >= 3200) { // частота измерений температуры  3200мс(задержка) + 800мс(конвертация) = 4сек
        last_millis = millis();                            // + 10мс обмен по шине и преобразование ( очень примерно )
        w = 0;                                             // при w = 0 передаём первые два байта команд датчику
        start();                                           //
        peredacha();
        key = 1;                                           // изменяем значение ключа
      }
      break;

    case 1:                                                // ключ в положении 1
      if ((millis() - last2_millis) >= 800) {              // ждём датчик
        last2_millis = millis();
        key = 2;                                           // изменяем значение ключа
      }
      break;
    case 2:                                                // ключ в положении 2
      w = 2;                                               // при w = 2 (смещение цикла) передаём вторые два байта команд
      start();
      peredacha();
      chtenie();                                           // читаем значение темп-ры
      crc_8();                                             // проверяем контр.сумму
      schet();                                             // преобразуем в значения десятичных разрядов
      key = 0;                                             // первоначальное значение ключа
      break;
  }

}

: это нормальное решение, или можно сделать лучше?

Или сойдёт для начала?

Прошу конструктивной критики и направления в нужную сторону...

Это первоначальный вариант, как видим, значительно проще

void loop() {

  for (int i = 0; i < 8; i++) {

    digitalWrite(RAZR[i], HIGH); // выбор разряда

    PORTD = CIFRY[a[i]]; // вывод на индикатор цифры из таблицы CIFRY по адресу [a] в текущий разряд [i]
    if (i == 2)
      PORTD = PORTD | 0b10000000; // зажигаем точку

    delayMicroseconds(500);


    digitalWrite(RAZR[i], LOW); // гасим разряд для динамической индикации
  }

  if ((millis() - last_millis) >= 4000) { // частота измерений температуры 4сек
    last_millis = millis();

    start();

    peredacha();

    chtenie();
    schet();
    crc_8();

  }
}

Задержка была в функции peredacha() просто delay(800)

Там же был и второй вызов функции start() после задержки

rkit
Offline
Зарегистрирован: 23.11.2016

Логику работы разных вещей нужно разделять. У тебя должен быть класс-таймер. Класс для работы с дисплеем, к нему прикреплен экземпляр таймера. Класс для работы с датчиком, к нему тоже свой отдельный таймер.

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

А можно еще тот кусок глянуть, который датчик читает?

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

rkit пишет:

Логику работы разных вещей нужно разделять. У тебя должен быть класс-таймер. Класс для работы с дисплеем, к нему прикреплен экземпляр таймера. Класс для работы с датчиком, к нему тоже свой отдельный таймер.

Спасибо, пока не понятные для меня слова, но буду учиться.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Rumata пишет:

А можно еще тот кусок глянуть, который датчик читает?

У меня отдельно передача и чтение. Всё пока сырое, не упакованное в циклы, но работает

//======= функция передачи команд датчику DS18B20 ================
//=========== попытка сохранить дин. индикацию на время измерения 800мс( запас 50мс )

void peredacha() {
  for (int i = w; i < (w + 2); i++) {                // передача 4-х команд,  1 команда - 1 байт
    // с помощью выбора в loop() значения w = 0 или w = 2
    // выбираем команды в массиве  temp_tx

    if (temp_tx[i] & 0x01) { //0                    // пока эта часть сырая, потом упакую в цикл
      peredacha_1bit();                             // проверяем , начиная с младшего, биты в байте команды
    }
    else {                                          // и устанавливаем соответствующее значение на шину
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00000010) { //1
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00000100) { //2
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00001000) { //3
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00010000) { //4
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00100000) { //5
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }


    if (temp_tx[i] &  0b01000000) { //6
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b10000000 ) { //7
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

  }
}

 

Это чтение из датчика

void chtenie() {

  for (int i = 0; i < 9; i++) {      // читаем 9 байт из памяти датчика
    chtenie_byte();
    temp_rx[i] = temp_0;
  }
  // temp_rx[3] =  temp_rx[3] + 1; //  раскоментировать для проверки crc
  low_byte = temp_rx[0];
  high_byte = temp_rx[1];

 

b707
Offline
Зарегистрирован: 26.05.2017

"закат Солнца вручную"

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

b707 пишет:

"закат Солнца вручную"

Точно! )))

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

Неблокирующий опрос ds18b20. Извиняюсь что без 100500 цифр "после запятой")) Лишнее сами уберете


#include <OneWire.h>         

const uint32_t msRepTime {10000};   // DS18b20 будем опрашивать каждые 10 секунд (по факту каждые 11)
const uint8_t ds1Pin{7};            // DS18b20 будем подключать к пину D7
uint32_t msTemp {msRepTime};        // Объявляем счетчик для опроса DS18b20 и инициализируем его значением для моментального начала процедуры
uint8_t ds1Qty {0};                 // Количество датчиков DS18b20 на пине (не более 3-х). Если больше одного, значения будут усредняться 
int8_t  ds1Temp {0};                // Собственно, значение температуры по Цельсию от DS18b20
uint8_t ds1DS[3][8];                // Адреса положу пока здесь. Если кому не лень, их нужно убрать из глобальной ОВ, как и количество датчиков


void setup() {
  Serial.begin(115200);             // Скорость должна соответствовать настройкам монитора порта 
  searchSensors();                  // Запускаем первоначальный поиск датчиков DS18b20 на пине
}


void loop() {
  if (millis() - msTemp > msRepTime)  updateTemp();       // Опрашиваем температуру DS18b20 с частотой msRepTime
}



void updateTemp(){                       // Основная процедура обновления температурных данных со всех датчиков
  static uint8_t stage {0};
//  Первый этап. Отправка запросов на конвертацию 
  if (stage == 0){
    if (ds1Qty) requestSensor(ds1Pin);
    stage++; 
    msTemp = millis() - msRepTime + 750;    // 0.75 секунды требуется датчику для осуществления конвертации на максимальном разрешении
    return;
  }
// Второй этап. Чтение показаний  
  if (stage == 1){  
    if (ds1Qty) readSensor(&ds1Temp, ds1Pin, ds1DS, ds1Qty);
    msTemp = millis(); 
    stage = 0; 
    return;
  }
}


void readSensor(int8_t* t, uint8_t pin, void* buf, uint8_t qt){       // Чтение температуры с датчика ds18b20
  OneWire ds(pin);
  uint8_t addr[8];
  uint8_t data[9];
  float temp[3];
  uint8_t qty {0};
  for (uint8_t c {0}; c < qt; c++){
    for(uint8_t i {0}; i<8 ;i++) addr[i] = *((uint8_t*)buf+c*8+i);
    ds.reset(); ds.select(addr); ds.write(0xBE); 
    for (uint8_t d {0}; d<9; d++) data[d] = ds.read();    
    int16_t raw = (data[1] << 8) | data[0];
    raw = raw & ~1;
    temp[qty++] = raw / 16.0;  
  }
  float tmp {0};
  for (uint8_t i {0}; i<qty; i++) tmp+= temp[i];
  *t = round(tmp/qty);
  Serial.print("Температура пин "); Serial.print(pin); Serial.print(" : "); Serial.println(*t);
}

void requestSensor(uint8_t pin){          // Отправка запроса на конвертацию ds18b20
  OneWire ds(pin);
  ds.reset();
  ds.skip();
  ds.write(0x44,0);
}

void searchSensors(){                          // Поиск датчиков на всех линиях
  ds1Qty =   src(ds1DS, ds1Pin);
}

uint8_t src(void * adr, uint8_t pin){      // Вспомогательная функция для поиска на одной шине. Возвращает количество найденных датчиков
  if (pin == 0) return 0;
  OneWire ds(pin);
  uint8_t newAddr[8]{0};
  uint8_t count {0};
  ds.reset_search();
  delay(5);
  while (ds.search(newAddr) && count <3){
    if (ds.crc8(newAddr, 7) == newAddr[7]){
       for (uint8_t i{0}; i<8; i++) *((uint8_t*)adr + count * 8 + i) = newAddr[i];
       count++;
    }
  }
  return count;
}
Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Rumata пишет:

Неблокирующий опрос ds18b20.

Спасибо, будем посмотреть!

b707
Offline
Зарегистрирован: 26.05.2017

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

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

Цитата:
Вопрос показался интересным, ведь решив его, можно , по аналогии решать другие подобные.

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

b707 пишет:

он ведь не просто свою проблемку решает. он вопрос для общества разрабатывает:

Цитата:
Вопрос показался интересным, ведь решив его, можно , по аналогии решать другие подобные.

 

Да нет же, пытаюсь сам пока разобраться, мне пока не до общества, сам мало-чего понимаю)))

Но процесс "разбирания" интересен, жаль маловато времени на хобби остаётся

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Дим-мычъ пишет:

//======= функция передачи команд датчику DS18B20 ================

//=========== попытка сохранить дин. индикацию на время измерения 800мс( запас 50мс )

void peredacha() {
  for (int i = w; i < (w + 2); i++) {                // передача 4-х команд,  1 команда - 1 байт
    // с помощью выбора в loop() значения w = 0 или w = 2
    // выбираем команды в массиве  temp_tx

    if (temp_tx[i] & 0x01) { //0                    // пока эта часть сырая, потом упакую в цикл
      peredacha_1bit();                             // проверяем , начиная с младшего, биты в байте команды
    }
    else {                                          // и устанавливаем соответствующее значение на шину
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00000010) { //1
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00000100) { //2
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00001000) { //3
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00010000) { //4
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b00100000) { //5
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }


    if (temp_tx[i] &  0b01000000) { //6
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

    if (temp_tx[i] & 0b10000000 ) { //7
      peredacha_1bit();
    }
    else {
      peredacha_0bit();
    }

  }
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Только у меня ащющение, что ТС вырезан из цельного куска стоеросового дерева?  

void peredacha() {
  for (int i = w; i < (w + 2); i++) { // передача 4-х команд,  1 команда - 1 байт
    // с помощью выбора в loop() значения w = 0 или w = 2
    // выбираем команды в массиве  temp_tx
 
  for(uint8_t mask=0x01; mask>0; mask<<=1) {

    if (temp_tx[i] & mask) 
      peredacha_1bit();      
    else                             
      peredacha_0bit();
    }
   
   } 
}

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Rumata , ещё раз спасибо, посмотрел, упростил, даже ещё проще , чем в примере получилось.

Вообще без флагов и ключей, только два счётчика. Зато работает!

void loop() {

  for (int i = 0; i < 8; i++) {

    digitalWrite(RAZR[i], HIGH); // выбор разряда

    PORTD = CIFRY[a[i]]; // вывод на индикатор цифры из таблицы CIFRY по адресу [a] в текущий разряд [i]
    if (i == 2)
      PORTD = PORTD | 0b10000000; // зажигаем точку

    delayMicroseconds(500);      // задержка для индикатора

    digitalWrite(RAZR[i], LOW); // гасим разряд для динамической индикации
  }

  
  if ((millis() - last_millis) >= 3200){// частота измерений температуры  3200мс(задержка) + 800мс(конвертация) = 4сек
    last_millis = millis();               // + 10мс обмен по шине и преобразование ( очень примерно )
    w = 0;                                // при w = 0 передаём первые два байта команд датчику
    start();                              // сигнал RESET/PRESENT
    peredacha();                          // 

    if ((millis() - last2_millis) >= 800) {     // ждём датчик 800мс
      last2_millis = millis();
      w = 2;                                    // при w = 2 (смещение цикла) передаём вторые два байта команд
      start();
      peredacha();
      chtenie();                                           // читаем значение темп-ры
      crc_8();                                             // проверяем контр.сумму
      schet();                                             // преобразуем в значения десятичных разрядов
      
    }

  }

 

Rumata
Rumata аватар
Offline
Зарегистрирован: 29.03.2019

b707 пишет:

 команды датчику целыми байтами, а не побитно, как уважаемый автор. А вдруг библиотека не каждый бит верно обрабатывает?? 

Я для целей надежности передачи после каждой команды использую макрос "КАК СЛЫШНО? ПРИЁМ!", просто вырезал из кода перед публикацией. Это мое секретное ноу-хау ))

b707
Offline
Зарегистрирован: 26.05.2017

Дим-мычъ пишет:

упростил, даже ещё проще , чем в примере получилось.

Вообще без флагов и ключей, только два счётчика. Зато работает!

Как-то странно упростил... один счетчик в этом коде явно лишний - он вообще ничего не делает

 

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

DetSimen пишет:

Только у меня ащющение, что ТС вырезан из цельного куска стоеросового дерева?  

Не! 

Из цельного дуба вырезана вот эта лестница. Это ж скока, суки, древесины попортили!

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

b707 пишет:

Как-то странно упростил... один счетчик в этом коде явно лишний - он вообще ничего не делает

 

Спасибо за замечание! И правда, посмотрел ещё раз на свежую голову,  и тоже это заметил.

Но больше всего смутило, что код работает!  И долго бы я бился головой об стену, если бы не выяснил, что в

Proteus не требуется время для преобразования датчиком. Закоментировал delay() в старом  варианте скетча, и всё равно, всё работает!

Так что приношу свои извинения. Вот последний вариант

void loop() {

  for (int i = 0; i < 8; i++) {

    digitalWrite(RAZR[i], HIGH); // выбор разряда

    PORTD = CIFRY[a[i]]; // вывод на индикатор цифры из таблицы CIFRY
    if (i == 2)          // по адресу [a] в текущий разряд [i]
      PORTD = PORTD | 0b10000000; // зажигаем точку

    delayMicroseconds(500);      // задержка для индикатора

    digitalWrite(RAZR[i], LOW); // гасим разряд для динамической индикации
  }

  if (((millis() - last_millis) >= 3200) && !key) { //пока не пройдёт 3200мс
    last_millis = millis();     // обнуляем таймер
    //  выполняется  только индикация
    // по прохождении 3200мс выполняем 1-ую часть работы с датчиком
    w = 0;          // при w = 0 передаём первые два байта команд датчику
    start();                      // сигнал RESET/PRESENT
    peredacha();                  // передача команд
    key = true;                   // запрещаем выполнение 1-ой части
  }
    if (((millis() - last2_millis) >= 800) && key) { // ждём датчик 800мс
      last2_millis = millis();   // выполняем 2-ю часть работы с датчиком
      w = 2;  // при w = 2 (смещение цикла) передаём вторые два байта команд
      start();                    // сигнал RESET/PRESENT
      peredacha();                // передача 2-ой части команд
      chtenie();                  // читаем значение темп-ры
      crc_8();                    // проверяем контр.сумму
      schet();                    // преобразуем в значения десятичных разрядов  
      key = false;                // сброс флага
    }
  }

 

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

Осмелюсь предложить свой вариант избавления от делеев:

int i=0;
int synchr=0;
unsigned long time_r;
void setup() {
    
}

void loop() {
  if(micros()-time_r>=500)
  {time_r=micros();
    i++;
    if(i>7)
  {
  i=0;
synchr++;// 4 ms
  }
  //------------> динамическая идикация с параметром i
  }
  switch(synchr)
  case 800// 800x4=3 200 ms 
  //------------>запрос датчика
  break;
  case 1000//1000x4=4 000 ms
  synchr=0;
  // ------------>обработка ответа датчика
  break;
  
    
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Осмелюсь предложить свой вариант избавления от делеев:

https://github.com/DetSimen/Arduino_TimerList

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Спасибо за помощь!  Разберусь, испытаю и обязательно отпишусь, когда позволит время.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

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

В общем всё работает отлично ,(проверяю в Proteus), но смущают данные датчика

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

Для сравнения выкладываю работу датчика в последнем варианте #17( это то, как я понял код , что дал Rumata)

По объёму, Ваш код ,вместе со всем скетчем, занимает 2314байт памяти устройств(7%) и 99байт(4%)динамической памяти

А предыдущий 2404(7%) и 100(4%) соответственно

int k = 0; 
int synchr=0;             //объявил переменные
unsigned long time_r = 0;//как глобальные


//---------------------


void setup() {

 

 

void loop() {
   if(micros()-time_r>=500)
  {time_r=micros();
   digitalWrite(RAZR[k], LOW); // гасим разряд для динамической индикации 

    k++;
    if(k>7)
  {
  k=0;
synchr++;// 4 ms
  }
  //------------> динамическая идикация с параметром i


    digitalWrite(RAZR[k], HIGH); // выбор разряда

    PORTD = CIFRY[a[k]]; // вывод на индикатор цифры из таблицы CIFRY
    if (k == 2)          // по адресу [a] в текущий разряд [i]
      PORTD = PORTD | 0b10000000; // зажигаем точку
  }
  switch (synchr) {
    case 800:// 800x4=3 200 ms         
      //------------>запрос датчика   
      start();                  
      w = 0;                    
      peredacha();
      break;
    case 1000://1000x4=4 000 ms 
      synchr = 0;               
      // ------------>обработка ответа датчика
      start();
      w = 2;
      peredacha();
      chtenie();
      crc_8();
      schet();
      break;
  }

}

Так, что надо будет с этим ещё позаниматься, возможно я где-то накосячил...

P.S. Вариант от DetSimena пока только глянул, там мне много с чем разбираться ещё придётся,

не все сразу понятно. Позже отпишусь.

 

 

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

Рад помочь

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

В общем понял, почему датчик опрашивается по 8раз. Так и написано в коде. Переменная synchr изменится с 800 на 801 только после 8-ми проходов  через case 800:  и так же case 1000:  Теперь дело за малым - найти решение)))

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Добавил флаг, и всё за  чих - пыхало!

void loop() {
   if(micros()-time_r>=500)
  {time_r=micros();
  flg = false;
   digitalWrite(RAZR[k], LOW); // гасим разряд для динамической индикации 

    k++;
    if(k>7)
  {
  k=0;
synchr++;// 4 ms
 flg = true;
  }
  //------------> динамическая идикация с параметром i


    digitalWrite(RAZR[k], HIGH); // выбор разряда

    PORTD = CIFRY[a[k]]; // вывод на индикатор цифры из таблицы CIFRY
    if (k == 2)          // по адресу [a] в текущий разряд [i]
      PORTD = PORTD | 0b10000000; // зажигаем точку
  }
  switch (synchr) {
    case 800:// 800x4=3 200 ms         
      //------------>запрос датчика 
      if(flg){  
      start();                  
      w = 0;                    
      peredacha();
      break;
      }
    case 1000://1000x4=4 000 ms 
    if(flg){
      synchr = 0;               
      // ------------>обработка ответа датчика
      start();
      w = 2;
      peredacha();
      chtenie();
      crc_8();
      schet();
      break;
  }

}
}

Так что Proteus не проведёшь!)))

Получается, Alexey_Rem  я тоже внёс свои 5копеек(может меньше)  в Ваш код)))

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

Вместе и папу легче отметелить :)

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Вот, наконец я разобрался, насколько смог конечно, самые азы, в "будильнике" от DetSimena.

Спасибо за помощь! Насколько я понял, это что-то вроде планировщика задач в windows. И это уже получается С++, язык высокого

уровня? Я так далеко ещё не заходил, читаю пока Кернигана и Ритчи, и то, в самом начале. Остальные знания беру в интернете,  по ходу возникновения вопросов,там много есть про С. 

Всё написано понятно, и даже я смог спокойно запустить. Индикация заработала от 4мс, ниже не получалось, но и этого в принципе достаточно. Код занял(в целом) 3336байт (10%) памяти устройств и 123байта(6%) дин. памяти, что очень неплохо, учитывая, что

можно запустить еще 3-4-ре датчика (а может и больше).

void setup() {

  pinMode(RELE, OUTPUT);
  digitalWrite(RELE, LOW); // настройка пина для управления внешним устройством (пока как возможность)

  high();                   // настройка шины 1-wire
  for (int i = 0; i < 8; i++) {
    pinMode(DATASEG[i], OUTPUT);
  }
  for (int i = 0; i < 4; i++) {
    pinMode(RAZR[i], OUTPUT); // настройка выходов динамической индикации
  }
  IzmTimer = TimerList.Add(3200, tmrIzmTimer); // таймер 1-ой части
  // работы с датчиком
  KonvTimer = TimerList.Add(4000, tmrKonvTimer); //таймер 1-ой части

  IndTimer =  TimerList.Add(4, tmrIndTimer); //таймер дин. индикации

  delay(300); // задержка для нормального запуска датчика
}

void tmrIzmTimer() {
  w = 0;
  start();
  peredacha();
}

void tmrKonvTimer() {
  w = 2;
  start();
  peredacha();
  chtenie();
  crc_8();
  schet();
}

void tmrIndTimer() {

  for (int i = 0; i < 8; i++) {

    digitalWrite(RAZR[i], HIGH); // выбор разряда

    PORTD = CIFRY[a[i]]; // вывод на индикатор цифры из таблицы CIFRY
    if (i == 2)          // по адресу [a] в текущий разряд [i]
      PORTD = PORTD | 0b10000000; // зажигаем точку

    delayMicroseconds(500);      // задержка для индикатора

    digitalWrite(RAZR[i], LOW); // гасим разряд для динамической индикации
  }
}

void loop() {
}

Ещё раз спасибо DetSimen,  и всем ответившим в теме.

 

 

 

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну, нальёшь при случае. 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

DetSimen пишет:

Ну, нальёшь при случае. 

 Хорошо))))

b707
Offline
Зарегистрирован: 26.05.2017

Дим-мычъ пишет:

Код занял(в целом) 3336байт (10%) памяти устройств и 123байта(6%) дин. памяти, что очень неплохо, учитывая, что можно запустить еще 3-4-ре датчика (а может и больше).

Вы думаете -  если код опроса одного датчика занимает ХХХХ байт, то код опроса 4 датчиков займер 4 * ХХХХ байт? - большое заблуждение.

Не стоит рассуждать о размере кода в таком ключе

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

b707 пишет:

Вы думаете -  если код опроса одного датчика занимает ХХХХ байт, то код опроса 4 датчиков займер 4 * ХХХХ байт? - большое заблуждение.

Не стоит рассуждать о размере кода в таком ключе

 

Вы правы, конечно же это не так прямолинейно, я и не говорил этого. Но всё же, думаю, что возможности контроля и размер кода взаимосвязаны. Как, например , сравнить Windows  и  CP/M

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

И снова делей:(. Даже два

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Alexey_Rem пишет:

И снова делей:(. Даже два

Точно! Но первый делей не опасен, т.к. работает один раз.  А второго(в индикации) в этом варианте и не пробовал избегать, т.к. минимальный заявленный счётчик 1мс. Но теперь вижу, что всё равно индикация работает через 4мс. 

Так что , спасибо за подсказку, попробую убрать и его.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Вот убрал, работает уже на 2мс. Это наверно потому, что убрал delay500мкс.

Добавил 1-ну глобальную переменную k.

void setup() {

  pinMode(RELE, OUTPUT);
  digitalWrite(RELE, LOW); // настройка пина для управления внешним устройством (пока как возможность)

  high();                   // настройка шины 1-wire
  for (int i = 0; i < 8; i++) {
    pinMode(DATASEG[i], OUTPUT);
  }
  for (int i = 0; i < 4; i++) {
    pinMode(RAZR[i], OUTPUT); // настройка выходов динамической индикации
  }
  IzmTimer = TimerList.Add(3200, tmrIzmTimer); // таймер 1-ой части
  // работы с датчиком
  KonvTimer = TimerList.Add(4000, tmrKonvTimer); //таймер 1-ой части

  IndTimer =  TimerList.Add(2, tmrIndTimer); //таймер дин. индикации

  delay(300); // задержка для нормального запуска датчика
}

void tmrIzmTimer() {
  w = 0;
  start();
  peredacha();
}

void tmrKonvTimer() {
  w = 2;
  start();
  peredacha();
  chtenie();
  crc_8();
  schet();
}

void tmrIndTimer() {
  digitalWrite(RAZR[k], LOW); // гасим разряд для динамической индикации
  k++;
  if (k > 7) {
    k = 0;
  }
  digitalWrite(RAZR[k], HIGH); // выбор разряда

  PORTD = CIFRY[a[k]]; // вывод на индикатор цифры из таблицы CIFRY
  if (k == 2)          // по адресу [a] в текущий разряд [i]
    PORTD = PORTD | 0b10000000; // зажигаем точку
}


void loop() {
}

Первый delay() как-бы и не вижу смысла убирать...

Alexey_Rem
Offline
Зарегистрирован: 09.09.2019

Может я туплю, но в сетапе у вас назначается 4 пина на разряды, а tmrIndTimer() считает их 8?

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Alexey_Rem пишет:

Может я туплю, но в сетапе у вас назначается 4 пина на разряды, а tmrIndTimer() считает их 8?

Точно, протупил здесь! Но всё работает, потому что в шапке всё правильно назначено. Просто сетап взял из старой версии)))

Спасибо за замечание

// программа для чтения данных из датчика ds18b20 с максимальным разрешением (12бит) и выводе на
//             8-ми разрядный 7-сегментный индикатор с общим катодом
//             и инвертирующим буфером (транзистором)
// Частота процессора 8 Мгц
#include "TimerList.h"
extern TTimerList TimerList;
THandle IzmTimer;  // таймер частоты измерений
THandle KonvTimer; // таймер ожидания преобразования датчика
THandle IndTimer;       //
const int DATASEG[] = {0, 1, 2, 3, 4, 5, 6, 7}; // пины для данных на 7 сегментов и точку
const int RAZR[] = {A0, A1, A2,  13, 12, 11, 9, A3}; //   пины для разряда индикатора
const int WIRE = 8; //  пин шины 1-wire
const int RELE = 13; // управляющий выход на реле ( предусмотрен, но пока не задействован )))
const int CIFRY[] = {
  0b00111111,//0

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

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

(к тому же я там в соавторах))).

Т. к. датчиков добавлять больше не планировал. Другие варианты интересны на будущее.

Дальше по плану доделать шину и ещё думаю попробовать меню и eeprom сделать

Пока использовать сторонние библиотеки избегаю, они для меня пока как кот в мешке, смутно представляю ещё себе их работу.

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

Ещё раз всем спсб.

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

А где желогика.

просто другая логика!
Сравниваем показания таймера миллис с последним запомненным показанием онаго для СОБЫТИЯ/процесса (при этом можно добавлять дополнительные условия) и заданными в предыдущий раз , когда те звезды сошлись, интервалом и условиями. И вот тогда наступит новая реинкарнация типоПроцесса, в которой можно сделать всеЧто необходимо и задать условия( интервал, доп триггеры) для следующей реинкарнации. 
и так для каждого процесса по-отдельности.
нужно только помнить, что это неНастоящщая мультизадачность, пока происходит каждая реинкарнация, остальные ждут ее завершения. И тайминги будуть съезжать. Я использую это для процессов типа померять температуру от  18b20 : В сетапе запустили преобразование, выставили переменную сравнения миллис на 3 минуты. Через примерно три минуты провалились в процесс, считали температуру, которая уже точно созрела, чтонить с этой температурой посчитали, выставили какиенить переменные для других проуессов, запустили новое преобразование, выставили новый интервал, через который надо опросить датчик(и) , и все, вернулись в лууп. А там другие, похожие процессы, прсыпаются периодически, смотрят свои переменные, что то делают и засыпают.

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

вот и сказочке конец, дочитал кто - молодец :)

ухты, публикация изменилась в кои то веки чтотто новое:)

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

inspiritus пишет:

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

Ну это уже следующая ступень для меня. Как говорится : бери ношу по себе, чтоб не падать при ходьбе)))

Гриша
Offline
Зарегистрирован: 27.04.2014

Дим-мычъ пишет:

inspiritus пишет:

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

Ну это уже следующая ступень для меня. Как говорится : бери ношу по себе, чтоб не падать при ходьбе)))

это называется - развиваем свою логику (логическое мышление) и вникаем в причинно-следственные связи.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Гриша пишет:

это называется - развиваем свою логику (логическое мышление) и вникаем в причинно-следственные связи.

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

Pyotr
Offline
Зарегистрирован: 12.03.2014

inspiritus пишет:

 Я использую это для процессов типа померять температуру от  18b20 : В сетапе запустили преобразование, выставили переменную сравнения миллис на 3 минуты. Через примерно три минуты провалились в процесс, считали температуру, которая уже точно созрела, ...

За 3 минуты она и "протухнуть" может)))