Попытался научить русскому языку свой Arduino Mega 2560, ЖК индикатор WH1602BYYK-CTK по ссылке загрузив библиотеку [сообщение #11375772] - не получается. Библиотека загрузилась, но не работает.
Помогите настроить. Я индикатор и спиртом протирал и огурчик соленый ему предлагал - не помогает.
Аппаратная платформа Arduino для автоматизации наших процессов
alekslug
Научный сотрудник
винокур, Лобня.
5.2K 1.7K
Отв.600 29 Окт. 13, 12:45
asvar
Специалист
Крога
163 30
Отв.601 29 Окт. 13, 12:51, через 7 мин
я парился долго, но тоже так и не одолел, видать такая разновидность экрана.
делал иначе, но правда дополнительные телодвижения нужны. Не помню где это нашел, тачка не моя, но работает
Потом в коде вывод на экран делаю функцией printToScreen("НАЖМИТЕ КНОПКУ", "ВВЕРХ");
Может кто доведёт до ума и сделает этот как библиотеку, но мои знания это не позволяют.
делал иначе, но правда дополнительные телодвижения нужны. Не помню где это нашел, тачка не моя, но работает
//-----------------------------------------------------------------
//Кусок кода отвечающий за русскую трансляцию букв
//Для вывода на дисплей русских символов используйте функцию
//printToScreen("", "") первый аргумент - верхняя строка, второй - нижняя
//Ахтунг! Не используйте маленькие буквы "ё" и "с",
//их коды в младшей части совпадают с буквами 'Б' и 'Е'
//из-за отсутствияих нормальной работы с юникодом не представляю как это поправить
//-----------------------------------------------------------------
//Список загруженных недостающих букв
char loadedLetters[9];
//Русская кодировка недостающих букв
//В двоичном виде получается наглядно отобразить очертание символов,
//но получается очень длинная портянка, поэтому сделал в HEX
byte rusLetterB[8] = {0x1F,0x11,0x10,0x1E,0x11,0x11,0x1E,0}; //Б
byte rusLetterG[8] = {0x1F,0x11,0x10,0x10,0x10,0x10,0x10,0}; //Г
byte rusLetterD[8] = {0x0F,0x05,0x05,0x05,0x09,0x11,0x1F,0x11}; //Д
byte rusLetterGH[8] = {0x15,0x15,0x15,0x0E,0x15,0x15,0x15,0}; //Ж
byte rusLetterI[8] = {0x11,0x11,0x13,0x15,0x19,0x11,0x11,0}; //И
byte rusLetterIY[8] = {0x0A,0x15,0x13,0x15,0x19,0x11,0x11,0}; //Й
byte rusLetterL[8] = {0x0F,0x05,0x05,0x05,0x05,0x15,0x09,0}; //Л
byte rusLetterP[8] = {0x1F,0x11,0x11,0x11,0x11,0x11,0x11,0}; //П
byte rusLetterF[8] = {0x04,0x0E,0x15,0x15,0x15,0x0E,0x04,0}; //Ф
byte rusLetterC[8] = {0x11,0x11,0x11,0x11,0x11,0x11,0x1F,1}; //Ц
byte rusLetterCH[8] = {0x11,0x11,0x11,0x0F,0x01,0x01,0x01,0}; //Ч
byte rusLetterSH[8] = {0x15,0x15,0x15,0x15,0x15,0x15,0x1F,0}; //Ш
byte rusLetterSCH[8] = {0x15,0x15,0x15,0x15,0x15,0x15,0x1F,1}; //Щ
byte rusLetterTZN[8] = {0x18,0x08,0x08,0x0E,0x09,0x09,0x0E,0}; //Ъ
byte rusLetterEI[8] = {0x11,0x11,0x11,0x19,0x15,0x15,0x19,0}; //Ы
byte rusLetterEE[8] = {0x0E,0x11,0x01,0x07,0x01,0x11,0x0E,0}; //Э
byte rusLetterYU[8] = {0x12,0x15,0x15,0x1D,0x15,0x15,0x12,0}; //Ю
byte rusLetterYA[8] = {0x0F,0x11,0x11,0x0F,0x05,0x09,0x11,0}; //Я
//Функция ищет символ среди дополнительно загруженных (максимум ,
//при необходимости и если есть место символ загружается в LCD
char loadAndGetChar(char c, uint8_t *letterMap) {
int ix = 9;
//Ищем букву в уже загруженных символах
for (int i = 1; i < ix; i++) {
if (c == loadedLetters) {
return char(i);
}
else if (loadedLetters == ' ') {
ix = i;
break;
}
}
//Если загружено 8 символов, то выводим пробел
if (ix == 9) {
return ' ';
}
//Загружаем новый символ в LCD
lcd.createChar(ix, letterMap);
loadedLetters[ix] = c;
return char(ix);
}
//Функция возвращает локализованный символ или пробел,
//если не хватает места в памяти под дополнительные символы
char getTranslatedLetter(char c) {
switch (c) {
case 'А' : case 'а' : return 'A';
case 'Б' : case 'б' : return loadAndGetChar(c, rusLetterB);
case 'В' : case 'в' : return 'B';
case 'Г' : case 'г' : return loadAndGetChar(c, rusLetterG);
case 'Д' : case 'д' : return loadAndGetChar(c, rusLetterD);
case 'Е' : case 'е' : return 'E';
case 'Ё' : return 'E';
case 'Ж' : case 'ж' : return loadAndGetChar(c, rusLetterGH);
case 'З' : case 'з' : return '3';
case 'И' : case 'и' : return loadAndGetChar(c, rusLetterI);
case 'Й' : case 'й' : return loadAndGetChar(c, rusLetterIY);
case 'К' : case 'к' : return 'K';
case 'Л' : case 'л' : return loadAndGetChar(c, rusLetterL);
case 'М' : case 'м' : return 'M';
case 'Н' : case 'н' : return 'H';
case 'О' : case 'о' : return 'O';
case 'П' : case 'п' : return loadAndGetChar(c, rusLetterP);
case 'Р' : case 'р' : return 'P';
case 'С' : return 'C';
case 'Т' : case 'т' : return 'T';
case 'У' : case 'у' : return 'y';
case 'Ф' : case 'ф' : return loadAndGetChar(c, rusLetterF);
case 'Х' : case 'х' : return 'X';
case 'Ц' : case 'ц' : return loadAndGetChar(c, rusLetterC);
case 'Ч' : case 'ч' : return loadAndGetChar(c, rusLetterCH);
case 'Ш' : case 'ш' : return loadAndGetChar(c, rusLetterSH);
case 'Щ' : case 'щ' : return loadAndGetChar(c, rusLetterSCH);
case 'Ъ' : case 'ъ' : return loadAndGetChar(c, rusLetterTZN);
case 'Ы' : case 'ы' : return loadAndGetChar(c, rusLetterEI);
case 'Ь' : case 'ь' : return 'b';
case 'Э' : case 'э' : return loadAndGetChar(c, rusLetterEE);
case 'Ю' : case 'ю' : return loadAndGetChar(c, rusLetterYU);
case 'Я' : case 'я' : return loadAndGetChar(c, rusLetterYA);
default : return c;
}
}
//Функция печатает верхнюю и нижнюю строку на LCD
void printToScreen(char *st1, char *st2) {
//Очистка списка загруженных кастомных символов
for (int i = 0; i < 9; i++) loadedLetters = ' ';
//Печать первой строки
char result1[17] = " "; int ix = 0;
for (int i = 0; i < 32; i++) {
char c = getTranslatedLetter(st1);
if (byte(c) == 0) break;
else if (byte(c) != 0xD0 && byte(c) != 0xD1) {
result1[ix] = c;
ix++;
}
}
lcd.setCursor(0,0);
lcd.print(result1);
//Печать второй строки
char result2[17] = " "; ix = 0;
for (int i = 0; i < 32; i++) {
char c = getTranslatedLetter(st2);
if (byte(c) == 0) break;
else if (byte(c) != 0xD0 && byte(c) != 0xD1) {
result2[ix] = c;
ix++;
}
}
lcd.setCursor(0,1);
lcd.print(result2);
}
//-----------------------------------------------------------------
//Конец кода отвечающего за русскую трансляцию букв
//-----------------------------------------------------------------
Потом в коде вывод на экран делаю функцией printToScreen("НАЖМИТЕ КНОПКУ", "ВВЕРХ");
Может кто доведёт до ума и сделает этот как библиотеку, но мои знания это не позволяют.
alekslug
Научный сотрудник
винокур, Лобня.
5.2K 1.7K
Отв.602 29 Окт. 13, 20:16
Частично можно решить эту задачу.
#include <LiquidCrystal.h>
//Создаем объект для работы с дисплеем.
//При создании указываем номера портов
//в порядке RS, E, DB4, DB5, DB6, DB7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
void setup() {
//Выставлем число столбцов и строк
lcd.begin(16, 2);
//Выводим текст
lcd.print("\240\341\241\261\340\242\243\244\246\252\260\342\247\250\251\255");
}
void loop() {
//Выставляем курсор во 2-ю строку,
//1й столбец (счет идет с 0, поэтому
//строка номер 1, стобец номер 0)
lcd.setCursor(0, 1);
//Выводим число секунд со старта
lcd.print(millis()/1000);
}
alekslug
Научный сотрудник
винокур, Лобня.
5.2K 1.7K
Отв.603 29 Окт. 13, 21:22
Калибруем кнопки. Русский шрифт.
#include <LiquidCrystal.h> //подключаем библиотеку работы с ЖКИ
// инициализация библиотеки дисплея. Аргументы - пины на которые подключен LCD
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int butPin = 0; // вход кнопок
int butPush = 0; // код нажатой кнопки
void setup() {
// говорим сколько строк и столбцов в нашем дисплее
lcd.begin(16, 2);
lcd.print("P\251CCK\245\246 \254P\245\252T"); // печатаем строку
delay(5000); // ждем 2 секунды
lcd.clear(); // очищаем дисплей
lcd.print("KA\247\245\240P\251EM KHO\250K\245"); // печатаем строку
}
void loop() {
lcd.setCursor(0,1); // устанавливаем курсор во вторую строку
lcd.print(analogRead(butPin)); //печатаем значение возвращаемое функцией analogRead
// значение от 0 до 1023 пропорционально поданному напряжению
lcd.print(" "); // строка пробелов нужна чтобы затереть символы от предыдущего замера если
// текущее значение имеет меньше знаков чем прошлое
delay(100); // задержка в 0,1 секунды
}
KD
Научный сотрудник
Танкоград
1.4K 648
Отв.604 07 Нояб. 13, 14:30
немного дополню
далеко не всегда дисплей имеет набор кириллических символов
метод предложенный asvar позволяет загрузить недостающие символы в контроллер дисплея, соответственно работать будет с любым экранчиком.
в коде что приводит alekslug подразумевается что символы уже есть (сообщается из код).
alekslug, твой дисплей, судя по маркировке, должен поддерживать кириллицу.
далеко не всегда дисплей имеет набор кириллических символов
метод предложенный asvar позволяет загрузить недостающие символы в контроллер дисплея, соответственно работать будет с любым экранчиком.
в коде что приводит alekslug подразумевается что символы уже есть (сообщается из код).
alekslug, твой дисплей, судя по маркировке, должен поддерживать кириллицу.
alekslug
Научный сотрудник
винокур, Лобня.
5.2K 1.7K
Отв.605 07 Нояб. 13, 15:03, через 34 мин
Да, WH1602B-YYK-CTK кириллицу поддерживает. Знаний пока не хватает.
asvar
Специалист
Крога
163 30
Отв.606 18 Нояб. 13, 15:25
По времени. Если через 15 минут температура не вернулась на исходную позицию процесс надо закончить.alekslug, 23 Окт. 13, 15:46На выходных тестировал дописанный код, ректифицировал 27л 40% сэма. Выяснилось что ждать СТОПа длительностью 15 минут и более смысла нет. Я остановился на 8 минутах. Пока думаю есть ли в этом смысл, т.к отбор в самом конце процесса уменьшается очень сильно, стоит ли морочить голову пару часов за пол литра спирта.
Вобщем, всё получается отлично, для своей колонны в скором будущем допишу полный автомат ректификации (очень надеюсь).
alekslug
Научный сотрудник
винокур, Лобня.
5.2K 1.7K
Отв.607 18 Нояб. 13, 18:50
asvar,скетчем поделишься?, мне ещё далеко до результата. Програмист из меня пока плохой. Обычно я заканчиваю процесс ректификации при Т. в кубе 96*С , что соответствует остатку спирта в кубе несколько процентов, переводом колонны на режим дистилляции хвостов. Т.е. нагрев и отбор на полную мощность включаю. Но иногда может понадобиться режим ректификации до упора, до полного истощения спирта из куба и колонны. Ардуино позволяет гибко подойти к решению этого вопроса. Колонны могут быть разной производительности. Имеет смысл заложить в программу регулировать этот параметр.
asvar
Специалист
Крога
163 30
Отв.608 19 Нояб. 13, 18:58
Из меня программист не лучше. Скетч вылаживаю. Но после последней ректификации уже пишу код дальше, но выложу по итогам.
По тому что выкладываю - пока регулировка отбора и мощности руками (записываю показания с экрана, потом буду их вводить из меню с возможностью изменения). Регулирую мощность один раз, после разгона колоны, уменьшаю крутилкой до величины подобраной эксперементально, всё про мощность на этом забываю.
По клапану отбора - кручу его 2 раза. Первый - после работы колонны на себя, также устанавливаю эксперементально подобраную величину (100мл/ч) и иду спать. Просыпаюсь - головы вот-вот отберуться, нюхаю всё проверяю, меняю тару.
Второй раз - для отбора тела (так же эксперементально подобранная величина +- 1400мл/час).
Всё дальше можно отдыхать.
Что есть: проверка на аварию в дефлегматоре, если затоп - выключаем нагрев. Режим СТАРТ/СТОП - при достижении в 20 см от низа колонны (царга 2 метра) температуры 78.2 - срабатывает СТОП.
Чего пока нет, но пишется:
Автоматом после разгона переходить на работу на себя, понижая мощность.
После работы на себя, автоматом отбирать головы
С помощью гидравлического автостопа и датчика уровня голов в банке, автоматически переходить в режим отбора тела.
Ждать пока длительность СТОП не будет больше 8 минут и завершать процесс.
Код корявый и не оптимизирован, как есть, Всё откладываю на потом, но понимаю что так и будет.
По тому что выкладываю - пока регулировка отбора и мощности руками (записываю показания с экрана, потом буду их вводить из меню с возможностью изменения). Регулирую мощность один раз, после разгона колоны, уменьшаю крутилкой до величины подобраной эксперементально, всё про мощность на этом забываю.
По клапану отбора - кручу его 2 раза. Первый - после работы колонны на себя, также устанавливаю эксперементально подобраную величину (100мл/ч) и иду спать. Просыпаюсь - головы вот-вот отберуться, нюхаю всё проверяю, меняю тару.
Второй раз - для отбора тела (так же эксперементально подобранная величина +- 1400мл/час).
Всё дальше можно отдыхать.
Что есть: проверка на аварию в дефлегматоре, если затоп - выключаем нагрев. Режим СТАРТ/СТОП - при достижении в 20 см от низа колонны (царга 2 метра) температуры 78.2 - срабатывает СТОП.
Чего пока нет, но пишется:
Автоматом после разгона переходить на работу на себя, понижая мощность.
После работы на себя, автоматом отбирать головы
С помощью гидравлического автостопа и датчика уровня голов в банке, автоматически переходить в режим отбора тела.
Ждать пока длительность СТОП не будет больше 8 минут и завершать процесс.
Код корявый и не оптимизирован, как есть, Всё откладываю на потом, но понимаю что так и будет.
asvar
Специалист
Крога
163 30
Отв.609 25 Нояб. 13, 21:06
Дописали тут совместными усилиями код, боль мень привели в порядок. По замыслу - полный автомат (для моей колонны). На выходных будет проверка боем. Кроме всего что описывал, еще добавилась возможность изменения основных параметров из меню настройки, перед запуском процесса. И приделал еще тумблер для переключения режимов управления колонной (ручной режим и авторежим) - переключать можно в любое время работы колонны.
После обкатки выложу код и распиновку подключения к ардуине всех обвесов.
После обкатки выложу код и распиновку подключения к ардуине всех обвесов.
msg31
Научный сотрудник
Барнаул
4.6K 2.5K
Отв.610 27 Нояб. 13, 18:32
Программа "Термометр винокура". По заданной температуре, умноженной на 100 (например 9678 - это 96,78) выдает содержание спирта в объемных частях в формате, умноженном на 10 (например 455 - это 45.5 объемных). Точность проверена по калькулятору Руди и в худшем случае составляет +-0.2 объемных, самая большая погрешность после температуры 99 - до 0.5 объемных (это сделано специально по причине экономии памяти на Atmega16). Написана на С, но может быть легко переведена на ардуиновский язык.
eeprom unsigned char tempr[47]={80,10,10,15,110,100,85,85,80,80,75,70,60,50,30,80,50,20,70,40,20,70,30,30,45,55,40,30,50,70,72,48,60,30,45,45,40,25,15,20,30,25,35,10,20,10,5};
eeprom unsigned char spirt[47]={99,11,11,11,108, 88,70,41,45,37,31,25,22,19,17,15,14,11,11,10,10,16, 8, 7,13,11, 9, 9,11,11,11,10,10, 6,12,11,11, 8, 9,10,11, 8,18, 4,10,11,9};
int GetSpirt(unsigned int T)
{
int T1=7815;
int S1=972;
char n=46;
if (T<T1) return -1;
while (n>=0)
{
if (T<T1+tempr[n])
{
//Нашли промежуток для интерполящии
S1 = S1 - (T-T1)*spirt[n] / tempr[n];
return S1;
}
T1=T1+tempr[n];
S1=S1-spirt[n];
n--;
}
return 0;
}
eeprom unsigned char tempr[47]={80,10,10,15,110,100,85,85,80,80,75,70,60,50,30,80,50,20,70,40,20,70,30,30,45,55,40,30,50,70,72,48,60,30,45,45,40,25,15,20,30,25,35,10,20,10,5};
eeprom unsigned char spirt[47]={99,11,11,11,108, 88,70,41,45,37,31,25,22,19,17,15,14,11,11,10,10,16, 8, 7,13,11, 9, 9,11,11,11,10,10, 6,12,11,11, 8, 9,10,11, 8,18, 4,10,11,9};
int GetSpirt(unsigned int T)
{
int T1=7815;
int S1=972;
char n=46;
if (T<T1) return -1;
while (n>=0)
{
if (T<T1+tempr[n])
{
//Нашли промежуток для интерполящии
S1 = S1 - (T-T1)*spirt[n] / tempr[n];
return S1;
}
T1=T1+tempr[n];
S1=S1-spirt[n];
n--;
}
return 0;
}
Bitner
Научный сотрудник
NN
950 416
Отв.611 27 Нояб. 13, 20:45
Библиотека для создания Меню на дисплеях
hxxp://forum.amperka.ru/threads/%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F-%D0%9C%D0%B5%D0%BD%D1%8E-%D0%BD%D0%B0-%D0%B4%D0%B8%D1%81%D0%BF%D0%BB%D0%B5%D1%8F%D1%85.1815/
ММХО погонял в протеусе, понравилось.
hxxp://forum.amperka.ru/threads/%D0%91%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B0-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F-%D0%9C%D0%B5%D0%BD%D1%8E-%D0%BD%D0%B0-%D0%B4%D0%B8%D1%81%D0%BF%D0%BB%D0%B5%D1%8F%D1%85.1815/
ММХО погонял в протеусе, понравилось.
asvar
Специалист
Крога
163 30
Отв.612 28 Нояб. 13, 00:41
Программа "Термометр винокура". По заданной температуре, умноженной на 100 (например 9678 - это 96,78) выдает содержание спирта в объемных частях в формате, умноженном на 10 (например 455 - это 45.5 объемных). Точность проверена по калькулятору Руди и в худшем случае составляет +-0.2 объемных, самая большая погрешность после температуры 99 - до 0.5 объемных (это сделано специально по причине экономии памяти на Atmega16). Написана на С, но может быть легко переведена на ардуиновский язык.Это получится типа того что игорь223 начал продавать у себя на сайте?
msg31, 27 Нояб. 13, 18:32
http://samogon-i-vodka.ru/...2129/item_7653/
msg31
Научный сотрудник
Барнаул
4.6K 2.5K
Отв.613 28 Нояб. 13, 04:05
Это получится типа того что игорь223 начал продавать у себя на сайте?Ну да, принцип тот же.
http://samogon-i-vodka.ru/...2129/item_7653/
asvar, 28 Нояб. 13, 00:41
mihase
Специалист
Краснодар
165 74
Отв.614 01 Дек. 13, 03:08
ММХО погонял в протеусе, понравилось.Может кто тут на дуинке тестил? Бьюсь на Меге 2560 - ошибки вылазят, использую библиотеку LiquidCrystal_I2C для 20х4, может в этом проблема, скетч написан для стандартной LiquidCrystal...
Bitner, 27 Нояб. 13, 20:45
lakmus
Специалист
С-Петербург
196 49
Отв.615 02 Дек. 13, 01:49
Может кто тут на дуинке тестил? Бьюсь на Меге 2560 - ошибки вылазят, использую библиотеку LiquidCrystal_I2C для 20х4, может в этом проблема, скетч написан для стандартной LiquidCrystal...попробуй i2c адрес 0x27
mihase, 01 Дек. 13, 03:08
SDA и SCL к +5V подтянул через 10к?
контрастность крутил?
а по хорошему - надо сначала запустить его на примере для LiquidCrystal_I2C
mihase
Специалист
Краснодар
165 74
Отв.616 02 Дек. 13, 03:59
попробуй i2c адрес 0x27Дык так то экран работает прекрасно, только адрес у меня 0х3F, а я вот менюху выше указанную не могу загрузить, проверку делаю, куча ошибок..
lakmus, 02 Дек. 13, 01:49
lakmus
Специалист
С-Петербург
196 49
Отв.617 02 Дек. 13, 07:19
Дык так то экран работает прекрасно, только адрес у меня 0х3F, а я вот менюху выше указанную не могу загрузить, проверку делаю, куча ошибок..кроме очевидной замены в проекте на LiquidCrystal_I2C и его инициализац.
mihase, 02 Дек. 13, 03:59
надо поменять все вхождения LiquidCrystal в библиотечных (MyMenu) файлах на LiquidCrystal_I2C
mihase
Специалист
Краснодар
165 74
Отв.618 03 Дек. 13, 01:41
надо поменять все вхождения LiquidCrystallakmus, 02 Дек. 13, 07:19Согласен. А, пожалуйста, тыкни пальцем, куда смотреть, и как это провернуть?
lakmus
Специалист
С-Петербург
196 49
Отв.619 03 Дек. 13, 02:31, через 51 мин
вот уже измененные библиотеки MyMenu: так наверн. проще!
зы: добавил файл проекта для и2с (MyMenuAmperkaI2C)
в ардуинной оболочке пашет...
[size=2pt]а из под NetBeans - увы ,[/size]
зы: добавил файл проекта для и2с (MyMenuAmperkaI2C)
в ардуинной оболочке пашет...
[size=2pt]а из под NetBeans - увы ,[/size]