inglewoodpete
Senior Member
During the development of Little Ben, the need arose for a clock timer that did not require adjusting or periodical replacement of a backup battery. Little Ben 'clock' was to be installed in a public recreation park and needed to thrive on neglect and withstand power outages while maintaining accurate time.
I had a couple of surplus GPS data receiver modules, originally intended for use in a car navigation device. A check of the datasheet indicated that the module required 3.3 volts at 45mA and the default data output should be 9600 baud. On-line research showed that the data packet with a "$GPGGA" header would probably give me that data I wanted for a clock.
I initially placed the GPS receiver on a window sill, with an extension cable connected to an AXE027 into my computer. The PICAXE terminal showed the data at 9600 baud was garbled. The default output format for my module idled high. Sequences of data packets were being sent every second.
The attached code demonstrates a PICAXE 28X2 GPS data receiver, using the background receive mode for its hardware UART 'hSerial' port. The PICAXE's background timer is also used, to provide a backup should GPS data be corrupted.
Hardware for the demonstration consisted of a PICAXE 28X2 running off a (LM7805-based) 5v supply. This is fed into a LD1117AV33 low dropout 3.3v regulator, used to supply the GPS module. Data from the GPS receiver is fed directly into PICAXE hSerIn/Pin C.7/Leg 18. A LED & current limiting resistor are connected to pin A.1/Leg 3, used as a digital output.
The demonstration software receives data from the GPS module, which needs reasonable access to satellite data (Eg. placed near a window - my home has double brick walls and a steel roof). The PICAXE firmware receives data from the hardware UART and logs it sequentially in the scratchpad RAM, used as a circular buffer. Subroutine hReceive searches the logged data for a "$GPGGA" header (in subroutine Check_GPS_Header) and waits for the entire packet to be received before building the checksum in subroutine hRecCheckSum. If the rebuilt checksum matches the received checksum, the master time variables are overwritten in subroutine hReadGPSData
The time is output to the PICAXE Terminal window at 19200 baud every 10 seconds. If "#Define Show_Packet_Diags" is specified, every validly received "$GPGGA" packet is logged as well. A working version would not have "#Define Show_Packet_Diags" specified. Note that "#Define Show_Packet_Diags" places a considerable load on the PICAXE and it does not always receive and validate every "$GPGGA" data packet. If the packet's checksum fails validation, the packet is discarded. When this happens, the background timer's 1-second interrupt keeps time, with minutes and hours incrementing where appropriate.
If you are adding your own code to the main loop of the program, be aware that blocking commands could interfere with the operation of background serial data reception. Blocking commands could also prevent interrupts, stopping the software backup clock from 'ticking' every second.
I have included a lot of comments to help explain the operation of the code. As a result, the code is quite large and has to occupy two posts: Declarations/Initialisation/Main_Loop/Interrupts and All Subroutine Code.
I had a couple of surplus GPS data receiver modules, originally intended for use in a car navigation device. A check of the datasheet indicated that the module required 3.3 volts at 45mA and the default data output should be 9600 baud. On-line research showed that the data packet with a "$GPGGA" header would probably give me that data I wanted for a clock.
I initially placed the GPS receiver on a window sill, with an extension cable connected to an AXE027 into my computer. The PICAXE terminal showed the data at 9600 baud was garbled. The default output format for my module idled high. Sequences of data packets were being sent every second.
The attached code demonstrates a PICAXE 28X2 GPS data receiver, using the background receive mode for its hardware UART 'hSerial' port. The PICAXE's background timer is also used, to provide a backup should GPS data be corrupted.
Hardware for the demonstration consisted of a PICAXE 28X2 running off a (LM7805-based) 5v supply. This is fed into a LD1117AV33 low dropout 3.3v regulator, used to supply the GPS module. Data from the GPS receiver is fed directly into PICAXE hSerIn/Pin C.7/Leg 18. A LED & current limiting resistor are connected to pin A.1/Leg 3, used as a digital output.
The demonstration software receives data from the GPS module, which needs reasonable access to satellite data (Eg. placed near a window - my home has double brick walls and a steel roof). The PICAXE firmware receives data from the hardware UART and logs it sequentially in the scratchpad RAM, used as a circular buffer. Subroutine hReceive searches the logged data for a "$GPGGA" header (in subroutine Check_GPS_Header) and waits for the entire packet to be received before building the checksum in subroutine hRecCheckSum. If the rebuilt checksum matches the received checksum, the master time variables are overwritten in subroutine hReadGPSData
The time is output to the PICAXE Terminal window at 19200 baud every 10 seconds. If "#Define Show_Packet_Diags" is specified, every validly received "$GPGGA" packet is logged as well. A working version would not have "#Define Show_Packet_Diags" specified. Note that "#Define Show_Packet_Diags" places a considerable load on the PICAXE and it does not always receive and validate every "$GPGGA" data packet. If the packet's checksum fails validation, the packet is discarded. When this happens, the background timer's 1-second interrupt keeps time, with minutes and hours incrementing where appropriate.
If you are adding your own code to the main loop of the program, be aware that blocking commands could interfere with the operation of background serial data reception. Blocking commands could also prevent interrupts, stopping the software backup clock from 'ticking' every second.
I have included a lot of comments to help explain the operation of the code. As a result, the code is quite large and has to occupy two posts: Declarations/Initialisation/Main_Loop/Interrupts and All Subroutine Code.