PSoCとGPSモジュールで経緯度を表示する


psoc_gps_00.gif
今回はPSoCに組み込み機器用のGPSモジュールを接続して経緯度などを表示する。

利用したGPSモジュールはストロベリーリナックスで6200円程度で売られているものだ。これは電源電圧3.3~5Vで動作し、信号出力は3.3VとRS-232Cレベルでのシリアル出力(4800bps、パリティなし、ストップビット1)に対応している。TTLレベル(3.3V)のシリアル出力に対応しているので外付け部品は必要なくPSoCに直接つなぐことができる。コントロールチップはSiRF IIIのため感度が非常によい。

psoc_gps_01.gif
今回のGPSモジュールはプロトコル上はRS-232Cと同等の方法で通信する。ただしPSoCからGPSへデータを送信することはない。そのため受信専用のモジュールを利用することにした。「Digital Comm」の中の「RX8」を右クリックして現れたメニューからSelectを選択する。


ちなみにPSoC Designerには送信専用の「TX8」、送受信対応の「UART」なども用意されている。

psoc_gps_02.gif
さらにGPSモジュールから受信した経緯度などを表示するための液晶を追加する。「Misc Digital」の「LCD」を右クリックして「Select」する。

psoc_gps_03.gif
次に配線などの設定をするため画面を切り替える。「Config」メニューから「Interconnect」を選択する。

psoc_gps_04.gif
まず「Global Resources」を設定する。今回特に重要なのがこの部分だ。ここで
「VC1=SysClk/N」を「6」に、
「VC2=VC1/N」を「8」に、
「VC3 Source」を「VC2」に、
「VC3 Divider」を「13」にする。PSoCのクロックは24MHzなので、24,000,000Hz÷(6×8×13)≒38461(≒4800×8)になる。この値はGPSの通信速度4800bpsの8倍にほぼ等しくなっている。このようにクロックの分周率で通信速度を決める。
さらに「LCD_1」の「LCDPort」を「Port_2」に設定しておく。

psoc_gps_05.gif
次に「RX8_1」を使えるようにする。「RX8_1」を右クリックして現れたメニューから「Place」を選択して配置する。

psoc_gps_06.gif
そして左側の欄で設定する。
「Clock」を「VC3」に、
「Input」を「Row_0_Input_0」に、
「ClockSync」を「Sync to SysClk」に、
「RX Output」を「None」に、
「Data Clock Out」を「None」にすればいい。

psoc_gps_07.gif
次に内部配線をする。作業しやすいように画面を拡大して、GIEの0の線をクリックする。

psoc_gps_08.gif
するとメニューが現れるので「Pin」を選択する。

psoc_gps_09.gif
さらに現れた選択肢から「Port_0_0」を選択する。

psoc_gps_10.gif
これで受信用の「RX8_1」のInput端子がポート00とつながる。確認したら「View」メニューの「Application Editor」を選択して画面を切り替える。

psoc_gps_11.gif
「Source Files」の「main.c」の中に処理を書く。
今回は受信割り込みなどは使わずサンプルコードの受信ルーチンをそのまま使って適当に作った。また表示内容もGPSからのNMEA-0183フォーマットのGGAデータの中身を切りだしてそのまま利用している。


//----------------------------------------------------------------------------
// C main line
//----------------------------------------------------------------------------

#include <m8c.h> // part specific constants and macros
#include "PSoCAPI.h" // PSoC API definitions for all User Modules

BYTE bRxData;
BOOL fWaitToReceiveByte(void)
{
BYTE bRxStatus;
/* Wait to receive full byte*/
while ( !( bRxStatus=RX8_1_bReadRxStatus() & RX8_1_RX_COMPLETE ) )
{
/* might want to sleep or keep track of time */
}
/* data received, now check for errors */
if (( bRxStatus & RX8_1_RX_NO_ERROR ) == 0 )
{
/* no error detected */
bRxData = RX8_1_bReadRxData();
return( TRUE );
}
else
{
/* error detected */
bRxData = bRxStatus;
return( FALSE );
}
}


// Can not retreave last data of CSV
BOOL GetCSVData(char* pszCSV,int nIndex,char** ppszStart,char** ppszEnd)
{
int i;
int nFind;

if(nIndex < 0)
return FALSE;

*ppszStart = pszCSV;
*ppszEnd = pszCSV;
nFind = 0;
i = -1;
while(1)
{
i++;
if(pszCSV[i] != ',')
continue;

nFind++;

if(nFind == nIndex)
*ppszStart = &(pszCSV[i+1]);
if(nFind == nIndex + 1)
{
*ppszEnd = &(pszCSV[i-1]);
return TRUE;
}
}

return FALSE;
}


BOOL PrintCSVData(int nY,int nX,char* pszCSV,int nIndex)
{
BOOL ret;
char* pszStart;
char* pszEnd;

LCD_1_Position(nY,nX);
ret = GetCSVData(pszCSV,nIndex,&pszStart,&pszEnd);
if(ret == FALSE)
return FALSE;

*(pszEnd+1) = 0;
LCD_1_PrString(pszStart);
*(pszEnd+1) = ',';

return TRUE;
}


void main()
{
char pszBuff[64];
int nIndex;

LCD_1_Start();
RX8_1_Start(RX8_PARITY_NONE);
RX8_1_DisableInt();

nIndex = 0;
while(1)
{
if(fWaitToReceiveByte() == FALSE)
continue;
if(bRxData == '$')
{
if(nIndex > 0)
{
//Print GGA($GPGGA) data in NMEA-0813 format from GPS unit.
if(pszBuff[3] == 'G' && pszBuff[4] == 'G' && pszBuff[5] == 'A')
{
if(0)
{
//for debug out
char tmp;

tmp = pszBuff[33];
pszBuff[33] = 0;
LCD_1_Position(0,0);
LCD_1_PrString(pszBuff);

pszBuff[33] = tmp;
pszBuff[62] = 0;
LCD_1_Position(1,0);
LCD_1_PrString(pszBuff + 32);
}
else
{
PrintCSVData(0,0,pszBuff,1); //Time
PrintCSVData(1,0,pszBuff,2); //Longitude
PrintCSVData(0,16,pszBuff,4); //Latitude
PrintCSVData(0,13,pszBuff,7); //Satelite count
PrintCSVData(1,16,pszBuff,9); //Height from sea level
PrintCSVData(3,4,pszBuff,11); //Height from WGS84
}
}
}
nIndex = 0;
}

if(nIndex < 64)
{
pszBuff[nIndex] = bRxData;
nIndex++;
}

//for debug
// LCD_1_WriteData(bRxData); //Display RAW Data
}
}





_DSC9040.JPG
今回もCY8C29466とPSoCEval基板にて動作確認をした。

GPSモジュールからのケーブルは赤色をVCC、黒色をGND、黄色をポート00に接続し、ほかは利用しない。

_DSC9041.JPG
これがGPSモジュール。「4800」というシールはおそらく通信速度4800bpsを示しているのだろう。ということは9600bpsやそれ以上の速度のモジュールもあるのかな?

_DSC9042.JPG
こちらがアンテナ面。青色LEDが搭載されている。衛星を捉えて測位できているときは点滅、衛星をロストしているときは点灯したままになるようだ。

_DSC9043.JPG
これでGPSからのGGAデータの一部を表示できた。「033555.000」は時間(UTC)を示す。03:35:55.000という意味だ。日本時間に直すと12:35:55.000になる。「06」は衛星の捕捉数。雨の日の室内にも関わらず常に5~7個の衛星を捕捉できていた。同じ条件でGarmin eTrex Vistaでは...完全にダメ。
次の2行目と3行目はそれぞれ緯度と経度を示す。かなり正確な位置がでていたので2桁モザイクをかけている。例えば「13543.6343」と表示されている場合は、135度43分6343=135度43分38秒058を示す。小数点以下は「秒数÷60」なので小数点以下を60倍したのが秒数になる。
4行目は海抜とWGS82楕円体からの高度を示す。



カテゴリー「電子工作」 のエントリー