Подсчет импульсов от Меркурий, при помощи фоторезистора.

Тема в разделе "Arduino & Shields", создана пользователем Miheeei, 27 апр 2017.

  1. Miheeei

    Miheeei Нерд

    Добрый день, сразу скажу что темой микроконтроллеров начала увлекаться 2 месяца назад, так что прошу сильно не критиковать)).
    Столкнулась с необходимостью чтение импульсов светодиода на электросчетчики Меркурий 201.
    Доступа к клеймам телеметрического выхода нет, электрики запретили подключаться к ним, дублирующий счетчик ставить не планирую.
    Остается только фоторезистор. Нашла похожую тему на этом форуме правда тема стара и уже не актуальна.
    Собрала делитель на основе фоторезистора и и потенциометра(схема прилагается).
    Потенциометром выставила чувствительность, таким образом при горящем светодиоде valHigh == 100
    а, при погасании светодиода valHigh == 43

    Нашла рабочий скетч
    Проблема такая: иногда schet увеличивается на 2, не смотря на то что он изначально добавляет 2 единицы а затем делится на 2. Все работает но, таким образом я получаю завышенные показания, примерно на 1 кВт лишних 100 ВТ.
    Подскажите как исправить?

    P.S. Сегодня наткнулась на модуль светло - темно(тот же фоторезистор, драйвер LM393? потенциометр), но на цифровом выходе модуля в зависимости от освещения, 1 или 0.
    Решит ли данный модуль мою проблему если я уже на цифровом пине буду считывать и считать состояние. Как мне избежать расхождений и проскальзывания?
     

    Вложения:

  2. serg_admin

    serg_admin Гик

    Нужно либо поставить задержку. Либо реализовать "гестирезис".
     
  3. serg_admin

    serg_admin Гик

    Вообще загадочный блок
    Код (C++):
    schet++;
    schet/2;
     
  4. Miheeei

    Miheeei Нерд

    Счетчик считает когда светодиод горит и когда не горит, по этому получается что за 1 имп переменная добавляется на 2. после чего делится на 2.

    "Гестирезис" это мне не о чем не говорит))
    Объясните пожалуйста...
     
  5. serg_admin

    serg_admin Гик

    Код (C++):
    schet++;
    schet/2;
    schet/2; // я честно говоря ни когда такой операции не видел
    Бывает такая:
    Код (C++):

    schet /= 2;
     
    Но все равно бесполезно. Во первых переменная schet целая поэтому не может хранить половинку от деления. Во вторых делиться будет не только прибавлена единичка, а все содержимое переменной. Я не вижу ситуации когда она может стать больше двух.
     
  6. serg_admin

    serg_admin Гик

    Что такое петля гистерезиса лучше почитать. Там ни чего сложного, но писать много.
    Для Вашего случая примерно так
    Код (C++):
    if ((flag == true) && (analogRead(A0) > 80)
      flag = false;

    if ((flag == false) && (analogRead(A0) < 63)
      flag = true;
    Вместо:
    Код (C++):
    flag = (analogRead(A0) < valHigh);
    То есть если состояние переключилось на false (светло) он не переключится в темно пока не станет "реально темно".
    Ну и аналогично наоборот.
     
  7. mcureenab

    mcureenab Гуру

    В данном случае следует задать High и Low пороги.
    И реализовать такую логику:
    Если сигнал был ниже Low, то считаем schet++, когда сигнал станет выше High.
    И наоборот.
    Если сигнал был выше High, то считаем schet++, когда сигнал станет ниже Low.
     
  8. Miheeei

    Miheeei Нерд

    Код взят от суда: http://forum.amperka.ru/threads/Считать-импульсы-с-Меркурий-201.5746/#post-47563
    Если переменная schet будет не int a float?
     
  9. serg_admin

    serg_admin Гик

    Я так понял 100 и 43 в начале топика и есть эти пороги.
     
  10. serg_admin

    serg_admin Гик

  11. Miheeei

    Miheeei Нерд

    Так я вроде так и делаю, сравниваю предыдущие состояние(в скетче стоят цифры 100 это ошибки, наглядно себе писала и забыла затереть)

    bool flag;
    bool oldFlag;

    flag = (analogRead(A0) < valHigh);
    if (flag != oldFlag)
    {
    schet++;
    oldFlag = flag;
     
  12. serg_admin

    serg_admin Гик

    В том топе корректно потому что делится при выводе в порт.
    А у Вас деление "в воздухе"
     
  13. mcureenab

    mcureenab Гуру

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

    Если значение датчика будет дрожать вблизи valHigh (это могут быть помехи и т.п.), вам много чего насчитается.
     
  14. mcureenab

    mcureenab Гуру

    Если деление приземлить, то считаться вообще не будет.

    пусть i == 0;
    i++ -> i==1;
    i /= 2; -> i == 0;

    От чего пришли к тому вернулись.
     
  15. Miheeei

    Miheeei Нерд

    Так верхний порог у меня = 100(он конечно пляшет но в рамках 92-100)
    нижний порог = 43 (он тоже плавает от 43-50)
    Поэтому приходится брать середину, таким образом я знаю что если < 70 то явно светодиод тухнет.

    Если Вам не тяжело поправьте мой скетч, попробую разобраться в ошибках по факту
     
  16. serg_admin

    serg_admin Гик

    Код (C++):
    nt schet = 0; //Cчетчик импульсов
    bool flag;100
    bool oldFlag;100
    byte valHigh = 70;

    void setup()
    {
    Serial.begin(9600);
    pinMode(A0, INPUT);
    flag = (analogRead(A0) < valHigh);
    oldFlag = flag;
    }

    void loop()
    {
    if((flag ==true)&&(analogRead(A0)>80)
      flag =false;

    if((flag ==false)&&(analogRead(A0)<63)
      flag =true;
    if (flag != oldFlag)
    {
     if (flag)
    schet++;
    oldFlag = flag;
    }
    Serial.println(schet);
    }
     
  17. Miheeei

    Miheeei Нерд

    Спасибо, вечером буду дома залью, проверю.
    А по поводу модуля про который я говорила, есть ли в нем смысл для данного проекта?
     
  18. serg_admin

    serg_admin Гик

    На нем один компаратор. То есть будите иметь теже проблемы
     
  19. Miheeei

    Miheeei Нерд

    Здравствуйте. Протестировала Ваш код. Все отлично, за 4 суток расхождений нет.
    Спасибо