Работа с кнопками. В помощь новичку.

Клапауций
Offline
Зарегистрирован: 10.02.2013

nestandart пишет:

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

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

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Вы это серьезно ?!

Ну тогда можно и про скорость движения электронов поговорить.

О каких промежуточных значениях вы говорите ? Скорость переключения от 0 до нужного напряжения определяется рскоростью распространения электрического поля в проводе.

Если углубляться в такие дебри то да, переключение происходит не мгновенно. Оно длятся несколько пикосекунд.

А теперь посмотрите ( в справочных материалах) сколько времени занимает опрос пина АЦП. 

Клапауций
Offline
Зарегистрирован: 10.02.2013

nestandart пишет:

О каких промежуточных значениях вы говорите ? Скорость переключения от 0 до нужного напряжения определяется рскоростью распространения электрического поля в проводе.

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

Chubaka
Offline
Зарегистрирован: 28.01.2014

Здравствуйте. Подскажите пожалуйста.

Есть резистивные кнопки. Подключены к аналоговому пину. Ардуино в качестве HID клавиатуры.

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

Не могу понять как сделать чтобы при одиночном нажатии отправлялось одно действиие а при удержании другое. Например кнопка "следующий трек". При одиночном нажатии отправляла Remote.next() (следующий трек), а при удержании постоянно отправляла Remote.forward() (перемотка).

Вот какой скетч сейчас.

int buttonPin=6; //пин для резистивных кнопок
int data;
int flag=0;

void setup()
{
 Keyboard.begin();
 Serial.begin(9600);
}

void loop()
{
 data=analogRead(buttonPin); //читаем значение нажатой кнопки
 Serial.println(data); //для определения кодов нажатых кнопок на мониторе порта
  
//кнопка громкости +
   if (data>=210 && data<=232 && flag==0)  // нажата кнопка
  {
   Remote.increase();
   Remote.clear();
   flag=1;
  }

//кнопка громкости -
   if (data>=460 && data<=488 && flag==0)  // нажата кнопка
  {
   Remote.decrease();
   Remote.clear();
   flag=1;
  }

//кнопка следующий трек
   if (data==0 && flag==0)  // нажата кнопка
  {
   Remote.next();
   Remote.clear();
   flag=1;
  }
  
//кнопка предидущий трек
   if (data>=76 && data<=92 && flag==0)  // нажата кнопка
  {
   Remote.previous();
   Remote.clear();
   flag=1;
  }
  
//кнопка приглушения звука
   if (data>=565 && data<=594 && flag==0)  // нажата кнопка
  {
   Remote.mute();
   Remote.clear();
   flag=1;
  }
  
//не нажата не одна из кнопок
   if (data>=950 && data<=960 && flag==1)
  {
   flag=0;
  }
}

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Делаете таймер , который при нажатии на кнопку  начинает отсчет времени и присваивает это значение переменной. При отпущеной кнопке переменная обнуляется. 

А потом отслеживаете значение переменной. Если время нажатия превысило пороговое значение - удержание кнопки. Если нет (обнулилось)  - короткое нажатие.

Chubaka
Offline
Зарегистрирован: 28.01.2014

nestandart пишет:

Делаете таймер , который при нажатии на кнопку  начинает отсчет времени и присваивает это значение переменной. При отпущеной кнопке переменная обнуляется. 

А потом отслеживаете значение переменной. Если время нажатия превысило пороговое значение - удержание кнопки. Если нет (обнулилось)  - короткое нажатие.

Спасибо!!! Почти всё получилось. Вот только при нажатии и удержании кнопки "следующий трек", сначало переключается трек а потом начинается перемотка. Т.е. выполняется и условие строки 063 и условие строки 070. С другими кнопками аналогичная ситуация. А как сделать что бы при удержании не выполнялось условие 063?


int buttonPin=6; //пин для резистивных кнопок
int data;
int flag=0;
long previousMillis = 0; 
int val=0; 


void setup()
{
 Keyboard.begin();
 Serial.begin(9600);
}

void loop()
{
 data=analogRead(buttonPin); //читаем значение нажатой кнопки
 Serial.println(data); //для определения кодов нажатых кнопок на мониторе порта
 
   if (data<=900) //если нажата любая из кнопок начинается отсчёт
  { 
      if (millis() -previousMillis >40)    
     { 
      previousMillis = millis();     
      val++; 
     } 
  } 
   else 
  { 
   val=0; 
  }
     
//кнопка громкости +
   if (data>=210 && data<=232 && flag==0 && val>=1 && val<=3)  //одиночное нажатие
  {
   Remote.increase(); //прибавить громкость на ед.
   Remote.clear();
   flag=1;
   val=0;
  }
   else if (data>=210 && data<=232 && val>=4)  // удержание
  {
   Remote.increase(); //прибавлять громкость до отпускания
   Remote.clear();
   val=0;
  }

//кнопка громкости -
   if (data>=460 && data<=488 && flag==0 && val>=1 && val<=3)  //одиночное нажатие
  {
   Remote.decrease(); //убавить громкость на ед.
   Remote.clear();
   flag=1;
   val=0;
  }
   else if (data>=460 && data<=488 && val>=4)  //удержание
  {
   Remote.decrease(); //убавлять громкость до отпускания
   Remote.clear();
   val=0;
  }

//кнопка следующий трек
   if (data==0 && flag==0 && val>=1 && val<=5)  //одиночное нажатие
  {
   Remote.next(); //следующий трек
   Remote.clear();
   flag=1;
   val=0;
  }
   else if (data==0 && val>=6)  //удержание
  {
   Remote.forward(); //перемотка вперёд
   Remote.clear();
   val=0;
  }
  
//кнопка предидущий трек
   if (data>=76 && data<=92 && flag==0 && val>=1 && val<=5)  //одиночное нажатие
  {
   Remote.previous(); //предидущий трек
   Remote.clear();
   flag=1;
   val=0;
  }
   else if (data>=76 && data<=92 && val>=6)  //удержание
  {
   Remote.rewind(); //перемотка назад
   Remote.clear();
   val=0;
  }
  
//кнопка приглушения звука
   if (data>=565 && data<=594 && flag==0)  //нажата кнопка
  {
   Remote.mute();
   Remote.clear();
   flag=1;
  }
  
//не нажата не одна из кнопок
   if (data>=950 && data<=960 && flag==1)
  {
   flag=0;
  }
}

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

 

В программу особо не вчитывался , но ...

Переделайте все конструкции if else if на просто if ( лучше вообще откажитесь от оператора else).  Возможно у вас конфликт по условиям if  else.

Примерно так.
//кнопка следующий трек
	   if (data==0 && flag==0 && val>=1 && val<=5)  //одиночное нажатие
	  {
	   Remote.next(); //следующий трек
	   Remote.clear();
	   flag=1;
	   val=0;
	  }
               if (data==0 && val>=6)  //удержание
	  {
	   Remote.forward(); //перемотка вперёд
	   Remote.clear();
	   val=0;
	  }
	   

И еще. Как вариант , перенесите скобку из строки 25 в самый низ.

Ход таймера маловат (40мс). Получается чтобы сработало одиночное нажатие нужно удерживать кнопку не более 120мс (неудобно).

Оптимальное время для одиночного нажатия 500-1000мс.

 

Я бы сделал отдельный таймер для каждой кнопки. 

 

kriss
Offline
Зарегистрирован: 24.01.2014

 

Прошу  программистов помочь в  очень простой для вас, практической задаче для уменьшения простоя лифта. Сегодня  лифты  напичканы электроникой, а элмеханик не всегда может локализовать неисправность – то ли электроника глючит (тогда жди пока наладчик приедет – бывает долго. Это я и есть)  или   в  шахте непорядок. У меня   есть самодельный стенд для полной проверки, собрал его на жесткой логике. Вот хочу для механиков собрать такую приблуду, чтобы меня  меньше дергали – старенький я и сами меньше в шахте ползали.

Для начала информация:

В шахте лифта и на кабине расположены  шунты, а на кабине -герконовые датчики. Основных датчиков три:  VN, TO и   VV.    (Дал им имена  для   скетча).                                                                                     По последовательности появления   этих сигналов ,   главный контроллер лифта определяет направление движения,  местоположение кабины и обеспечивает точную остановку в  датчике ТО.

                  VN -  TO -   VV    -вниз           VV -  TO -   VN    -вверх

Задача  :  собрать с помощью Ардуино эмулятор  движения кабины лифта для проверки  главного контроллера  в части работы узла местоположения кабины.   Датчики – это три светодиода VN, TO и   VV, подключенные к выходам 50,51 и 52    Они должны поочередно засвечиваться в зависимости от заданного направления.

Направление задают две кнопки  , подключенные на выходы 30 и 31.

 Собрал схемку – 3 светодиода с резисторами и две кнопки кподключил к МЕГА 2560, загрузил  свой примитивный скетч – последовательность работает,  но неправильно.  Просьба помочь  по двум вопросам: 

1. при снятии сигнала на входе, цикл продолжается , а нужна немедленная остановка.   И если он остановился, в момент, когда на выходе пина «1», то  выход должен остаться в этом состоянии (запомнить эту «1»).??

2. Другой цикл движения не знаю как вставить. ?

  // определяю назначение  выходов и входов

  int VN  =  51;   //датчик замедления вниз ( светодиод+резистор)

  int TO  =  50;   // датчик точной остановки

  int VV  =  52;   // датчик замедления вверх

  int pinN = 31;   // команда на включение привода кабины вниз          ( кнопка и резистор  дотяжки 15ком)                                                               

  int pinV = 30;   // команда на включение привода кабины вверх

  int valN=0 ; 

  int valV=0;

   void setup() {

   pinMode(VN , OUTPUT);

   pinMode(TO , OUTPUT);

   pinMode(VV , OUTPUT);   

   pinMode(pinN, INPUT);

   pinMode(pinV, INPUT);       

}

   void loop(){

   valN = digitalRead(pinN);

   valV = digitalRead(pinV);

  if (val == 1)                          //  поехали  вверх, поочередно включаем светодиоды. имитируем вход -выход шунта из датчика.  (потом эти выходы будут подключены ко входам проверяемого контроллера)

  {        

     digitalWrite(VN, 1);

     delay (2000);

     digitalWrite(VN, 0);

     digitalWrite(TO, 1);

     delay (2000);

     digitalWrite(TO, 0);       //понимаю, что это примитивно., но не знаю других способов, без delay

     digitalWrite(VV, 1);

     delay (2000);

     digitalWrite(VV, 0);  

  } else  {    

    digitalWrite(VN, 0);  // ЭТО ВЕРОЯТНО ЛИШНЕЕ?

    digitalWrite(TO, 0);

    digitalWrite(VV, 0);

  }}

 

второй цикл  хотел, но не знаю куда вставить        

******************************************

if (valV == 1)            //вниз  {        

     digitalWrite(VV, 1);     

     delay (2000);

     digitalWrite(VV, 0);

     digitalWrite(TO, 1);

     delay (2000);

     digitalWrite(TO, 0);

     digitalWrite(VN, 1);

     delay (2000);

     digitalWrite(VN, 0);

  

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

не в эту тему ;)

maksim
Offline
Зарегистрирован: 12.02.2012

Мега для таких целей ох как жирновато....

// определяю назначение  выходов и входов
#define VN    51   //датчик замедления вниз ( светодиод+резистор)
#define TO    50   // датчик точной остановки
#define VV    52   // датчик замедления вверх
#define pinN  31   // команда на включение привода кабины вниз          ( кнопка и резистор  дотяжки 15ком)                                                               
#define pinV  30   // команда на включение привода кабины вверх

byte state = 1; 

void setup() 
{
  pinMode(VN, OUTPUT);
  pinMode(TO, OUTPUT);
  pinMode(VV, OUTPUT);   
}

void loop()
{
  if(digitalRead(pinV))
  {
    state++;
    if(state == 4) state = 1;
    State(state);
  }
  
  if(digitalRead(pinN))
  {
    state--;
    if(state == 0) state = 3;
    State(state);
  }
}

void State(byte state)
{
  if(state == 1) digitalWrite(VV, 1); else digitalWrite(VV, 0); 
  if(state == 2) digitalWrite(TO, 1); else digitalWrite(TO, 0); 
  if(state == 3) digitalWrite(VN, 1); else digitalWrite(VN, 0);  
  delay (2000);
}

 

kriss
Offline
Зарегистрирован: 24.01.2014

 МАКСИМ! Спасибо большое - сразу заработало.  мне нужно время изучить,  как ВЫ сделали.

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

Это ведь начало задачи.    Буду  потом искат прогу для  подсчета  количества остановок по этим трем импульсам и вывода №этажа на семисегментный двустрочный индикатор.      Может сразу мне и подскажите где  посмотреть пример?

Заранее благодарю.

maksim
Offline
Зарегистрирован: 12.02.2012

kriss пишет:

где  посмотреть пример?

Нигде.

Chubaka
Offline
Зарегистрирован: 28.01.2014

nestandart пишет:

В программу особо не вчитывался , но ...

Переделайте все конструкции if else if на просто if ( лучше вообще откажитесь от оператора else).  Возможно у вас конфликт по условиям if  else. [/

И еще. Как вариант , перенесите скобку из строки 25 в самый низ.

Ход таймера маловат (40мс). Получается чтобы сработало одиночное нажатие нужно удерживать кнопку не более 120мс (неудобно).

Оптимальное время для одиночного нажатия 500-1000мс.

 

Я бы сделал отдельный таймер для каждой кнопки.

Перенёс скобку, else убрал, всё равно не получается(((

Есть у кого ещё идеи?

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

 

nestandart
nestandart аватар
Offline
Зарегистрирован: 15.06.2011

Как именно не получается ? Что происходит ?

Chubaka
Offline
Зарегистрирован: 28.01.2014

Всё так же как и было. При нажатии и удержании кнопки сначало проходит сигнал как при одиночном нажатии а потом как при удержании. Т.е. при нажатии идалнейшем удержании кнопки следующий трек отсылается сначала и remote.next и потом remote.forward (стр. 065, 072)

int buttonPin=6; //пин для резистивных кнопок
int data;
int flag=0;
long previousMillis = 0; 
int val=0; 

void setup()
{
 Keyboard.begin();
 Serial.begin(9600);
}

void loop()
{
 data=analogRead(buttonPin); //читаем значение нажатой кнопки
 Serial.println(data); //для определения кодов нажатых кнопок на мониторе порта
 
  if (data<=900) //если нажата любая из кнопок начинается отсчёт
  { 
    if (millis() -previousMillis >200)    
    { 
      previousMillis = millis();     
      val++; 

//кнопка громкости +
      if (data>=210 && data<=232 && flag==0 && val==1)  //одиночное нажатие
      {
      Remote.increase(); //прибавить громкость на ед.
      Remote.clear();
      flag=1;
      val=0;
      }
      if (data>=210 && data<=232 && val>=2)  // удержание
      {
      Remote.increase(); //прибавлять громкость до отпускания
      Remote.clear();
      val=0;
      }

//кнопка громкости -
      if (data>=460 && data<=488 && flag==0 && val>=1 && val<=3)  //одиночное нажатие
      {
      Remote.decrease(); //убавить громкость на ед.
      Remote.clear();
      flag=1;
      val=0;
      }
      if (data>=460 && data<=488 && val>=4)  //удержание
      {
      Remote.decrease(); //убавлять громкость до отпускания
      Remote.clear();
      val=0;
      }

//кнопка следующий трек
      if (data==0 && flag==0 && val==1)  //одиночное нажатие
      {
      Remote.next(); //следующий трек
      Remote.clear();
      flag=1;
      val=0;
      }
      if (data==0 && val>=2)  //удержание
      {
      Remote.forward(); //перемотка вперёд
      Remote.clear();
      val=0;
      }
  
//кнопка предидущий трек
      if (data>=76 && data<=92 && flag==0 && val>=1 && val<=5)  //одиночное нажатие
      {
      Remote.previous(); //предидущий трек
      Remote.clear();
      flag=1;
      val=0;
      }
      if (data>=76 && data<=92 && val>=6)  //удержание
      {
      Remote.rewind(); //перемотка назад
      Remote.clear();
      val=0;
      }
    
//кнопка приглушения звука
      if (data>=565 && data<=594 && flag==0)  //нажата кнопка
      {
      Remote.mute();
      Remote.clear();
      flag=1;
      val=0;
      }
    }
  } 
//не нажата не одна из кнопок
   if (data>=950 && data<=960 && flag==1)
  {
   flag=0;
  }
}

 

romeo_b
Offline
Зарегистрирован: 08.11.2013

Добрый вечер.

Подскажите  можно ли в матричной клавиатуре  к примеру 3 на 3,

сделать  событие при удержании одной  кнопки

 мне нужно плано увеличивать значение   set++  


#include <Keypad.h>

int set = 0;

const byte ROWS = 3; //four rows
const byte COLS = 3; //three columns
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'}

};
byte rowPins[ROWS] = {2, 3, 4}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 6, 7}; //connect to the column pinouts of the keypad

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){
  Serial.begin(9600);
}
  
void loop(){
  char key = keypad.getKey();
  
  if (key){
    Serial.println(key);
  }



// ?????

 if (key  ==  '1' )
 { set++;
    
 }
 
 
  if (key  ==  '2' )
 { set--;
    
 }
 

Serial.println(set);




}

в таком варианте  получается нужно все время нажимать на кнопку   а хочу чтоб при нажатии показания увеличивались 

Как это сделать?
Спасибо.

dimka
dimka аватар
Offline
Зарегистрирован: 21.09.2012

button switch Read boolean

// button switch boolean
const int buttonPin = 2; 
int Val;
boolean q;
void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT);   
}
void loop(){
  if (digitalRead(buttonPin) == q)
  {
    q=!q;
    Val++;
    delay(100);
    Serial.println(Val);
  }
}

 

iwizard7
iwizard7 аватар
Offline
Зарегистрирован: 30.04.2013

Всем привет! 

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

//////////Включаем и выключаем свет кнопкой///////////
  currentButton = debounce(lastButton);
  
 if (lastButton == LOW && currentButton == HIGH)
 {
   ledOn = !ledOn;
   }
 lastButton = currentButton;
digitalWrite(ledPin, ledOn);
 
то срабатывает код 
 if (RTC.hour >= 19 && RTC.hour <= 23) digitalWrite(ledPin, HIGH); //устанавливаем время и зажигаем светодиод
    else digitalWrite(ledPin, LOW); // тушим светодиод
 если же первый код не закомментирован то включение по часам не срабатывает

весь код целиком :

#include <DS1307new.h> // for clock
#include <Wire.h> // for i2c protocol
#include <OneWire.h> // for DS18B20
#include <LiquidCrystal_I2C.h> // for 1602
#include <SPI.h>
#include <Ethernet.h>
boolean lastButton = LOW; // переменная для хранения состояния кнопки
boolean ledOn = false;    //
boolean currentButton = LOW; //
float maxF=0, minF=212; //переменные для макс и мин температуры
OneWire  ds(6);  // on pin 10 (a 4.7K resistor is necessary)  
int ledPin = 8;  // pin for LED
int LedStatus = 0;   // показывает статус светодиода на страничке
int sensorPin = A0;  // датчик света
const int buttonPin = 2;      // номер входа, подключенный к кнопке
int buttonState = 0;          // переменная для хранения состояния кнопки
unsigned int sensorValue = 0; // цифровое значение фоторезистора
LiquidCrystal_I2C lcd(0x20,16,2); // 0x20 is adresss for LCC 16x2
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC адрес
IPAddress ip(192,168,2,120); // IP адрес
EthernetServer server(80);   // Порт WEB сервера
byte grad[8] = { // рисует значек градуса
  B01110,
  B10001,
  B10001,
  B01110,
  B00000,
  B00000,
  B00000,
};

int ics =0; //count number of sensor

void setup(){
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
   
  Serial.begin(9600);  

  lcd.init(); 
  lcd.backlight(); //backlight is now ON
  // set up the LCD's number of columns and rows: 
  lcd.createChar(0, grad);
  lcd.begin(16, 2);
  /* Print a logo message to the LCD.
   lcd.print("AQUACONTROLLER");  
   lcd.setCursor(0, 1);
   lcd.print("by iWizard");
   delay (2500);
   lcd.clear();
   */
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

}

//////////////////////DEBOUNCE//////////////////////
boolean debounce(boolean last)
{
boolean current = digitalRead(buttonPin);
if (last != current)
{
delay(5);
current = digitalRead(buttonPin);
}
return current;
}
////////////////////////////////////////////////////


void loop(){
  sensorValue = analogRead(sensorPin);  // считываем значение с фоторезистора 
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

  if ( !ds.search(addr)) {
    // lcd.clear();   
    lcd.setCursor(0, 1);
    //   lcd.print("doar ");
    //   lcd.print(ics);
    //  lcd.print(" senzor(i)");    
    ds.reset_search();
    ics=0;


    if (RTC.hour >= 19 && RTC.hour <= 23) digitalWrite(ledPin, HIGH); //устанавливаем время и зажигаем светодиод
    else digitalWrite(ledPin, LOW); // тушим светодиод

//////////Включаем и выключаем свет кнопкой///////////
   currentButton = debounce(lastButton);
  
 if (lastButton == LOW && currentButton == HIGH)
  {
   ledOn = !ledOn;
   }
 lastButton = currentButton;

digitalWrite(ledPin, ledOn);
///////////////////////////////////////////////////// 
///----------------------------- начало кода часов -----------------------------///

    RTC.getTime();
    if (RTC.hour < 10)                   
    {
      Serial.println();
      Serial.print("0");
      Serial.print(RTC.hour, DEC);
    }
    else
    {
      Serial.print(RTC.hour, DEC);
    }

    Serial.print(":");

    if (RTC.minute < 10) Serial.print("0");
    Serial.print(RTC.minute, DEC);

    Serial.print(":");
    if (RTC.second < 10) Serial.print("0");
    Serial.print(RTC.second, DEC);


    Serial.print(" ");
    if (RTC.day < 10) Serial.print("0");
    Serial.print(RTC.day, DEC);


    Serial.print("-");
    if (RTC.month < 10) Serial.print("0");
    Serial.print(RTC.month, DEC);  
    Serial.print("-");
    Serial.print(RTC.year, DEC);         
    Serial.print(" ");
    Serial.print("-");
    switch (RTC.dow)                     
{
    case 0: Serial.print("SUN "); break;
    case 1: Serial.print("MON "); break;
    case 2: Serial.print("TUE "); break;
    case 3: Serial.print("WED "); break;
    case 4: Serial.print("THU "); break;
    case 5: Serial.print("FRI "); break;
    case 6: Serial.print("SAT "); break;
}

Serial.print("Uptime: ");
Serial.print(millis()/60000);//Display the Uptime since last Start/Reset and System version.
Serial.print(" Min, ");
//int miliseconds = 9999999;
//printf("%d hours, %d minutes and %d seconds\n", (int) miliseconds / (1000 * 60 * 60), (int) miliseconds / (1000 * 60), (int) miliseconds / 1000);


    ics++; 

    ds.reset();
    ds.select(addr);
    ds.write(0x44, 1);        // start conversion, with parasite power on at the end

    delay(750);     // maybe 750ms is enough, maybe not
    // we might do a ds.depower() here, but the reset will take care of it.

    present = ds.reset();
    ds.select(addr);    
    ds.write(0xBE);         // Read Scratchpad

    for ( i = 0; i < 9; i++) {           // we need 9 bytes
      data[i] = ds.read();
    }
    // Convert the data to actual temperature
    // because the result is a 16 bit signed integer, it should
    // be stored to an "int16_t" type, which is always 16 bits
    // even when compiled on a 32 bit processor.
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
      raw = raw << 3; // 9 bit resolution default
      if (data[7] == 0x10) {
        // "count remain" gives full 12 bit resolution
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    } 
    else {
      byte cfg = (data[4] & 0x60);
      // at lower res, the low bits are undefined, so let's zero them
      if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
      //// default is 12 bit resolution, 750 ms conversion time
    }

 //   if (OneWire::crc8(addr, 7) != addr[7]) {
 //     lcd.print("CRC is not valid!");
 //     return;
 //   }

    celsius = (float)raw / 16.0;

    lcd.setCursor(0,0);
    lcd.print("Temp");
    lcd.print(" = ");
    lcd.print(celsius);
    lcd.write(byte(0));
    lcd.print("C");
    Serial.print(celsius);
    Serial.print("C, ");
    //вывод часов на дисплей//  
    lcd.setCursor(0, 1);
    if(RTC.hour<10)lcd.print(0);
    lcd.print(RTC.hour);

    lcd.print(":");
    //lcd.print( (RTC.second %2 )?" ":":"); //мигать двоеточием
    if(RTC.minute<10)lcd.print(0);
    lcd.print(RTC.minute);

    lcd.setCursor(10, 1); 
    switch (RTC.dow)                      // Friendly printout the weekday
    {
    case 0: lcd.print("SUN"); break;
    case 1: lcd.print("MON"); break;
    case 2: lcd.print("TUE"); break;
    case 3: lcd.print("WED"); break;
    case 4: lcd.print("THU"); break;
    case 5: lcd.print("FRI"); break;
    case 6: lcd.print("SAT"); break;
    }
    lcd.print("-"); 
    lcd.print(RTC.day);
  Serial.print("Light Sensor: ");   
  Serial.print(sensorValue, DEC);     // вывод данных с фоторезистора (0-1024)
  Serial.println("");                 // возврат каретки 

    // listen for incoming clients
    EthernetClient client = server.available();
    if (client) {
      Serial.println("new client");
      // an http request ends with a blank line
      boolean currentLineIsBlank = true;
      while (client.connected()) {
        if (client.available()) {
          char c = client.read();
          Serial.write(c);
          // if you've gotten to the end of the line (received a newline
          // character) and the line is blank, the http request has ended,
          // so you can send a reply
          //if (c == '\n' && currentLineIsBlank) {
            // send a standard http response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("<head> ");
            client.println("<meta http-equiv=Content-Type content=text/html; charset=utf-8/>");
            client.println("<title> Arduino :: Акваконтролеер</title>");
            client.println("</head> ");
            client.println("<body bgcolor=\"#9bbad6\">"); // цвет фона
            client.println("Connection: close");  // the connection will be closed after completion of the response
            client.println("Refresh: 10");  // refresh the page automatically every 5 sec
            client.println();
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            client.println("<center>");
            // output the value of each analog input pin
            for (int analogChannel = 0; analogChannel < 1; analogChannel++) {
              int sensorReading = analogRead(analogChannel);
             client.println("<H1>");
              client.print(RTC.hour, DEC);
              client.print(":");
              if (RTC.minute < 10) client.print("0");
              client.print(RTC.minute, DEC);

              client.println("<br>");
              client.println("</h1>");
            client.println("<h2>");
              if (RTC.day < 10) client.print("0");
              client.print(RTC.day, DEC);


              client.print(" ");
             // if (RTC.month < 10) client.print("0");
             // client.print(RTC.month, DEC);
              switch (RTC.month)                     
              {
              case 1: client.print("Января"); break;
              case 2: client.print("Февраля"); break;
              case 3: client.print("Марта"); break;
              case 4: client.print("Апреля"); break;
              case 5: client.print("Мая"); break;
              case 6: client.print("Июня"); break;
              case 7: client.print("Июля"); break;
              case 8: client.print("Августа"); break;
              case 9: client.print("Сентября"); break;
              case 10: client.print("Октября"); break;
              case 11: client.print("Ноября"); break;
              case 12: client.print("Декабря"); break;
}            
              client.print(" ");
              client.print(RTC.year, DEC);         
              client.print(" ");
              client.print(",");
              switch (RTC.dow)                     
{
              case 0: client.print("Воскресенье"); break;
              case 1: client.print("Понедельник"); break;
              case 2: client.print("Вторник"); break;
              case 3: client.print("Среда"); break;
              case 4: client.print("Четверг"); break;
              case 5: client.print("Пятница"); break;
              case 6: client.print("Суббота"); break;
}
              client.println("</h2>");
              client.println("<br>");
                    client.println("<h3>");
              client.print("Температура");
              client.print(" = ");
              client.print(celsius);
              client.write(byte(0));
              client.print("°C");
                 client.println("</h3>");
              client.print(", ");
           
              if (celsius>maxF) {maxF=celsius;}  //check for max temp
  	if (celsius<minF) {minF=celsius;}  //check for min temp
  	client.print("Макс=");
  	client.print(maxF);
        client.print("°C ");
  	client.print("Мин=");
  	client.print(minF);
  	client.print("°C ");
        client.print(", Датчик№");
        client.print(ics); //показывает номер датчика
client.println("<br>");
 if ( digitalRead(ledPin) == HIGH ) {

      client.print ("Подсветка Включена");

  }
  if ( digitalRead(ledPin) == LOW ) {

      client.print ("Подсветка Выключена");

}
client.println("<br>");
client.print("Уровень света:");
client.print(sensorValue);
client.println("<br>");
client.print("Uptime: ");
client.print(millis()/60000);//Display the Uptime since last Start/Reset and System version.
client.print(" Min");
 
   //     client.print("Uptime: ");
   // client.println(uptime/60000);
       client.println("<br>");
       client.print("IP адрес: ");
       client.print(Ethernet.localIP());
            client.println("<br>");
             client.print("Ver. v 0.0.6 ");





}
            client.println("</center>");
            client.println("</html>");
            break;

  }
}

      delay(500);
      client.stop();
      Serial.println("client disonnected");
    }
  }
}

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

Ошибка в логике.
Допустим, сейчас 20 часов. Свет автоматически включается (строка 97). И тут же гасится (строка 109, ledOn в состоянии low). Естественно, реле не успевает отработать за эти микросекунды, поэтому визуально ничего не происходит.
По этой же причине днём не удастся включить свет кнопкой - он тут же будет гаситься, потому что часы говорят: "День. Пин должен быть в Low".

iwizard7
iwizard7 аватар
Offline
Зарегистрирован: 30.04.2013

Tomasina пишет:
Ошибка в логике. Допустим, сейчас 20 часов. Свет автоматически включается (строка 97). И тут же гасится (строка 109, ledOn в состоянии low). Естественно, реле не успевает отработать за эти микросекунды, поэтому визуально ничего не происходит. По этой же причине днём не удастся включить свет кнопкой - он тут же будет гаситься, потому что часы говорят: "День. Пин должен быть в Low".

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

jane Jack
Offline
Зарегистрирован: 08.10.2013

может как то так ловить?



#include <DS1307new.h> // for clock
#include <Wire.h> // for i2c protocol
#include <OneWire.h> // for DS18B20
#include <LiquidCrystal_I2C.h> // for 1602
#include <SPI.h>
#include <Ethernet.h>
boolean lastButton = LOW; // переменная для хранения состояния кнопки
boolean ledOn = false;    //
boolean currentButton = LOW; //
float maxF=0, minF=212; //переменные для макс и мин температуры
OneWire  ds(6);  // on pin 10 (a 4.7K resistor is necessary)  
int ledPin = 8;  // pin for LED
int LedStatus = 0;   // показывает статус светодиода на страничке
int sensorPin = A0;  // датчик света
const int buttonPin = 2;      // номер входа, подключенный к кнопке
int buttonState = 0;          // переменная для хранения состояния кнопки
unsigned int sensorValue = 0; // цифровое значение фоторезистора
LiquidCrystal_I2C lcd(0x20,16,2); // 0x20 is adresss for LCC 16x2
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // MAC адрес
IPAddress ip(192,168,2,120); // IP адрес
EthernetServer server(80);   // Порт WEB сервера
byte grad[8] = { // рисует значек градуса
  B01110,
  B10001,
  B10001,
  B01110,
  B00000,
  B00000,
  B00000,
};

int ics =0; //count number of sensor

void setup(){
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
   
  Serial.begin(9600);  

  lcd.init(); 
  lcd.backlight(); //backlight is now ON
  // set up the LCD's number of columns and rows: 
  lcd.createChar(0, grad);
  lcd.begin(16, 2);
  /* Print a logo message to the LCD.
   lcd.print("AQUACONTROLLER");  
   lcd.setCursor(0, 1);
   lcd.print("by iWizard");
   delay (2500);
   lcd.clear();
   */
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

}

//////////////////////DEBOUNCE//////////////////////
boolean debounce(boolean last)
{
boolean current = digitalRead(buttonPin);
if (last != current)
{
delay(5);
current = digitalRead(buttonPin);
}
return current;
}
////////////////////////////////////////////////////


void loop(){
  sensorValue = analogRead(sensorPin);  // считываем значение с фоторезистора 
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

  if ( !ds.search(addr)) {
    // lcd.clear();   
    lcd.setCursor(0, 1);
    //   lcd.print("doar ");
    //   lcd.print(ics);
    //  lcd.print(" senzor(i)");    
    ds.reset_search();
    ics=0;


    if (RTC.hour == 19 && RTC.minute == 0 && RTC.second == 0) ledOn = true; //устанавливаем время и включаем свет
    if (RTC.hour == 23 && RTC.minute == 0 && RTC.second == 0) ledOn = false; // устанавливаем время и выключаем свет

//////////Включаем и выключаем свет кнопкой///////////
   currentButton = debounce(lastButton);
  
 if (lastButton == LOW && currentButton == HIGH)
  {
   ledOn = !ledOn;
   }
 lastButton = currentButton;

digitalWrite(ledPin, ledOn);
///////////////////////////////////////////////////// 
///----------------------------- начало кода часов -----------------------------///

    RTC.getTime();
    if (RTC.hour < 10)                   
    {
      Serial.println();
      Serial.print("0");
      Serial.print(RTC.hour, DEC);
    }
    else
    {
      Serial.print(RTC.hour, DEC);
    }

    Serial.print(":");

    if (RTC.minute < 10) Serial.print("0");
    Serial.print(RTC.minute, DEC);

    Serial.print(":");
    if (RTC.second < 10) Serial.print("0");
    Serial.print(RTC.second, DEC);


    Serial.print(" ");
    if (RTC.day < 10) Serial.print("0");
    Serial.print(RTC.day, DEC);


    Serial.print("-");
    if (RTC.month < 10) Serial.print("0");
    Serial.print(RTC.month, DEC);  
    Serial.print("-");
    Serial.print(RTC.year, DEC);         
    Serial.print(" ");
    Serial.print("-");
    switch (RTC.dow)                     
{
    case 0: Serial.print("SUN "); break;
    case 1: Serial.print("MON "); break;
    case 2: Serial.print("TUE "); break;
    case 3: Serial.print("WED "); break;
    case 4: Serial.print("THU "); break;
    case 5: Serial.print("FRI "); break;
    case 6: Serial.print("SAT "); break;
}

Serial.print("Uptime: ");
Serial.print(millis()/60000);//Display the Uptime since last Start/Reset and System version.
Serial.print(" Min, ");
//int miliseconds = 9999999;
//printf("%d hours, %d minutes and %d seconds\n", (int) miliseconds / (1000 * 60 * 60), (int) miliseconds / (1000 * 60), (int) miliseconds / 1000);


    ics++; 

    ds.reset();
    ds.select(addr);
    ds.write(0x44, 1);        // start conversion, with parasite power on at the end

    delay(750);     // maybe 750ms is enough, maybe not
    // we might do a ds.depower() here, but the reset will take care of it.

    present = ds.reset();
    ds.select(addr);    
    ds.write(0xBE);         // Read Scratchpad

    for ( i = 0; i < 9; i++) {           // we need 9 bytes
      data[i] = ds.read();
    }
    // Convert the data to actual temperature
    // because the result is a 16 bit signed integer, it should
    // be stored to an "int16_t" type, which is always 16 bits
    // even when compiled on a 32 bit processor.
    int16_t raw = (data[1] << 8) | data[0];
    if (type_s) {
      raw = raw << 3; // 9 bit resolution default
      if (data[7] == 0x10) {
        // "count remain" gives full 12 bit resolution
        raw = (raw & 0xFFF0) + 12 - data[6];
      }
    } 
    else {
      byte cfg = (data[4] & 0x60);
      // at lower res, the low bits are undefined, so let's zero them
      if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
      else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
      else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
      //// default is 12 bit resolution, 750 ms conversion time
    }

 //   if (OneWire::crc8(addr, 7) != addr[7]) {
 //     lcd.print("CRC is not valid!");
 //     return;
 //   }

    celsius = (float)raw / 16.0;

    lcd.setCursor(0,0);
    lcd.print("Temp");
    lcd.print(" = ");
    lcd.print(celsius);
    lcd.write(byte(0));
    lcd.print("C");
    Serial.print(celsius);
    Serial.print("C, ");
    //вывод часов на дисплей//  
    lcd.setCursor(0, 1);
    if(RTC.hour<10)lcd.print(0);
    lcd.print(RTC.hour);

    lcd.print(":");
    //lcd.print( (RTC.second %2 )?" ":":"); //мигать двоеточием
    if(RTC.minute<10)lcd.print(0);
    lcd.print(RTC.minute);

    lcd.setCursor(10, 1); 
    switch (RTC.dow)                      // Friendly printout the weekday
    {
    case 0: lcd.print("SUN"); break;
    case 1: lcd.print("MON"); break;
    case 2: lcd.print("TUE"); break;
    case 3: lcd.print("WED"); break;
    case 4: lcd.print("THU"); break;
    case 5: lcd.print("FRI"); break;
    case 6: lcd.print("SAT"); break;
    }
    lcd.print("-"); 
    lcd.print(RTC.day);
  Serial.print("Light Sensor: ");   
  Serial.print(sensorValue, DEC);     // вывод данных с фоторезистора (0-1024)
  Serial.println("");                 // возврат каретки 

    // listen for incoming clients
    EthernetClient client = server.available();
    if (client) {
      Serial.println("new client");
      // an http request ends with a blank line
      boolean currentLineIsBlank = true;
      while (client.connected()) {
        if (client.available()) {
          char c = client.read();
          Serial.write(c);
          // if you've gotten to the end of the line (received a newline
          // character) and the line is blank, the http request has ended,
          // so you can send a reply
          //if (c == '\n' && currentLineIsBlank) {
            // send a standard http response header
            client.println("HTTP/1.1 200 OK");
            client.println("Content-Type: text/html");
            client.println("<head> ");
            client.println("<meta http-equiv=Content-Type content=text/html; charset=utf-8/>");
            client.println("<title> Arduino :: Акваконтролеер</title>");
            client.println("</head> ");
            client.println("<body bgcolor=\"#9bbad6\">"); // цвет фона
            client.println("Connection: close");  // the connection will be closed after completion of the response
            client.println("Refresh: 10");  // refresh the page automatically every 5 sec
            client.println();
            client.println("<!DOCTYPE HTML>");
            client.println("<html>");
            client.println("<center>");
            // output the value of each analog input pin
            for (int analogChannel = 0; analogChannel < 1; analogChannel++) {
              int sensorReading = analogRead(analogChannel);
             client.println("<H1>");
              client.print(RTC.hour, DEC);
              client.print(":");
              if (RTC.minute < 10) client.print("0");
              client.print(RTC.minute, DEC);

              client.println("<br>");
              client.println("</h1>");
            client.println("<h2>");
              if (RTC.day < 10) client.print("0");
              client.print(RTC.day, DEC);


              client.print(" ");
             // if (RTC.month < 10) client.print("0");
             // client.print(RTC.month, DEC);
              switch (RTC.month)                     
              {
              case 1: client.print("Января"); break;
              case 2: client.print("Февраля"); break;
              case 3: client.print("Марта"); break;
              case 4: client.print("Апреля"); break;
              case 5: client.print("Мая"); break;
              case 6: client.print("Июня"); break;
              case 7: client.print("Июля"); break;
              case 8: client.print("Августа"); break;
              case 9: client.print("Сентября"); break;
              case 10: client.print("Октября"); break;
              case 11: client.print("Ноября"); break;
              case 12: client.print("Декабря"); break;
}            
              client.print(" ");
              client.print(RTC.year, DEC);         
              client.print(" ");
              client.print(",");
              switch (RTC.dow)                     
{
              case 0: client.print("Воскресенье"); break;
              case 1: client.print("Понедельник"); break;
              case 2: client.print("Вторник"); break;
              case 3: client.print("Среда"); break;
              case 4: client.print("Четверг"); break;
              case 5: client.print("Пятница"); break;
              case 6: client.print("Суббота"); break;
}
              client.println("</h2>");
              client.println("<br>");
                    client.println("<h3>");
              client.print("Температура");
              client.print(" = ");
              client.print(celsius);
              client.write(byte(0));
              client.print("°C");
                 client.println("</h3>");
              client.print(", ");
           
              if (celsius>maxF) {maxF=celsius;}  //check for max temp
  	if (celsius<minF) {minF=celsius;}  //check for min temp
  	client.print("Макс=");
  	client.print(maxF);
        client.print("°C ");
  	client.print("Мин=");
  	client.print(minF);
  	client.print("°C ");
        client.print(", Датчик№");
        client.print(ics); //показывает номер датчика
client.println("<br>");
 if ( digitalRead(ledPin) == HIGH ) {

      client.print ("Подсветка Включена");

  }
  if ( digitalRead(ledPin) == LOW ) {

      client.print ("Подсветка Выключена");

}
client.println("<br>");
client.print("Уровень света:");
client.print(sensorValue);
client.println("<br>");
client.print("Uptime: ");
client.print(millis()/60000);//Display the Uptime since last Start/Reset and System version.
client.print(" Min");
 
   //     client.print("Uptime: ");
   // client.println(uptime/60000);
       client.println("<br>");
       client.print("IP адрес: ");
       client.print(Ethernet.localIP());
            client.println("<br>");
             client.print("Ver. v 0.0.6 ");





}
            client.println("</center>");
            client.println("</html>");
            break;

  }
}

      delay(500);
      client.stop();
      Serial.println("client disonnected");
    }
  }
}
leshak
Offline
Зарегистрирован: 29.09.2011

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

iwizard7
iwizard7 аватар
Offline
Зарегистрирован: 30.04.2013

leshak пишет:

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

Извиняюсь, не хотел никого напугать :))) просто я сам еще новичек в общении с ардуино, и потребовался совет именно по кнопке

jane Jack
Offline
Зарегистрирован: 08.10.2013

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

leshak
Offline
Зарегистрирован: 29.09.2011

nestandart пишет:

Очень не советую использовать функцию pulseIn для данных целей (да и вообще не советую).

Потому что эта функция использует все программные таймеры ардуино.
С функцией pulseIn НЕ будут работать
Tone()
Millis()
analogWrite()
Так же не будут работать сервоприводы.

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

Вообщем откуда взялась идея что " эта функция использует все программные таймеры ардуино", со всемы вытекающими из этого ужасами? В документации об этом ни слова. Да и зачем ей могли понадобится "все програмные таймеры?"  (ну хотя-бы исходи из логики что на разных дуинах и разное кол-во, а работает она на всех).

Заглянул в ее исходник (вдруг дока не полна):

unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{
	// cache the port and bit of the pin in order to speed up the
	// pulse width measuring loop and achieve finer resolution.  calling
	// digitalRead() instead yields much coarser resolution.
	uint8_t bit = digitalPinToBitMask(pin);
	uint8_t port = digitalPinToPort(pin);
	uint8_t stateMask = (state ? bit : 0);
	unsigned long width = 0; // keep initialization out of time critical area
	
	// convert the timeout from microseconds to a number of times through
	// the initial loop; it takes 16 clock cycles per iteration.
	unsigned long numloops = 0;
	unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
	
	// wait for any previous pulse to end
	while ((*portInputRegister(port) & bit) == stateMask)
		if (numloops++ == maxloops)
			return 0;
	
	// wait for the pulse to start
	while ((*portInputRegister(port) & bit) != stateMask)
		if (numloops++ == maxloops)
			return 0;
	
	// wait for the pulse to stop
	while ((*portInputRegister(port) & bit) == stateMask) {
		if (numloops++ == maxloops)
			return 0;
		width++;
	}

	// convert the reading to microseconds. The loop has been determined
	// to be 20 clock cycles long and have about 16 clocks between the edge
	// and the start of the loop. There will be some error introduced by
	// the interrupt handlers.
	return clockCyclesToMicroseconds(width * 21 + 16); 
}

Никаких таймеров не видно. Обычная блокирующая функция. "Зла" от нее, ровно столько же сколько и от delay(). Поэтому можно согласится что "нежелательно использовать" (когда во время ожидания импульса нужно еще чем-нибудь заниматся), но этим ее "нежелательность" и ограничивается. По большому счету это и есть тот же самый delay(), только который прерывается состоянием пина и может сказать "когда его прервали".

mikov
Offline
Зарегистрирован: 01.05.2013

Добрый день !  Прошу помощи,так как в программировании совсем новичок. Пытаюсь сделать подобие умного дома, необходимо чтобы выключатель мог поочередно включать несколько разных светильников, воспользовался вот этим примером

int regim=1; 
 int flag=0; 

 void setup()   
 { 
 pinMode(4,OUTPUT);    
 pinMode(5,OUTPUT);    
       
 } 

 void loop() 

 { 
       
     if(digitalRead(12)==HIGH&&flag==0)//если кнопка нажата   
     // и перемення flag равна 0 , то ... 
     { 
       regim++;   
       flag=1; 
         
        //это нужно для того что бы с каждым нажатием кнопки 
        //происходило только одно действие 
        // плюс защита от "дребезга"  100% 
          
        if(regim>4)//ограничим количество режимов 
        { 
          regim=1;//так как мы используем только одну кнопку, 
                    // то переключать режимы будем циклично 
        } 
       
     } 
       
      if(digitalRead(12)==LOW&&flag==1)//если кнопка НЕ нажата 
     //и переменная flag равна - 1 ,то ... 
     { 
          
        flag=0;//обнуляем переменную "knopka" 
     } 
      
       
       
    if(regim==1)//первый режим 
    { 
      digitalWrite(4,LOW);//выключаем все светодиоды 
      digitalWrite(5,LOW); 
        
        
      //здесь может быть любое ваше действие 
    } 
    if(regim==2)//второй режим 
    { 
      digitalWrite(4,HIGH);//включае красный светодиод 
      digitalWrite(5,LOW); 
        
      //здесь может быть любое ваше действие 
    } 
      
    if(regim==3)//третий режим 
    { 
        
      digitalWrite(5,HIGH);//включае зеленый светодиод 
      digitalWrite(4,LOW); 
        
        
      //здесь может быть любое ваше действие 
    } 
      
    if(regim==4)//четвертый режим 
    { 
        
      digitalWrite(4,HIGH);//включаем светодиоды одновременно 
      digitalWrite(5,HIGH); 
      //здесь может быть любое ваше действие 
    } 
      
 } 

при работе с кнопкой на макетной плате все работает ок, но при подключении кнопочного выключателя проявляется дребезг и система работает неустойчиво. Подскажите пожалуйста, как повысить надежность срабатывания и ввести в этот скетч кнопку "выключить всё" ? Заранее благодарю !!!

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

vvadim
Offline
Зарегистрирован: 23.05.2012
 
Так у вас в первом режиме светики не горят
wOOlf
Offline
Зарегистрирован: 21.04.2014

Подскажите каким образом можно подсчитать количество нажатий кнопки в течении времени, т.е для выполнения действия необходимо трижды нажать на кнопку в течении 3 секунд. причем таймер запускается первым нажатем этой же кнопки.
если подумать:
 

const int ledPin =  5;      // the number of the LED pin
#define unlock 3               //пин сигнала unlock

int ledState = LOW;             
unsigned long previousMillis = 0;
unsigned long currentMillis;
long interval = 2000;          
int i=0;
void setup() {
    pinMode(ledPin, OUTPUT);      
}

void loop()
  {
    if(digitalRead(3)==HIGH)//
  { i=i++;
  delay(500);
  currentMillis = millis();
  previousMillis = currentMillis;//запоминаем момент первого нажатия
  while(currentMillis - previousMillis < interval)// считаем 3 секунды 
    {currentMillis = millis();
      if (digitalRead(3)==HIGH)
     {i=i++;
     delay (500);
     }
     }
    if (i==3)
    {digitalWrite(ledPin, HIGH);
    i=0;
    }
    else 
    {digitalWrite(ledPin, LOW);
     i=0;
    }

 

Gvined
Offline
Зарегистрирован: 25.07.2014

вариан с переменной flag. удачно проходит компиляцию а на ардуине не работает диод горит в самом начале и при нажатии на кнопку загорается чуть ярче почему ?

01 int flag=0;
02  
03 void setup()   
04 {
05        
06     pinMode(13, OUTPUT);        
07       
08         
09 }
10  
11 void loop()
12  
13 {
14         
15      if(digitalRead(8)==HIGH&&flag==0)//если кнопка нажата   
16      // и перемення flag равна 0 , то ...
17      {
18            
19        digitalWrite(13,!digitalRead(13));
20        flag=1;
21         //это нужно для того что бы с каждым нажатием кнопки
22         //происходило только одно действие
23         // плюс защита от "дребезга"  100%
24         
25      }
26         
27       if(digitalRead(8)==LOW&&flag==1)//если кнопка НЕ нажата
28      //и переменная flag равна - 1 ,то ...
29      {
30            
31         flag=0;//обнуляем переменную flag
32      }
33 }

 

подключил кнопку с одного конца на 5v ,а со второго на 8 вход и второй провод от этой же лапки кнопки через резистор на земле

пробовал даже ставить перемычку на 8 вход и GND и светодиод горит в самом начале что не так ?

Oleg.L.
Offline
Зарегистрирован: 19.08.2014

Здравствуйте, Дмитрий. Я Вас заочно знаю по многочисленным роликам в You Tube с Вашим опытом не откажите в помощи. Есть скетч в котором четыре светодиода включаются и выключаются от своих кнопок. На каждый  светодиод по одной кнопке. Все прекрасно работает, но нужно, чтобы одновременно с включением одного из светодиодов, отключался любой другой светодиод, если он был включен раньше. Проще говоря - взаимоотключение друг друга. Может есть другой вариант скетча, главное чтобы соблюдался алгоритм:

1. Скетч на четыре светодиода и четыре кнопки

2. Включение и отключение каждого светодиода  своей  одной кнопкой

3. Невозможность одновременного включения двух и более светодиодов (взаимоотключение)

Заранее поблагодарю. Пожалуйста подсобите.

Вот скетч.

#define knopka1 1
#define lampa1 2

#define knopka2 3
#define lampa2 4

#define knopka3 5
#define lampa3 6

#define knopka4 7
#define lampa4 8
 
bool statuslamp1 = 1;
bool statusknop1 = 0;

bool statuslamp2 = 1;
bool statusknop2 = 0;

bool statuslamp3 = 1;
bool statusknop3 = 0;

bool statuslamp4 = 1;
bool statusknop4 = 0;

 
void setup()

{
 pinMode(knopka1, INPUT);
 pinMode(lampa1, OUTPUT);
 
 pinMode(knopka2, INPUT);
 pinMode(lampa2, OUTPUT);
 
 pinMode(knopka3, INPUT);
 pinMode(lampa3, OUTPUT);
 
 pinMode(knopka4, INPUT);
 pinMode(lampa4, OUTPUT);
 
 
}

void loop()

//========включить-отключить нагрузку  кнопкой 1
{
 
 bool AAAAA1 = digitalRead(knopka1);
 if (AAAAA1 && !statusknop1)
 {
 statuslamp1 = !statuslamp1;
 delay(10);
 }
 statusknop1 = AAAAA1;
 digitalWrite(lampa1, statuslamp1);

//========включить-отключить нагрузку  кнопкой 2
 
 bool AAAAA2 = digitalRead(knopka2);
 if (AAAAA2 && !statusknop2)
 {
 statuslamp2 = !statuslamp2;
 delay(10);
 }
 
 statusknop2 = AAAAA2;
 digitalWrite(lampa2, statuslamp2);

//=========включить-отключить нагрузку  кнопкой 3

 bool AAAAA3 = digitalRead(knopka3);
 if (AAAAA3 && !statusknop3)
 {
 statuslamp3 = !statuslamp3;
 delay(10);
 }
 statusknop3 = AAAAA3;
 digitalWrite(lampa3, statuslamp3);

 //======включить-отключить нагрузку  кнопкой 4

 bool AAAAA4 = digitalRead(knopka4);

 if (AAAAA4 && !statusknop4)
 {
 statuslamp4 = !statuslamp4;
 delay(10);
 }
 statusknop4 = AAAAA4;
 digitalWrite(lampa4, statuslamp4);
 
 
 
}
 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

maksim пишет:

nestandart пишет:
В ардуино есть встроенные подтягивающие резисторы (pull-up) которые можно включить программно, но я не советую их использовать.
А я наоборот советую и рекомендую их использовать, потому как они именно для этого и предназначены.

это 20 kOm, который встроенный.... моя думает - что нано рассчитать ентот резюк ! попал в 20 kOm - подключай встроенный, не попал - вешай dytiyvq !

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

пардон... ВЕШАЙ ВНЕШНИЙ !

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

nestandart пишет:

>>а про это где можно подробнее почитать? Если я правильно понимаю, то это 3,4в на первой кнопке? Как вообще этот диапазон вычисляется или есть какие-то табличные значения?<<

Да это 3.4в . Если вы имеете в виду диапазон АЦП, то это от 0 до 1023 . Что соответствует напряжению от 0 до 5в. Например значение 512 это 2.5в.

А вот вам конкретый множитель - 0.0048828125. Если умножить значение пина АЦП на этоу цифру то получите точное напряжение в вольтах.

 

эта тема обсуждена до мозга костей  ИЛИ до костей мозга - 0 = 0 V , 1023 = 5 / 1024 *1023 = 4.995

jane Jack
Offline
Зарегистрирован: 08.10.2013

Олег, а может лучше будет вот этот вариант?

const int pin1 = 1;     //кнопка1
const int led1 =  11;   //светодиод1
const int pin2 = 2;     //кнопка2
const int led2 =  12;   //светодиод2
const int pin3 = 3;     //кнопка3
const int led3 =  13;   //светодиод3
const int pin4 = 4;     //кнопка4
const int led4 =  14;   //светодиод4
long previousMillis = 0;
int val1=0; 
int val2=0; 
int val3=0; 
int val4=0;
void setup()
{  pinMode(led1, OUTPUT);  // определяет pin на которой подключен led1 как выход
   pinMode(led2, OUTPUT);  // определяет pin на которой подключен led2 как выход
   pinMode(led3, OUTPUT);  // определяет pin на которой подключен led3 как выход
   pinMode(led4, OUTPUT);  // определяет pin на которой подключен led4 как выход
   pinMode(pin1, INPUT_PULLUP);  // определяет pin1 как вход с внутренней подтяжкой
   pinMode(pin2, INPUT_PULLUP);  // определяет pin2 как вход с внутренней подтяжкой
   pinMode(pin3, INPUT_PULLUP);  // определяет pin1 как вход с внутренней подтяжкой
   pinMode(pin4, INPUT_PULLUP);  // определяет pin2 как вход с внутренней подтяжкой
  }
  void loop() {
    if  (digitalRead(pin1) == LOW ){    //если pin1 включили,
     if (millis() -previousMillis >100) //то ждем 100мс для     
     {previousMillis = millis();        //отсечки дребезга контактов
        val1++;}}                       // и в переменную val1 прибавим один
     else 
     {val1=0;}
     if(val1>=5){ 
       if (digitalRead(led2) == HIGH)  //проверяем led2  
         {digitalWrite(led2,LOW);}     // и если включен выключаем
       if (digitalRead(led3) == HIGH)  //проверяем led3  
         {digitalWrite(led3,LOW);}     // и если включен выключаем
       if (digitalRead(led4) == HIGH)  //проверяем led4  
         {digitalWrite(led4,LOW);}     // и если включен выключаем
       digitalWrite(led1,!digitalRead(led1));//инвертируем состояние пина 
        val1=0;}

    if  (digitalRead(pin2) == LOW ){    //если pin2 включили,
     if (millis() -previousMillis >100) //то ждем 100мс для     
     {previousMillis = millis();        //отсечки дребезга контактов
        val2++;}}                       // и в переменную val2 прибавим один
     else 
     {val2=0;}
     if(val2>=5){ 
       if (digitalRead(led1) == HIGH)  //проверяем led1  
         {digitalWrite(led1,LOW);}     // и если включен выключаем
       if (digitalRead(led3) == HIGH)  //проверяем led3  
         {digitalWrite(led3,LOW);}     // и если включен выключаем
       if (digitalRead(led4) == HIGH)  //проверяем led4  
         {digitalWrite(led4,LOW);}     // и если включен выключаем
      digitalWrite(led2,!digitalRead(led2));//инвертируем состояние пина 
        val2=0;}
        
    if  (digitalRead(pin3) == LOW ){    //если pin3 включили,
     if (millis() -previousMillis >100) //то ждем 100мс для     
     {previousMillis = millis();        //отсечки дребезга контактов
        val3++;}}                       // и в переменную val3 прибавим один
     else 
     {val3=0;}
     if(val3>=5){ 
       if (digitalRead(led2) == HIGH)  //проверяем led2  
         {digitalWrite(led2,LOW);}     // и если включен выключаем
       if (digitalRead(led1) == HIGH)  //проверяем led1  
         {digitalWrite(led1,LOW);}     // и если включен выключаем
       if (digitalRead(led4) == HIGH)  //проверяем led4  
         {digitalWrite(led4,LOW);}     // и если включен выключаем
       digitalWrite(led3,!digitalRead(led3));//инвертируем состояние пина 
        val3=0;}
        
    if  (digitalRead(pin4) == LOW ){    //если pin4 включили,
     if (millis() -previousMillis >100) //то ждем 100мс для     
     {previousMillis = millis();        //отсечки дребезга контактов
        val4++;}}                       // и в переменную val4 прибавим один
     else 
     {val4=0;}
     if(val4>=5){ 
       if (digitalRead(led2) == HIGH)  //проверяем led2  
         {digitalWrite(led2,LOW);}     // и если включен выключаем
       if (digitalRead(led3) == HIGH)  //проверяем led3  
         {digitalWrite(led3,LOW);}     // и если включен выключаем
       if (digitalRead(led1) == HIGH)  //проверяем led1  
         {digitalWrite(led1,LOW);}     // и если включен выключаем
       digitalWrite(led4,!digitalRead(led4));//инвертируем состояние пина 
        val4=0;}

  }
    
  

 

jane Jack
Offline
Зарегистрирован: 08.10.2013

Gvined пишет:

вариан с переменной flag. удачно проходит компиляцию а на ардуине не работает диод горит в самом начале и при нажатии на кнопку загорается чуть ярче почему ?

 

подключил кнопку с одного конца на 5v ,а со второго на 8 вход и второй провод от этой же лапки кнопки через резистор на земле

пробовал даже ставить перемычку на 8 вход и GND и светодиод горит в самом начале что не так ?

 

 

Gvined проблема в самом коде.

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

Oleg.L.
Offline
Зарегистрирован: 19.08.2014

 Большое спасибо, надо попробовать.  Обязательно отпишусь по результатам.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

кнопки можно подсоединять через К555ТР2 ( четыре RS-триггера )... один корпус К555ТР2 , восемь резисторов по 10 kOm , четыре кнопки ( НО - три контакта ).... где есть возможность поставить НЗ-НР-Общ-кнопки - всегда ставлю ТР2.... а в коде про дребезг можно забыть зато :) 

Oleg.L.
Offline
Зарегистрирован: 19.08.2014

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

хотя у меня будут кнопки только с НО контактами, видимо, триггеры придется отставить...

Oleg.L.
Offline
Зарегистрирован: 19.08.2014

??

Oleg.L.
Offline
Зарегистрирован: 19.08.2014

Здравствуйте, jane Jack. Сегодня проверил работу программы. Вполне стабильно работает. но есть один нюанс: если удерживать любую кнопку нажатой то светодиод мигает, а если нажать одновременно две и более кнопок светодиоды начинают загораться по очереди. А можно сделать так, чтобы состояние светодиода изменялось один раз   только либо при нажатии или при отпускании и не мигали. и не включались все при удержании нескольких кнопок?  Если не получится отпишитесь, пож-та. ОК?

jane Jack
Offline
Зарегистрирован: 08.10.2013

Олег, по пробуй убрать матиматику из скетча. замени val++ на val=1. А в сравнении val>=5 замени на val==1. И эксперементируй с таймером 

if (millis() -previousMillis >100) //то ждем 100мс для 

думаю можно поднять планку примерно до 300 это около 1/3 секунды. Хотя если это весь скеч, то можно не ловить проблему с таким таймером и написать на делей с использованием примера флаг описанные выше по этой теме. А вот при нажатии двух и более кнопок надо добавить проверку и о этой задаче я по думаю не сегодня. Может на неделе но не буду обещать.

Oleg.L.
Offline
Зарегистрирован: 19.08.2014

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

У меня это будет не весь скетч, а  фрагмент, который, благодаря тебе,  будет вставлен в общую программу. И, я думаю, что таймер заменить на  delay не желательно, дабы не затормозить обшее быстродействие скетча. Ведь у меня их там сколько-то встречается.  Хотя все равно надо посмотреть, может и с такой задержкой будет вполне нормально рабтать. Благодарю еще раз!!

varistor
varistor аватар
Offline
Зарегистрирован: 03.02.2013
В дополнение к вышеизложенному, предлагаю очень простую схемку для подключения матричных клавиатур. Вариантов схем много, но такая позволяет использовать всего 1 аналоговый вход и 6 (либо 7) резисторов для 16 клавиш 4х4. Резисторы понадобятся всего двух номиналов, отличающихся в 4 раза. Резистор R7 можно использовать из подтяжки pullUp. При последовательном нажатии клавиш (1, 2, 3, А, 4, 5, 6, В ...) сопротивление между А1 и GND будет увеличиваться ровно на значение резисторов R1-R3 (на 1к в варианте на схеме). С резистором R7 они составляют делитель напряжения 5в.
 
Скетч, любезно предоставленный maksim, можно применить и для опроса матричной клавиатуры. В коде нужно только изменить в строке 01: NUM_KEYS на 16   и в строке 02:  {30, 150, 360, 535, 760}; прописать 16 значений порогов.  Значения порогов легко получить временно добавив в стороке  17:
 
  Serial.println(input, DEC);   
 
Запустив монитор COM-порта и понажимав все клавиши по очереди (1, 2, 3, А, 4, 5, 6, В ...) , получим ряд значений. Для надежности работы и устранения ошибок от дрейфа параметров, пороги следует выбирать в середине между значениями данной клавиши и следующей (средне арифметическое). Например, если для кнопки "1" получили 4, а для "2" - 216, то порог "1" будет 110.
 
Удачи!
 
#define NUM_KEYS 16
int  adc_key_val[NUM_KEYS] = {110, 284, 402, 482, 542, 595, 637, 670, 696, 720, 743, 761, 775, 790, 804, 916};
 
void setup()
{
  Serial.begin(9600);
}

void loop()
{
  int key = get_key(A1);
  if(key) Serial.println(key, DEC);
  delay(500);
}

int get_key(int key_pin)
{
  int input = analogRead(key_pin); //Serial.println(input, DEC); 
  for(int k = 0; k < NUM_KEYS; k++) if(input < adc_key_val[k])  return k + 1;    
  return 0;
}

 

схема матричной клавиатуры

матричная клавиатура 4х4

 

 

Coolerr
Offline
Зарегистрирован: 30.06.2014

Блин, откуда такие номиналы 4кОм. Нет таких в стандартных рядах. Есть такие 3.6, 3.9, 4.7, 5.1

varistor
varistor аватар
Offline
Зарегистрирован: 03.02.2013

По сути дела это не номиналы. Это означает всего лишь, что резисторы R1-R3 и  R4-R6 должны отличаться друг от друга примерно в 4 раза. Мне не хотелось писать 1xR, 4xR. Разброс номиналов сопротивлений может достигать 20%. Причем совсем не обязательно д.б. 1к0 и 3к9. Допустимы сопротивления от 100 ом до 1 Мом. Крайности нежелательны. Возможные варианты: 1к6\6к8, 2к0\8к2, 5к6\22к и так далее.

Space-06
Offline
Зарегистрирован: 22.11.2014

Доброго всем времени суток уважаемые коллеги!

Столкнулся с такой проблемой: на первой странице приведен пример работы с кнопкой и режимами, так вот если в одном из режимов находится ШИМ (Плавное загорание Светодиода и его плавное отключение) то невозможно перейти на следующий за ним режим.

такое ощущение что кнопка не читается и цикл не видит ее изменение.

Каким образом можно выйти из положения?

Для примера приведу пример:

#define led 1
#define BUTTON 3
int val=0;
int old_val=0;
int state=0; 

void setup()
{
  pinMode(led,OUTPUT);
  pinMode(BUTTON,INPUT);
}

void LEDFade(){
    for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=5) { 
    analogWrite(led, fadeValue);          
    delay(30);}
    delay(500); 
      for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=5) { 
      analogWrite(led, fadeValue);          
      delay(30);}
      delay(500); 
}

void loop()
{
  val=digitalRead(BUTTON); //check status of pushbutton
  if((val==HIGH)&&(old_val==LOW)) //button pressed
  {
    state++; //increment state
    delay(10); //debounce consideration
    if(state>3) //want only 4 brightness options
    {
      state=1;
      delay(10);
    }
  }
  old_val=val;
  if(state==1)
  {
    analogWrite(led,0); //0 brightness
  }
  else if(state==2)
  {
    analogWrite(led,125);
    delay(1500);
    analogWrite(led,150);
    delay(1500);
    analogWrite(led,20);
    return;
  }
  else if(state==3)
  {
    analogWrite(led,255);
  }
}

 

Coolerr
Offline
Зарегистрирован: 30.06.2014

А какой из режимов ШИМ. state1,2 или 3? Ни в одном не наблюдаю. Если шим в цикле for, то где условие входа в функцию LEDFade?

Y.
Offline
Зарегистрирован: 28.11.2014

PULL_UP на аналоговом пине

Подскажите!

void  setup(){
 Serial.begin(9600);
 pinMode(A3,INPUT);
 digitalWrite(A3, HIGH); 
 }
void loop(){ 
 Serial.print("analogRead:   ");
 Serial.println (analogRead(A3));
 Serial.print("digitalRead:   ");
 Serial.println (digitalRead(A3));
 delay(1000);
 }

В описании (http://arduino.cc/n/Tutorial/AnalogInputPins) говорится:

"The analog pins also have pullup resistors, which work identically to pullup resistors on the digital pins. They are enabled by issuing a command such as

digitalWrite(A0, HIGH); // set pullup on analog pin 0 while the pin is an input.

Be aware however that turning on a pullup will affect the values reported by analogRead()."

Подтягиваю неподключенный А3 и читаю значение на нем analogRead. Ожидаю близко к 1023, но получаю 0.

В то же время digitalRead читает pullup правильно (HIGH). Что я неправильно делаю?

 

maksim
Offline
Зарегистрирован: 12.02.2012

Так не бывает

analogRead:   1011
digitalRead:   1
analogRead:   995
digitalRead:   1
analogRead:   1004
digitalRead:   1
analogRead:   1004
digitalRead:   1
analogRead:   1011
digitalRead:   1
analogRead:   1012
digitalRead:   1
analogRead:   1013
digitalRead:   1
analogRead:   1013
digitalRead:   1
analogRead:   1012
digitalRead:   1
analogRead:   1010
digitalRead:   1
analogRead:   1006
digitalRead:   1
analogRead:   1004
digitalRead:   1
analogRead:   1011
digitalRead:   1
analogRead:   1009
digitalRead:   1

 

Y.
Offline
Зарегистрирован: 28.11.2014

Спасибо.

Оказалось, что если AVCC (pin 20 ATMega328) подтянут к +5В, то происходит такая ошибка. Отключил - работает правильно. Почему - пока не понятно, буду разбираться.