Перейти к содержанию

Помощь с кодом


brusel

Рекомендуемые сообщения

Привет, помогите сделать так, чтобы по нажатию кнопки на несколько секунд появлялся высокий уровень на выходах LED и OUT.

#define F_CPU 1200000UL
#define OUT PB2
#define LED PB0
#define BUTTON1 PB4 
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  // Пины кнопок
  DDRB &= ~((1<<BUTTON1)); // входы
  PORTB |= (1<<BUTTON1); // подтянуты
  // Пин светодиода
  DDRB |= (1<<LED)|(1<<OUT); // выход
  PORTB &= ~((1<<LED)|(1<<OUT)); // выключен
  
    while (1) 
    {
        _delay_ms (50); // антидребезг
        if ( (PINB & (1<<BUTTON1)) == 0 )    // если нажата кнопка
          {
          PORTB |= ((1<<OUT)|(1<<LED));           //вкл
          }
          _delay_ms (1000);                       // пауза 
          PORTB &= ~((1<<OUT)|(1<<LED));          //выкл
    }
}

 

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Паузу в несколько секунд сделайте там же, где и "вкл" :) 

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Правильно? В протеусе вроде работает. Пауза где-то 7-8 сек.

#define F_CPU 1200000UL
#define OUT PB2
#define LED PB0
#define BUTTON1 PB4 
#include <avr/io.h>
#include <util/delay.h>

int main(void)
{
  // Пины кнопок
  DDRB &= ~((1<<BUTTON1)); // входы
  PORTB |= (1<<BUTTON1); // подтянуты
  // Пин светодиода
  DDRB |= (1<<LED)|(1<<OUT); // выход
  PORTB &= ~((1<<LED)|(1<<OUT)); // выключен
  
    while (1) 
    {
        _delay_ms (50); // антидребезг
        if ( (PINB & (1<<BUTTON1)) == 0 )    // если нажата кнопка
          {
          PORTB |= ((1<<OUT)|(1<<LED));           //вкл
          _delay_ms (45000);                       // пауза 
          }
          PORTB &= ~((1<<OUT)|(1<<LED));          //выкл         
    }
}

 

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

11 hours ago, brusel said:

Пауза где-то 7-8 сек.

Значит неправильно настройки заданы. Пауза должна быть 45 секунд. И вообще, на кой для такой простейшей задачи целый МК?

Ссылка на комментарий
Поделиться на другие сайты

Грубо говоря, есть. Опрос кнопок будет выполняться с интервалом в 50 мс, что не даст среагировать на дребезг. Правда, 50 мс вряд ли хватит, надо хотя бы 100 мс. Но делать антидребезг на задержках - костыль. Гораздо оптимальнее опрашивать состояние портов через промежутки времени. Допустим, 10 раз в секунду. Это отлично фильтрует дребезг.

Изменено пользователем BARS_
Ссылка на комментарий
Поделиться на другие сайты

Just now, IMXO said:

нет здесь никакого антидребезга!

Как же нет, если есть? Опрос состояния контактов кнопки с интервалами, заведомо больше, чем длительность дребезга - это и есть защита от последнего. Например, во многих проектах опрашивают пины кнопок по таймеру каждые 50-100 мс, сразу формируя коды нажатий - и никаких проблем не возникает и возникнуть не может!

При желании могу привести и диаграммы, но думаю, вы и сами понимаете, что поспешили с утверждением... Вот и ув. @BARS_ в ту же дуду...

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

4 hours ago, BARS_ said:

Пауза должна быть 45 секунд

А час задержки сможет эта функция отработать _delay_ms(3600000)?

Я не спец в AVR, но должен же быть какой-то предел, максимально возможная задержка у _delay_ms() ...

Ссылка на комментарий
Поделиться на другие сайты

Just now, Yurkin2015 said:

должен же быть какой-то предел, максимально возможная задержка у _delay_ms()

65536 мс

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

2 hours ago, ARV said:

Например, во многих проектах опрашивают пины кнопок по таймеру каждые 50-100 мс, сразу формируя коды нажатий - и никаких проблем не возникает и возникнуть не может!

может и возникает.

ситуация первая : кнопка не нажата, на линии проходит импульсная помеха в момент опроса пина = включение таймера

ситуация вторая: кнопка отпускается после окончания отсчета таймера , дребезг контактов  в момент опроса пина = ложный запуск таймера по отпусканию кнопки

так что нет у товарища антидребезга.

Ссылка на комментарий
Поделиться на другие сайты

Just now, Yurkin2015 said:

Это потому, что аргумент у _delay_ms() имеет размер 2 байта?

Нет, аргумент имеет тип float, но реализация сделана так, что более догую задержку не отрабатывает

Just now, IMXO said:

так что нет у товарища антидребезга

Мда...

Just now, IMXO said:

ситуация первая

Расскажите про алгоритм подавления дребезга для этой ситуации.

Наиболее оптимальный, как я понимаю, заключается в сравнении состояния пина ДО и ПОСЛЕ некоторой задержки. Если вам известен алгоритм 100% безошибочного обнаружения нажатий кнопок в условиях сильного дребезга и помех - хотел бы узнать о нем.

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

23 minutes ago, IMXO said:

ситуация первая

Это не антидребезг, а борьба с импульсными помехами на линии.

 

24 minutes ago, IMXO said:

ситуация вторая:

а с чего это вдруг отработается ложное повторное нажатие кнопки, если дребезг закончился за время меньшее, чем период опроса кнопки?

Ссылка на комментарий
Поделиться на другие сайты

дребезг это и есть импульсные помехи на линии.

причем здесь повторное нажатие , читайте не по диагонали

1 hour ago, ARV said:

 хотел бы узнать о нем.

я пользую примерно такой:

Spoiler

struct button_type {
  unsigned jitter         :8; // Для подавления дребезга
  unsigned old            :1; // Старое состояния пина
  unsigned new            :1; // Состояния пина
  unsigned pressed        :1; // Состояние кнопоки
  unsigned oldpressed     :1; // Старое состояния кнопоки
  unsigned justPressed    :1; // Кнопка только что нажата
  unsigned justReleased;  :1; // Кнопка только что отпущена
  unsigned     :1;
  unsigned     :1;
} m_Batton;

unsigned int tamer=0;
unsigned char task=0;

void Task_Button (void)
{
//**опрос кнопки
  m_Batton.new=0;
  if( (PINB & (1<<BUTTON1)) == 0 ) m_Batton.new=1;

//** подавление дребезга  
  if(m_Batton.new==m_Batton.old)
    { 
      if (m_Batton.jitter<5) 
        {m_Batton.jitter++;}
       else
        {m_Batton.pressed=m_Batton.new;} 
    }
   else
    {
      m_Batton.jitter=0;
    }
   m_Batton.old=m_Batton.new;

//*** фиксация фронтов нажатия/отпускания
  if(!m_Batton.oldpressed && m_Batton.pressed)
     {m_Batton.justPressed=1;}

  if(m_Batton.oldpressed && !m_Batton.pressed)
     {m_Batton.justReleased=1;} 
   m_Batton.oldpressed=m_Batton.pressed;
}

 

применительно к задаче ТС получим

Spoiler

int main(void)
{
  // Пины кнопок
  DDRB &= ~((1<<BUTTON1)); // входы
  PORTB |= (1<<BUTTON1); // подтянуты
  // Пин светодиода
  DDRB |= (1<<LED)|(1<<OUT); // выход
  PORTB &= ~((1<<LED)|(1<<OUT)); // выключен
  
    while (1) 
    {
        _delay_ms (1); // 
        Task_Button (); 

        if(task==2) {m_Batton.justPressed=0;} 
        
        if(m_Batton.justPressed)
          {
           task=1;
           m_Batton.justPressed=0;
          }

        switch (task) {
         case 0:
              PORTB &= ~((1<<OUT)|(1<<LED));          //выкл 
              break;
         case 1:
              PORTB |= ((1<<OUT)|(1<<LED));           //вкл
              tamer=0; 
              task=2
              break;
         case 2:
              if(tamer<45000)
                {
                  tamer++;
                } 
                else
                 {
                   task=0;
                 }    
              break;
        default:
             task=0;
        } 
        
    
    }
}

 

делай заменяем на системный тик 1мс и получаем сквозной, нигде не тормозящий код с возможность расширения на другие задачи.

если комментируем строку  if(task==2) {m_Batton.justPressed=0;} получаем таймер с перезапуском по фронту.

Ссылка на комментарий
Поделиться на другие сайты

Мда...

А я опрашиваю кнопки раз в 100 мс и ни разу не зафиксировал ложного срабатывания за примерно лет 15, как я стал так делать. И пропуска нажатия тоже не было, во всяком случае в те моменты, когда я это делал.

Что же не так со мной?!

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

2 hours ago, IMXO said:

кнопка отпускается после окончания отсчета таймера , дребезг контактов  в момент опроса пина = ложный запуск таймера по отпусканию кнопки

 

52 minutes ago, IMXO said:

читайте не по диагонали

Ну, батенька, специально для Вас разжую свой вопрос.

Состояние кнопки читается один раз во время дребезга. Возможно только два варианта.

Если прочитали состояние "нажато", то значит состояние кнопки не изменилось, как было нажато, так и осталось нажато. Прочитаем правильное установившееся состояние при следующем опросе, когда дребезг уже закончится.

Если прочитали "отпущено", то значит кнопка отпустилась. Так и останется отпущеной при следующем опросе.

Откуда "ложный запуск таймера" возьмётся?

 

Ссылка на комментарий
Поделиться на другие сайты

53 minutes ago, Yurkin2015 said:

Состояние кнопки читается один раз во время дребезга

а откуда ты знаешь, что чтение точно совпадает с дребезгом?

кнопка может быть нажата и между циклам чтения порта, и к следующему чтению дребезг уже закончится.

1 hour ago, ARV said:

А я опрашиваю кнопки раз в 100 мс и ни разу не зафиксировал ложного срабатывания за примерно лет 15, как я стал так делать. И пропуска нажатия тоже не было, во всяком случае в те моменты, когда я это делал.

а я опрашиваю кнопки раз в 1/3 секунды, и тоже никогда проблем не имел.

в принципе пропуск возможен - когда опрос попадет точно на разомкнутую цепь во время дребезга. и это вообще не горе, подержишь кнопку нажатой, пока она не сработает в следующем цикле опроса.

а еще можно сделать так - лет 20 с гаком я такой алгоритм подсмотрел у профессиональных программистов.

опрашиваем кнопки довольно часто и имеем на каждую кнопку свой счетчик нажатого состояния.

а потом в главном цикле проверяем счетчики кнопок.

например, опрашиваем через 20 мс., а главный цикл равен, допустим, 500 мс.

тогда при длительном нажатии кнопки за 500 мс счетчик насчитает 25.

но в главном цикле делаем проверку не на все 25, а, например, на 15. если счетчик насчитал 15 или больше, то считаем, что кнопка была нажата.

а если там меньше 15 - то считаем, кнопка не была нажата.

это самая надежная защита от дребезга, и также исключает пропуски, про которые я сказал выше в этом сообщении.

в своих первых проектах я сам применял этот алгоритм со счетчиками нажатого состояния кнопок. а потом решил, что мне достаточно однократной проверки кнопок.

Мудрость приходит вместе с импотенцией...

Когда на русском форуме переходят на Вы, в реальной жизни начинают бить морду.

Ссылка на комментарий
Поделиться на другие сайты

Один челдон утверждал, что по военной приемке читать состояние пина надо несколько раз. А чтобы не было импульсных помех на пине, то RC цепь и подтяжка. Можно применять как порознь, так и вместе.

Ссылка на комментарий
Поделиться на другие сайты

2 hours ago, Yurkin2015 said:

Ну, батенька, специально для Вас разжую свой вопрос. 

Состояние кнопки читается один раз во время дребезга. Возможно только два варианта.

Если прочитали состояние "нажато", то значит состояние кнопки не изменилось, как было нажато, так и осталось нажато. Прочитаем правильное установившееся состояние при следующем опросе, когда дребезг уже закончится.

1. покажите мне где в этом куске кода:

    while (1) 
    {
        _delay_ms (50); // антидребезг
        if ( (PINB & (1<<BUTTON1)) == 0 )    // если нажата кнопка
          {
          PORTB |= ((1<<OUT)|(1<<LED));           //вкл
          _delay_ms (45000);                       // пауза 
          }
          PORTB &= ~((1<<OUT)|(1<<LED));          //выкл         
    }

повторное чтение?

2. у ТС четко сформированы задача

On 24.07.2019 at 10:01, brusel said:

по нажатию кнопки на несколько секунд появлялся высокий уровень на выходах LED и OUT

читай по спадающему фронту на пине.  в коде выше  при удержании кнопки таймер работает в цикле:  работа 45сек/ пауза 50мс.

теперь, если кнопка будет отпущена в конце "работа" и в момент опроса пина при дребезге будет прочитан лог0 = будет перзапуск таймера.

так понятно или надо на картинках показывать?

1 hour ago, Starichok said:

в принципе пропуск возможен - когда опрос попадет точно на разомкнутую цепь во время дребезга. и это вообще не горе, подержишь кнопку нажатой, пока она не сработает в следующем цикле опроса. 

я об этом и говорил , но в случае задачи ТС это заранее расставленные грабли на плохо отлавливаемый баг в процессе работы.

1 hour ago, Starichok said:

а еще можно сделать так - лет 20 с гаком я такой алгоритм подсмотрел у профессиональных программистов.

опрашиваем кнопки довольно часто и имеем на каждую кнопку свой счетчик нажатого состояния.

а потом в главном цикле проверяем счетчики кнопок.

что собственно и делает код приведенный мной выше.

Ссылка на комментарий
Поделиться на другие сайты

11 minutes ago, IMXO said:

если кнопка будет отпущена в конце "работа" и в момент опроса пина при дребезге будет прочитан лог0

Это всего-навсего означает, что кнопку передержали более 45 секунд, и таймер пошёл на новый круг. При чём тут дребезг?

Точно такая же ситуация будет и при идеальной кнопке без дребезга. Продержите её на миллисекунду дольше, чем 45 сек, и таймер точно так же перезапустится.

Ссылка на комментарий
Поделиться на другие сайты

То, что топикстартер не корректно обрабатывает события нажатий, не означает, что его код чувствителен к дребезгу кнопки. 

Ранее я спрашивал: что я делаю не так, если делаю так же и не имею проблем? И не один я...

Если забанить всех, кто набрался смелости думать независимо, здорово будет на форуме - как на кладбище: тишина, птички поют...

Ссылка на комментарий
Поделиться на другие сайты

то что вы не видете/ не замечаете суслика не значит что его нет.

элементарная симуляция опроса кнопки

системный тик кнопки = 100мс

первое нажатие = 120мс

второе = 430мс

дребезг=20мс

1022800334___.png.471a10827eb239c83039c44ea9780430.png

куда потерялось нажатие

Ссылка на комментарий
Поделиться на другие сайты

1 hour ago, IMXO said:

куда потерялось нажатие

Никуда не потерялось - просто система не чувствует короткие нажатия. Опять, причем тут дребезг?

С идеальной кнопкой без дребезга тоже будут пропуски нажатий, если время нажатия меньше периода опроса кнопки.

Чтобы гарантировано не было пропусков нужно обеспечить время удержания кнопки дольше, чем период опроса плюс длительность "дребезга".

Вот увеличьте немного

1 hour ago, IMXO said:

первое нажатие = 121мс

и проверьте, есть ли суслик на самом деле.

Ссылка на комментарий
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • Релюхи не причём. При неисправности релюх симптомы были бы другие. И ИБП даже не клацает когда переходит в  "аварию".   Да. Аккум новый. Более того - 2 новых пробовал. И без АКБ тоже. Не влияет. Да мелкие особо не вздуваются ж. Хотя С21 под подозрением..   Спасибо. Буду иметь ввиду.
    • #include <Wire.h> #include <Oregon_TM.h> #include <BME280I2C.h> //////////////////////////////////////////////////////////////////////////////////////////////////////////// //Скетч для устройства, передающего данные датчика BME280 в формате Oregon Scientific THGN132N //Принципиальная схема прилагается. //Для работы необходима библиотека https://github.com/finitespace/BME280/ //Устройство работает от 3-ех пальчиковых батареек, для экономии электричества заливать скетч нужно через ISP //////////////////////////////////////////////////////////////////////////////////////////////////////////// //Также возможна передача данных в формате - THP (температура, влажность, давление, напряжение батареи) //Пример с приёмником поддерживает расшифоовку THP //////////////////////////////////////////////////////////////////////////////////////////////////////////// # define THGN_SEND 1 // Передавать ли данные в формате THGN132 # define THP_SEND 0 // Передавать ли данные в формате THP # define DEVICE_LOG 1 //Писать ли лог В Serial # define DONE_PIN 15 // вывод сигнала об окончании работы на таймер # define BME_WAIT 10 // Сколько мс ожидать датчик BME # define BATTERY_THR 3.5 // Порог напряжения для выставляения флага разряда батарейки (THGN) ///////////////////////////////////////////////////////////////////////////////////////////////// //Ниблы датчика THP //Во всех полях младшие ниблы идут вперёд!!! // 1-2 - тип (55) // 3 - канал (0-7) // 4-6 - (температура от -100С) * 10. Т.е. +25.1С = 1251 = 4E3h // 7-9 - Влажность *10 Т.е. 25.1% = 251 = 0FBh // 10-12 - (давление от 500ммртст) * 10. Т.е. 765мм = 2650 = A5Ah // 13-15 - данные с АЦП (A0) // 16-17 - CheckSUM // 18-19 - CRC8 (poly 0x07 start 0x00) ///////////////////////////////////////////////////////////////////////////////////////////////// Oregon_TM transmitter(4); BME280I2C bme; bool bme_present = false; float bme_temp(NAN), bme_hum(NAN), bme_pres(NAN); ///////////////////////////////////////////////////////////////////////////////////////////////// void setup() { digitalWrite(DONE_PIN, LOW); pinMode(DONE_PIN, OUTPUT); #ifdef DEVICE_LOG Serial.begin(115200); Serial.println("Waiting for BMEsensor..."); #endif //Обмен данными с BME////////////////////////////////// Wire.begin(); while(!bme.begin()) { if (millis() > BME_WAIT) break; } if (!bme.begin()) { #ifdef DEVICE_LOG Serial.println("No BME sensor found"); #endif bme_present = false; } else { switch(bme.chipModel()) { case BME280::ChipModel_BME280: bme_present = true; bme.read(bme_pres, bme_temp, bme_hum); #ifdef DEVICE_LOG Serial.println("Found BME280 sensor! Success."); Serial.print("Temperature = "); Serial.print(bme_temp, 1); Serial.println("C"); Serial.print("Humidity = "); Serial.print(bme_hum, 1); Serial.println("%"); Serial.print("Pressure = "); Serial.print(bme_pres * 0.75, 1); Serial.println("mmHg"); #endif break; default: #ifdef DEVICE_LOG Serial.println("Found UNKNOWN sensor! Error!"); #endif bme_present = false; } } //Напряжения батареи/////////////////////////////////////////// word battvotage = (word)(((float)(1.1 * 16368) / Vbg()) * 100); #ifdef DEVICE_LOG Serial.print("Battery voltage = "); Serial.println(battvotage,HEX); #endif //Подготовка и отправка данных THGN////////////////////////////////////// transmitter.protocol == 2; if (THGN_SEND) { transmitter.setType(THGN132); transmitter.setChannel(3); transmitter.setBatteryFlag(battvotage < BATTERY_THR); if (bme_present) { if (bme_hum > 98) bme_hum = 98; if (bme_hum < 2) bme_hum = 2; if (bme_temp > 70) bme_temp = 70; if (bme_temp < -50) bme_temp = -50; transmitter.setTemperature(bme_temp); transmitter.setHumidity(bme_hum); transmitter.setComfort(bme_temp, bme_hum); } else { transmitter.setTemperature(-49.9); transmitter.setHumidity(2); transmitter.setComfort(-49.9, 2); } transmitter.SendPacket(); } // Если отправляются оба формата пакетов, межу ними надо выдержать паузу if (THP_SEND && THGN_SEND) delay(100); //Подготовка и отправка данных THP////////////////////////////////////// if (THP_SEND) { transmitter.setType(THP); transmitter.setChannelTHP(1); transmitter.setBatteryTHP( battvotage); if (bme_present) { transmitter.setTemperatureTHP(bme_temp); transmitter.setHumidityTHP(bme_hum); transmitter.setPressureTHP(bme_pres * 0.75); // перевод Pa в mmHg } else { transmitter.setErrorTHP(); } transmitter.SendPacket(); } #ifdef DEVICE_LOG Serial.println(); Serial.print(millis()); Serial.println("ms"); Serial.println(); #endif //Команда на отключение питания digitalWrite(DONE_PIN, HIGH); } ///////////////////////////////////////////////////////////////////////////////////////////////// void loop(){} ///////////////////////////////////////////////////////////////////////////////////////////////// int Vbg() { ADMUX = (1<<REFS0)|(0<<REFS1)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(0<<MUX0); long buffersamp=0; for (int n=0x0; n<=0xff; n++ ) { ADCSRA = 0xc7; while (bit_is_set(ADCSRA,ADSC)); buffersamp += ADC; } buffersamp >>=4; //16368 full scale 14bit ADCSRA &= ~(1 << ADEN); // отключаем АЦП return buffersamp; } Вот код программы. Пробовал по разному и от 5в запитывал и всю систему от 3,3 в. Причем голая ардуинка с таймером работает в нормальном режиме некоторое время, но потом все равно слетает и начинает питать мк постоянно( Причем это происходит всегда через разный промежуток времени.
    • На фото может быть название , характеристики и т.д. И по этому фото я смогу выбрать такой же в инете.. самому мне не собрать..
    • А что даст фотка? Тот же щуп, только чуть крупнее и с проводами питания.
    • Для меня наверное лучше купить готовый.. цель повысить чувствительность до 1 mV.. Наверное на Авто стоит покупать , мне бы фотку какую нить..такого активного щупа..))
    • Так на схемах обозначается подключение к сети 220 В.
×
×
  • Создать...