05/21/2019 at 16:26 •
Timer is a project I work on in between bigger things. Partly because of its simplicity but more importantly its versatility.
For some time I've wanted it to be able to run by temperature but didn't pursue because of the self-heating effect and lack of processing power. But it can get reasonably close to ambient when off and isn't burdened with current sampling. So I wrote v6 to add a simple 'timed temperature' mode.
This mode starts a timing cycle when the temperature is greater / less than a set value. It runs for a set time (the same as set for 'timed' mode) and turns off. It resumes sampling after a fixed cool-off period of 20 minutes.
07/16/2018 at 01:51 •
Timer needs a reboot. I love the simplicity of the gesture interface but as the feature set has grown it has become a pain in the ass. It's easy to lose your place and what & how much you can communicate is limited. It's also a hassle to setup if it's plugged in under a table or something. For me it's really important to keep the box clean - no buttons, switches, dials, etc. That means some sort of remote control.
Right now the plan is to use Bluetooth, probably Microchip's RN4678 and data exchange over the GATT profile talking to a smartphone appl. This will make configuration a snap, along with changing them during operation. New features can also be added. To accommodate this and keep the same PCB / case footprint several things need to happen.
- Reevaluate the logic supply's capacity. The mechanical relay requires 40mA. The controller & SSR require up to 20mA. That only leaves 40mA for Bluetooth with no headroom. A slightly larger supply will likely be required but must be condensed to a smaller footprint than the existing one.
- The continuity sense circuit's PCB footprint must be condensed. Possible & necessary to make room for Bluetooth module.
- Review MCU capability against Bluetooth requirements and additional features.
In parallel enough work should be done on the smartphone appl to ensure that protocol overhead and its impact on the MCU are accounted for before the hardware design is frozen.
I'll probably start with #s 1 & 2 and some rework on the PCB but not sure when that will happen.
07/15/2018 at 19:55 •
First an apology: the code is sloppy. It reflects its slow organic growth and part-time attention. And, I'm still surprised at how such an outwardly simple gadget can have disproportionately complex software. Still, the firmware is mostly conventional in structure so I'll only give a brief overview and focus on the secret sauce.
There are three basic sections: boot, menu, and run. The boot section initializes the MCU's peripherals, calibrates the ADC, and gets the real-time clock going. The ADC is calibrated because Vdd is used for +Vref for the widest dynamic range. Parameter checking is done throughout and out-of-bound values will halt the boot process. This includes a review of the power control & status registers: anything other than a power-up will halt the boot process on the premise that a serious fault was encountered.
Once boot is complete the menu is entered which gives the user the opportunity to set operating mode & options. This is done by gesturing over the light sensor. The menu exits to the run section automatically when the user stops gesturing.
The run section is the typical infinite loop that controls timing cycles. It can only be exited thru a reboot. The design philosophy of the run (and menu) section is that all data required to control operation be available by polling variables thru each loop. Anything that is timing or safety critical is handled by the interrupt vector (ISR). The ISR is also expected to handle data acquisition and the hardware interface. It can be thought of as a primitive hardware abstraction layer. This allows the run loop to focus on functionality while the ISR does the heavy lift and keeps things safe.
The ISR is responsible for:
- Calculating AC RMS current
- Disabling the AC output when the current limit is exceeded
- Switch from SSR to mechanical relay when SSR current limit is exceeded
- Disabling the AC output when the temperature limit is exceeded
- Sensing light level and interpreting a gesture
- Maintaining chronological time
- Maintains various timers used in the menu & run sections
- Monitors AC continuity logic signal, handles de-bounce, sets status
The tricky piece in the ISR is calculating RMS current. The square root sum-of-squares method is used. This requires many samples and is computationally intensive. It's really a job for a DSP or at least a 16-bit processor but that was part of the fun and required some creativity. (it also kept costs & complexity down) What really made it possible was a low bar for accuracy: Timer needs to know approximate current values and the hardware can tolerate several hundred milli-amps of error.
So the Nyquist criteria is violated and only ninety (90) samples are taken during a 60Hz sine cycle (16.66666mS). At 90 samples / cycle there is ~ 185uS between them. To make this work the PIC is run at its maximum instruction speed of 8MHz. Timer four generates an interrupt every ~ 46uS. The service block for timer4 works in four sequential steps, each being performed on a given interrupt and incrementing to the next step on the next interrupt:
- AD conversion of current value
- Read & square obtained current value, start light acquisition
- AD conversion on light, sum squared current value
- Read & evaluate obtained light value, start current acquisition
This is the most time sensitive work in the overall ISR and is placed at the top. The remaining sections of the ISR complete the data processing and set the data objects used by the foreground code.
Timer0 runs at 20mS intervals and controls AC RMS data acquisition cycles. It also completes the RMS calculation by taking the square root of the summed values. It's interval is deliberately longer than a 60Hz cycle. When a full set of samples is ready for RMS calculation the timer4 AC calculations are bypassed until the sample counter is reset. This maintains sufficient execution headroom for other parts of the ISR as well as foreground code.
This section of the ISR also handles connectivity state changes in the AC circuit. It uses the Interrupt On Change (IOC) flags but not the interrupt. This, in combination with timer0's interval, ensures that a state change will be detected without having to constantly monitor the logic state. Last, it also checks for high temperature. Since we're only interested in a threshold a comparator is used along with a fixed voltage supplied by the FVR & DAC. The output of the comparator is polled.
Timer0 code does a lot, but its total execution time is balanced with timer4 to ensure all code in the interrupt vector receives timely attention.
Timer1 is used for chronological timekeeping and is the last code block to be serviced in the ISR. This is possible because the timer interrupt only occurs every two (2) seconds.
You can glean additional details by reading thru the code's in-line documentation.
07/15/2018 at 18:46 •
This post describes the overall function of Timer. I'll talk about the challenging & interesting areas of the design in a separate post.
The TI UCC28880 is a monolithic direct off-line switch mode controller functioning as a non-isolated buck to provide a regulated 5VDC and maximum of 100mA. It is a variable frequency/duty cycle controller with a maximum switching frequency of about 80kHz. C9, C10, and L2 filter differential mode noise and also provide bulk capacitance to supply. L3, C12, and C13 form the output LC filter and D4 is the free-wheeling diode. Q6 & Q7 and the associated resistors provide temperature compensated and level shifted feedback to the controller. For details on this see my project Temperature Stabilizing the TI UCC28880.
Q8, Q9, U5, and their associated diodes & resistors form the continuity sense circuit used by the application override feature. This is accomplished by injecting a low AC voltage (13V), very low current to the output. When the circuit is closed Q9 is biased and it's collector output is amplified and shaped into a logic signal that can be processed by the controller. For details on this see my project In-Line AC Continuity Sense.
The AC switch circuit is a hybrid of mechanical & solid state. This is done to extend the life & reliability of the unit. How: loads below ~ 2A are handled exclusively by the SSR. The majority of applications that household timers are used for is lighting which will likely be below this. So the cycle count on the mechanical relay is greatly reduced and there is no concern that light loads won't be sufficient to properly 'wet' the relay contacts. MOSFETs Q3 & Q4 dissipation is low and hence no heat sink or thermal management is required.
Loads exceeding the MOSFET's safe threshold use the mechanical relay. The SSR is also used to reduce the switching stress on the relay. First, all turn-on events are done with the SSR. Current is constantly sampled and when it exceeds the SSR threshold for 2S the relay is turned on. After a brief overlap period the SSR is switched off. At the end of the timing cycle, before turning the output off, the SSR is switched back on, the relay is then turned off, and after a small delay the SSR is turned off. This methodology operates the relay zero voltage / current conditions and thus prevents arcing & the associated carbon build-up on the relay contacts. Under these conditions the MOSFETs are switched on under 0 volts / current but the turn-off is done under full load. However, the duration of the event, along with the shaped turn-off and selected SOA of the MOSFEts prevents failure or the need for additional thermal management.
Q2, L1, D1, and their associated components form the isolated gate drive necessary for the MOSFET-based SSR. Turn on/off times are generally less than 100uS. See project MOSFET Based Solid State Relays (SSR) for a detailed examination on this approach and shaping switch times.
U3 is a 20A hall effect current sensor that provides a resolution of 100mV/A centered at Vdd/2. This value is continuously sampled by the controller to control the switching function and provide over-current protection. U2 is an active, linear temperature sensor with a resolution of 10mV/C and used to provide thermal protection to the unit.
Q1 is a photo-transistor that along with C4 & R2 output a voltage that is logarithmically related to the luminous energy it senses. This is processed by the controller to interpret gestures, set the status LED brightness, and control the output when used in light sensing modes.
U1 is a Microchip 8-bit, midrange, controller that manages all aspects of operation. Y1 is a 32.768kHz tuning fork crystal connected to the controller's secondary oscillator and used maintain chronological time with an accuracy of about two minutes per year.
07/15/2018 at 15:14 •
Expanding on simple & reliable. I wanted a small form factor and something that could be put together without custom enclosures or special milling & routing. That meant nothing more than a hand drill.
It also had to be weatherproof and relatively inexpensive to build. And at the time I wasn't interested in remote control or a smartphone interface. That meant no buttons, dials, or switches. So it would need some form of sensory input for control. I looked at light, sound, even vibration (like tapping the box) but opted for light since that allow light-based timing cycles.
I settled on a single pole Solid State Relay (SSR) for the switching. No relay eliminated problems with arching, carbon on the contacts, or poor conduction due to not meeting the minimum current requirement. I stuck with the flyback gate drive from the prototype and settled on a 6.3mm dia toroid. With 26/28AWG wire and a handful of turns it's easy to build and mounts directly to the board.
I chose the same ABS case I had used for the Triple5: cheap & small form factor. Seals well and easy to work with.
Surprisingly I spent a lot of time on finding the right strain reliefs. They needed to mount in a drilled hole, be weatherproof, and not too bulky. With a home build it seemed harder than it should have been. I started with the compression bushings you see on a lot of small appliances but they are not weatherproof. I then went to PG9 spiral reliefs which are strong & weatherproof but very bulky & expensive. I finally settled on molded strain reliefs (the kind normally molded to the cord) after I found a glue that secured them to the cord.
I stuck with a PIC MCU and went thru several variants in the 8-bit midrange family before finally settling on the 16F18324. More on that later.
The logic power supply took some time. It needed to be cheap, compact, and simple but provide all the requisite protections (over-current, thermal, etc.). So far the TI UCC28880 has served me well. It's a monolithic, non-isolated buck solution that requires just over a dozen components. The topology is flexible, with some design trade-offs, and I found it necessary to modify the reference design to temperature stabilize it.