Для новичков прикладываю схему и формулу для расчета резистора для диода оптопары (на схеме R1, R2 вот здесь у меня была ошибка, все остальное подключал правильно).
(U - UF) / IF = R
Напряжение подаваемое на светодиод минус макс. прямое напряжение светодиода и всё это делим на ток светодиода.
Для малых напряжений достаточно одного R1 удвоенного номинала. На 220 вольт желательно как на схеме - снижаем в два раза требуемую мощность и дополнительная защита, если схватитесь за лапу оптрона.
Решаю задачу - по датчику напряжения через прерывание вызывать обработчик при отключении AC220V, что-то вроде:
void AC_off_handler() {
// handler idea - hold the AC on and off time,set TRIGGER_PIN HIGH and disable TRIGGER_PIN state change,
AC_off_flag = true;
AC_change_time = CurrentMillis;
digitalWrite(TRIGGER_PIN, HIGH);
}
Вопрос - как в прерывании запретить изменение состояния TRIGGER_PIN в основном цикле? То есть можно остановить сам основной цикл while (AC_off_flag)
Но вдруг есть более изящный способ? В идеале игнорирование обращений digitialWrite while (AC_off_flag)?
Это как раз не изящный способ, но, конечно, рабочий, спасибо! Приходится перед каждым вызовом digitalWrite ставить проверку проверку AC off flag. К примеру (ниже) уже 2 раза в строках 13, 15.
void trigger_1 (uint8_t pusk_pin, uint32_t pusk_seconds, uint32_t duration) { // if time from RTC is within "pusk_seconds + longevity" pusk_pin is LOW. If trigger 2 has been started less than 30 secons ago - wait
uint32_t time_from_RTC = time_sec(); // seconds from the start of the day
if ((((pusk_seconds + duration) <= DAY_SECONDS) // cycle ends before midnight
&&(time_from_RTC >= pusk_seconds)
&&(time_from_RTC < (pusk_seconds + duration)))
||(((pusk_seconds + duration) > DAY_SECONDS) // cycle ends after midnight
&&((time_from_RTC >= pusk_seconds)
|| (time_from_RTC < (pusk_seconds + duration - DAY_SECONDS))))) {
if (digitalRead(pusk_pin)) {
if (digitalRead(TRIGGER2_PIN)) {
start_1_millis = CurrentMillis; // hold last trigger start time
if (!AC_off_flag) digitalWrite(pusk_pin, LOW);
}
else if ((CurrentMillis - start_2_millis) >= THRESHOLD * 1000 / DEBUG_TIME_MULTIPLIER) if (!AC_off_flag) digitalWrite(pusk_pin, LOW);
}
}
else if (!digitalRead(pusk_pin)) digitalWrite(pusk_pin, HIGH);
}
#include "Arduino.h"
#include "Alarm220.h"
using PAlarmFunc = void(*)(int);
volatile bool Tick220 = false; // было ли прерывание от 220
volatile uint32_t LastTick220 = 0; // когда было последний рас
PAlarmFunc OnAlarm = NULL; // функция, вызываемая при пропадании 220
void Alarm220(int); // prototype
void setup() {
OnAlarm = Alarm220;
}
void loop() {
if (Tick220) { // если было прерывание от 220
Tick220 = false; // то сбрасываем его флаг
return; // и уходим, аптамуш всё в порядке
}
// если нет, то
// смотрим сколько времени не было прерывания
uint32_t now = millis();
// если времени прошло меньше 25 мс, то тоже пока всё в порядке, выходим
if ((now - LastTick220) < 25) return;
// иначе тревога, 25 мс прерывания не было, значить 220 Вольт пропало
if (OnAlarm) OnAlarm(кодошибки);
abort();
}
ISR какой то там вектор{ // прерывание
Tick220 = true;
LastTick220 = millis();
}
void Alarm220(int alarmnum) {
// включай все что нужно при пропадании напряжения
}
nickol - у вас общая логика условия кривая. поэтому и "некрасиво". Насколько я понял, вы при каждом проходе через луп проверяете, находится ли время в заданном интервале - и если да - включаете нагрузку. Зачем так делать?
Вот представьте - вам надо зажечь свет в комнате и оставить его включенным на час. Вы же не станете весь этот час стоять у выключателя и непрерывно нажимать кнопку включения? Вы просто включите его и все... а через час выключите.
Вот и в светче надо сделать точно так же. Когда настает время pusk_seconds - включаем нагрузку, от этого момента отсчитываем duration и выключаем. И тогда эти зубодробительные условия станут значительно проще , а проверку на переход через полночь можно будет убрать вовсе.
Для новичков прикладываю схему и формулу для расчета резистора для диода оптопары (на схеме R1, R2 вот здесь у меня была ошибка, все остальное подключал правильно).
(U - UF) / IF = R
Напряжение подаваемое на светодиод минус макс. прямое напряжение светодиода и всё это делим на ток светодиода.
Для малых напряжений достаточно одного R1 удвоенного номинала. На 220 вольт желательно как на схеме - снижаем в два раза требуемую мощность и дополнительная защита, если схватитесь за лапу оптрона.
Что за изврат ? зачем прерывания ? Это лишнее
Берем любую зарядку от телефона и через резистор+ стабилизатор на 5в подаем на цифровой вход ардуины..
Ардуина в цикле уже проверяет наличие единички на входе и действует..
Обязателен ли резистор (ом?) и стабилитрон?? В БП зарядки вроде они и так стоят....
На ваше усмотрение, дополнительная защита от китайцев. Во многих китай-зарядках стабилизатора нет в принципе.
Если ардуина на 3.3В то схема такая:
БП (5В) -> зарядное для LiOn акк-ра -> диод Шоттки -> LiOn акк -> ардуина
До диода Шоттки можно брать напряжение.
https://ru.aliexpress.com/item/Active-Single-Phase-Voltage-Transformer-M...
Решение проблем
Здравствуйте!
Решаю задачу - по датчику напряжения через прерывание вызывать обработчик при отключении AC220V, что-то вроде:
Вопрос - как в прерывании запретить изменение состояния TRIGGER_PIN в основном цикле? То есть можно остановить сам основной цикл while (AC_off_flag)
Но вдруг есть более изящный способ? В идеале игнорирование обращений digitialWrite while (AC_off_flag)?
Спасибо!
Изящный способ конечно есть. Это условный оператор if.
Это как раз не изящный способ, но, конечно, рабочий, спасибо! Приходится перед каждым вызовом digitalWrite ставить проверку проверку AC off flag. К примеру (ниже) уже 2 раза в строках 13, 15.
я бы делал проще.
nickol - у вас общая логика условия кривая. поэтому и "некрасиво". Насколько я понял, вы при каждом проходе через луп проверяете, находится ли время в заданном интервале - и если да - включаете нагрузку. Зачем так делать?
Вот представьте - вам надо зажечь свет в комнате и оставить его включенным на час. Вы же не станете весь этот час стоять у выключателя и непрерывно нажимать кнопку включения? Вы просто включите его и все... а через час выключите.
Вот и в светче надо сделать точно так же. Когда настает время pusk_seconds - включаем нагрузку, от этого момента отсчитываем duration и выключаем. И тогда эти зубодробительные условия станут значительно проще , а проверку на переход через полночь можно будет убрать вовсе.
Спасибо, идея понятна! На досуге попробую реализовать.