Добрый вечер Есть поверхностные знания ардуино, прошу помощи от пользователей форума Все делается на Arduino Leonardo Имеется сервер, потребление которого требуется измерять, точнее получать сигнал о его низком потреблении (если программа на сервере не работает, то потребление электричества падает) Собираюсь измерять следующим образом: На счетчике есть светодиод, который мигает с разной частотой в зависимости от потребляемого тока (примерно 4 Гц при потреблении 2кВт), предположительное напряжение диода 2 В, от него предполагаю лучше вывести 2 провода на оптрон (счетчик установлен Б/У и только для личных наблюдении), который в свою очередь будет создавать низкий уровень на входе ардуино при моргании диода. Нужно чтобы ардуино засекал падение потребления (частоту ниже 3 Гц для примера) тока и если это длиться более 15 минут (можно делать 3 измерения с интервалом в 5 минут и складывать полученные значения) выполнял функцию, пример digitalWrite(ledPin,LOW); Точность измерении не важна, нужно просто видеть разницу между потреблением в 1.5 кВт и 2 кВт
attachInterrupt, ну и далее простенькая работа с millis(), чтобы понять, длится ли частота 3 Гц более 15 минут или нет.
Проблема банальна, с ардуино знаком очень поверхностно, смысла изучать глубоко ради одной задачи не вижу, да и трудно это мне дается. Решил спросить у знатоков... Нужен скетч, который бы выполнил эту задачу, сам написать не могу ((
Для таких вещей есть протокол SNMP/ Твоя задача очень просто решается на сдвоенном NE555. А если хочется готовое решение, то это в "закажу проект".
Либо в "закажу проект", либо - самому пробовать. Я могу накидать костяк, но - проверять на корректность работы и писать комментарии - не буду, там и так всё достаточно просто. Вот, смотрите - есть от чего отталкиваться: Код (C++): volatile bool triggered = false; volatile uint32_t triggeredTime = 0; volatile uint32_t pulseWidth = 0; bool timerEnabled = false; uint32_t timerStartTime = 0; void interruptFunction() { if(digitalRead(2) == LOW) { triggeredTime = micros(); } else { if(triggeredTime && !triggered) { pulseWidth = (micros() - triggeredTime); triggeredTime = 0; triggered = true; } } } void setup() { attachInterrupt(digitalPinToInterrupt(2),interruptFunction, CHANGE); } void loop() { if(triggered) { if(pulseWidth <= 330000) { if(!timerEnabled) { timerEnabled = true; timerStartTime = millis(); } } else { timerEnabled = false; } triggered = false; } if(timerEnabled && ( (millis() - timerStartTime) > 1000*60*15)) { digitalWrite(13,HIGH); } }
Если вас не затруднит укажите пожалуйста в каком месте у кода задается частота после которой выполняется действие?
У вас с английским как? Словосочетание "pulse width" что-нибудь говорит? Код (C++): if(pulseWidth <= 330000) Это ширина импульса в микросекундах, ниже которой включается таймер, и если за время, пока таймер включён, частота не превысила минимальную - то на пине 13 появится высокий уровень. 330 000 микросекунд - это 330 миллисекунд, или примерно три раза в секунду, т.е. примерно 3 Гц.
Спасибо за "костяк", подкорректировал под себя и все заработало. Код у меня не работал по следующей причине Код начинает измерять микросекунды между импульсами если видит падение Код (C++): void interruptFunction() { if(digitalRead(2) == LOW) Я этот участок подкорректировал на Код (C++): void interruptFunction() { if(digitalRead(2) == HIGH) Причина этого в том, что у меня сигнал не 50/50 (мэандр), а с 6% заполнением снизу и 94% сверху. Конечный вариант Код (C++): volatile bool triggered = true; //Переменная должна быть объявлена volatile, когда её значение может быть изменено за пределами того участка программы, где она объявлена volatile uint32_t triggeredTime = 0; //uint32_t Если в коде критично важна разрядность целочисельных типов даных. volatile uint32_t pulseWidth = 0; //uint32_t Если в коде критично важна разрядность целочисельных типов даных. bool timerEnabled = false; uint32_t timerStartTime = 0; //uint32_t Если в коде критично важна разрядность целочисельных типов даных. void interruptFunction() { if(digitalRead(2) == HIGH) //если на пине 2 высокий уровень { triggeredTime = micros(); //присваиваем triggeredTime = количество микросекунд с момента начала выполнения текущей программы } else { if(triggeredTime && !triggered) //если triggeredTime && !triggered { pulseWidth = (micros() - triggeredTime); triggered = true; } } } void setup() { //Serial.begin(9600); //мониторинг порта, нужен только для отладки pinMode(2, INPUT); // Инициализируем цифровой вход/выход в режиме входа. pinMode(7, OUTPUT); pinMode(13, OUTPUT); attachInterrupt(digitalPinToInterrupt(2),interruptFunction, CHANGE); //прерывание вызывается при смене значения на порту, с LOW на HIGH и наоборот } void loop() //циклично выполняемая функция { //Serial.print("pulseWidth: "); // Для отладки //Serial.print(pulseWidth); //Serial.print(" timerEnabled: "); //Serial.print(timerEnabled); //Serial.print(" timerStartTime: "); //Serial.print(timerStartTime); //Serial.println(analogRead(13)); delay(1000); // Частота опроса при отладке if(triggered) { if(pulseWidth >= 270000) // Примерно 270000 микросекунд для измерения частоты 3.6 Герц { if(!timerEnabled) { timerEnabled = true; timerStartTime = millis(); } } else { timerEnabled = false; } triggered = false; } if(timerEnabled && ( (millis() - timerStartTime) > 300000)) //Ставим таймер 300000 (5 минут) { digitalWrite(7,HIGH); digitalWrite(13,HIGH); //Serial.print("13,HIGH "); } else { digitalWrite(7,LOW); digitalWrite(13,LOW); //Serial.print("13,LOW "); } }