Sunday, December 30, 2012

Dew Controller (Software)

This post is the second part of the Dew Controller.  Corresponding source code (one ino file) can be found here:


As described in the previous post, the controller uses several different communication protocols such as I2C, 1-Wire, and SPI, it starts with the following lines


Writing data or command to the LCD can be done by

Here data can be command code or character codes you want to display on the LCD. However there is one thing should be fixed. According to the LCD manual, maximum allowable clock speed of the I2C communication is 100KHz. But you might get a lot of unstable behavior in the communication in that speed. So it is safe to lower the I2C clock speed.

If you refer to the file


You can find the following line

However Arduino does not provide any convenient way to override this setting. So just replace the line with the new speed setting (50KHz in this case).

If you use the function provided by my code, you can show initial screen below with these lines of code.

You can turn on the backlight as in the 718th line above. But as explained before, the backlight consumes a lot of power, it will burn the 5V regulator if it is turned on for a considerable amount of time.

The function slcdRoutine() takes care of this and it will automatically turn off the LCD if the LCD has been turned on for certain period of time.
This routine should be called from inside of your loop function


Speed of ADC module in this type of low cost sensor is extremely slow. In the case of DS18B20, it takes around 750msec to finish the conversion. Either you have to do nothing but wait for this period or separate the procedure of conversion start command and actual reading of the results. 

In the code, at every odd second of time conversion start command is issued and at every even second of time, the results are collected. So you don't have to insert useless idle loop between those two events.

At each odd second, the conversion commands for two sensors are issued.

And at every even second the results from both sensors are collected. This code is for the DS18B20 sensor

And this is for the HIH6131 sensor

Actual data collected from the sensor should be converted into meaningful data via some floating point calculation, which is not desirable for low-end mcus like ATmega328.  In the code all the temperature data are multiplied by 100 to have integer values instead of floating point values. You only have to take care of it when you display it.

So the following picture, actual temperature variable has 2185 as its value but it is displayed as 21.85 when it is shown on the LCD.

Dew point is calculated from the ambient temperature and relative humidity. Both values are measured by the HIH6131 sensor. And it is compared to the mirror (or eyepiece) temperature measured by the DS18S20 to figure out when the condensation might occur.

In the following picture, we can expect that if there is no changes in the humidity condition (amount of water molecules in the air), then we will get condensation at 12.25 degree. In actual situation, this dew point should be updated frequently to forecast the condensation condition accurately.


Heater should be turned on if the condensation condition is expected or the dew point is approaching.  In the code, at every second the mirror temperature is compared with the calculated dew point and turn on or off the heaters.

Note that the control of the heater is done by the simple digitalWrite() function instead of PWM output (analogWrite() function). You don't need PWM output because you have a closed-loop control system(mirror temperature feedback). If the dew condition is met, then turn on the heaters. And if the condition is cleared then turn off the heaters. It is as simple as that when you have the closed-loop control structure.

At the same time, the battery voltage level is read by ADC module to provide information about the battery life. Internal ADC module runs fast and takes only insignificant of time compared other operations. So, the ADC reading operation is embedded in the code that displays the heater on/off status.

Note that the battery reading is divided by 2. Actual value of the reading has no meaning itself but should be adjusted together with the potentiometer to get actual voltage value. So, dividing the reading by 2 is just for the convenience of the code.


If you refer to the schematic, you will find that one digital input is dedicated to check the presence of a SD card. This is required because you are not supposed to initiate the SD file system unless there is a SD card present. Otherwise the whole SD routines will be messed up.

SD card check is included in the timer routine and its state is update at every second. Be sure not to pull out the card once the controller recognize the card and start the file system.

Data logging is done for every 1 min (60 second). At the logging moment, display will show the data writing action or it will display the error when the error condition occurs.

The Sys Tick above is just second count ever increasing from 0 when it is powered up.  Since this controller has no battery backup and no dedicated real time clock, counting seconds is most convenient way of doing time keeping. The code uses millis() function to get 1 second. So if you need to keep the data with actual time stamp, then you have to record the moment when you powered up this controller.

Dew Controller(Hardware)

This project is inspired by someone who has good understanding about amateur astronomy. He actually gave me detailed conceptual design and I only implemented it. 

Instead of explaining what it is (and what it is for), you can refer to an excellent prior work.

One of the possible issues I could expect from the above is the humidity sensor that will be addressed later down there. But most of all, it was the fact drove me into this project that this will utilize many peripherals and libraries of Arduino, so it will demonstrate how much your Arduino can do while not requiring too much in-depth knowledge about hardware and software.

Here is the picture of the controller.

It is designed to
  • operate on 12V battery,
  • monitor the battery voltage level,
  • have 2 line character LCD with backlight as a display,
  • have rotary encoder with a pushbutton as an input device,
  • control up to 6 heating strap,
  • have 1 combo (temperature and humidity) sensor for sensing ambient condition,
  • have 1 temperature sensor for sensing the mirror temperature,
  • have a SD card interface to log all the sensing data during its operation,
From the hardware perspective, it consists of ATmega328/328P (Arduino Uno) with
  • a serial character LCD with backlight (SPI interface)
  • a linear regulator for 5V power,
  • an LDO for 3.3V power
  • a SD card interface (with a level converter)
  • a rotary encoder with pushbutton (digital inputs)
  • a HIH6131 combo sensor (I2C interface)
  • a DS18B20 temperature sensor (1-Wire interface)
  • an ADC input for voltage monitoring (analog input)
  • 6 FETs (digital output)
So, it is indeed one good example of utilizing most of the Arduino Uno. For the sake of compactness, the controller is built with a ATmega328. However, one can use Arduino Uno/Mega instead without any difficulty. The schematic can be found here.

The character LCD goes on top of ATmega328 and 74LVC245

Back side of the board is a bit messy. But  if you use Arduino Uno, it should be much simpler than this.

Each part of the circuit is explained below one by one.


This converts 12V battery input  into 5V and supplies the main power of the circuit. It is included in the Arduino boards. LM317 is used for no particular reason but the instant availability. Popular 7805 will do the same job. However you have to expect fair amount of heat from this part if the backlight of the LCD is being turned on for a long time. 

Basically all the linear regulators including LDOs are dissipating ohmic loss during regulation. For example, if the regulator converts 12V input to 5V output (7V drop) with 250mA, which is the typical current consumption of the backlight, then it will dissipate 7 x 0.25 = 1.75 Watt. That will burn! And the regulator could not sustain that amount of power without a proper heat sink. So, the backlight should be turned on for only a short period of time and should be turned off automatically via software.

One thing you may want to remember is not to be fooled by such specifications like absolute maximum ratings. If an IC consumes 1Watt of power, then it dissipates 1Watt of heat. And that 1Watt is pretty much the maximum an semiconductor can handle without a heat sink.


This converts 5V into 3.3V to supply power to the SD card interface. SD cards operate on 3V3 only, so it is required to provide 3V3 power. And it is also required to use proper 5V - 3V3 logic level converter, which will be discussed later.


Since ATmega328 IC is used instead of Arduino Uno, an interface should be prepared for the  programming tool of choice.  This port is for the TTL-232R cable, which I mentioned before in this blog.


Considering limited pin count of Uno, an character LCD with serial interface is only feasible option in this case. This LCD is equipped own CPU(PIC16) and can handle a couple of serial interface protocol such as I2C, SPI, and UART.  Since SPI and UART are dedicated to the SD card interface and the programming port respectively, I2C protocol is selected. Be sure to pull up the I2C bus signals for proper operation if you are not using Arduino board.

When it comes to the (serial) LCD, there are a lot of choices. But only a couple of them can operate under such environment like below freeze. You may want to find 'Wide Temperature' version of LCD if you are considering outdoor use. This particular LCD claims that it can run as low as -20 degree. 


This is a rotary encoder with an additional pushbutton switch. From the hardware perspective it is a collection of 3 SPST switches. By combining ROT_R signal with ROT_L signal, you can detect which direction (CW or CCW) the rotation occurs. The center pushbutton switch operates independently.

This switch can be a good input device especially when you are thinking about hierarchical menu structure. You can map CW or CCW action to navigating a certain level of menu and map the center button to  moving one level upward or downward in the hierarchy.


Dallas (now Maxim) DS18 series sensor is used for sensing mirror temperature. The measurement from this sensor should be distinguished from the ambient temperature measured by the HIH6131 sensor below. It is the mirror (or eyepiece) temperature the sensor is measuring, which is controlled by the heater strap. This temperature should be compared to the dew point to ensure that the mirror is dew free. The dew point is calculated from the ambient temperature and the relative humidity, which are measured by the combo sensor below.

The sensor has Dallas 1-Wire interface. It is designed to be long enough to reach to the point on which it is measuring the temperature.


There are several humidity sensors (or temperature/humidity combo sensors) available out there. But  you have to be careful when you are using those in the outdoor environment. Most of the humidity sensors are designed for stable and controlled humidity conditions. If it is exposed to the environment such as condensation, it stops functioning or even gets permanent damage. If not, it requires factory reconditioning to function again. Do check the specifications carefully before you grab one.

Honeywell HIH6131 is one of a few (probably the only available) humidity sensors that can be used in the outdoor environment. It has hydrophobic filter on the sensor so it is condensation-resistant. It uses I2C interface.

It is mounted on the end of the plastic cylinder. And this sensor module is plugged into the controller via a 4-contact audio jack.


When it comes to the SD interface, you should be able to find all the information you need here:

The above circuit may differ only because I used the parts readily available. Actual part number of the buffer above (denoted by 74LS245N) is 74LVC245 which is 3V3 logic and is tolerant to 5V signal. So all the outputs from the ATmega328 (SEL, MOSI, SCK) should be converted to 3V3 level via 74LVC254. Output from the SD card(MISO) is 3V3 level, so it can be connected directly to the input of ATmega328.  One additional signal SD_DET is required to check if the SD card is present


12V voltage level is measured by an analog input port (A0) of ATmega328. Since the maximum input level that the Aruduino can take is limited to 5V, a potentiometer is used as a simple voltage divider.


When you choose a MOSFET as a power switch, you may have to check the ON resistance of the FET with respect to the gate voltage. In most cases, nominal turn-on gate voltage of power MOSFET is 10V or higher. These do not show very good performance if you control them directly with a mcu such as ATmega328. You need to find logic-level FETs.

PSMN022-30PL is a cheap logic level MOSFET. It shows very low on resistance at 5V gate input.

Although in the schematic the control signals of the FETs are denoted as PWMx, they are not the PWM signals that actually control the FETs. As it will be explained in the next post, you do not have to use PWM signal to control the heater strap because the mirror temperature sensor provides closed-loop control scheme.

Monday, October 29, 2012

Build Arduino CLI Environment with Vim

I found the Aduino Sketch is a quite inconvenient, not to mention the ugly GUI. I hate the Java font rendering on Linux (and Eclipse too for that reason). It is not an development environment actually but an awkward and obscure Java wrapper for a couple of command-line tools. So, I was delighted when I found the CLI(Command Line Interface) for Arduino.


Thanks to the arduino-cli , I was able to get rid of the Sketch and made my life much easier. If you are using Debian based Linux including Ubuntu and its variants, then you can install it by

$sudo apt-get install arduino-mk

As of Sep. 17, 2012, version 0.10 was released and the repository was not updated yet but the version 0.8 is still working very well with the recent version of Arduino (v1.0.1). So just go for the official package of the arduino-mk.

If the install was successful, the only thing you have to do is to create a simple makefile for your project (*.ino), which might contain the following lines

ARDUINO_DIR = /usr/share/arduino
BOARD_TAG = <your Arduino board>
ARDUINO_PORT = /dev/<your Arduino port>
ARDUINO_LIBS = <libraries of your choice>
include /usr/share/arduino/

So, actually all the makefile scripts required is in the file


That script will search for your *.ino file in the current directory and do the build job. For the BOARD_TAG parameter, you can choose one from the output of

$ard-parse-board --boards

Or, instead you can use your own settings by specifying parameters such as


With those few lines, your CLI environment should work like a charm. You can build your sketch:


You can upload it via the Arduino port:

$make upload

Or you can use your ISP device to upload:

$make ispload

in which case, you may need to specify your ISP tools:

ISP_PORT = /dev/<your ISP device port>
ISP_PROG = <your avrdude parameters>

For more information, you can refer to the manual comes with the package


or visit the author's page.


Since the extensions of Aduino source files (*.ino or *.pde) are not recognized by vim, it is likely that  you see a plain text-like screen when you open up the arduino file with vim. So it is time to set up the filetype settings of the vim for the arduino sources, which is well documented here.

First, in case you don't have already, you need to create a custom filetype file


with the following contents

" custom filetypes
if exists("did_load_filetypes")
augroup filetypedetect
    au! BufRead,BufNewFile *.ino setfiletype arduino
    au! BufRead,BufNewFile *.pde setfiletype arduino
augroup END

then download the syntax scripts (arduino.vim)


into the following directory


Finally, you may want to create your own filetype plugin file


which should be quite similar to C or C++ filetype plugins naturally. Mine is

setlocal tabstop=4
setlocal softtabstop=4
setlocal shiftwidth=4
setlocal noexpandtab
setlocal autoindent
setlocal smarttab
setlocal errorformat=%f:%l:%c:\%m
setlocal makeprg=make
setlocal makeef=/tmp/vim##.err

Thursday, September 13, 2012

Relay Control 101

Sometimes, certain things are not as simple as it looks, particularly when you expand your program knowledge into the real worlds. For example, if you want to implement your idea into action, then inevitably you have to deal with the actuators, which convert electrical signal into mechanical action. Solenoids and relays are the most common form of the actuators. But it is not as simple as you might guess if you do not have certain knowledge about electricity and electronics.

Please bear in mind that there is no such thing as '1' or '0' in real world. Everything is analog.  When you say '1' or '0',  what goes in the mind of hardware engineers are slew rate, jitter, heat dissipation, voltage drop, EMI effect, and so on. Situation is the same in the relays. I'm not going to discuss much details about the relay and its control. However, most of the topics here should be considered if you do not want to fail your Arduino project with your relay circuit or off-the-shelf relay shields.


There are basically three types of relays are available in terms of control. Most popular type is N.O. (normally open), whose secondary circuit (as a switch) is open when there is no signal (actuating current) in the primary side(as an actuator). Contact is made by flowing certain amount of current into the primary side and it keeps its state as long as you maintains the primary current.

N.C. (normally closed) type relay operates in exactly opposite way. It opens the secondary circuit when you apply current to the primary coil otherwise it remains closed.

Then there are third type of relay, what they call latching relay. Once it operates by the control signal, it holds its position even after the control signal is removed. So, naturally you need two distinctive signals for ON action and OFF action, respectively.


You cannot drive relays directly with the (output) port of the Arduino even if the relay operates under 5V control signal. Because not only its output driving current of the Arduino is limited but also the maximum voltage it can take is much lower than desired. Like solenoids, the primary circuit of a relay is nothing but a coil, so it generates high voltage spike when it is turned off to dissipate its electromagnetic energy abruptly. Output of the relay drivers should be protected by snubber circuits, which is also called fly-back or freewheeling circuits. In most cases, circuit for this coil suppression technique is as simple as single diode across the relay primary coil.

The left circuit shows typical output stage of a relay driver, where L1 represents the actuator coil. This simple fly-back diode will do the job. But it is also known that this may reduce the life of the relay. The right hand side circuit can be found in more elegant designs.


As almost all the mechanical switches do, relays are vibrating when they operate. You may already familiar with this phenomenon if you've had a chance to play with tact switches.  Since the contact switches in the secondary side of the relays usually deal with higher ratings of current, the chattering will severely aggravate the contact arc phenomenon, which directly related with the life of the relays. For D.C. loads, an arc-suppression capacitor can be used across the load.

However, if the secondary circuit is A.C. then you have to consider the zero-crossing detection scheme, which basically detects the A.C. waveform and synchronize the relay switching action at the zero-crossing point of the A.C. power, so you can minimize the contact arc phenomenon. Many zero-crossing detector circuits are out there for this purpose but designing a reliable and energy effective zero-crossing detector is not trivial at all.

Besides, if the load is significantly reactive(inductive), in other words, the power factor of the load is far less than 1, then you also have to consider the phase shift effect (phase lag) of the current waveform. Otherwise it is highly likely that the relay will stick (contact fusing) in just a few operation. Electric motors and CFLs (compact fluorescent light) are good examples of such inductive loads. Low power factor (around 0.6) of CFLs is not only the concerns of hydro companies but also it will give you a headache if you try to control the CFLs in your house with a simple relay circuit.


If you don't have much experience in real applications. Then one of the most unexpected (but quite apparent at the same time) thing might be the fact that the relays are generating heat when they operate. Heat dissipation occurs in both the primary circuit (ohmic dissipation in the actuator coil) and the secondary circuit(also ohmic dissipation mostly at the contact point).  If your relay circuit is open or has good air flow, then it hardly make any issue. But if you enclose the relay circuit completely then you have to carefully calculate the power dissipation of the circuit. In that case, you will find that the data sheet of the relay is quite useful for the problem. For example,  if the operating condition of the relay is 100mA at 12Vdc, then that single relay will spend 1.2W continuously when it operates. It is not completely safe to ignore even the 1W of dissipation if it is in the air-tight enclosure.

Easiest way of dealing with this is to use the latching relay, which does not require any current to maintain its current state. So, heat dissipation of the latching relays is significantly lower. However, latching relays are more expensive.

Common trick is to reduce the actuator coil current after the contact is made. If you check the data sheet of the relay, you will find that the current required to operate the relay and the current required to maintain the contact are not the same. For example, you have to apply 100mA to make the contact, then you can safely reduce the current to 60mA maintaining the contact. Of course in this case, you need current control scheme in your relay driver. Many dedicate relay drivers are equipped with such capabilities.


The final and the most important thing you have to remember is that all relays will fail eventually for a number of reasons. So, it is almost mandatory to prepare backup or safety measures especially when your project is mission-critical.

Wednesday, June 13, 2012

Another minimal Arduino implementation

If you, for some reason, have to deploy many Arduino kits, then you may want to consider the minimal configuration of hardware for your Arduino environment to work. And, there are a lot of articles dealing with this subject on the web. Here is another.

I happened to have a FTDI TTL-232R-3V3 cable, which is being used to program various other MCUs such as propellers. Left of the circuit is 3V3 power supply. That is required because the FTDI cable is for 3V3 logic. If you have TTL-232R-5V, then you can provide the power directly from the FTDI cable. The tact switch on the bottom right is optional. In fact, the 16MHz crystal circuit (crystal with two stabilizing capacitors) is also optional. ATmega328 works quite well with its internal RC oscillator(8Mhz). If the accuracy became an issue, then you can fine-tune the oscillator.

Actual connection between the FTDI cable and the mcu is quite simple.

The RTS connection is to give an reset to the mcu when uploading as real Arduino boards do. Someone might think that the reset should be connected to DTR rather than RTS, which the FTDI cable does not have. But if you dig into the avrdude source, then you will realize that RTS and DTR act together by the command:


So in fact, the autoreset feature works with the RTS connection as well. If it does not seem to work, then it might be the case that R1 is not big enough so the reset pulse is not formed very well. In that case raise the value of R1 to 47K, for example.

Sunday, June 10, 2012

Implementing your own touch screen control

Most of resistive touch screen sensors mounted on small size TFT LCD do not come with dedicated controllers. Only 4 sensor lines directly from the sensor are exposed. So, you need to connect the sensor to the ADC lines of the MCU and implement your own touch sensor algorithms.  In fact, Arduino MCUs are far more capable than the dedicated touch screen controllers, you can expect better performance. Instead, you have to assign 4 ADC lines and some of MCU computing resources.

While there are a lot of articles about the principle of resistive touch screens and there usage in the internet, you can find an excellent article about this here. Most of the contents in this post came from this application note.


As mentioned above, a resistive touch screen sensor provides 4 sensor lines, usually denoted X+, X-, Y+, and Y- or XP, XM, YP, and YM. These lines are connected to the end bars of resistive films and this can be modeled by the following equivalent circuits.

Connect 4 sensor lines to the 4 ADC input of ATmega. Then you can measure various values of the sensor via different measurement configurations, which can be controlled by port settings and ADC channel settings of ATmega.

Here Z1 and Z2 represent the area of touch rather than the pressure of touch. And it is not reliable and accurate enough to be used as any quantitative measurements. But it is still quite useful to detect the touch status in some way.

More specifically, you can capture the event of touch by setting the ports for PCINT input configuration. It works very well when you want to detect the starting moment of touch or touch as a single event. But this method is useless in the middle of touch action, for example to track continuous movement of touch for drawing a contour.   In this case, you need another method to figure out that the touch is maintained or not. This Z value is a good measure for that purpose. It makes your touch sensing much more reliable. This will be demonstrated in the video at the end of this post.


In the touch library (SdcTouch), these two methods are demonstrated. For detecting a single touch event, you can call:


This function wait indefinitely until user touch event happens. On the other hand,  to check the touch status continuously, you can use:


This function returns immediately with true or false as its return value. The Z value is used here to detect the touch is going on or not.

Just like any other touch library, the first thing you need to do is to calibrate your touch sensor to match the sensor value with your TFT LCD screen coordinate. This can be done by running the example sketch Calibrate. This program takes 3 reference values, calculate the calibration parameters, and save it to the EEPROM area of the ATmega. So, once you finish the calibration, you don't need to repeat it.

Following video shows some simple demonstration using the touch library(SdcTouch) and the LCD library(SdcLCD). As you can see in the video,  tracking the stylus is done smoothly. As always you can download the library here.

(For some reason I don't know the video is unsearchable in the YouTube. You can go directly here for the video.)

Monday, May 28, 2012

Faster image display on TFT LCD

With the SD card FAT library and the LCD library, you can easily do a slideshow of BMP images on the LCD. It was already demonstrated in the previous post. It is as easy as copying a block of data into the LCD frame buffer. This simple function might have many use in real applications for displaying icons, stock images, and backgrounds wallpapers.


If you check the actual code, which reads BMP files from SD FAT file system and displays them on the LCD screen, you will realize that  each and every pixel is being converted from 24bit BMP pixel into 16 bit 565 LCD pixel format. Naturally, this conversion process takes up a large portion of the total time taken for the display.

If you have the image data in native pixel format, then you don't need the pixel conversion routine. And you will get much faster display speed. So, define your own image format. It is still raw format like BMP, no compression is involved here, but each pixel is stored in  RGB565 format. And convert BMP files into the native pixel format in the desktop. You can find a conversion utility here. Details are omitted. But it is quite straightforward.

You can see the result here.

For 320x240 full size images, it takes about 1 second to display each BMP format images, whereas it only takes less than 0.5 second with the native format. Speed is doubled.