Управление подсветкой дисплея 1602 I2C

Marshall Kross
Offline
Зарегистрирован: 19.01.2019

Добрый день. Прошу помощи, пнуть в нужном направлении. Есть связка ардуино нано, LCD 1602  на шине I2C, DHT22, часы реального времени на базе DS3231 (тоже I2C). Подсветка включается посредством команды lcd.backlight(); Отключить ее можно командой lcd.noBacklight(); Основную задумку по коду почти  реализовал кроме листинга выводимой на дисплей информации (код прилагаю), основная проблема с реализацией задумки вкл. и выкл. подсветки кнопкой. Идея такая, есть кнопка подключенная к пину D2 при ее нажатии подсветка должна отключится и при повторном нажатии снова включится. Планировалась реализация без коственно програмно без использования транзистора.  Я перечитал много тем, примеров, но так и не нашел как реализовать это. Если не сложно подскажите пожалуйста. Буду очень благодарен.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <iarduino_RTC.h>
#include "DHT.h"
#define DHTPIN 2 
DHT dht(DHTPIN, DHT22);
iarduino_RTC time(RTC_DS3231);
LiquidCrystal_I2C lcd(0x3F, 16, 2);

void setup() {

    dht.begin();
    lcd.init(); 
    lcd.backlight();
    time.begin();
}
void loop(){
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    float f = dht.readTemperature(true);
    if(millis()%1000==0){ 
    lcd.setCursor(0, 0);
    lcd.print(time.gettime("H"));
    lcd.setCursor(2, 0);
    lcd.print(":");
    lcd.setCursor(3, 0);
    lcd.print(time.gettime("i"));
    lcd.setCursor(5, 0);
    lcd.print(":");
    lcd.setCursor(6, 0);
    lcd.print(time.gettime("s"));
    lcd.setCursor(9, 0);
    lcd.print(time.gettime("d"));
    lcd.setCursor(12, 0);
    lcd.print(time.gettime("Y"));
    lcd.setCursor(0, 1);
    lcd.print("t=");
    lcd.setCursor(3, 1);
    lcd.print(t, 1);
    lcd.setCursor(7, 1);
    lcd.print("c");
    lcd.setCursor(9, 1);
    lcd.print("h=");
    lcd.setCursor(11, 1);
    lcd.print(h, 1);
    lcd.print("%"); 
    }
}

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

А в чем проблема? Команды  lcd.noBacklight(); /lcd.backlight();  работают? 

Marshall Kross
Offline
Зарегистрирован: 19.01.2019

Естественно работают. Я писал выше что не нашел информации как реализовать включение и выключение подсветки кнопкой не прибегая к отрезанию подсветки и управлению ею через транзистор.

Цитирую сам себя:

"Идея такая, есть кнопка подключенная к пину D2 при ее нажатии подсветка должна отключится и при повторном нажатии снова включится. "

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Не понял. Если lcd.noBacklight() работает. То пошлите эту команду по нажатию кнопки. А по второму нажатию пошлите lcd.backlight().

Причем здесь транзистор?

Marshall Kross
Offline
Зарегистрирован: 19.01.2019

Я пробовал, но видать где то я туплю. Не до конца понимаю как подставить эту команду. За основу взял этот кусок кода. Но не могу понять как правильно подсунуть команду, отладчик все время ругается на приставку lcd.

Я писал его для отработки флагов на кнопке, но как всунуть ему команду не могу понять(( 

ПС. Если вдруг что я не студент и курсак не пишу, я еще в 2015 закончил институт)) Я просто изучаю ардуинки.

boolean butt_flag = 0;
boolean butt;
boolean button_flag = 0;
unsigned long last_press;

void setup() {
  pinMode(3, INPUT_PULLUP);
  pinMode(4, OUTPUT);
  Serial.begin (9600);
}

void loop() {

    butt = !digitalRead(3); 
    if (butt == 1 && butt_flag == 0 && millis() - last_press > 200) {
    butt_flag = 1;
    Serial.println("on");
    button = !button;
    digitalWrite(4, button);
    last_press = millis();
  }
  if (butt == 0 && butt_flag == 1) {
    butt_flag = 0;
    Serial.println("off");
  }
}

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Ну в коде от сообщения №1 на lcd же не ругается. Посмотрите там на строку 8 и помедетируйте.

bwn
Offline
Зарегистрирован: 25.08.2014

Ну да, а еще на 2 и 13. 
 

Pyotr
Offline
Зарегистрирован: 12.03.2014

Попробую впарить ТСу свою кнопку)) Пусть разбирается.

#define CLICK_DOWN  B10
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F,16,2);
word carrMillis, prevMillis; 
const word interval = 20;
const byte pinButt = 7; 
byte stateButt = 0xFF;//отпущена
boolean stateLight = 0;

void setup() { 
  lcd.init();                     
  lcd.backlight(); 
  pinMode(pinButt, INPUT_PULLUP);
}
void loop() {  
  carrMillis = millis();//интервалы до 1 минуты
  if(carrMillis - prevMillis >= interval){
    prevMillis = carrMillis;
    stateButt <<= 1;//сдвиг.влево (в млад.бите ноль)
    stateButt |= digitalRead(pinButt);//пишем в млад.бит состояние кнопки
    if((stateButt & B11) == CLICK_DOWN){
      stateLight ? lcd.backlight() : lcd.noBacklight();
      stateLight = !stateLight;
    }
  }
}

 

gfx125
Offline
Зарегистрирован: 27.05.2017

Marshall Kross пишет:

Я писал выше что не нашел информации как реализовать включение и выключение подсветки кнопкой не прибегая к отрезанию подсветки и управлению ею через транзистор.

без транзистора и даже без МК

 

 

 

 

 

Marshall Kross
Offline
Зарегистрирован: 19.01.2019

В перерывах от выходных забот немного занимался этой задачей в итоге основной код приобрел такой вид. Теперь подсветка включается и выключается тактовой кнопкой. 

Единственный момент. Т.к. задействовал прерывание attachInterrupt();  вылез жесткий дребезг контактов кнопки, пытался избавится путем задержки но что то не выходит. Возможно где то не так делаю. Посмотрите, будьте любезны. 


#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <iarduino_RTC.h>
#include "DHT.h"
#define DHTPIN 2 
DHT dht(DHTPIN, DHT22);
iarduino_RTC time(RTC_DS3231); 
LiquidCrystal_I2C lcd(0x3F, 16, 2);
boolean button_flag = 1;
int ledPin = 13;
unsigned long last_time;

void setup() {
    dht.begin();
    lcd.init(); 
    delay(200);
    Serial.begin(9600);
    time.begin();  
    pinMode(3, INPUT_PULLUP);
    attachInterrupt(1, button, FALLING);
    
}

void loop() {
  if(button_flag) {
    lcd.backlight();
  if (millis() - last_time > 100) {
  }
  }  else {
  if (millis() - last_time > 100) {
  }
    lcd.noBacklight();
  }
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    float f = dht.readTemperature(true);
    if(millis()%1000==0){ 
    lcd.setCursor(0, 0);
    lcd.print(time.gettime("H"));
    lcd.setCursor(2, 0);
    lcd.print(":");
    lcd.setCursor(3, 0);
    lcd.print(time.gettime("i"));
    lcd.setCursor(5, 0);
    lcd.print(":");
    lcd.setCursor(6, 0);
    lcd.print(time.gettime("s"));
    lcd.setCursor(9, 0);
    lcd.print(time.gettime("d"));
    lcd.setCursor(12, 0);
    lcd.print(time.gettime("Y"));
    lcd.setCursor(0, 1);
    lcd.print("t=");
    lcd.setCursor(3, 1);
    lcd.print(t, 1);
    lcd.setCursor(7, 1);
    lcd.print("c");
    lcd.setCursor(9, 1);
    lcd.print("h=");
    lcd.setCursor(11, 1);
    lcd.print(h, 1);
    lcd.print("%"); 
    delay(1); 
    }
}
void button(){
  button_flag = !button_flag;
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

задействовать для кнопки целое прерывание не очень хорошая идея

Marshall Kross
Offline
Зарегистрирован: 19.01.2019

Подскажите пожалуйста как надо. И почему идея плоха? Хочется понять. Буду очень признателен.

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

ua6em пишет:

задействовать для кнопки целое прерывание не очень хорошая идея


Это ведь, как для одной тарелки холодца целого кабанчика заколоть!! ;)))))

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

Marshall Kross пишет:
Подскажите пожалуйста как надо. И почему идея плоха? Хочется понять. Буду очень признателен.

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

Как правильно сделать - смотри предпоследний пример головного сообщения http://arduino.ru/forum/programmirovanie/rabota-s-knopkami-v-pomoshch-novichku

 

gfx125
Offline
Зарегистрирован: 27.05.2017

Marshall Kross пишет:
Подскажите пожалуйста как надо.

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

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <iarduino_RTC.h>
#include "DHT.h"
#define DHTPIN 2 
DHT dht(DHTPIN, DHT22);
iarduino_RTC time(RTC_DS3231); 
LiquidCrystal_I2C lcd(0x3F, 16, 2);
boolean button_flag = 0;
int led_backlight=1;
int ledPin = 13;
unsigned long last_time=0;

void setup() {
     dht.begin();
    lcd.init(); 
    delay(200);
    Serial.begin(9600);
   time.begin();  
    pinMode(3, INPUT_PULLUP);
    pinMode(13,OUTPUT);
  //  attachInterrupt(1, button, FALLING);
    
}

void loop() {
  
if(digitalRead(3)==HIGH && button_flag==0) button_flag=1;
                     

if(digitalRead(3)==LOW && button_flag==1)
     
     {      
 if(led_backlight==1)
      {
        lcd.backlight();
        led_backlight=0;
      }
        
else {
  lcd.noBacklight();
   led_backlight=1;
}

button_flag=0;

if (millis() - last_time > 100) last_time=millis(); 
     } 


  
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    float f = dht.readTemperature(true);
    if(millis()%1000==0){ 
    lcd.setCursor(0, 0);
    lcd.print(time.gettime("H"));
    lcd.setCursor(2, 0);
    lcd.print(":");
    lcd.setCursor(3, 0);
    lcd.print(time.gettime("i"));
    lcd.setCursor(5, 0);
    lcd.print(":");
    lcd.setCursor(6, 0);
    lcd.print(time.gettime("s"));
    lcd.setCursor(9, 0);
    lcd.print(time.gettime("d"));
    lcd.setCursor(12, 0);
    lcd.print(time.gettime("Y"));
    lcd.setCursor(0, 1);
    lcd.print("t=");
    lcd.setCursor(3, 1);
    lcd.print(t, 1);
    lcd.setCursor(7, 1);
    lcd.print("c");
    lcd.setCursor(9, 1);
    lcd.print("h=");
    lcd.setCursor(11, 1);
    lcd.print(h, 1);
    lcd.print("%"); 
    delay(1); 
    }
}

 

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Поставьте кнопку с фиксацией или тумблер, зачем извращаться-то в данном вопросе?

AlexanderNO
Offline
Зарегистрирован: 08.11.2018

sadman41 пишет:

Поставьте кнопку с фиксацией или тумблер, зачем извращаться-то в данном вопросе?

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

sadman41
Offline
Зарегистрирован: 19.10.2016

Можно даже этой кнопкой в космос запускать ракету.

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

Marshall Kross
Offline
Зарегистрирован: 19.01.2019

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

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

Marshall Kross
Offline
Зарегистрирован: 19.01.2019

gfx125 пишет:

Marshall Kross пишет:
Подскажите пожалуйста как надо.

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

Спасибо. Вот оно, как говорится рядом было. Я ковырял вот этот кусок кода. Только у меня подсвет включался по нажатию и отключался когда я отпускал кнопку.

boolean butt_flag = 0;
boolean butt;
boolean led_flag = 0;
unsigned long last_press;

void setup() {
  pinMode(3, INPUT_PULLUP);
  Serial.begin(9600);
  pinMode(13, OUTPUT);
}

void loop() {
  butt = !digitalRead(3); // считать текущее положение кнопки
  
  if (butt == 1 && butt_flag == 0 && millis() - last_press > 100) {
    butt_flag = 1;
    Serial.println("On");
    led_flag = !led_flag;
    digitalWrite(13, led_flag);
    last_press = millis();
  }
  if (butt == 0 && butt_flag == 1) {
    butt_flag = 0;
    Serial.println("Off");
  }
}
Виктор50
Offline
Зарегистрирован: 05.12.2019

Добрый день! Я начинающий программист-любитель.Ни одного скетча еще не написал. Но встретил в сети любопытную систему программирования FLProg называется. Программирование с помощью соединения графических изображений элементов. Таких систем видимо существует несколько, но я попал на эту. Захотелось сделать на базе Ардуино нано схему управления насосом пневомобака  установленного в колодце, дабы заменить механические реле давления аналоговым датчиком давления. И, о чудо, все получилось с нескольких попыток. 

Попробовал порешать Вашу проблему, получился вот такой скетч:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C _lcd1(0x27, 16, 2);
int _dispTempLength1=0;
boolean _isNeedClearDisp1;

int _disp6oldLength = 0;
bool _D1B2 = 0;
bool _bounseInputD2S = 0;
bool _bounseInputD2O = 0;
unsigned long _bounseInputD2P = 0UL;
bool _trgt1 = 0;
bool _trgt1I = 0;
void setup()
{
Wire.begin();
delay(10);
pinMode(2, INPUT_PULLUP); 

_lcd1.init();
_lcd1.noBacklight();
_bounseInputD2O =  digitalRead(2);
}
void loop()
{if (_isNeedClearDisp1) {_lcd1.clear(); _isNeedClearDisp1= 0;}

bool  _bounceInputTmpD2 =  (digitalRead (2));

if (_bounseInputD2S) 
    {
     if (millis() >= (_bounseInputD2P + 40)) 
         {_bounseInputD2O= _bounceInputTmpD2; _bounseInputD2S=0;}
     }
else
    {
     if (_bounceInputTmpD2 != _bounseInputD2O )
         {_bounseInputD2S=1; _bounseInputD2P = millis();} 
      } 


//Плата:1
if (!(0)) {
_dispTempLength1 = (String("Out of date")).length();
if (_disp6oldLength > _dispTempLength1) {_isNeedClearDisp1 = 1;} 
_disp6oldLength = _dispTempLength1;
_lcd1.setCursor(int((16 - _dispTempLength1)/2), 1);
_lcd1.print(String("Out of date"));
} else {
if (_disp6oldLength > 0) {_isNeedClearDisp1 = 1; _disp6oldLength = 0;} 
}
bool  _tmp1 = !(_bounseInputD2O);
if (_tmp1)  { if (! _trgt1I) _trgt1 = ! _trgt1; } 
_trgt1I = _tmp1; 
if(_trgt1) {if(! _D1B2){_lcd1.backlight(); _D1B2=1; }} else {if(_D1B2){_lcd1.noBacklight(); _D1B2=0; }}

}

 

 
Работает, как вы хотели. Может подойдет?
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Немедленно выкинь каку!!!!

bwn
Offline
Зарегистрирован: 25.08.2014

Во, во, и руки с мылом помой.))))

b707
Offline
Зарегистрирован: 26.05.2017

Виктор50 - для обсуждения программ, написанных на ФЛПРОГе и ей подобных системах существуют специальные форумы. На нашем форуме не стоит даже упоминать, что вы этой системой пользуетесь - с вами после этого и пары слов никто не захочет сказать.

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

строка 31 - неверная работа со временем
строка 42 - бредовое условие
строки 43 и 47 - неаккуратное отношение к памяти - повтороное использование одной и тоже строки в формате String

Система FLProg генерит монструозный, абсолютно нечитаемый код,  который содержит много корявых конструкций и не слишком эффективно работает. Зачем пользоваться этим костылем, когда вручную можно написать короче и красивее? :)

Для многих здешних обиталей программирование - это творчество, это игра, это похоже на флирт. А вы нам предлагаете флиртовать с надувной куклой из секс-шопа? :)