Hacking the HP45

Powder and inkjet printing
Priyashree2
Posts: 3
Joined: Tue Apr 07, 2020 4:51 pm

Re: Hacking the HP45

Post by Priyashree2 »

I am trying to test my hp 45 ink cartridge using tlc59213 and Arduino mega board. I have used following code for testing

Code: Select all

//the test code for the HP45 hacking tests. Connected to an Arduino Mega 2560. All primitives and addresses go to TLC59213 drivers. All address outputs are pulled to ground with a 10k resistor on the TLC output side.

//pin names
const byte Led = 13;
const byte Switch = 10;

//variables
word nozzle = 0;
const byte LineBufferSize = 200;
byte LineBuffer[LineBufferSize][22]; //holds the information for a sweep, only holds the even side (0-12) of the printhead, even odd (1-13) is not used for now
byte LineBufferRepeat[LineBufferSize]; //holds the information on how often a sweep needs to be repeated
byte LineBufferFilled = 0;


//nozzle table
const byte NozzlePrim[300] = {
  1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
  1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
  1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
  1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
  3, 4, 3, 4, 3, 4, 3, 4, 3, 4,
  3, 4, 3, 4, 3, 4, 3, 4, 3, 4,
  3, 4, 3, 4, 3, 4, 3, 4, 3, 4,
  3, 4, 3, 4, 3, 4, 3, 4, 3, 4,
  3, 4, 3, 4, 5, 6, 5, 6, 5, 6,
  5, 6, 5, 6, 5, 6, 5, 6, 5, 6,
  5, 6, 5, 6, 5, 6, 5, 6, 5, 6,
  5, 6, 5, 6, 5, 6, 5, 6, 5, 6,
  5, 6, 5, 6, 5, 6, 5, 6, 7, 8,
  7, 8, 7, 8, 7, 8, 7, 8, 7, 8,
  7, 8, 7, 8, 7, 8, 7, 8, 7, 8,
  7, 8, 7, 8, 7, 8, 7, 8, 7, 8,
  7, 8, 7, 8, 7, 8, 7, 8, 7, 8,
  7, 8, 9, 10, 9, 10, 9, 10, 9, 10,
  9, 10, 9, 10, 9, 10, 9, 10, 9, 10,
  9, 10, 9, 10, 9, 10, 9, 10, 9, 10,
  9, 10, 9, 10, 9, 10, 9, 10, 9, 10,
  9, 10, 9, 10, 9, 10, 11, 12, 11, 12,
  11, 12, 11, 12, 11, 12, 11, 12, 11, 12,
  11, 12, 11, 12, 11, 12, 11, 12, 11, 12,
  11, 12, 11, 12, 11, 12, 11, 12, 11, 12,
  11, 12, 11, 12, 11, 12, 11, 12, 11, 12,
  13, 14, 13, 14, 13, 14, 13, 14, 13, 14,
  13, 14, 13, 14, 13, 14, 13, 14, 13, 14,
  13, 14, 13, 14, 13, 14, 13, 14, 13, 14,
  13, 14, 13, 14, 13, 14, 13, 14, 13, 14
};

const byte NozzleAdd[300] = {
  1, 9, 16, 2, 9, 17, 2, 10, 17, 3,
  10, 18, 3, 11, 18, 4, 11, 19, 4, 12,
  19, 5, 12, 20, 5, 13, 20, 6, 13, 21,
  6, 14, 21, 7, 14, 22, 17, 15, 22, 8,
  15, 1, 8, 13, 1, 9, 16, 2, 9, 17,
  2, 10, 17, 3, 10, 18, 3, 11, 18, 4,
  11, 19, 4, 12, 19, 5, 12, 20, 5, 13,
  20, 6, 13, 21, 6, 14, 21, 7, 14, 22,
  7, 15, 22, 8, 15, 1, 8, 16, 1, 9,
  16, 2, 9, 17, 2, 10, 17, 3, 10, 18,
  3, 11, 18, 4, 11, 19, 4, 12, 19, 5,
  12, 20, 5, 13, 20, 6, 13, 21, 6, 14,
  21, 7, 14, 22, 7, 15, 22, 8, 15, 1,
  8, 16, 1, 9, 16, 2, 9, 17, 2, 10,
  17, 3, 10, 18, 3, 11, 18, 4, 11, 19,
  4, 12, 19, 5, 12, 20, 5, 13, 20, 6,
  13, 21, 6, 14, 21, 7, 14, 22, 7, 15,
  1, 8, 16, 1, 8, 16, 1, 9, 16, 2,
  9, 17, 2, 10, 19, 3, 10, 18, 3, 11,
  18, 4, 11, 19, 4, 12, 19, 5, 12, 20,
  5, 13, 20, 6, 13, 21, 6, 14, 21, 7,
  14, 22, 7, 15, 22, 8, 15, 1, 8, 16,
  1, 9, 16, 2, 9, 17, 2, 10, 17, 3,
  10, 18, 3, 11, 18, 4, 11, 19, 4, 12,
  19, 5, 12, 22, 5, 13, 20, 6, 13, 21,
  6, 14, 21, 7, 14, 22, 7, 15, 22, 8,
  15, 1, 8, 16, 1, 9, 16, 2, 9, 17,
  2, 10, 17, 3, 10, 18, 3, 11, 18, 4,
  11, 19, 4, 12, 19, 5, 12, 20, 5, 13,
  20, 6, 13, 21, 6, 14, 21, 7, 14, 21
};

const byte CharBuffer[40][5] = {
  {B00111110, B01000101, B01001001, B01010001, B00111110}, //0
  {B00000000, B00100001, B01111111, B00000001, B00000000}, //1
  {B00100001, B01000011, B01000101, B01001001, B00110001}, //2
  {B01000010, B01000001, B01010001, B01101001, B01000110}, //3
  {B00001100, B00010100, B00100100, B01111111, B00000100}, //4
  {B01110010, B01010001, B01010001, B01010001, B01001110}, //5
  {B00011110, B00101001, B01001001, B01001001, B00000110}, //6
  {B01000000, B01000111, B01001000, B01010000, B01100000}, //7
  {B00110110, B01001001, B01001001, B01001001, B00110110}, //8
  {B00110000, B01001001, B01001001, B01001010, B00111100}, //9
  {B00000000, B00000000, B00000000, B00000000, B00000000}, //SPACE
  {B00111111, B01000100, B01000100, B01000100, B00111111}, //A
  {B01111111, B01001001, B01001001, B01001001, B00110110}, //B
  {B00111110, B01000001, B01000001, B01000001, B00100010}, //C
  {B01111111, B01000001, B01000001, B00100010, B00011100}, //D
  {B01111111, B01001001, B01001001, B01001001, B01000001}, //E
  {B01111111, B01001000, B01001000, B01001000, B01000000}, //F
  {B00111110, B01000001, B01001001, B01001001, B00101111}, //G
  {B01111111, B00001000, B00001000, B00001000, B01111111}, //H
  {B00000000, B01000001, B01111111, B01000001, B00000000}, //I
  {B00000010, B00000001, B01000001, B01111110, B01000000}, //J
  {B01111111, B00001000, B00010100, B00100010, B01000001}, //K
  {B01111111, B00000001, B00000001, B00000001, B00000001}, //L
  {B01111111, B00100000, B00011000, B00100000, B01111111}, //M
  {B01111111, B00010000, B00001000, B00000100, B01111111}, //N
  {B00111110, B01000001, B01000001, B01000001, B00111110}, //O
  {B01111111, B01001000, B01001000, B01001000, B00110000}, //P
  {B00111110, B01000001, B01000101, B01000010, B00111101}, //Q
  {B01111111, B01001000, B01001100, B01001010, B00110001}, //R
  {B00110001, B01001001, B01001001, B01001001, B01000110}, //S
  {B01000000, B01000000, B01111111, B01000000, B01000000}, //T
  {B01111110, B00000001, B00000001, B00000001, B01111110}, //U
  {B01111100, B00000010, B00000001, B00000010, B01111100}, //V
  {B01111110, B00000001, B00001110, B00000001, B01111110}, //W
  {B01100011, B00010100, B00001000, B00010100, B01100011}, //X
  {B01110000, B00001000, B00000111, B00001000, B01110000}, //Y
  {B01000011, B01000101, B01001001, B01010001, B01100001}, //Z
};
/*
   pins on the Arduino Mega
   Address clock PH3 (6)
   Address _clear PH4 (7)
   Primitive clock PH5 (8)
   Primitive _clear PH6 (9)

   Primitive 1-8 PL0-PL7 (49;48;47;46;45;44;43;42)
   Primitive 9-14 PK0-PK5 (A8;A9;A10;A11;A12;A13)
   Address 1-8 PC0-PC7 (37;36;35;34;33;32;31;30)
   Address 9-16 PA0-PA7 (22;23;24;25;26;27;28;29)
   Address 17-22 PF0-PF5 (A0;A1;A2;A3;A4;A5)

   Temp sense
   10x resistor
   Nozzle check pin
*/

//global variables
int Loops = 1000; //the amount of loops done while triggering the printhead.
int extradelay = 500;

void setup() {

  //set pin directions
  pinMode(Led, OUTPUT);
  pinMode(Switch, INPUT);

  DDRH = DDRH | B01111000; //clears and clocks
  DDRL = DDRL | B11111111; //primitive 1-8
  DDRK = DDRK | B00111111; //primitive 9-14
  DDRC = DDRC | B11111111; //address 1-8
  DDRA = DDRA | B11111111; //address 9-16
  DDRF = DDRF | B00111111; //address 17-22

  //reset clears
  PORTH = PORTH | B01010000;
  PORTH = PORTH & B10101111;

  //set addresses and primitives to 0
  PORTL - PORTL & B00000000;
  PORTK - PORTK & B11000000;
  PORTC - PORTC & B00000000;
  PORTA - PORTA & B00000000;
  PORTF - PORTF & B11000000;
}

void loop() {

  //set the led high to show ejecting is in progress
  if (digitalRead(Switch)) {//eject a zigzag pattern
    digitalWrite(Led, 1);

    delay(2000);

    for (int pr = 0; pr < 37; pr ++) {

      GenerateChar(pr, 10);
      PrintLinebuffer(1000);
      ClearLinebuffer();
      delay(100);
    }

    /*
    FillLinebufferTest();
    PrintLinebuffer(1000);
    delay(1000);*/



    //make the led low to show ejection is over
    digitalWrite(Led, 0);
  }
}





void ClearLinebuffer() {
  for (int lb = 0; lb < LineBufferSize; lb++) {
    for (int a = 0; a < 22; a++) {
      LineBuffer[lb][a] = 0;
    }
    LineBufferRepeat[lb] = 0;
  }
  LineBufferFilled = 0;
}


void GenerateSquare(byte SquareSize, byte SquareThickness) {
  LineBufferFilled = SquareSize;
  for (byte sz = 0; sz < SquareSize; sz++) {
    //generate start
    if (sz < SquareThickness) {
      for (int ss = 0; ss < SquareSize; ss++) { //all nozzles in the square need to be on
        word ActualNozzle = ss * 2; //needs to be multiplied to get even side
        word PrimAddress = NozzlePrim[ActualNozzle] - 1;
        PrimAddress /= 2;
        bitWrite(LineBuffer[sz][NozzleAdd[ActualNozzle] - 1], PrimAddress, 1);
        LineBufferRepeat[sz] = 1;
      }
    }

    //generate end
    else if (sz > SquareSize - SquareThickness) {
      for (int ss = 0; ss < SquareSize; ss++) { //all nozzles in the square need to be on
        word ActualNozzle = ss * 2; //needs to be multiplied to get even side
        word PrimAddress = NozzlePrim[ActualNozzle] - 1;
        PrimAddress /= 2;
        bitWrite(LineBuffer[sz][NozzleAdd[ActualNozzle] - 1], PrimAddress, 1);
        LineBufferRepeat[sz] = 1;
      }
    }

    //generate middle
    else {
      for (int ss = SquareSize; ss > SquareSize - SquareThickness; ss--) { //all nozzles on the edges of square need to be on
        word ActualNozzle = ss * 2; //needs to be multiplied to get even side
        word PrimAddress = NozzlePrim[ActualNozzle] - 1;
        PrimAddress /= 2;
        bitWrite(LineBuffer[sz][NozzleAdd[ActualNozzle] - 1], PrimAddress, 1);
        LineBufferRepeat[sz] = 1;
      }
      for (int ss = 0; ss < SquareThickness; ss++) { //all nozzles on the edges of square need to be on
        word ActualNozzle = ss * 2; //needs to be multiplied to get even side
        word PrimAddress = NozzlePrim[ActualNozzle] - 1;
        PrimAddress /= 2;
        bitWrite(LineBuffer[sz][NozzleAdd[ActualNozzle] - 1], PrimAddress, 1);
        LineBufferRepeat[sz] = 1;
      }
    }
  }
}


void GenerateChar(byte CharNumber, byte CharMultiplier) {
  byte NumberOfCols = 0;
  for (byte col = 0; col < 5; col++) { //run through all columns of the specified character
    for (byte pixelwidth = 0; pixelwidth < CharMultiplier; pixelwidth ++) {
      for (byte pixel = 0; pixel < 8; pixel ++) { //run through all inidividual pixels
        if (bitRead(CharBuffer[CharNumber][col], pixel) == 1) {
          for (byte pix = 0; pix < CharMultiplier; pix ++) {
            word ActualNozzle = pixel * CharMultiplier;
            ActualNozzle += pix;
            ActualNozzle *= 2;
            word PrimAddress = NozzlePrim[ActualNozzle] - 1;
            PrimAddress /= 2;
            bitWrite(LineBuffer[NumberOfCols][NozzleAdd[ActualNozzle] - 1], PrimAddress, 1);
            LineBufferRepeat[NumberOfCols] = 1;
          }
        }
      }
      NumberOfCols ++;
    }
  }
  LineBufferFilled = NumberOfCols;
}

void PrintLinebuffer(word LinebufferSpeed) { //prints what is stored in the linebuffer
  for (int lb = 0; lb < LineBufferFilled; lb++) { //start at the first place of the linebuffer, and work up
    for (byte r = 0; r < LineBufferRepeat[lb]; r++) { //repeat the information in the linebuffer n times
      for (byte a = 0; a < 22; a++) {
        //rewrite primitive ports
        byte TriggerPortP1 = 0;
        byte TriggerPortP2 = 0;
        byte TempPrim = LineBuffer[lb][a];
        for (int p = 0; p < 7; p++)
        {
          byte TempPrim2 = p * 2;
          if (bitRead(TempPrim, p) == 1) {
            if (TempPrim2 < 8) {
              bitWrite(TriggerPortP1, TempPrim2, 1);
            }
            else {
              bitWrite(TriggerPortP2, TempPrim2 - 8, 1);
            }
          }
        }

        //rewrite Addresses to ports
        byte TriggerPortP3 = 0;
        byte TriggerPortP4 = 0;
        byte TriggerPortP5 = 0;
        if (a >= 0 && a < 8) {
          bitWrite(TriggerPortP3, a, 1);
        }
        else if (a >= 8 && a < 16) {
          bitWrite(TriggerPortP4, a - 8, 1);
        }
        else {
          bitWrite(TriggerPortP5, a - 16, 1);
        }




        //open address
        PORTH = PORTH & B11110111; //set clock to low
        PORTH = PORTH | B00010000; //set clear to high
        PORTC = PORTC | TriggerPortP3; //set address pin high
        PORTA = PORTA | TriggerPortP4; //set address pin high
        PORTF = PORTF | TriggerPortP5; //set address pin high
        PORTH = PORTH | B00001000; //set clock to high
        PORTH = PORTH & B11110111; //set clock low
        PORTC = PORTC & B00000000; //set address pin low
        PORTA = PORTA & B00000000; //set address pin low
        PORTF = PORTF & B11000000; //set address pin low

        //address clear remains high until it needs to be reset
        delayMicroseconds(2); //opening delay

        //trigger primtive
        PORTH = PORTH & B11011111; //turn clock off
        PORTH = PORTH | B01000000; //turn clear high
        PORTL = TriggerPortP1; //set primitive1 pins high
        PORTK = TriggerPortP2; //set primitive2 pins high
        PORTH = PORTH | B00100000; //trigger clock
        PORTH = PORTH & B11011111; //set clock to low
        PORTL = PORTL & B00000000; //set primitive pins low
        PORTK = PORTK & B11000000; //set primitive pins low
        //primitive clear remains high until the primitives need to be reset

        //trigger delay
        delayMicroseconds(2);

        //close primitive
        PORTH = PORTH | B01000000; //set clear to high
        PORTH = PORTH & B10111111;//set clear to low
        delayMicroseconds(3); //delay to allow the ports to close properly

        //close address
        PORTH = PORTH | B00010000; //set address clear to high
        PORTH = PORTH & B11101111; //set address clear to low
        delayMicroseconds(2);


      }
      delayMicroseconds(LinebufferSpeed);
    }
  }
}

void FillLinebufferTest() {
  for (int lb = 0; lb < 10; lb++) {
    for (int a = 0; a < 22; a++) {
      LineBuffer[lb][a] = B01111111;
    }
    LineBufferRepeat[lb] = 10;
  }
  LineBufferFilled = 10;
}

void DepositZigzag() { //deposits an up and down zigzag pattern once
  for (int i = 0; i < 150; i ++) {
    TriggerSingleNozzle(i * 2);
    delayMicroseconds(extradelay);
  }

  for (int i = 149; i >= 0; i --) {
    TriggerSingleNozzle(i * 2);
    delayMicroseconds(extradelay);
  }
}

void TriggerSingleNozzle(int TriggerNozzle) { //triggers a single defined nozzle
  TriggerNozzle = constrain(TriggerNozzle, 0, 299);
  byte TriggerPrimitive = NozzlePrim[TriggerNozzle] - 1; //calculate what primitive needs to be on
  byte TriggerAddress = NozzleAdd[TriggerNozzle] - 1;//calculate what address needs to be on

  //rewrite Primitives to ports
  byte TriggerPortP1 = 0;
  byte TriggerPortP2 = 0;
  if (TriggerPrimitive >= 0 && TriggerPrimitive < 8) {
    bitWrite(TriggerPortP1, TriggerPrimitive, 1);
  }
  else if (TriggerPrimitive >= 8 && TriggerPrimitive < 16) {
    bitWrite(TriggerPortP2, TriggerPrimitive - 8, 1);
  }


  //rewrite Addresses to ports
  byte TriggerPortP3 = 0;
  byte TriggerPortP4 = 0;
  byte TriggerPortP5 = 0;
  if (TriggerAddress >= 0 && TriggerAddress < 8) {
    bitWrite(TriggerPortP3, TriggerAddress, 1);
  }
  else if (TriggerAddress >= 8 && TriggerAddress < 16) {
    bitWrite(TriggerPortP4, TriggerAddress - 8, 1);
  }
  else {
    bitWrite(TriggerPortP5, TriggerAddress - 16, 1);
  }


  //open address
  PORTH = PORTH & B11110111; //set clock to low
  PORTH = PORTH | B00010000; //set clear to high
  PORTC = PORTC | TriggerPortP3; //set address pin high
  PORTA = PORTA | TriggerPortP4; //set address pin high
  PORTF = PORTF | TriggerPortP5; //set address pin high
  PORTH = PORTH | B00001000; //set clock to high
  PORTH = PORTH & B11110111; //set clock low
  PORTC = PORTC & B00000000; //set address pin low
  PORTA = PORTA & B00000000; //set address pin low
  PORTF = PORTF & B11000000; //set address pin low

  //address clear remains high until it needs to be reset
  delayMicroseconds(2); //opening delay

  //trigger primtive
  PORTH = PORTH & B11011111; //turn clock off
  PORTH = PORTH | B01000000; //turn clear high
  PORTL = TriggerPortP1; //set primitive1 pins high
  PORTK = TriggerPortP2; //set primitive2 pins high
  PORTH = PORTH | B00100000; //trigger clock
  PORTH = PORTH & B11011111; //set clock to low
  PORTL = PORTL & B00000000; //set primitive pins low
  PORTK = PORTK & B11000000; //set primitive pins low
  //primitive clear remains high until the primitives need to be reset

  //trigger delay
  delayMicroseconds(2);

  //close primitive
  PORTH = PORTH | B01000000; //set clear to high
  PORTH = PORTH & B10111111;//set clear to low
  delayMicroseconds(3); //delay to allow the ports to close properly

  //close address
  PORTH = PORTH | B00010000; //set address clear to high
  PORTH = PORTH & B11101111; //set address clear to low
  delayMicroseconds(2);

  delayMicroseconds(200);//end delay
}

HP45 Mega connection diagram.jpg
HP45 Mega connection diagram.jpg (332.99 KiB) Viewed 13102 times
I have soldered wires directly on HP 45 Ink Cartirage. As you can see arrangement on my youtube link (
https://youtu.be/Z8CNYmF_oX8)

I won't able to get ink out of cartridge. I need help regarding my setup how can I debug or test the circuit. I am using 12v 2amps power supply. But I didn't put 10k on address output side. Is that might be problem ?
User avatar
dragonator
Site Admin
Posts: 595
Joined: Fri Aug 14, 2015 4:48 pm
Location: The Nethelands
Contact:

Re: Hacking the HP45

Post by dragonator »

The pulldown resistors on the address side are not really optional when using TLC59213. Without pull down and address takes well over 1ms to go to low. In your current setup there is a good chance that multiple or even all addresses are open when you print. This prevent the nozzles from firing properly.

The code does seem right, but it is hard to judge whether or not there are tiny mistakes without measuring the outputs. It was a bit confusing to me that you first make clear high after each trigger, and then low, since it only activates while it is low, but that should not hinder the functionality.

If you have something like an oscilloscope I would suggest using that on your setup. If you can see what type of signal goes to an address and a primitive, you might be able to see why your printhead is not triggering.
Priyashree2
Posts: 3
Joined: Tue Apr 07, 2020 4:51 pm

Re: Hacking the HP45

Post by Priyashree2 »

dragonator wrote: Thu Apr 09, 2020 6:27 am The pulldown resistors on the address side are not really optional when using TLC59213. Without pull down and address takes well over 1ms to go to low. In your current setup there is a good chance that multiple or even all addresses are open when you print. This prevent the nozzles from firing properly.

The code does seem right, but it is hard to judge whether or not there are tiny mistakes without measuring the outputs. It was a bit confusing to me that you first make clear high after each trigger, and then low, since it only activates while it is low, but that should not hinder the functionality.

If you have something like an oscilloscope I would suggest using that on your setup. If you can see what type of signal goes to an address and a primitive, you might be able to see why your printhead is not triggering.
Thanks for your response @dragonator.
I have simplified the circuit now, I am now trying to trigger single nozzle using Address 1 and Primitive 1. I have now putted 10k pull down on address output.
IMG_20200409_224626.jpg
IMG_20200409_224626.jpg (414.4 KiB) Viewed 13073 times
Arduino code for testing the nozzle

Code: Select all

//the test code for the HP45 hacking tests

//pin names
//const byte AddressClock = A7; //C0 //is connected to both _clear and clock
//const byte AddressClear = A6; 
//const byte Addres1 = A5; 
//const byte PrimitiveClock = A4; //C2 //is connected to both _clear and clock
//const byte Primitive1 = A3; //C3
//const byte PrimitiveClear = A2; //D6
const byte Led = 13;

//global variables
int Loops = 5000; //the amount of loops done while triggering the printhead.

void setup() {

  //set pin directions
  pinMode(Led, OUTPUT);

  DDRF = DDRF | B11111100;

  PORTF = PORTF | B01001000;
  PORTF = PORTF & B10110111;
}

void loop() {

  //set the led high to show ejecting is in progress
  digitalWrite(Led, 1);

  for (int i = 0; i < Loops; i++) {
    //open the address:
    PORTF = PORTF & B01111111;  //turn 7 (address clock) low
    PORTF = PORTF | B01100000;  //turn 5 and 6 (address _clear & address pin1) high
    PORTF = PORTF | B10000000;  //turn 7 (address clock) high
    PORTF = PORTF & B01011111;  //turn 5 and 7 (address pin1 & address clock) low
    //address _clear remains low until the pins need to be reset
    delayMicroseconds(2);

    //open the primitive:
    PORTF = PORTF & B11101111;  //turn 4 (prim clock) low
    PORTF = PORTF | B00001100;  //turn 2 and 3 (prim _clear & prim pin1) high
    PORTF = PORTF | B00010000;  //turn 4 (prim clock) high
    PORTF = PORTF & B11101011;  //turn 2 amd 4 (prim pin1 & prim clock) low
    //primitive _clear remains low until the pins need to be reset
  
    //delay
    delayMicroseconds(2);
    
    //close primitive
    PORTF = PORTF | B00001000; //turn 3 (prim _clear) high
    PORTF = PORTF & B11110111; //turn 3 (prim _clear) low 
    delayMicroseconds(2);

    //close address
    PORTF = PORTF | B01000000; //turn 6 (address _clear) high
    PORTF = PORTF & B10111111; //turn 6 (prim _clear) low 
    delayMicroseconds(140);
  }

  //make the led low to show ejection is over
  digitalWrite(Led, 0);

  //wait for a second
  delay (1000);
}

Before running the Hardware, I have checked the cartridge connectivity with daughter board. As I am getting the valve as follows. DMM has been set on continuity mode.
IMG_20200409_220309.jpg
IMG_20200409_220309.jpg (179.3 KiB) Viewed 13073 times
IMG_20200409_220102.jpg
IMG_20200409_220102.jpg (309.77 KiB) Viewed 13073 times
IMG_20200409_215903.jpg
IMG_20200409_215903.jpg (236.36 KiB) Viewed 13073 times
Schematic diagram

IMG_20200409_232216.jpg
IMG_20200409_232216.jpg (215.1 KiB) Viewed 13073 times
Actually I don't have oscilloscope , so it getting difficult to check why it's not triggering the nozzle.
myying
Posts: 17
Joined: Mon Dec 16, 2019 10:16 am
Location: Taipei

Re: Hacking the HP45

Post by myying »

david wrote: Thu Oct 05, 2017 12:34 pm
dragonator wrote: I still want to really try the L6452. I do however still have a few objections with the L6452 that have stopped me from completely stopping what I am doing so far and use the L6452.
  • Limited availability. Only Mouser sells them in small quantities and I don't know if they restock.
  • Unknowns in the datasheet. The entire VBoost section is an unknown. We assume 19V, but we don't know.
  • Not completely standalone. You still need a boost converter for the driving of the gates.
  • More pins required. I need 9 pins to drive the entire circuit. The L6452 needs 16 (?)
  • (Maybe not 3.3V compatible, but that I still need to test, datasheet is on the limit)
On the other hand it is a bit more compact and has more advanced features. The testing part has a proper constant current source. I will still give this a try cause I still think it is a neat solution, but I have started to make the TLC circuit work, and the last big problem I had (not being able to fire all primitives at once) seems to be gone. I am not going to redo the entire circuit again only to save a few components. If I am going to use the L6452 it will be on V3. After I am done writing the code for V2 I will see if I can experiment with it myself.
Your concerns about L6452 are actually true. It is valuable to have a different implementation. BTW, what initially stopped you from fire all nozzles at once with the TLC chip?
Hi David
Right now, does L6452 not phase out?
L6452 is mostly same as DJ9xx printhead ASIC.
smeric
Posts: 10
Joined: Sat Mar 14, 2020 11:08 am
Location: Turkey & Sweden

Re: Hacking the HP45

Post by smeric »

I am trying to fix my HP45 Head. I write before and dragonator give some tips but its still not working. I did standart alone circuit with teensy 3.2.

I dont have printer parts I wanna use and trow some ink with HP45. I am Trying send command via Serial Port.
first I am trying THD and its turning "/" .. thats mean all nozzle is connected.
and when I am trying to send GTP. its send back only -C. that mean someting wrong.

I test all mosfet. SIRA21(Q3) and Q1,Q2

there are some different on my circuit components like

Original Bom -> My Circuit
(Q1,Q2) PMV20CNER -> 2N7002
(IC5) HCF4081 -> HEF4081BT
Oasis SA 3.00.00

OK

THD://////////////////////////////////////////////////
OK

GTP:-C


As I said I dont wanna use that head as a 3dprinter. so I dont have any other mechanic and electonic for take step and dir signal. I wanna use that firware via Serial port. dragonator said me use "PRM Po" command via serial. result is only "OK" but notting happened.

I need some more help to solve that GTP error. I dont know but are there any other test code ? how that system sensing heat ? what I must check ?
selimmeriçMSc Electric & Electronic Eng.
void main(){return null;}
smeric
Posts: 10
Joined: Sat Mar 14, 2020 11:08 am
Location: Turkey & Sweden

Re: Hacking the HP45

Post by smeric »

I check pins which is reading via GTP command. they are A10 (10x) and A11(CTSR). I check that pins on my circuit and 10x = 2.01v and TSR pin is 0.19v. I open some serial debug code from firmware "printhead.cpp"

line 364 : Serial.print("10X resistor: "); Serial.println(temp_10x_res);
line 371 : Serial.print("RSR resistor: "); Serial.println(temp_tsr_res);

Code: Select all

10X resistor: 1790.28
RSR resistor: 0.36
GTP:-C
OK
10X resistor: 1788.62
RSR resistor: 0.20
GTP:-C
that function is returning at that line.
line 374 : if (temp_10x_res < 150.0 || temp_10x_res > 500.0) return -2;
line 375 : if (temp_tsr_res < 150.0 || temp_tsr_res > 500.0) return -2;

who can explain me real problem.
selimmeriçMSc Electric & Electronic Eng.
void main(){return null;}
User avatar
dragonator
Site Admin
Posts: 595
Joined: Fri Aug 14, 2015 4:48 pm
Location: The Nethelands
Contact:

Re: Hacking the HP45

Post by dragonator »

I will try to run through all the issues in order. For more information on the printhead in general, go here: http://ytec3d.com/hp45-inkjet-printhead/

The values for the 10X and the TSR are what the controller measures on the 10X resistor and the TSR resistor. Both are supposed to be in the neighborhood of 300-400 ohm. A simple voltage divider is used with R11 and R12 and the internal resistor of the HP45. GTP only tries to measure the temperature, and nothing else. It should return something other than -C. -C means that there is something wrong. In your case, 10X is way too high, and TSR is way too low. You can measure the printhead directly on the pads between 10X and ground, and TSR and ground and see if you get the right resistance. However, just to print, the temperature is not necessary. The head can print without the sensors. They are only used to check the connection to the head.

PRM Po is prime printhead 1000x. It should only give and OK. The printhead tries to fire all nozzles 1000x. Your printhead should have fired a dot of ink. You do need to wipe the printhead with a damp paper towel before you can print. You will need to see black ink on the towel to make sure there is ink in the head. If after that you still see nothing, there is something wrong with the connection.

As for your original goal. There is currently no real way to turn the printhead into a marker without some modifications. The PRM command is closest to what you are looking for, but it is firing the nozzles as fast as possible. You could modify it to fire more slowly once you have the printhead running.
User avatar
dragonator
Site Admin
Posts: 595
Joined: Fri Aug 14, 2015 4:48 pm
Location: The Nethelands
Contact:

Re: Hacking the HP45

Post by dragonator »

@Priyashree2

You will need to add a 10k pulldown to every address. Also before you print you should always wipe the head. Even if you do not use them, floating addresses cause issues. I cannot find any issues with the code you are using.
smeric
Posts: 10
Joined: Sat Mar 14, 2020 11:08 am
Location: Turkey & Sweden

Re: Hacking the HP45

Post by smeric »

I read It and check pins
in this code I check that line "HP45_Standalone_V3.00.00.ino"
line 56 : Printhead HP45(29, 33, 24, 16, 28, 15, 26, 14, 27, 20, 8, 18, 7, 17, 25, 19, 3, 2, 23, 22, A11, A10);

Printhead.cpp line 78 : Printhead(uint8_t primclk, uint8_t primclr, uint8_t p0, uint8_t p1, uint8_t p2, uint8_t p3, uint8_t p4, uint8_t p5, uint8_t p6, uint8_t p7, uint8_t p8, uint8_t p9, uint8_t p10, uint8_t p11, uint8_t p12, uint8_t p13, uint8_t addclk, uint8_t addrst, uint8_t hen, uint8_t ncheck, uint8_t stsr, uint8_t s10x)


last 2 value is tsr and 10x value but in my circuit its going another pins I think.

in HP45 both 10x and TSR pins nearly 300-315 ohm
Ads2.png
Ads2.png (323.52 KiB) Viewed 13009 times

is that pinout is wrong ?
I check all code and schematic and

Code: Select all

primclk		29	*
primclr		33	*
p0		24	*
p1		16	*
p2		28	*
p3		15	*
p4		26	*
p5		14	*
p6		27	*
p7		20	*
p8		8	*
p9		18	*
p10		7	*
p11		17	*
p12		25	*
p13		19	*
addclk		3	*
addrst		2	*
hen		23	A11
ncheck		22	22
stsr		A11	23
s10x		A10	A10
dragonator wrote: Sun Apr 12, 2020 2:14 pm I will try to run through all the issues in order. For more information on the printhead in general, go here: http://ytec3d.com/hp45-inkjet-printhead/

The values for the 10X and the TSR are what the controller measures on the 10X resistor and the TSR resistor. Both are supposed to be in the neighborhood of 300-400 ohm. A simple voltage divider is used with R11 and R12 and the internal resistor of the HP45. GTP only tries to measure the temperature, and nothing else. It should return something other than -C. -C means that there is something wrong. In your case, 10X is way too high, and TSR is way too low. You can measure the printhead directly on the pads between 10X and ground, and TSR and ground and see if you get the right resistance. However, just to print, the temperature is not necessary. The head can print without the sensors. They are only used to check the connection to the head.

PRM Po is prime printhead 1000x. It should only give and OK. The printhead tries to fire all nozzles 1000x. Your printhead should have fired a dot of ink. You do need to wipe the printhead with a damp paper towel before you can print. You will need to see black ink on the towel to make sure there is ink in the head. If after that you still see nothing, there is something wrong with the connection.

As for your original goal. There is currently no real way to turn the printhead into a marker without some modifications. The PRM command is closest to what you are looking for, but it is firing the nozzles as fast as possible. You could modify it to fire more slowly once you have the printhead running.
selimmeriçMSc Electric & Electronic Eng.
void main(){return null;}
User avatar
dragonator
Site Admin
Posts: 595
Joined: Fri Aug 14, 2015 4:48 pm
Location: The Nethelands
Contact:

Re: Hacking the HP45

Post by dragonator »

Can you tell me exactly where and roughly when you downloaded the files for that board? I recognize that layout, it is the prototype V3.00 controller that I used to have. The pinout was wrong and the layout was fixed, but I simply resoldered 2 wires. The fact that people still have access to that wrong version worries me a quite a bit. It might explain the headache some people have with this. The current hackaday.io version is correct. All others I keep no track of. When you tell me where you got that I will remove it so no people can download that anymore.

The difference is that TSR and HENA are swapped. A11 can ONLY do analog readings, and I wrongly assumed that it was also an output. What I did was cut these 2 traces and resoldered wires the correct way around. This should fix both issues. Right now, you head is not enabling, and the TSR is reading the enable mosfet. If the head is not enabled, the 10x is also not read, so it explains everything.
Post Reply