GPS and MSP430

ソロバン評価ボードについて
Discussions about soft and hard solutions with Soroban development board.

GPS and MSP430

Postby pascal » Sun Mar 18, 2007 2:01 pm

Hello!

You need an application to track where your son goes with your car?
You came to the right place.
Today, I will just add a report I wrote last year about a GPS module I
had put on one of the earliest versions of Soroban. This morning, I set this
module on the latest version, compiled, and it just works.

The module

This is a GPS module with a patch antenna. It is quite small. I would like
it smaller, but it is a good compromise as it is not very expensive. A little
bit less than 27 mm square.

Image

Now here is a view of its thickness, a little bit under 9mm. Sorry for the
quality of the photographs, I am not a specialist, and the camera I use
is one of the earliest 3 MPix I bought in 2000.

Image

The platform
This time (surprise?) I used a new version of Soroban to which I have
added a nice lithium polymer battery. According to the GPS specs, it
should use at most 28 mA. The rest of the board (MSP430 + RTC +
LCD) consume together about 5mA at 8MHz, which brings us to 33. Make
it 40 worst case, and suppose the 650 mAh of the battery are an
optimistic label, then we can maybe count on 400 mAh which enables
to have have about 10 hours of continuous use, which should be OK for
most of your bicycle trips.

Image

Wiring the module on Soroban

Before wiring, I had to punch a hole to leave some room for the 3
antenna pins that are off-pitch. They are not used anyway because
the module has a patch antenna.

Image

Wiring the module is extremely easy. The module outputs data through
serial port (UART), so we need to wire Rx, Tx. As USART1 is already
used for LCD and RTC in SPI mode, we are going to use USART0, so
there will be no need to switch between UART and SPI mode.
So Rx and Tx are wired to pins 32 and 33.
Now, the specs of the module say that the reset level has to be around
2V. As the MPU is powered in 3.3V, we are clearly out of range. I have
tried to use 3.3V for reset, it didn't work (luckily, the module survived).
So I have set up a resistor bridge to divide the reset signal by 2.
As you can see on the next picture, I have used 2 chip resistor (51k).
The left one is wired to MSP430's port 4.3 (pin 39). The right one is
grounded, and the middle is used for the GPS module reset signal.
it is not exactly 2V, but I don't have proper resistors to get exactly
2V. Anyway it works. Here is a closeup of the chip resistors.

Image

Software
The software part is quite easy.
I had to write functions to manage the UART. Sorry, this is quick & dirty
code and I would recommend to use it with extreme care, but it is good
enough for experimentation.

UART source code
Here is the .h file: (types.h defines uint8, uint16, etc...)

Code: Select all
#ifndef _USART_H_
#define _USART_H_
#include <msp430x16x.h>
#include "types.h"

//   Non-realtime functions. These are configuration functions.
//   This is to be changed to reduce the number of functions.
//   USART0 inits:

void InitUsart0(void);
void USART0Enable(void);
void USART0Disable(void);
void SetUSART0Rate(uint16 freq);
void Enable_IE_USART0(void);
void Disable_IE_USART0(void);
void SetTimeout(uint8 which, uint16 t);

//   Realtime functions (USART0 send and receive functions)

void USART0SendByte(uint8 byte);
void USART0SendBuffer(uint8 * buf, uint16 len);
uint8 USART0RecvByte(void);
uint16 USART0RecvBuffer(uint8 * buf, uint16 len);

#endif



Now here is the C file. globals.h defines the external crystals frequencies
(XTFREQ is used here). Timeout has been set so that the function does
not hang. By setting the timeout properly, you can decide how you will
receive a block of data. Basically you receive 2~300 consecutive bytes,
then there is a break. In the consecutive bytes, the maximum delay
can be set to the transmission time for 3 bytes for example. If you have
to wait more, this is likely to indicate the end of the buffer, so you can
return.

Code: Select all
#include  <msp430x16x.h>
#include "USART.h"
#include "globals.h"

static uint16 timeout0;

//---------------------------------------------------------
//         Initializatons USART0
//---------------------------------------------------------

void InitUsart0(void) {
   // P3.4,5 = USART0 TXD/RXD
   P3SEL |= 0x30; 
   P3DIR |= 0x10;  //P3.4 = output direction
   P3DIR &= ~0x20; // P3.5 = input direction
   // 8-bit, UART
   U0CTL = (CHAR | SWRST);     
   // UCLK= SMCLK
   U0TCTL |= SSEL1;       
   // Set baud rate to 9600 (might be changed later).
   SetUSART0Rate(9600);
   // Initalize USART state machine
   U0CTL &= ~SWRST;
   // Enable USART0 RX interrupt
   USART0Enable();
   Enable_IE_USART0();
}

//   Enable USART0 TXD/RXD
void USART0Enable(void) {
   //   Enable module
   ME1 = UTXE0 | URXE0;
   //   Remove reset flag
   U0CTL &= ~SWRST;
}

//   Disable USART0
void USART0Disable(void) {
   //   Set reset flag
   U0CTL |= SWRST;
   //   Disable module
   ME1 &= ~UTXE0;
   ME1 &= ~URXE0;
}

//   Set USART baud rate
void SetUSART0Rate(uint16 BaudRate) {
   uint16 divisor;
   uint8 * div;
   //   Temporarily disable the module
   U0CTL |= SWRST;
   //   Calculate the divisor
   divisor = XTFREQ / BaudRate;
   timeout0 = 2* divisor;
   //   Superpose a uint8 pointer
   div = (uint8 *)(&divisor);
   U0BR1 = div[1];
   U0BR0 = div[0];
   //   Re-enable the module
   U0CTL &= ~SWRST;
}

//   Enable USART0 Rx Interrupt
void Enable_IE_USART0(void){   
   IE1 |= URXIE0;
}

//   Disable USART0 Rx Interrupt

void Disable_IE_USART0(void){   
   IE1 &= ~URXIE0;
}

void SetTimeout(uint16 t) {
   timeout0 = t;
}

//---------------------------------------------------------
//          Transmit and receive USART0
//---------------------------------------------------------

//   Send a single byte
void USART0SendByte(uint8 byte) {
   IFG1 &= ~UTXIFG0;
   /* Send the byte */
   U0TXBUF = byte;
   /* Wait for the byte to be sent */
   while (!(IFG1 & UTXIFG0)) { }
}

void USART0SendBuffer(uint8 * buf, uint16 len) {
   int i;
   for(i = 0 ; i < len ; ++i) {
      USART0SendByte(buf[i]);
   }
}

//   Receive a single byte
uint8 USART0RecvByte(void) {
   uint8 retval;
   IFG1 &= ~URXIFG0;
   //   Wait for the receive flag.
   while (!(IFG1 & URXIFG0)) {}
   retval = U0RXBUF;
   return retval;
}

uint16 USART0RecvBuffer(uint8 * buffer, uint16 len) {
   uint16 retlength = 0;
   uint16 timeout;
   while(retlength < len) {
      timeout = 0;
      IFG1 &= ~URXIFG0;
      while(!(IFG1 & URXIFG0) && (timeout++ < timeout0)) {}
      if(timeout >= timeout0) break;
      buffer[retlength] = U0RXBUF;
      retlength++;
   }
   return retlength;
}



That's it.

GPS module source code
The GPS source code is pretty straightforeward.

Code: Select all
#ifndef _GPS_H_
#define _GPS_H_

#include "Types.h"

#define GPSRESET   0x08

// GPS specific
void   InitGPS(void);
void   ResetGPS(void);
uint16   ReadNMEA(void);

// Custom functions for parsing NMEA data
uint8   GetAltitude(uint8 * str);
uint8   GetCap(uint8 * str);
uint16   GetCompass();
uint8   GetGMTTime(uint8 * str);
uint8   GetLatitude(uint8 * str);
uint8   GetLongitude(uint8 * str);
uint8   GetLocalTime(uint8 * str);
uint8   GetNSats(void);
uint8   GetSpeed(uint8 * str);
void   SetTimeZone(int8 zone);

#endif



As for the implementation, first I knew that I would get some NMEA
data. When looking at that home page, I understand that NMEA is nothing
more than plain text data. The module spec says that I would get
1 set of informations every second. After a few experiments, I found
out that the data is about 250 bytes coming in a burst every second.
Sometimes there is more, but the most I had was about 400 bytes.
So I decided to receive data in a 512 byte buffer.

So in the implementation, I have setup a static buffer to keep the
NMEA data. Then I also reserved a 18-character string (remember
that the display PW10164LCD has 8 lines of 17 characters). This string
will be used to extract NMEA data from the NMEA buffer.
Then, last thing is to have a static timezone in order to setup Japanese
time (in my case) or any other time zone.

Here is one part of the implementation (I skip data retrieving functions
which are plain string processing routines).

Code: Select all
#include <msp430x16x.h>
#include "GPS.h"
#include "Usart.h"
#include "Clock.h"
#include "AltitudeFilter.h"

//   This implementation is a "hardcoded" implementation which assumes
//   that the GPS module has been set to UART0.
//   This file keeps a buffer of the NMEA data.

#define NMEA_BUF_LEN   0x200

//   Static variables and buffers
static uint8 NMEABuffer[NMEA_BUF_LEN];
static uint8 RawString[18];
static int8 timezone;

//   Configures the UART first for 9600 baud. This will be subject to
//   changes later.

void InitGPS(void) {
   empty_buffer(NMEABuffer, NMEA_BUF_LEN);
   SetTimeZone(9);
   ResetGPS();
   InitUsart0();
}

void ResetGPS(void) {
   P4DIR |= GPSRESET;
   P4OUT &= ~GPSRESET;
   delay(100);
   P4OUT |= GPSRESET;
}

uint16 ReadNMEA(void) {
   uint16 len;
   empty_buffer(NMEABuffer, NMEA_BUF_LEN);
   len = USART0RecvBuffer(NMEABuffer, 0x200);
   return len;
}



That's it. Once you get a buffer of NMEA data, you have all what you
need and you can extract or ignore any data, store it in the SD card
and so on.

Some results

Here are photographs of the results:

Image

Note that I was walking slowly in order to take a picture. I was heading
south, and therefore the heading 179 degrees seems to be right. I have
developed a kind of compass with the indications N, NE, E, SE, S, SW,
W, NW. As you can see on the picture, the SE indication is on the left,
which sounds true if you are heading south.

The chip which is on the board is a pressure sensor. The GPS is not
accurate in altitude, so this will bring some more accuracy, but this
will be described in another article.

The second picture shouws the screen detail:

Image

Conclusion

We have shown that new hardware can be added to Soroban with minimal
trouble. A complete GPS receiver with potential storage capability (let's
be honest, it was not developed here) could be developed by adding
7 wires only. As it is only a demonstration, the source code has still
a lot to be improved.
Another thing that could be improved would consist in constantly storing
the coordinates into the CPU flash. The startup of the module takes more
than 1 minutt because it is a "cold start" (the module has no hint about
its position at start up). So if we store the parameters and give hints
to the module at start-up, startup will be a lot faster.

NB
The whole working source code can be provided to customers buying
Soroban and a GPS module. The GPS module will be available now.

Careful:
Recording is not implemented in the current application, although all
the pieces exist. Note that we provide routines to access the SD card,
but these are raw routines, not a file system implementation.
Last edited by pascal on Sun Oct 07, 2007 3:38 pm, edited 3 times in total.
pascal
Site Admin
 
Posts: 231
Joined: Sun Mar 04, 2007 11:47 am

Nice project!

Postby hamayan » Sun Mar 18, 2007 3:59 pm

Hello.

I thought,it is a very nice project.
And,I looking for a very small GPS module.
I look forward to release day.

Thanks.
hamayan
 
Posts: 6
Joined: Wed Mar 14, 2007 1:17 am


Return to MSP430 development board Soroban hard & soft

Who is online

Users browsing this forum: No registered users and 0 guests

cron