Термопринтер от кассового аппарата

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015





String inputString;
void setup() {

   Serial.begin(19200);
    delay(500);
    Serial.println(F("--------input string (ENTER=Finish)------------"));   
}

void loop() {
 
        inputString=Serial.readString();  
        if(inputString.length()>0){
        Serial.println("pechataem S terminala  :"+inputString+ "");   

        inputString =String( " 1 ПРИВЕТ");  
        Serial.println(("pechataem stroky1     :"+inputString+ ""));
//     printString();  //печать на термопринтере
//     motorStep(3000); 
        inputString =String( " 2 PRIVET");  
        Serial.println(("pechataem stroky2     :"+inputString+ ""));  
//        printString();  //печать на термопринтере
//         motorStep(3000);

      char putString[] = "\40\63\40\317\360\350\342\345\362";//ПРИВЕТ  WIN1251
        inputString = String(putString);
        Serial.println(("pechataem stroky3     :"+inputString+ ""));  
//        printString();  //печать на термопринтере
//         motorStep(3000);         
        
       }
}

Не получается победить кодировку кириллицы для вывода на термопринтер. Печать работает но при компиляции в разных версиях IDE ведёт себя по разному и не так как нужно.

              IDE1.6.6                                                                   IDE1.8.13

№      монитор                    термопринтер                     монитор                       термопринтер

13     привет                       привет                               кракозябры                   привет

16     кракозябры                кракозябры                        привет                          кракозябры

20     PRIVET                       PRIVET                               PRIVET                          PRIVET

26     Привет                       Привет                               6-кубиков                     Привет

Собственно интересует строка кода №16, то есть текст набранный кириллицей был распечатан на термопринторе  тоже на кириллице. Вывод в монитор IDE не важен. Понимаю что это связано с кодировками шрифта, но как это исправить ?    

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Изучай мануал к принтеру. Хз в какой кодировке он хавает данные.

vanila
Offline
Зарегистрирован: 25.08.2015

судя по всему хавает 1251 а у 1,8 скетч и вывод в порт в ютф. 

а чего кракозябрами не пишется? сначала все на латинице, а потом как все написал - заменил на вот такие приветы "\40\63\40\317\360\350\342\345\362" 

 ну или хз чо будет, но можно попробовать писать в нотопеаде++ илитп изменив на кодировку 1251, а в иде 1,6 выбрать использовать внешний редактор. иде обратно кодировку не переделывает, как есть так и загружает. а сериал и так в 1251 у него выводит если я правильно понял что там написано. 

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015

BOOM пишет:

Изучай мануал к принтеру. Хз в какой кодировке он хавает данные.

Судя по строкам 24 - 26 он хавает данные   в WIN1251.

 

 

vrd
Offline
Зарегистрирован: 20.01.2022

По гуглить смещение в кодировках utf8 ahci & win1251. В скетче считывать в массив char и преобразовывать коды прибавляя или отнимая смещение.

Можно сделать тестовый цикл, который от 0 до 300 разпечатает все символы в формате "число=символ".

Сравнить сериал ide и напечатанное на бумаге. Вычислить смещение будет не трудно и гуглить не надо :)

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

oleg_kazakof пишет:
Понимаю что это связано с кодировками шрифта, но как это исправить ?    

Вообще-то очень странно: первый раз вижу, чтобы слово, набранное ЗАГЛАВНЫМИ, печаталось строчными.

Но в общем случае исправлять следует так:

1. Выяснить, какая кодировка нужна принтеру.

2. Выяснить, какая кодировка используется в IDE.

3. Перекодировать из 2 в 1.

Green
Offline
Зарегистрирован: 01.10.2015

А ещё не плохо бы название принтера.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

vrd пишет:

По гуглить смещение в кодировках utf8 ahci & win1251. В скетче считывать в массив char и преобразовывать коды прибавляя или отнимая смещение.

Можно сделать тестовый цикл, который от 0 до 300 разпечатает все символы в формате "число=символ".

Сравнить сериал ide и напечатанное на бумаге. Вычислить смещение будет не трудно и гуглить не надо :)

Чушь: 

1. О каком "смещении" вообще идет речь?

2. Алгоритм для обработки кодировки символов переменной длины вообще не может быть основан на "преобразовании кодов char".

3. Откуда взялся диапазон от 0 до 300? (откуда бы ни взялся - это в любом случае неверно)

vrd
Offline
Зарегистрирован: 20.01.2022

1 Код символа "А" в utf8 и 1251 - разный. Разница этих кодов и является смещением.

2 привет "\40\63\40\317\360\350\342\345\362"

3 Там 130 или 150 адрес последний в одной из кодировок. Я просто умножил на 2. Можно и до  тысячи прогнать цикл. Но проще посмотреть в гугле.

 PS https://wiki.iarduino.ru/page/encoding-arduino/

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015

andriano пишет:

2. Выяснить, какая кодировка используется в IDE.

3. Перекодировать из 2 в 1.

andriano, при наборе текста в терминале IDE (версии 1.6.6 - это критично) принтер повторяет текст 1 в 1, что кириллицу, что латиницу (в полной программе после № 13  вызывается печать). 

Ваши пункты 2 и 3 содержатся в стартовом топики (возможно несколько завуалированном виде) вот в этом и вопрос. 

Термопринтер от кассы миника 1102ф, на самой термоголовке нет маркировки. Скорее всего это ТД или (ТВ)4032а или её аналог Т1001Б. Но это так для справки так как повторю принтер печатает текст и рус и лат, но только с окна терминала IDE1.6.6

rs: по случаю достались 5 касс, вот и решил сделать печать этикеток на свой напитки.

Green
Offline
Зарегистрирован: 01.10.2015

Дядя, ну так распечатай от 128 до 255 и погляди.

vrd
Offline
Зарегистрирован: 20.01.2022

По таблице до /177 идёт без изменений. Вам осталось переписать байты в не совпадающих местах.

Определяем размер с помощью length(). И циклом вынимаем getBytes() в свою переменную и меняем на нужную при значении более /177. Далее записать полученное значение в новый стринг. Вывести переделанный стринг на принтер. Всё.

vrd
Offline
Зарегистрирован: 20.01.2022

Там 6 разных смещений а значит в 7 if-ов можно влезть. Первый будет значения до /177 писать без изменений.

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015

andriano, я выяснил IDE 1.6.6 сохраняет текст в UTF-8, а терминал отправляет текст WIN 1251 и программа управления термопринтером понимает WIN 1251 поэтому и печатает и рус и лат.

Осталось самая малость. Сделать конвертацию текста UTF-8 > WIN 1251 и можно будет пихать всё в корпус.

 

vanila
Offline
Зарегистрирован: 25.08.2015

oleg_kazakof пишет:

andriano, я выяснил IDE 1.6.6 сохраняет текст в UTF-8, а терминал отправляет текст WIN 1251 и программа управления термопринтером понимает WIN 1251 поэтому и печатает и рус и лат.

Осталось самая малость. Сделать конвертацию текста UTF-8 > WIN 1251 и можно будет пихать всё в корпус.

 


Так а вы пробовали сам скетч в 1251 перевести? Может и не понадобится ничего конвертировать.

Green
Offline
Зарегистрирован: 01.10.2015
// print UTF-8 -> Windows-1251
void printWin1251(char* src)
{
  while (*src) {
    uint8_t c = *src++;
    if (c == 0xD0) {
      c = *src++;
      if (c >= 0x90 && c <= 0xBF)
        c += 0x30;
      else if (c == 1)
        c = 0xA8;
    }
    else if (c == 0xD1) {
      c = *src++;
      if (c >= 0x80 && c <= 0x8F)
        c += 0x70;
      else if (c == 0x91)
        c = 0xB8;
    }
    Printer.write(c);
  }
}

Только Printer.println() нужно в конце печати.

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015

Green пишет:

// print UTF-8 -> Windows-1251

Green, спасибо, но у меня уже всё работает, скетч конвертации для строки.

[code]
//ковертация UTF-8 в WIN 1251
//РАБОТАЕТ

String tape ;

void setup() {
  Serial.begin(9600);
  tape = utf8rus("Привет мир");

}

void loop() {

utf8rus(tape);
 char mas1[16];
strcpy(mas1, tape.c_str());  
 for(int i = 0; i<16; i++){
 Serial.print ((byte)(mas1[i]));// печать кода символа
 Serial.print(" ");  
 }   
Serial.println();   

}
/* Перекодировать русские шрифты из UTF-8 в Windows-1251 */ 
String utf8rus(String source){
  int i,k;
  String target;
  unsigned char n;
  char m[2] = { '0', '\0' };
 
  k = source.length(); i = 0;
  while (i < k) {
    n = source[i]; i++;
    if (n >= 0xC0) {      //192 если рус 
      switch (n) {
        case 0xD0: {      //208
          n = source[i]; i++;
          if (n == 0x81) { n = 0xA8; break; }//129,168
          if (n >= 0x90 && n <= 0xBF) n = n + 0x2F;//144,191,47
          break;
        }
        case 0xD1: {       //209
          n = source[i]; i++;
          if (n == 0x91) { n = 0xB7; break; }//145,183
          if (n >= 0x80 && n <= 0x8F) n = n + 0x6F;//128,143,111
          break;
        }
      }
    n++;// ------------------------------------------------
    }    
    m[0] = n; target = target + String(m);
  }
return target ;
}
 
[/code]


 

oleg_kazakof
Offline
Зарегистрирован: 24.04.2015

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

vrd пишет:

1 Код символа "А" в utf8 и 1251 - разный. Разница этих кодов и является смещением.

2 привет "\40\63\40\317\360\350\342\345\362"

3 Там 130 или 150 адрес последний в одной из кодировок. Я просто умножил на 2. Можно и до  тысячи прогнать цикл. Но проще посмотреть в гугле.

 PS https://wiki.iarduino.ru/page/encoding-arduino/

1. Видите ли, понятие "код символа" однозначно только для кодировок фиксированной длины. utf8 к таковым не относится. Поэтому, как минимум, следует указать, что лично Вы в данном конкретном случае подразумеваете под словосочетанием "код символа".

Идем дальше, предположим, мы выяснили, что такое "код символа" и теперь можем использовать его в арифметических операциях. Теперь представьте, для "А" указанная Вами разница одна, для "Б" - другая, для "С" - третья. Что именно в данном случае является смещением?

3. Если кодировка 7-битная, в ней 128 символов, если 8-битная - 256, если же 16-битная - 65536. Вопрос: зачем "прогонять цикл" до каких-то других чисел кроме указанных трех?