Ситуация такая, есть монетоприемник, который отправляет импульсы определенной фиксированный длинны. 50 миллисекунд. Дабы избежать ложных срабатываний, нужно каким-то образом, замерить длинну полученного импульса, учитывая то, что монетник подключен к прерыванию. То есть, линия подтянута к 5 вольтам через резистор, монетник, при попадании монеты притягивает к 0, соответственно срабатывает прерывание (FALLING), и вот в нём нужно каким-то образом понять, какое время был притянут к 0 ? Подскажите, как реализовать?
Можно сконфигурировать прерывание не только переход 1->0, но и на переход 0->1. Замерить таймером время между двумя прерываниями.
Ребят, подскажите, что не так? Код (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)
Я вот думаю, может я херней страдаю Просто сначала объявил FALLING, потом RISING, а по итогу, первое заменилось вторым, и не работает именно по этому, надо наверно на CHANGE Делать.
Так точно. Смотри, какая шляпа: тебе надо померить время, когда на пине 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); } } Писал навскидку, надеюсь, логика понятна.
Сделал так Код (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; } } Пока тестирую, но вроде норм
Вариант Код (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); } } }
В итоге подправил код функции, убрав проверку по 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; } }