Thursday, January 19, 2012

Toy traffic light using a signal tower

Just finished building a toy traffic light for the kids. It uses a signal tower (used on factory floors to provide visual alarms and indication of machine status) which employs 12VDC incandscent lamps. I haven't checked but the bulbs look like the same size and actually have same socket type as automobile tailight lamps.

There's nothing particularly unique or special about this circuit, although I haven't come across any toy traffic light design that uses signal towers. What I do like about this circuit is the fact that a single user interface--a momentary contact pushbutton--controls all the functions, and that I didn't have to include any indicator LED or buzzer and instead could use the lamps of the traffic light itself to provide feedback to the user.



Operation

There are three modes:
1. Flashing amber (0.8sec on, 0.8sec off)
2. Flashing red (0.8sec on, 0.8sec off)
3. Normal traffic light operation: green --> amber --> red (variable red/green on-time, amber on-time = 2sec)

Upon power up the traffic light starts in mode 1. Modes are selected by pressing the button momentarily.

The stop (red) and go (green) time is user selectable. This is accomplished by pressing and holding the button down (regardless of what mode the traffic light is in). 1.5 seconds after pressing the button all lights will be turned off indicating the green light is about to begin showing the amount of go/stop time. Three seconds after pressing the button the green light will go through sets of blinking. The number of flashes per set indicates the go/stop time:

Number of flashes per set Go/Stop time in seconds
1 5
2 10
3 15
4 20

As with the modes keeping the button depressed will eternally cycle through the four sets. To choose a go/stop time the user releases the button after the particular set of flashes has occured. So letting go of the button after the set of three flashes of the green light will set the go time and stop time to 15 seconds. The selected go/stop time is stored in EEPROM so the circuit doesn't forget even when powered down. Once the button is released the traffic light goes into mode 3 and begins with the yield (amber) light on. 

Hardware


I originally planned to use the PIC12615 which is more than adequate. Unfortunately I need EEPROM which the 615 lacks. The only 8-pin PIC with EEPROM that I have right now is the 12F1822 and so that's what I ended up using for the MCU.

The circuit has a polarity reversal protection in the form of a 1N5822 Scottky diode (D1 in the schematic) which has a rated capacity of 3A. Although the wall wart has a no-load measured output of 16VDC, this drops to around 12V when any of the lamps is on. Each of the power transistors also has a voltage drop across their collector-emitter. So to minimize further dip in voltage across the the incandescents I opted to use a Schottky instead of an ordinary rectifier. I've used the TIP102 NPN Darlington since as I reported in the Darlington transistor test, the 102 has the least collector-emitter voltage in the three types I was able to get hold of and play around with. As stated in that test using this very same signal tower, the power dissipation in the Darlingtons is such that heatsinks can be dispensed with.

Here's the finished board with all the components soldered. You'll notice there are several drill holes around the MCU. I've added pads to the unused MCU pins as well to the +5V rail and to the pushbutton tracks. These are "just in case" pads if ever I need to modify the board. The additional pushbutton pads are 0.1" apart and will accommodate a 2-way (2-pin) connector. I was going to solder the connector in case things don't work out and the board-mounted pushbutton doesn't work the way I planned. That rod sticking out of the blue pushbutton is a one and quarter inch piece of bamboo cut from a disposable chopstick. It extends out of case (through a small drilled hole) and will act as the button the user will pushing. It's the rod-poking-out-of-the-case part which I wasn't sure would work--and thus the backup connector for a case-mounted pushbutton. I applied a coat of nail polish to the chopstick just to seal the pores and prevent it from being attacked by molds (I've noticed that some brand new but long stored chopsticks have molds on them and I've seen molds appear on a bamboo chopping board after it had been left damp for some 24 hours).

I made the 12VDC traces to and from the incandescent lamps including ground really wide--150 mils--to minimize voltage drop. The traces narrow to just 50mils near the TO-220 pads to prevent shorts. Yes, the text at the bottom of the board is a dedication to the users of this circuit--my young nephews and niece. Naturally I chose Comic Sans as the font. You might notice scratches on the green photosensitive coating (which I always intentionally leave on the tracks). There was a lot of flux residue after soldering so I washed the board with detergent and scrubbed it using a toothbrush. So the blame for those unsightly scratches rests squarely on the shoulders of that brush!

Although the case has provisions--standoffs with holes in them--for screw mounting of boards, I couldn't find small enough screws that would fit. So I just dabbed copious amounts of hot melt glue on the standoffs and pressed the board onto them. Part of the glue oozed through the drilled holes of the board and formed nice hemispherical beads. The hefty black wall wart is at the bottom right. Its wire is too short so I added a meter more so the kids have leeway in placing the traffic light in their play area.

One of my concerns is that the children will knock this thing over and break it. So I cut out a sponge in the shape of circle with a diameter one and a half times larger than the signal tower. I can just glue it on top of the tower. It'll definitely break any falls and save the polystyrene or acrylic lenses from cracking and breaking. But the sponge solution is ugly to state it mildly. So I might instead superglue something akin to an O-ring around the sides of top cap of the tower. Not as elastic and shock absorbing as the sponge but it's still better than nothing at all. Another is option would be a quarter inch PVC or rubber tubing.

Firmware

I simply adapted the firmware I used for the 4-way traffic light I built the kids last year. This signal tower version is actually a lot simplier--no charlieplexing necessary. I opted to just clock the MCU using its default power-on frequency of 500kHz. Only one timer is used. I can no longer remember why I chose timer2 instead of timer0. For expediency's sake I didn't bother changing what ain't broken. A state machine is used with a timer tick of 4ms. In the configuration word, watchdog timer, power up timer, brownout reset, stack over/underflow reset are all enabled. All other options are disabled. Internal oscillator is used with I/O function on all pins.

/*

Kids' Traffic Light Using a Signal Tower

Created:        January 10 2012
Processor:      PIC 12F1822
Compiler        mikroC Pro 5.0.0


* Uses a 12VDC wall wart as power supply

* Tower light 12VDC red, amber, green incandescent lamps are switched by NPN Darlington transistors

* pushbutton:
     * when momentarily pressed: cycles through different possible modes:
          1. normal traffic light: green -> amber -> red
          2. flashing amber
          3. flashing red
     * when pressed and kept depressed for over a couple of seconds: cycles through different green/red light on time:
          1. 5sec
          2. 10sec
          3. 15sec
          4. 20sec.

* green/red light on time is stored in EEPROM


--------------------------+--------------------------------------
No. of green flashes/set  |   Green/red light on time in seconds
--------------------------+--------------------------------------
         1                |            5
         2                |           10
         3                |           15
         4                |           20
--------------------------+--------------------------------------

*/



// ************************************************************************************************
//       input / output
// ************************************************************************************************

#define  lred      LATA.f0                       // NPN darlington switches 12VDC incandescent lamp
#define  lamber    LATA.f1                       // NPN darlington switches 12VDC incandescent lamp
#define  lgreen    LATA.f2                       // NPN darlington switches 12VDC incandescent lamp

#define  tris_red  TRISA.f0
#define  tris_amber TRISA.f1
#define  tris_green TRISA.f2

#define  pb        PORTA.f3                      // momentary contact push button
#define  tris_pb   TRISA.f3

#define  wpullup   0b111000                      // for WPUA -- enable pull ups on pb and unused pins


// ************************************************************************************************
//       for traffic light
// ************************************************************************************************

#define  ambertime           500       // in normal mode -- amount of time for amber light to be on after green and before red -- time in terms of timer2 ticks
#define  flashambertime      200       // in flashing amber mode -- amount of time for amber light to be on and amount of time to be off -- time in terms of timer2 ticks
#define  flashredtime        200       // in flashing red mode -- amount of time for red light to be on and amount of time to be off -- time in terms of timer2 ticks
#define  flashgreentime      50        // during selection of green/red light on time -- amount of time for green light to be on and amount of time to be off when it is flashing -- time in terms of timer2 ticks

#define  changergtime        750       // minimum amount of time for button to be kept pressed before cycling through the green light on time -- time in terms of timer2 ticks
                                       // given 4ms timer2 tick, changergtime of 250 = 1sec real time

#define  prechangergtime     changergtime - 375  // amount of time after button is held down when all lights are turned off in preparation for possible change of green/red light on time

#define  rgtime_increm       1250      // amount of time for green/red light to be on, and multiples thereof upon continual button press -- value in terms of timer2 ticks.
#define  maxgtime            4         // maximum allowed multiple of rgtime_increm

int16 REDGREENTIME;                    // amount of time for green/red light to be on -- time in terms of timer2 ticks
int8  RGTIME;                          // multiples of rgtime_increm such that RGTIME*rgtime_increm = REDGREENTIME


// ************************************************************************************************
//       eeprom
// ************************************************************************************************

#define  addr_rgtime      0x10         // eeprom address for user selected green/red light on time

// ************************************************************************************************
//       for pushbutton
// ************************************************************************************************

#define  rising              1         // rising edge detected. used by PBedge
#define  released            1         // rising edge detected. used by PBedge
#define  falling             2         // falling edge detected. used by PBedge
#define  pressed             2         // falling edge detected. used by PBedge
#define  none                0         // no edge. used by PBedge

int8 PBval;                            // last eight values of the switch upon reading it
int8 PBedge;                           // edge detected?, 0 = no edge detect, 1 = rising edge, 2 = falling edge; other values = Not Used / Undefined for now
bit PBlevel;                           // voltage level of switch when not bouncing (hi = 1, lo = 0)

// ************************************************************************************************
//       general defines and variables
// ************************************************************************************************


#define  int1                bit
#define  int8                unsigned char
#define  int16               unsigned int
#define  int32               unsigned long

#define  on                  1
#define  off                 0

#define  _on                 0
#define  _off                1

#define  yes                 1
#define  no                  0

#define  input               1         // for TRISx
#define  output              0         // for TRISx

#define  analog              1         // for ANSELx
#define  digital             0         // for ANSELx

#define  hi                  1         // switch level high
#define  lo                  0         // switch level low

int16 TIME = 0;                        // records how long a light has been on  -- in terms of timer2 ticks

// ************************************************************************************************
//       for state machines
// ************************************************************************************************

enum {_normal, _flashingamber, _flashingred, _flashgreen, _standby} STATEMODE = _flashingamber;
enum {_go, _yield, _stop} STATENORMAL = _stop;
enum {_init, _flash} STATEFLASHGREEN = _init;

// ===========================================================================================
//       functions
// ===========================================================================================


void ComputeRedGreenTime()
{
  REDGREENTIME = RGTIME*rgtime_increm;
}

void IniReg()
{
  TRISA = input;
  ANSELA = digital;
  
  tris_red = output;
  tris_amber = output;
  tris_green = output;

  // enable weak pull up for pushbutton and unused pins
  OPTION_REG.NOT_WPUEN = 0;
  WPUA = wpullup;
  
  // default clock frequency is 500kHz upon power up.
  // Timer2 is used for state machine and switch debouncing timing tick
  // with clock = 500kHz, PR2 = 125, prescale = 1:4, postscale = 1:1
  // TMR2 will count from zero to PR2 and timer2 interrupt occurs every 125*4 / (500kHz / 4) = 4ms = timer2 tick
  T2CON = 0b101;             // postscaler = 1:1, prescaler = 1:4, timer2 on
  TMR2 = 0;
  PR2 = 125;

  WDTCON = 0b1000;           // prescale = 1:512 (16ms typical)
                             // WDTE in configuration word is configured so that WDT enabled when MCU awake and disabled when MCU asleep

  // retrieve stored green/red light on time value.
  // If eeprom-stored value is out of valid range then set it to minimum and store this value in eeprom
  // stored values are in terms of multiples of rgtime_increm such that stored value multiplied by rgtime_increm = time in terms of TMR2 ticks
  RGTIME = EEPROM_Read(addr_rgtime);
  if (RGTIME == 0 || RGTIME > maxgtime)
  {
    RGTIME = 1;
    EEPROM_Write(addr_rgtime, RGTIME);
  }
  ComputeRedGreenTime();                     //REDGREENTIME = RGTIME*rgtime_increm;

  // initialize push button
  PBval = 0xFF;
  PBlevel = hi;
} // void InitRegisters()


// normal traffic light operation: green --> amber --> red
// red/green light on time is user selectable
void Normal()
{
  switch (STATENORMAL)
  {
    case _go:
      if (++TIME < REDGREENTIME)
        lgreen = on;
      else
      {
        STATENORMAL = _yield;
        TIME = 0;
        lgreen = off;
      }
      break;

    case _yield:
      if (++TIME < ambertime)
        lamber = on;
      else
      {
        STATENORMAL = _stop;
        TIME = 0;
        lamber = off;
      }
      break;

    case _stop:
      if (++TIME < REDGREENTIME)
        lred = on;
      else
      {
        STATENORMAL = _go;
        TIME = 0;
        lred = off;
      }
      break;

    default:
      TIME = 0;
      STATENORMAL = _yield;
  } // switch (STATENORMAL)
} // void StateMachNormal()


// amber flashes on and off
void FlashingAmber()
{
  static bit flag;

  if (++TIME < flashambertime)
  {
    if (flag)
      lamber = on;
    else
      lamber = off;
  }
  else
  {
    if (flag)
      flag = 0;
    else
      flag = 1;
    TIME = 0;
  }
} // void FlashingAmber()


// red flashes on and off
void FlashingRed()
{
  static bit flag;

  if (++TIME < flashredtime)
  {
    if (flag)
      lred = on;
    else
      lred = off;
  }
  else
  {
    if (flag)
      flag = 0;
    else
      flag = 1;
    TIME = 0;
  }
} // void FlashingRed()


// when user selects red/green light on time the green light is flashed 1,2,3,or 4 times 
// to indicate 5, 10, 15, 20sec of on time
void FlashGreen()
{
  static int8 i, CYCLES;
  static bit flag;
  
  switch (STATEFLASHGREEN)
  {
    case _init:
      i = 0;
      flag = 1;
      TIME = 0;
      CYCLES = RGTIME*2-1;
      STATEFLASHGREEN = _flash;
      break;

    case _flash:
      if (++TIME < flashgreentime)
      {
        if (flag)
          lgreen = on;
        else
          lgreen = off;
      }
      else
      {
        if (flag)
          flag = 0;
        else
          flag = 1;
        TIME = 0;
        if (++i >= CYCLES)
        {
          lgreen = off;
          STATEMODE = _standby;
        }
      }
      break;
  } // switch (STATEFLASHGREEN)
} // void FlashGreen()


void StateMachMain()
{
  switch (STATEMODE)
  {
    case _normal:
      Normal();
      break;

    case _flashingamber:
      FlashingAmber();
      break;

    case _flashingred:
      FlashingRed();
      break;

    case _flashgreen:        // green light is flashed to indicate to user the length of time green/red light are on during normal mode
      FlashGreen();
      break;

    case _standby:           // do nothing mode where all lights are off. used when changing green on time
      break;

    default:
      STATEMODE = _normal;
  }
} // void StateMachMain()


void AllLightsOff()
{
  lred = off;
  lamber = off;
  lgreen = off;
}

void DebounceSwitch()
{
  // shift all bits to the left
  // if switch reading is hi then let pb_val bit 0 = 1
  PBval <<= 1;
  if (pb)
    ++PBval;

  PBedge = none;

  // if level is lo and all bits of pb_val are now hi then
  // a rising edge has been detected
  // switch is considered just released when rising edge is detected
  // switch level is now hi
 if ((!PBlevel) && (PBval == 0xFF))
  {
    PBlevel = hi;
    PBedge = rising;
  }

  // if level is hi and all bits of pb_val are now low then
  // a falling edge has been detected
  // switch is considered just pressed when falling edge is detected
  // switch level is now lo
  if ((PBlevel) && (!PBval))
  {
    PBlevel = lo;
    PBedge = falling;
  }
} // void DebounceSwitch()


void ProcessKey()
{
  int8 MODE;                           // temporary storage of current STATEMODE
  
  static  int16  PBPRESSTIMETOTAL = 0; // Keeps track of how long PB is depreesed in terms of timer2 ticks
                                       // Keeps track of total time from falling edge (switched pressed) to rising edge (switch released).
                                       // if less than changergtime then we know the keypress is momentary and is meant to cycle through the various traffic light modes

  static  int16  PBPRESSTIME = 0;      // Keeps track of how long PB is depreesed in terms of timer2 ticks
                                       // this variable is reset every time it exceeds changergtime
                                       // every time it exceeds changergtime green on time is incremented

  DebounceSwitch();
  MODE = STATEMODE;
  
  if (PBlevel == lo)
  {
    if (++PBPRESSTIMETOTAL == prechangergtime)
    {
      AllLightsOff();
      STATEMODE = _standby;
    }
    
    if (++PBPRESSTIME >= changergtime)
    {
      PBPRESSTIME = 0;
      if (++RGTIME > maxgtime)
        RGTIME = 1;
      EEPROM_Write(addr_rgtime, RGTIME);
      ComputeRedGreenTime();                 //REDGREENTIME = RGTIME*rgtime_increm;
      STATEMODE = _flashgreen;
      STATEFLASHGREEN = _init;
    } // if (++PBPRESSTIME >= changergtime)
  } // if (PBlevel == lo)

  if (PBedge == released)
  {
    if (PBPRESSTIMETOTAL < changergtime)
    {
      switch (MODE)
      {
        case _flashingred:
          STATEMODE = _normal;
          STATENORMAL = _yield;
          break;
          
        case _normal:
          STATEMODE = _flashingamber;
          break;
           
        case _flashingamber:
          STATEMODE = _flashingred;
          break;
          
        default:
          STATEMODE = _normal;
      } // switch (MODE)
    } // if (PBPRESSTIMETOTAL < changergtime)
    else  // green/red light on time has been changed so go to normal traffic light mode and begin with amber light
    {
      STATEMODE = _normal;
      STATENORMAL = _yield;
    }
    
    AllLightsOff();
    TIME = 0;                // reset timer so that whatever mode has been selected, light will go through full time allotted
    PBPRESSTIMETOTAL = 0;
    PBPRESSTIME = 0;
  } // if (PBedge == released)
} // void ProcessKey()


void main()
{
  IniReg();

  while(1)
  {
    if (PIR1.TMR2IF)
    {
      PIR1.TMR2IF = 0;
      asm{clrwdt}
      ProcessKey();
      StateMachMain();
    } // if (PIR1.TMR2IF)
  } // while(1)
} // void main()



----

10am Addendum:

Rummaged through the junk bins and found this silicone gasket. It's probably from some old thermos bottle. Still very elastic, has an internal diameter several millimeters smaller than the signal tower's and even matches the cream color of the signal tower and circuit board's plastic case. Great find.

I wiped down the sides of the cap with alcohol, let it dry, coated it with a thin layer of cyanoacrylate adhesive, and then slipped the gasket on. The only problem is I didn't expect the superglue to set within 10 seconds (usually takes about half a minute) so part of what is now the rubber bumper isn't properly aligned with the cap. Oh well.

I knocked the tower over a couple of times. From the sound of the thud it still doesn't match the exceptional shock absorbing properties of the sponge but this will have to do. It certainly beats having no bumpers at all.

Saturday, January 14, 2012

NPN Darlington test

Am currently modding a signal tower I bought the nephews months ago and converting it into a multi-featured traffic light for them to play with. The tower has 12VDC red, amber and green incandescent lamps. Back when I bought it I just wired individual rocker switches for each of the lamps and powered it via a 12VDC wall cube. It was a fully manual system where any combination of lights could be turned on.

I've removed all the switches and will be adding a brain so it can function automatically. Initial measurements showed the incandescents draw about half an ampere each. To switch them I'd need either relays or power transistors. I've opted to use NPN Darlingtons instead of relays even if Darlingtons will have a substantial voltage drop across the collector-emitter. A more major concern, however, is the power dissipation because of a Darlington's high voltage drop. Dissipation translates to heat which means high temperatures which, if high enough, would require the use of heatsinks--something I would rather not have to resort to. So in order to find out whether I'd be better off using miniature PCB mounted relays, I bought a few Darlingtons and tested their VCE and the temperature of their cases.

The corner store from which I get my parts doesn't have a good range of Darlingtons and so the parts I ended up testing were the TIP102, TIP112, and TIP120. I breadboarded the following circuit and powered it off my bench supply.

Resistor R5 represents the incandescent lamp. The following tables show the measurements I obtained for each of the bulbs and transistors. VCE is the voltage across the collector and emitter. IC is the current going the lamp. Case temperature was measured using a Fluke 62 infrared thermometer around two inches away from the Darlington. I recorded the maximum reading. VCE drifted as the transistor temperature went up so I gave the circuit a settling time of between two to three minutes before taking the measurements. I previously took some measurements of the inrush current (without using the Darlingtons) using a Fluke 87V's Peak-Min-Max function and the highest value I obtained was 5.2A. 

TIP120 NPN DARLINGTON
Red Amber Green
VCE (volts) 0.735 0.744 0.745
IC (amperes) 0.363 0.467 0.469
Case Temp. (Celsius) 41 43 43

TIP112 NPN DARLINGTON
Red Amber Green
VCE (volts) 0.714 0.728 0.730
IC (amperes) 0.360 0.467 0.469
Case Temp. (Celsius) 40 43 43

TIP102 NPN DARLINGTON
Red Amber Green
VCE (volts) 0.691 0.700 0.697
IC (amperes) 0.362 0.468 0.470
Case Temp. (Celsius) 40 41 42


The TIP102 clearly stands out as having the least VCE and consequently the lowest power dissipation. The temperature as measured by the IR thermometer is of course hardly accurate (I could've used the 87V's thermocouple but I wasn't in the mood to go through the hassle). Since we have all the values necessary let's compute for the (near actual) case temperature. The TO-220 package has a junction to ambient thermal resistance of 62.5°C/W. Current draw of the green bulb is 0.47A. VCE = 0.697V. Power dissipation is therefore 0.697 x 0.47 = 0.328W. Temperature rise of the case is therefore 62.5 x 0.328 = 20.5°C. Ambient temperature was measured to be 30°C. So case temp. ought to be approximately 30 + 20.5 = 50.5°C.

The TIP102 is the most expensive amongst the three Darlingtons, but by less than 10% over the cheapest. Given how I'm averse to designing in heatsinks for this toy I'll use the TIP102, despite the fact that its temperature will be a mere 1.4° less than if I use the TIP120.

Saturday, December 31, 2011

MCP79400 RTCC breakout board

Last design for the year! 32.768kHz crystal and capacitors will be onboard as well as the Schottky diode and current limiting resistor for the back-up coin battery (which will be off-board). PCB measures 0.8 x 1.0 inch. All components except for the 0.1" male headers are on the copper side (am using a single-sided presensitized board) because the MCP79400 real time clock calendar chip is available only in surface mount packages. I don't have any chip resistors and capacitors so the discretes are all through-holes. The two headers are spaced 0.7-inch apart so they'll still plug nicely into a breadboard.

I could have this board fabricated tomorrow. Thing is, I have yet to purchase my very first MCP79400! Might do so in mid-January.

Ignore that yellow airwire at pin 6. I think it's a bug in DesignSpark PCB 3.0. Even after routing, some airwires remain. Even after executing a design rule check. And even after closing DesignSpark and opening it again. Go figure.

You'll probably notice the SMD pads are much longer than recommended by chip manufacturers. When the chip is mounted on the board there should be around 2mm of exposed pad. The rationale is that the excess pad area permits the soldering iron tip to simultaneously make contact with the pad and the leads. Without the excess we'd have to position the iron tip on top of the pins to solder them. This translates to higher thermal resistance and longer heating time--not good for the chip.



-----

January 1, 2012 Addendum

Made a couple of revisions. Added a 1uF filter cap just to make sure there's sufficient power on board. Also added a 10K pull resistor to the MFP pin as specified in the MCP79400 datasheet. The I2C's SDA and SCL lines need pull-ups but since their value depends on the I2C frequency I've left them out.


Friday, December 30, 2011

Voltmeter woes

Just got duped. The digital panel-mounting voltmeter I bought which supposedly has a range of 0 to 20VDC stops measuring--with fairly good accuracy--at a little over 15V. Feed any voltage higher than that and meter's accuracy starts dropping off fast. By the time the measured voltage is 20V the meter reads less than 17V.




The exasperating part about it is I found this out only after I had redesigned a circuit so as to factor its limited range of 20V. If you haven't guessed it yet, the cheapo meter is made in China. Yes, it came in that blue and white box with Chinese characters. Doesn't come with any instruction leaflet. And there are only Chinese text on all sides of the carton. Frustrating. At least the silkscreen on the board isn't in Chinese! As you can probably make out, the pins for the connectors are marked (left to right) 5VIN, GND, GND, VIN+. The first two pins are for power and the latter two are for the measured voltage input. A check using a DMM shows the two middle pins (GND) are in fact connected to one another on the PCB. The multiturn potentiometer (blue rectangular component at the top) is used to calibrate the meter. Calibration is fine--if you don't need the entire specified range of 20V. Else, it's a joke.

Tuesday, December 13, 2011

Devil's in the details

And I just got burned. I inadvertently designed a short circuit in a pcb!

I create circuit board artwork using DesignSpark PCB and when printing it out on transparency film I always have the board outline printed out as well. The outline allows for precise alignment of the mask (the film) and the presensitized board prior to exposure. In this particular design of a simple 5-volt power supply I had a wide strip of copper for both the +5V and ground. And I extended those tracks all the way to the edge of the board (see the left side of the artwork image below).


Yep, disaster in the waiting. I printed the artwork, exposed the presensitized board, etched it, drilled the holes, soldered the components, and all the while I was absolutely oblivious to the short I had created. I powered up the board while probing the output with a multimeter. Reading? 23mV. I cut off power immediately. Tried it again. Still the same zero voltage. I was so clueless of the booboo that I even desoldered one of the filter caps suspecting it might be defective. Only while poring through board with a magnifying lens did I finally spot the fine 5-mil trace at the very edge of the board bridging the power rails. Facepalm moment indeed. Actually if I had moved the mask by some half millimeter that outline would've been off the physical board and the short wouldn't have appeared.

It's worth noting that even a 5-mil track is faithfully reproduced--implying there's insufficient undercutting during etching to remove the track. This is good of course--if we want such fine copper traces. Luckily it's easy to cut and gouge out the offending copper track. After making sure the bridge had been completely obliterated I soldered the cap back on and the circuit worked as designed. No electronic component was harmed in the making of this sophomoric design mistake.

Hopefully the stress, anxiety, and panic I was subjected to has burned the lesson in my head--since I'll still continue the practice of printing the board outline, I must remember to leave some 20 mils around the perimeter of the board copper-free. I better burn that minimum gap requirement into DesignSpark's design rules. And more importantly, I better start paying attention to the error messages which the design rule check routine spits out--because I don't usually take a look at the track-to-track, pad-to-track, shape-to-track, shape-to-pad, etc. spacing errors. I have a knack for breaking rules. Unfortunately, this time around I got bitten.

Ambient light sensor on the roof

Installed an ambient light level sensor on the roof. Voltage from the simple voltage divider made up of an LDR and a fixed 5% resistor (750Kohm in this case) is digitized by the analog-to-digital converter of the PIC12F1822 (16 readings are taken successively--takes around 1ms--and averaged) and is sent out through the its serial port at 19.2kbps every 50ms. Communications is simplex--this transmitter merely sends while receivers in remote locations can only receive data. Serial data from the MCU is fed to the SN75176B transceiver which then converts the data stream to an RS-485 compliant signal which is then sent down a pair of unshielded twisted pair cable, for use by any circuit requiring the data. Checksum is sent with every data packet for data integrity verification.

A pair of wires in the UTP cable provides filtered (but unregulated) power to the board. Because the input voltage is somewhere around 8 to 8.5V and may drop below 8 if loads elsewhere (various circuits use the same power supply) increase, I used a 1N5817 Schottky diode instead of a 1N400x for polarity reversal protection. That halves the forward voltage drop across the diode to just 0.3V and thus increases the headroom for the 78L05, ensuring it's able to maintain voltage regulation. There are separate power and ground tracks/traces for the analog and digital sections to minimize digital noise from contaminating the sensor section. The analog section has a 1uF tantalum filter cap and the MCP6232 op amp has the mandatory 0.1uF decoupling cap. You might notice the 1/4-watt resistor adjacent to the LDR. Reason is the dang supplier doesn't have the complete range of values for 1/8-watt resistors.



Image below shows the board in situ with the translucent plastic cover yet to be snapped on. Screws on the board act as standoffs to keep the soldered side from contact with the bottom which might accumulate moisture (hence the drilled holes on the blue plastic to act as drain). The gray 4-pair UTP cable can be seen on the lower left.

Sunday, December 4, 2011

Grew up on Casio


Photo of Casio fx-3000 and fx-115MS scientific calculator. An uncle bought me the 3000 back in 1977. Was already gaga over sci calcs back then. It still works but I haven't used it in decades. Though not noticeable in the pic with the 115 (because we're looking head-on through yellow plastic filter) the LCD is already showing its age and deteriorating. Actually it's fared better than my Casio fx-502P whose LCD went kaput years ago. The 3000's power switch had been giving me problems and had to take out its board and clean both the switch and board contacts.

I now use the 6-year old 115 exclusively. It probably has twice the number of functions. The engineering units (nano, micro, kilo, etc) and decimal/binary/hex functions make life easier. And being able to go back and edit the formula/equation and plug in different values for the variables is just indispensable.

As for speed, the two are truly generations apart. A "u" appears as the leftmost character in the 3000 to alert the user that the microcontroller is still running the numbers through its ALU (arithmetic logic unit). Even something as simple as 1+1 takes a quarter of a second. It's that slow. 69! takes 3.3sec. The 115 on the other hand spits out the factorial result in the blink of an eye, literally. Given that both calcs cannot handle or display any number greater than or equal to 10^100, 69 is the highest possible number for factorials for both.

The equation shown on the display of the 115 is (2π*1k*1µ)-1. This of course is the formula for the cutoff frequency of a simple low pass filter with a 1kohm resistor and 1µF cap. Being able to enter "M" for mega, "k" for kilo, "n" for nano, "p" for pico, etc.comes in very handy. They save me the trouble of keying in values in scientific notation.


Back side of the calculator. The sticker is original. Could be the serial number of the unit. You might be able to make out the printing at the bottom. Part of it says "Made in Japan." All Casios were back then. The 115MS on the other hand is churned out in China. Thumbs down.


Without the front panel you can clearly see the poor state of the LCD.


The microcontroller is a NEC D895G. Googled but can't find any datasheet for it.


This is the side of the board that greets you when you take off the back cover.