OpenGPSX component on SourceForge
- ผมได้นำ component ตัวนี้ไปใส่ใน SourceForge.net เป็นที่เรียบร้อยแล้ว ถ้าต้องการตัวที่ update ก็ไปดาวน์โหลดกันได้เลยครับ หน้าตาของ OpenGPSX บน sourceforge ก็ประมาณดังรูปด้านล่าง
- จากตอนที่แล้วเราทำการแปะคอมโพเน็นต์ลงบนฟอร์ม เพื่อทดสอบอย่างง่าย ต่อไปจะเปิด project ของ Lazarus ที่ผมเขียนขึ้นเพื่อนำคอมโพเน็นต์มาใช้งาน สามารถดาวน์โหลดตามลิงค์นี้ opengpsproject.zip ก่อนจะเปิด project นี้ต้องติดตั้งตัวคอมโพเน็นต์ ที่ผมกล่าวไปแล้วในภาคที่ 3 ก่อนนะครับ ไม่งั้นจะ Error เมื่อดาวน์โหลดมาแล้วก็ unzip ไปไว้ตรงไหนก็ได้
เปิดโปรแกรมทดสอบ
- รัน Lazarus คลิกที่เมนู Project > Open Project…
- เมื่อเปิดไฟล์ opengpstest.lpi แล้ว ที่ source editor ของ Lazarus คลิกไปที่ main กด F12 บนคีย์บอร์ดดูเพื่อดูฟอร์ม
ตั้ง property ให้ object
- เมื่อเราแปะ object ลงบนฟอร์ม Lazarus จะตั้งชื่อให้ NMEADecode1, GPSSkyplot1, GPSTarget1, GPSPortConnected1 และ GPSSignalplot1 เพื่อให้ object แต่ละตัวรู้จักกันจะต้องเพิ่มโค้ดประมาณ 3 บรรทัดที่ FormCreate ดังที่ผมคอมเม็นต์ไว้ครับ
- [sourcecode language=”delphi”]
- procedure TForm1.FormCreate(Sender: TObject);
- begin
- FNMEAs := TStringList.Create;
- InitControls;
- FStop := false;
- cmdStopPlay.Enabled := false;
- {Don’t forget to assign for the following objects.}
- GPSTarget1.NMEADecode := NMEADecode1;
- GPSSkyplot1.NMEADecode := NMEADecode1;
- GPSSignalPlot1.NMEADecode := NMEADecode1;
- FSuccess := false;
- end;
- [/sourcecode]
หลักการทำงานของ object
- ถ้าต่อกับเครื่อง GPS ตัว GPSPortConnected1 จะทำการเชื่อมกับ serial port เมื่อตั้งค่าต่างๆแล้วผ่านทางเมธอด GPSPortConnected1.SetupPort ทำการ connect เข้ากับ GPS ด้วยเมธอด GPSPortConnected1.OpenPort เครื่อง GPS จะส่งประโยค NMEA ผ่านทาง serial port ด้วยการสร้างอีเวนต์ GPSPortConnected1RxData ผู้ใช้ก็มาดักจับประโยค NMEA ที่นี่ โดยการเอา NMEADecode1 มาจับเอาประโยค NMEA ผ่านทาง property “Sentence”
- [sourcecode language=”delphi”]
- procedure TForm1.GPSPortConnected1RxData(Sender: TObject; Instring : string);
- begin
- //There are many empty string lines which come from TSdpoSerial.
- //Check it out.
- if InString <> ” then
- begin
- NMEADecode1.Sentence := Instring;
- if (NMEADecode1.Success) then
- memo1.Lines.Add(Instring);
- end;
- end;
- [/sourcecode]
- NMEADecode1 เมื่อทำการแปลสตริง NMEA ที่รู้จักแล้วถ้าสำเร็จจะส่งข้อมูลผ่านทางอีเวนต์ OnNMEA (รวมประโยค NMEA ที่แปลแล้วทุกๆประโยค) และกระจายอีเวนต์แยกไปตามรูปประโยค NMEA เช่น OnGGA, OnRMC, OnGSV, OnGLL เป็นต้น และ object ตัวนี้จะสร้างอีเวนต์พิเศษคือ OnGPSTarget, OnGPSSkyplot และ OnGPSSignalplot เพื่อส่งข้อมูลที่แปลแล้วไปให้ class TGPSTarget, TGPSSkyplot และ TGPSSignalplot ตามลำดับ
- GPSTarget1, GPSSkyplot1 และ GPSSignalplot1 เมื่อได้รับข้อมูล NMEADecode1 ก็จะทำหน้าที่ของตัวเอง
ทดสอบโดยการเล่นไฟล์ NMEA
- ในการทดสอบโปรแกรม บางท่านอาจจะไม่มีเครื่อง GPS ให้ลอง ผมได้เตรียมไฟล์ NMEA ให้โดยอยู่ที่โฟลเดอร์ “Data” เมื่อรัน opengpstest.lpi แล้ว ที่ด้านล่างจะมี Button ให้อยู่ 3 ตัว คลิกที่ัตัว “Open NMEA File…” ผมจะลองเปิดไฟล์ gpslog-mod.txt เสร็จแล้วก็คลิกที่ปุ่ม “Play NMEA >>” จะหยุดเล่นเวลาไหนก็คลิกที่ปุ่ม “Stop” ได้ครับ
- สำหรับ TGPSTarget มี property ที่สามารถตั้งค่าให้เลือกตั้งค่าพิกัดจุดหมายปลายทางได้เองหรือจะให้เลือกเอาจากประโยค $GPWPL ก็ได้ สังเกตว่าไฟล์นี้ขาดประโยค $GPVTG มาลองดูโค้ดที่ implement NMEA ที่ decode มาแล้ว
- [sourcecode language=”delphi”]
- {TNMEADecode is full of all decoded NMEA sentences.}
- procedure TForm1.NMEADecode1NMEA(Sender: TObject; NMEA: TNMEADecode);
- var
- dLat, dLong : double;
- begin
- case NMEA.MessageType of
- GGAMsg :
- begin
- with NMEA.GGA do
- begin
- lblGGAGeoidal.Caption := Separation + ‘ ‘ + SeparationUnits;
- lblGGAAltitude.Caption := Altitude + ‘ ‘ + AltitudeUnits;
- lblGGASatCount.Caption := SatsInUse;
- dLat := abs(strtofloat(LatitudeDegree));
- dLong := abs(strtofloat(LongitudeDegree));
- lblGGALat.Caption := format(‘%9.6f’, [dLat]) + ‘ (‘ + LatHemis + ‘)’;
- lblGGALong.Caption := format(‘%9.6f’, [dLong]) + ‘ (‘ + LongHemis + ‘)’;
- lblGGAHDOP.Caption := HDOP;
- lblGGAUTCTime.Caption := UTC;
- if (FixQuality = ‘0’) then
- lblGGAQuality.Caption := ‘Invalid’
- else if (FixQuality = ‘1’) then
- lblGGAQuality.Caption := ‘GPS Fix’
- else if (FixQuality = ‘2’) then
- lblGGAQuality.Caption := ‘DGPS Fix’;
- end;
- end;
- GSAMsg :
- begin
- with NMEA.GSA do
- begin
- if (FixStatus = ‘1’) then
- lblGSAFix.Caption := ‘Fix not available’
- else if (FixStatus = ‘2’) then
- lblGSAFix.Caption := FixStatus + ‘D’
- else if (FixStatus = ‘3’) then
- lblGSAFix.Caption := FixStatus + ‘D’;
- if (Mode = ‘A’) then
- lblGSAMode.Caption := ‘Automatic 2D/3D’
- else if (Mode = ‘M’) then
- lblGSAMode.Caption := ‘Manual’;
- lblGSAHDOP.Caption := HDOP;
- lblGSAVDOP.Caption := VDOP;
- lblGSAPDOP.Caption := PDOP;
- end;
- end;
- RMCMsg :
- begin
- with NMEA.RMC do
- begin
- if (Status = ‘A’) then
- lblRMCValidity.Caption := ‘Active’
- else if (Status = ‘V’) then
- lblRMCValidity.Caption := ‘Invalid’;
- dLat := abs(strtofloat(LatitudeDegree));
- dLong := abs(strtofloat(LongitudeDegree));
- lblRMCLat.Caption := format(‘%9.6f’, [dLat]) + ‘ (‘ + LatHemis + ‘)’;
- lblRMCLong.Caption := format(‘%9.6f’, [dLong]) + ‘ (‘ + LongHemis + ‘)’;
- lblRMCSpeed.Caption := format(‘%5.1f’, [strtofloat(Speed) * 1.852]) + ‘ Km/h’;
- lblRMCDate.Caption := UTCDate;
- lblRMCTime.Caption := UTCTime;
- lblRMCTrue.Caption := TrueCourse;
- if (MagneticVariation = ‘-9999’) then
- lblRMCMagVar.Caption := ”
- else
- lblRMCMagVar.Caption := MagneticVariation + ‘ ‘ + MagDeviation;
- end
- end;
- WPLMsg :
- begin
- with NMEA.WPL do
- begin
- lblWPName.Caption := WayPointName;
- lblWPLatitude.Caption := Latitude;
- lblWPLongitude.Caption := Longitude;
- end;
- end;
- GLLMsg :
- begin
- with NMEA.GLL do
- begin
- dLat := abs(strtofloat(LatitudeDegree));
- dLong := abs(strtofloat(LongitudeDegree));
- lblGLLLat.Caption := format(‘%9.6f’, [dLat]) + ‘ (‘ + LatHemis + ‘)’;
- lblGLLLong.Caption := format(‘%9.6f’, [dLong]) + ‘ (‘ + LongHemis + ‘)’;
- lblGLLTime.Caption := UTCTime;
- if (Status = ‘A’) then
- lblGLLStatus.Caption := ‘Valid’
- else if (Status = ‘V’) then
- lblGLLStatus.Caption := ‘Invalid’;
- end;
- end;
- PGRMMsg:
- begin
- with NMEA.PGRMM do
- lblGarminMapDatum.Caption := MapDatum;
- end;
- PGRMZMsg:
- begin
- with NMEA.PGRMZ do
- begin
- if (UnitAltitude = ‘f’) then
- lblGarminAltitude.Caption := Altitude + ‘ ‘ + ‘Feet’
- else
- lblGarminAltitude.Caption := Altitude + ‘ ‘ + UnitAltitude;
- lblGarminPosFix.Caption := PositionFix;
- end;
- end;
- PGRMEMsg:
- begin
- with NMEA.PGRME do
- begin
- lblGarminHPE.Caption := HPE + ‘ ‘ + UnitHPE;
- lblGarminVPE.Caption := VPE + ‘ ‘ + UnitVPE;
- lblGarminSEPE.Caption := SEPE + ‘ ‘ + UnitSEPE;
- end;
- end;
- end;
- end;
[/sourcecode]
- สังเกตว่าพารามิเตอร์ NMEA : TNMEADecode จะแยกชนิดของประโยคด้วย property “MessageType”
ทดสอบเล่นไฟล์ NMEA อีกไฟล์
- ลองเปิดไฟล์ NMEA อีกตัวคือไฟล์ “griffith-park.nmea” ซึ่งผมดาวน์โหลดได้จาก internet ดูค่าพิกัดแล้วน่าจะอยู่แถวๆ รัสเซีย ลองทดสอบดูกัน
- สังเกตว่าไฟล์ทดสอบนี้ำจะไม่มีประโยค $GPGLL และ $GPWPL แต่จะมีประโยค $GPVTG มาแทน เอาละครับมาต่อตอนต่อไป ผมอาจจะลองทดสอบดูใน Ubutu Linux หรืออาจจะทดสอบต่อกับเครื่อง GPS ผ่าน serial port