
Заказал я интернете Arduino Mega и дисплей 20x4 знакомест для великой цели измерения температуры с помощью пачки пирометров. Но великой цели я не достиг, потому что без преобразователей RS232-TTL ничего не получается. Преобразователи я заказал, но зуд в руках покоя не давал, поэтому решил сделать что-нибудь условно полезное.
Мигать диодом все умеют, поэтому я решил сделать подобие цифрового вольтметра с аналоговой шкалой. Но сначала надо было решить проблему подключения дисплея.
На плате самого дисплея была маркировка "QC2004A", подключен он был через микросхему с маркировкой "PCF8574T". Усиленный гуглинг вывел меня на одну статью, в которой автор довольно подробно расписал инициализацию дисплея в коде. Пришлось выкинут библиотеку "LiquidCrystal" из комплекта Arduino IDE и вместо нее поставить библиотеку со страницы https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads. В отличии от выкинутой эта умеет работать не только дисплеями, подключенными к портам на плате, но и с дисплеями на шине I2C, что и требуется.
Поиск адреса устройства осуществлялся с помощью скетча i2cscanner. А конфигурацию портов определил последовательным перебором параметров, приведенных в статье. Для моего дисплея подошел первый набор:
#define LCD_I2C_ADDR 0x27 // Define I2C Address where the PCF8574T is #define BACKLIGHT 3 #define LCD_EN 2 #define LCD_RW 1 #define LCD_RS 0 #define LCD_D4 4 #define LCD_D5 5 #define LCD_D6 6 #define LCD_D7 7И для подсветки:
lcd.setBacklightPin(BACKLIGHT,POSITIVE);А дальше уже было проще, потому что практически всё есть в примерах. Сложнее было сделать свои символы для обозначения долей на шкале, но проблему решил с помощью конвертеров BIN2HEX. Ну и до кучи познал прелести переключателей (switch) в коде. Для полного лоска добавил еще вывод измерений в COM-порт и получилась вот такая штука:
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
// Init LCD
#define LCD_I2C_ADDR 0x27
#define BACKLIGHT 3
#define LCD_EN 2
#define LCD_RW 1
#define LCD_RS 0
#define LCD_D4 4
#define LCD_D5 5
#define LCD_D6 6
#define LCD_D7 7
// Объект для работы с дисплеем
LiquidCrystal_I2C lcd(LCD_I2C_ADDR,
LCD_EN,
LCD_RW,
LCD_RS,
LCD_D4,
LCD_D5,
LCD_D6,
LCD_D7);
// Массив символов для шкалы
const uint8_t charBitmap[][8] = {
{ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 },
{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 },
{ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c },
{ 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e },
{ 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }
};
// Настройка
void setup() {
// Создание символов из массива
int charBitmapSize = (sizeof(charBitmap ) / sizeof (charBitmap[0]));
// Последовательный порт
Serial.begin(9600);
// Аналоговый вход
pinMode(A0,INPUT);
// Запись созданных символов в дисплей
lcd.begin(20,4);
for ( int i = 0; i < charBitmapSize; i++ )
{
lcd.createChar ( i, (uint8_t *)charBitmap[i] );
}
// Настройка подсветки
lcd.setBacklightPin(BACKLIGHT,POSITIVE);
lcd.setBacklight(HIGH);
// Подготовка надписей
lcd.clear();
lcd.setCursor(0,1);
lcd.print("0 1 2 3 4 5");
}
// Основной код
void loop() {
// Переменные
char A0str[20]="" ;
char str4[20]="" ;
int A0val;
float barl;
// Считывание значения напряжения
A0val=analogRead(A0);
// Расчет напряжения и вывод на первую строку
lcd.home();
lcd.setCursor(0,0);
sprintf(A0str, "U = %4d mV", int(A0val*4.883));
lcd.print(A0str);
// И в последовательный порт
Serial.println(A0str);
// Формирования полоски.
lcd.setCursor(0,2);
// Количество закрашенных мест
barl = 20.0/1024.0*float(A0val);
// Вывод
for ( int i = 0; i < int(barl); i++ )
{
lcd.print(char(4));
}
// Определение и вывод
// конца полоски
int tmp = int(A0val*4.883) % 250;
int partchar = tmp / 50;
if (partchar > 0) {
lcd.print(char(partchar));
} else {
lcd.print(" ");
}
// И добивание пробелами хвоста
for ( int j = barl+2; j < 21; j++ )
{
lcd.print(" ");
}
// Задержка переде следующим замером
delay(100);
}
А со стороны это выглядит так:
