Skip to main content
Topic: upgrading a hakko clone (Read 58641 times) previous topic - next topic

Re: upgrading a hakko clone

Reply #45
back to the topic, I found my old project for my hakko driver (I have hakko pencils available here so I made a driver) ... you seen the picture .. as I said I use 16F688 (no idea why I decided to do so) and I read thermocouple from pencil as NTC (or PTC I don't remember really) :D (it actually works!!!) ... here's the code .. it is very simple, written in ccs c (I have some fairly old version I purchased with some DLP module few years ago, works with 16F and smaller pic's and unfortunately cannot be upgraded for free :( ) ..  I never wrote the l2t function (convert ADC value to C):

Code: [Select]



// display the bar while changing the "target temp" in loops
#define BAR_DELAY 100

#define HEATER_ON()  output_high(PIN_A4)
#define HEATER_OFF()  output_low(PIN_A4)

#define BUTTON_UP  PIN_A1
#define BUTTON_DOWN PIN_A2
#define BUTTON_F    PIN_A3


#include <16F688.h>
#device adc=10

#FUSES WDT                      //Watch Dog Timer
#FUSES INTRC_IO                //Internal RC Osc, no CLKOUT
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NOBROWNOUT              //No brownout reset
#FUSES NOMCLR                  //Master Clear pin used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOIESO                  //Internal External Switch Over mode disabled
#FUSES NOFCMEN                  //Fail-safe clock monitor disabled

#use delay(clock=8000000,RESTART_WDT)

unsigned long temperature; //0-1023 ZELJENA TEMPERATURA
unsigned long current;
unsigned int  f, i, j;
unsigned int  DEBOUNCE_TIME;
unsigned int  HYST;


// LCD.RS == PIN_A5

struct lcd_pin_map {
          int    data : 4;
          BOOLEAN enable;
          BOOLEAN rw;
          BOOLEAN nc1;
          BOOLEAN nc2;
} lcd;


#locate lcd = getenv("sfr:PORTC")
#define set_tris_lcd(x) set_tris_c(x)


#define lcd_type 2          // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40    // LCD RAM address for the second line


BYTE const LCD_INIT_STRING[4] = {0x20 | (lcd_type << 2), 0xc, 1, 6};
                            // These bytes need to be sent to the LCD
                            // to start it up.


                            // The following are used for setting
                            // the I/O port direction register.

struct lcd_pin_map const LCD_WRITE = {0,0,0,0,0}; // For write mode all pins are out
struct lcd_pin_map const LCD_READ = {15,0,0,0,0}; // For read mode data pins are in

BYTE lcd_read_byte() {
      BYTE low,high;
      set_tris_lcd(LCD_READ);
      lcd.rw = 1;
      delay_cycles(1);
      lcd.enable = 1;
      delay_cycles(1);
      high = lcd.data;
      lcd.enable = 0;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(1);
      low = lcd.data;
      lcd.enable = 0;
      set_tris_lcd(LCD_WRITE);
      return( (high<<4) | low);
}


void lcd_send_nibble( BYTE n ) {
      lcd.data = n;
      delay_cycles(1);
      lcd.enable = 1;
      delay_us(2);
      lcd.enable = 0;
}


void lcd_send_byte( BYTE address, BYTE n ) {

      output_low(PIN_A5); // lcd.rs = 0;
      while ( bit_test(lcd_read_byte(),7) ) ;
      output_bit(PIN_A5, address); //lcd.rs = address;
      delay_cycles(1);
      lcd.rw = 0;
      delay_cycles(1);
      lcd.enable = 0;
      lcd_send_nibble(n >> 4);
      lcd_send_nibble(n & 0xf);
}


void lcd_init() {
    BYTE i;
    set_tris_lcd(LCD_WRITE);
    output_low(PIN_A5); // lcd.rs = 0;
    lcd.rw = 0;
    lcd.enable = 0;
    delay_ms(15);
    for(i=1;i<=3;++i) {
      lcd_send_nibble(3);
      delay_ms(5);
    }
    lcd_send_nibble(2);
    for(i=0;i<=3;++i)
      lcd_send_byte(0,LCD_INIT_STRING[i]);
}


void lcd_gotoxy( BYTE x, BYTE y) {
  BYTE address;

  if(y!=1)
    address=lcd_line_two;
  else
    address=0;
  address+=x-1;
  lcd_send_byte(0,0x80|address);
}

void lcd_putc( char c) {
  switch (c) {
    case 'f'  : lcd_send_byte(0,1);
                  delay_ms(2);
                                          break;
    case 'n'  : lcd_gotoxy(1,2);        break;
    case 'b'  : lcd_send_byte(0,0x10);  break;
    default    : lcd_send_byte(1,c);    break;
  }
}

//1022 - room temp
//
unsigned long l2t (unsigned long a){ // get the temp in C from 0-1023
  return (a*10+433)/3; //return C*10
}

void store(unsigned long x){
  // SAVE TO EEPROM
  write_eeprom(0, (unsigned int8) (x >> 8) & 0xff);
  write_eeprom(1, (unsigned int8) x & 0xff);
}


unsigned long fetch(){
  // FETCH FROM EEPROM
  unsigned long x;
  x = read_eeprom(0);
  x = x << 8;
  x = x + read_eeprom(1);
  return x;
}


void menu(){
  unsigned long temp;
  temp = temperature;
  temperature = fetch();

  //turn off the heater
  HEATER_OFF();


  // DEFAULT TEMPERATURE
  printf(lcd_putc, "f-    menu    +n      ENTER    ");
  while (!input(BUTTON_F)) restart_wdt(); // wait for Function key to continue
  delay_ms(DEBOUNCE_TIME);
  while (input(BUTTON_F)) restart_wdt(); // wait for release
  printf(lcd_putc, "f-    %4Lu      +n Power On  TEMP ", l2t(temperature)/10);
  while (!input(BUTTON_F)){
    if ( input(BUTTON_UP) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_UP) ){
          if (temperature < 1023) ++temperature;
        }
    }//BUTTON UP
    if ( input(BUTTON_DOWN) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_DOWN) ){
          if (temperature > 0) --temperature;
        }
    }//BUTTON DOWN
    lcd_gotoxy(6,1);
    printf(lcd_putc, "%4Lu", l2t(temperature)/10);
  }
  while (input(BUTTON_F)) restart_wdt(); // wait for release
  //STORE VALUE
  store(temperature);
  temperature = temp;

  // DEFAULT DEBOUNCE TIME
  printf(lcd_putc, "f-    %4u      +n DEBOUNCE  (ms) ", DEBOUNCE_TIME);
  while (!input(BUTTON_F)){
    if ( input(BUTTON_UP) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_UP) ){
          if (DEBOUNCE_TIME < 250) ++DEBOUNCE_TIME;
        }
    }//BUTTON UP
    if ( input(BUTTON_DOWN) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_DOWN) ){
          if (DEBOUNCE_TIME > 5) --DEBOUNCE_TIME;
        }
    }//BUTTON DOWN
    lcd_gotoxy(6,1);
    printf(lcd_putc, "%4u", DEBOUNCE_TIME);
  }
  while (input(BUTTON_F)) restart_wdt(); // wait for release
  //STORE VALUE
  write_eeprom(2, DEBOUNCE_TIME);


  // DEFAULT HYSTERESIS
  printf(lcd_putc, "f-    %4u      +n  HYSTERESIS  ", HYST);
  while (!input(BUTTON_F)){
    if ( input(BUTTON_UP) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_UP) ){
          if (HYST < 250) ++HYST;
        }
    }//BUTTON UP
    if ( input(BUTTON_DOWN) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_DOWN) ){
          if (HYST > 2) --HYST;
        }
    }//BUTTON DOWN
    lcd_gotoxy(6,1);
    printf(lcd_putc, "%4u", HYST);
  }
  while (input(BUTTON_F)) restart_wdt(); // wait for release
  //STORE VALUE
  write_eeprom(3, HYST);
}




void main()
{
  setup_adc_ports(sAN0|VSS_VDD);
  setup_adc(ADC_CLOCK_INTERNAL);
  setup_timer_0(RTCC_INTERNAL);
  setup_wdt(WDT_DIV_65536);
  setup_timer_1(T1_DISABLED);
  setup_comparator(NC_NC);
  setup_vref(FALSE);

  setup_oscillator(OSC_8MHZ);

  current = 0;
  f = 0;
  set_adc_channel(0);
  lcd_init();

  printf(lcd_putc, " CRSN DOO Lemilon      V2.1");

  temperature = fetch();
  DEBOUNCE_TIME = read_eeprom(2);
  if (DEBOUNCE_TIME < 5) DEBOUNCE_TIME = 5;
  if (DEBOUNCE_TIME > 250) DEBOUNCE_TIME = 50;
  HYST = read_eeprom(3);
  if (HYST < 2) HYST = 2;
  if (HYST > 250) HYST = 3;
  delay_ms(1000);

  lcd_putc('f'); //clear display

loop:
    read_adc(ADC_START_ONLY); // start the conversion

    if ( input(BUTTON_UP) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_UP) ){
          if (temperature < 1023) ++temperature;
          f = BAR_DELAY;
        }
    }//BUTTON UP

    if ( input(BUTTON_DOWN) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_DOWN) ){
          if (temperature > 0) --temperature;
          f = BAR_DELAY;
        }
    }//BUTTON DOWN

    if ( input(BUTTON_F) ){ // button pressed
        delay_ms(DEBOUNCE_TIME); //debounce
        if ( input(BUTTON_F) ){
        while (input(BUTTON_F)) restart_wdt(); // wait for release
          while(input(BUTTON_F)); //wait for release
          menu();
        }
    }//BUTTON Function





    current = (current + read_adc(ADC_READ_ONLY)) >> 1; //read the data

    if (f == 0){
      lcd_gotoxy(1,1);
      printf(lcd_putc, "Current: %4Lu.%1i  ", l2t(current)/10, (int8) l2t(current)%10);
      lcd_gotoxy(1,2);
      printf(lcd_putc, "Target : %4Lu  ", l2t(temperature)/10);
    } else {
      lcd_gotoxy(1,1);
      j = temperature >> 6;
      for (i = 0; i < j; ++i){
          lcd_putc('#');
      }
      for (i = j; i < 15; ++i){
          lcd_putc('.');
      }
      lcd_gotoxy(1,2);
      printf(lcd_putc, "Target : %4Lu.%1i  ", l2t(temperature)/10, (int8) l2t(temperature)%10);

    }

    if (current < temperature - HYST){
      HEATER_ON();
    }else if (current > temperature){
      HEATER_OFF();
    }
    if (f > 0) --f;
  goto loop;
}

Re: upgrading a hakko clone

Reply #46
I split the stuff about the simulation software to here:
viewtopic.php?f=56&t=1956&p=19099#p19053
Got a question? Please ask in the forum for the fastest answers.

Re: upgrading a hakko clone

Reply #47
i have cleaned up the schematic and added an LCD, i don't think an 16x2 is necessary. there is also a rotary encoder the dial definately has better feel than a few buttons.
[attachment=0]

Re: upgrading a hakko clone

Reply #48
8x1, 16x1, 8x2 ... all are enough ... I just have bunch of 16x2 that I use .. both small and big ones ... recently I purchased 10 COG 16x2 modules :D



it is 16x2, beautiful :) use almost no power at all, they are small, great contrast ...

It does have downside
- no backlight (one could add some leds behind it ..)
- 5V only (so if you are using 2V or 3V design it gets ugly) and this is big - taking into account that you would probably select them for low power apps ..
- driver - it is "kinda" compatible with hd44780. mine code I use with all mine 16x2 works fine with all of them but I can't get this one to work properly - I only see left side of it (left 2x8) .. it works properly when I use mikroC compiler but since I use demo version it is limiting my code size so I prefer to use csc c for 16F or c18 for 18F that are not limited (one I purchased and other is free).... anyhow I will disassemble mikroC driver and find out what I am doing wrong :D

Re: upgrading a hakko clone

Reply #49
now with regards to that schematic, again few suggestions
1. move encoder+button to B port. One pin of the encoder link to B0 and other to B1. This way you can read encoder very simple. Just turn on the INT_EXT interrupt (interrupt on B0)

Code: [Select]
#define MAXTEMP 1020
#define MINTEMP 20
#define TEMPSTEP 1

volatile int8 encoder;

#int_ext
void detect_rb0_change() {
  encoder = 1;
  if (input(PIN_B0) == input(PIN_B1) ) {  //direction
      if(target < MAXTEMP-TEMPSTEP) target += TEMPSTEP;
  } else {
      if(target > MINTEMP-TEMPSTEP) target -= TEMPSTEP;
  }
}

2. you need 10-100n from MCLR to Vss

Re: upgrading a hakko clone

Reply #50
Quote
2. you need 10-100n from MCLR to Vss

Do you often do this? We never use caps on MCLR, just a 10K and 1N4148 to keep VPP out of the power supply.
Got a question? Please ask in the forum for the fastest answers.

Re: upgrading a hakko clone

Reply #51
using interrupt on the encoder makes sense,
this will free up more of port a
[attachment=0]

Re: upgrading a hakko clone

Reply #52
[quote author="ian"]
Quote
2. you need 10-100n from MCLR to Vss

Do you often do this? We never use caps on MCLR, just a 10K and 1N4148 to keep VPP out of the power supply.[/quote]

since ~2-3 years - on EVERY project.

Before ~3 years ago I never did it, then I had some "weird" behaviour with one project (18F2550 but I was not using USB on it) that I was unable to debug ... mcu resetted from time to time, sometimes SPI was "missing" bytes .. and 1wire bus was working only 10% of the time and I checked the source few times and it was all perfect .. really weird stuff .. it was working "good enough" so after few weeks debugging I just left it "as is" ... couple of months after that I had issues with another project (16F877A this time) .. similar problems - random restarts, some peripherals were not working ok .. but this time it was driving a flyer (zeppelin) so it was really important for me to debug it. I asked a friend (old guy, he was doing electronics when I was not even born) to look at the schematic and to look at pcb as I might made some errors there (maybe some noise ... even it all works on very low frequencies) and first thing he told me was "put 10-100n from mclr to gnd" and let me know if it helps. I put the cap and it solved all problems on this 16F877A project .. it was crazy .. then (actually tomorrow) I remembered the "project from few months ago" and soldered 100nF directly onto mcu (mclr-gnd) and darn .. it solved all problems.

Why it solved the problem - I have no idea
Do I now put that cap on every single board - oh yes, on every single one

Re: upgrading a hakko clone

Reply #53
one more thing I do that is not "normal/usual" but it proved that it helps :D .... near the mcu I don't use 100n decoupling cap but I use 10-50pF + 10-33nF + 100nF + 1uF (tantalum). Yes, it is 4 capacitors instead of 1 but it's something I follow like a mantra :) ... if there is problem with pcb realestate then I skip the pF one and uF one, but 10n+100n is always there, but I keep 1uF tantalum on the Vdd/Vss somewhere on the board.

Re: upgrading a hakko clone

Reply #54
i have found that for most applications a single 0.1u ceramic is sufficient, usually add a 4.7uF tantalum near vreg.

Re: upgrading a hakko clone

Reply #55
"for MOST applications" being a key word :D .. since I figured out that I don't know "for what apps I need more" I decided to "overdo it" every time and just don't worry about it :D

btw as for the "near vreg" I was told a "secret formula" that I also follow like a mantra and that served me well :D . 1000uF per 1A that your circuit draws. So if your circuit will draw 100mA then 100uF, 4.7uF is right for the 5mA circuit by that formula .. again, this formula is "overdoing it" but the thing is - you will never be wrong with it .. and for hobby you don't really care if the board will be 15 or 15.5EUR .. you need to calculate "mininal settings" only if you make 1000+ and then that 0.5EUR makes a difference

EDIT: forgot to say, this 1000uF per 1A is only if you use voltage regulator or you don't know your voltage source (for e.g. usb powered devices - usb is "unknown" voltage source as it is known to produce very dirty 5V) .. if you use batteries or you are using "good voltage source" then you can go below those 1000uF/1A

Re: upgrading a hakko clone

Reply #56
on larger designs i try to use a few different size caps so i have flexibility, and don't have to redesign the board just to change a capacitor. i have found it is more important to have proper capacitance on the input of linear regulators.

for this application a few 0.1uF and a 4.7 on the output of the regulator will be fine, i don't expect the micro and amp to draw more than 10mA.

Re: upgrading a hakko clone

Reply #57
Great tips, thank you.

Quote
but 10n+100n is always there

I read an article about the history of 100nF and why we use it. I think is a Xilinx app note, and the up shot was that modern stuff if much happier with 10nF, 100nF is a hold over from analog designs or very early digital design. I forget the details, but the graphs were nice and convincing :)
Got a question? Please ask in the forum for the fastest answers.

Re: upgrading a hakko clone

Reply #58
yes, the "short circuit" digital circuits now make last for very very very short time so 10n fits better as it has enough capacitance and much lower esr .. .that is the way i see it .. 100n added to the 10n helps with higher frequencies as it allows 10n to "top up" faster

Re: upgrading a hakko clone

Reply #59
I'm awaiting delivery of a scope(from china) and will do a more through probe into the existing analog control circuit.
after some digging the iron i have is actually made by Atten, however i still believe there is enough in common with the Hakko it should work with their irons.