Ethernet AC Interface (Part 9)
I really like my Ethernet AC Controller. Its probably the most useful thing I’ve built. So when I decided to give PCB manufacturing a try, it was a good candidate for an upgrade. This post covers the (re)design and features of my new Ethernet AC controller. If you haven’t read my other posts, my goal here was to be able to control my air conditioner from my cellphone.
Besides simply moving from perf-board to a printed circuit board, I had a couple other goals: I wanted to build/design/code everything myself, and I wanted a better IR communications dialect. With the exception of a few shortcuts, I pretty happy with reaching these goals.
IR communication
Physical Layer
You can find my previous documentation on the IR communication of my AC here. I’ve figured out a lot since writing that post. Most of what I learned came from this universal remote. Instead of having simple buttons for “Up/Down”, this remote has an LCD with the current temperature displayed. This means instead of sending “Up/Down” signals, this remote has to send “Set Temperature to 70″. Even better the remote also sends “On” and “Off” instead of “Toggle power.” This was great since my previously known commands, “Power Toggle”, “Temperature Up/Down” were of limited usefulness when trying to control the air conditioner away from home.
I hooked the new remote up to an oscilloscope and yanking out the codes. I stared at the raw captures for a long time, and eventually sorted out the physical layer. It looks the same as in my previous post, but I’ve interpreted it very differently. Data is transmitted with a carrier of 38khz with a 50% duty cycle. A “unit of time” is defined as 1/38,000 of a second.
- Prolog:
- LED is illuminated for 344 units of time
- LED is off for 172 units of time
- Data:
- At this point data is transmitted MSB
- Each bit is framed by illumination for 22 units of time.
- If transmitting a 0, the LED stays off for 23 units of time.
- If transmitting a 1, the LED stays off for 68 units of time.
- The light is illuminated for 22 units of time, and we go back to step 7 if there’s more data to send.
I spent considerable time making sure I was correctly understanding the physical layer. This was critical to being able to construct custom IR commands, and calculate correct check-sums.
Data Layer
Once I defined the physical layer correctly, figuring out the data protocol was easy. Data is transmitted in 24 bits plus a 4 bit checksum:
IIII IIII SSSS SSSS TTTT RRFF CCCC
Where:
I - always 0x88 (the unit id?)
S - always 0x00 to turn the unit and set mode to "cool"
other values in the field include "dehumidify", but I didn't
document them
T - is the desired temperature. 0x1 being coolest, 0xF the warmest
in increments of 1 degree Celsius.
R - reserved (or rather, I don't know, but sent as 0x0)
F - fan speed (low = 0x0, med= 0x2, high = ox4)
C - a 4 bit check some of all other data
If you have an AC with the same physical layer, but data transmission is completely different, the code / project may still be of used. If you compile with -D SUPPORT_RAW_COMMAND it’s possible to to use the web server to send raw binary commands over the IR transmitter using the physical protocol described above. For example, the following turns my AC off: http://myac/cgi-bin/ac/raw/1C88C00510. 0x1C is the length of transmission in bits. 0x88c00510 is the data transmitted, including the check-sum.
Code
The entire process of signal generation, and command construction can be found here: lg.c. See the top of the file for the predefined IR commands, and lg_create_command() for building an IR op-code for specific temperature and fan speed.
Hardware
Ethernet
I decided on trying the WIZnet W5100. This decision worked well for a couple reasons. First, I could easily prototype software on an Arduino + WIZnet shield setup. I’ve never used the Arduino tool-chain, but as a hardware platform for verifying my firmware before integrating with my PCB it worked great.
Second, the W5100 meant I wouldn’t have to try to implement TCP/IP like an ENC28J60 based project. Really, the only problem with the W5100 was its 0.4mm pitch on the leads (which was out-of-spec for BatchPCB). The W5200 solves this problem, but it doesn’t support SPI, and I wasn’t ready to try my hand at routing memory access bus. I was left with no choice but to use a break-out board
.
MCU
MCU selection was pretty easy, I went with an ATmega328 (although the code will fit on an 8K part too, depending on compiled features). I picked up Atmel parts when I started years ago because of the stronger Linux support. I stayed in the 88/168/328 line to ease any issues porting the code form Arduino.
PCB Layout
I think after about 2 weekends of work, I managed to layout my PCB. It was my first experience creating a circuit board. I used this tutorial to get started, plus some other resources which I forgot to bookmark.
It took a few tries to get right, and months of waiting for delivery, but here’s the final version:
Assembly
Assembly was a lot easier than expected. Some of the parts are really small, but as long as I used a generous amount of flux the solder flowed where it was needed and wicked up easily. For harder to solder parts, or if I was just lazy, I switched to lead solder.
This was only my second or third time using surface mount parts. I’ve found tweezers, flux, wick, temperature controlled iron, and magnifier the only required tools. SMT is getting a lot easier with each attempt. I’m a lot faster now, and rarely have problems with part alignment.
Here’s revision 1 (left) and 2 (right). Only one “green wire” on my very first PCB!
What Didn’t Work
In system programming
The W5100 seems to have trouble when initially powered on. Even on the Adruino shield it failed. I fixed the shield by adding a 0.1uf cap to the reset pin. For my PCB, I simply wired reset to a GPIO pin on the AVR. I figured if the problem did show up, be able to fix it in software.
But, I didn’t pay close enough attention to the SPI bus. PCB Rev 1 had problems with in-system-programming (ISP) of the AVR. Since the W5100′s reset was controlled by software, I could not hold it in reset while ISP routines were running and as a result it was driving MISO. PCB Rev 2 fixed this by adding tri-state buffers to the W5100 and uSD card. Under normal operation the buffers default MISO to HiZ unless CS is active. I also added somewhat strong pull-up resistors (10k) to make sure the buffers remained HiZ while the AVR was held in reset.
Parts
I had redesign the PCB a few times because I built around parts that weren’t in stock. Even parts I thought would be no trouble to find, like a 2×9 2mm header just didn’t exist.
Heat
I added a temperature sensor to the board, an MCP9800. I thought it would be neat to build some graphs on temperature trending, but it turned out to not work at all. Although the software and I2C interface were fine, the board ran slightly warm, so I couldn’t get ambient temperature readings.
IR Transmitter
I drive the IR LED with 20 ma (the maximum source current of the AVR), but it is not bright enough to cover range of more than a few feet. Next time I’ll add a transistor.
Software
All of the source code is linked below. It basically includes: libc like socket api for W5100, simple webserver, url handlers for invoking lg/ir signal generation, and a simple rom based filesystem.
To control the AC i have two interface: first I can simply type the AVR’s ip address into a web browser and use a GUI, and second there is an API interface: http://air.conditioner/cgi-bin/ac/on?temp=74&fan=1
I’m not really happy with the performance of the software, maximum download speeds are ~20-30kbytes/second. This is more then fast enough for my application, but there’s definitely room to make things faster (but, probably at the expense of reuse and readability).
Source and Design Files
I wrote almost all the code myself, with only one exception. The board is also a webserver, reading content off of a FAT uSD card. Support for uSD and FAT come from elm-chan.
Eagle PCB Files & Gerbers: https://github.com/braiden/embedded-ac-controller/tree/master/pcb
Source Code: https://github.com/braiden/embedded-ac-controller
Parts List: http://www.mouser.com/ProjectManager/ProjectDetail.aspx?AccessID=8c0f0b4605
WIZ810MJ: http://www.saelig.com/product/ETH027.htm
Circuit Board: http://batchpcb.com/index.php/Products/36530
See LICENSE. Feel free to try to build one yourself, or re-purpose the design.
More to Come
I still want to implement a nice android widget for controlling the AC.
Tags: avr, c, infrared, project-ac






October 3rd, 2010 at 12:15 pm
Hi!
Great post!
I was looking at W5100 and W5300, and found the W7100 MCU….. it has a 8051 core
, I like AVR the most, but, the price is: too good… at around US$5.29 http://www.saelig.com/product/ICTCP006.htm , I mean, it has the W5100 plus microcontroller …. Has you evaluated that one?
Also, on other things: have you used KiCad or gEDA?
Regards,
Ildefonso Camargo
October 22nd, 2010 at 10:59 am
@Ildefonso,
I’ve never used the W7100. Sounds interesting. I’ve been stubborn to try anything that can’t develop in linux, but 8051 + sdcc sound like it might work (assuming there’s some way to load the code.) I’m eager to try an 802.11 module next, provided I can find something interesting.
I’ve never tried KiCad or gEDA, I should probably give them a try. I started with eagle, mainly because I found the SparkFun tutorials.