Одновременный счет импульсов с 4х входов и передача их по 485 в ПК

ALEX_099
Offline
Зарегистрирован: 17.04.2020

Привет всем. В ардуино новичок. Интересует вопрос. Горожу счетчик фотонов на ФЭУ. Сигнал с ФЭУ поступает на дискриминаторы настроенные на разный уровень сигнала. после каждого дискриминатора стоит триггер для более крутых фронтов. Уровень 5в.  Сигнал не периодический, частоту по длительности полки не померить. Надо именно посчитать количество импульсов за единицу времени (от0,5 мин до 1 мин) . С каждого входа. И измеренные значения передать в ПК. В пк уже будет программа обсчета этого.  Частота следования импульсов по осциллу ну где то килогерц, может два в зависимсти от их амплитуды (чем меньше амплитудла тем они чаще)

Возможно ли такое реализовать на ардуино микро?

WavGat
Offline
Зарегистрирован: 14.04.2020

Теоретически можно. Лучше использовать прерывания. А какова длительность самого импульса?

ALEX_099
Offline
Зарегистрирован: 17.04.2020

0,25-1 мкс по справочнику на NaI c теллуром. фэу не сильно его растянет.

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

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

Если Вы новичок, то для 4-х входов лучше взять не микру, а... Может мегу.

WavGat
Offline
Зарегистрирован: 14.04.2020

Порты PD0, PD1, PD2 и PD3 имеют собственные прерывания, но PD2 и PD3 используются так же и как UART.
Еще можно любой пин из порта PORTB задействовать, так как у него (у порта), есть собственное прерывание. Итого максимум 5 независимых счётчиков, но это если отказаться от UART-а. Я бы посоветовал сначала задействовать 3 прерывания PD0, PD1 и любой пин порта В, а когда программу отладишь, можно будет и 4 прерывание добавить. Ну а если есть Мега, то там конечно с прерываниями (в плане их количества) попроще будет.

SLKH
Offline
Зарегистрирован: 17.08.2015

ALEX_099 пишет:

Привет всем. В ардуино новичок. Интересует вопрос. Горожу счетчик фотонов на ФЭУ. Сигнал с ФЭУ поступает на дискриминаторы настроенные на разный уровень сигнала. после каждого дискриминатора стоит триггер для более крутых фронтов. Уровень 5в.  Сигнал не периодический, частоту по длительности полки не померить. Надо именно посчитать количество импульсов за единицу времени (от0,5 мин до 1 мин) . С каждого входа. И измеренные значения передать в ПК. В пк уже будет программа обсчета этого.  Частота следования импульсов по осциллу ну где то килогерц, может два в зависимсти от их амплитуды (чем меньше амплитудла тем они чаще)

Возможно ли такое реализовать на ардуино микро?

Уточни:

в зависимости от наличия и амплитуды сигнала от ФЭУ внешнее устройство формирует уровень лог. 1 на своих выходах, 0000-0001-0011-0111-1111 -  так?

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

ALEX_099 пишет:
на ардуино микро их не так много.
Это 32U4 что ли? Там их 13 штук - "8xPCINT + 5xINT sources". Неужели Вам нужно больше?

ALEX_099
Offline
Зарегистрирован: 17.04.2020

внешнее устройство дает 5 в импульс то  биш лог 1 при приходу импульса заданной амплитуды

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

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

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

 

ALEX_099
Offline
Зарегистрирован: 17.04.2020

8xPCINT + 5xINT sources да именно. с РС INT можно считать приход фронтов лог 1 с частотой пару килогерц?

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

ALEX_099 пишет:

РС INT можно считать приход фронтов лог 1 с частотой пару килогерц?

легко, причем если импульсы от всех 4х источников равноценны - то вообще можно  использовать только один PCint. без внешних прерываений

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

Только надо учитывать, что PCINT будет не только на RISING реагировать. Ну и вообще - это посложнее, чем просто на external Interrupt подвесится.

WavGat
Offline
Зарегистрирован: 14.04.2020

ТС же сказал, что они не равноценны и считать нужно каждый в отдельности.
Только вот он пока не ответил на вопрос SLKH, как именно приходят импульсы. Если, к примеру, сработал дискриминатор 2, то первый тоже даст сигнал? Будет 0011 или 0010 ?

ALEX_099
Offline
Зарегистрирован: 17.04.2020

WavGat пишет:

ТС же сказал, что они не равноценны и считать нужно каждый в отдельности.
Только вот он пока не ответил на вопрос SLKH, как именно приходят импульсы. Если, к примеру, сработал дискриминатор 2, то первый тоже даст сигнал? Будет 0011 или 0010 ?

допустим дискриминаторы настроены на урони 0,2, 0,4 , 0,8 и 1,2 вольта

0,2 вольта будет отдавать то что от 0,2 и выше

0,4 отсеит то что меньше 0,4 и так далее

импульс с величиной 1,3 вольта попадет везде.

поэтому считать нужно по 4м отдельным входам

ALEX_099
Offline
Зарегистрирован: 17.04.2020

sadman41 пишет:

Только надо учитывать, что PCINT будет не только на RISING реагировать. Ну и вообще - это посложнее, чем просто на external Interrupt подвесится.

то есть берем на этот вход сажаем счетчик, считаем переходы с низкого на высокое с высокое на низкое, делим на два и получаем искомое число ?

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

Зачем считать переходы в обе стороны и делить на 2, если можно считать переходы в одну сторону? Тут надо держать в голове, что общий обработчик будет дёргаться чаще, чем раздельные. И, если он будет "удачно" написан, то напропускаете импульсы за милую душу.

SLKH
Offline
Зарегистрирован: 17.08.2015

ALEX_099 пишет:

WavGat пишет:

ТС же сказал, что они не равноценны и считать нужно каждый в отдельности.
Только вот он пока не ответил на вопрос SLKH, как именно приходят импульсы. Если, к примеру, сработал дискриминатор 2, то первый тоже даст сигнал? Будет 0011 или 0010 ?

допустим дискриминаторы настроены на урони 0,2, 0,4 , 0,8 и 1,2 вольта

0,2 вольта будет отдавать то что от 0,2 и выше

0,4 отсеит то что меньше 0,4 и так далее

импульс с величиной 1,3 вольта попадет везде.

поэтому считать нужно по 4м отдельным входам

ну так повесь прерывание (одно) на первый дискриминатор (0,2);  в обработчике читай уровни с трёх остальных входов и инкрементируй соответствующие счетчики. 

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

Прочитал первое сообщение и сильно удивился вывертам окружающей реальности, т.к. сижу отлаживаю пятиканальный счётчик импульсов.  Сделано на блюпиле. Пять ног имеют собственные прерывания и считают импульсы. Таймер задаёт интервал и по окончании интервала считываются насчитанные импульсы, обнуляются переменные и всё по новой. По запросу отдаются компу по MODBUS. Блюпил взят, потому что импульсы могут идти до 500 кГц. Да и связь с компом по усб проводу не последнюю роль играет.          

ALEX_099
Offline
Зарегистрирован: 17.04.2020

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

итак по обработке прерывания накорябал следующее


#include <LiquidCrystal.h>
const byte interruptPin = 8; // контакт к которому подключен триггер
long int rot = 0; // переменная для хранения количества импульсов

// функция-обработчик, которая вызывается во время прерывания
void detect() {
    rot++;  
}
void setup() {
    Serial.begin(9600);
  
    // настроим контакт D8 на вход, да ещё с подтяжкой к питанию
    pinMode(interruptPin, INPUT_PULLUP);
    // активируем прерывание и свяжем его с функцией detect
    attachInterrupt(digitalPinToInterrupt(interruptPin), detect, RISING);
}

void loop() {
    Serial.println(rot);
    delay(100);
}

 

 
получается каждые 100 мс будет вываливаться в интерфейс то что насчитает в переменной rot
ALEX_099
Offline
Зарегистрирован: 17.04.2020

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

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

ALEX_099 пишет:

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

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

И. прежде чем продолжить - вставте код в сообщение по правилам

ALEX_099
Offline
Зарегистрирован: 17.04.2020

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

для наглядности хочу это значение вывести на лсд дисплей. 

ALEX_099
Offline
Зарегистрирован: 17.04.2020

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

как быть? шил через шнур юсб. плата в воздухе

 

ALEX_099
Offline
Зарегистрирован: 17.04.2020

шут с ней с ардуиной, на нано все работает. вот скетч

вопрос следующий. с ноги ардуино я вывел шим. со скважностью 2.  подаем это на два входа прерывания ардуино. допустим задали мы 5000 импульсов в секунду. включаем.  первая итеррация считает 5002 оба счетчика. последующая итак далее 4988. ну плюс минус. понятно что точность от много чего зависит. непонятно почему первое точное а последующие отличаются причем сильно от первой. на врем вывода я отключаю прерывание. и потом запускаю вновь. во внешний 485 все пуляется. 

#include <SoftwareSerial.h>
#include <TimerOne.h>
const int watermeterPin = 2;
const int watermeterPin1 = 3;
volatile int  pulse_frequency;
volatile int  pulse_frequency1;
unsigned long currentTime, loopTime;
unsigned long t=200,f,k=512;
byte sensorInterrupt = 0;
byte sensorInterrupt1 = 1;
SoftwareSerial RS485 (10, 11); // RX, TX
void setup()
{ 
  Timer1.initialize(t); // период    
  Timer1.pwm(9, k); // k - коэффициент заполнения 0-1023. Сигнал снимаем с выхода 9
   pinMode(watermeterPin, INPUT);
   pinMode(watermeterPin1, INPUT);
   pinMode(9, OUTPUT);
   //pinMode(, OUTPUT);
   Serial.begin(57600); 
   RS485.begin(57600);
   attachInterrupt(sensorInterrupt, getFlow, RISING);
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
                                      
   currentTime = millis();
   loopTime = currentTime;
} 

void loop ()    
{
   currentTime = millis();
   if(currentTime >= (loopTime + 1000))
   {
    detachInterrupt(sensorInterrupt);
    detachInterrupt(sensorInterrupt1);
      loopTime = currentTime;
      Serial.print ("#"),
      Serial.print(pulse_frequency);
      Serial.print("*");
      Serial.print(pulse_frequency1);
      Serial.println("#");
      digitalWrite(13, HIGH);
      RS485.print("#");
      RS485.print(pulse_frequency);
      RS485.println("#");
      pulse_frequency = 0;
      pulse_frequency1 = 0;
      attachInterrupt(sensorInterrupt, getFlow, RISING);
      
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
         }
}
void getFlow ()
{ 
   pulse_frequency++;
   }
   
   void getFlow1 ()
{ 
   pulse_frequency1++;
}

 

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

Во-первых - интервалы считаются по-еврейски, во-вторых - между стр. 36 и 38 накидано ещё много чего.

SLKH
Offline
Зарегистрирован: 17.08.2015

Там по дороге есть шанс на ещё одни грабли наступить:

импульс длительностью 0,25 мксек (#2) - это всего 4 такта процессора. хорошо бы как-то убедиться что такие импульсы нормально обрабатываются. 

ещё лучше повесить триггеры перед входами МК.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

SLKH пишет:

Там по дороге есть шанс на ещё одни грабли наступить:

импульс длительностью 0,25 мксек (#2) - это всего 4 такта процессора. хорошо бы как-то убедиться что такие импульсы нормально обрабатываются. 

ещё лучше повесить триггеры перед входами МК.

Или перейти на более скоростные аппараты. Хотя сигналы с ФЭУ мы считывали и считали еще 30 лет назад на Очень больших ЭВМ.

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

SLKH пишет:

Там по дороге есть шанс на ещё одни грабли наступить:

импульс длительностью 0,25 мксек (#2) - это всего 4 такта процессора. хорошо бы как-то убедиться что такие импульсы нормально обрабатываются. 

Согласен. Даташит на 328й мк содержит:

-----------------
The interrupt execution response for all the enabled AVR® interrupts is four clock cycles minimum. After four clock cycles the program vector address for the actual interrupt handling routine is executed. During this four clock cycle period, the program counter is pushed onto the stack.
-----------------

Так что, если импульс - 4 такта, то на высшей границе частоты регистрация импульсов станет непредсказуемой.

ALEX_099
Offline
Зарегистрирован: 17.04.2020

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

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

Для начала - строку 36 перенести поближе к аттачинтерраптам в 48-й

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

ALEX_099 пишет:

в чем еврейство

Евреи справа налево пишут.

-----

В строке №32 мина замедленного действия Прочитайте вот это, а потом исправьте эту строку.

ALEX_099
Offline
Зарегистрирован: 17.04.2020

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

ALEX_099 пишет:

в чем еврейство

Евреи справа налево пишут.

-----

В строке №32 мина замедленного действия Прочитайте вот это, а потом исправьте эту строку.

#include <SoftwareSerial.h>
#include <TimerOne.h>
const int watermeterPin = 2;
const int watermeterPin1 = 3;
volatile int  pulse_frequency;
volatile int  pulse_frequency1;
unsigned long currentTime, loopTime;
unsigned long t=200,f,k=512;
byte sensorInterrupt = 0;
byte sensorInterrupt1 = 1;
SoftwareSerial RS485 (10, 11); // RX, TX
void setup()
{ 
  Timer1.initialize(t); // период    
  Timer1.pwm(9, k); // k - коэффициент заполнения 0-1023. Сигнал снимаем с выхода 9
   pinMode(watermeterPin, INPUT);
   pinMode(watermeterPin1, INPUT);
   pinMode(9, OUTPUT);
   //pinMode(, OUTPUT);
   Serial.begin(57600); 
   RS485.begin(57600);
   attachInterrupt(sensorInterrupt, getFlow, RISING);
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
                                      
   currentTime = millis();
   loopTime = currentTime;
} 

void loop ()    
{
   currentTime = millis();
   if(currentTime - loopTime <= 1000)
   {
    detachInterrupt(sensorInterrupt);
    detachInterrupt(sensorInterrupt1);
      loopTime = currentTime;
      Serial.print ("#"),
      Serial.print(pulse_frequency);
      Serial.print("*");
      Serial.print(pulse_frequency1);
      Serial.println("#");
      digitalWrite(13, HIGH);
      RS485.print("#");
      RS485.print(pulse_frequency);
      RS485.println("#");
      pulse_frequency = 0;
      pulse_frequency1 = 0;
      attachInterrupt(sensorInterrupt, getFlow, RISING);
      
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
         }
}
void getFlow ()
{ 
   pulse_frequency++;
   }
   
   void getFlow1 ()
{ 
   pulse_frequency1++;
}

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

 

Bruzzer
Offline
Зарегистрирован: 17.03.2020

ALEX_099 пишет:

   if(currentTime - loopTime <= 1000)

вот исправил...

Условие не перепутали?   <=

ALEX_099
Offline
Зарегистрирован: 17.04.2020

поправил. все равно при подсчете сначала шим мериется 5003, затем 4993, затем 4988, затем опять 4993 и так по циклу. вопрос почему?

 

ALEX_099
Offline
Зарегистрирован: 17.04.2020

про вычитание в миллс я понял. спасибо за совет.

ALEX_099
Offline
Зарегистрирован: 17.04.2020
#include <SoftwareSerial.h>
#include <TimerOne.h>
const int watermeterPin = 0;
const int watermeterPin1 = 1;
const int watermeterPin2 = 2;
const int watermeterPin3 = 3;
volatile int  pulse_frequency;
volatile int  pulse_frequency1;
volatile int  pulse_frequency2;
volatile int  pulse_frequency3;
unsigned long currentTime, loopTime;
unsigned long t=200,f,k=512;
byte sensorInterrupt = 0;
byte sensorInterrupt1 = 1;
byte sensorInterrupt2 = 2;
byte sensorInterrupt3 = 3;
SoftwareSerial RS485 (10, 11); // RX, TX
void setup()
{ 
  Timer1.initialize(t); // период    
  Timer1.pwm(9, k); // k - коэффициент заполнения 0-1023. Сигнал снимаем с выхода 9
   pinMode(watermeterPin, INPUT);
   pinMode(watermeterPin1, INPUT);
   pinMode(watermeterPin2, INPUT);
   pinMode(watermeterPin3, INPUT);
   pinMode(9, OUTPUT);
   //pinMode(, OUTPUT);
   Serial.begin(57600); 
   RS485.begin(57600);
   attachInterrupt(sensorInterrupt, getFlow, RISING);
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
   attachInterrupt(sensorInterrupt2, getFlow2, RISING);
   attachInterrupt(sensorInterrupt3, getFlow3, RISING);
                                      
   currentTime = millis();
   loopTime = currentTime;
} 

void loop ()    
{
   currentTime = millis();
   if(currentTime - loopTime >= 1000)
   {
    detachInterrupt(sensorInterrupt);
    detachInterrupt(sensorInterrupt1);
    detachInterrupt(sensorInterrupt2);
    detachInterrupt(sensorInterrupt3);
    loopTime = currentTime;
      Serial.print ("#"),
      Serial.print(pulse_frequency);
      Serial.print("*");
      Serial.print(pulse_frequency1);
      Serial.print("*");
      Serial.print(pulse_frequency2);
      Serial.print("*");
      Serial.print(pulse_frequency3);
      Serial.println("*");
      digitalWrite(13, HIGH);
      RS485.print("#");
      RS485.print(pulse_frequency);
      RS485.print("*");
      RS485.print(pulse_frequency1);
      RS485.print("*");
      RS485.print(pulse_frequency2);
      RS485.print("*");
      RS485.print(pulse_frequency3);    
      RS485.println("#");
      pulse_frequency = 0;
      pulse_frequency1 = 0;
      pulse_frequency2 = 0;
      pulse_frequency3 = 0;
      loopTime = currentTime;
      attachInterrupt(sensorInterrupt, getFlow, RISING);
      
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
   attachInterrupt(sensorInterrupt2, getFlow2, RISING);
   attachInterrupt(sensorInterrupt3, getFlow3, RISING);
         }
}
void getFlow ()
{ 
   pulse_frequency++;
   }
   
   void getFlow1 ()
{ 
   pulse_frequency1++;
}
void getFlow2 ()
{ 
   pulse_frequency2++;
   }
void getFlow3 ()
{ 
   pulse_frequency3++;
   }   

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

ALEX_099
Offline
Зарегистрирован: 17.04.2020

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

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

Вот вам ещё одна потенциальная проблема: SoftwareSerial блочит прерывания наглухо, когда дергает ногой.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

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

#if defined(PCINT0_vect)
ISR(PCINT0_vect)
{
  SoftwareSerial::handle_interrupt();
}
#endif

#if defined(PCINT1_vect)
//ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect)); // комментируем, чтоб свое прерывание использовать
#endif

#if defined(PCINT2_vect)
ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect));
#endif

#if defined(PCINT3_vect)
ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect));
#endif

 

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

Это на вход. На выход он просто cli делает.

ALEX_099
Offline
Зарегистрирован: 17.04.2020

при подключении к юсб монитором порта в строчке получаются левые значения в 3 и 4 числе. с чем моет быть связано. сейчас попробую подкинуть внешний 485 порт и посмотреть чего туда валится при отключенном мониторе порта

ALEX_099
Offline
Зарегистрирован: 17.04.2020

ступил. подключил шим. считает

вопрос остается открытым следующий

какова точность миллс. 

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

Точность millis() в пределах нормы при стандартных условиях.

SLKH
Offline
Зарегистрирован: 17.08.2015

ALEX_099 пишет:

При любом импульсе у тебя будет фронт на самом "низковольтном" пине.  Нах те тебе четыре прерывания?

ALEX_099
Offline
Зарегистрирован: 17.04.2020

Други. теперь встал вопрос посчитать среденне значение импульсов за интервал в 5 отсчетов по 200 мс и передать их в пк. как реализовать в моем случае усредение?

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

Просуммировать и поделить на количество.

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

ALEX_099 пишет:

Други. теперь встал вопрос посчитать среденне значение импульсов за интервал в 5 отсчетов по 200 мс и передать их в пк. как реализовать в моем случае усредение?

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

Просуммировать и поделить на количество.

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

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

ALEX_099
Offline
Зарегистрирован: 17.04.2020
#include <SoftwareSerial.h>
#include <TimerOne.h>
#include <OneWire.h>
#include <DallasTemperature.h>
OneWire oneWire(12);                                       
DallasTemperature ds(&oneWire);
const int watermeterPin = 0;
const int watermeterPin1 = 1;
const int watermeterPin2 = 2;
const int watermeterPin3 = 3;
volatile int  pulse_frequency;
volatile int  pulse_frequency1;
volatile int  pulse_frequency2;
volatile int  pulse_frequency3;
unsigned long currentTime, loopTime;
unsigned long t=200,f,k=512;
byte sensorInterrupt = 0;
byte sensorInterrupt1 = 1;
byte sensorInterrupt2 = 2;
byte sensorInterrupt3 = 3;
SoftwareSerial RS485 (10, 11); // RX, TX
void setup()
{ 
  ds.begin();
  Timer1.initialize(t); // период    
  Timer1.pwm(9, k); // k - коэффициент заполнения 0-1023. Сигнал снимаем с выхода 9
   pinMode(watermeterPin, INPUT);
   pinMode(watermeterPin1, INPUT);
   pinMode(watermeterPin2, INPUT);
   pinMode(watermeterPin3, INPUT);
   pinMode(9, OUTPUT);
   pinMode(13, OUTPUT);
   Serial.begin(57600); 
   RS485.begin(57600);
   attachInterrupt(sensorInterrupt, getFlow, RISING);
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
   attachInterrupt(sensorInterrupt2, getFlow2, RISING);
   attachInterrupt(sensorInterrupt3, getFlow3, RISING);
                                      
   currentTime = millis();
   loopTime = currentTime;
} 

void loop ()    
{
   currentTime = millis();
   if(currentTime - loopTime >=1000)
   {
    detachInterrupt(sensorInterrupt);
    detachInterrupt(sensorInterrupt1);
    detachInterrupt(sensorInterrupt2);
    detachInterrupt(sensorInterrupt3);
    loopTime = currentTime;
    ds.requestTemperatures();
     // Serial.print ("#"),
      // Serial.print(pulse_frequency);
      // Serial.print("*");
      // Serial.print(pulse_frequency1);
      // Serial.print("*");
      //Serial.print(pulse_frequency2);
      //Serial.print("*");
      //Serial.print(pulse_frequency3);
      //Serial.print("*");
      //Serial.print(ds.getTempCByIndex(0));
      //Serial.println("#");
      digitalWrite(13, HIGH);
      RS485.print("#");
      RS485.print(pulse_frequency);
      RS485.print("*");
      RS485.print(pulse_frequency1);
      RS485.print("*");
      RS485.print(pulse_frequency2);
      RS485.print("*");
      RS485.print(pulse_frequency3); 
      RS485.print("*");
      RS485.print(ds.getTempCByIndex(0));   
      RS485.println("#");
      pulse_frequency = 0;
      pulse_frequency1 = 0;
      pulse_frequency2 = 0;
      pulse_frequency3 = 0;
      loopTime = currentTime;
   attachInterrupt(sensorInterrupt, getFlow, RISING);
      
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
   attachInterrupt(sensorInterrupt2, getFlow2, RISING);
   attachInterrupt(sensorInterrupt3, getFlow3, RISING);
         }
}
void getFlow ()
{ 
   pulse_frequency++;
   }
   
   void getFlow1 ()
{ 
   pulse_frequency1++;
}
void getFlow2 ()
{ 
   pulse_frequency2++;
   }
void getFlow3 ()
{ 
   pulse_frequency3++;
   }   

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

ALEX_099
Offline
Зарегистрирован: 17.04.2020

если ввести задержку в 750 или 800 мс после строчки 54 он будет стоять и ждать отвтет датчика. в время цикла увеличить на эту задержку. или это совсем коряво?

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

Если уж чинить скетч серебрянным скотчем, то лично я бы все детачинтеррапты перенес под 54-ю строку.

ALEX_099
Offline
Зарегистрирован: 17.04.2020
void loop ()    
{{
 ds.requestTemperatures();
  
}
     currentTime = millis();
   if(currentTime - loopTime >=1000)
   {
        loopTime = currentTime;
      
    detachInterrupt(sensorInterrupt);
    detachInterrupt(sensorInterrupt1);
    detachInterrupt(sensorInterrupt2);
    detachInterrupt(sensorInterrupt3);
   
     // Serial.print ("#"),
      // Serial.print(pulse_frequency);
      // Serial.print("*");
      // Serial.print(pulse_frequency1);
      // Serial.print("*");
      //Serial.print(pulse_frequency2);
      //Serial.print("*");
      //Serial.print(pulse_frequency3);
      //Serial.print("*");
      //Serial.print(ds.getTempCByIndex(0));
      //Serial.println("#");
      digitalWrite(13, HIGH);
      RS485.print("#");
      RS485.print(pulse_frequency);
      RS485.print("*");
      RS485.print(pulse_frequency1);
      RS485.print("*");
      RS485.print(pulse_frequency2);
      RS485.print("*");
      RS485.print(pulse_frequency3); 
      RS485.print("*");   
      RS485.print(ds.getTempCByIndex(0));   
      RS485.println("#");
      pulse_frequency = 0;
      pulse_frequency1 = 0;
      pulse_frequency2 = 0;
      pulse_frequency3 = 0;
      loopTime = currentTime;
   attachInterrupt(sensorInterrupt, getFlow, RISING);
   attachInterrupt(sensorInterrupt1, getFlow1, RISING);
   attachInterrupt(sensorInterrupt2, getFlow2, RISING);
   attachInterrupt(sensorInterrupt3, getFlow3, RISING);
         }
          
}

переделал, сначала он запрашивает температуру, ждет ответ. потом 1000 мс считает прерывания по 4м входам и отдает в порт значения счета и температуру

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

Зачем считать переходы в обе стороны и делить на 2, если можно считать переходы в одну сторону? Тут надо держать в голове, что общий обработчик будет дёргаться чаще, чем раздельные. И, если он будет "удачно" написан, то напропускаете импульсы за милую душу.

так ты и предложил мегу, если повесить на раздельные аппаратные а в обработчике только ++ то видимо это будет самый удачный подход!?