• Уважаемые посетители сайта esp8266.ru!
    Мы отказались от размещения рекламы на страницах форума для большего комфорта пользователей.
    Вы можете оказать посильную поддержку администрации форума. Данные средства пойдут на оплату услуг облачных провайдеров для сайта esp8266.ru
  • Система автоматизации с открытым исходным кодом на базе 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 - входят в стандарт - и не надо радовать злобных троллей своей безграмотностью.
 
Сверху Снизу