Освой Arduino играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Рассмотрим примеры с термопринтером с интерфейсом TTL.
Популярной библиотекой для работы с принтером является библиотека adafruit/Adafruit-Thermal-Printer-Library. Устанавливайте через менеджер библиотек в Arduino IDE.
Будем использовать программную шину UART. Мы можем назначить функции TX и RX шины для любых выводов Arduino UNO. Выводы назначаются при объявлении объекта библиотеки SoftwareSerial:
SoftwareSerial mySerial(5, 6); // mySerial(RX, TX)
Библиотека снабжена несколькими примерами для показа всех основных возможностей принтера: A_printertest, B_charsets, C_barcodes, bitmapImageConvert. Немного видоизменённые примеры представлены ниже.
#include <SoftwareSerial.h>
#include <Adafruit_Thermal.h>
// Объявляем объект библиотеки SoftwareSerial,
// указывая выводы Arduino: RX = 5 (зелёный), TX = 6 (синий). Можно назначить другие выводы Arduino
#define RX_PIN 5
#define TX_PIN 6
SoftwareSerial mySerial(RX_PIN, TX_PIN);
// Объявляем объект библиотеки Adafruit_Thermal, указывая ссылку на созданный объект mySerial
Adafruit_Thermal printer(&mySerial);
void setup() {
// Инициируем передачу данных по программной шине UART на скорости 9600.
// Функцию следует вызвать до вызова функции printer.begin!
mySerial.begin(9600);
// Инициируем работу с термопринтером.
// В качестве параметра можно указать время нагрева пикселей от 3 (0,03 мс) до 255 (2,55 мс),
// чем выше тем темнее пиксели. Значение по умолчанию = 120 (1,20 мс)
printer.begin();
printer.setSize('L'); // Устанавливаем крупный размер шрифта 'L' (Large)
printer.println("Large"); // Выводим текст
printer.setSize('M'); // Устанавливаем средний размер шрифта 'M' (Medium)
printer.println("Medium"); // Выводим текст
printer.setSize('S'); // Устанавливаем маленький размер шрифта 'S' (Small) - используется по умолчанию
printer.println("Small"); // Выводим текст
printer.justify('R'); // Устанавливаем выравнивание текста по правому краю 'R' (Right)
printer.println("Right"); // Выводим текст
printer.justify('C'); // Устанавливаем выравнивание текста по центру 'C' (Center)
printer.println("Center"); // Выводим текст
printer.justify('L'); // Устанавливаем выравнивание текста по левому краю 'L' (Left) - используется по умолчанию
printer.println("Left"); // Выводим текст
printer.inverseOn(); // Устанавливаем инверсию цвета текста.
printer.println("Inverse"); // Выводим текст
printer.inverseOff(); // Отменяем инверсию цвета текста.
printer.doubleHeightOn(); // Устанавливаем удвоенную высоту текста.
printer.println("Double Height"); // Выводим текст
printer.doubleHeightOff(); // Отменяем удвоенную высоту текста.
printer.doubleWidthOn(); // Устанавливаем удвоенную ширину текста.
printer.println("Double Width"); // Выводим текст
printer.doubleWidthOff(); // Отменяем удвоенную ширину текста.
printer.boldOn(); // Устанавливаем полужирное начертание текста.
printer.println("Bold"); // Выводим текст
printer.boldOff(); // Отменяем полужирное начертание текста.
// Устанавливаем подчёркивание текста линией в 1 пиксель.
// Равнозначно вызову функции с параметром 1: printer.underlineOn(1);
printer.underlineOn();
printer.println("Underline 1px"); // Выводим текст
printer.underlineOn(2); // Устанавливаем подчёркивание текста линией в 2 пикселя.
printer.println("Underline 2px"); // Выводим текст
printer.underlineOff(); // Отменяем подчёркивание текста.
// Межстрочный интервал в 2,5 мм.
// В качестве параметра можно указать интервал от 24 (2,4 мм) до 32767. По умолчанию 30 (3,0 мм)
printer.setLineHeight(25);
printer.println("1\r\n2\r\n3"); // Выводим 3 строки текста
printer.setLineHeight(60); // Устанавливаем межстрочный интервал в 6,0 мм.
printer.println("4\r\n5\r\n6"); // Выводим 3 строки текста
printer.setLineHeight(); // Устанавливаем межстрочный в значение по умолчанию (3,0 мм)
// Устанавливаем межсимвольный интервал в 10 пикселей.
// В качестве параметра можно указать интервал от 0 до 32767 пикселей. По умолчанию 0
printer.setCharSpacing(10);
printer.println("CharSpacing"); // Выводим текст
printer.setCharSpacing(); // Отменяем межсимвольный интервал. Равнозначно вызову printer.setCharSpacing(0);
printer.tab(); // Устанавливаем отступ (табуляцию).
printer.println("<- Tabulation"); // Выводим текст
// Прокручиваем ленту на 10 пикселей. В качестве параметра можно указать от 0 до 255
printer.feedRows(10); пикселей.
if (printer.hasPaper()) { // Если кассовая лента установлена (есть бумага), то ...
printer.println("Paper OK"); // Выводим текст
} else { // Если нет бумаги, то ...
// Что-то делаем, например, включаем светодиод или звуковой сигнал
}
// Устанавливаем настройки принтера по умолчанию.
// Функцию удобно использовать, если хотите быть уверены что на него не повлияют ранее установленные размеры или начертания.
printer.setDefault();
printer.feed(3); // Прокручиваем ленту на 3 строки
}
void loop() {}
В первый день пример работал, а на следующий день почему-то перестал. Я не разбирался в проблеме, оставил на всякий случай.
#include <SoftwareSerial.h>
#include <Adafruit_Thermal.h>
#define RX_PIN 5
#define TX_PIN 6
SoftwareSerial mySerial(RX_PIN, TX_PIN);
Adafruit_Thermal printer(&mySerial);
// Объявляем функцию перевода русских символов из кодировки UTF-8 в кодировку CP866
char* RUS(char*);
void setup() {
mySerial.begin(9600);
printer.begin();
printer.setDefault();
printer.setCodePage(CODEPAGE_CP866); // Устанавливаем кодовую таблицу CP866 с поддержкой русского языка
printer.println(RUS("Hello Kitty - Привет киска")); // Выводим текст на принтер. Функция RUS преобразует русские символы, а остальные вернёт как есть
char text1[] = "Текст в переменной text1"; // Определяем переменную text1
RUS(text1); // Функция RUS преобразует русские символы переменной text1 и сохранит их в той же переменной
//printer.println(text1); // Выводим преобразованный текст на принтер
// Вывод из переменной text2:
char text2[] = "Текст в переменной text2"; // Определяем переменную text2
//printer.println(RUS(text2)); // Функция RUS преобразует русские символы переменной text2
//printer.feed(3); // Прокручиваем ленту на 3 строки
} //
// Вы можете применять различные стили начертания и размеры шрифта при выводе его на термопринтер.
void loop() {}
char* RUS(char* str) { // Определяем функцию которая преобразует код русских символов из кодировки UTF-8 в кодировку CP866
uint8_t i = 0, j = 0; // Определяем переменные: i - счетчик входящих символов, j - счетчик исходящих символов
while (str[i]) { // Проходим по всем символам строки str, пока не встретим символ конца строки (код 0)
if (uint8_t(str[i]) == 0xD0 && uint8_t(str[i + 1]) >= 0x90 && uint8_t(str[i + 1]) <= 0xBF ) {
str[j] = (uint8_t) str[i + 1] - 0x10;
i++;
} else // Символы «А-Я а-п» (код UTF-8: D090-D0AF D0B0-D0BF) сохраняем в кодировке CP866: код 80-9F A0-AF (символ занимал 2 байта, а стал занимать 1 байт)
if (uint8_t(str[i]) == 0xD1 && uint8_t(str[i + 1]) >= 0x80 && uint8_t(str[i + 1]) <= 0x8F ) {
str[j] = (uint8_t) str[i + 1] + 0x60;
i++;
} else // Символы «р-я» (код UTF-8: D180-D18F) сохраняем в кодировке CP866: код E0-EF (символ занимал 2 байта, а стал занимать 1 байт)
if (uint8_t(str[i]) == 0xD0 && uint8_t(str[i + 1]) == 0x81 ) {
str[j] = 0xF0;
i++;
} else // Символ «Ё» (код UTF-8: D081) сохраняем в кодировке CP866: код F0 (символ занимал 2 байта, а стал занимать 1 байт)
if (uint8_t(str[i]) == 0xD1 && uint8_t(str[i + 1]) == 0x91 ) {
str[j] = 0xF1;
i++;
} else // Символ «ё» (код UTF-8: D191) сохраняем в кодировке CP866: код F1 (символ занимал 2 байта, а стал занимать 1 байт)
{
str[j] = (uint8_t) str[i];
} j++; i++; // Остальные символы оставляем как есть, без преобразования, но их место в строке могло сдвинуться, если до них были встречены русские символы
} while (j < i) {
str[j] = 0;
j++;
} return str; // Так как место занимаемое символами в строке могло уменьшиться, заполняем оставщиеся байты символами конца строки (код 0)
}
#include <SoftwareSerial.h>
#include <Adafruit_Thermal.h>
#define RX_PIN 5
#define TX_PIN 6
SoftwareSerial mySerial(RX_PIN, TX_PIN);
Adafruit_Thermal printer(&mySerial);
void setup() {
mySerial.begin(9600);
printer.begin();
// Выводим название формата, затем сам штрих-код
// В данном формате используются 12 цифр
printer.print(F("UPC-A:"));
printer.printBarcode("123456789012", UPC_A);
// Выводим название формата, затем сам штрих-код
// Штрих-код EAN-13, аналогичен формату JAN-13. В данном формате используются 13 цифр
printer.print(F("EAN-13:"));
printer.printBarcode("1234567890123", EAN13);
// Выводим название формата, затем сам штрих-код
// Штрих-код EAN-8, аналогичен формату JAN-8. В данном формате используются 8 цифр
printer.print(F("EAN-8:"));
printer.printBarcode("12345678", EAN8);
// Выводим название формата, затем сам штрих-код
printer.print(F("CODE 39:"));
// Штрих-код CODE 39. Можно использовать от 2 до 255 цифр и заглавных латинских букв
printer.printBarcode("ARDUINO", CODE39);
// Выводим название формата, затем сам штрих-код
// Штрих-код CODE 93. Можно использовать от 2 до 255 цифр, заглавных латинских букв, пробелы, и знаки *.:$%/+-
printer.print(F("CODE 93:"));
printer.printBarcode("ARDUINO", CODE93);
// Выводим название формата, затем сам штрих-код
// Штрих-код ITF. Можно использовать от 2 до 255 цифр
printer.print(F("ITF:"));
printer.printBarcode("1234567890", ITF);
// Выводим название формата, затем сам штрих-код
// Штрих-код CODABAR. Можно использовать от 2 до 255 цифр, заглавных латинских букв, и знаки .:%/+-
printer.print(F("CODABAR:"));
printer.printBarcode("1234567890", CODABAR);
// Выводим название формата, затем сам штрих-код
// Выводим штрих-код CODE 128. Можно использовать от 2 до 255 символов
// коды которых лежат в диапазоне от 0 до 127 таблицы символов ASCII
printer.print(F("CODE128:"));
printer.printBarcode("iArduino", CODE128);
printer.feed(2); // Прокручиваем ленту на 3 строки
printer.setDefault(); // Восстанавливаем стандартные настройки
}
void loop() {}
Принтер позволяет печатать простенькую графику. Но делать это очень неудобно. Сначала нужно с помощью сторонних программ (LCDAssistant) сконвертировать изображение в чёрно-белый вариант, затем преобразовать её в набор байтов, а потом уже посылать на принтер. Я решил пока не заморачиваться в этом направлении. Обойдёмся без картинок.
Описание функций библиотека Adafruit Thermal Printer Library