Если бы MikaTech была недобросовестной компанией, вы бы нашли множество негативных отзывов о её услугах в интернете за 28-летнюю историю
Итак, ответ — ДА! Мы хорошие люди.Почему выбирают Mikatech, пожалуйста, нажмите здесь, чтобы узнать
О компании MikaTech
Время пролетело быстро: с того дня, когда мы выполнили наш первый проект по обратной разработке MCU 8051 в 1998 году, до того дня, когда мы создали нашу миллионную лабораторию обратной разработки в 2012 году, прошло 14 лет. Теперь мы начинаем наш новый бизнес по разработке встраиваемых визуальных систем, надеемся, что сможем прослужить ещё 10 лет.
Peter Lee
Сооснователь и генеральный директор
Последние два года я планировал построить себе 3D-принтер из старых струйных принтеров, которые собирал годами. Но только две недели назад я наконец начал над ним работать.
3D-принтер, который я хочу сделать, использует струйные головки для нанесения химического вещества на платформу построения. Платформа опускается, когда на неё насыпается новый слой порошка. Затем химикат распыляется из печатающей головки, что вызывает связывание порошка. Если вам нужна дополнительная информация о таких принтерах, посмотрите здесь.
Мой выбор пал на старый Epson Stylus C63 по следующим причинам:
1. Картриджи с чернилами только подают чернила, сами не имеют сопел струйной головки.
2. Я могу подсоединить резиновые шланги или другие трубки, которые позволят мне печатать другим химикатом по моему выбору.
3. Сопла печатающей головки используют пьезоэлектрический материал для образования капель чернил (служат намного дольше, чем термические струйные).
4. Большинство руководств по обслуживанию принтеров Epson содержат подробные схемы основной платы.
Примечание. В связи с определёнными обстоятельствами этот принтер уже был разобран.
Первое, что мне нужно было сделать, — запустить принтер, чтобы я мог подключить логический анализатор и посмотреть сигналы. Проблема была в том, что у меня отсутствовал один картридж, поэтому принтер отказывался печатать или что-либо делать.
Из-за моего бюджета (без работы и собираюсь поступать в университет) я решил попытаться эмулировать отсутствующий картридж или все сразу с помощью одного микроконтроллера, что позволило бы мне продвинуться вперёд и использовать воду для печатающей головки вместо чернил, которые оставляют пятна.



Итак, чтобы эмулировать чернильные картриджи, мне нужно сначала узнать, как они работают. К счастью, картриджи в моём принтере имеют простые EEPROM, которые хранят информацию об использовании чернил и другие важные данные, такие как срок годности, цвет, серийный номер и т.д.
Внутри печатающей головки есть плата с контактными площадками, которые являются точным зеркалом площадок на чернильных картриджах, и шлейф, который соединяет эту плату с основной платой по выводам 1–6.
Быстрый взгляд на схему основной платы показывает, что выводы 1–6 называются CVDD, CSDA, CRST, GND, CSCK и COI.
Имея эти имена сигналов, я решил, что лучше нарисовать схему соединительной платы, так как она отсутствовала в руководстве по обслуживанию. Это показало, что CSDA, CSCK, CRST имеют подтягивающие резисторы 100 кОм к земле, что, по моему мнению, необычно, так как это не I2C (где обычно используются подтягивающие резисторы 1,8–47 кОм к питанию). Сигнал COI последовательно соединяется с картриджами, но на конце замыкается на землю. Любопытно, я проверил непрерывность площадок на картриджах и обнаружил, что они замкнуты, это означает, что когда COI замкнут на землю, все картриджи присутствуют.

Теперь, когда я знаю имена сигналов, я хотел увидеть, как выглядят сами сигналы.
Я достал паяльник, шлейф (раньше это был IDE-кабель от старого компьютера) и канцелярский нож. Я отрезал 6-жильный шлейф длиной около 30 см, аккуратно зачистил концы с помощью канцелярского ножа (это намного проще, чем использовать кусачки или плоскогубцы) и припаял их к печатной плате, которая соединяется с картриджами.
Я также зачистил другие концы и припаял штырьки, чтобы их можно было подключить к логическому анализатору.
После подключения логического анализатора к печатной плате и просмотра сигналов я обнаружил, что сразу же SCK, SDA совсем не похожи на I2C. Я почти уверен, что Epson должна была изобрести свой собственный последовательный протокол для общения с EEPROM внутри чернильных картриджей.
Я обнаружил, что CVDD подаётся питание, а вскоре после этого CRST и CSDA поднимаются одновременно, а затем CSCK начинает выдавать импульсы. CSDA изменяется по переднему фронту CSCK, и я предположу, что он считывается по спадающему фронту.
CSCK — это последовательная тактовая частота (Serial ClocK)
CSDA — это последовательные данные (Serial Data)
CRST — это сброс (Reset)
а CVDD — питание
Выглядит достаточно просто, но я хотел получить больше информации об этом протоколе: были ли там какие-либо адреса?
Я увеличил частоту дискретизации на логическом анализаторе и обнаружил, что есть 4 тактовых цикла, пауза, затем 8 циклов, пауза, ещё 8 и так далее. 4 тактовых цикла в начале навели меня на мысль, что первые четыре бита могут быть 4-битным адресом картриджа. Тем не менее, много информации об этом протоколе было неизвестно. Поэтому я провёл небольшое исследование!
Поиск в Google не дал результатов об этом протоколе, следующим лучшим местом для поиска были патенты.
Да, патенты. Я искал «Epson SDA SCK RST memory eeprom» на http://www.freepatentsonline.com/ и один из патентов, который я нашёл (US7660008), содержал именно то, что я искал. В нём описывались SCK, SDA, RST и VDD протокола.
Я избавлю вас от хлопот и укажу, что я нашёл:
1. Блок-схемы, описывающие, что делают ведущий и ведомый.
2. Временная диаграмма протокола.
3. Первые 3 бита — это 3-битный адрес, за которым следует бит чтения/записи (Read = 0, Write = 1).
4. Счётчик адреса всегда начинается с 0x00 и увеличивается на 1 за каждый такт (это означает, что запись идёт побитно, а не побайтово).
5. Как только RST переходит в низкий уровень, EEPROM останавливает всё и сбрасывается.
6. Всего 252 бита для чтения, последние 3 бита (на самом деле они в начале) — это адрес чернильного картриджа.
Используя то, что я нашёл, я решил начать писать код.
Я хотел прочитать ПЗУ из картриджей, а затем использовать эти данные для попытки эмуляции отсутствующего картриджа. Это означает создание библиотеки, которая будет действовать как ведущий для чтения данных, но также может использоваться для эмуляции чернильного картриджа.
Используя предыдущие знания по созданию программных протоколов, я создал заголовочный файл со следующими функциями:
• extern void epsnCartInit(void);
• extern void epsnCartStart(unsigned char addr, unsigned char write);
• extern void epsnCartStop(void);
• extern void epsnCartWrite(unsigned char data);
• extern unsigned char epsnCartRead(void);
Я также создал следующие определения, которые помогают запомнить, какой вывод за что отвечает:
Для вашего микроконтроллера вам нужно будет изменить эти значения в соответствии с вашим приложением.
#define _ecSCKTRIS TRISCbits.TRISC0
#define _ecSDATRIS TRISCbits.TRISC1
#define _ecRSTTRIS TRISCbits.TRISC2
#define _ecVDDTRIS TRISBbits.TRISB1

#define _ecSCKLat LATCbits.LATC0
#define _ecSDALat LATCbits.LATC1
#define _ecRSTLat LATCbits.LATC2
#define _ecVDDLat LATBbits.LATB0
#define _ecSCK PORTCbits.RC0
#define _ecSDA PORTCbits.RC1
#define _ecRST PORTCbits.RC2
#define _ecVDD PORTBbits.RB1
#define wait() DelayUS(50)
Примечание: Я использовал PIC18F и использовал защёлки для установки выходов, это просто моё предпочтение. Вы можете использовать любой микроконтроллер, с которым вы знакомы.
void epsnCartInit(){
_epsnCartSCKTRIS = 0;
_epsnCartSDATRIS = 0;
_epsnCartRSTTRIS = 0;
_epsnCartVDDTRIS = 0;
_epsnCartSCK = 0;
_epsnCartSDA = 0;
_epsnCartRST = 0;
_epsnCartVDD = 0;
_epsnCartSCKLat = 0;
_epsnCartSCKLat = 0;
_epsnCartSCKLat = 0;
_epsnCartSCKLat = 0;
}
Функция старта поднимает VDD, ждёт, затем устанавливает SDA в соответствии с битом адреса, а также SCK. Ждёт, опускает SCK, снова ждёт и затем поднимает SDA в соответствии с адресом. Это повторяется ещё 2 раза, за исключением того, что на 4-й раз SDA устанавливается в низкий уровень, потому что мы хотим читать данные из EEPROM, а не записывать.
void epsnCartStart(unsigned char addr,unsigned char write){
char i = 0; // Используется для счёта
char tmp = 0; // Временная переменная хранения
_ecVDDLat = 1; // Установить VDD высоко
DelayMS(1); // Подождать, пока EEPROM будут готовы
_ecRSTLat = 1; // Включить EEPROM для связи
tmp = addr; // Скопировать адрес во временную переменную
if(write){ // Если мы хотим записать
temp |= 0x08; // установить 4-й бит высоко ( '|' означает ИЛИ )
}
while(i<4){
_ecSDALat = (tmp&0x01); // Установить SDA высоко или низко в соответствии с младшим битом
wait(); // Подождать примерно 50 мкс
_ecSCKLat = 1; // Установить такт высоко
wait(); // Подождать ещё 50 мкс
_ecSCKLat = 0; // Установить такт низко
wait(); // Подождать ещё 50 мкс
tmp>>=1; // Сдвинуть все биты tmp вправо на один
i++; // Увеличить счётчик на один
}
}
Следующая функция, которую нужно реализовать, — stop:
void epsnCartStop(){
_ecRSTLat = 0; // Установить RST низко
DelayMS(1); // Подождать немного
_ecVDDLat = 0; // Выключить EEPROM
}
И, наконец, функция чтения:
unsigned char epsnCartRead(){
char i=0;
char temp = 0x00;
while(i<8){
temp>>=1; // Сдвинуть временную переменную вправо на один
_ecSCKLat = 1; // Установить SCK высоко
wait(); // Подождать примерно 50 мкс
if(_ecSDA){ // Если SDA высоко
temp |= 0x80; // Тогда установить 7-й бит высоко
}
_ecSCKLat = 0; // Снова опустить SCK
wait(); // Подождать ещё 50 мкс
i++; // Увеличить счётчик на 1
}
return temp; // Вернуть то, что мы прочитали
}
Теперь у нас есть базовые функции, необходимые для чтения данных из чернильных картриджей. Давайте настроим наш микроконтроллер и посмотрим результаты.

Запустите свою среду разработки, в моём случае это MPLab, создайте новый проект для вашего чипа и создайте простую программу «Hello World», чтобы убедиться, что ваш чип работает.
Примечание: Моя программа Hello World отправляет «Hello World!\r\n» по последовательному порту на мой компьютер со скоростью 38400 бит/с.
#include <p18f2550.h> // Файл включения для этого чипа
#include <usart.h> // Функции USART
#include <stdio.h> // printf(format,...), sprintf(string, format, ...), и т.д.
#include "delay.h"
void main(){
PORTA = 0x00;
PORTB = 0x00;
PORTC = 0x00;
TRISA = 0x00;
TRISB = 0x00;
TRISC = 0x00;
ADCON1 = 0x0F; // Это доставляет много хлопот, никогда не забывайте переключать аналоговые выводы обратно в цифровые! :P
TRISCbits.TRISC7 = 1; // Превращает вывод RX во вход (посмотрите в вашем даташите для вашего чипа)
OpenUSART(USART_TX_INT_OFF & USART_RX_INT_OFF & USART_ADDEN_OFF & USART_BRGH_HIGH & USART_CONT_RX & USART_EIGHT_BIT & USART_ASYNCH_MODE,78);
while(1){
putrsUSART("Hello World!\r\n"); // Отправить сообщение через Serial
LATAbits.LATA0 = ~LATAbits.LATA0; // Мигать светодиодом, переключая его вкл/выкл
DelayMS(500); // Функция задержки, которую я создал
}
}
Это было настроено с источником питания 3,3 В, потому что чернильные картриджи работают от 3,3 вольт.
Зачем программа Hello World? Что ж, каждый раз, когда я настраиваю новый проект на макетной плате, я всегда хочу убедиться, что биты конфигурации установлены правильно и что я не получаю мусор в терминале.
Я думаю, это хорошая практика, и каждый должен так делать! :P
Если ваш чип делает что-то простое, как мой, отлично! Переходим к следующему шагу.
Реализация нашей библиотеки
Теперь мы хотим включить библиотеку, которую мы создали для взаимодействия микроконтроллера с чернильным картриджем.
В верхней части файла добавьте:
#include "epsnCart.h" // имя созданного нами заголовочного файла
Поскольку этот микроконтроллер выступает в роли ведущего, он управляет сигналами SCK, SDA и RST. Поэтому убедитесь, что они являются выходами, добавьте это вместе с другими регистрами TRIS внутри main():
epsnCartInit();
Следующий код я использовал внутри while(1) {
Он запрашивает адрес, начиная с 0x00, и затем увеличивает его на 1 после 32 прочитанных байт:
void main(){
char addr = 0, i = 0;
char string[40];
...
epsnCartInit(); // Инициализировать используемые выводы
while(1){ // Бесконечный цикл!
sprintf(string, "Чтение картриджа с адресом: 0x%02X\r\n",addr);
putsUSART(string); // Выводит сообщение типа: Чтение картриджа с адресом: 0x03
epsnCartStart(addr,0); // Запустить, отправив адрес в режиме чтения
i = 0;
while(i<32){ // продолжать цикл, пока i меньше 32
sprintf(string,"0x%02X,",epsnCartRead());
putsUSART(string);
i++;
}
epsnCartStop(); // опускает RST обратно в низкий уровень
putrsUSART("\r\n");
addr++
if(addr>7){
addr = 0;
}
DelayMS(500);
}
}
Вы, вероятно, смотрите на строку «sprintf(string,"0x%02X,",epsnCartRead());» и думаете «А?»
sprintf — это функция форматирования строк, похожая на printf, но сохраняющая отформатированную строку в переменную string.
"0x%02X," вернёт строку с читаемым шестнадцатеричным значением, например 0xFE, а epsnCartRead() возвращает значение, прочитанное из картриджа.
Это было настроено с источником питания 3,3 В, потому что картриджи работают от 3,3 вольт.
Я запрограммировал это в свой микроконтроллер, отключил печатающую головку от принтера, чтобы избежать помех.
Затем я вставил 3 имеющихся у меня картриджа и включил его.
Примечание: На этом этапе, если вы запускаете этот код в первый раз, я ожидаю, что у вас будут проблемы. Как и у меня, я просматривал код десятки раз, изменяя его то там, то здесь, чтобы заставить его работать. Это нормально, если у вас не получится с первого раза. Это отличный опыт обучения — выяснять, что пошло не так! :P


Вот что я получил в своём терминале
Адрес: 0x01
57,07,02,F2,00,00,00,00,00,50,98,6A,EB,D3,54,A3,39,50,14,15,31,93,E4,B4,24,96,57,04,35,F5,E4,14,
Адрес: 0x02
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
Адрес: 0x03
03,00,02,F2,00,00,00,00,00,50,C8,1C,2A,A5,82,00,3B,50,16,17,31,93,E4,B4,24,96,57,04,35,F5,E4,34,
Адрес: 0x04
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
Адрес: 0x05
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
Адрес: 0x06
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,
Адрес: 0x07
03,00,02,F2,00,00,00,00,00,50,30,9F,74,81,D1,40,3B,50,1A,1B,31,93,E4,B4,24,96,57,04,35,F5,E4,74,
Теперь обратите внимание, что только нечётные адреса вернули данные, кроме 0x05?
Это потому, что 0x05 — это адрес пурпурного картриджа, которого у меня, к сожалению, нет :(
Подпрограммы эмуляции
Теперь самое интересное!
Мне нужно, чтобы принтер думал, что установлены четыре чернильных картриджа фокусированный ионный пучок fib цена, для этого нам нужно сначала реализовать некоторые функции эмуляции. Опять же, на основе предыдущих знаний я предопределил их в заголовочном файле:
• #define epsnCartReady() (_ecRST)
• extern unsigned char espnCartGetAddr(void);
• extern void epsnCartOut(unsigned char data);
• extern unsigned char epsnCartIn(unsigned char data);
epsnCartReady — это макрос, который используется для проверки, установлен ли RST высоко.
epsnCartGetAddr возвращает адрес, который запрашивает печатающая головка.
epsnCartOut используется для отправки данных ведущему контроллеру.
epsnCartIn используется для получения данных от ведущего, когда он выполняет запись.
Итак, на этот раз вместо управления SCK для перехода в высокое или низкое состояние нам нужно ждать его перехода в высокое или низкое состояние, но если сброс переходит в низкое состояние, то остановить всё и вернуться:
unsigned char espnCartGetAddr(void){
char i=0;
char temp = 0x00;
while((i<4) && _ecRST){ // Цикл, пока i < 4 и RST высок
temp>>=1; // Сдвиг Temp вправо на один
while((!_ecSCK) && (_ecRST)); // Ждать, пока такт перейдёт в высокое состояние
if(_ecSDA){// только если SDA высок
temp |= 0x08; // тогда установить 4-й бит
}
while((_ecSCK) && (_ecRST));// ждать, пока такт перейдёт в низкое состояние
i++; // увеличить счётчик
}
if(_ecRST == 0){
return 0xFF;//если RST стал низким, значит ведущий оборвал сигнал
}
return temp; //вернуть адрес и бит чтения/записи
}
И функция вывода:
void epsnCartOut(unsigned char data){
char i = 0;
char temp = data;
_ecSDATRIS = 0; // установить SDA как выход
_ecSDALat = 0; // установить SDA низко
while((i<8) && _ecRST){ // Цикл, пока i < 8 и RST высок
while(!_ecSCK && _ecRST); // Ждать, пока SCK перейдёт в высокое состояние
_ecSDALat = temp&0x01; // Установить SDA высоко или низко в соответствии с первым битом
while(_ecSCK && _ecRST); // Ждать, пока SCK перейдёт в низкое состояние
temp>>=1; // Сдвинуть данные вправо на один
i++; // Увеличить счётчик на один
}
_ecSDATRIS = 1; // Установить SDA как вход
_ecSDA = 1; // не уверен, нужно ли это
}
И наконец функция ввода:
unsigned char epsnCartIn(void){
unsigned char i=0;
char temp = 0x00;
while((i<8) && _ecRST){ // Цикл, пока i < 8 и RST высок
temp>>=1; // Сдвиг temp вправо на один
while(!_ecSCK && _ecRST); // Ждать, пока SCK перейдёт в высокое состояние
if(_ecSDA){ // только если SDA высок
temp |= 0x80; // Установить 8-й бит
}
while(_ecSCK && _ecRST);// Ждать, пока SCK перейдёт в низкое состояние
i++; // Увеличить счётчик на один
}
return temp; // вернуть полученное
}
Теперь нам нужно настроить наш микроконтроллер так, чтобы он содержал данные, которые мы извлекли. Затем позволить ведущему принтера читать и записывать их.
Проблема в том, что я не хочу, чтобы мои фальшивые картриджи когда-либо израсходовались. Для этого мы используем фиксированный дамп, который микроконтроллер будет загружать в ОЗУ при каждом запуске. Это позволит принтеру не только читать, но и записывать в него. Когда микроконтроллер выключается и снова включается, предыдущие данные восстанавливаются. (Двойной бонус)
Хранение массивов данных в микроконтроллере. Поместите это где-нибудь после включений, но перед void main()
Примечание: Это может отличаться для разных семейств микроконтроллеров, но отлично работает с моим PIC18F.
ram unsigned char black[32] = {0x10,0x00,0x02,0xF2,0x00,0x00,0x00,0x00,0x00,0x50,0x90,0x6A,0x17,0xE3,0x54,0xA3,Примечание: Заметили, что у меня нет пурпурного? Это потому, что это тот картридж, которого у меня нет.
Следующий шаг — написать подпрограмму, которая проверяет, какой картридж запрашивается, и позволяет ведущему читать и записывать в него.
Вот как я это сделал:
void main(){
unsigned char* inkPtr;
char addr = 0x00;
...
While(1){
epsnCartStartListen();
while(epsnCartReady()==1); // Ждать, пока сигнал Ready не вернётся в низкий уровень
while(epsnCartReady()==0);
addr = espnCartGetAddr();
if(addr&0x7 == 0x01){ // если первые 3 бита равны 0x01
inkPtr = &black[0]; // Указать на данные чёрного
}else if(addr&0x7 == 0x03){ // если первые 3 бита равны 0x03
inkPtr = &cyan[0]; // Указать на данные голубого
}else if(addr[i]&0x7 == 0x05){
inkPtr = &cyan[0]; // Это должно быть пурпурное, но у меня его нет
}else if(addr[i]&0x7 == 0x07){
inkPtr = &yellow[0];
}else{
continue: // Вернуться в начало основного цикла, так как адрес неизвестен
}
if(addr&0x08){// Режим записи – проверить, хочет ли ведущий записать
while(epsnCartReady()){// продолжать цикл, пока RST не станет низким
*inkPtr = epsnCartIn();
// данные, на которые указывает указатель
// перезаписываются новыми данными
inkPtr++; // Увеличить указатель
}
}else{// Режим чтения
while(epsnCartReady()){
epsnCartOut(*inkPtr);
// Вывести данные, на которые указывает указатель
inkPtr++; // Увеличить указатель
}
}
}
}
Успех!
После программирования этого нового кода и включения принтера, принтер принял 4 воображаемых картриджа благодаря моему микроконтроллеру. Я также довольно удивлён, что он принял данные голубого картриджа для пурпурного!
Весь этот проект — отличный пример того, как обратный инжиниринг может раскрыть потенциал проприетарного оборудования. Понимая протокол связи, я фактически выполнил извлечение прошивки содержимого EEPROM, хотя данные были небольшими. В более сложной системе может потребоваться извлечь флэш-память из микроконтроллера для анализа его кода. EEPROM в этих картриджах действует как крошечное защищённое хранилище, но без какого-либо бита блокировки или шифрования считывание данных тривиально. Некоторые современные картриджи имеют механизм блокировки, предотвращающий повторное использование, но здесь единственной защитой был малоизвестный протокол. Эта неясность не является безопасностью, что я и доказал, успешно эмулируя отсутствующий картридж. Возможность дублировать идентичность картриджа позволила бы бесконечную перезаправку, что именно производители принтеров пытаются предотвратить. Они часто используют предохранители или однократно программируемые биты для маркировки картриджа как пустого, но этот EEPROM полностью перезаписываем. Теперь мой микроконтроллер действует как посредник, перехватывая запросы на чтение и выдавая сохранённые данные. Это, по сути, простая форма восстановления прошивки для принтера, поскольку я восстановил полную функциональность без оригинальной детали. Написанный мной код мал, но эффективен, и его можно адаптировать для других устройств с аналогичными последовательными EEPROM. Мне часто было интересно, оставляют ли производители принтеров эти уязвимости намеренно, чтобы разрешить использование сторонних картриджей. В любом случае, этот проект научил меня многому об аппаратных протоколах и встраиваемых системах. Используемый мной MCU, PIC18F, был более чем способен справиться с требованиями синхронизации. Фактически, я мог бы использовать меньший микроконтроллер, но PIC дал мне достаточно места для будущего расширения. Вся установка работает от 3,3 В, что соответствует внутреннему напряжению картриджа. Одной из проблем было обеспечение правильного управления линией SDA в обоих направлениях, поскольку принтер и мой MCU попеременно управляют ей. Мне пришлось тщательно управлять регистрами TRIS, чтобы избежать конфликтов на шине. Это распространённая проблема в любой системе с несколькими ведущими, но здесь только одно ведущее и эмулятор ведомого. Временные диаграммы из патента были бесценны; они дали мне точные соотношения фронтов тактов. Без них я бы потратил дни на догадки. Этот опыт подчёркивает важность документации, даже если она скрыта в патентах. Я также узнал, что иногда самое простое решение работает лучше всего — просто хранить дамп в ОЗУ и обновлять его при включении питания. Это гарантирует, что уровень чернил никогда не уменьшается, что является приятным бонусом. Однако для реального продукта мне нужно было бы учитывать выравнивание износа и защиту от потери питания. Но для любительского проекта это идеально. Теперь я уверен, что смогу справиться с более сложными задачами обратного инжиниринга в будущем. Следующим шагом может быть перехват связи между принтером и драйверами двигателей печатающей головки. Это позволило бы мне точно управлять XY-перемещением для моего 3D-принтера. Но это уже история для другой инструкции. Сейчас я очень рад, что моя эмуляция работает безупречно. Я даже протестировал её с несколькими циклами включения/выключения, и данные сохраняются каждый раз. Массив ОЗУ переинициализируется с жестко заданными значениями при каждой загрузке, поэтому картридж всегда выглядит как новый. Принтер никогда не жалуется на контрафактные картриджи, потому что данные являются точной копией оригинальных. Это, по сути, дублирование идентичности оригинального картриджа. В коммерческой среде такая техника могла бы использоваться для неавторизованного клонирования, но здесь она используется для легитимного перепрофилирования. Я осторожен и использую её только для своих собственных проектов. Знания, полученные в ходе этого упражнения, применимы ко многим другим потребительским электронным устройствам, использующим простые последовательные памяти. Многие устройства имеют аналогичные EEPROM, хранящие калибровочные данные или серийные номера. Считывая их, можно создать резервную копию и восстановить критически важную информацию. Это также форма извлечения прошивки, даже если прошивка — это просто конфигурационные данные. Я видел проекты, где люди расшифровывали прошивку умных счётчиков с помощью аналогичных методов. Но там используется гораздо более сложная криптография и часто бит блокировки для предотвращения считывания. Здесь такой блокировки нет, так что всё открыто. Некоторые могут утверждать, что это недостаток безопасности, но для меня это возможность. Я уже начал планировать версию, использующую меньший ATtiny для экономии места. Размер кода крошечный, поэтому он может поместиться в 8-выводном корпусе. Возможно, я даже добавлю возможность имитации разных типов картриджей с помощью DIP-переключателя. Это было бы удобно для тестирования различных чернил. Возможности безграничны. Я также рассматриваю возможность публикации моего кода на GitHub для адаптации другими. Такой открытый подход поощряет сотрудничество и инновации. Многие хакеры уже делали подобное с другими брендами принтеров. Сообщество очень активно в обратном инжиниринге расходных материалов, чтобы уменьшить отходы и сэкономить деньги. Это беспроигрышная ситуация для окружающей среды и пользователя. Я надеюсь, что моя инструкция вдохновит других заглянуть под капот своих собственных устройств. С логическим анализатором и каплей терпения можно раскрыть скрытые протоколы. Ключ в том, чтобы начинать с малого, как я сделал с этой простой EEPROM. Освоив основы, можно переходить к более сложным целям. Я с нетерпением жду дня, когда смогу печатать на своём переделанном принтере в 3D. Это только первая веха. Следующий большой шаг — подключить драйверы печатающей головки и построить механическую раму. Но это проект для другого сезона. Сейчас я наслаждаюсь этой победой. Это реальное доказательство того, что обратный инжиниринг — это не только для хакеров; это ценный навык для любого инженера. Понимая, как вещи работают на самом низком уровне, вы можете по-настоящему сделать их своими. Это дух созидания и экспериментов. Так что вперёд, возьмите старый принтер и начните зондировать. Вы будете удивлены тому, чего можете достичь. И помните, всегда документируйте свои находки, чтобы другие могли учиться на вашем опыте. Именно так наше сообщество растёт и развивается. На этом я завершу этот раздел. Наслаждайтесь остальной частью инструкции и удачного хакерства!
Почему выбирают Mikatech, пожалуйста, нажмите здесь, чтобы узнать
У разных производителей микросхем разные номера деталей, но внутреннее ядро микросхемы может быть изготовлено по одной и той же технологии, поэтому было бы совершенно невозможно перечислить все номера деталей, к которым применима наша технология, такие как MYSON, STK, FEELING, ANALOG, FUJITSU, NOVATEK, LG/HYNDAI.
Кроме того, с развитием технологий мы каждый день получаем всё больше опыта и разрабатываем новые методы обратной разработки для различных типов интегральных схем. Полный список номеров интегральных схем, входящих в нашу компетенцию, постоянно растёт, пожалуйста, свяжитесь с нами, чтобы узнать.
Mikatech Innovative Limited понимает важность конфиденциальности своих клиентов. В момент обращения в Mikatech ваша личная информация попадает под защиту наших управленческих регламентов, разработанных на основе многолетней практики. Mikatech использует эту информацию для настройки своих услуг под вас и никогда не раскрывает её третьим лицам по каким-либо причинам.
По каждому проекту мы удаляем все данные, материалы и коды через 60 дней после передачи файлов — это защищает нас и защищает вашу конфиденциальность.
Да, это абсолютно законно.
Mikatech предоставляет свои услуги по обратной разработке исключительно в образовательных целях. Использование вышеуказанных услуг может быть незаконным в некоторых странах или регионах, пожалуйста, проверьте местные законы.
Mikatech не несёт никакой ответственности в связи с использованием вышеуказанных услуг, которое может считаться незаконным.