Привет, Хабр!

Как то раз была у меня «работа» — нужно было сделать управление кассовым аппаратом Штрих-ФР-К. Так как моя карьера начиналась с ремонта ККТ, то решил взяться за эту работу.

image

Так выглядит сама касса и пробное изображение моего коллеги:

image

Так же по мимо управления движками и термоголовкой в аппарате пришлось написать небольшой скрипт на питоне с использованием библиотеки OpenCV. Итак, поехали.

Все началось с изучения рем. дока. к данной кассе и последующего подключения логического анализатора на пины термоголовки. Я отправил на печать, через штриховый тест драйвер букву «С». И вот что у меня получилось:

image

По DATA значение точек (всего 432 точки в строке), SCK — cинхросигнал, STB0, STB1, STB2 — стробы для нагрева термоголовки, LATCH — защелкивание данных. Строчку вбил в сдвиговый регистр, прожег, пошел дальше.

Следующий этап был доработка платы для ускорения процесса разработки.

image

Теперь перейдем к коду.

 void go(int n, int shag)
{
	switch (shag)
	{
		case 0: 	PORTA=0b10001000; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 1: 	PORTA=0b10101010; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 2: 	PORTA=0b00100010; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 3: 	PORTA=0b01100110; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 4: 	PORTA=0b01000100; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 5: 	PORTA=0b01010101; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 6: 	PORTA=0b00010001; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
		case 7: 	PORTA=0b10011001; PORTD|=(1<<2); dela(n); PORTD&=0b11111011; PORTA=0; PORTD|=(1<<2); PORTD&=0b11111011;
		break;
	}

}

Есть две схемы управления шаговым двигателем для этой кассы. 4-шаговый и 8-шаговым. Я выбрал 8, так как движки работали лучше.

#define DATA 2
#define SCK 1
#define LATCH 3
#define STB0 2
#define STB1 3
#define STB2 4
#define DATA_IN PORTB
#define STB_IN PORTE

int sck()
{
	_delay_us(3);
	DATA_IN|= (1<<SCK);
	DATA_IN&= 0b11111101;
}
int x;
int bit;
void bait(int bait1)
{
	x=0;
	while(x<8)
	{
		bit|= (1<<x);
		bit =bait1&bit;
		if (bit>0)
		{
			DATA_IN|=(1<<DATA);
		}
		else
		{DATA_IN&=0b11111011;}

		sck();
		x++;
	}
}
void latch()
{
	DATA_IN&=0b11110111;
	DATA_IN|=(1<<LATCH);

}

Код отправки данных в термоголовку. Термоголовка работает как сдвиговый регистр. Как она работает я писал выше.

void print_all_pixel()
{
	while(n<55)
	{
		print_stroka(str[n]);
		_delay_us(3);
		n++;
	}
	latch();
	n=0;
	STB_IN&=0b11111011;
	_delay_us(500);
	STB_IN|=(1<<STB0);
	STB_IN&=0b11110111;
	_delay_us(500);
	STB_IN|=(1<<STB1);
	STB_IN&=0b11101111;
	_delay_us(500);
	STB_IN|=(1<<STB2);

	//vpered(300);
	//n=0;
	//_delay_ms(100);
	//vpered(100);
}

Функция печати и прожига строк.

void recieve()
{
///while(f);
	if ((com==0x50)&&(rezhim==0))/// P
	{
	//USART_Transmit('X');
		com=0;
				USART_Transmit('B');
		rezhim=1;

	}

	if ((rezhim==1)&&(send!=0))
	{

		str[iFF]=com;

		send=0;
		iFF++;
		if (send == 1)
		{
		USART_Transmit('B');
		}

		if (iFF==54)
		{
		USART_Transmit('P');
			USART_Transmit('R');
			USART_Transmit('I');
			USART_Transmit('N');
			USART_Transmit('T');
			USART_Transmit('E');
			USART_Transmit('D');
			PORTB|=1<<0;
			_delay_ms(1);
		print_all_pixel();
		//print_all_pixel();
						go1(1500,ggg);
		
				rezhim=0;
				iFF=0;
			ggg++;
			if (ggg==8)
			{
			ggg=0;
			}

		}

	}
	if ((com==0x52)&&(rezhim==0))///R
	{
	com=0;
	go1(1000,ggg);
	rezhim=0;
	iFF=0;
	ggg++;
	if (ggg==8)
	{
		ggg=0;
	}
	USART_Transmit('O');
	USART_Transmit('K');
	//vpered(300);
	}
}

Основная функция, которая крутится в вечном вайле. Когда приходит буква «P» я включаю вход в режим печати. Далее все остальные символы начинают набиваться в буфер. Далее когда буфер набивается 54 байтами (или 432 бита), то печатаем строку и отправляем по УСАРТ слово PRINTED.
Ну вот и все с железной частью. В следующей части я распишу про программную часть, а именно про программу на питоне. Исходники.

image

Комментарии (8)


  1. Z55
    02.09.2019 14:31
    +1

    О чём статья?


  1. pewpew
    02.09.2019 15:11
    +1

    rezhim=1;
    ...
    vpered();
    ...
    nazad();
    ...
    promotka();

    Ужасно.


    1. Rebel028
      02.09.2019 21:00
      +1

      Самое вкусное забыли


      switch (shag)

      вырезка из словаря, для тех кто не силен в сленге


  1. tormozedison
    02.09.2019 17:43

    Здорово вышло, теперь попробуйте дизеринг.


    1. xo4y_B_BostonDynamics Автор
      02.09.2019 20:59

      у меня уже нет этого аппарат


  1. goodic
    02.09.2019 18:20

    Спасибо за то что расписали как с термопринтерем в Штрихах работать. Но вы бы чуть подробнее по железу написали, картинок приложили. Я с ними работал, мне суть проблемы и результат понятны. Остальным — не очень.

    upd в ФР предусмотрена регулировка напряжения которым «прожигается» картинка. Рекомендую посмотреть как питается «голова» и уменьшить. У вас или бумага такая, медленно тянете или все же перегреваете голову высоким напряжением.

    ps схемы можно из ремдоков взять.


    1. xo4y_B_BostonDynamics Автор
      02.09.2019 20:59

      попробую


  1. kovserg
    02.09.2019 21:58

    Селедующий шаг после печати на принтере извлечение из него звука
    www.youtube.com/watch?v=G-X-p0C0Uas