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

gorar
Offline
Зарегистрирован: 11.12.2018

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

Есть електронный счетчик  топлива MGE110 с дисплеем. Он умеет только отобразить объем. А мне надо управлять насосом. Я вижу такой выход: подключиться к датчикам оборотов (похоже на геркон, на плате даже есть розъем с сигналами от этих датчиков) счетных овальных шестеренок и соорудить свой счетчик на ардуинке. 

Подключил ардуино, по отдельности кажется щитает нормально. Но вот пока никак в голову не придет алгоритм для сведения этих сигналов в сумму. Не просто суммировать количество, а учитывать только поочередные импульсы кроме первого (a-b-a-b-a-b-a-b = 7имп;  a-b-b-a-a-b-b = 3имп).

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Откуда a-a-a и b-b-b ббберутся у Вас? Там же двоичный код должен быть?...

gorar
Offline
Зарегистрирован: 11.12.2018

a,b - импульс с первого и второго датчика соответственно. Нет там двоичного кода (не нашел, а было бы проще).

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

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

gorar пишет:
a,b - импульс с первого и второго датчика соответственно. Нет там двоичного кода (не нашел, а было бы проще). Если по простому, то датчики срабатывают по очереди и мне надо посчитать количество срабатываний,но исключить дубли от одного датчика.

у вас с одного датчика выходят два сигнала? Если да, то они код выдают, подключите библиотеку энкодера и проверьте

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

gorar пишет:
a,b - импульс с первого и второго датчика соответственно. Нет там двоичного кода (не нашел, а было бы проще). Если по простому, то датчики срабатывают по очереди и мне надо посчитать количество срабатываний,но исключить дубли от одного датчика.

Ищите, должны быть коды... Обязаны!))

Сами то (хоть примерно) поняли как «отфильтровать»?

gorar
Offline
Зарегистрирован: 11.12.2018

ua6em пишет:

у вас с одного датчика выходят два сигнала? ...

нет, датчика - 2 и сигналов - 2. При вращении измерительного механизма датчики замыкаются поочередно.

BOOM пишет:

Ищите, должны быть коды... Обязаны!))

Не спорю, может они и есть, но пока до осцила еще не дожился. До проца также не добраться - он под большим ЖК дисплеем. Пока буду розбираться с тем что есть.

BOOM пишет:

Сами то (хоть примерно) поняли как «отфильтровать»?

Примерно  так: при каждом срабатывании датчика (первого или второго) проверять была ли сработка "напарника" и если "да" то добавлять единицу к общей сумме и выставлять флаги. Но пока затрудняюсь как правильно расставить флаги. Первый импульс может быть как с "А" так и с  "B" датчика.

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

Вам же уже сказали

ua6em пишет:
подключите библиотеку энкодера

gorar
Offline
Зарегистрирован: 11.12.2018

ua6em пишет:

 подключите библиотеку энкодера и проверьте

Спасибо за пинок в нужном направлении, сама библиотека мне совсем не помогла, но попался кусок кода (всеми "любимого" Гайвера) обработчика энкодера который я подогнал под свои нужды и ПОКА (на столе) работает как надо.

Может кому пригодится:

#define ENC_A 2       // пин A
#define ENC_B 3       // пин B
volatile int encCounter;
volatile boolean flag;
volatile byte curState, prevState;
void setup() {
  Serial.begin(115200);
  attachInterrupt(0, int0, FALLING );
  attachInterrupt(1, int1, FALLING );
}
void int0() {
  Serial.println("int0");
  encTick();
}
void int1() {
  Serial.println("int1");
  encTick();
}

void encTick() {
  curState = digitalRead(ENC_A) | digitalRead(ENC_B) << 1; 
  if (curState == 0b01 && prevState == 0b10) {
    encCounter++;
    flag = true;
  }
  if (prevState == 0b01 || prevState == 0b00){
  if (curState == 0b10) {
    encCounter++;
    flag = true;
  }
  }
  prevState = curState;
}
void loop() {
  if (flag) {
    Serial.println(encCounter);
    Serial.print(float(encCounter / 42.00));
    Serial.println('L');
    flag = false;
  }
}
gorar
Offline
Зарегистрирован: 11.12.2018

Продолжу здесь.

Соорудил минимально необходимый алгоритм для обработки счетчика, на столе (магнит в руке) работает нормально. Но вот в железе -  пропускает импульсы. Из 820 ипм насчитывает 780-800, при коеф. 42 имп на литр это уже большая погрешность.

Вот такой сигнал на входах.

Что уже проверял:

1. Питание платы брал от отдельного акумулятора - никакой разницы.

2. При отключении програмной проверки поочередности сигнала (считает все срабатывания) количество импульсов растет в 3-4 раза и количество плавает уже на несколько сотен единиц.

 

Подскажите алгоритм как найти виновника

 

 

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

Serial-у не место в обработчике прерывания.
Чтение volatile-переменной без обеспечения атомарности может привести к разным спецэффектам.

gorar
Offline
Зарегистрирован: 11.12.2018

sadman41 пишет:
Serial-у не место в обработчике прерывания.


void int0() {                  // переривання на перший датчик
   encTick();
}
void int1() {               // переривання на другий датчик
   encTick();
}

void encTick() {              // обробка переривання датчиків
  curState = digitalRead(ENC_A) | digitalRead(ENC_B) << 1; 
  if (curState == 0b01 && prevState == 0b10) {
    encCounter++;
    flag = true;
  }
  if (prevState == 0b01 || prevState == 0b00) {
    if (curState == 0b10) {
      encCounter++;
      flag = true;
    }
  }
  prevState = curState;
}

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

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

https://github.com/PaulStoffregen/Encoder/blob/master/examples/Basic/Basic.pde

Проконтролируйте на этом скетче.

gorar
Offline
Зарегистрирован: 11.12.2018

sadman41 пишет:

Проконтролируйте на этом скетче.

Спасибо!

Подключил эту библиотеку к своему проекту и все работает ! Правда выдает количество импульсов *2 но в данном случае это не критично, главное повторяемость результата, пока прогнал пару раз - все отлично! 

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

 

Сразу еще вопрос:

Хочу еще сделать связь по Serial из еще одним блоком, для обмена данными. частота обмена не критична, около 0.5-1 Гц

Вопрос: не помешают ли прерывание обмена для правильного подсчета импульсов. 

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

Слишком абстрактный вопрос. Ни скорости обмена, ни алгоритма, ни объема данных, ни указания по какому сериалу - софтовому или нет.
Поставьте куда-нить println и посмотрите - будут или нет сбиваться показания с приемом частоты с генератора.

gorar
Offline
Зарегистрирован: 11.12.2018

sadman41 пишет:
Слишком абстрактный вопрос.

Да, но главное что правильный: действительно может мешать работе!

 

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

Для передачи планирую использовать радиомодуль прозрачний для UART. Вопрос: какой сериал предпочтительней для такой стуации, апаратный или софт? Если софт то порекомендуйте  адекватную библиотеку.

Скорость обмена будет небольшая (для нормальной работы радиомодуля)

Спасибо!

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

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