Можно конечно и потенциометр подключить. Но он неудобен тем что для того чтобы установить его в какое либо положение нужно проскакать по предыдущим.
кнопки не решают проблемы практической невозможности мгновенной телепортации значения напряжения от 0 до, допустим 3,5В, минуя промежуточные значения - по любому значение напряжения будет повышаться от 0 до 3,5В, включая все кнопки в этом диапазоне.
Ну тогда можно и про скорость движения электронов поговорить.
О каких промежуточных значениях вы говорите ? Скорость переключения от 0 до нужного напряжения определяется рскоростью распространения электрического поля в проводе.
Если углубляться в такие дебри то да, переключение происходит не мгновенно. Оно длятся несколько пикосекунд.
А теперь посмотрите ( в справочных материалах) сколько времени занимает опрос пина АЦП.
О каких промежуточных значениях вы говорите ? Скорость переключения от 0 до нужного напряжения определяется рскоростью распространения электрического поля в проводе.
ок - проверю практически, теоретически - более чем уверен, что существует ненулевая вероятность срабатывания кнопок находящихся в диапазоне изменяемых напряжений.
Есть резистивные кнопки. Подключены к аналоговому пину. Ардуино в качестве 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;
}
}
Делаете таймер , который при нажатии на кнопку начинает отсчет времени и присваивает это значение переменной. При отпущеной кнопке переменная обнуляется.
А потом отслеживаете значение переменной. Если время нажатия превысило пороговое значение - удержание кнопки. Если нет (обнулилось) - короткое нажатие.
Делаете таймер , который при нажатии на кнопку начинает отсчет времени и присваивает это значение переменной. При отпущеной кнопке переменная обнуляется.
А потом отслеживаете значение переменной. Если время нажатия превысило пороговое значение - удержание кнопки. Если нет (обнулилось) - короткое нажатие.
Спасибо!!! Почти всё получилось. Вот только при нажатии и удержании кнопки "следующий трек", сначало переключается трек а потом начинается перемотка. Т.е. выполняется и условие строки 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;
}
}
Прошу программистов помочь в очень простой для вас, практической задаче для уменьшения простоя лифта. Сегодня лифты напичканы электроникой, а элмеханик не всегда может локализовать неисправность – то ли электроника глючит (тогда жди пока наладчик приедет – бывает долго. Это я и есть) или в шахте непорядок. У меня есть самодельный стенд для полной проверки, собрал его на жесткой логике. Вот хочу для механиков собрать такую приблуду, чтобы меня меньше дергали – старенький я и сами меньше в шахте ползали.
Для начала информация:
В шахте лифта и на кабине расположены шунты, а на кабине -герконовые датчики. Основных датчиков три: 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
МАКСИМ! Спасибо большое - сразу заработало. мне нужно время изучить, как ВЫ сделали.
У меня просто уже есть мега от внука- подарил ему на день рождения - получилось себе. Своим механикам, если все получится, дам схему на что-нить подешевле.
Это ведь начало задачи. Буду потом искат прогу для подсчета количества остановок по этим трем импульсам и вывода №этажа на семисегментный двустрочный индикатор. Может сразу мне и подскажите где посмотреть пример?
Всё так же как и было. При нажатии и удержании кнопки сначало проходит сигнал как при одиночном нажатии а потом как при удержании. Т.е. при нажатии идалнейшем удержании кнопки следующий трек отсылается сначала и 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;
}
}
если же первый код не закомментирован то включение по часам не срабатывает
весь код целиком :
#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");
}
}
}
Ошибка в логике.
Допустим, сейчас 20 часов. Свет автоматически включается (строка 97). И тут же гасится (строка 109, ledOn в состоянии low). Естественно, реле не успевает отработать за эти микросекунды, поэтому визуально ничего не происходит.
По этой же причине днём не удастся включить свет кнопкой - он тут же будет гаситься, потому что часы говорят: "День. Пин должен быть в Low".
Ошибка в логике. Допустим, сейчас 20 часов. Свет автоматически включается (строка 97). И тут же гасится (строка 109, ledOn в состоянии low). Естественно, реле не успевает отработать за эти микросекунды, поэтому визуально ничего не происходит. По этой же причине днём не удастся включить свет кнопкой - он тут же будет гаситься, потому что часы говорят: "День. Пин должен быть в 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.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");
}
}
}
Очень не советую использовать функцию 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(), только который прерывается состоянием пина и может сказать "когда его прервали".
Добрый день ! Прошу помощи,так как в программировании совсем новичок. Пытаюсь сделать подобие умного дома, необходимо чтобы выключатель мог поочередно включать несколько разных светильников, воспользовался вот этим примером
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 Ищу также, не безвозмездно, специалиста,который на основе моих пожеланий по созданию умного дома, поможет написать программу и параллельно обучит меня минимальным основам программирования на ардуино,для возможности внесения изменений в работу программы при дальнейшей эксплуатации системы.
Подскажите каким образом можно подсчитать количество нажатий кнопки в течении времени, т.е для выполнения действия необходимо трижды нажать на кнопку в течении 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;
}
вариан с переменной flag. удачно проходит компиляцию а на ардуине не работает диод горит в самом начале и при нажатии на кнопку загорается чуть ярче почему ?
Здравствуйте, Дмитрий. Я Вас заочно знаю по многочисленным роликам в You Tube с Вашим опытом не откажите в помощи. Есть скетч в котором четыре светодиода включаются и выключаются от своих кнопок. На каждый светодиод по одной кнопке. Все прекрасно работает, но нужно, чтобы одновременно с включением одного из светодиодов, отключался любой другой светодиод, если он был включен раньше. Проще говоря - взаимоотключение друг друга. Может есть другой вариант скетча, главное чтобы соблюдался алгоритм:
1. Скетч на четыре светодиода и четыре кнопки
2. Включение и отключение каждого светодиода своей одной кнопкой
3. Невозможность одновременного включения двух и более светодиодов (взаимоотключение)
>>а про это где можно подробнее почитать? Если я правильно понимаю, то это 3,4в на первой кнопке? Как вообще этот диапазон вычисляется или есть какие-то табличные значения?<<
Да это 3.4в . Если вы имеете в виду диапазон АЦП, то это от 0 до 1023 . Что соответствует напряжению от 0 до 5в. Например значение 512 это 2.5в.
А вот вам конкретый множитель - 0.0048828125. Если умножить значение пина АЦП на этоу цифру то получите точное напряжение в вольтах.
эта тема обсуждена до мозга костей ИЛИ до костей мозга - 0 = 0 V , 1023 = 5 / 1024 *1023 = 4.995
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;}
}
вариан с переменной flag. удачно проходит компиляцию а на ардуине не работает диод горит в самом начале и при нажатии на кнопку загорается чуть ярче почему ?
подключил кнопку с одного конца на 5v ,а со второго на 8 вход и второй провод от этой же лапки кнопки через резистор на земле
пробовал даже ставить перемычку на 8 вход и GND и светодиод горит в самом начале что не так ?
кнопки можно подсоединять через К555ТР2 ( четыре RS-триггера )... один корпус К555ТР2 , восемь резисторов по 10 kOm , четыре кнопки ( НО - три контакта ).... где есть возможность поставить НЗ-НР-Общ-кнопки - всегда ставлю ТР2.... а в коде про дребезг можно забыть зато :)
Здравствуйте, jane Jack. Сегодня проверил работу программы. Вполне стабильно работает. но есть один нюанс: если удерживать любую кнопку нажатой то светодиод мигает, а если нажать одновременно две и более кнопок светодиоды начинают загораться по очереди. А можно сделать так, чтобы состояние светодиода изменялось один раз только либо при нажатии или при отпускании и не мигали. и не включались все при удержании нескольких кнопок? Если не получится отпишитесь, пож-та. ОК?
Олег, по пробуй убрать матиматику из скетча. замени val++ на val=1. А в сравнении val>=5 замени на val==1. И эксперементируй с таймером
if (millis() -previousMillis >100) //то ждем 100мс для
думаю можно поднять планку примерно до 300 это около 1/3 секунды. Хотя если это весь скеч, то можно не ловить проблему с таким таймером и написать на делей с использованием примера флаг описанные выше по этой теме. А вот при нажатии двух и более кнопок надо добавить проверку и о этой задаче я по думаю не сегодня. Может на неделе но не буду обещать.
Спасибо большое. Буду эксперементировать. Вот , с помощью отзывчивых людей , можно двигаться дальше.
У меня это будет не весь скетч, а фрагмент, который, благодаря тебе, будет вставлен в общую программу. И, я думаю, что таймер заменить на delay не желательно, дабы не затормозить обшее быстродействие скетча. Ведь у меня их там сколько-то встречается. Хотя все равно надо посмотреть, может и с такой задержкой будет вполне нормально рабтать. Благодарю еще раз!!
В дополнение к вышеизложенному, предлагаю очень простую схемку для подключения матричных клавиатур. Вариантов схем много, но такая позволяет использовать всего 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;
}
По сути дела это не номиналы. Это означает всего лишь, что резисторы 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к и так далее.
Столкнулся с такой проблемой: на первой странице приведен пример работы с кнопкой и режимами, так вот если в одном из режимов находится ШИМ (Плавное загорание Светодиода и его плавное отключение) то невозможно перейти на следующий за ним режим.
такое ощущение что кнопка не читается и цикл не видит ее изменение.
"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). Что я неправильно делаю?
Оказалось, что если AVCC (pin 20 ATMega328) подтянут к +5В, то происходит такая ошибка. Отключил - работает правильно. Почему - пока не понятно, буду разбираться.
Можно конечно и потенциометр подключить. Но он неудобен тем что для того чтобы установить его в какое либо положение нужно проскакать по предыдущим.
кнопки не решают проблемы практической невозможности мгновенной телепортации значения напряжения от 0 до, допустим 3,5В, минуя промежуточные значения - по любому значение напряжения будет повышаться от 0 до 3,5В, включая все кнопки в этом диапазоне.
Вы это серьезно ?!
Ну тогда можно и про скорость движения электронов поговорить.
О каких промежуточных значениях вы говорите ? Скорость переключения от 0 до нужного напряжения определяется рскоростью распространения электрического поля в проводе.
Если углубляться в такие дебри то да, переключение происходит не мгновенно. Оно длятся несколько пикосекунд.
А теперь посмотрите ( в справочных материалах) сколько времени занимает опрос пина АЦП.
О каких промежуточных значениях вы говорите ? Скорость переключения от 0 до нужного напряжения определяется рскоростью распространения электрического поля в проводе.
ок - проверю практически, теоретически - более чем уверен, что существует ненулевая вероятность срабатывания кнопок находящихся в диапазоне изменяемых напряжений.
Здравствуйте. Подскажите пожалуйста.
Есть резистивные кнопки. Подключены к аналоговому пину. Ардуино в качестве HID клавиатуры.
Сейчас у меня при нажатии на кнопку отправляется только одно значение. Работает отлично, как и надо при одиночном нажатии.
Не могу понять как сделать чтобы при одиночном нажатии отправлялось одно действиие а при удержании другое. Например кнопка "следующий трек". При одиночном нажатии отправляла Remote.next() (следующий трек), а при удержании постоянно отправляла Remote.forward() (перемотка).
Вот какой скетч сейчас.
Делаете таймер , который при нажатии на кнопку начинает отсчет времени и присваивает это значение переменной. При отпущеной кнопке переменная обнуляется.
А потом отслеживаете значение переменной. Если время нажатия превысило пороговое значение - удержание кнопки. Если нет (обнулилось) - короткое нажатие.
Делаете таймер , который при нажатии на кнопку начинает отсчет времени и присваивает это значение переменной. При отпущеной кнопке переменная обнуляется.
А потом отслеживаете значение переменной. Если время нажатия превысило пороговое значение - удержание кнопки. Если нет (обнулилось) - короткое нажатие.
Спасибо!!! Почти всё получилось. Вот только при нажатии и удержании кнопки "следующий трек", сначало переключается трек а потом начинается перемотка. Т.е. выполняется и условие строки 063 и условие строки 070. С другими кнопками аналогичная ситуация. А как сделать что бы при удержании не выполнялось условие 063?
В программу особо не вчитывался , но ...
Переделайте все конструкции if else if на просто if ( лучше вообще откажитесь от оператора else). Возможно у вас конфликт по условиям if else.
И еще. Как вариант , перенесите скобку из строки 25 в самый низ.
Ход таймера маловат (40мс). Получается чтобы сработало одиночное нажатие нужно удерживать кнопку не более 120мс (неудобно).
Оптимальное время для одиночного нажатия 500-1000мс.
Я бы сделал отдельный таймер для каждой кнопки.
Прошу программистов помочь в очень простой для вас, практической задаче для уменьшения простоя лифта. Сегодня лифты напичканы электроникой, а элмеханик не всегда может локализовать неисправность – то ли электроника глючит (тогда жди пока наладчик приедет – бывает долго. Это я и есть) или в шахте непорядок. У меня есть самодельный стенд для полной проверки, собрал его на жесткой логике. Вот хочу для механиков собрать такую приблуду, чтобы меня меньше дергали – старенький я и сами меньше в шахте ползали.
Для начала информация:
В шахте лифта и на кабине расположены шунты, а на кабине -герконовые датчики. Основных датчиков три: 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);
не в эту тему ;)
Мега для таких целей ох как жирновато....
МАКСИМ! Спасибо большое - сразу заработало. мне нужно время изучить, как ВЫ сделали.
У меня просто уже есть мега от внука- подарил ему на день рождения - получилось себе. Своим механикам, если все получится, дам схему на что-нить подешевле.
Это ведь начало задачи. Буду потом искат прогу для подсчета количества остановок по этим трем импульсам и вывода №этажа на семисегментный двустрочный индикатор. Может сразу мне и подскажите где посмотреть пример?
Заранее благодарю.
где посмотреть пример?
В программу особо не вчитывался , но ...
Переделайте все конструкции if else if на просто if ( лучше вообще откажитесь от оператора else). Возможно у вас конфликт по условиям if else. [/
И еще. Как вариант , перенесите скобку из строки 25 в самый низ.
Ход таймера маловат (40мс). Получается чтобы сработало одиночное нажатие нужно удерживать кнопку не более 120мс (неудобно).
Оптимальное время для одиночного нажатия 500-1000мс.
Я бы сделал отдельный таймер для каждой кнопки.
Перенёс скобку, else убрал, всё равно не получается(((
Есть у кого ещё идеи?
Таймер пока настроил оптимально для моих целей, потом возможно перестрою получше.
Как именно не получается ? Что происходит ?
Всё так же как и было. При нажатии и удержании кнопки сначало проходит сигнал как при одиночном нажатии а потом как при удержании. Т.е. при нажатии идалнейшем удержании кнопки следующий трек отсылается сначала и remote.next и потом remote.forward (стр. 065, 072)
Добрый вечер.
Подскажите можно ли в матричной клавиатуре к примеру 3 на 3,
сделать событие при удержании одной кнопки
мне нужно плано увеличивать значение set++
в таком варианте получается нужно все время нажимать на кнопку а хочу чтоб при нажатии показания увеличивались
Как это сделать?
Спасибо.
button switch Read boolean
Всем привет!
помогите разобраться пожалуйста, не работает включение кнопкой светодиода и включение по времени, тоесть либо одно либо другое, если закомментить код
весь код целиком :
Ошибка в логике.
Допустим, сейчас 20 часов. Свет автоматически включается (строка 97). И тут же гасится (строка 109, ledOn в состоянии low). Естественно, реле не успевает отработать за эти микросекунды, поэтому визуально ничего не происходит.
По этой же причине днём не удастся включить свет кнопкой - он тут же будет гаситься, потому что часы говорят: "День. Пин должен быть в Low".
ну да, точно, получается так, может быть посоветуете как правильно сделать ?
может как то так ловить?
Хм... представил что кто-то делая свои первые шаги и желая разобратся "как же работать с кнопками", наткнется на скетч из #212. Поседеет сразу.
Хм... представил что кто-то делая свои первые шаги и желая разобратся "как же работать с кнопками", наткнется на скетч из #212. Поседеет сразу.
Извиняюсь, не хотел никого напугать :))) просто я сам еще новичек в общении с ардуино, и потребовался совет именно по кнопке
а скетч то проверил? я его в блокноте правил, так как у меня сейчас не платы не среды нет .
Очень не советую использовать функцию pulseIn для данных целей (да и вообще не советую).
Потому что эта функция использует все программные таймеры ардуино.
С функцией pulseIn НЕ будут работать
Tone()
Millis()
analogWrite()
Так же не будут работать сервоприводы.
Ох блин, в первый раз заметил (сорри если уже обсудили, быстренько пробежался по ветке не нашел упоминаний).
Вообщем откуда взялась идея что " эта функция использует все программные таймеры ардуино", со всемы вытекающими из этого ужасами? В документации об этом ни слова. Да и зачем ей могли понадобится "все програмные таймеры?" (ну хотя-бы исходи из логики что на разных дуинах и разное кол-во, а работает она на всех).
Заглянул в ее исходник (вдруг дока не полна):
Никаких таймеров не видно. Обычная блокирующая функция. "Зла" от нее, ровно столько же сколько и от delay(). Поэтому можно согласится что "нежелательно использовать" (когда во время ожидания импульса нужно еще чем-нибудь заниматся), но этим ее "нежелательность" и ограничивается. По большому счету это и есть тот же самый delay(), только который прерывается состоянием пина и может сказать "когда его прервали".
Добрый день ! Прошу помощи,так как в программировании совсем новичок. Пытаюсь сделать подобие умного дома, необходимо чтобы выключатель мог поочередно включать несколько разных светильников, воспользовался вот этим примером
при работе с кнопкой на макетной плате все работает ок, но при подключении кнопочного выключателя проявляется дребезг и система работает неустойчиво. Подскажите пожалуйста, как повысить надежность срабатывания и ввести в этот скетч кнопку "выключить всё" ? Заранее благодарю !!!
P.S Ищу также, не безвозмездно, специалиста,который на основе моих пожеланий по созданию умного дома, поможет написать программу и параллельно обучит меня минимальным основам программирования на ардуино,для возможности внесения изменений в работу программы при дальнейшей эксплуатации системы.
Подскажите каким образом можно подсчитать количество нажатий кнопки в течении времени, т.е для выполнения действия необходимо трижды нажать на кнопку в течении 3 секунд. причем таймер запускается первым нажатем этой же кнопки.
если подумать:
вариан с переменной 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 и светодиод горит в самом начале что не так ?
Здравствуйте, Дмитрий. Я Вас заочно знаю по многочисленным роликам в 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);
}
это 20 kOm, который встроенный.... моя думает - что нано рассчитать ентот резюк ! попал в 20 kOm - подключай встроенный, не попал - вешай dytiyvq !
пардон... ВЕШАЙ ВНЕШНИЙ !
>>а про это где можно подробнее почитать? Если я правильно понимаю, то это 3,4в на первой кнопке? Как вообще этот диапазон вычисляется или есть какие-то табличные значения?<<
Да это 3.4в . Если вы имеете в виду диапазон АЦП, то это от 0 до 1023 . Что соответствует напряжению от 0 до 5в. Например значение 512 это 2.5в.
А вот вам конкретый множитель - 0.0048828125. Если умножить значение пина АЦП на этоу цифру то получите точное напряжение в вольтах.
эта тема обсуждена до мозга костей ИЛИ до костей мозга - 0 = 0 V , 1023 = 5 / 1024 *1023 = 4.995
Олег, а может лучше будет вот этот вариант?
вариан с переменной flag. удачно проходит компиляцию а на ардуине не работает диод горит в самом начале и при нажатии на кнопку загорается чуть ярче почему ?
подключил кнопку с одного конца на 5v ,а со второго на 8 вход и второй провод от этой же лапки кнопки через резистор на земле
пробовал даже ставить перемычку на 8 вход и GND и светодиод горит в самом начале что не так ?
Gvined проблема в самом коде.
у меня этот код не спасал от дребезга контактов.
Большое спасибо, надо попробовать. Обязательно отпишусь по результатам.
кнопки можно подсоединять через К555ТР2 ( четыре RS-триггера )... один корпус К555ТР2 , восемь резисторов по 10 kOm , четыре кнопки ( НО - три контакта ).... где есть возможность поставить НЗ-НР-Общ-кнопки - всегда ставлю ТР2.... а в коде про дребезг можно забыть зато :)
возможно тоже вариант.надо пробовать, и смотреть как будет работать. Благодарю за дельные советы.
хотя у меня будут кнопки только с НО контактами, видимо, триггеры придется отставить...
??
Здравствуйте, jane Jack. Сегодня проверил работу программы. Вполне стабильно работает. но есть один нюанс: если удерживать любую кнопку нажатой то светодиод мигает, а если нажать одновременно две и более кнопок светодиоды начинают загораться по очереди. А можно сделать так, чтобы состояние светодиода изменялось один раз только либо при нажатии или при отпускании и не мигали. и не включались все при удержании нескольких кнопок? Если не получится отпишитесь, пож-та. ОК?
Олег, по пробуй убрать матиматику из скетча. замени val++ на val=1. А в сравнении val>=5 замени на val==1. И эксперементируй с таймером
думаю можно поднять планку примерно до 300 это около 1/3 секунды. Хотя если это весь скеч, то можно не ловить проблему с таким таймером и написать на делей с использованием примера флаг описанные выше по этой теме. А вот при нажатии двух и более кнопок надо добавить проверку и о этой задаче я по думаю не сегодня. Может на неделе но не буду обещать.
Спасибо большое. Буду эксперементировать. Вот , с помощью отзывчивых людей , можно двигаться дальше.
У меня это будет не весь скетч, а фрагмент, который, благодаря тебе, будет вставлен в общую программу. И, я думаю, что таймер заменить на delay не желательно, дабы не затормозить обшее быстродействие скетча. Ведь у меня их там сколько-то встречается. Хотя все равно надо посмотреть, может и с такой задержкой будет вполне нормально рабтать. Благодарю еще раз!!
Блин, откуда такие номиналы 4кОм. Нет таких в стандартных рядах. Есть такие 3.6, 3.9, 4.7, 5.1
По сути дела это не номиналы. Это означает всего лишь, что резисторы 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к и так далее.
Доброго всем времени суток уважаемые коллеги!
Столкнулся с такой проблемой: на первой странице приведен пример работы с кнопкой и режимами, так вот если в одном из режимов находится ШИМ (Плавное загорание Светодиода и его плавное отключение) то невозможно перейти на следующий за ним режим.
такое ощущение что кнопка не читается и цикл не видит ее изменение.
Каким образом можно выйти из положения?
Для примера приведу пример:
А какой из режимов ШИМ. state1,2 или 3? Ни в одном не наблюдаю. Если шим в цикле for, то где условие входа в функцию LEDFade?
PULL_UP на аналоговом пине
Подскажите!
В описании (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). Что я неправильно делаю?
Так не бывает
Спасибо.
Оказалось, что если AVCC (pin 20 ATMega328) подтянут к +5В, то происходит такая ошибка. Отключил - работает правильно. Почему - пока не понятно, буду разбираться.