This project was completed individually by Zachary Kotlarek.
I have already developed a relatively complex HVAC control system. It has got a bunch of I/O — several temperature and humidity sensors, equipment malfunction sensors, bluetooth presence detection, machine control relays, damper servo controllers, time-of-day mode scheduling, logging, etc. However, this system is currently implemented in PHP and other tools on top of linux, using serial-interfaced, hand-built hardware for physical interfaces — it all works, but it's essentially a software simulation and not anything like a device you could actually mount on your wall in place of a thermostat.
I have decided to refactor this system into some sort of microcontroller-driven device, with the eventual hope of producing a self-contained, integrated I/O, 24 VAC powered, physically small unit that I actually could mount in place of a thermostat, and I think that general idea fits into what you're hoping for in the class project. Clearly the scope of that design is too large for this project, but I can still produce something useful by limiting this project to the core functionality of:
In my existing software-only implementation the "pick a control mode" bit is quite complicated, but it's pretty easy to pare it down to something that doesn't require all 47 inputs or database-backed storage — traditional thermostats just compare the current temperature to the setpoint(s) and provide some hysteresis if the physical system does not, and this project will aim for that same feature set.
This software-only implementation is written in PHP and includes a number of features, inputs, and outputs not present in the SpecC/SystemC implementation due to the limited scope of this project. However, the outputs of both implementations match if the extra inputs present in the software implementation are held at fixed values and the extra outputs are ignored.
The source code for the software-only reference implementation is available in this PHP file: thermostat.txt
A SpecC specification model and associated test data is available in this ZIP archive: spec.zip. The archive includes the model itself in the "spec" folder, the same model imported into an SCE model in the "spec-sce" folder, and test data for stimulus and comparison in the "data" folder. A verification can be completed by providing the data/off-…off.in file on STDIN input and comparing STDOUT to the data/off-…off.out file. The SCE project is configured to use the same stimulus data and automatically make a comparison using diff when the simulation is run.
A PSM diagram for the specification model is available in this PNG image: spec.png.
A SpecC specification model and associated test data is available in this ZIP archive: arch.zip. The archive includes the model as an SCE project in the "arch-sec" folder and test data for stimulus and comparison in the "data" folder. The project is configured to automatically verify simulations using the same methods and data as the specification model.
A PSM diagram for the architecture model is available in this PNG image: arch.png.
In the architecture model I selected a general-purpose processor, a DSP, and a custom-hardware controller as processing elements. The "temp" behavior was mapped to the DSP because that behavior includes continuous data stream conversions that can take advantage of the DSP-specific hardware functions. The "ctrl" behavior was mapped to the controller because it is computationally simplistic, requires a number of dedicated I/O pins, and may need to run at higher voltages or currents than are available in other processing elements. The "mode" behavior was mapped to a general-purpose processor because the software it runs is likely to be upgraded over the life of the project and a general-purpose processor offers high flexibility and low re-design costs through these changes. Because the three behaviors from the specification model were mapped to three separate processing elements all intra-element functions are now sequential and no dynamic scheduling is necessary. SCE was used to facilitate this step of the refinement.
In order to support mapping to processing elements all variables were moved inside behaviors and data transfers and synchronization were combined into channels. This change actually simplifies the overall design by reducing the need for explicit synchronization among the behaviors. This step of the refinement was completed manually.
Given the larger scale of the full project I expect data like "current temperature", "current mode", and "last temperature" would all be made available in a shared-memory element as they would be simultaneously consumed by several behaviors. For example, in the PHP reference implementation the command mode can be overridden from "cool" to "alt_cool" after the mode behavior has selected a mode. This change would likely eliminate much of the direct signaling between processing elements, though the related synchronization would clearly still be necessary.
The SystemC model and associated test data is available in this ZIP archive: systemc.zip. The archive includes the model itself in the "systemc" folder and test data for stimulus and comparison in the "data" folder. A verification can be completed by providing the data/off-…off.in file on STDIN input and comparing STDOUT to the data/off-…off.out file, just as with the SpecC specification model above. The makefile also includes a "simulate" target which will run the compiled simulation and automatically verify the output.
In the SystemC model I recreated the "mode" behavior from the SpecC models. By creating the "intbuf" channel I was able to recreate a double-handshake-like behavior and re-implement the "mode" behavior essentially without change from the SpecC models. Therefore, with only a small amount of kludging I was able to match the stimulus data and monitor output so verification can be completed with the same datasets. However, the SystemC model does not have runtime-adjustable setpoints; the included stimulus data will work but other data sets might require recompilation with new setpoints.
A PSM diagram for the SystemC model is available in this PNG image: systemc.png.
While simplified in the limited-scope models presented in my project, one of the major components of the overall thermostat design is sensors. Traditional thermostats typically use only one sensor, but my design supports an arbitrary number of sensors in different zones as well as sensors for delicate equipment, system feedback, and outdoor conditions. The current software-only implementation gathers this sensor data from purpose-built analog sensors via A/D converts on serial interfaces. However, this approach requires a significant amount of hardware, is difficult to modularize given the non-bus nature of standard UART-driven communications, and requires calibration or even re-design anytime the analog components are changed.
Therefore it is desirable to find a data acquisition platform that supports modular, interchangeable, sensors, preferably with self-contained A/D conversion and a bus interface — given that temperature and other low-data-rate sensors are common in embedded systems there are actually several such external IP platforms available for integration. Two of the most common platforms for temperature sensors are I2C from Philips and 1-Wire from Dallas Semiconductor.
I2C is a two-wire, multi-master, serial, single-ended bus for low-speed communications. It has been standardized since 1992 and more recently has been refined into the no-cost SMBus protocol, though hardware addresses must still be licensed from Phillips. I2C is widely implemented on computer motherboards and embedded systems for acquiring temperature, battery, switch and other sensor data, so sensor modules are widely available and very low cost. I2C typically runs at 5V or less, uses 7-bit addressing, and supports bus speeds of up to 100 kbps, so a network of more than 100 sensors could be readily supported with only one bus. I2C protocols libraries are also available for a variety of host controllers and require only 2 I/O pins, making it relatively straightforward to integrate I2C sensors as a random-access (albeit slow) memory element. I2C also supports multiple masters, so it is possible to connect a sensor network to more than one host device, allowing for shared use without direct integration or out-of-band access arbitration. However, I2C supports a maximum bus capacitance of only 400pF, which typically limits bus length to only a few yards.
1-Wire, as the name implies, is a single-wire communications bus. In typical application at least 2 and sometimes 3 physical wires are used, but only one of these need be interfaced to an I/O pin for communication, and it is possible to use the bus with only a single wire if a reliable earth-ground is available at all nodes. Since 1-Wire is a single-master bus and is not sensitive to capacitance it supports bus lengths of up to several hundred yards. In comparison I2C requires 4 wires — 2 I/O pins, Vcc and a low-capacitance ground — in all applications. 1-Wire uses 64-bit address with 48 bits available for each device type, so each bus can support thousands of devices. However 1-Wire only supports data rates of 10-150 kbps, so it is best suited for applications that can tolerate slow refresh rates. As with I2C, 1-Wire protocol libraries are available for a variety of host controllers making integration easy. In fact, given the single I/O pin and the low data rate 1-Wire busses can be controlled using a standard UART (in combination with a few resistors), allowing easy integration with everything from embedded systems to desktop computers.
While both serial busses could be made to work in my thermostat, I believe 1-Wire will be the best fit. If I were building a traditional thermostat using only on-board sensors I might make use of I2C, but in my application the bus length limitations are not acceptable. The support for longer wire runs have also made 1-Wire more popular for weather-sensing applications, which makes the outdoor sensors I want to deploy more readily available. Finally, the single-pin communication is attractive because it reduces the cost of bus segmentation — in order to build a reliable system it is desirable to isolate the outdoor sensor bus from the indoor sensor bus from the feedback sensor bus, and using 1-Wire over I2C reduces the number of I/O pins required for these isolated busses by 50%.
I've been excited all throughout this course to apply what I've learned about system-level design to my thermostat. Though I have some experience with control systems I was totally unaware that tools like SpecC/SystemC even existed; my experience has been 100% in platform-based environments where software and hardware were developed essentially independently. As such I was considering a platform-based system for my embedded thermostat project — specifically the Arduino Uno I've got sitting here on my desk — and while that platform is still likely to be an important part of my design I no longer feel locked into its limitations. I've also been freed from my relative lack of hardware design skills; I've built a few analog signal processors and poked at VHDL but I don't have the knowledge to design complex systems in hardware and the mixed hardware-software approach of system-level design opens up a whole new range of possibilities within my existing skill set.
In specific, the refinement steps between the specification model and the communications model were totally outside my knowledge base. I have a lot of experience with software design, and I know enough about hardware to pick components and design logical communications protocols. However there's quite a gulf between those two steps and until this semester I was unaware that any tools or methods for that design space even existed, or at least that any existed that I might actually be able to apply to my low-budget, hobby projects. Even very simple things like SpecC's c_double_handshake structure can immensely simplify the translation of a design from software to hardware by bridging the gap between the software concept of guaranteed sequence of execution among the behaviors and the signalling required to actually accomplish that task. And none of that even considers the theory of design that can guide my selection of hardware with respect to the intended use and target cost/speed/etc.
In terms of this project, rather than the course as a whole, I've probably learned the most about SystemC. The sensitivities list is a concept that I find quite intuitive for system-level design, and which is not well represented in the software-only design to which I'm accustomed. Also, while my C++ skills are quite rusty, once I figured out how the SystemC examples worked I became intrigued by the possibility of using OO design methodologies in system-level design. Even as we worked through the course and I "implements"-ed in SpecC I had not really considered the possibilities for OO; conceptually I've always segregated hardware and software and while it's clear in retrospect that the same design concepts could apply to both I have never worked with hardware outside of a strictly sequential, global, imperative model, which is quite limiting.