17 сентября 2017 г.

Метеостанция на arduino #6. LCD дисплей 1602

Нашел у себя ЖК дисплей 1602 с переходником на интерфейс I2C (что за зверь такой - см. здесь).

Измерил энергопотребление: 5,4 мА (кратковременно до 6,5 мА) потребляет сам дисплей с переходником и 19 мА - подсветка при напряжении питания 5 В. Выпаял светодиод питания на I2C переходнике - ток снизился до 2,3 мА (3,4 в пике). Подсветку повесил на PWM-пин (D5), благодаря чему ее ток можно значительно снизить, при этом информация на дисплее останется вполне читабельной. Питание самого дисплея с переходником коммутируется пином D4.
Обнаружилась одна неприятная особенность дисплея: при уменьшении напряжения питания "плывет" контрастность, приходится подкручивать подстроечный резистор на I2C переходнике. Пока придумал только такой вариант - внешний подстроечный резистор для управления контрастностью дисплея. Пожалуй оставлю этот дисплей в проекте.
Текущая схема:

Для дисплея использовал библиотеку отсюда. У моей версии I2С переходника адрес 0x3F.
Вернулся к setup() и loop(), так как не удалось "завести" дисплей без них.
Собственно код (просыпаемся по нажатию кнопки, показываем в течение 5 секунд приветствие на дисплее и засыпаем):
//код++
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <util/delay.h>

// для ЖК дисплея 1602 с I2C

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// кнопка

#define BUTTON_PIN        2

// Подключение дисплея

// LCD 1602 I2C <---> Arduino
// GND <------------> GND
// VCC <------------> D4
// SDA <--------> A4
// SCL <--------> A5
// A <--------------> D5
#define LCD_POWER_PIN       4
#define LCD_BACKLIGHT_PIN   5
#define LCD_BACKLIGHT_VALUE 50

// устанавливаем адрес дисплея

LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

void m_sleep();

void m_wake_up();
void lcd_on();
void lcd_off();
void lcd_show();

void setup() {

  // все пины на выход и в низкий уровень
  for (byte i = 0; i <= A3; i++) {
    pinMode(i, OUTPUT);    
    digitalWrite(i, LOW);
  }

  // установливаем на пине с кнопкой подтяжку к VCC

  pinMode(BUTTON_PIN, INPUT);
  digitalWrite(BUTTON_PIN, HIGH);
  
  // устанавливаем обработчик прерывания INT0
  attachInterrupt(0, m_wake_up, FALLING);
}

void loop() {

  // засыпаем
  m_sleep();
      
  lcd_on();
  lcd_show();
  _delay_ms(5000);
  lcd_off();  
}

void m_sleep() {
  // все пины на выход и в низкий уровень
  for (byte i = 0; i <= A7; i++) {
    // на второй ноге висит прерывание, поэтому ее не трогаем
    if (i == 2) continue;
    pinMode(i, OUTPUT);    
    digitalWrite(i, LOW);
  }
  
  // отключаем АЦП
  ADCSRA = 0;  

  // отключаем всю периферию

  power_all_disable ();

  // устанавливаем режим сна - самый глубокий, здоровый сон :)

  set_sleep_mode (SLEEP_MODE_PWR_DOWN);  

  // разрешаем спящий режим

  sleep_enable();

  // разрешаем прерывания

  sei();
  
  // собственно засыпаем
  sleep_cpu();              

}


void m_wake_up () {


  // запрещаем прерывания

  cli();
  
  // запрещаем режим сна
  sleep_disable();

  // включаем периферию

  power_all_enable();
}

///////////////////////////////////////////////////////////////////////////////

// LCD 1602 I2C

void lcd_on() {
 
  digitalWrite(LCD_POWER_PIN, HIGH);
  analogWrite(LCD_BACKLIGHT_PIN, LCD_BACKLIGHT_VALUE); 
}

void lcd_off() {

  digitalWrite(LCD_POWER_PIN, LOW);
  digitalWrite(LCD_BACKLIGHT_PIN, LOW);
}

void lcd_show() {
 
  // инициализируем дисплей
  lcd.begin(16,2);  
   
  lcd.setCursor(0,0);
  lcd.print("Hello, world!"); 
}
//код--

Или здесь.


Комментариев нет: