2012-10-02

Ethernet-connected temperature sensor, part 2: design/schematic capture

(Since I'm writing this not only after making the schematic, but also after making the PCB layout and after buying all the components, I won't go through this in steps, but rather just jump to the full schematic, and go through it as-is instead.)

The final schematic

Slightly annotated schematic

Unannotated schematic

Power regulation

First out, we have the power input and 5 volt regulator, in the top left of the schematic.
Not much of anything of note here, just a plain LDO/linear regulator circuit.
Two high-temperature (for the longer lifespan) electrolytic caps on the input, as a local energy reserve. One 10 µF low ESR ceramic, since the regulator's datasheet points out that's what you should use to get stability.
On the output side, the resistors are, of course, chosen to give 5 volts, via the formula Vout = 1.21 V * (R3/R1 + 1) = 5.0336 V
(The 1.21 V is the voltage of the regulator's internal bandgap voltage reference.)
The set resistors are 0.1 % tolerance, IIRC. Not really necessary, but since this is a one-off build, the additional cost is negligible!
On the output is another 10 µF low ESR ceramic cap, again because that's what the datasheet recommends.
I also chose to separate the ground for the input from the main ground plane, and run it through a regular (thick) trace, instead, all the way to the regulator - which is why you might spot the "NET_TIE" component that ties them together at a single point. The reasoning for this (which is really irrelevant for this project) is to keep high-frequency currents of the ground plane, for noise/EMI concerns. (The input power comes from a switchmode supply.)
More on this in the PCB design post. However, do note that I'm far from a professional engineer - I started with this hobby less than 9 months ago - so this rationale might not be perfectly sensible to a professional. I hope it is, though!
Also, since there is no analog stuff on this board, it almost certainly doesn't matter at all.

After that subcircuit, we have the 3.3 V regulator. It's pretty much a straight clone of the 5 V one, except that it's powered from the 5 V regulator and doesn't need input electrolytics, and that it of course has different resistor values to set the output voltage properly.

The microcontroller

To the bottom left - not circled, since that would be a bit silly - is the project's brain: the Atmega328 microcontroller. As mentioned in the first post in this series, I chose that particular model because I wanted Arduino compatibility, and I already had an Arduino Uno (which uses a socketed Atmega328P-PU).
100 nF bypass cap as per usual, 16 MHz crystal (again, for Arduino compatibility - a 20 MHz one, which would fit the 328 spec, would ruin timing unless code is changed) with 22 pF load capacitors - same as the Arduino boards.
Aside from the layout and programming, subjects of upcoming posts, there isn't much interesting going on with it.

The reset circuit

There's a capacitor between the RESET pin and ground, to help reduce noise that might cause accidental resets. A pullup resistor, since the reset pin is active low, and we don't want it to become low without the button being pressed (or the programmer pulling it low). And, last but perhaps not least, a smaller resistor between the switch and ground, as the AVR Hardware Design Considerations [PDF] guide suggests, apparently to reduce di/dt voltages due to parasitic inductance when the capacitor is emptied.
If an external switch is connected to the RESET pin it is important to add a series resistance. Whenever the switch is pressed it will short the capacitor, the current through the switch can have high peak values. This will cause the switch to bounce and give steep spikes in 2-10ms periods until the capacitor is discharged. The PCB tracks and the switch metal will introduce a small inductance, this inductance can generate high voltages according to Vi = L* di/dt. These voltages are most likely outside the specification of the RESET pin. By adding a series resistor between the switch and the capacitor the peak currents generated will be significantly [sic], these currents won’t be large enough to generate high voltages at the RESET pin. An example connection is shown in Figure 3-2.
Figure 3-2 shows the pullup resistor, the capacitor, and also a reversed diode between VCC and reset. However, it appears that a ton of hobbyists (a huge majority in a small, non-representative forum poll) skip the diode, with no real ill effects, so I did too.

Aside from that, there's not much to see here.

ISP interface

One subject that might be worth bringing up regarding the Atmega328, though, is the In-System Programming (ISP) interface.
Most members of the Atmega family are programmed via a SPI bus, connected to four pins: three SPI pins (MISO (Master In Slave Out), MOSI (Master Out Slave  In), SCLK (clock)) plus the RESET pin.
Since I need the SPI bus for the Ethernet module, this proved to be a slight challenge - mostly because there was slightly conflicting information on the best way to solve the possible issue of bus contention.
Programming works like this: you connect a programmer to the ISP interface - a 2x3 pin header - which pulls and holds the microcontroller into reset mode via the RESET pin. That causes it to listen to SPI signals sent by the programmer.
So far so good... However, we also want the Ethernet module connected to the same pins. If it were guaranteed to behave properly, and tri-state its pins, there would be no problem here, as it couldn't possibly interfere when its pins are all high-impedence and essentially disconnected.
However, it seems that quite a few SPI devices out there aren't always so nice, so we need some way to ensure it doesn't interfere with the programming process.

Researching this, I found two different options:
1) Use a pull-up resistor on the SS (slave select) line; when the programmer resets the microcontroller, it will tri-state all pins - including SS - which causes it to float high. This should then cause the Ethernet module to also tri-state and "disconnect", until SS is pulled low again. (SS is active low.)
2) Another solution, as recommended by Atmel in the AVR ISP documentation, is to add series resistors to the SPI bus. The programmer connects directly to the microcontroller, while other SPI devices connect to it through ~5k resistors. This way, if the Ethernet module attempts to interfere, the programmer will massively overpower it.

The first solution, using an SS pullup, seems straightforward and easy. However, it also seems some SPI chips - including the WIZnet W5100 Ethernet chip (the predecessor to the W5200 I'm using) had a bug where it didn't tri-state when SS was high (keep in mind that SS is active low!). This bug is supposedly fixed in the W5200, but I didn't dare take the risk of relying on that method alone, so I chose to use both solutions... except that I'll use 0-ohm jumpers for the series resistors, unless/until that proves not to work.

Debugging

Since, from what I could tell, it seems the only "real" way to debug the Atmega328 is via debugWire, an interface only available with hardware debuggers like the JTAGICE mkII (€290) or AVR Dragon (€50, but I've heard stability/reliability complaints), I ended up going with a different solution.
I did buy a programmer, the AVR ISP mkII (€33), but it doesn't support debugging.

The solution I chose - granted, it is inferior - was to add a UART header to the board (just the TX and RX pins on the micro, plus ground), and to use my Arduino Uno as a UART<->USB bridge. That way, I can access the serial console even when the project is on its custom PCB. What I can't do, however, is set breakpoints, step through code, and inspect variable values... Something which I've managed without, so far - on microcontrollers, at least. I wouldn't say the same for other projects (e.g. OS development!).

Sensors

There really isn't much - or anything at all - to say about the sensors in this post (as I intend to keep this post about the schematic, not the manufacturing part of it all). The only reason I'm even writing this section is to make it clear I didn't forget about it!

Ethernet module

There are a few things worth mentioning here, but I've already talked about most of them! One is that the WIZnet chip is powered off 3.3 volts (and 1.8 volts, through an internal regulator), unlike the rest of the PCB which runs off 5 volts... but I've already talked about the voltage regulators.
Another thing is the trouble with the ISP interface and the SPI bus (SS pullup/series resistors for the SPI lines), which I've also mentioned previously.

So, is there anything left to say?
Well, not a lot. The module has three pins aside from the 4 SPI pins and power/ground pins: power down (usually known as shutdown), which causes the chip to power down and save energy if held low. Since this is a 24/7 device, that sends samples many times a minute (currently every 10 seconds), I simply wired that to VCC.

Then there's the RESET line, which I wired to a pin on the microcontroller, so that the code can reset it when required. Not much interesting here, either.
Lastly, there's the INT (interrupt) pin, which the module uses to signal that it wants the microcontroller's attention. However, it appears that the Arduino Ethernet library doesn't use this functionality at all.
I considered rewriting the library to change this, but it was quite frankly a bit of a mess, and seems to work either way, so at least for the time being, I'll just live with polling. It's not as if performance is crucial.

Add-on header

Towards the end of the design part of the project, I was considering adding other types of sensors, especially humidity and light. (This project was/is intended as a simple greenhouse monitor.)
Those sensor types seem to have one thing in common: there are no cheap, decent digital sensors around. Humidity sensors appear to be mostly capacitive in nature, and I've never dealt with measuring such things before. Since I was ordering the project and PCB before prototyping, I didn't want to risk it.

As for light sensing, all useful solutions I could find were analog in nature (no matter whether they used photodiodes, phototransistors or other components at their core). That's not necessarily a horrible thing, of course, but I decided against it for pretty much the same reason as the humidity sensor - I didn't want to design, layout the board and buy the parts without testing it properly first. There was also the argument that precision analog circuits require low-noise designs.

And so, I scrapped those ideas - for the time being - and went for another: an add-on header. That is, a "slot" (pretty much a 12-pin DIP socket) where a future daughterboard can fit.
All but 4 of the otherwise unused microcontroller pins go to this header. There's power (5 V, 3.3 V and ground), plus the SPI bus pins, the I2C bus pins, the 1-Wire bus pin, two other ADC pins (4 ADC pins in total, since the I2C bus shares pins with the ADC) and one of the external interrupt pins, the other going to the Ethernet module.

This way, I can add on pretty much anything (one way or the other) at a later date. I'm still considering adding the humidity and light sensors, though only after testing them out properly on a breadboard first, to make sure that they're sensitive enough to be of use throughout the whole range of humidities and especially light levels they will experience.
Natural illuminance spans many orders of magnitude - a non-moonlit night can be as dark as 10^-4 (0.0001) lux, while direct sunlight can reach >10^5 (130000 or so) lux. The sensor would hardly need to give accurate readings for each of these extremes, but it should be able to tell the difference between ~10-30k lux (daylight, but not direct sunlight) and ~30k+ (direct sunlight) - something that might not be possible with a simple circuit, as they might get saturated too early.

Everything else

Everything major is mentioned above, and only three small things remain.

One is the LEDs (power, network status and general status).
The power LED is simply wired between 5 V and ground, with a current-limiting resistor, of course.
The others are wired from 5 V to microcontroller pins, again with current-limiting resistors.
You can wire them up either way: 5 V - LED - resistor - µC pin, or µC pin - LED - resistor - ground.
In the first case, the LED lights up when the pin is low (and sinks current), and in the other, the pin sources current when the pin is high.

I'm not using the ADC for this project (if I do end up with that daughterboard, I might use an external ADC for added precision and noise, rather than dragging that sensitive low-level analog trace across 5 inches of PCB), but I still made sure to make it usable, just in case.
By having a decoupling capacitor between the AREF (analog reference) pin and ground, rather than connecting AREF straight to the 5 V rail, you can select between the internal voltage reference and 5 V, in software.
If no external voltage is applied to the AREF pin, the user may switch between AVCC and [internal] 1.1V as reference selection.
Left are... the test points. Whoop-ti-do. I chose a model that looked nice for hooking on oscilloscope probes. What I didn't quite add properly was a ground pad, for use with the ground spring (when you want better measurements, by not using the relatively long, inductive ground clip).
I'm not sure there's much more to say on this subject, but they are Harwin's model S1751-46.
There are also two test pads on the PCB for 5 V and 3.3 V, intended for multimeter use.

Next up: PCB layout and enclosure planning

Well, that's about it for this time!
These posts turn out longer than I anticipated when I first got the idea to blog about this project.
The next post will be, as stated above, about the PCB layout and enclosure choice. See you then!