circuitcellar.com
Magazine Support   Digital Library   Products & Services   Suppliers Directory 
 
 





 

January 2007, Issue 198

Self-Powered Solar Data Logger


by Abigail Krich


PROGRAM

An interrupt-driven program runs the system and enables accurate timing. An interrupt service routine decrements a series of task timers once per millisecond. The main task in the program calls various subroutines at predetermined intervals when their task timers run out and the appropriate flags are set to enable a task to run. Each of the eight buttons is polled separately once every 30 ms with a state machine to debounce the button as it stabilizes after a transition. The only button that is not debounced is the LCD Wake button because bouncing is not a concern with this function. The debouncing routine is based on code written by Bruce Land.

Each time the system is turned on or reset, it welcomes the user and guides her through the set-up process (see Photo 4). During set-up, you set the system time and date, select the logging frequency, decide whether to clear any stored data or to continue by appending future data, and indicate when to actually begin logging after the system is in place.

(Click here to enlarge)

Photo 4—The data logger greets users before leading them through the system setup.

In order to enable data appending after a reset, the memory pointers have to be stored in nonvolatile memory and initialized only when the chip is programmed, not each time the system is reset. The ATmega32 contains 1,024 bytes of data EEPROM memory organized as a separate data space in which single bytes can be read and written. The pointers to the flash memory as well as a log of how long the system has been logging are kept in EEPROM. During operation, you can reset the time if needed or change the logging frequency without interrupting the data collection. If the logging frequency were changed, it would be impossible to calculate how long the system had been logging unless a running tally had been kept.

A series of flags and state machines are used throughout the program to prevent erroneous user input from activating a section of code out of order. At any given point in the program, only the relevant buttons are active and their functions change as shown in the button labels in Photo 5.

(Click here to enlarge)

Photo 5—Check out the STK500 board with labels for each of the eight buttons.

The battery voltage and the photodiode output are fed into two channels of the ATmega32’s ADC. The ADC has a maximum input of 5 V. So, in order to read the battery voltage, it was necessary to use a voltage divider to guarantee that the input to the ADC was within range. Initially, the system sampled only the light level with the frequency at which the user wanted data stored. However, with logging frequencies of 1 min. to 1 h, this did not allow for a satisfying real-time display that showed changes in light intensity. Moreover, it allowed less accuracy if only one sample was taken per stored data point. Instead, the final design reads the ADC once per second through a task that enables an ADC interrupt routine and starts a conversion. The ADC interrupt automatically switches between the two channels for the photodiode and the battery voltage, reading the battery voltage once for every five times the photodiode is read.

To get an accurate battery voltage reading, the PV panel is disconnected just before the reading is taken and then reconnected immediately after if the battery voltage is below 13 V. If it is at 13 or above, the PV panel is not reconnected to prevent overcharging.     

The instantaneous readings are displayed to the LCD screen and kept in a running average over the logging interval. When the logging interval is complete, a data point is stored in the flash memory and the running average is cleared.

To be able to run for a useful length of time, the data logger needed an external memory for storing measured data. The older STK500 boards have flash memory chips built into them (as can be seen on the upper right of the board in Photo 5), making this an obvious choice. Unfortunately, I did not have any instruction set for interfacing with the flash memory. An earlier ECE476 project used this flash memory. Based on the project’s code and comments, I was able to learn how the flash memory interface worked.[3] The designers used a program named dFlash, which was written by Terje Frostad of Atmel Norway. I e-mailed the Atmel AVR technical support team and received permission to use dFlash in my project as well. The dFlash program provides a set of routines to interface with the flash memory by writing to a 264-byte buffer. This buffer is then written to one of 1,024 264-byte pages of the flash memory.

Because the routines take byte-size data as input, I had to break the insolation value (stored as an integer) into 2 bytes and then put it back together again when storing or retrieving it. The 2-byte insolation together with the time and date stamp meant that each time the system logged a data point it used 8 bytes of memory. This allowed the system to log 33,792 data points. The logging interval is user-selectable from 1 min. to 1 h. At an interval of 1 min., the system is able to continuously log data for 23.4 days before filling the memory. At an interval of 1 h, the system is able to log for 3.8 years.

One thing I did not realize that caused me a considerable headache was that PortB.4:7 is used for interfacing with the flash. I had initially been using PortB as input for the switches, but I found that three of the switches ceased functioning properly. When I realized that dFlash was reinitializing these pins, I was able to switch these buttons to PortA.

The flash memory can be read either through a buffer or directly, the latter being my choice for the logger. If you were to call for the data to be retrieved before the buffer had filled and written the data to flash, there would be no data to retrieve. Thus, it was necessary to write the buffer to flash memory just before the data retrieve routine was entered as well as when the buffer became full. It was also necessary to give the microcontroller a brief period to finish writing the buffer before the read command was executed or the same problem would occur.

The read command is executed when you press the Retrieve Data button (active only when the logger is stopped). The logger must be connected to a computer using an RS-232 cable with straight-through connection. You should start a simple terminal program on the PC (e.g., HyperTerminal) set to 9,600 bps, no parity, 1 stop bit, and no flow control.

When the Retrieve Data button is pressed, the system prints identifying header rows followed by a row for each data point logged with the time and date at which it was stored. The LCD displays the message “Uploading Data” followed by the time and insolation value presently being uploaded. Upon reaching the end of the data, a footer row is printed to the terminal program and the LCD displays the message “Done Uploading Please Restart.” The data in the terminal program on the PC may then be copied into another program for storage or analysis. If an incomplete transmission was made, you may reset the logger and choose to upload the data at the first prompt. The data may be uploaded as many times as the user desires until the memory is cleared.

Initially, the program was written with each of the subroutines that updated a parameter sending its update to the LCD. This avoided updating the LCD more frequently than necessary. However, when power-saving code was incorporated to turn the LCD screen off when the system was idle by driving it with a port pin, the system would freeze every time it went idle. It turns out that the LCD sends and receives messages to and from the microcontroller. If the LCD is off when the microcontroller sends it a message, it is not able to respond and the microcontroller hangs, waiting. The program thus had to be rewritten to prevent the LCD from being called when the LCD screen was turned off. I did this by writing a single routine that printed to the LCD screen. A state machine and a variety of flags controlled it so that the correct message would be displayed.

Additionally, there was some difficulty at times with the LCD not making proper contact with the surplus whiteboard I was using. When the LCD lost contact momentarily, it would cause the system to freeze. Thus, I added an extra new whiteboard solely to hold the LCD screen securely because I was not able to solder the borrowed LCD to my project. Another problem I had with the LCD was when the STK ground was not properly connected to the system ground, the negative terminal of the battery. This happened during testing with the STK500 plugged into an AC/DC power supply. When the two grounds were not at equal voltages, the voltage across the LCD was not in its operating range. The positive voltage was coming from the STK port pin and the negative voltage from the battery negative terminal. Once the two systems were joined by connecting to the STK ground pin (or also powering the STK from the battery), the LCD resumed normal operation.