The PWM can run on 7-12vdc. The PID is wired into the PWM, rather than the SSR. When the switch is in the "off" position, the PID controls the SSR. Once turned "on", the PWM takes over control of the signal.
The schematic & board were drawn in Cadsoft Eagle (freeware version). I used iTead's CAM files to create the gerber files for the boards, and then had them produce the boards for me. I emailed the files on 7/8/12, the boards arrived 7/30/12. 10 boards cost me $18.90 to the door. It would have been less, but I got them in black, just because.
I considered using a 555, but went with an ATtiny85 instead. With a 555, I'd have to recalculate resistors and capacitor values, and then actually break out a soldering iron again to change anything. With this chip, I can change the code on it in seconds if I want to change the function. The downside is the ATtiny85 costs a little more and requires a voltage regulator.
It was going to be all through-hole parts, but CS223 encouraged me to try using these surface mount components. The parts on the back (that 8 pin chip, the two brick shapes pieces and the voltage regulator) were a breeze. Much easier than expected. On the front, there's 8 or 9 components in that little area behind the potentiometer. They are 0603 components (0.06" x 0.03"). This is the LAST time I'll use them. WOW those are tough to handle. The take-home lesson is to stick with the surface mount stuff (small & cheap), but use the more manageable 0805 or 1206 parts. I've got enough parts to make a handful of these PWM's. Maybe once I'm done, I'll have had enough practice to think differently.
If there's some way to do it, I'll zip the Eagle files and post them here. I put the OSHW logo on there, and the CC-SA license in hopes that someone will take the files and build something more impressive.
The code is stupidly simple:
#define potPin 1
#define ssrPin 4
#define windowTime 1000
unsigned long markTime=millis();
int period = map(analogRead(potPin),0,1023,0,windowTime);
if ((millis()-markTime)<period) digitalWrite(ssrPin,HIGH);
if ((millis()-markTime)>period) digitalWrite(ssrPin,LOW);
if ((millis()-markTime)>windowTime) markTime=millis();
The code could easily be modified, though. For instance, you could have the knob start at 30% instead of 0%. Or max out at 80% if you wanted to. Or reverse direction.
For my own copy, I will have the first 10% of the knob cover from 0-40%, the last 10% cover 80-100%, and then have doubly fine control from 40-80% (the range where I suspect most of us are boiling).