Хитрое реле задержки

johnnie
Offline
Зарегистрирован: 06.01.2019

Задача:

Есть датчик потока воды ГВС в котле. Он 3-х проводной: +5В,Общий, Выход.

Когда потока воды нет, на выходе либо 0В, либо +5В. Когда есть - импульсы, частота которых пропорциональна  потоку.

Надо:

В разрыв сигнального провода поставить Arduino Nano, которая будет вырезать первые N секунд каждой серии импульсов.

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Это раздел для проектов, а не для задач.

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

Это раздел для готовых проектов.

Вам надо перепостить вот сюда - это специальный раздел для заказа работы за деньги.

-NMi-
Offline
Зарегистрирован: 20.08.2018

Он хотел нахалтай, Скифу нежно маякнуть)))

johnnie
Offline
Зарегистрирован: 06.01.2019

Я прошу помочь советом как это алгоритмически правильно реализовать,  а программу я сам напишу.

Пока для повтора входа на выход следующий алгоритм:

init:

1. TRANSMIT == 0

2. Устанавливаем прерывание по фронту на входе.

Обработчик прерывания:

if TRANSMIT {OUT == IN}

Осталось выполнить условие и установить TRANSMIT в 1. Сейчас подумаю как это сделать.

 
johnnie
Offline
Зарегистрирован: 06.01.2019

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

Это раздел для готовых проектов.

Вам надо перепостить...

Я думаю мне сюда

Как перепостить?

johnnie
Offline
Зарегистрирован: 06.01.2019

Устанавливаем условие прекращения серии импульсов на входе когда TRANSMIT становится равным 1:

1. Запускаем таймер по кругу на 1 секунду.

Обработка прерывания окончания счета от таймера :

1. Если аппаратный счетчик по входу = 0, то TRANSMIT == 0 и остановить таймер;

2.

2. Обнуляем аппаратный счетчик по входу

Осталось определиться когда TRANSMIT станет 1

johnnie
Offline
Зарегистрирован: 06.01.2019

Вот что получилось:

Начальная инициализация:

1. TRANSMIT = 0;    // Разрешение передачи
2. TransmitDelay = 0;    // Задержка передачи в секундах
3. Разрешить только прерывание по фронту на входе;
-----------------------------------------------------------------------------------

Обработчик прерывания по фронту на входе:

if TRANSMIT then OUT = IN
   else if TransmitDelay == 0
    then     1. Запретить прерывание по фронту на входе
        2. Обнулить аппаратный счетчик по входу
        3. Разрешить прерывание по окончанию счета таймера (переполнения?);
        4. Запустить таймер по кругу на 1 секунду.
-----------------------------------------------------------------------------------

Обработчик прерывания окончания счета от таймера:

1. Если аппаратный счетчик по входу == 0,
    то     TRANSMIT = 0
           TransmitDelay = 0
           запретить прерывания от таймера
            остановить таймер
        Разрешить прерывание по фронту на входе
    иначе     TransmitDelay++;

2. if TransmitDelay == N
    then     TRANSMIT = 1
        Разрешить прерывание по фронту на входе

3. Обнулить аппаратный счетчик по входу

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

johnnie пишет:

В разрыв сигнального провода поставить Arduino Nano, которая будет вырезать первые N секунд каждой серии импульсов.

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

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

johnnie пишет:

Я думаю мне сюда

Напрасно думаете. У Вас нет скетча и нет конкретных вопросов, потому Вам именно туда, куда я написал.

johnnie
Offline
Зарегистрирован: 06.01.2019

andriano пишет:

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

Вы правы. Я к этому сразу пришёл. Критерий окончания серии: В течении 1 секунды(например) не было изменений уровня на входе. Я это представил в вышеизложенном алгоритме.

johnnie
Offline
Зарегистрирован: 06.01.2019

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

У Вас нет скетча и нет конкретных вопросов

sadman41
Offline
Зарегистрирован: 19.10.2016

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

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

johnnie пишет:

Критерий окончания серии: В течении 1 секунды(например) не было изменений уровня на входе. Я это представил в вышеизложенном алгоритме.

Видите ли, алгоритм принято излагать на каком-либо понятном языке. У Вас, увы, это не так.

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

johnnie
Offline
Зарегистрирован: 06.01.2019

sadman41 пишет:

я прямо заинтригован программной реализацией пункта "Запустить таймер по кругу на 1 секунду".

Поэтому и прощу помощи в аппаратно-програмных возможностях Arduino

johnnie
Offline
Зарегистрирован: 06.01.2019

andriano пишет:

я вообще не вижу смысла в применении прерываний в Вашей задаче

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

johnnie
Offline
Зарегистрирован: 06.01.2019

Вот код для повтора входа на выход (без условий пока):

const int INPin = 2;     // номер вывода входа
const int OUTPin =  13;  // номер вывода выхода пока со светодиодом

volatile int INState = 0;         // переменная для чтения состояния входа

void setup()
{
  // настроить вывод OUT на выход:
  pinMode(OUTPin, OUTPUT);
  // настроить вывод IN на вход:
  pinMode(INPin, INPUT);
  // прикрепить прерывание к вектору ISR
  attachInterrupt(0, pin_ISR, CHANGE);
}

void loop()
{
  // Здесь будем спать
}

void pin_ISR()
{
  INState = digitalRead(INPin);
  digitalWrite(OUTPin, INState);
}
MaksVV
Offline
Зарегистрирован: 06.08.2015

объясните куда идёт этот сигнал от датчика и зачем вырезать часть импульсов. 

johnnie
Offline
Зарегистрирован: 06.01.2019

MaksVV пишет:

объясните куда идёт этот сигнал от датчика и зачем вырезать часть импульсов. 

Пожалуйста! Это датчик потока воды в двухконтурном котле. Сигнал от него идет на плату управления котла. Наличие импульсов с него переводит котёл в режим приготовления горячей воды. Вырезать N секунд из серии импульсов нужно, чтобы исключить срабатывание котла на кратковременные открытия крана горячей воды.

p.s. Котёл подключен последовательно с электрическим бойлером.

johnnie
Offline
Зарегистрирован: 06.01.2019

andriano пишет:

алгоритм принято излагать на каком-либо понятном языке. У Вас, увы, это не так.

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

Алгоритмы принято излагать в виде блок-схем. То что я написал - текстовое изложение блок-схемы, чтобы не рисовать её. Посмотрите, пожалуйста, код. Правильна ли основа программы?

johnnie
Offline
Зарегистрирован: 06.01.2019

sadman41 пишет:

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

Запускать таймер по кругу на 1 секунду так:

#include "timer-api.h"

void setup() {
    timer_init_ISR_1Hz(TIMER_DEFAULT);
}

void loop() {
    // здесь любой код
}

void timer_handle_interrupts(int timer) { 

    // здесь обработка прерывания

}

Для остановки таймера использовать вызов timer_stop_ISR, для повторного запуска — timer_init_ISR_1Hz(TIMER_DEFAULT), как и раньше.

-NMi-
Offline
Зарегистрирован: 20.08.2018

Возьми любой таймер и сделай его таймером с нужным тебе интервалом. Возьми другой таймер и сделай его СЧЁТЧИКОМ с нужным тебе количеством импульсов. Пока счётчик считает импульсы а таймер не переполнился - молчим. Как только счётчик ДОСЧИТАЛ нужное а таймер НЕ переполнился - вырубаем нафиг таймера и делаем проброс с входа на выход.  Как только импульсы прекратились - запускаем таймеры снова. Вуаля!

johnnie
Offline
Зарегистрирован: 06.01.2019

-NMi- пишет:

Возьми любой таймер и сделай его таймером с нужным тебе интервалом. Возьми другой таймер и сделай его СЧЁТЧИКОМ с нужным тебе количеством импульсов. Пока счётчик считает импульсы а таймер не переполнился - молчим. Как только счётчик ДОСЧИТАЛ нужное а таймер НЕ переполнился - вырубаем нафиг таймера и делаем проброс с входа на выход.  Как только импульсы прекратились - запускаем таймеры снова. Вуаля!

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

sadman41
Offline
Зарегистрирован: 19.10.2016

johnnie пишет:

sadman41 пишет:

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

Запускать таймер по кругу на 1 секунду так:

Адриано прав - не мудрили бы вы сразу прерывания/таймеры... Длительность импульса какова?

johnnie
Offline
Зарегистрирован: 06.01.2019

sadman41 пишет:

Адриано прав - не мудрили бы вы сразу прерывания/таймеры... Длительность импульса какова?

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

sadman41
Offline
Зарегистрирован: 19.10.2016

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

johnnie
Offline
Зарегистрирован: 06.01.2019

sadman41 пишет:

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

Так это было уже 11 лет назад. А Arduino я даже в руках еще не держал. Релюшка не наш метод. Подловить фронт мало, надо установить что имульсы не кончались, и не секунда, а N секунд.

Ваша заинтрегованность по таймеру прошла? Как Вам код?

Спрашиваю у Вас, потому что нет практики программирования Arduino, мне неизвестны её нюансы и аппаратные возможности, не писал для Atmela код на С++

sadman41
Offline
Зарегистрирован: 19.10.2016

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

nik182
Offline
Зарегистрирован: 04.05.2015

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

А алгоритм простой. Заводим два флага начало пачки импульсов и разрешение на выдачу. В лупе ждем когда изменится уровень на входе. при изменении уровня выставляем флаг начала пачки, запоминаем время и начинаем считать импульсы по перепаду уровня. Это надо для того, что бы понять что импульсы действительно идут, а не произошёл просто перекид уровня из небльшого колебания воды. Ждем время задержки и если импульсов больше какого то предела, типа 10, то выставляем флаг разрешения выдачи и просто передаем входной сигнал на выход. Иначе сбрасываем флаг. На каждой передаче запоминаем время и сравниваем с предыдущим. Если время между импульсами превысило уставку, то сбрасываем все флаги. Я б такое устройство на attiny25 делал. Прицепил прямо на датчик тремя проводками и выход на четвёртую ногу. 

johnnie
Offline
Зарегистрирован: 06.01.2019

sadman41 пишет:

только странные декларации.

Проект arduino-timer-api

johnnie
Offline
Зарегистрирован: 06.01.2019

nik182 пишет:

на спичках экономить в сон процессор посылать

Если процессору целый день нечего делать - пусть спит

nik182 пишет:

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

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

nik182 пишет:

запоминаем время и начинаем считать импульсы по перепаду уровня. Это надо для того, что бы понять что импульсы действительно идут, а не произошёл просто перекид уровня из небльшого колебания воды. Ждем время задержки и если импульсов больше какого то предела, типа 10, то выставляем флаг разрешения выдачи и просто передаем входной сигнал на выход. Иначе сбрасываем флаг. На каждой передаче запоминаем время и сравниваем с предыдущим. Если время между импульсами превысило уставку, то сбрасываем все флаги.

я ж так и делаю, только я не считаю импульсы, а проверяю не пропадали ли они больше, чем на секунду с момента их начала

nik182
Offline
Зарегистрирован: 04.05.2015

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

johnnie
Offline
Зарегистрирован: 06.01.2019

Пока мой алгоритм преобразован вот в такой код:

"#include "timer-api.h"

const int INPin = 2;            // номер вывода входа
const int OUTPin =  13;         // номер вывода выхода
const int N =  10;              // задержка передачи в секундах

volatile int TRANSMIT = 0;      // разрешение передачи
volatile int TransmitDelay = 0; // текущая задержка передачи в секундах
 

void setup()
{
  pinMode(OUTPin, OUTPUT);      // Настройка вывода OUT на выход
  pinMode(INPin, INPUT);        // Настройка вывода IN на вход
  attachInterrupt(0, pin_ISR, CHANGE); // Разрешить прерывание по фронту на входе
}

void loop()
{
  if (TRANSMIT == 0 && TransimtDelay == 0) // Если передача не разрешена И не выдерживается пауза,
  {                                      
       ?;                                // то лечь спать
  }
}

void pin_ISR()                  // обработка прервания по фронту на входе
{
  if (TRANSMIT == 1)            // Если передача разрешена,
  {
    digitalWrite(OUTPin, digitalRead(INPin)); // то передаём вход на выход
  }
  else                          // иначе
  {
      if (TransmitDelay == 0)   // Если серия импульсов только началась
    {                           // то
        detachInterrupt(0);     // Запретить прерывание по фронту на входе
        ?;                      // Обнулить аппаратный счетчик по входу
        timer_init_ISR_1Hz(TIMER_DEFAULT);    // Запустить таймер по кругу на 1 секунду
        
    }    
  }
}

void timer_handle_interrupts(int timer)    // обработка прерывания от таймера
{
  if (аппаратный счетчик по входу == 0)
  {
    TRANSMIT = 0;               // Запретить передачу
    TransmitDelay = 0;          // Сбросить задержку
    timer_stop_ISR;             // Остановить таймер
    attachInterrupt(0, pin_ISR, CHANGE); // Разрешить прерывание по фронту на входе
  }
  else                          // иначе
  {
    TransmitDelay++;            // Прошла ещё 1 секунда задержки
  }

  if (TransmitDelay == N)       // Если нужная задержка выдержана
  {                             // то
    TRANSMIT = 1;               // Разрешить передачу
    attachInterrupt(0, pin_ISR, CHANGE); // Разрешить прерывание по фронту на входе
  }

  ?;                            // Обнулить аппаратный счетчик по входу
}
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

johnnie пишет:

Алгоритмы принято излагать в виде блок-схем. 

Было. Лет 50-60 назад.

nik182
Offline
Зарегистрирован: 04.05.2015

Даже програмировать блоксхемами можно. Я в начале знакомства с AVR для attiny15 программу строил в http://cxem.net/software/algorithm_builder.php . Для тиньки 15 только ассемблер был доступен. У неё нет оперативной памяти и компиляторы си не поддерживали. 

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

Позвольте поитересоваться:

  1. Нахрена переменная  INState :
    1. Вообще нужна? Не проще ли написать digitalWrite(OUTPin, digitalRead(INPin))
    2. Объявлена волатильной? Вы собираетесь использовать её и в прерывании, и снаружи? А нет, так зачем?
    3. Объявлена глобальной, хотя используется ТОЛЬКО в одной функции?
  2. Нахрена такие, простите мой французский, хитрожопости, с таймером и что это даёт?
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

nik182 пишет:

Даже програмировать блоксхемами можно. 

Программировать можно чем угодно. Это ещё не повод тем же и алгоритмы излагать. Цель программы - быть выполненой машиной, а цель описания алгоритма - быть понятым человеком. Разные цели - разные средства.

nik182
Offline
Зарегистрирован: 04.05.2015

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

nik182 пишет:

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

Блок-схемами можно только изобразить процесс. Но когда на ПК процессов море , то уже это пачка независимых(слабо- и очень зависимых) блок-схем. И все тот же цифровой автомат лучше описывать другим способом. 

ПС: Удивительно, но знаки на письме у разных народов отличатся. Видно тупые иностанцы так и не доумались писать на кириллице. Ведь все ясно и понятно. Вот я же пишу сейчас, а вы читаете.

ПС2: И еще блоксхемы описывают БЛОКИРУЮЩИЕ алгоритмы. Что не рационально для использования мощних процессоров.

sadman41
Offline
Зарегистрирован: 19.10.2016

Для нашей ардуины любой процесс - блокирующий, так что ОК.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

sadman41 пишет:

Для нашей ардуины любой процесс - блокирующий, так что ОК.

То то все орут как заменить как заменить delay на millis или найти лишнее прерывание, что бы выйти из ямы которую вырыли.

sadman41
Offline
Зарегистрирован: 19.10.2016

delay ли, millis или обработчик прерывания - они всё едино блокирующие. Параллельно две операции не выполняются. 

И никто никому не рыл ям. Зачем ждать от пилы способности рубить?

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

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Похоже вы не понимаете что такое блокирующие, а что нет. Но жевать и просвещать у меня желания нет. Все равно оффтоп.

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

ТС, тебе нужны асинхронные таймеры?  Ни от чего не зависящие?

Их есть у меня. Спроси меня как. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Неужели автоматы пуха и тут отличились - сделали авр-ку мультиядерной? Cool story.

ВН
Offline
Зарегистрирован: 25.02.2016

johnnie пишет:

Задача:

Есть датчик потока воды ГВС в котле. Он 3-х проводной: +5В,Общий, Выход.

Когда потока воды нет, на выходе либо 0В, либо +5В. Когда есть - импульсы, частота которых пропорциональна  потоку.

Надо:

В разрыв сигнального провода поставить Arduino Nano, которая будет вырезать первые N секунд каждой серии импульсов.

не вполне понимаю логический смысл всего действа

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

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

 

 

johnnie
Offline
Зарегистрирован: 06.01.2019

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

Позвольте поитересоваться:

  1. Не проще ли написать digitalWrite(OUTPin, digitalRead(INPin))?
  2. Нахрена такие, простите мой французский, хитрожопости, с таймером и что это даёт?

I. Спасибо, исправил.

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

johnnie
Offline
Зарегистрирован: 06.01.2019

nik182 пишет:

...только ассемблер был доступен...

+

johnnie
Offline
Зарегистрирован: 06.01.2019

Pyotr пишет:

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

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

johnnie
Offline
Зарегистрирован: 06.01.2019

DetSimen пишет:

ТС, тебе нужны асинхронные таймеры?  Ни от чего не зависящие?

Их есть у меня. Спроси меня как. 

Нужны, спрашиваю.

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