GPS Solar Tracker (1)

MTM Scientific, Inc.

This series of webpages describes a GPS enabled solar tracker based upon the STMAX tilt-tilt platform design. The STMAX solar tracker controller is described in much more detail at http://www.mtmscientific.com/stmax.html, and also in our book "Build a Solar Tracker".

Briefly: The STMAX Solar Tracker is unique because the tilt-tilt design of the mechanical structure allows the use of a MEMS gravity sensor module to easily measure the tracker's aiming direction. In the STMAX design a special sun sensor and search algorithm are used to accurately find the sun in the sky. Once located, the sun's position is recorded with reference to an onboard clock, and the process becomes more efficient and rapid as the software learns the sun's daily sky path.

STMAX dual axis tracker
Figure 1. The STMAX Dual Axis Solar Tracker

Instead of using a sensor to find the sun, the apparent position of the sun in the sky can be calculated based upon the time and location of the observer. A GPS module is capable of providing the time and location information. However, the actual calculation of the sun's position requires a microcontroller capable of performing trigonometric math. The STMAX solar tracker controller uses a Picaxe-20X2 microcontroller. The Picaxe-20X2 microcontroller is capable of receiving the GPS information and is also capable of calculating the sun's position. This webpage describes how to acquire the GPS data. We will be publishing additional webpages to describe the calculations ( Page 2: Calculate the sun's position ), and also how to move to the correct aiming position using a MEMS gravity sensor module for feedback.

GPS Data Acquistion

GPS stands for "Global Positioning System". A network of satellites is in orbit around the earth and the satellites transmit radio signals which can be used for position location. These same satellites also transmit the date and time. The radio signals from the satellites can be received with a compact and inexpensive stand-alone electronic GPS module. The GPS module receives the signals, calculates the time and position, and transmits the data to the user via a simple RS-232 serial message protocol. The Picaxe-20X2 microcontroller is capable of receiving the serial data stream. ( External Link: Make a GPS Clock with Picaxe )

In this project we are using the EM-411 GPS module from Globalsat Technology Corporation. This particular GPS module is a self-contained device: complete with internal antenna, calculation engine and serial stream output... all in a tiny 3cm square package. The EM-411 is available from www.dx.com ( Datasheet: EM-411.PDF ) The GPS module begins signal acquisition when +5VDC power is applied. When the GPS signals are correctly received a red LED on the module begins to flash. The module transmits the  the information as a continuous string of RS-232 messages. The format of the text messages is called 'NMEA', which stands for National Marines Electronics Association.

GPS Module EM-411
Figure 2. The EM-411 GPS Module

Each message from the GPS module is preceded by a text string identifier. In this project we are using the text message identified by the string "$GPRMC". The serial data strings are transmitted at 4800 baud with 8 data bits, no parity and 1 stop bit. (Note: Serial data protocol is discussed extensively in our book "Build A Solar Tracker".) The Picaxe-20X2 microcontroller easily receives this serial data protocol.

The serial data stream conveys the GPS information as a string of text data separated by comma delimiters. Our code must receive the data string, and then parse the information to extract specific data for calculating the sun's position. So briefly, the code: 1) Watches for the text string "$GPRMC", 2) Stores the text data string after the header is identified, and 3) Parses the data string to extract the needed information.

The information we are parsing from the data string is the following: UTC Time (Hour & Minute), Position (Latitude-Longitude & Hemispheres) and Date (Month & Day of Month).

The GPS module begins searching for satellites when +5VDC power is applied. The time required to establish satellite reception the first time depends on several factors. In most cases the data stream is acquired in less than 1 minute. This is sometimes referred to as a 'cold start'. The GPS module transmits the serial text messages continuously thereafter, so long as DC power is present.

The program to receive the serial data stream is written in a computer language called "Picaxe Basic". The software language is available free of charge as part of an IDE (Integrated Development Enviroment) from Revolution Education, LLC. (http://www.picaxe.co.uk). Once downloaded and installed, the IDE can be used to view and modify the source code available here. The IDE is also capable of programming the Picaxe-20X2 IC by way of a simple serial port connection. (This is described in much more detail in our book.)

It is a rather simple matter to connect the GPS module to the Picaxe-20X2. The STMAX circuit board was designed to include provision for adding optional features. In this example we have connected the serial stream data line from the GPS module to Pin C.6 of the Picaxe-20X2 on the STMAX printed circuit board. Note that you don't need the STMAX circuit board to experiment with this code. You can simply work with a breadboard setup that supplies a Picaxe-20X2 with power and has the basic serial programming connections shown here, and as described in the Picaxe manuals.

GPS Picaxe-20X2 Circuit Diagram

Figure 3. Circuit Diagram for using the GPS module with the Picaxe

The software source code for the GPS data acquisition includes numerous comments to explain the general program flow. However, there are several features of the code which will be given special mention: The serial GPS text data is a fast stream of information which is quickly shuttled to memory using the incrementing bit pointer command after the header is detected. The data stream is afterwards relayed to the host computer as a simple memory dump of ASCII data. Because the data is comprised of ASCII symbols, it is necessary to perform an arithmetic conversion into their true numerical equivalents. The numerical equivalents are stored in upper memory, so as to free up lower memory for other uses. (To be explained in subsequent webpages.) The parsing routine simply uses the byte locations as the determinant of data identity. This parsing routine encounters a pitfall with the month and day data near the end, due to a variable-length data element preceding it. A simple logical parsing branch solves that issue. Finally, a data integrity check is performed to insure reasonable information has been acquired. Failure of the data integrity check forces another string of GPS information to be acquired for subsequent evaluation.

If you would like to experiment with this code simply copy and past the text below into the Picaxe Programming Software Editor. If you prefer, here is the Picaxe BASIC source code in a file: ( gpsweb.bas )

'Define Symbols
Symbol LAT=B55        'Latitude (0-90)
Symbol N_S=BIT0      'North=0 & South=1
Symbol LONG=B54     'Longitude (0-180)
Symbol E_W=BIT1      'East=0 & West=1
Symbol MONTH=B53  'Month (1-12)
Symbol DAY=B52        'Day of Month (1-31)
Symbol HOUR=B51      'Hour of Day UTC (0-23)
Symbol MINUTE=B50  'Minute of Day UTC (0-59)
'************************************************************************************************
'Code to query GPS for LAT, LONG, MONTH, DAY, HOUR, MINUTE
'Store results in unused high memory to avoid corrupting low memory
'Uses an EM-411 GPS Module (www.dx.com)
SERTXD("GPS Signal Acquisition: Wait 30 Sec",32,13,10)
PAUSE 30000
'Using the GPRMC Sentence from GPS Module
'By default data is stored starting in B0,B1,B2, etc.
'POKE and PEEK data to avoid memory conflicts with lower memory
'Do range checks at end for basic error testing
QUERY:    'Return here if the range check fails
bptr=0    'Set bit pointer to zero
'Note: SERIN has 30 second timeout, and a timeout destination
'SERIN looks for text string "$GPRMC" to start memory logging
SERIN[30000,END_P],C.6, T4800_8,("$GPRMC"),@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,_
@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,_
@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,_
@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,_
@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,_
@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptrinc,_
@bptrinc,@bptrinc,@bptrinc,@bptr
'Note: ASCII Characters have been stored in memory
SERTXD("1st= ",B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16,B17,B18,B19,32,13,10)
SERTXD("2nd= ",B20,B21,B22,B23,B24,B25,B26,B27,B28,B29,B30,B31,B32,B33,B34,B35,B36,B37,B38,B39,32,13,10)
SERTXD("3rd= ",B40,B41,B42,B43,B44,B45,B46,B47,B48,B49,B50,B51,B52,B53,B54,32,13,10)
'The ASCII Value is the numeric value plus $30 (See any ASCII table)
'Convert ASCII characters to equivalent numeric values...
B1=B1-$30
B1=B1*10
B2=B2-$30
B1=B1+B2
'SERTXD("HR= ",#B1,32,13,10)
POKE 56, B1    '56 is first byte of upper memory
'SERTXD("MIN= ",B3,B4,32,13,10)
B3=B3-$30
B3=B3*10
B4=B4-$30
B3=B3+B4
'SERTXD("MIN= ",#B3,32,13,10)
POKE 57, B3 '57 is second byte of upper memory
'SERTXD("LAT= ",B14,B15,32,13,10)
B14=B14-$30
B14=B14*10
B15=B15-$30
B14=B14+B15
'SERTXD("LAT= ",#B14,32,13,10)
POKE 58, B14 '58 is third byte of upper memory
'SERTXD("LONG= ",B26,B27,B28,32,13,10)
'Should not exeed 180, so byte will hold value
B26=B26-$30
B26=B26*100
B27=B27-$30
B27=B27*10
B26=B26+B27
B28=B28-$30
B26=B26+B28
'SERTXD("LONG= ",#B26,32,13,10)
POKE 59, B26    'Uses 59 in upper memory
'GPS string does not pad heading: Must do logical branch
'IF B50=44 then a normal case with 3 digit heading
IF B49=44 THEN GOTO PARSE1 'ASCII 44 is a comma, 2 digit
IF B48=44 THEN GOTO PARSE2 'ASCII 44 is a comma, 1 digit
'SERTXD("DAY= ",B51,B52,32,13,10)
B51=B51-$30
B51=B51*10
B52=B52-$30
B51=B51+B52
'SERTXD("DAY= ",#B51,32,13,10)
POKE 61, B51
'SERTXD("MONTH= ",B53,B54,32,13,10)
B53=B53-$30
B53=B53*10
B54=B54-$30
B53=B53+B54
'SERTXD("MONTH= ",#B53,32,13,10)
POKE 60, B53
GOTO END_OF_PARSE
PARSE1: 'Handles special case of a 2 digit heading report
'SERTXD("DAY= ",B50,B51,32,13,10)
B50=B50-$30
B50=B50*10
B51=B51-$30
B50=B50+B51
'SERTXD("DAY= ",#B50,32,13,10)
POKE 61, B50
'SERTXD("MONTH= ",B52,B53,32,13,10)
B52=B52-$30
B52=B52*10
B53=B53-$30
B52=B52+B53
'SERTXD("MONTH= ",#B52,32,13,10)
POKE 60, B52
GOTO END_OF_PARSE
PARSE2: 'Handles special case of a 1 digit heading report
'SERTXD("DAY= ",B49,B50,32,13,10)
B49=B49-$30
B49=B49*10
B50=B50-$30
B49=B49+B50
'SERTXD("DAY= ",#B49,32,13,10)
POKE 61, B49
'SERTXD("MONTH= ",B51,B52,32,13,10)
B51=B51-$30
B51=B51*10
B52=B52-$30
B51=B51+B52
'SERTXD("MONTH= ",#B51,32,13,10)
POKE 60, B51
GOTO END_OF_PARSE
END_OF_PARSE:
'**********
'Check if Northern or Southern Hemisphere
'N_S=0 'Northern
'E_W=1 'Western
IF B24=78 THEN    'ASCII 78='N'
    N_S=0        'Northern
    ELSE
    N_S=1        'Southern
ENDIF
'**********
'Check if East or West of prime meridian
'SERTXD("B37= ",B37,32,13,10)
IF B37=87 THEN    'ASCII 87='W'
    E_W=1        'West
    ELSE
    E_W=0        'East
ENDIF
'**********
'Do data range checks (Veracity of data)
PEEK 56, HOUR
IF HOUR > 23 THEN GOTO QUERY
PEEK 57, MINUTE
IF MINUTE > 59 THEN GOTO QUERY
PEEK 58, LAT
IF LAT > 90 THEN GOTO QUERY
PEEK 59, LONG
IF LONG > 180 THEN GOTO QUERY
PEEK 60, MONTH
IF MONTH > 12 THEN GOTO QUERY
PEEK 61, DAY
IF DAY > 31 THEN GOTO QUERY
SERTXD("HOUR= ",#HOUR,32,13,10)
SERTXD("MINUTE= ",#MINUTE,32,13,10)
SERTXD("LAT= ",#LAT,32,13,10)
SERTXD("LONG= ",#LONG,32,13,10)
SERTXD("MONTH= ",#MONTH,32,13,10)
SERTXD("DAY= ",#DAY,32,13,10)
SERTXD("E_W= ",#E_W,32,13,10)
SERTXD("N_S= ",#N_S,32,13,10)
'This is the program ending.
END_P:
SERTXD("PROGRAM ENDING",32,13,10)
END