perjantai 25. huhtikuuta 2014

Tiny PICs: Schematic and software


This took I little longer than I intended, but after a few distractions here is the last chapter (for now at least) for using PIC12 for toy modification. So now the electrical and software details.

The airplane used three LR44 1,5v batteries in series, so it fit perfectly for PICs operating voltage limits of 2-5v. The white LED had forward voltage drop of 3v, and original series resistor was 120 ohms, meaning about 8 mA for forward current. Easy enough to handle.

I used PIC12F509 for this. PIC10F206 would have been sufficient too, but for some reason I just couldn't get it working, so after a few hours I just gave up. I could load software on the chip but it wouldn't do anything. Weird. Most likely just some stupidly minor detail I missed, but I just couldn't justify using more time on that now, especially since PIC12 worked right away. Since I only that two PIC12s remaining and five PIC10s from last attempt, I suspect that last time I tried situation was the same (yes, tried multiple PIC10s, same result with all, must be the software, or build environment bug)

So I decided to use original LED and series resistor as-is. Single pin of PIC can source 25mA (IIRC), but I still connected two in parallel (specifically GP1 and GP2, pins 5 and 6) to source the LEDs. No reason really, but the "feel good" factor for ridiculously over-engineering single part of design.

My paper schematics end always looking the same, some parts huge and some parts tiny. Oh well, guess I'll just explain it then since schematic isn't exactly most readable.

Circled + and - symbols are battery positive and negative; connecting to PIC pins 1 and 8 respectively. It may not be necessary but I still added small bypass capacitor directly between power pins. For some applications you may get away without one, but as rule of a thumb you'll always want to put one there, especially when there are significant current changed around (like here, 100nA to 10mA) as they smooth out voltage seem by MCU.

Button is connected between pins 8 (GND) and 7 (GP0). GP0 is also very very weakly (1Mohm) pulled high. Since there is basically no load on this pin the pull-up could be a lot smaller without affecting standby power consumption (say, 10k). For EMI resilience (for very very noisy environment) you might want to use smaller resistor (or more importantly, actual well designed PCB). And finally the LED with series resistor. All in all, very simple build.

I also mentioned that it might have been possible to use original switch instead of button. This assumes that the three-pin switch is breaking type (that is, connection is broken before other side is connected). In such case center pin would be negative, and both sides are connected to same sense pin and common pull-up. Pull-up might need to be smaller in that case to pull line up during short break period but it would also make constant always-on current draw so you still would want to use as large resistor as you can get away with.

Now, the software. When dealing with MCUs without OS I just write all the software in plain C nowadays, even for tiny devices such as this. I see no point in learning assembly of even one device crossing my path, there are just too many different MCUs I use. There are exceptions, of course, but there must be sufficient financial reason to spend time delving into mysteries of specific assembly dialect for me to bother for anything more complex than often-useful NOP and almost-always-necessary interrupt enable/disable instructions (and really, nowadays compilers almost always have macros for those - and more)

For PICs I do majority of my work in MPLab X, and for C compiler I used MicroChip's XC8 compiler. Software was fairly simple; whenever processor is reset (for any reason, but typically power-on or wakeup due GP0) it will turn LED on, wait for approximately 5 minutes (timing isn't that critical so variance in RC oscillator is not an issue) and then drop output drivers and enter back to sleep.

#include <xc.h>

// CONFIG - PIC12F509 Configuration Bit Settings
#pragma config OSC = IntRC      // Oscillator Selection bits (internal RC oscillator)
#pragma config WDT = OFF        // Watchdog Timer Enable bit (WDT disabled)
#pragma config CP = OFF         // Code Protection bit (Code protection off)
#pragma config MCLRE = ON       // GP3/MCLR Pin Function Select bit (GP3/MCLR pin function is MCLR)


/* -----------------------------------------------------------
 * Small delay. About 3ms (as measured)
 */
void delay()
{
  unsigned char i;
  for (i = 0; i < 250; ++i)
    { asm ("nop; nop; nop; nop; nop; nop; nop; nop; nop; 
            nop; nop; nop; nop; nop; nop; nop; nop; nop; nop");
    }
}


/* --------------------------------------------------------------
 * Simple main. On startup LED will be on; after specified time
 * it is turned off, and processor will enter sleep mode.
 */
int main(int argc, char** argv)
{
  unsigned int counter;

   // Configure IO:
   //   GP0      = input (externally pulled high, button pulls down to wake)
   //   GP1, GP2 = LED output (drives high)
  TRISGPIO = 0xF9;
  GPIO = 6; // LED on after wakeup

   // Enable wakeup on pin change (GP0,1,3); disable pull-ups;
  OPTION = 0x40; // 0100'0000

  counter = 0; // timer counter

  while (1) 
    { ++counter;
      if (counter == 33333) // 9 ms per iteration; this makes about 5 minutes
        { GPIO = 0; // turn LED off

          delay(); // let drivers settle (this may not be necessary)

          GPIO; // dummy read state before sleep (required for proper function). 
          GPIO;
          asm("sleep");

           // pin 0 change will then reset chip, (re)starting main again.
          
        }
      delay();
      delay();
      delay(); // 9ms total per iteration
    }
}

This absolutely isn't something I'd put into production, as I don't feel that it is as resilient to external interference (EMI) as it could be (or even optimal solution to this problem actually). My hunch is that this may react "badly" to RF interference (not in sense that it'll cause fire or anything, more like waking up when not needed) but in this case it is not that big problem.

But for intended purpose - to make a toy last a bit longer as useful - it is good enough. That for now, that is more than enough - already forgotten (dead) toy became "hot" item again. Weird how doing something "useless" like this gives you that nice, warm feeling inside...


Ei kommentteja:

Lähetä kommentti