Réinitialisation du kilométrage pour RICOH SP 150SUw

Je ne crois pas à la théorie du complot des fabricants (électronique) pour réduire la ressource du produit, il s'agit simplement de rechercher le meilleur rapport qualité / prix pour un segment de marché spécifique. Mais il y a un moment à partir duquel je brûle sauvagement juste sous le ventre. Ce sont les fabricants d'imprimantes. Non seulement les prix des consommables sont tels qu'ils ne peuvent être justifiés que par la présence d'un bébé vierge dans le sang, mais aussi le «déchiquetage» généralisé des cartouches, qui est déjà passé dans les unités laser pas les plus budgétaires. Mais ce qui m'a vraiment "bombardé" du produit suivant: RICOH SP 150SUw. Cet appareil a été acheté en raison du déménagement de la région de Moscou à Minsk et de la nécessité de copier / imprimer un grand nombre de documents pour obtenir un permis de travail / séjour.



Le choix était basé sur les exigences suivantes: MFP pas cher, compact, impression réseau, disponibilité des pilotes pour Linux (Fedora / Mint / OpenSUSE). Le héros de l'article possédait toutes ces caractéristiques, mais une nuance n'a pas été remarquée. Compteur de ressources incurvé. Si vous vous demandez comment guérir et



(Mémo pour Grammar Nazi d'une personne souffrant de dysgraphie légère)
, . . / , . , . «», . , , , / . , , , , . , , . , —



Bienvenue!



La chose est,que le MFP ne compte pas la quantité de toner utilisé, mais le nombre de pages imprimées. Si j'imprimais la cartouche de démarrage avec un degré de remplissage suffisamment important, alors un incident se produisait avec la seconde. Le fait est que ma femme a rapidement rejoint la communauté locale des anglophones et une partie du travail lié à la fourniture de l'imprimerie nous incombait. Ainsi, toutes sortes d'images de contour pour la découpe / la coloration / l'origami sont remplies de toner, au maximum 1% de la feuille. En conséquence, je me suis retrouvé "vide" sur le comptoir, mais en fait - un plein 70 pour cent de la cartouche. Non, je ne suis pas si pauvre pour ne pas me permettre d'en acheter un nouveau, pas si sensibilisé à l'environnement pour éprouver des tourments moraux, jeter un produit en bon état dans une décharge, mais du sentiment que vous avez été légalement vomi - la chaise a commencé à la fumée, qui était une impulsion à l'action ...



Honnêtement, je n’espérais pas devenir un «hacker de la mère», étant donné qu’une telle protection matérielle est très difficile à briser. J'ai compté, au moins, sur des algorithmes de cryptage décents et de la mémoire OTP (une fois programmable). Mais la réalité s'est avérée beaucoup plus courante. Heureusement, il y avait beaucoup d'instructions sur la demande de réinitialisation de la cartouche, et la "puce de protection" s'est avérée être une EEPROM AT24C01 I2C assez répandue , soudée avec un minimum de "kit carrosserie" pas une carte. En gros, dans l'image suivante, vous pouvez terminer l'article:





Vidéo originale



Avec n'importe quel programmeur, nous lisons le contenu du microcircuit, «zéro» les cellules entourées de cadres rouges et changeons les deux derniers chiffres du numéro de série. Il convient de noter que la série est une chaîne de texte se terminant par un espace, vous devez donc la changer dans la plage 0 ... 9 (0x30 ... 0x39). L'adresse physique du microcircuit soudé sur la carte est 0x03. Mais ... Rencontrez un cordonnier sans bottes. Il n'y a pas de programmeur universel, donc nous prenons PIC16F819 et PICKit 3, non, pour la promotion auprès des masses - Arduino UNO / Nano, une paire de résistances 4.7k (de 3k à 10k pour cette tâche - ça fera l'affaire), un compteur MGTF ou votre fil préféré et assemblez le suivant "Scheme":







Assemblé, il ressemble à ceci:







J'ai retiré la carte "protection" de la cartouche pour m'assurer que le brochage donné dans le manuel correspond à la réalité et pour obtenir l'adresse physique du microcircuit sur le bus:





Plots de contact, de gauche à droite: GND, + 5V, SCL . SDA.



Vous n'avez pas besoin d'être intelligent avec la fabrication de l'adaptateur, mais soudez les fils directement sur la carte sans la retirer de la cartouche. Ensuite, copiez mon code merdique dans l'IDE Arduino:



Shitcode
#include <stdint.h>
#include <Wire.h>

//----------------------------------------------------------------
#define EERROM_SZ         (0x80)
#define EERROM_PHY_ADDR   (0x03)
#define EERROM_HEAD       (0x50)
#define PRN_BUFF_SZ       (0x08)
#define SER_START_ADDR    (0x20)
#define SER_END_ADDR      (0x2B)
#define SER_MOD_ADDR0     (0x2A)
#define SER_MOD_ADDR1     (0x29)
#define SER_MOD_ADDR2     (0x28)

//----------------------------------------------------------------
static uint8_t eeprom_data[EERROM_SZ];
static bool erased;
static bool z_filled;
//----------------------------------------------------------------
static uint8_t ee_read(uint8_t phy_addr, uint8_t addr)
{
  uint8_t res;

  Wire.beginTransmission(EERROM_HEAD | phy_addr);
  Wire.write(addr);
  Wire.endTransmission();
  Wire.requestFrom(EERROM_HEAD | phy_addr, 1);
  res = Wire.read();
  
  return res;
}

//----------------------------------------------------------------
static void ee_write(uint8_t phy_addr, uint8_t addr, uint8_t data)
{
  Wire.beginTransmission(EERROM_HEAD | phy_addr);
  Wire.write(addr);
  Wire.write(data);
  Wire.endTransmission();
  delay(5);
}


//----------------------------------------------------------------
static void read_data(uint8_t phy_addr)
{
  uint8_t addr;
  uint8_t data;
  
  erased = true;
  z_filled = true;
  
  Serial.print("Read from phy addr ");
  Serial.print(phy_addr);

  for (addr = 0; addr < EERROM_SZ; addr++)
  {
    if (0 == (addr & 0x03))
    {
      Serial.print(".");
    }
    data = ee_read(phy_addr, addr);
    eeprom_data[addr] = data;

    if (0xFF != data)
    {
      erased = false;
    }

    if (0x00 != data)
    {
      z_filled = false;
    }
  }
  
  Serial.println("Ok");
}

//----------------------------------------------------------------
static void write_data(uint8_t phy_addr)
{
  uint8_t addr;

  Serial.print("Write to phy addr ");
  Serial.print(phy_addr);

  for (addr = 0; addr < EERROM_SZ; addr++)
  {
    if (0 == (addr & 0x03))
    {
      Serial.print(".");
    }
    ee_write(phy_addr, addr, eeprom_data[addr]);
  }

  Serial.println("Ok");
}

//----------------------------------------------------------------
static bool check_data(uint8_t phy_addr)
{
  uint8_t addr;
  uint8_t data;
  
  Serial.print("Check from phy addr ");
  Serial.print(phy_addr);

  for (addr = 0; addr < EERROM_SZ; addr++)
  {
    if (0 == (addr & 0x03))
    {
      Serial.print(".");
    }
    data = ee_read(phy_addr, addr);
    if (eeprom_data[addr] != data)
    {
      Serial.println("FAILED");
      return false;
    }
  }
  
  Serial.println("Ok");
  return true;
}


//----------------------------------------------------------------
static void print_data(void)
{
  uint16_t addr;
  char prn_buff[PRN_BUFF_SZ];
  
  for(addr = 0; addr < EERROM_SZ; addr++)
  {

    if (0x00 == (addr & 0x0F))
    {
      snprintf(prn_buff, PRN_BUFF_SZ, "%4X:  ", addr);
      Serial.print(prn_buff);
    }
    
    snprintf(prn_buff, PRN_BUFF_SZ, "%2X ", eeprom_data[addr]);
    Serial.print(prn_buff);
    
    if (0x0F == (addr & 0x0F))
    {
      Serial.print("\n\r");
    }
  }
  Serial.print("\n\r");
}

//----------------------------------------------------------------
static void prn_serial(void)
{
  Serial.print("Serial #: ");
  Serial.write(&eeprom_data[SER_START_ADDR], 1 + SER_END_ADDR - SER_START_ADDR);
  Serial.print("\n\r");
}

//----------------------------------------------------------------
static void mod_serial(void)
{
  eeprom_data[SER_MOD_ADDR0]++;
  if (eeprom_data[SER_MOD_ADDR0] > '9')
  {
    eeprom_data[SER_MOD_ADDR0] = '2';
  }

  eeprom_data[SER_MOD_ADDR1]++;
  if (eeprom_data[SER_MOD_ADDR1] > '9')
  {
    eeprom_data[SER_MOD_ADDR1] = '3';
    eeprom_data[SER_MOD_ADDR2]++;
    if (eeprom_data[SER_MOD_ADDR2] > '9')
    {
      eeprom_data[SER_MOD_ADDR2] = '1';
    }
  }
}

//----------------------------------------------------------------
static void reset_mileage(void)
{
  uint8_t i;
  
  for (i = 0x12; i <= 0x1F; i++)
  {
    eeprom_data[i] = 0;
  }

  for (i = 0x2C; i <= 0x7F; i++)
  {
    eeprom_data[i] = 0;
  }
}

//----------------------------------------------------------------
static bool test_magic(void)
{
  if (0x32 != eeprom_data[0]) return false;
  if (0x00 != eeprom_data[1]) return false;
  if (0x01 != eeprom_data[2]) return false;
  if (0x03 != eeprom_data[3]) return false;
  return true;
}

//----------------------------------------------------------------
void setup()
{
  int key;

  Serial.begin(9600);
  Wire.begin();

  Serial.println("\tSP 150 cartridge mileage resetter");
  Serial.println("Connect like this:");
  Serial.println("             TOP");
  Serial.println("______________________________");
  Serial.println("|o |GND| |+5V| |SCL| |SDA|  <=");
  Serial.println("|  |GND| | 5V| | A5| | A4|    ");
  Serial.println("------------------------------");
  Serial.println("        cartridge roller");
  
  Serial.println("\n\r\n\r\tTo start, press 'm' or any button for test (not prog)...\n\r");

  do
  {
    key = Serial.read();
  }
  while(-1 == key);
  
#if 0
  for (uint8_t paddr = 0; paddr < 8; paddr++)
  {
    Serial.print("Scan phy ");
    Serial.println(paddr);
    for (uint8_t i = 0; i < 5; i++)
    {
      Serial.print("Read from ");
      Serial.print(i);
      Serial.print(".........");
      Serial.println(ee_read(paddr, i));
    }
  }
  return;
#endif

  read_data(EERROM_PHY_ADDR);
  Serial.println("Read:");
  print_data();
    
  if (true == erased)
  {
    Serial.println("ERROR! The EEPROM is erased or the connection / phy addr is incorrect.");
    return;
  }

  if (true == z_filled)
  {
    Serial.println("ERROR! The EEPROM is Z filled.");
    return;
  }

  
  if (false == test_magic())
  {
    Serial.println("ERROR! Invalid magic number.");
    return;
  }

  prn_serial();
  
  mod_serial();
  reset_mileage();

  Serial.println("\n\rModified:");
  print_data();
  prn_serial();

  if ('m' != (char)key)
  {
    Serial.println("WARNING! The data was not modified in the EEPROM");
    return;
  }

  write_data(EERROM_PHY_ADDR);

  if (false == check_data(EERROM_PHY_ADDR))
  {
    return;
  }
  
  Serial.println("Fin");
}



void loop()
{
  //do nothing
}

      
      







(À propos du code de merde - oui, il n'a pas été optimisé ni par la mémoire (toutes les données sont lues dans un tableau), ni par les performances (la lecture et l'écriture sont effectuées octet par octet), ni par fonctionnalité, mais pour une tâche aussi simple - et ainsi de suite!)



Nous flashons Arduinka, ouvrons n'importe quel terminal (I18n, 9600 bauds), l'IDE Arduino intégré fera l'affaire, réinitialisons la carte, appuyez sur n'importe quel bouton:







Après cela, le contenu de l'EEPROM sera lu, modifié, mais pas écrit. Si la procédure s'est déroulée sans erreur, réinitialisez à nouveau la carte, appuyez sur m, après quoi toutes les étapes seront exécutées et les données modifiées seront écrites. En cas de problème, vérifiez à nouveau le diagramme et réessayez. Après une remise à zéro réussie, nous soudons les fils et installons la cartouche en place. Le niveau de toner doit être de 100%.



Je m'excuse pour le "eau", l' instruction de 3 lignes - très peu pour un message. J'espère que les informations ont été utiles, et aussi - l'auteur n'est pas responsable des éventuels dommages matériels, de la privation du service de garantie, tout ce que vous faites est à vos risques et périls ...



Une autre mise à jour, une décharge reçue de ma cartouche:



Read from phy addr 3................................Ok
   0:  32  0  1  3  2  1  1  0  0  0 34 30 38 30 31 30 
  10:  16  5 4D 4D  1  2 11 70  0  0  0  0 14 14  5 21 
  20:  43 37 30 36 4D 39 30 33 31 39 35 20  0 45  0  0 
  30:  39  1  0  0  0  0  0  0 3E  4  0  0  0  0  0  0 
  40:   5  3  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
  50:   0  0  0  0  0  0  0  0 14  E  5 1B 14  E  5 1B 
  60:   0  0  0  0  0  0  0  0 77  2  0  0  0  0  0  0 
  70:  C3 23 2A  0 16  0  0 55  0  0  0  0  0  0  0  0 

      
      






All Articles