Tuesday, November 29, 2011

Relay board

Over the years I've moved away from relays and adopted triacs for switching high voltage AC loads. Their quiet operation and compact size (heat sink excluded) are a plus. In the last few years, however, I've reverted to the electromechanical device. The prodigal son has returned (nahhh). Relays have their drawbacks including mechanical failure, contact point burning/pitting, and coil burnout, but they provide superb electrical isolation between control and power side of the circuit and negligible voltage drop across the contacts.

So here's my relay module v1.0 complete with polarity reversal protection diode, flyback diode, and LED power-on indicator. The relay in this case is a SPDT with a contact rating of 10A @240VAC/24VDC and a coil of 12VDC (measured resistance = 420 ohms). The board is designed such that the LED and its current limiting resistor need not be installed for the circuit to work--the additional current draw may be undesirable or an indicator lamp may simply be superfluous. Even the input diode in series with the positive rail isn't absolutely essential (if polarity reversal isn't an issue) and a jumper wire can be soldered in its stead. Omitting the flyback diode, on the other hand, is an experiment for foolhardy to try out.

DC coil power input is via the 2-pin connector with red going to V+ as per convention, while relay contacts are accessed via the 3-way terminal block. I'm obsessed with isolation so I've placed them on opposite ends of the board.

The paper phenolic board is 1 x 3 inches, scored and snapped off from a 4x3-inch "mother" board which contains three other clones. Yeah, I'm mass producing this.... Uhhh sort of.

Saturday, November 26, 2011

Random number generator

Needed a way to make a microcontroller turn a load on at random. A little research and I found an algorithm that goes by the highfalutin name linear feedback shift register. Basically the bits in the register are shifted one bit either to the left or right and the result is then XORed with a constant. The content of the register changes in a pseudo random way. It isn't at all random because when we perform the shift and XOR the register goes through each possible value once and only once (each of 255 numbers for an 8-bit register) until we cycle back to the original seed value (initial value of the register). Thereafter, the exact same sequence gets repeated.

It's important to make sure the seed stored in the register is nonzero, else it will remain zero.

PIClist has a number of code snippets for implementing the LFSR in Microchip PICs. The following is for generating a 16-bit random number written in PIC18 assembly:

  BCF     STATUS,C
  RRCF    LFSRVALUEH,F
  RRCF    LFSRVALUEL,F
  BTFSS   STATUS,C
  RETURN
  MOVLW   0xA1
  XORWF   LFSRVALUEH
  XORWF   LFSRVALUEL
  RETURN

Converting the above into mikroC PIC16 assembly with the 16-bit random number stored in variable N, we have:

asm{bcf     STATUS,C
    rrf     _N_L0+1,F
    rrf     _N_L0+0,F
    btfss   STATUS,C
    goto    $+4
    movlw   0xA1
    xorwf   _N_L0+1,F
    xorwf   _N_L0+0,F}

And converting the same into mikroC we have:

int8 RanNum()
{
  static unsigned int RANDOM = 1;

  RANDOM >>= 1;
  if (STATUS.C)
    RANDOM ^= 0xA1A1;
  return RANDOM;
}

The above code translates into just 8 lines of mikroC assembly using the enhanced midrange instruction set.

For the circuit I'm using it in, I need a number from 0 to 99 to emulate a percentage value. So what I did was to simply take the last two digits (decimal) by dividing the 16-bit number by 100 and taking the remainder. I used a 16-bit generator instead of an 8-bit because the application requires that repetition of the sequence does not occur too quickly. I also wanted the seed number to be changed every time the circuit starts from a power-off condition so that the same sequence doesn't repeat every time the circuit powers up. To implement this the firmware loads RANDOM with the value stored in an EEPROM address. A crucial check is made to make sure RANDOM is not zero. If it is then it's incremented by one. RANDOM is then incremented and stored back in the same EEPROM location. Thus, every time the circuit boots up, RANDOM starts with a different seed.

#define  addr_seed     0x1    // plug in your choice of eeprom address for the seed number
static unsigned int RANDOM;

void IniSeed()
{
  // seed number for random number generator is obtained from an eeprom location
  // the value of seed number is incremented and stored back in eeprom
  // thus, a different seed number is used every time the MCU powers up.
  RANDOM = EEPROM_Read(addr_seed);
  if (!RANDOM)                           // seed number must not be zero!
    RANDOM++;
  EEPROM_Write(addr_seed, RANDOM+1);
}

int8 RanNum()
{
  RANDOM >>= 1;
  if (STATUS.C)
    RANDOM ^= 0xA1A1;
  return RANDOM % 100;     // a number from 0 to 99 is returned 
} 

Note that EEPROM_Read() and EEPROM_Write() are mikroC built-in functions. Admittedly the seed number in the above routine is only 8 bits long, but for my particular application this is sufficient. If you need a 16-bit seed then simply read the contents of two EEPROM addresses into RANDOM, increment RANDOM, and store the low and high bytes of RANDOM in the appropriate EEPROM addresses:

void IniSeed()
{
  RANDOM = EEPROM_Read(addr_seed)*256 + EEPROM_Read(addr_seed + 1);
  if (!RANDOM)                           // seed number must not be zero!
    RANDOM++;
  EEPROM_Write(addr_seed, (RANDOM + 1)/256);
  EEPROM_Write(addr_seed+1, RANDOM + 1);
}

Wednesday, November 23, 2011

Variable intermittent wiper control - printed circuit board

Finally got around to making a PCB for the wiper control. Used DesignSpark PCB to draw the schematic and PCB layout. The board is 3 x 3.5 inches and was exposed to fluorescent light for 70 seconds. Vertical distance of the two 11-watt Toshiba compact fluorescent lamps from the board was 3 inches. On the long sides, I placed cardboard on which aluminum foil had been taped to reflect light back into the exposure area and even out the lighting. (Up to now I have no idea whether the board is sensitive only to UV or UV + visible light, nor do I know to what degree aluminum reflects/absorbs UV.) Details of the procedure and materials I use can be found in Making PCBs using presensitized boards.

I introduced one modification to the June 2011 circuit. The wire length from the board to the push button (a tact switch epoxied to the end of the stem switch that controls the headlights and turn signal lights) is almost a meter in length, so instead of directly connecting it to one of the MCU pins, I am now using a KB817 optoisolator. I also added a red LED to the circuit. It's connected to one of the MCU pins via a current limiting 330-ohm resistor. Right now it serves no function. I just included it just in case and since the MCU pin is unused.

The Sonalert buzzer isn't in the pics because it's connected via the terminal blocks.






As always the soldering leaves much to be desired. I particularly had trouble soldering the huge pins of the Telemecanique RXM2 DPDT relay to the board. The trick, which I learned only after botching it, is to lay on lots of flux paste on the pins (and copper pads) and melt a huge blob of solder to the puny 30W soldering iron (30-year old, non temperature controlled, and directly plugged into the 220VAC outlet). The thermal mass of the gob of solder and large contact area coupled with the cleaning action of the flux greatly increases the chances of successfully and cleanly soldering these gargantuan pins.