Introduction: USB Indoor/Outdoor Thermometer (or, 'My First USB Device')
This is a simple design that demonstrates the USB peripheral on the PIC 18Fs. There are a bunch of examples for the 18F4550 40 pin chips online, this design demonstrates the smaller 18F2550 28 pin version.
The PCB uses surface mount parts, but all components are available in through hole versions. I use surface mount parts because its faster to make the board without drilling holes.
The end result is a small USB peripheral that measures indoor/outdoor temperatures. Data is available to the PC through a virtual serial port. Temperature sensors are used in the example, but other analog sensors can be added.
See a live graph of the data from my logger here:
Step 1: Design Overview
Required PIC components
This USB peripheral is based on the 28 pin PIC 18F2550. This chip has everything needed for a full speed USB interface.
A 0.1uf capacitor between power and ground decouples the PIC from the power supply.
A 20MHz crystal (used to generate a 48MHz internal clock) and two 27pf capacitors.
A 10K resistor from power to the MCLR pin. I added a 1n4148 equivalent diode between the resistor and power so that the 13+volts placed on MCLR during programming doesn’t damage other components on the circuit board.
An ICSP header (5 pins) is used to program and debug the device.
Required USB stuff
A USB female ‘B’ style socket.
220nf-440nf of capacitance is required for the internal USB voltage regulator. I use two 0.1uf capacitors (same as used for decoupling) without a problem.
A LED with 330ohm current limiting resistor is used to display USB connection status.
Required sensor stuff
I used the microchip TC1047A temperature sensor as the indoor temperature sensor. It is physically soldered to the board - this causes it to run a few degrees hotter than room temperature.
A header is used to connect an outdoor temperature probe (TO-92 version of TC1047a). An additional 0.1uf capacitor helps decouple a long wire run from the rest of the board.
USB voltage levels are not consistent enough to accurately measure and compute temperature from the analog sensors. An external voltage reference (MCP1525, 2.5volt) is used. The voltage reference requires a capacitor on the output of 1uf to 10uf. Without this capacitor the voltage reference will not work.
Step 2: Firmware
The firmware uses the CDC USB class to emulate a serial port. The device will show up as a virtual com port on a PC. The firmware is broken into three sections:
1. The USB driver takes care of enumerating the device on a PC and emulating a COM port.
2. A service routine alternately reads the temperature values and converts them to a readable format. Doing both of these operations at once caused the USB device to loose connection the PC (time hogging). Converting the floating point values to a string in the service cycle following the conversion cleared up the connectivity problem.*
3. Finally, a main routine receives bytes sent from PC and returns the requested measurements. Multiple measures are separated by a comma, lines are terminated with a null character (hex 0x00)
The demonstration firmware accepts the follow commands:
Hex value Returns
0x00 Indoors temperature (on-board sensor)
0x01 Outdoor temperature (external header)
0x02 Both temperatures (comma separated)
Temperature is calculated based on the 2.5 volt reference and the Microchip TC1047A offset and slope. Other temperature sensors may have different characteristics. The TC1047A datasheet is available here:
The firmware is written in MPLAB with the demonstration PIC C18 compiler.
The actual USB firmware is provided by Microchip. The original environment is available here:
To edit the firmware: extract the entire directory structure of the source to your root directory (c:\MCHPFSUSB). You can then load the workspace file in MPLAB.
*The float to string routine is a resource hog. To get around the connectivity problem the USB service routine is called at various points in the float2string routine. This would best be fixed by servicing the USB peripheral on an interrupt. I used the hack so that the firmware stayed as close to the reference version as possible.
Step 3: Testing the Device
Instructions are for windows, but the device can be connected to anything that has CDC serial port emulation drivers.
Program the device with the firmware. All configuration bits should be set correctly in the firmware.
Plug the device into a USB port. Windows will detect it and prompt you to choose a driver. BE SURE TO CLICK ‘BROWSE FOR CUSTOM DRIVER’. Navigate to the location of the .inf file included with the project archive(driver-win2k_winxp). Windows will use this file to install the device.
*A note on the CDC driver – the CDC serial port emulation driver is included with Windows. The .inf file (provided by Microchip) simply tells Windows to connect these drivers to the device.
To find out what COM port the device was assigned do the following:
Go to the control panel (start->settings->control panel)
Double click ‘system’
Click the ‘hardware’ tab.
Click ‘device manager’
Click the ‘+’ next to ports
A list of COM ports on the system is shown. I have seen the device show up as COM 3 and 4, but it will vary by system.
If its not obvious which port is new, try this:
Unplug the device from the USB port.
One of the ports will disappear. This is the device’s COM port #.
Plug the device back in, the port will reappear.
The small VB application (source included) can be used to test the device. Enter the command to send, click 'Start'. The reply will be shown in the window.
Step 4: What Else Can It Do?
This demonstration board is a good starting point for a small home weather station:
Add a HIH3160 humidity sensor, or replace the analog temperature sensor with the Sensiron HT74 high accuracy serial temperature and humidity sensor.
Add a Freescale MPX(a)4115 pressure sensor to measure barometric pressure.
Want to syndicate this data to web? Include it in your own website, view it in google earth, or get updates in your RSS reed? See this instructable on integrating this device with the syndicIT.com web backend: