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

imv14
Offline
Зарегистрирован: 02.04.2014

Добрый уважаемые знатоки. Собран детектор гамма квантов, на выходе импульсы от 1 до 5 вольт.  Подскажите пожалуйста как ардуиной посчитать, колличество импульсов в секунду.

Radjah
Offline
Зарегистрирован: 06.08.2014

Таймер и прерывания например.

imv14
Offline
Зарегистрирован: 02.04.2014

А можно поточнее, я в ардуино вообще не соображаю.

faraddin
Offline
Зарегистрирован: 11.08.2013

Ну если длина импульса много больше чем длина такта ардуины (16 мГц) тогда просто ждете начало импульса, плюсуете к счетчику еденицу, ждете конец импульса, проверяете сколько прошло времени. как проходит одна секунда так счетчик и покажет количество импульсов. А узнать сколько прошло время поможет millis()

imv14
Offline
Зарегистрирован: 02.04.2014

Спасибо за помощь. По моим подсчетам в секунду должно проходить порядка 30 импульсов, при нормальном фоне. Длина импульса намного меньше такта ардуины. Как правильнее делать?

Radjah
Offline
Зарегистрирован: 06.08.2014

Вот так я мегой импульсы считал. https://github.com/radjah/arduino/blob/master/interrupt/test_timer/test_...

imv14
Offline
Зарегистрирован: 02.04.2014

Спасибо. Попробую чего-нибудь написать, потом спрашу.

imv14
Offline
Зарегистрирован: 02.04.2014

Всем добрый день. Почивав форумы понял, что нужно использовать 2 прерывания, внешнее прерывание по приходу импульса (attachInterrupt(0, функция увеличивающее кол-во импульсов на 1, RISING);),все ли я правильно понял? Второе прерывание по времени через каждую секунду. Не могу сообразить как правильно сделать прерывание по времени, помогите пожалуйста

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

SSStylish
Offline
Зарегистрирован: 15.03.2014

Скетч для автомобильного тахометра:

const int tachPIN=2;
const unsigned long sampleTime=1000;
const int maxRPM = 10200; 

void setup() 
    {
    pinMode(tachPIN, INPUT);
    digitalWrite(tachPIN, HIGH); //Turns on pullup resistor on pin.    
    Serial.begin(9600);
    }

void loop() 

{
    int rpm=getRPM();
    Serial.print("RPM: ");
    Serial.print(rpm);
    Serial.print("\n");
}

int getRPM()

{
  // sample for sampleTime in millisecs
  int kount=0;
  boolean kflag=LOW;
  unsigned long currentTime=0;
  unsigned long startTime=millis();
  while (currentTime<=sampleTime)
{

if (digitalRead(tachPINPin)==HIGH)
    {
     kflag=HIGH;
    }

if (digitalRead(tachPINPin)==LOW && kflag==HIGH)
    {
    kount++;
    kflag=LOW;
    }

currentTime=millis()-startTime;
}

int kount2rpm = int(60000./float(sampleTime))*kount;
return kount2rpm;

}
 
imv14
Offline
Зарегистрирован: 02.04.2014

Спасибо, попробую разобраться что здесь.

imv14
Offline
Зарегистрирован: 02.04.2014

Корректно ли будет вот так:

#include <LiquidCrystal.h> // Буду использовать дисплей, без I2C
#include <TimerOne.h>    

volatile int colImp = 0;   // Счетчик импульсов
volatile int T = 0;
const int ledPin = 9;     // Подаю импульсы на 9 ножку 

void setup() 
{
  pinMode(ledPin, INPUT);
  digitalWrite(ledPin, LOW);       // Сомневаюсь что нужно HIGH или LOW
  attachInterrupt(1, D2Int, RISING);// Прерывание по приходу импульса

  Timer1.initialize(1000000);       // Таймер на 1 секундe 
  Timer1.attachInterrupt(D3Int);

  Serial.begin(9600);
}
void loop() 
{
  if (T == 1) // Если прошла 1 секунда тогда 
{
  Serial.print(colImp);
  colImp = 0; //обнуляем колличество накопленных импульсов
  T = 0;      // сбрасываем T
}
}
void D2Int() 
{
  colImp++;   // увеличиваем на 1 колличество импульсов 
}
void D3Int()
{
  T = 1; // по прошествию 1 сек 
}

Могу ли я прямо в фунуции D3Int()-прерывания по времени, выводить информацию в порт или на дисплей.

Radjah
Offline
Зарегистрирован: 06.08.2014

http://arduino.ru/Reference/AttachInterrupt

Внутри функции обработки прерывания не работает delay(), значения возвращаемые millis() не изменяются. Возможна потеря данный передаваемых по последовательному соединению (Serial data) в момент выполнения функциии обработки прерывания. Переменные, изменяемые в функции, должным быть объявлены как volatile.

Rednaxela
Offline
Зарегистрирован: 26.08.2013

вот, 1 секунда без извращений  (только библиотеку скачайте)

#include "MsTimer2.h"

void setup() {
 MsTimer2::set(1000, flash); // 1000 ms  = 1 s
 MsTimer2::start();
}

void flash(void) { /*вызывается строго раз в секунду*/ } 

 

imv14
Offline
Зарегистрирован: 02.04.2014

Спасибо. Можно еще вопрос по

pinMode(ledPin, INPUT);
digitalWrite(ledPin, LOW);       // Сомневаюсь что нужно HIGH или LOW

 

imv14
Offline
Зарегистрирован: 02.04.2014

Всем добрый день, извиняюсь за тупость, не могу понять почему программа не считает импульсы. Собрал устройство, импульсы идут ровные 5 Вольт (смотрю осцилографом).
 

#include <MsTimer2.h>
volatile int colImp = 0;   // Счетчик импульсов
volatile int T = 0;
const int ledPin = 12;     // Подаю импульсы на 9 ножку
void setup()
{
  pinMode(ledPin, INPUT);
  digitalWrite(ledPin, HIGH);       // Сомневаюсь что нужно HIGH или LOW
  attachInterrupt(1, D2Int, RISING);// Прерывание по приходу импульса
    MsTimer2::set(1000, flash); // 1000 ms  = 1 s
    MsTimer2::start();	 
  Serial.begin(9600);
}
void loop()
{
  if (T == 1) // Если прошла 1 секунда тогда
{
Serial.print(colImp);
  colImp = 0; //обнуляем колличество накопленных импульсов
  T = 0;      // сбрасываем T
}
}
void D2Int()
{
  colImp++;   // увеличиваем на 1 колличество импульсов
}
void flash(void) //*вызывается строго раз в секунду*/ 
{
  T = 1; // по прошествию 1 сек
}
jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

у меня одного странно выглядит?

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

Нет, у меня тоже весь экран вни "забит" кодом, точнее дублем кода.

ТС, попробуйте не использовать пин 1, возьмите другие, кроме 0 и 1.

 

imv14
Offline
Зарегистрирован: 02.04.2014

pin 1 - допустил "описку", там 12. Использую ардуино Nano, на D12 подключаю провод с импульсами.

Radjah
Offline
Зарегистрирован: 06.08.2014

Таймер для выставления флага? Но нахрена?

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

imv14
Offline
Зарегистрирован: 02.04.2014

Как то так?

void loop()
{
Serial.print(T);
}
void D2Int()
{
  colImp++;   // увеличиваем на 1 колличество импульсов
}
void flash() //*вызывается строго раз в секунду*/ 
{
  T = colImp; // по прошествию 1 сек
  colImp = 0; //обнуляем колличество накопленных импульсов
}

Я думаю, что проблема тут, только не понимаю в чем.

  pinMode(ledPin, INPUT);
  digitalWrite(ledPin, HIGH);       // Сомневаюсь что нужно HIGH или LOW
  attachInterrupt(1, D2Int, RISING);// Прерывание по приходу импульса

 

imv14
Offline
Зарегистрирован: 02.04.2014

Нашел ряд ошибок:

1. Nano внешнее прерывание на D2 и D3.

2. Неправильно написал colImp++, надо было наоборот.

digitalWrite(ledPin, LOW); 

Замыкаю D2 на 5 вольт все срабатывает заходит в прерывание, а с устройства не импульсы не берет, завтра увеличу амплитуду импульсов.

Radjah
Offline
Зарегистрирован: 06.08.2014

LOW если ловишь такой импульс _П_ Прерывание на RISING для начала импульса или FALLING для конца импульса.

HIGH в противоположном случае.

По идее ардуина должна ловить импульсы от 2,4 вольт.

imv14
Offline
Зарегистрирован: 02.04.2014

Спасибо Radjah.  Импульсы такие  _П_.  Я правильно понимаю, что прерывание в виде attachInterrupt(1, D2Int, RISING) мне должно быть достаточно.

 

Radjah
Offline
Зарегистрирован: 06.08.2014

Ну это зависит от того, что тебе посчитать надо. Если целые импульсы, то FALLING (спад), если фронты, то RISING (нарастание).

imv14
Offline
Зарегистрирован: 02.04.2014

Нужно считать колличество целые импульсы _П_, не могу понять в чем проблема, пробовал и FALLING и RISING.

Radjah
Offline
Зарегистрирован: 06.08.2014

Я вот так мутил https://github.com/radjah/arduino/blob/master/interrupt/test_timer/test_...

А вот так импульсы другой ардуиной делал https://github.com/radjah/arduino/blob/master/interrupt/gen_random/gen_r...

На название не смотри :)

art100
Offline
Зарегистрирован: 09.03.2014

не бейте ногами сильно не удержался скопипастю веселье :)

я вижу только один косячек перевода "летучие" unsigned

#есть <TimerOne.h>
#есть <CyberLib.h>
#есть <Проволоки.h>
#есть <LCD.h>
#есть <LiquidCrystal_I2C.h>


// Порты LCD
#определить LCD_I2C_ADDR 0x27
#определить Подсветка     3
#определить LCD_EN  2
#определить LCD_RW  1
#определить LCD_RS  0
#определить LCD_D4  4
#определить LCD_D5  5
#определить LCD_D6  6
#определить LCD_D7  7

LiquidCrystal_I2C lcd(LCD_I2C_ADDR, LCD_EN, LCD_RW, LCD_RS, LCD_D4, LCD_D5, LCD_D6, LCD_D7);

летучие долго int count = 0;     // Счетчик
летучие долго int oldcount = 0;  // Для вычисления скорости
летучие float скорость = 0;   // Значение скорости

void установки() {
  // D3 на ввод
 D3_In;
 D3_High;
  // Прерывание по нарастанию
  attachInterrupt(1, D2Int, RISING);
  // Таймер на 4 секунды
 Timer1.инициализировать(1000000);
 Timer1.attachInterrupt(Calcspeed);
  // Запуск дисплея
 lcd.начать(20, 4);
 lcd.setBacklightPin(ПОДСВЕТКА, ПОЗИТИВНЫЕ);
 lcd.setBacklight(Высокая);
  // Шаблон
 lcd.ясно();
 lcd.setCursor(0,1);
 lcd.печать("Скорость: ");
 lcd.дома();
 Серийный.начать(9600);
}

void цикл() {
 lcd.дома();
  // Буферы для вывода на дисплей
  char cnt[20] = "";  // Счетчик
  char СПД[13] = "";  // Скорость
  // Счетчик в строку
  sprintf(cnt, "Граф: %13lu", count);
 lcd.печать(cnt);
  // Скорость в строку
  dtostrf(скорость, 13, 2, СПД);
 lcd.setCursor(7,1);
 lcd.печать(СПД);
 Серийный.печать(count);
 Серийный.печать("   ");
 Серийный.println(скорость);
  // Задержка
  delay_ms(1000);
}
void D2Int() {
  // Приращение счетчика по прерыванию
 count++;
}

void Calcspeed(){
  // Вычисление скорости
 скорость = float(граф - oldcount);
 oldcount = count;
}

 

imv14
Offline
Зарегистрирован: 02.04.2014

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

imv14
Offline
Зарегистрирован: 02.04.2014

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

batman5573
Offline
Зарегистрирован: 27.08.2015

И какой же окончательный (правильный) код???

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

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

Ну это так...просто размышление...как вариант.

DarkMoons
Offline
Зарегистрирован: 29.12.2015

Добрый вечер) нужна помощь в написании кода. Суть работы в том что к ардуино подсоеденем датчик расхода топлива, мне нужно что бы ардуино считывал импульсы с датчика и по ком порту передавал их на ПК.  Спасибо)

 

Radjah
Offline
Зарегистрирован: 06.08.2014

> нужна помощь

Показывай код или в "Ищу исполнителя"

CODE or GTFO

DarkMoons
Offline
Зарегистрирован: 29.12.2015

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

 

 
bwn
Offline
Зарегистрирован: 25.08.2014

DarkMoons пишет:

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

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

DarkMoons
Offline
Зарегистрирован: 29.12.2015

Спасибо)