Замерить длину импульса

Тема в разделе "Arduino & Shields", создана пользователем Scrypto, 29 июн 2018.

  1. Scrypto

    Scrypto Нерд

    Ситуация такая, есть монетоприемник, который отправляет импульсы определенной фиксированный длинны.
    50 миллисекунд.
    Дабы избежать ложных срабатываний, нужно каким-то образом, замерить длинну полученного импульса, учитывая то, что монетник подключен к прерыванию.
    То есть, линия подтянута к 5 вольтам через резистор, монетник, при попадании монеты притягивает к 0, соответственно срабатывает прерывание (FALLING), и вот в нём нужно каким-то образом понять, какое время был притянут к 0 ?
    Подскажите, как реализовать?
     
  2. Daniil

    Daniil Гуру

    Можно сконфигурировать прерывание не только переход 1->0, но и на переход 0->1.
    Замерить таймером время между двумя прерываниями.:)
     
    Scrypto и arkadyf нравится это.
  3. Scrypto

    Scrypto Нерд

    Все гениальное просто ) Спасибо )
     
  4. parovoZZ

    parovoZZ Гуру

    На таймере. У него даже специальный аппаратный пин наружу торчит)))
     
    Scrypto нравится это.
  5. Scrypto

    Scrypto Нерд

    Ребят, подскажите, что не так?
    Код (C++):
      attachInterrupt(1, coinsCounterA, FALLING);   // прерывание 1a
      attachInterrupt(1, coinsCounterB, RISING);   // прерывание 1b

    Код (C++):
    volatile unsigned long duration;
    //Прерывание 1a
    void coinsCounterA (){
    duration =millis();// Записываем время срабатывания прерывания
    impulseCount++;
    }
    //  Прерывание 1b
    void coinsCounterB (){
    if(millis()- duration >40&&millis()- duration <100){// Если время между Falling & RisinG подходит
    rele1Open =LOW;
    impulseCount++;
    }
    Срабатывает только 1b ( Ну естетственно условие не срабатывает, но если добавить в оба прерывания какой нибудь boolean, то меняться он будет только при срабатывании 1b)
     
  6. Limoney

    Limoney Гик

    посмотрите на функцию pulseIn()
     
  7. Scrypto

    Scrypto Нерд

    Если честно, не особо понял, как её можно использовать в моём случае
     
  8. Scrypto

    Scrypto Нерд

    Я вот думаю, может я херней страдаю
    Просто сначала объявил FALLING, потом RISING, а по итогу, первое заменилось вторым, и не работает именно по этому, надо наверно на CHANGE Делать.
     
  9. DIYMan

    DIYMan Guest

    Так точно. Смотри, какая шляпа: тебе надо померить время, когда на пине 0. Делаешь прерывание на CHANGE, и внутри что-то типа такого:

    Код (C++):
    #define INTERRUPT_PIN 2
    bool hasData = false;
    uint32_t pulseTimeInMicros = 0;
    uint32_t startPulseTime = 0;
    bool active = false;


    void measure()
    {
        if(!digitalRead(INTERRUPT_PIN))
        {
            active = true;
            startPulseTime = micros();
        }
        else
        {
            if(active)
            {
                active = false;
                pulseTimeInMicros = micros() - startPulseTime;
                hasData = true;
            }
        }
    }

    void setup()
    {
        Serial.begin(9600);
        attachInterrupt(digitalPinToInterrupt(INTERRUPT_PIN), measure, CHANGE);
    }

    void loop()
    {
        if(hasData)
        {
            cli();
            hasData = false;
            uint32_t thisPulseTime = pulseTimeInMicros;
            sei();
         
            Serial.print(F("Pulse time: "));
            Serial.println(thisPulseTime);
         
        }
    }
    Писал навскидку, надеюсь, логика понятна.
     
    Limoney, Daniil и Scrypto нравится это.
  10. Scrypto

    Scrypto Нерд

    Сделал так

    Код (C++):
    // Переменные для работы с монетоприемником
    volatile boolean fal = false;
    volatile static unsigned long durationBegin;

    attachInterrupt(1, coinsCounter, CHANGE);
    Код (C++):
    void coinsCounter () {
    if(!fal){
      durationBegin = millis();
      fal = true;
    }
    else if (millis() - durationBegin > 40 && millis() - durationBegin < 60){
      impulseCount++;
      durationBegin = 0;
      fal = false;
      rele1Open = LOW;
    }
    // Чтобы если импульс не подошел по длинне, не мешал следующей работе
    else
    {
    fal =false;
    durationBegin =0;
    }
    }
    Пока тестирую, но вроде норм
     
    Последнее редактирование: 29 июн 2018
  11. Limoney

    Limoney Гик

    Вариант
    Код (C++):
    const byte IntPIN = 2;
    boolean volatile IntComplete = false;
    unsigned long timeimpulse = 0;

    void specie() {
      IntComplete = true;
    }

    void setup() {
      Serial.begin(9600);
      attachInterrupt(digitalPinToInterrupt(IntPIN), specie, FALLING);
    }

    void loop() {
      if (IntComplete) {
        IntComplete = false;
        timeimpulse = pulseIn(IntPIN, LOW);
        if (timeimpulse != 0) {
          Serial.println(timeimpulse);
        }
      }
    }
     
    Scrypto нравится это.
  12. Scrypto

    Scrypto Нерд

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

    Код (C++):
    void coinsCounter () {
    if(digitalRead(3) == LOW){
      durationBegin = millis();
    }
    else if (millis() - durationBegin > 90 && millis() - durationBegin < 110 && digitalRead(3) == HIGH){
      impulseCount++;
      durationBegin = 0;
      rele1Open = LOW;
    }
    else // Если импульс не подошел по длинне, то восстанавливаем начальные значения
    {
       durationBegin = 0;
    }
    }