• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь ESP-01. Отображения значения переменной на Web странице

bavspb

New member
А вот тут точно считать не будет. За одно срабатывание геркона насчитает сотню или тысячи, если не больше.
@nikolz вы правы, отвыкать я стал от Ардуино :)
А нет, АрдуиноИДЕ как всегда непредсказуема ;)
Вы правы при одиночном срабатывании геркона появляется значение с 6 нулями и если обновить страницу, то оно увеличивается само и без замыкания. А с чем это связано?

Вот, немного поправленный код

void loop() {

server.handleClient();
CounterState = digitalRead(CounterPin);

if (CounterState == LOW) { //замыкание геркона
Result=Result+1; // увеличиваем счет на единицу

}


}
 

bavspb

New member
Логика должна быть такой
1) Значение с пина сравнивается с флагом
2) если равны и флаг равен нулю то прибавляете 1
3) флаг меняете на противоположный
-------------
т е вы должны проверять на замыкание и размыкание геркона
при замыкании считать если надо число замыканий

Не совсем понял про флаг и как его реализовать.

Я делаю так:
1. Значение с пина заношу в переменную int CounterState.
2. Проверяю его на ноль(сработала ли кнопка/ геркон).
3. Если сработала, то в переменную int Result добавляю 1
4. Повторяю цикл снова.

Как здесь использовать флаг?
 

Сергей_Ф

Moderator
Команда форума
@bavspb флаг - это просто булевая переменная, но можно и int как у вас CounterState. Как использовать вам сказали. Вот замкнулся у вас геркон и цикл ходит кругами и прибавляет значение, а надо ждать пока не разомкнутся контакты, прежде чем дальше считать. Во флаге храните предыдущее состояния CounterState - если так проще понять.
 

bavspb

New member
@bavspb флаг - это просто булевая переменная, но можно и int как у вас CounterState. Как использовать вам сказали. Вот замкнулся у вас геркон и цикл ходит кругами и прибавляет значение, а надо ждать пока не разомкнутся контакты, прежде чем дальше считать. Во флаге храните предыдущее состояния CounterState - если так проще понять.
т.е. в конце цикла(после добавления единицы) проверять значение CounterState == HIGH?
 

Сергей_Ф

Moderator
Команда форума
@bavspb нет
Логика должна быть такой
1) Значение с пина сравнивается с флагом
2) если равны и флаг равен нулю то прибавляете 1
3) флаг меняете на противоположный
Может так нагляднее Эксперимент 14. Счётчик нажатий [Амперка / Вики]

Кстати, рекомендую считать не количество замыканий контактов, а их размыкания. Так и дребезг меньше влияет и сразу логика правильная в голове (и программе) складывается.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
@nikolz только надо Result не забыть объявить как volatile.
И процессор отдыхать все равно не будет, ему же надо в цикле крутить server.handleClient(). А код действительно меньше и изящнее.
 

Сергей_Ф

Moderator
Команда форума
Последнее редактирование:

rst

Member
в си на ESP работает без этого определения.
Т е это очевидно не есть догма
Очевидно здесь только ваше дилетантство. volatile для переменных, совместно используемых в ISR(-ах) и фоновой задаче(-ах) - обязательно.
ESP это или не ESP, а что-то другое - вообще не имеет никакого значения.
Учите матчасть(си)!
 

rst

Member
void pin_cb() { Result++; } // Обработчик прерывания
-------------------
и код меньше и процессор отдыхает
.....и глюков больше.
Тупо инкрементировать по фронту или спаду сигнала идущего с механического контакта - это значит просто гарантированно ловить несколько срабатываний от дребезга. Не важно - замыкание или размыкание ловится - дребезг всё равно будет.
Вроде как даже начинающие должны это знать.... o_O
 

rst

Member
Как по Вашему оптимизация испортит приведенный мною код?
Без volatile в цикле, ожидающем установки этой переменной в какое-то состояние, оптимизирующий компилятор имеет полное право перенести такую переменную в регистр. И цикл будет ждать вечно.
 

Сергей_Ф

Moderator
Команда форума
@nikolz немного эмоционально, но @rst ответил верно.
Не важно - замыкание или размыкание ловится - дребезг всё равно будет.
Я не говорил, что его не будет. Но его будет меньше и бороться с ним проще. Даже задержка на 5-20 мс может помочь. Для геркона уж точно.
 

rst

Member
Я не говорил, что его не будет. Но его будет меньше и бороться с ним проще. Даже задержка на 5-20 мс может помочь. Для геркона уж точно.
Конечно поможет. Только я в том посте комментировал конкретный пример nikolz с простым инкрементом по спаду, где никакой задержки вообще нет.
 

Сергей_Ф

Moderator
Команда форума
@nikolz если верить тому что написано в той статье, то надо не объявлять volatile int Result
а везде обращаться к ней как *(volatile int*)&Result
но сути это не меняет, надо оградить компилятор от возможности помещать данную переменную в регистры, иначе можно встрять в бесконечный цикл или не увидеть правильного вывода
 
  • Like
Реакции: rst

rst

Member
Дело в том, что в функции выполняется явное изменение Result++; Поэтому компилятор не будет помещать Result во флеш.
А именно это он и может всего-то cделать.
Во флешь??? :eek: И что - при каждом её инкременте (срабатывании прерывания) будет перешиваться флешь? :eek:
 

Сергей_Ф

Moderator
Команда форума
функции выполняется явное изменение Result++; Поэтому компилятор не будет помещать Result ва флеш.
надеюсь что последнее слово просто описка. По поводу явного изменения по ++, это вы немного погорячились. В любом случае будет выполнено загрузка значения из памяти в регистр и уж потом ее увеличение. Что скажет компилятору, что оптимизировать код основной программы при работе с Result не нужно? Вполне вероятно он решит что значение можно оставить в регистре до следующего вызова. Дальше при входе в процедуру прерывания произойдет сброс регистров в стэк, обработка прерывания и возврат с загрузкой регистров. Вот тут есть вероятность что значение Result окажется загружено из стэка, если оно было оптимизировано.
 

bavspb

New member
Попробовал через прерывание. Подключил к GPIO2 тактовую кнопку.

int CounterPin = 2;

void handleInterrupt() {
Result++;
} // если прерывание по нажатию кнопки срабатывает, то добавляем единицу

void setup(){
...
pinMode(CounterPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(CounterPin), handleInterrupt, FALLING);
...
}

void loop(){
server.handleClient(); // единственная функция
}

В результате, прерывание срабатывает, но подсчет в переменную Result идет очень странно:
1 нажатие - 1
2 нажатие - 2
3 нажатие - 3
4 нажатие - 4
5 нажатие - 6

и далее беспорядочно прибавляет то 2 то 3 то 5

Что не так ?
 

rst

Member
По делу тут уже сказана куча слов. Только что толку если вы читать не умеете?
 

Юрий Ботов

Moderator
Команда форума
volatile так же как register - входят в стандарт - и не надо радовать злобных троллей своей безграмотностью.
 
Сверху Снизу