Tag: SDK

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 8 โปรแกรมคำนวณสเกลแฟคเตอร์ (Scale Factor)

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 8 โปรแกรมคำนวณสเกลแฟคเตอร์ (Scale Factor)

โปรแกรมคำนวณสเกลแฟคเตอร์ (Scale Factor) สำหรับเครื่องคิดเลข Casio fx-9860 G

ช่วงนี้อยู่ในชุดซีรี่ย์โปรแกรมเครื่องคิดเลข Casio fx-9860G  ต่อไปขอนำเสนอโปรแกรมคำนวณสเกลแฟคเตอร์ (Scale Factor) ตัวโปรแกรมพัฒนาด้วยภาษาซี  ใช้เป็นโปรแกรม AddIn ดังรูปด้านล่าง

ปัญหาการคำนวณสเกลแฟคเตอร์

สเกลแฟคเตอร์ในที่นี้ผมจะขอหมายถึง Elevation Scale Factor (ESF), Grid Scale Factor (GSF) ตลอดจน Combined Scale Factor (CSF) สามารถอ่านได้จาก blog ก่อนหน้านี้ของผมได้ที่ใช้โปรแกรม Surveyor Pocket Tools มาช่วยคำนวณ ผู้อ่านอาจจะเคยสังเกตว่าจะไม่เคยเห็นโปรแกรมคำนวณสเกลแฟคเตอร์ในเครื่องคิดเลขเท่าใดนัก ในกรณีนี้คือพวกเราใช้ค่าระดับที่อิงระดับน้ำทะเลปานกลาง (แทนด้วยสัญลักษณ์ตัว “H“) กันเป็นหลัก น้ำทะเลปานกลางนี้สามารถใช้พื้นผิวจีออยด์ (Geoid) แทนได้ แต่การคำนวณหา Elevation Scale Factor เราจะต้องทราบค่าระดับที่อ้างอิงกับ Ellipsoid (แทนด้วยสัญลักษณ์ตัว “h“) ไม่ใช่เทียบกับระดับน้ำทะเลปานกลาง ความต่างระหว่างพื้นผิวจีออยด์และพื้นผิวทรงรี เราเรียกว่า Geoid Separation (แทนด้วยสัญลักษณ์ตัว “N“) ความสัมพันธ์ระหว่างสามสิ่งนี้คือ h = H + N

การหา Geoid Separation (N) จะต้องใช้ Earth Gravity Model ซึ่งก่อนหน้านี้ใช้ EGM96 ปัจจุบันใช้ EGM2008 ที่มีความละเอียดถูกต้องมากกว่า ซึ่งโมเดลต่างๆเหล่านี้จะเป็นไฟล์ที่มีขนาดค่อนข้างใหญ่จนใหญ่มาก ทำให้ไม่สามารถนำมาใช้กับเครื่องคิดเลขในระดับนี้ได้ และถ้าเขียนโปรแกรมด้วย Casio Basic ก็คงหมดสิทธิ์ครับเพราะไม่มีคำสั่งในการอ่านเขียนไฟล์

ปัญหาและทางออก

ผมพยายามใช้โค้ดภาษาซีในการอ่านไฟล์โมเดล EGM96  ด้วย egm96-f477.c โปรแกรมสามารถคอมไพล์และบิวท์ผ่าน แต่ตอนประมวลผลอ่านไฟล์ เนื่องจากต้องใช้เมโมรีเครื่องคิดเลขมาอ่านไฟล์เข้าไปเก็บในหน่วยความจำพบว่า เมโมรีไม่พอ พยายาม optimize ด้วยตัวเองหลายๆทางแต่ไม่สำเร็จ จนมาพบโดยบังเอิญในเว็ปไซต์ ตามลิ๊งค์นี้ จุดประสงค์ทางผู้พัฒนาไลบรานี้เพื่อเขียนแอพลงบนโทรศัพท์มือถือแอนดรอยด์ วิธีการคือเขาได้ Normalize ค่า geoid separation จาก EGM2008 ขนาดเต็มลงมาเหลือขนาดแถวคอลัมน์ 181 x 91 ความถูกต้องจะถูกลดทอนลง ผมสนใจเลยเอามาคอมไพล์บน Casio SDK พบว่าทำงานได้ ใช้เมโมรีเครื่องคิดเลขที่มีอยู่เพียงพอ แต่ก็จวนเจียนจะใช้หมดเหมือนกัน เอาละความคิดที่เคยจะเขียนโปรแกรมคำนวณสเกลแฟคเตอร์บเครื่องคิดเลขก็มาเป็นจริง อาจจะได้ค่าสเกลแฟคเตอร์ที่ไม่ละเอียดเท่าคำนวณจากคอมพิวเตอร์แต่ในระดับทศนิยมหกตำแหน่ง ถือว่าได้ครับ

เครดิตผู้พัฒนาไลบรารี Geoid

ต้องขอบคุณผู้พัฒนาคือ Stefan Röttger (stefan@stereofx.org) มา ณ ที่นี้ ติดตามผลงานได้ที่เว็บไซต์ http://www.open-terrain.org/index.php ไลบรานี้ใช้สัญญาอนุญาตแบบ New BSD License

เตือนสติเรื่องสเกลแฟคเตอร์

ผมชอบวาทะของอ.ดีบุญ เมธากุลชาติ ก็ขออนุญาตเอาจากสไลด์มาแสดง ณ ที่นี้ด้วย อ.ดีบุญเรียก Grid Scale Factor ว่าตัวประกอบมาตราส่วน ส่วน Elevation Scale Factor เรียกว่าตัวประกอบความสูง ได้ใจความครบถ้วนดีครับ และก็เตือนสติคนใช้แผนที่ดังนี้

Grid Scale Factor เมื่อคูณกับ Elevation Scale Factor จะได้ Combined Scale Factor ตัวประกอบตัวนี้คือตัวสำคัญที่จะนำไปคูนกับระยะทางที่วัดบนพื้นผิวโลกเพื่อทอนลงมาบนระนาบราบของแผนที่ (Grid Distance)

ใช้ไลบรารีแปลงพิกัด MGRS

เนื่องจากโปรแกรมนี้ต้องแปลงค่าพิกัดจากระบบพิกัดฉาก  UTM  บนดาตั้ม WGS84 ไปยังค่าพิกัดภูมิศาสตร์ เพื่อส่งไปให้ฟังก์ชั่นคำนวณหาค่าสเกลแฟคเตอร์ที่ต้องการทราบค่าละติจูด ดังนั้นผมใช้ไลบรารี mrgs พัฒนาโดย Howard Butler ไลบรานี้ใช้สัญญาอนุญาตแบบ MIT License

สิ่งที่โปรแกรมต้องการ

โปรแกรมสามารถคำนวณได้ 2 แบบคือแบบ Point Scale Factor คือแบบจุดเดี่ยวๆ สามารถคำนวณมาใช้แทนพื้นที่เล็กๆประมาณ 1 กม. x 1 กม. ได้ดี และรูปแบบที่ 2 คือ Line Scale Factor ใช้สำหรับพื้นที่ที่ใหญ่ขึ้นมา ใช้ค่าพิกัด 2 จุดหัวและท้าย โปรแกรมจะต้องการทราบค่าดังนี้

  1. เลือกโซนของยูทีเอ็ม (UTM  Zone) ตั้งแต่โซน 1 ถึง 60 และเลือกซีกโลก (Hemisphere)  เลือกได้สองอย่างคือเหนือหรือใต้เส้นศูนย์สูตร
  2. ค่าพิกัดและค่าระดับของจุดที่ต้องการทราบค่าสเกลแฟคเตอร์ ต้องการค่าพิกัดเหนือใต้ในระบบยูทีเอ็มและค่าระดับที่อ้างอิงเหนือระดับน้ำทะเลปานกลาง (Orthometric Height above Meas sea level)

ในการคำนวณตัวประกอบความสูง (Elevation Scale Factor) โปรแกรมจะนำค่าความสูงเหนือระดับน้ำทะเลปานกลางมาคำนวณเป็นค่าระดับความสูงเทียบกับระดับทรงรี (Ellipsoid Height) ที่เราไม่สามารถนำค่าระดับความสูงเหนือระดับน้ำทะเลปานกลางมาใช้คำนวณเพราะว่า ตัวอย่างเข่นในประเทศไทย ค่าระดับน้ำทะเลปานกลางจะอยู่ใต้ทรงรีประมาณ 6-42 เมตร ถ้านำไปคำนวณจะได้ค่าตัวประกอบความสูงที่ไม่ถูกต้อง

ดาวน์โหลดโปรแกรม

ไปที่หน้าดาวน์โหลด Download มองหาโปรแกรม Scale Factor สำหรับเครื่องคิดเลข Casio fx-9860 G II SD ดาวน์โหลดไฟล์โปรแกรมชื่อ SFACTOR.G1A ติดตั้งลงเครื่องคิดเลข

เริ่มต้นใช้งาน

เมื่อเมนูหลัก (Main Menu) เมื่อเลื่อนลูกศรมาที่ไอคอนโปรแกรมกดคีย์ “EXE” จะเข้ามาในโปรแกรมดังรูปด้านล่าง จะเห็นเมนูด้านล่างเรียงรายกันไป ได้แก่

Sett- Setting (ตั้งค่าโซนยูทีเอ็มและเลือกซีกโลก)

PSF – Point Scale Factor ( คำนวณหาค่าสเกลแฟคเตอร์ของจุดเดี่ยว

LSF – Line Scale Factor (คำนวณหาค่าสเกลแฟคเตอร์เฉลี่ยจากจุดสองจุด)

Info – Information (แสดงไลบรารีที่ผมใช้งานอยู่ ให้เครดิตแก่พัฒนา)

Exit – Exit Program (ออกจากโปรแกรม)

ตั้งค่ายูทีเอ็ม (UTM Settings)

ทีเมนูหลักกดคีย์ F1 – Sett จะเห็นหน้าตาจอภาพเครื่องคิดเลขดังนี้

เนื่องจากโปรแกรมบนเครื่องคิดเลขมีข้อจำกัดมากๆ ผมไม่สามารถใส่ระบบพิกัดได้มากเหมือน Surveyor Pocket Tools จึงจำกัดแค่ datum “WGS84” เท่านั้น สำหรับประเทศไทยก็เลือกโซนได้สองโซนคือ 47 และ 48 ตัวอย่างที่จะแสดงต่อไปเลือกเป็นโซน 47 ส่วนซีกโลก (Hemisphere) เลือกเป็น “North” กดคีย์ F6 – OK

 

คำนวณ Point Scale Factor

ตัวอย่างที่คำนวณต่อไปจะยกมาจากตัวอย่างที่แสดงในบล็อกของ Surveyor Pocket Tools เพื่อเปรียบ

เทียบผลลัพธ์กันได้ กลับมาที่เมนูหลักกดคีย์ F1-Sett ป้อนค่าพิกัด N=1499662.173, E=683068.285, H=0.791 

เสร็จแล้วกดคีย์ F1 – Calc เพื่อคำนวณสเกลแฟคเตอร์ของจุดนี้

ผลลัพธ์จะแสดงออกมาดังรูปด้านล่าง โปรแกรมจะแสดงค่าพิกัดและค่าระดับมาให้ จากนั้นแสดงค่าละติจูดและลองจิจูด แสดงความสูงเทียบกับทรงรี = -29.598 m กดคีย์ F2-PgDn เพื่อเลื่อนไปดูหน้าต่อไป

จะเห็นค่า Geoid Separation หรือ Geoid Height = -30.389 m และได้ค่า Elevation Scale Factor = 1.00000465, Grid Scale Factor = 1.00001458 สุดท้ายค่า Combine Scale Factor = 1.00001924 ลองเทียบกับค่าที่คำนวณด้วย Surveyor Pocket Tools ดังนี้

ค่า Combined Scale Factor  = 1.0000192644 ต่างกันที่ทศนิยมแปด ผมถือว่าใช้ได้เพราะเราใช้แค่ทศนิยมที่หกก็เพียงพอแล้ว ความต่างที่แตกต่างจากที่ผมเคยบอกไปแล้วคือมาจากค่า Ellipsoid height ที่คำนวณจากโปรแกรมเครื่องคิดเลขได้ -29.598 เมตร ส่วนค่าความสูงทรงรีที่ได้จาก Surveyor Pocket Tools ได้ค่า -29.776 เมตร ต่างกันประมาณ 20 ซม.

คำนวณหาค่า Line Scale Factor

จะแสดงไดอะแกรมของการคำนวณค่าสเกลแฟคเตอร์เฉลี่ยดังรูปด้านล่าง

ที่โปรแกรมเครื่องคิดเลขกลับมาที่เมนูหลัก

กดคีย์ F3-LSF จะเห็นหน้าตาโปรแกรมดังรูปด้านล่าง ป้อนค่าพิกัดจุดที่ 1 และกดคีย์ F2-Next เพื่อไปป้อนจุดที่ 2

พร้อมแล้วกดคีย์ F1-Calc ต่อไปจะได้ผลลัพธ์ดังนี้ เลื่อนลงไปดูหน้าต่อไปก็กดคีย์ F2-PgDn

สรุปแล้วจะได้ค่าเฉลี่ย Combined Scale Factor = 1.00082320

เปรียบเทียบกับค่าที่ได้จาก Surveyor Pocket Tools เท่ากับ 1.0008232302 เช่นเคยค่าต่างกันที่ทศนิยมแปด สามารถนำไปใช้งานได้

จัดเก็บข้อมูลและเรียกมาใช้ภายหลัง

เพื่อให้ผู้ใช้งานได้สะดวก การจับเก็บตัวแปรเช่นค่าพิกัดที่เคยป้อนไปแล้ว เมื่อเปิดโปรแกรมมาอีกรอบค่านั้นจะยังอยู่ ผมจึงอาศัยวิธีการจัดเก็บไฟล์ลงบน SDCard ที่เสียบไว้ที่เครื่องคิดเลขของเรา เมื่อออกจากโปรแกรม และจออ่านไฟล์มาอีกทีเมื่อเปิดโปรแกรม

ก่อนจะใช้งานได้ต้องมีการเตรียมโฟลเดอร์บน SDCard ดังต่อไปนี้  คือดึง SDCard จากเครื่องคิดเลขมาเสียบบนคอมพิวเตอร์ แล้วทำการสร้างโฟลเดอร์ชื่อ “svdata” ดังรูป แต่ถ้ามีการสร้างมาแล้วก็ไม่จำเป็นต้องทำอะไร

จากนั้นนำ SDCard มาเสียบบนเครื่องคิดเลขอีกครั้ง เมื่อนำไปใช้งานได้สักพักถ้าเอามาเปิดอีกครั้งจะเห็นไฟล์หลายๆไฟล์ มีนามสกุลเป็น “CFG”  หมายถึง config ตัวอย่างถ้าใช้โปรแกรมคำนวณหาสเกลแฟคเตอร์นี้ไฟล์ที่จัดเก็บข้อมุลคือ “SFACTOR.CFG

เครดิตไลบรารี

ที่เมนูหลักกดคีย์ F5-Info จะเห็นเครดิตดังรูปด้านล่าง

โปรแกรมนี้มีขนาดใหญ่กว่าโปรแกรมอื่นๆก่อนเกือบสองเท่าเพราะว่าใช้ไลบรารีอื่นๆสามไลบรารีด้วยกัน ก็ติดตามชุดโปรแกรมเครื่องคิดเลข Casio fx-9860 G กันต่อไปครับ

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 7 โปรแกรมคำนวณโค้งราบ (Horizontal Curve)

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 7 โปรแกรมคำนวณโค้งราบ (Horizontal Curve)

โปรแกรมคำนวณโค้งราบ HCurve สำหรับเครื่องคิดเลข Casio fx-9860 G

ช่วงนี้อยู่ในชุดซีรี่ย์โปรแกรมเครื่องคิดเลข Casio fx-9860G ที่ใช้ไลบรารี MyLib ต่อไปขอนำเสนอโปรแกรมคำนวณโค้งราบ (Simple Horizontal Curve) ตัวโปรแกรมพัฒนาด้วยภาษาซี  ใช้เป็นโปรแกรม AddIn ดังรูปด้านล่าง

โปรแกรม HCurve คำนวณโค้งราบ (Simple Horizontal Curve)

องค์ประกอบของโค้งราบ (Elements of Horizontal Curve)

องค์ประกอบของโค้งราบ (Elements of Curve)

คำนิยาม (Abbrivations)

R – Radius คือรัศมีของโค้งราบ รัศมีจะตั้งฉากกับเส้นสัมผัสวงกลมเสมอ

PC –  Point of Curvature คือจุดเริ่มต้นโค้ง บางครั้งเรียกว่า BC (beginning of curve) หรือ TC (tangent to curve)

PI – Point of Intersection คือจุดตัดของ tangent 2 เส้น

PT – Point of Tangency คือจุดสิ้นสุดโค้ง บางครั้งเรียกว่า EC (end of curve) หรือ CT (curve to tangent)

POC – Point of Curve คือจุดบนโค้งในตำแหน่งใดก็ตาม

L – Length of Curve คือความยาวโค้งวัดตามโค้งจากจุด PC ไปจุด PT

T – Tangent Distance หรือ Tangent Length คือเส้นตรงที่สัมผัสโค้งวัดจากจุด PC ไปจุด PI หรือวัดจาก จุด PI ไปจุด PT

คุณสมบัติของโปรแกรม

โค้งราบ (Simple Horizontal Curve) ในงานสำรวจใช้ในงานสำรวจเพื่อการก่อสร้าง (Construction Survey) โดยที่ให้ตำแหน่ง (Setting out) งานก่อสร้างถนน ทางรถไฟ ผู้ใข้ป้อนข้อมูลองค์ประกอบของโค้งราบที่โปรแกรมต้องการจนครบ โปรแกรมสามารถคำนวณองค์ประกอบโค้งที่เหลือและสามารถคำนวณค่าพิกัดบนเส้น Center line หรือกระทั่งสามารถ offset ไปด้านซ้ายหรือด้านขวาก็ได้เช่นเดียวกัน สามารถคำนวณค่าพิกัดแบบทุกช่วงระยะ (interval) ให้ค่าพิกัดออกมาเป็นบัญชีรายการได้ โปรแกรมนี้ออกแบบและพัฒนามาเพื่อช่วยช่างสำรวจให้สามารถนำโปรแกรมไปตรวจสอบข้อมูลโค้งราบได้ด้วยตัวเอง

ในปัจจุบันการวางโค้งในสนาม ไม่ได้ถูกจำกัดเช่นสมัยแต่ก่อนเนื่องจากเครื่องมือเช่นอุปกรณ์กล้องสำรวจ Total Station ทันสมัยสามารถให้ตำแหน่งจากค่าพิกัดได้เลย ไม่เหมือนสมัยแต่ก่อนที่มีแต่กล้อง Theodolite และเทปวัดระยะ ที่การวางโค้งต้องอาศัยการตั้งกล้องที่จุด PC หรือ PI หรือแม้กระทั่ง PT แล้วทำการเปิดมุมและดึงเทปไปตามคอร์ด ปัจจุบันไม่ต้องทำอย่างนั้นแล้ว สามารถตั้งกล้องที่ไหนก็ได้ที่สะดวก

ก็เนื่องจากความทันสมัยของกล้อง Total Station นี้เอง ในอนาคตไม่ไกลการโอนข้อมูลจากกล้องไปที่ออฟฟิศหรือจากออฟฟิศไปที่กล้องจะเป็นเรื่องธรรมดามากผ่านทางออนไลน์ ซึ่งเรื่องนี้ข้อดีก็มีมากมาย แต่ข้อเสียที่เกิดขึ้นคือช่างสำรวจจะมีเวลาใช้สมองคิดเรื่อง geometry น้อยลงเพราะโปรแกรมบนกล้องทำให้หมด ทำให้ขาดการฝึกฝนทักษะในด้านนี้ ซึ่งผมคิดว่าอาจจะทำให้คุณภาพของบุคลากรด้านสำรวจของเราด้อยลงในอนาคต ดังนั้นการใช้เครื่องคิดเลขมาช่วยอาจจะช่วยฝึกฝนทักษะได้บ้างในจุดนี้

ดาวน์โหลดโปรแกรม (Download)

ไปที่หน้าดาวน์โหลด มองหาโปรแกรมคำนวณโค้งราบ HCurve  จะได้ไฟล์ชื่อ “HCURVEEX.G1A” เมื่อดาวน์โหลดมาแล้วโอนเข้าเครื่องคิดเลขผ่านทางโปรแกรม FA-124 หรือ SD Card

ใช้งานฟรี (Freely Usable)

ก็ยังเหมือนเดิมไม่ว่าจะโปรแกรมบนเครื่องคอมพิวเตอร์หรือบนเครื่องคิดเลข คือให้ใช้งานได้ฟรี

เริ่มต้นใช้งาน

ที่เครื่องคิดเลขกดคีย์ “Menu” เพื่อเข้าสู่หน้า AddIn หรือ  Main Menu ของเครื่องคิดเลข เลื่อนลูกศรลงไปด้านล่างๆจะเห็นไอคอนของโปรแกรมดังรูปด้านล่าง กดคีย์ “EXE” เพื่อเข้าสู่โปรแกรม

จะเห็นหน้าเมนูหลักของโปรแกรมดังนี้

ก็เหมือนโปรแกรมคำนวณโค้งดิ่ง (VCurve) ที่ผ่านมาคือมีเมนูย่อยเรียงจากซ้ายไปขวา สัมพันธ์กับการกดคีย์ F1-F6 เรียงกันไป

เมนูหลัก (Main Menu)

F1 (Know) – Known สำหรับป้อนจุดที่ทราบค่า station และค่าพิกัด

F2 (Angl) – Angle สำหรับป้อนที่เกี่ยวกับมุมเช่น back tangent azimuth และมุมเบี่ยงเบน (Deflection Angle) ตลอดจนถึงทิศทางของโค้ง (Curve Direction)

F3 (Elem) – Elements สำหรับป้อนองค์ประกอบของโค้งเช่นรัศมีหรือความยาวโค้าง

F4 (Info) – Information สำหรับคำนวณหาข้อมูลพื้นฐานของโค้งทั้งหมด

F5 (Calc) – Calculate สำหรับคำนวณหาค่าพิกัดโค้งได้หลายรูปแบบเช่นกำหนดสถานี ระยะ offset ตลอดจนคำนวณจากช่วงระยะทาง (interval) ที่กำหนดให้

F6 (Exit) – Exit ออกจากโปรแกรม

ตัวอย่างการคำนวณโค้งราบ (Example)

มาดูวิธีการใช้งานจากตัวอย่างจะเข้าใจง่ายที่สุด

เลือกและป้อนสถานีที่ทราบและค่าพิกัด (Known Station and Know Coordinates)

ที่เมนูหลักกดคีย์ F1 (Know) แก้ไขค่าตามโจทย์ตัวอย่างที่ 1 ดังนี้

ในที่นี้สถานีและค่าพิกัดกำหนดที่จุด PI ทั้งคู่ เมื่อป้อนค่าเสร็จแล้วกดคีย์ F6 (OK) เพื่อออก

เลือกป้อนมุมอะซิมัทและมุมเบี่ยงเบน(Known Tangent and Deflection Angle)

ที่เมนูหลักกดคีย์ F2 (Angl) เพื่อเลือกอะซิมัทของเส้นสัมผัสที่ทราบค่าและมุมเบี่ยงเบน ตลอดจนป้อนทิศทางของโค้งราบว่าเลี้ยวซ้ายหรือเลี้ยวขวา จากตัวอย่างเลือกและป้อนค่าดังนี้

เสร็จแล้วกดคีย์ F6 (OK) เพื่อจัดเก็บค่าและออก

ป้อนองค์ประกอบโค้งราบ (Elements of Curve)

ที่เมนูหลักกดคีย์ F3 (Elem)  เลือกว่าจะป้อนค่ารัศมีโค้ง (Radius) หรือว่าความยาวโค้ง (Length of Curve) ในที่นี้เลือกรัศมีโค้งและป้อนค่า 201.950 เมตร

คำนวณหาข้อมูลพื้นฐานโค้งราบ (Curve Information)

ที่เมนูหลักกดคีย์ F4 (Info)

แสดงองค์ประกอบของโค้งและข้อมูลพื้นฐาน ค่าพิกัดของจุด PC, PI และ PT ตลอดจนจุดศูนย์กลางของโค้ง เนื่องจากจอภาพมีขนาดเล็กดังนั้นใช้การกดคีย์ F1 (PgUp) หรือ F2 (PaDn) เพื่อเลื่อนดูหน้าก่อนหน้านี้หรือหน้าถัดไป กดคีย์ F6 (Done) เพื่อออก

การคำนวณโค้งราบ (Horizontal Curve Calculation)

ที่เมนูหลักกดคีย์ F5 (Calc)จะเห็นเมนูย่อยอีกเมนูคือเมนูสำหรับคำนวณโค้งราบ

จะมีเมนูดังนี้

F1 (Sta) – Station คำนวณหาค่าพิกัดเมื่อกำหนดสถานี

F2 (INT) – Interval คำนวณหาค่าพิกัดสถานีเมื่อกำหนดช่วงระยะทาง (Interval) ให้

F4 (Info) – Information คำนวณข้อมูลพื้นฐานโค้งราบ โดยที่ผลลัพธ์เหมือนกับเมนู Info บนเมนูหลัก

F5 (Plot) – Plot Curve วาดรูปร่างโค้งราบ

F6 (Done) ออกจากเมนูคำนวณโค้งราบ

คำนวณหาค่าพิกัดเมื่อกำหนดสถานี (Calculate Coordinates of Station)

ที่เมนูคำนวณโค้งราบกดคีย์ F1 (Sta) จะมีไดอะล็อกให้ป้อนสถานี ตัวอย่างนี้ต้องการทราบค่าพิกัดของสถานี 17+200 โดยที่ offset ไปด้านซ้าย 8 เมตร ป้อนข้อมูลดังรูป ถ้าไม่ต้องการคำนวณหรือเก็บข้อมูลที่ป้อนก็กดคีย์ F5 (Canc) เพื่อ Cancel ออกไป หรือต้องการเก็บค่าแต่ไม่คำนวณก็กดคีย์ F6 (OK) ออกไป ถ้าต้องการคำนวณก็กดคีย์ F1 (Calc) จะได้ผลลัพธ์ดังรูปถัดไป กดคีย์ “EXE” เพื่อออก

คำนวณหาค่าพิกัดสถานีแบบกำหนดช่วงระยะทาง (Interval Calculation)

ที่เมนูคำนวณโค้งกดคีย์ F2 (INT) ในที่นี้ต้องการคำนวณทุกๆระยะ 25 เมตร โดยคำนวณในแนว Center Line (ไม่มีการ offset ไปซ้ายหรือขวา) กดคีย์ F1 (Calc) เพื่อคำนวณ

จะได้ผลลัพธ์ เริ่มตั้งแต่ PC (17+151.314), Sta 17+175, Sta 17+200, Sta 17+225, Sta 17+250, Sta 7+275, Sta 17+300 และสุดท้ายที่ PT (17+313.794) กด F1 (PgUp) เพื่อเลื่อนไปหน้าก่อนหน้านี้ และกด F2 (PgDn) เพื่อไปดูหน้าถัดไป กด F6 (Done)

 

วาดรูปโค้งราบ (Plot Curve)

จากเมนูคำนวณโค้งราบ กดคีย์ F5 (Plot) จะมีเมนูย่อยลงไปอีกสำหรับย่อ F1 (Z-) ขยาย F2 (Z+) ดึงรูปไปด้านซ้าย F3 (Lt) ดึงรูปไปด้านขวา F4 (Rt) กดคีย์ F5 (>) เพื่อไปเมนูย่อยอีกเมนูด้านขวา เมนูด้านขวาจะมีดึงรูปลง F1 (Dn) หรือดึงรูปขึ้น F2 (Up) กดคีย์ F6 (Exit) เพื่อออกจากเมนู

ก็อย่างว่าเครื่องคิดเลขรุ่นนี้เป็นจุดภาพ (pixel) บนจอภาพ ไม่ใช่จอภาพแบบโทรศัพท์มือถือในปัจจุบันที่มีความละเอียดสูง ข้อเสียคือแสดงภาพความละเอียดสูงไม่ได้ แต่ข้อดีไม่เปลืองแบตเตอรี สังเกตว่าแค่ถ่าน AAA สามก้อนใช้กันจนลืมครับ ดังนั้นก็ดูรูปโค้งพอให้เกิดจินตนาการว่าโค้งวางตัวในลักษณะไหน เวลาไปอยู่หน้างานจะได้วางภาพในใจได้

จัดเก็บข้อมูลและเรียกมาใช้ภายหลัง

เพื่อให้ผู้ใช้งานได้สะดวก การจับเก็บตัวแปรเช่นค่าพิกัดที่เคยป้อนไปแล้ว เมื่อเปิดโปรแกรมมาอีกรอบค่านั้นจะยังอยู่ ผมจึงอาศัยวิธีการจัดเก็บไฟล์ลงบน SDCard ที่เสียบไว้ที่เครื่องคิดเลขของเรา เมื่อออกจากโปรแกรม และจออ่านไฟล์มาอีกทีเมื่อเปิดโปรแกรม

ก่อนจะใช้งานได้ต้องมีการเตรียมโฟลเดอร์บน SDCard ดังต่อไปนี้  คือดึง SDCard จากเครื่องคิดเลขมาเสียบบนคอมพิวเตอร์ แล้วทำการสร้างโฟลเดอร์ชื่อ “svdata” ดังรูป แต่ถ้ามีการสร้างมาแล้วก็ไม่จำเป็นต้องทำอะไร

จากนั้นนำ SDCard มาเสียบบนเครื่องคิดเลขอีกครั้ง เมื่อนำไปใช้งานได้สักพักถ้าเอามาเปิดอีกครั้งจะเห็นไฟล์หลายๆไฟล์ มีนามสกุลเป็น “CFG”  หมายถึง config ตัวอย่างถ้าใช้โปรแกรมคำนวณโค้งราบนี้ไฟล์ที่จัดเก็บข้อมุลคือ “HCVEX.CFG

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 6 โปรแกรมคำนวณโค้งดิ่ง (Vertical Curve)

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 6 โปรแกรมคำนวณโค้งดิ่ง (Vertical Curve)

ประเภทลักษณะของโค้ง (Type of Curve)

โค้งในงานถนน งานรถไฟมีสองแบบคือโค้งราบ (Horizontal Curve) และโค้งดิ่ง (Vertical Curve) โค้งราบเป็นตัวกำหนดรูปรางและทิศทางของถนนในแนวราบ ส่วนโค้งดิ่งเป็นโค้งที่รองรับลักษณะภูมิประเทศขึ้นๆลงๆ การออกแบบโค้งสำหรับงานวิศวกรรมงานถนนนั้นเพื่อให้มีความปลอดภัยต่อยวดยานผู้ขับขี่ตลอดทั้งผู้โดยสาร

ประเภทโค้งดิ่ง (Type of Vertical Curve)

โค้งดิ่งจะแบ่งเป็นเส้นโค้งพาราโบลา (Parabola Vertical Curve) ลักษณะนี้จะเป็นโค้งที่นิยมกันมากที่สุดในโลกนี้แทบจะว่า 99% ก็ได้เพราะเวลารถยนต์หรือรถไฟเข้าโค้งนี้จะมีความนุ่มนวลมากที่สุด และเส้นโค้งประเภทต่อไปคือเส้นโค้งวงกลม (Circular Vertical Curve) ตามที่ได้ยินมาคือโค้งวงกลมนี้จะมีความสบายและความนุ่มนวลน้อยกว่าเส้นโค้งพาราโบลา จึงมีความนิยมน้อยกว่า ผมค้นหาในเว็บโดยใช้เสิร์ชเอนจิ้นปรากฎว่าเจอแค่เว็บเดียวที่เป็นเอกสาร PDF อธิบายสูตร คิดดูแล้วกันครับว่ามันใช้กันน้อยขนาดไหน ถึงแม้จะใช้กันน้อยมากแต่ผมก็มีโอกาสได้ใช้โค้งดิ่งแบบวงกลมนี้ในโครงการรถไฟฟ้าที่บังคลาเทศ แต่แปลกแต่จริงสำหรับรถไฟความเร็วสูงกลับนิยมใช้โค้งดิ่งแบบวงกลมมากกว่าพาราโบลา ซึ่งใช้รัศมีที่ใหญ่มากประมาณ10 กม.ขึ้นไป

ลักษณะของโค้งดิ่งจะมี 2 ลักษณะคือ โค้งหงาย (Sag Curve) และโค้งคว่ำ (Crest Curve)

โค้งทางดิ่ง (vertical Curve) แบบโค้งคว่ำ (Crest Curve) เครดิตภาพ wikibooks.org

ออกแบบโปรแกรมใหม่ (New Design)

ถ้าลองใช้โปรแกรมเครื่องคิดเลข Casio fx-9860G ที่ผมปล่อยฟรีมาก่อนหน้านี้ ระบบการติดต่อผู้ใช้จะเป็นลักษณะจากบนลงล่างคือเปิดโปรแกรมมาแล้ว โปรแกรมจะถามค่าตัวแปร เมื่อผู้ใช้ป่อนค่าลงไปจนครบ ต่อไปจะเป็นการนำค่าตัวแปรเหล่านี้มาคำนวณและแสดงผลให้ทราบ วิธีการดีตรงที่ตรงไปตรงมา ผู้ใช้จะถูกบังคับให้ป้อนค่าตามที่โปรแกรมต้องการจนครบ แต่ข้อเสียเมื่อต้องการคำนวณอีกครั้งในกรณีป้อนค่าผิดต้องการป้อนใหม่ จะต้องเรียกโปรแกรมมาอีกครั้งตั้งแต่ต้น ทำให้เสียเวลามากเกินไป จนในที่สุดก็ต้องหาตัวช่วยมาช่วยและก็ได้พบกับไลบรารี MyLib

ไลบรารี MyLib

ผมมีโอกาสได้เห็นโปรแกรมเครื่องคิดเลข HP 50g จากเว็บไซต์ที่ทางฝั่งผู้พัฒนาจากแคนาดาชื่อ Simple Geospatial Solution โปรแกรมนี้ไม่ฟรีต้องเสียเงินซื้อ ผมลองดูรูปแบบแล้วน่าสนใจ เลยกลายเป็นแรงบันดาลใจ หน้าตาประมาณรูปด้านล่าง

โปรแกรมสำรวจบนเครื่องคิดเลข HP 50g

หันมามองฝั่งเครื่องคิดเลข Casio fx-9860G ผมได้เจอคนเขียนไลบรารีเล็กๆชื่อ MyLib จากผู้ใช้นามว่า  hayzel ปล่อยซอร์สโค้ดภาษาซีออกมาด้วย ไลบรารีนี้สามารถนำมาเขียนเมนูเพื่อติดต่อกับผู้ใช้งาน และสามารถสร้างไดอะล็อกเพิ่อป้อนข้อมูลได้ และมีโค้ดสำหรับช่วยในการวาดรูปอีกนิดหน่อย ผมดูโค้ดแล้ว ถ้าให้ผมเขียนเองคงทำไม่ได้แน่ แต่ถ้าจะแกะเอามาใฃ้ก็เป็นงานถนัดไม่เหลือบ่ากว่าแรง ก็ต้องยกเครดิตและขอขอบคุณผู้เขียนไลบรารีนี้ ไม่มีไลบรารีนี้ก็ไม่มีโปรแกรมนี้

รูปแบบการติดต่อผู้ใช้ (User Interface)

รูปแบบการติดต่อผู้ใช้ ผมเขียนโปรแกรมโดยที่ออกแบบเมนูเล็กๆเรียงจากซ้ายไปขวาวางด้านล่างหน้าจอ  วิธีการนี้ผู้ใช้จะแก้ไขข้อมูลตรงไหนก็สามารถเลือกเมนูเข้าไปแก้ไขได้ การเลือกเมนูในเครื่องคิดเลขก็สามารถทำได้ง่ายด้วยการกดคีย์ F1-F6 เรียงกันไป

ไลบราาี MyLib บนเครื่องคิดเลข Casio fx-9860G

ใช้งานได้ฟรี (Free to use)

ก็ยังเหมือนเดิมคือให้ใช้งานได้ฟรีไม่มีค่าใช้จ่ายและเพื่อช่วยเหลือวงการสำรวจบ้านเราเล็กๆน้อยๆตามกำลังที่ผมมีอยู่ โปรแกรมขนาดนี้ประมาณ 800-1000 บรรทัดดูมากสำหรับเครื่องคิดเลข แต่ถ้าเทียบกับโปรแกรมบนเครื่องคอมพิวเตอร์ถือว่าเล็กจิ๊บๆมาก

คำนิยาม (Abbreviations)

สำหรับโค้งดิ่งจะมีคำนิยามคำย่อ ที่บางตำราอาจจะเรียกแตกต่างกัน

BVC – Begin of Vertical Curve – จุดเริ่มโค้ง(บางทีเรียก PVC – Point of Vertical Curve)
PVI – Point of Vertical Intersection – จุดตัดแนวดิ่ง
EVC – End of Vertical Curve  – จุดสุดโค้ง(บางทีเรียกว่า PVT – Point of Vertical Tangent)
L – Length of Curve – ความยาวโค้ง
R – Radius – รัศมีโค้ง ใช้ในโค้งดิ่งแบบวงกลม(Circular Vertical Curve) เท่านั้น
g1 – Grades of Tangents (%) – ความชันด้านสัมผัสที่ผ่านจุด BVC/PVC
g2 – Grades of Tangents (%) – ความชันด้านสัมผัสที่ผานจุด EVC/PVT

ดาวน์โหลดโปรแกรม (Download)

ไปที่หน้าดาวน์โหลด มองหาโปรแกรม VCurve สำหรับเครื่องคิดเลข Casio fx-9860G แล้วทำการดาวน์โหลดจะได้ไฟล์ VCURVEEx.G1A ทำการติดตั้งลงเครื่องคิดเลขด้วยโปรแกรม FA-124 หรือ copy ผ่าน SD Card ก็ได้

วิธีการใช้งานโปรแกรม (How to Use)

ที่เครื่องคิดเลขกดคีย์ “Menu” จะเห็นโปรแกรม AddIn ขึ้นมาใช้คีย์ลูกศรกดไปจนพบกับไอคอนโปรแกรมดังรูป กดคีย์ “EXE” เพื่อรันโปรแกรม

เมนูหลัก (Main Menu)

จะเห็นเมนูโปรแกรมเรียงรายจากซ้ายมาขวาอยู่ที่ด้านลางของจอภาพ แต่ละเมนูจะสัมพันธ์กับคีย์ F1 ,F2, F3, F4, F5 และ F6 

เมนูหลัก (main menu)

Type – Curve Type – เลือกประเภทโค้งดิ่ง (F1)

Know – Known Station – เลือก Station ที่กำหนดค่าระดับ (F2)

Elem – Elements of Curve – ป้อนค่าส่วนประกอบของโค้ง (F3)

Info – Curve Information – แสดงข้อมูลโค้ง (F4)

Calc – Calculate – คำนวณโค้งเพื่อหาสถานี ค่าระดับ (F5)

Exit – Exit Program – ออกจากโปรแกรม (F6)

ตัวอย่างที่ 1 โค้งดิ่งแบบพาราโบลา (Example 1 – Parabola Curve)

ลักษณะโค้งดิ่ง (Vertical curve diagram)

ลักษณะเป็นโค้งหงาย (Sag Curve) ความยาวโค้ง 200 เมตร ต้องเตือนใจกันลืมนิดหนึ่งความยาวโค้งดิ่งที่ระบุมานั้นเป็นความยาวในแนวราบ  (ไม่ใช่ระยะทางวัดไปตามความยาวโค้ง)

เลือกประเภทโค้งดิ่ง

จากเมนูหลักเลือกกดคีย์ F1 (Type) จะเป็นการเลือกประเภทของโค้ง จะเห็น Dropdown List

เมนูหลัก (main menu)
ประเภทโค้งดิ่ง (Curve type)

กดคีย์ “EXE” เพื่อเลือก จะเห็นมีสองทางเลือกคือลักษณะเป็นโค้งดิ่งแบบวงกลม (Circular) กับโค้งดิ่งแบบพาราโบลา สามารถใช้คีย์ลูกศรเลื่อนขึ้นลงเพื่อเลือกได้ ในที่นี้เราเลือก “Parabola” ด้วยการกดคีย์ “EXE” เมื่อเสร็จแล้วกดคีย์ F6 (OK) เพื่อยืนยัน ถ้าต้องยกเลิกก็กดคีย์ F5(Canc)

เลือกสถานีที่ทราบค่าระดับ (Known Station)

กลับมาเมนูหลักกดคีย์ F2 (Know) จะเห็นจอภาพเครื่องคิดเลขดังรูปด้านล่าง

กำหนดสถานีที่ทราบค่า (Known station)

ตรง “Known” สามารถเลือกได้ว่าต้องการกำหนดค่าระดับที่สถานีไหน จะมีให้เลือก 3 อย่างคือ BVC/PVI/EVC เลื่อนคีย์ลูกศรขึ้นลงแล้วกดคีย์ “EXE” ตามตัวอย่างนี้เลือก “PVI

 

จากนั้นเลื่อนค่าลงไปที่ Station กดคีย์ “EXE” โปรแกรมจะแสดงไดอะล็อกให้ป้อนค่าสถานีลงไปตามตัวอย่างนี้ป้อน Station : 1000 ดังรูปด้านล่าง

และเลื่อนลูกศรไปป้อนค่า Elevation = 50 เมตรเข้าไป เสร็จแล้วกดคีย์ F6 (OK) เพื่อยืนยัน

ป้อนข้อมูลองค์ประกอบของโค้งดิ่ง (Elements of Vertical Curve)

ที่เมนูหลักกดคีย์ F3 (Elem) 

องค์ประกอบของโค้งจะประกอบไปด้วยความยาวโค้ง (L – Length of Curve), ความชันของเส้นสัมผัสด้านเข้าโค้ง (g1 – Entry Grade) และความชันของเส้นสัมผัสด้านออกโค้ง (g2 – Exit Grade) ป้อนข้อมูลตามรูปด้านบนโดยที่ L = 200 m, g1 = -2 % และ g2 = 3%

คำนวณโค้งหาข้อมูลพื้นฐาน (Curve Information)

ที่เมนูหลักกดคีย์ F4 (Info) โปรแกรมจะคำนวณข้อมูลพื้นฐานของโค้งมาให้  และแสดง station/elevation ของจุดต่ำสุดและสูงสุดของโค้งมาให้ด้วย

คำนวณโค้งหาระยะทางและค่าระดับ

ที่เมนูหลักกดคีย์ F5 (Calc) จะเห็นเมนูคำนวณโค้งดิ่ง

Elev? – Elevation? – คำนวณหาค่าระดับเมื่อทราบระยะทางหรือสถานี

Sta? – Station? – คำนวณหาระยะทางหรือสถานีเมื่อทราบค่าระดับ

INT – Interval – คำนวณหาระยะทางหรือสถานีและค่าระดับเมื่อกำหนดช่วงระยะทางให้

Info – Curve Information – คำนวณหาข้อมูลพื้นฐานโค้งดิ่ง

Plot – Plot Curve – วาดรูปโค้งดิ่ง

Done  – ออกจากเมนูคำนวณโค้ง

คำนวณหาค่าระดับ (Calculate Elevation)

ในกรณีทราบระยะทางหรือสถานีต้องการหาค่าระดับเช่นในภาคสนามต้องการ stake out สามารถคำนวณได้ ที่เมนูคำนวณโค้งดิ่ง กดคีย์ F1 (Elev?) ป้อนค่า 920 (0+920) ลงไป การป้อนสถานี้ให้ป้อนเป็นหน่วยเมตรไปก่อน รุ่นหน้าจะสามารถป้อนในลักษณะ 0+920 ได้ เมื่อป้อนเสร็จแล้วกดคีย์ F6 (OK) เพื่อยืนยัน

กดคีย์ F1 (Calc) เพื่อทำการคำนวณ จะได้ค่าระดับ 51.650 เมตร ดังรูปด้านล่าง

คำนวณหาสถานี (Calculate Station)

ในกรณีทราบค่าระดับต้องการคำนวณหาระยะทางหรือสถานี ที่เมนูคำนวณโค้งกดคีย์ F2 (Sta?) 

ป้อนค่า 51.5 เมตร กดคีย์ F1 (Calc) จะได้คำตอบเป็นสถานี 2 สถานีเพราะว่าเป็นโค้งหงายที่ค่าระดับเดียวกันคือ 51.5 เมตรถ้าลากเส้นตรงจะตัดผ่าน 2 สถานีคือสถานี 931.010 (0+931.010) และสถานี 1028.990 (1+028.990)

กำหนดช่วงห่างระยะทางคำนวณหาสถานีและค่าระดับ (Interval Calculation)

เมื่อกำหนดช่วงห่างระยะทาง (Interval) ต้องการหาระยะทาง(สถานี)และค่าระดับ ที่เมนูคำนวณโค้งดิ่งกดคีย์ F3 (INT) ตัวอย่างต้องการทราบระยะทางและค่าระดับทุกๆ 10 เมตร ป้อน 10.0 ดังรูป

กดคีย์ F1 (Calc) เพื่อทำการคำนวณจะได้ผลลัพธ์ออกมา ผลลัพธ์อาจจะมีหลายหน้าถ้าช่วงห่างระยะทางมีค่าน้อยๆ

กดคีย์ F2 (PgDn – Page Down) เพื่อดูหน้าถัดไป

ต้องการดูหน้าก่อนหน้านี้ก็กดคีย์ F1 (PgUp – Page Up) หรือกด F6 (Done) เพื่อออก

แสดงรูปรางของโค้งดิ่ง (Plot Curve)

การป้อนค่าและคำนวณโค้งดิ่งอาจจะไม่เห็นภาพว่าโค้งในลักษณะแบบไหน ผมจึงวาดแสดงให้ดูพอได้เกิดจินตนาการ เพราะว่าไลบรารีที่ใช้ในโปรแกรมเพื่อช่วยการวาดจำกัดจำเขี่ยเหลือเกิน ตัวอย่างเช่นไม่สามารถแสดงตัวอักษรแบบในอื่นได้นอกจากแนวราบ

ที่เมนูโค้งดิ่งกดคีย์ F5 (Plot) จะเห็นรูปร่างของโค้งดิ่งแสดงให้เห็นพอหอมปากหอมคอ (หมายเหตุ สเกลแนวราบแนวดิ่งอาจจะไม่เท่ากัน)


กดคีย์ F6 (Done) เพื่อออก

ตัวอย่างที่ 2 โค้งดิ่งแบบวงกลม (Example 2 – Circular Vertical Curve)

ก็จะขอไปแบบรวบรัดรูปเยอะๆ ภาพเครื่องคิดเลขอาจจะดูแปลกตานิดเพราะผมจับภาพจากเครื่องมือเขียนโปรแกรมบนเครื่องคอมพิวเตอร์

เลือกลักษณะของโค้งดิ่ง

เมนูหลัก กดคีย์ F1 (Type)
เลือกลักษณะโค้งดิ่ง กดคีย์ “EXE”
เลือกโค้งดิ่งแบบวงกลม (Circular)

กด F6 (OK) ออกไปหน้าเมนูหลัก

เลือกสถานีที่ทราบค่าระดับ (Known Station)

เมนูหลัก กดคีย์ F2 (Know)
ป้อนค่าสถานีและค่าระดับที่ทราบค่า

กดคีย์ F6 (OK) เพื่อออกกลับมาเมนูหลัก

ป้อนข้อมูลองค์ประกอบของโค้งดิ่ง (Elements of Vertical Curve)

เมนูหลัก กดคีย์ F3 (Elem)
ที่ Known: เลือก “Radius” ป้อนค่ารัศมีโค้งและค่าความชัน

กดคีย์ F6 (OK) เพื่อออกเข้าเมนูหลัก

คำนวณโค้งหาข้อมูลพื้นฐาน (Curve Information)

เมนูหลัก กดคีย์ F4 (Info)
องค์ประกอบของโค้งดิ่ง

กดคีย์ F6 (Done) เพื่อออกเข้าเมนูหลัก

เมนูหลัก กดคีย์ F5 (Calc)

กำหนดช่วงห่างระยะทางคำนวณหาสถานีและค่าระดับ (Interval Calculation)

เข้ามาเมนูคำนวณโค้งดิ่ง

กำหนดช่วงห่างระยะทางคำนวณหาสถานีและค่าระดับ (Interval Calculation)

ป้อนค่า  interval 5.0 เมตร เพื่อต้องการหาค่าสถานีและค่าระดับทุกๆ 5 เมตร

ป้อนค่า Interval กดคีย์ F1 (Calc)

กดคีย์ F1 (PgUp) เพื่อเลื่อนขึ้นไปหนึ่งหน้าหรือกดคีย์ F2 (PgDn) เพื่อเลื่อนไปหน้าถัดไป หรือกดคีย์ F6 (Done)  ออกมาเมนูคำนวณโค้งดิ่ง

 

แสดงรูปรางของโค้งดิ่ง (Plot Curve)

เมนูคำนวณโค้งดิ่ง

กดคีย์ F5 (Plot) เพื่อแสดงรูปร่างของโค้งดิ่ง

รูปร่างโค้งดิ่งแบบวงกลม

อยากจะเรียนให้ทราบว่าโปรแกรมที่ปล่อยให้ดาวน์โหลดมาก่อนหน้านี้ ผมจะรื้อมาเขียนใหม่ โดยใช้ไลบรารี MyLib ตัวนี้ เพราะว่าทำให้โปรแกรมใช้งานได้ง่ายขึ้นในแง่ที่สามารถแก้ไขค่าตัวแปรของโค้งและสามารถคำนวณใหม่ได้ตามที่ต้องการ ติดตามกันต่อไปครับ ตอนหน้าจะเป็นโปรแกรม Horizontal Curve ครับ

จัดเก็บข้อมูลและเรียกมาใช้ภายหลัง

ก่อนหน้านี้ผมพยายามจะใช้ตัวแปร A-Z เพื่อจัดเก็บค่าพิกัดหรือข้อมูลที่เราป้อนตอนใช้งาน เมื่อเปิดมาใช้งานใหม่สามารถเรียกกลับมาใช้ต่อได้ แต่ก็ยุ่งยากเพราะสามารถจัดเก็บได้น้อย จากตัวแปรบนเครื่องคิดเลข A-Z ได้แค่ 24 ตัวเท่านั้น ผมจึงอาศัยวิธีการจัดเก็บไฟล์ลงบน SDCard ที่เสียบไว้ที่เครื่องคิดเลขของเรา เมื่อออกจากโปรแกรม และอ่านอีกทีเมื่อเปิดโปรแกรม

ก่อนจะใช้งานได้ต้องมีการเตรียมโฟลเดอร์บน SDCard ดังต่อไปนี้  คือดึง SDCard จากเครื่องคิดเลขมาเสียบบนคอมพิวเตอร์ แล้วทำการสร้างโฟลเดอร์ชื่อ “svdata” ดังรูป

จากนั้นนำ SDCard มาเสียบบนเครื่องคิดเลขอีกครั้ง เมื่อนำไปใช้งานได้สักพักถ้าเอามาเปิดอีกครั้งจะเห็นไฟล์หลายๆไฟล์ มีนามสกุลเป็น “CFG”  หมายถึง config ตัวอย่างถ้าใช้โปรแกรมคำนวณโค้งดิ่งนี้ไฟล์ที่จัดเก็บข้อมุลคือ “VCVEX.CFG

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 4 โปรแกรมพื้นฐานงานสำรวจชุดที่ 1 (COGO SSE 1)

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 4 โปรแกรมพื้นฐานงานสำรวจชุดที่ 1 (COGO SSE 1)

COGO (Coordinate Geometry)

ผมพยายามจะแปลคำนี้เป็นภาษาไทยอยู่นานทีเดียว แต่สุดท้ายขอทับศัพท์ดีกว่า จริงๆแล้วงานสำรวจคืองานที่เกี่ยวกับทรงเรขาคณิต (Geometry) อยู่แล้ว และต้องสามารถระบุค่าพิกัด (Coordinate) ทุกๆจุดได้บนเรขาคณิตนั้นๆ ความเกี่ยวข้องระหว่างรูปทรงเรขาคณติกับค่าพิกัดจะเกี่ยวข้องกันด้วยมุมและระยะทางเป็นส่วนใหญ่

Selected Serie 1 (SSE 1)

คำนี้เอามันครับ ผมนึกถึงโปรแกรมตระกูลไมโครสเตชัน (Microstation) ที่มักจะใช้คำนี้บอกรุนของโปรแกรม ดังนั้นคำว่า  Selected Serie 1 คำแปลก็ประมาณว่าเลือกสรรแล้วชุดที่ 1

โปรแกรมพื้นฐานงานสำรวจชุดที่ 1 (COGO SSE 1)

ก่อนหน้านี้ผมเขียนโปรแกรมภาษาซีสำหรับเครื่องคิดเลข Casio fx-9860G II SD มาหลายตอนแต่เป็นโปรแกรมระดับ advance มาในตอนนี้จะกลับมาที่พื้นฐานงานสำรวจที่ต้องเกี่ยวข้องกับค่าพิกัด มุมและระยะทาง

ดาวน์โหลดและติดตั้ง

ไปที่หน้าดาวน์โหลด (Download) มองหาโปรแกรม COGO SSE1 แล้วดาวน์โหลดจะได้ไฟล์ COGOSSE1.G1A  แล้ว copy ไฟล์ไปที่เครื่องคิดเลขตามวิธีขั้นตอนที่ผมได้บอกไว้ก่อนหน้านี้

ส่วนประกอบของโปรแกรม

สำหรับโปรแกรมพื้นฐานงานสำรวจในชุดนี้จะจัดโปรแกรมย่อยเล็กๆ ไว้ 4 โปรแกรม

  1. Bearing-Dist (2 pt) เมื่อกำหนดจุดค่าพิกัด 2 จุด สำหรับคำนวณหามุมอะซิมัทและระยะทาง
  2. Bearing-Dist(3 pt) เมื่อกำหนดจุดค่าพิกัด 3 จุด สำหรับคำนวณหาง่ามมุมราบ อะซิมัทและระยะทาง ในงานสำรวจก็ได้แก่การตั้งเป้าหลัง  (backsight)  จุดตั้งกล้อง (station) และเป้าหน้า (target)
  3. Coordinate 2D เมื่อกำหนดจุดค่าพิกัด 2 จุด กำหนดมุมราบและระยะราบ คำนวณหาค่าพิกัดจุดที่ 3 คำนวณหาพิกัดจุดที่ 3 การคำนวณคำนวณในระนาบสองมิติอย่างเดียว ไม่มีค่าระดับมาเกี่ยวข้อง
  4. Coordinate 3D เมื่อกำหนดจุดค่าพิกัด 2 จุด กำหนดมุมราบและมุมดิ่ง ระยะทางแบบ slope distance ต้องการคำนวณหาค่าพิกัดและค่าระดับจุดที่ 3

วิธีการใช้งานโปรแกรม

กดคีย์ “MENU” ที่เครื่องคิดเลขจะเห็นหน้าตาประมาณนี้ เลื่อนลูกศรไปที่ไอคอนของโปรแกรมดังรูป กดคีย์ “EXE”

Bearing-Dist (2 pt)

ที่เมนูกดคีย์ “1” เป็นการคำนวณหาค่ามุมอะซิมัทและระยะทางเมื่อกำหนดจุดค่าพิกัดให้สองจุด ลองทดสอบจากตัวอย่างดังรูป การประยุกต์ใช้งานส่วนใหญ่เป็นตอนที่ช่างสำรวจตั้งกล้องที่หมุดและส่องไปเป้าหลังหรือเป้าหน้าแล้ววัดระยะทางเพื่อตรวจสอบจากค่าพิกัด

ผลลัพธ์ก็ออกมาดังนี้

Bearing-Dist (3 pt)

ที่เมนูกดคีย์เลข “2” การประยุกต์ใช้งานส่วนใหญ่จะเป็นการตั้งกล้องส่องไปหมุดเป้าหลังแล้วป้อนค่าพิกัดเป้าหน้าเพื่อตรวจสอบมุมราบหรือไม่ก็จะเป็นการวางผังโดยการเปิดมุมราบและวัดระยะทางที่เป้าบน pole ลองดูตัวอย่างทดสอบ

จะได้ผลลัพธ์มาดังนี้ ครั้งแรกจะแสดงมุมอะซิมัทและระยะทางไปเป้าหลังก่อน

ถัดไปจะเป็นมุมราบ มุมอะซิมัทและระยะทางไปเป้าหน้า

Coordinate 2D

ที่เมนูกดคีย์เลข “3” เป็นการคำนวณหาค่าพิกัดเป้าหน้าเมื่อกำหนดค่าพิกัดจุดตั้งกล้องและเป้าหลัง กำหนดมุมราบและระยะทาง การคำนวณจะไม่มีค่าระดับมาเกี่ยวข้อง จึงเรียกว่า 2D หรือสองมิติ สำหรับโปรแกรมนี้ผมได้นำค่าสเกลแฟคเตอร์เข้ามาช่วยประยุกต์ใช้ด้วย ในกรณีที่ไม่ต้องใช้ก็ป้อนค่าสเกลแฟคเตอร์นี้ เป็น 1.0

สเกลแฟคเตอร์ตัวนี้แล้วจริงๆคือ Combine Scale Factor (CSF) ที่ได้จาก Elevation Scale Factor (ESF) x Grid Scale Factor (GSF) การประยุกต์ใช้สเกลแฟคเตอร์ส่วนใหญ่นำมาใช้โครงการที่ระบบพิกัดฉากกริดยูทีเอ็มในงานใหญ่ๆยาวๆ เช่นโครงการก่อสร้างถนน รถไฟ เพราะว่าแบบ drawing เราอยู่บนระนาบพิกัดฉาก ให้คิดเสียว่าแบบอยู่บนกระดาษขนาดใหญ่มาตราส่วน 1:1 แล้วเราวัดระยะทางบนผิวโลกที่มีความโค้ง ดังนั้นการวัดระยะทางจะต้องมีการทอนจากบนผิวโค้งเพื่อให้ลงมาเข้ากับระนาบพิกัดฉากของกระดาษ

มาลองทดสอบข้อมูล ป้อนข้อมูลค่าพิกัดเป้าหลัง ค่าพิกัดจุดต้องกลองดังนี้

จากนั้นป้อนมุมราบ และระยะทาง (Ground Distance ใช้ตัวย่อ Gnd dist) ในกรณีกล้องโททัล สเตชัน ไม่ได้ตั้งค่าสเกลแฟคเตอร์ไว้ที่ตัวกล้อง ระยะทางที่วัดออกมาจะเป็นระยะทางบนพื้นโลก ส่วนค่าสเกลแฟคเตอร์ในตัวอย่างผมใช้ 1.000480

 

โปรแกรมจะคำนวณมุมอะซิมัทและระยะทางไปเป้าหลังให้ดูก่อนเพื่อตรวจสอบ และไม่ลืมว่าค่าพิกัดที่เราป้อนเข้าไปในเครื่องคิดเลขคือค่าพิกัดในระบบพิกัดฉาก ระยะทางที่คำนวณออกมาคือระยะทางบนพิกัดฉาก (Grid Distance ใช้ตัวย่อ Grd Dist) และถ้าวัดระยะทางจริงๆควรจะได้เท่ากับ Ground Distance

ทวนกันนิด ระยะทางบนพิกัดฉาก(กริด)= ระยะทางบนพื้นโลก x สเกลแฟคเตอร์ 

สุดท้ายจะได้แสดงข้อมูลได้แก่มุมอะซิมัทไปเป้าหน้า ระยะทางบนพิกัดฉากและระยะทางบนพื้นโลก รวมทั้งค่าพิกัดเป้าหน้าที่ต้องการ

Coordinate 3D

ที่เมนูกดคีย์ “4” โปรแกรมคล้าย Coordinate 2D แต่จะมีมิติทางดิ่งเข้ามาเพิ่มดังนั้นที่จุดตั้งกล้องจะวัดความสูงของกล้อง (HI – Height of instrument) และที่เป้าหน้าก็จะต้องวัดความสูงมาด้วย (HT – Height of target) นอกจากนั้นจะมีมุมดิ่ง (Vertical angle) มาด้วย มาดูข้อมูลทดสอบกัน เริ่มจากป้อนค่าพิกัดเป้าหลัง ต่อมาป้อนค่าพิกัดจุดตั้งกล้อง ค่าระดับจุดตั้งกล้อง ความสูงกล้อง

ต่อไปป้อนมุมราบ(H.Ang) มุมดิ่ง(V.Ang) ระยะทาง (Slope distance) และความสูงเป้า(HT) และค่าสเกลแฟคเตอร์ (Scale Factor)

โปรแกรมจะคำนวณอะซิมัท ระยะทางจากจุดตั้งกล้องไปเป้าหลัง ข้อสังเกตผมใส่เครื่องหมายดาว (*) หน้าระยะทางบนพื้นโลก (Ground Distance)

กดคีย์ “EXE” จะได้ผลลัพธ์ อะซิมัท ระยะราบทั้งระยะบนพื้นโลกและระยะกริดจากจุดตั้งกล้องไปเป้าหน้า

สุดท้ายคือผลลัพธ์ที่ต้องการคือค่าพิกัดและค่าระดับของเป้าหน้า

สรุป

ก็พอหอมปากหอมคอสำหรับโปรแกรมพื้นฐานงานสำรวจชุดที่ 1 โดยมีสิ่งที่ช่างสำรวจจะต้องเข้าใจตั้งแต่เรื่องมุมอะซิมัทคือมุมอะไร สำคัญมากเพราะมุมนี้เป็นหัวใจขั้นพื้นฐานและจะสัมพันธ์กับระยะทางโดยที่แยกกันไม่ออกและสามารถนำไปคำนวณค่าพิกัดได้ สำหรับการคำนวณแบบนี้ โปรแกรมในกล้อง Total Station ปัจจุบันก็คำนวณให้อยู่แล้ว แล้วก็เก่งขึ้นเรื่อยๆ แต่ในทางกลับกัน สำหรับช่างสำรวจเอง คงไม่มีใครได้จับกล้องพวกนี้ได้ตลอดเวลา จำเป็นจะต้องมีเครื่องคิดเลขคู่ใจไว้ติดตัวตลอด สามารถหยิบมาใช้งานได้สะดวกและถ้ามีโปรแกรมที่จำเป็นสำหรับการทำงานติดอยู่ด้วย ชีวิตการทำงานก็พลอยลื่นไหล ติดตามตอนต่อไปครับ

แนะนำโปรแกรมมิ่งภาษาซีบนเครื่องคิดเลข Casio fx-9860G II SD ด้วยเครื่องมือพัฒนา SDK ของ Casio

แนะนำโปรแกรมมิ่งภาษาซีบนเครื่องคิดเลข Casio fx-9860G II SD ด้วยเครื่องมือพัฒนา SDK ของ Casio

เคยเกริ่นมาก่อนว่าต้องการเขียนบทความนี้ขึ้นมาเพื่อวงการศึกษาบ้านเราที่สนใจเรื่องโปรแกรมมิ่งบนเครื่องคิดเลขสามารถจะพัฒนาโปรแกรมภาษาซีบน Casio fx-9860G II SD หรือรุ่นที่ใกล้เคียงนี้ได้ โดยที่มีไม่มีข้อจำกัดด้านภาษาโปรแกรมมิ่ง เหมือนกับภาษา casio basic อาจจะส่งผลให้ในอนาคต มีโปรแกรมที่พัฒนาโดยบุคคลากรท่านอื่นๆ เข้ามาสู่วงการนี้มากขึ้น และได้ตัวโปรแกรมงานสำรวจที่มีความหลากหลายและความสามารถมากขึ้นทั้งนี้เพื่อขยายขีดความสามารถโปรแกรมบนเครื่องคิดเลขให้สามารถคิดงานที่ยาก ซับซ้อนได้ บางครั้งเกือบจะเทียบเท่าโปรแกรมที่ใช้งานบนคอมพิวเตอร์

เครื่องมือพัฒนา Software Development Kit (SDK)

เครื่องมือตัวนี้เดิมทีสามารถดาวน์โหลดที่เว็บไซต์ตามลิ๊งค์นี้ได้ http://edu.casio.com/support/en/agreement.html#2 ขั้นตอนแรกยอมรับเงื่อนไขแล้วเลื่อนหน้าไปด้านล่างๆจะเห็นเครื่องคิดเลขรุ่น fx-9860 เมื่อคลิกลิ๊งค์ SDK เข้าไปจะเห็นว่าลิ๊งค์เครื่องมือพัฒนาโปรแกรมขาด แต่คู่มือยังสามารถดาวน์โหลดมาอ่านศึกษาได้ ผมอาศัยลงใต้ดินที่มีคนปล่อยให้ดาวน์โหลด (ถ้าใครอยากได้เครื่องมือตัวนี้ก็ขอมาหลังไมค์กันได้ครับ) และดาวน์โหลดโปรแกรม FA-124 มาด้วยอยู่ในหมวด Support Software/PC Link software

ติดตั้งเครื่องมือพัฒนาโปรแกรม

เปิดไฟล์ zip ของเครื่องมือพัฒนาจะเห็นไฟล์ข้างในดังนี้

จากนั้นทำการติดตั้งเครื่องมือลงคอมพิวเตอร์  ข้อสำคัญคือพาทของโฟลเดอร์หรือไดเรคทอรีที่ติดตั้งจะต้องไม่มีช่องว่าง ดังนั้นให้ติดตั้งไปที่รากของไดรว์ C: ตัวอย่างผมใช้ชื่อว่า fx-9860-sdk 

ถ้าพาทของโฟลเดอร์ที่ติดตั้งมีช่องว่างการ compile & build จะไม่ผ่านเลย เมื่อติดตั้งแล้วจะมีไอคอนที่หน้า desktop

เริ่มต้นใช้งาน

เมื่อเปิดโปรแกรมจากไอคอนที่ desktop จะเห็นหน้าตาเครื่องมือพัฒนาโปรแกรม ดังรูป อาจจะดูทื่อๆเพราะเครื่องมือตัวนี้ออกมานานแล้วตั้งแต่วินโดส์รุ่นก่อนหน้านี้ ที่เมนู “Project” คลิกเลือก “New” ผมสร้างโฟลเดอร์ชื่อ “FX9860GIISD” ไว้ที่ไดรว์ D: และตั้งชื่อโฟลเดอร์สำหรับทดสอบการเขียนโปรแกรมนี้ว่า “Test” และตั้งชื่อโปรแกรมว่า “Hello”

จะเห็นหน้าตาเครื่องมือพัฒนาประมาณรูปด้านล่าง และตัวอีมูเลเตอร์ “Display” และ “Keyboard” ของ fx-9860G

Project แรกเริ่ม

เมื่อเราสร้าง Project ใหม่จะเห็นโครงร่างที่เครื่องมือเขียนมาให้ดังนี้

/*****************************************************************/
/*                                                               */
/*   CASIO fx-9860G SDK Library                                  */
/*                                                               */
/*   File name : Hello.c                                 */
/*                                                               */
/*   Copyright (c) 2006 CASIO COMPUTER CO., LTD.                 */
/*                                                               */
/*****************************************************************/
#include "fxlib.h"

//****************************************************************************
//  AddIn_main (Sample program main function)
//
//  param   :   isAppli   : 1 = This application is launched by MAIN MENU.
//                        : 0 = This application is launched by a strip in eACT application.
//
//              OptionNum : Strip number (0~3)
//                         (This parameter is only used when isAppli parameter is 0.)
//
//  retval  :   1 = No error / 0 = Error
//
//****************************************************************************
int AddIn_main(int isAppli, unsigned short OptionNum)
{
    unsigned int key;

    Bdisp_AllClr_DDVRAM();

    locate(1,4);
    Print((unsigned char*)"This application is");
    locate(1,5);
    Print((unsigned char*)" sample Add-In.");

    while(1){
        GetKey(&key);
    }

    return 1;
}

//****************************************************************************
//**************                                              ****************
//**************                 Notice!                      ****************
//**************                                              ****************
//**************  Please do not change the following source.  ****************
//**************                                              ****************
//****************************************************************************

#pragma section _BR_Size
unsigned long BR_Size;
#pragma section

#pragma section _TOP

//****************************************************************************
//  InitializeSystem
//
//  param   :   isAppli   : 1 = Application / 0 = eActivity
//              OptionNum : Option Number (only eActivity)
//
//  retval  :   1 = No error / 0 = Error
//
//****************************************************************************
int InitializeSystem(int isAppli, unsigned short OptionNum)
{
    return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
}
#pragma section

จากโค้ดด้านบนจะเห็นว่าไม่เห็นจุดเริ่มต้นเข้าโปรแกรม (entry point) ฟังก์ชัน main() เช่นภาษาซีทั่วๆไป แต่จะมี AddIn_main() มาแทนให้รู้ว่าเป็นจุดเริ่มต้นของโปรแกรม AddIn สำหรับเครื่องคิดเลขนี้

มาดูโค้ดกันสักนิด ที่ #inlucde “fxlib.h” จะเป็น header ของ Casio สำหรับการแสดงผลเช่นฟังก์ชัน Print เพื่อแสดงบนจอภาพเครื่องคิดเลข Bdisp_AllClr_DDVRAM(); จะเป็นฟังก์ชันเคลียร์หน้าจอภาพให้ว่างเปล่า  locate(1,4); เลื่อนเคอเซอร์มาที่คอลัมน์ 1 และบรรทัดที่ 4 จากนั้นพิมพ์ด้วยฟังก์ชัน Print((unsigned char*)”This application is”); สุดท้ายปิดด้วย loop ไม่รู้จบ while (1) แล้วรอผู้ใช้กดคีย์ GetKey(&key); ตอนรันโปรแกรมถ้าผู้ใช้กดคีย์ “MENU” บนเครื่องคิดเลขก็จะเข้าสู่โหมด “MAIN MENU” แต่โปรแกรมก็ยังรันค้างอยู่ในสถานะเดิม

Compile & Build

มาลองคอมไพล์และบิวด์ดู ที่เมนู “Project” คลิก “Rebuild all” ถ้าไม่มีอะไรผิดพลาดที่กรอบ “Builds” จะแสดงผลดังนี้

Executing Hitachi SH C/C++ Compiler/Assembler phase

set SHC_INC=C:\fx-9860G-SDK\OS\SH\include
set PATH=C:\fx-9860G-SDK\OS\SH\bin
set SHC_LIB=C:\fx-9860G-SDK\OS\SH\bin
set SHC_TMP=D:\FX9860GIISD\Test\Debug
"C:\fx-9860G-SDK\OS\SH\bin\shc.exe" -subcommand=C:\Users\priabroy\AppData\Local\Temp\hmk9A12.tmp

Executing Hitachi OptLinker04 phase

"C:\fx-9860G-SDK\OS\SH\bin\Optlnk.exe" -subcommand=C:\Users\priabroy\AppData\Local\Temp\hmk9D5F.tmp

Optimizing Linkage Editor Completed

HMAKE MAKE UTILITY Ver. 1.1
Copyright (C) Hitachi Micro Systems Europe Ltd. 1998
Copyright (C) Hitachi Ltd. 1998 


	Make proccess completed

"D:\FX9860GIISD\Test\HELLO.G1A" was created.

Build has completed.

ถ้าสำเร็จจะเห็น HELLO.G1A ถูกสร้างขึ้นมา จากนั้นที่เมนู “Run” คลิกที่เมนูย่อย “Run” อีมูเลเตอร์จะเริ่มทำงาน

ที่ “Keyboard” กดปุ่มเลื่อนลูกศรลงที่ไอคอน “Debug” กดคีย์ “EXE” จะเห็นหน้าตาโปรแกรมดังนี้

ดาวน์โหลดซอร์สโค้ด (Source code) โปรแกรมแปลงพิกัดภูมิศาสตร์ (Geographic Calc)

เพื่อการลดระยะเวลาการเรียนรู้สำหรับคนที่เพิ่งจะมาศึกษาการใช้งานเครื่องมือ SDK ผมจะขอแสดงโครงการที่ผมทำไว้แล้ว ไปที่หน้าดาวน์โหลด (Download) มองหาซอร์สโค้ด (Source code) โปรแกรมสำหรับเครื่องคิดเลข Casio fx-9860G II SD จะได้ไฟล์ zip ชื่อ “UTM-Geo.zip” ทำการแตกไฟล์ zip จะเห็นไฟล์ดังนี้

ที่ผมวงสีแดงไว้คือโค้ดที่ได้จาก ไลบรารีที่ผมดาวน์โหลดมาใช้จาก githubพัฒนาโดย Howard Butler ส่วนที่ผมวงสีฟ้าไว้คือโค๊ดของผมเอง แตกไฟล์ zip ไปไว้ที่โฟลเดอร์สำหรับผมเองอยู่ที่ไดรว์ D:\FX9860GIISD

เปิดโครงการโปรแกรมแปลงพิกัดภูมิศาสตร์

ใช้เมนู “Project” > “Open…” เปิดไฟล์ชื่อ “UTMGeo.g1w”  ที่ช่อง panel  ด้านซ้ายสุดของเครื่องมือพัฒนาจะเห็นเป็นชื่อไฟล์ที่ผมได้ add มาไว้ จะสังเกตเห็นชื่อไฟล์บางตัวมี นามสกุล extension *.h, *.c ที่เป็นปกติของไฟล header และซอร์สโค้ดของภาษาซีและ *.hpp, *.cpp ของภาษาซีพลัสพลัส ซึ่งไฟล์ extension ที่เราตั้งชื่อไว้ถ้ามีโค้ดภาษาซีพลัสพลัส จะต้องใช้ extension เป็น hpp และ cpp

แก้ไขโครงการ

ใช้เมนู “Project” > “Edit…” เพื่อแก้ไขชื่อโครงการ หรือเพิ่มลดไฟล์ header และ source file

แก้ไขไอคอนสำหรับปรากฎที่หน้า “MAIN MENU” ของเครื่องคิดเลข ไอคอนขนาดกว้าง 39 pixel และสูงขนาด 19 pixel ฟอร์แม็ตเป็น bitmap แบบขาวดำ 1 bit ผมออกแบบในโปรแกรม Paint.net จัดเก็บเป็นไฟล์ bitmap (bmp) แต่ไม่สามารถจัดเก็บเป็นไฟล์ขาวดำแบบ 1 bit ได้ต้องไปเปิดต่อใน Gimp แล้วเลือกเมนู Image>Mode>Indexed ตรง Color map เลือก Use black and white (1 bit) palette จากนั้น save จึงจะได้ไฟล์รูปที่มีฟอร์แม็ต bitmap แบบ 1 bit ได้ ทั้งสองโปรแกรมนี้ฟรี

ตรง Edit icon เวลาจะคลิกต้องระวังเพราะถ้าเราออกแบบไอคอนมาแล้ว จะโดนทับด้วยรูปไอคอนดีฟอลท์ทันที ผมไม่ใช้เลยเพราะพลาดหลายทีแล้ว

การจัดการโค้ด C++

ถ้ามีโค้ดซีพลัสพลัสมาผสมด้วย ที่ด้านบนสุดไฟล์จะต้องกำหนดดังนี้

#ifdef __cplusplus
  extern "C" {
#endif

ด้านล่างสุดปิดท้ายด้วย

  #ifdef __cplusplus
}
  #endif

โค้ดจัดการการป้อนข้อมูล

การป้อนข้อมูลของงานสำรวจในเครื่องคิดเลขส่วนใหญ่จะเป็นเลขทศนิยมเช่นระยะทางหรือค่าพิกัด แต่ถ้าเป็นมุมทีแยกองศา ลิปดาและฟิลิปดา ปกติในเครื่องคิดเลขเช่น  fx-4500, fx-5800P จะมีคีย์ให้กดสะดวก แต่เครื่อง  fx-9860G II SD กลับเอาไปไว้ลึกมากต้องกดหลายครั้งจากคีย์ “OPTN” แต่ที่ผมช็อคคือใน SDK กลับไม่มีฟังก์ชันให้เรียกใช้งานได้เลย จะต้องเขียนฟังก์ชันขึ้นมาเองทั้งหมด ผมอาศัยไปอ่านตามฟอรั่มที่มีคนแฮ็คไว้ พบว่าสามารถเรียกใช้ฟังก์ชัน EditExpress ที่ทาง Casio ไม่ได้เปิดเผยเอกสารไว้ (สังเกตว่าใช้เป็น function pointer อ่านรายละเอียดการใช้งานได้ที่ลิ๊งค์นี้)

#define SCA 0xD201D002
#define SCB 0x422B0009
#define SCE 0x80010070

const unsigned int sc08DB[] = {SCA, SCB, SCE, 0x08DB};
typedef int(*sc_EE)(int, short, int, char*, char*, short, char*, int );
#define EditExpression (*(sc_EE)sc08DB) 

วิธีใช้งานก็ประมาณนี้

#define MAXEDITBUFFER 21
//
void AddIn_main(int isAppli, unsigned short OptionNum){
int key;
char vBCD[24];
unsigned char sBCD[MAXEDITBUFFER];

   memset( vBCD, 0, sizeof(vBCD));
   memset( sBCD, 0, sizeof(sBCD));
   key = EditExpression(0, KEY_CTRL_RIGHT, 1, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "Input:", 0x04);
   
   locate(1, 4);
   PrintLine(sBCD, 21);
   
   GetKey(&key);
   return 1;
}

ข้อมูลที่ผู้ใช้ป้อนจะกลับมาที่ข้อมูลสตริง sBCD ผมพบว่าเรียกใช้ EditExpression มี  mode ให้ป้อนเลือกว่าจะป้อนข้อมูลเป็น double ไหม ซึ่งตอนป้อนข้อมูลจะรับแค่ตัวเลข แต่ในโหมดตามตัวอย่างด้านบน (พารามิเตอร์สุดท้าย 0x04) นั้นจะรับค่าทั่วๆไปทั้งตัวอักษรผสมกับตัวเลข แต่ผมสังเกตว่าเวลาเราป้อนข้อมูลแล้วกดคีย์ “EXE” จะมีการประมวลผล expression ด้วย ปัญหาที่ผมพบคือถ้าป้อนสตริงค่าพิกัดแบบ MGRS เช่น “18SVK8588822509” กลับ error ผมเลยต้องเขียนฟังก์ชันขึ้นมาเองคือ inputMGRSString() โดยเฉพาะ

การป้อนข้อมูลมุม

เนื่องจากเครื่องมือพัฒนา SDK ไม่สนับสนุนการป้อนมุมแบบใช้งานปกติ ผมเลยกำหนดว่ามุมองศา ลิปดาและฟิลิปดาให้คั่นด้วยเครื่องหมายลบ (-) เช่นแลตติจูด (Latitude) จะใช้ตัวอักษร “N” หรือ “S” มากำกับว่าอยู่ในซึกโลกเหนือหรือซีกโลกใต้ คั่นด้วยเส้นศูนย์สูตร ส่วนมุมลองจิจูด (Longitude) แบ่งเป็นซีกโลกตะวันออก (“E” ปิดท้าย) และซีกโลกตะวันตก (“W” ปิดท้าย

ตัวอย่าง แลตติจูด 45-5-32.525N ลองจิจูด 98-45-38.587W

โค้ดอ่านเขียนข้อมูลเข้าตัวแปร  Alpha

ส่วนใหญ่เวลาเราป้อนข้อมูลเข้าไปในการคำนวณงาน เราต้องการให้โปรแกรมจดจำค่านั้นไว้ ดังนั้นโปรแกรมต้องมีการจัดเก็บเอาไว้แล้วเรียกมาใช้ทีหลังเมื่อเรียกโปรแกรมมาใช้งานอีกที เพราะไม่ต้องป้อนบ่อย ถ้ายังใช้ค่าเดิมแค่กดคีย์ “EXE” ผ่านได้เลย และก็เหมือนเดิมครับ SDK ไม่ได้เปิดเผยฟังก์ชันนี้ไว้ทั้งที่สำคัญมาก ผมไปค้นหาตามฟอรั่มพบว่าการจัดเก็บข้อมูลเข้าตัวแปรตัวอักษร A-Z ใช้โครงสร้างข้อมูลเฉพาะ อ่านได้ตามลิ๊งค์นี้ การแปลงข้อมูลสามารถใช้ class TBCD (โค๊ดเดิมมีบั๊กผมแก้ไปนิดหน่อย)

#define SCA 0xD201D002
#define SCB 0x422B0009
#define SCE 0x80010070

const unsigned int sc04E0[] = {SCA, SCB, SCE, 0x04E0};
const unsigned int sc04DF[] = {SCA, SCB, SCE, 0x04DF};

typedef void(*sc_agd)(char, TBCDvalue*);
typedef void(*sc_asd)(char, TBCDvalue*);

#define Alpha_GetData (*(sc_agd)sc04DF)
#define Alpha_SetData (*(sc_asd)sc04E0)

void GetAlphaDoubleData(char alpha, double *dval);
void SetAlphaDoubleData(char alpha, double val);

typedef struct{
  unsigned char hnibble:4;
  unsigned char lnibble:4;
} TBCDbyte;

typedef struct{
  unsigned short exponent:12;
  unsigned short mantissa0:4;
  TBCDbyte mantissa[7];
  char flags;
  short info;
} TBCDvalue;

typedef struct{
  int exponent;
  int sign;
  int unknown; 
  char mantissa[15];
} TBCDInternal;

//Implement of class TBCD please see utilities.cpp
class TBCD{
  public:
        TBCDvalue*PValue();
        int Get( TBCDvalue&value );
        int Set( TBCDvalue&value );
        int Set( double&value );
        int Get( double&value );
        int SetError( int error );
        int GetError();
        void Swap();
  protected:
  private:
        TBCDvalue FValue[2];
};

void GetAlphaDoubleData(char alpha, double *dval){
  TBCD *bcd;
  TBCDvalue *bval;
  int i, ii;

  bval = (TBCDvalue *)malloc(sizeof(TBCDvalue));
  Alpha_GetData(alpha, bval);
  bcd = new TBCD;
  i = bcd->Set(*bval);
  ii = bcd->Get(*dval);
  delete bcd;
  free(bval);
}

void SetAlphaDoubleData(char alpha, double dval){
  TBCD *bcd;
  TBCDvalue bval;
  int i, ii;

  bcd = new TBCD;
  i = bcd->Set(dval);
  ii = bcd->Get(bval);
  Alpha_SetData(alpha, &bval);
  delete bcd;
}

วิธีการใช้งานก็ง่ายๆ

      SetAlphaDoubleData('B', 123.456); //เอาค่า 123.456 เข้าเก็บที่ตัวแปรอักษร "B"
      GetAlphaDoubleData('B', &x); //ดึงค่าที่เก็บในตัวอักษร "B" ออกมาเข้าตัวแปร x
      Locate(1, 4);
      sprintf((char*) str, (char*) "Value = %.3lf", x); 
      Print((unsigned char*)str); //Value = 123.456     

โค้ดสำหรับเมนูหลัก

เป็นการเพิ่มทางเลือกให้ผู้ใช้ ข้อดีการสร้างเมนูคือสามารถรวมงานคำนวณที่มีลักษณะคล้ายๆกันมาอยู่โปรแกรมเดียวกันได้ อาจบางทีอาจจะใช้ไลบรารีร่วมกันดูตัวอย่างด้านล่าง

โค้ดก็ง่ายๆดังนี้

      memset(s, '-', 21);
      Bdisp_AllClr_DDVRAM(); 
      locate(0, 1);
      Print((unsigned char *)"Geographic Calc");
      locate(0, 2);
      PrintLine((unsigned char*)s, 21);
      locate(0, 3);
      PrintLine("[1]:UTM to Geo", 21);
      locate(0, 4);
      PrintLine("[2]:Geo to UTM", 21);
      locate(1, 5);
      PrintLine("[3]:MGRS to Geo", 21);
      locate(0, 6);
      PrintLine("[4]:Geo to MGRS", 21);
      locate(1, 8);
      PrintLine("Select 1,2,3 or 4", 21);
      while (!((key1 >= 0x31) && (key1 <= 0x34)){ 
        GetKey(&key1);

จะมีลูป while ดักการกดคีย์อีก loop ถ้าพบว่ากดคีย์เลข “1” (character code = 0x31) ถึงเลข “4” (Character code = 0x34) เงื่อนไขจริงจะออกจาก loop เข้าเงื่อนไข if (มีหลายชั้นใช้ case แทนได้)

โค้ดงานคำนวณหลัก

ถ้าผู้ใช้กดคีย์ “1” จะเป็นการคำนวณค่าพิกัดจาก UTM ไปยัง Geographic

    if (key1 == 0x31) { //UTM to Geo
      Bdisp_AllClr_DDVRAM(); 
      locate(0, 1);
      Print((unsigned char *)"UTM to Geo");
      locate(0, 2);
      PrintLine((unsigned char*)s, 21);

      GetAlphaDoubleData('A', A);//ดึงค่าข้อมูลเดิมจากหน่วยความจำตัวอักษร "A" 
      sprintf((char*)sBCD, (char*) "%.3lf", *A); //เตรียมรูปแบบข้อมูลทศนิยมสามตำแหน่งไว้ใน sBCD
      //เรียกฟังก์ชันป้อนข้อมูล โดยส่ง sBCD ไปให้
      key2 = EditExpression(0, KEY_CTRL_RIGHT, 3, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "N? : ", 0x04);
      y = atof((char*)sBCD); //แปลงข้อมูลที่ป้อนมาเป็นตัวเลขทศนิยม
      SetAlphaDoubleData('A', y);//เก็บค่าที่ป้อนไว้ในหน่วยความจำตัวอักษร "A"

      GetAlphaDoubleData('B', B);
      sprintf((char*)sBCD, (char*) "%.3lf", *B); 
      key2 = EditExpression(0, KEY_CTRL_RIGHT, 4, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "E? : ", 0x04);
      x = atof((char*)sBCD);
      SetAlphaDoubleData('B', x);
     
      GetAlphaDoubleData('Z', Z);
      sprintf((char*)sBCD, (char*) "%.3lf", *Z); 
      key2 = EditExpression(0, KEY_CTRL_RIGHT, 5, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "UTM Zone No.? : ", 0x04);
      if (strchr((char*)sBCD, 0x87) != NULL) {
        removechar((char*)sBCD, 0x87);
        hemi = 'S';
      } else if(strchr((char*)sBCD, 0x2D) != NULL) {
        removechar((char*)sBCD, 0x2D);
        hemi = 'S';
      } else
        hemi = 'N';

      zn = atoi((char*)sBCD);
      SetAlphaDoubleData('Z', zn);
      //เรียกไลบรารีแปลงพิกัดที่ประกาศใน utm.c
      err = Convert_UTM_To_Geodetic(zn, hemi, x, y, &lat, &lng);
      if (!err){
	      Lat = lat * RAD2DEG; 
	      Lng = lng * RAD2DEG;
              //แยกทศนิยมจัดรูปแบบที่ที่องศา ลิปดาและฟิลิปดาคั่นด้วยเครื่องหมายลบ
	      slat = degreetodms(fabs(Lat), NUMDECIMAL, 0x2D);
	      if(Lat >= 0)
	        sprintf(str, "Lat= %s N", slat);
	      else
	        sprintf(str, "Lat= %s S", slat);
	      locate(1, 6);
	      Print((unsigned char*)str); 
	      locate(1, 7);
	      slong = degreetodms(fabs(Lng), NUMDECIMAL, 0x2D);
	      if (Lng >= 0)
	        sprintf(str, "Lon= %s E", slong);
	      else
	        sprintf(str, "Lon= %s W", slong);
	      Print((unsigned char*)str);      
	      free(slat);
	      free(slong);
       }

ลองดูโค้ดแปลงพิกัดจากค่าพิกัดฉากยูทีเอ็มไปค่าพิกัดภูมิศาสตร์ โดยใช้ไลบรารี

err = Convert_UTM_To_Geodetic(zn, hemi, x, y, &lat, &lng);

zn คือโซนยูทีเอ็ม hemi คือซีกโลก x และ y คือค่าพิกัดฉากยูทีเอ็ม ส่วนค่าที่คำนวณแล้วจะส่งกลับมาที่ตัวแปร lat, lng ส่วนการแปลงพิกัดอย่างอื่นก็ลองดูได้ตามโค้ด

คอมไพล์และบิวด์ (compile & build)

ทดสอบโดยเมนู “Project” > “Rebuild all” ถ้าเมนูนี้ไม่ขึ้นให้คลิก “Project” > “Reload” ก่อน จากทำการรันโปรแกรมโดย “Run” > “Run” จะเห็นอีมูเลเตอร์ “Display” เลื่อนกดคีย์ ไปที่ไอคอนโปรแกรม จากอีมูเลเตอร์ “Keyboard” แล้วกดคีย์ “EXE”

จะเห็นโปรแกรม “Geographic Cacl” ขึ้นเมนูมา

การใช้งานโปรแกรมนี้พร้อมตัวอย่างไปดูที่ลิ๊งค์นี้ได้

ซอร์สโค้ดหลัก

ท้ายสุดผมเอาซอร์สโค้ดของไฟล์ “main.cpp” มาลงให้ดูเต็มๆ จะเห็นว่าไม่มีอะไรสลับซับซ้อนมาก ง่ายๆครับ

#ifdef __cplusplus
  extern "C" {
#endif

#include "fxlib.h"
#include "string.h"
#include "stdlib.h"
#include "stdio.h"
#include "math.h"
#include "mgrs.h"
#include "tranmerc.h"
#include "utm.h"
#include "utilities.hpp"


#define MAXEDITBUFFER 21
#define NUMDECIMAL 5


void removechar(char* s, const char toremove)
{
  while(s=strchr(s, toremove))   
    memmove(s, s+1, 1+strlen(s+1));
}

int InputMGRSString(int x, int y, unsigned char*prompt, unsigned char*buffer, int bufferSize ){
   unsigned int key, edit_key, return_key = 0;
   int pos, len, len2;
   Cursor_SetFlashMode(1);   // set cursor visibility on
   pos = strlen((char*)buffer);// initially set the cursor to the end of the string

   locate(x, y);
   Print(prompt);
   len2 = strlen((char*)prompt);
   while (!return_key){
      locate(x + len2, y);
      PrintLine(buffer, 22-x);
      locate (x + pos + len2, y);
      GetKey( &key );
      edit_key = 0;
      if ((key >= 0x30 ) && (key <= 0x39)){ edit_key = key; } else if ((key >= 0x41) && (key <= 0x5A)){ edit_key = key; } else{ switch (key){ case KEY_CTRL_DEL : if ( pos > 0 ) pos--;
               len = strlen( (char*)buffer );   // get the current length of the string
               memmove( buffer+pos, buffer+pos+1, len-pos);   // shift the memory: XXYDYYY -> XXXYYY
               break;
            case KEY_CTRL_RIGHT :
               len = strlen( (char*)buffer );   // get the current length of the string
               if ( pos < len ) pos++; break; case KEY_CTRL_LEFT : if ( pos > 0 ) pos--;
               break;
            case KEY_CTRL_UP :
            case KEY_CTRL_DOWN :
               return_key = key;
               break;
            case KEY_CTRL_EXE :
            case KEY_CTRL_EXIT :
               return_key = key;
               break;
            default :
               break;
         };
      }
      if ( edit_key ){
         if ( pos < bufferSize-1 ){ buffer[ pos ] = edit_key; pos++; } } } Cursor_SetFlashMode( 0 ); // set cursor visibility off return ( return_key ); } int AddIn_main(int isAppli, unsigned short OptionNum) { unsigned char buffer[21]; char str[21], s[21]; int editresult; unsigned int key1, key2; double x, y, lat, lng, Lat, Lng; char *slat, *slong, *sangle; long zn; char hemi;//North hemi is 'N', South hemi is 'S' char vBCD[24]; unsigned char sBCD[MAXEDITBUFFER] = ""; int err; unsigned char mgrs[15]; long precision; double *A, *B, *C, *D, *E, *F, *H, *I, *Z; A = (double *)malloc(sizeof(double)); B = (double *)malloc(sizeof(double)); C = (double *)malloc(sizeof(double)); D = (double *)malloc(sizeof(double)); E = (double *)malloc(sizeof(double)); F = (double *)malloc(sizeof(double)); H = (double *)malloc(sizeof(double)); I = (double *)malloc(sizeof(double)); Z = (double *)malloc(sizeof(double)); memset(s, '-', 21); while(1){ Bdisp_AllClr_DDVRAM(); locate(0, 1); Print((unsigned char *)"Geographic Calc"); locate(0, 2); PrintLine((unsigned char*)s, 21); locate(0, 3); PrintLine("[1]:UTM to Geo", 21); locate(0, 4); PrintLine("[2]:Geo to UTM", 21); locate(1, 5); PrintLine("[3]:MGRS to Geo", 21); locate(0, 6); PrintLine("[4]:Geo to MGRS", 21); locate(1, 8); PrintLine("Select 1,2,3 or 4", 21); while (!(key1 >= 0x31) && (key1 <= 0x34)){ GetKey(&key1); } if (key1 == 0x31) { //UTM to Geo Bdisp_AllClr_DDVRAM(); locate(0, 1); Print((unsigned char *)"UTM to Geo"); locate(0, 2); PrintLine((unsigned char*)s, 21); GetAlphaDoubleData('A', A); sprintf((char*)sBCD, (char*) "%.3lf", *A); key2 = EditExpression(0, KEY_CTRL_RIGHT, 3, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "N? : ", 0x04); y = atof((char*)sBCD); SetAlphaDoubleData('A', y); GetAlphaDoubleData('B', B); sprintf((char*)sBCD, (char*) "%.3lf", *B); key2 = EditExpression(0, KEY_CTRL_RIGHT, 4, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "E? : ", 0x04); x = atof((char*)sBCD); SetAlphaDoubleData('B', x); GetAlphaDoubleData('Z', Z); sprintf((char*)sBCD, (char*) "%.3lf", *Z); key2 = EditExpression(0, KEY_CTRL_RIGHT, 5, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "UTM Zone No.? : ", 0x04); if (strchr((char*)sBCD, 0x87) != NULL) { removechar((char*)sBCD, 0x87); hemi = 'S'; } else if(strchr((char*)sBCD, 0x2D) != NULL) { removechar((char*)sBCD, 0x2D); hemi = 'S'; } else hemi = 'N'; zn = atoi((char*)sBCD); SetAlphaDoubleData('Z', zn); //Call function declared in utm.c err = Convert_UTM_To_Geodetic(zn, hemi, x, y, &lat, &lng); if (!err){ Lat = lat * RAD2DEG; Lng = lng * RAD2DEG; slat = degreetodms(fabs(Lat), NUMDECIMAL, 0x2D); if(Lat >= 0)
	        sprintf(str, "Lat= %s N", slat);
	      else
	        sprintf(str, "Lat= %s S", slat);
	      locate(1, 6);
	      Print((unsigned char*)str); 
	      locate(1, 7);
	      slong = degreetodms(fabs(Lng), NUMDECIMAL, 0x2D);
	      if (Lng >= 0)
	        sprintf(str, "Lon= %s E", slong);
	      else
	        sprintf(str, "Lon= %s W", slong);
	      Print((unsigned char*)str);      
	      free(slat);
	      free(slong);
       }
    } else if (key1 == 0x32) { //Geographic to UTM
      Bdisp_AllClr_DDVRAM(); 
      locate(0, 1);
      Print((unsigned char *)"Geo To UTM");
      locate(0, 2);
      PrintLine((unsigned char*)s, 21);

      GetAlphaDoubleData('H', H);
      sangle = degreetodms(*H, NUMDECIMAL, 0x99); 
      if(*H >= 0)
        sprintf(str, "%sN", sangle);
      else
        sprintf(str, "%sS", sangle);
      key2 = EditExpression(0, KEY_CTRL_RIGHT, 3, vBCD, (char*)str, MAXEDITBUFFER - 1, "Lat?: ", 0x04);
      lat = parsedms((char*)str);
      SetAlphaDoubleData('H', lat);
      free(sangle);

      GetAlphaDoubleData('I', I);
      sangle = degreetodms(*I, NUMDECIMAL, 0x99); 
      if(*I >= 0)
        sprintf(str, "%sE", sangle);
      else
        sprintf(str, "%sW", sangle);
      key2 = EditExpression(0, KEY_CTRL_RIGHT, 4, vBCD, (char*)str, MAXEDITBUFFER - 1, "Lon?: ", 0x04);
      lng = parsedms((char*)str);
      SetAlphaDoubleData('I', lng);
      free(sangle);

      Lat = lat * DEG2RAD;
      slat = degreetodms(fabs(Lat), NUMDECIMAL, 0x2D);
      Lng = lng * DEG2RAD;
      slong = degreetodms(fabs(Lng), NUMDECIMAL, 0x2D);
      //Call function declared in utm.c
      err = Convert_Geodetic_To_UTM(Lat, Lng, &zn, &hemi, &x, &y);
      if (!err) {
	      sprintf(str, "North= %11.3lf", y);
	      locate(1, 5);
	      Print((unsigned char*)str);      
	      sprintf(str, "East= %10.3lf", x);
	      locate(1, 6);
	      Print((unsigned char*)str);      
	      sprintf(str, "UTM Zone No= %d%c", zn, hemi);
	      locate(1, 7);
	      Print((unsigned char*)str); 
      }
      free(slat);
      free(slong);      
    } else if (key1 == 0x33) { //MGRS to Geo
      Bdisp_AllClr_DDVRAM(); 
      locate(0, 1);
      Print((unsigned char *)"MGRS to Geo");
      locate(0, 2);
      PrintLine((unsigned char*)s, 21);

      memset(mgrs, 0, 16);
      editresult = InputMGRSString( 1, 3, "MGRS?", buffer, sizeof(buffer) );
      if (editresult) {
        memcpy(mgrs, buffer, 15);
        //Call function that declared in mgrs.c
        err = Convert_MGRS_To_Geodetic((char*)mgrs, &lat, &lng);
        if (!err){
          Lat = lat * 180.0 / PI;
          slat = degreetodms(fabs(Lat), NUMDECIMAL, 0x2D);
          Lng = lng * 180.0 / PI;
          slong = degreetodms(fabs(Lng), NUMDECIMAL, 0x2D);
          if(Lat >= 0)
            sprintf(str, "Lat= %s N", slat);
          else
            sprintf(str, "Lat= %s S", slat);
          locate(1, 4);
          Print((unsigned char*)str);      
          if(Lng >= 0)
            sprintf(str, "Lon= %s E", slong);
          else
            sprintf(str, "Lon= %s W", slong);
          locate(1, 5);
          Print((unsigned char*)str);        
          free(slat);
          free(slong);
        } 
      }
    } else if (key1 == 0x34) { //Geographic to MGRS
      Bdisp_AllClr_DDVRAM(); 
      locate(0, 1);
      Print((unsigned char *)"MGRS to Geo");
      locate(0, 2);
      PrintLine((unsigned char *)s, 21);

      memset(sBCD, 0, MAXEDITBUFFER);
      key2 = EditExpression(0, KEY_CTRL_RIGHT, 3, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "Lat?:", 0x04);
      lat = parsedms((char*)sBCD);
      lat = lat * DEG2RAD;
      memset(sBCD, 0, MAXEDITBUFFER);
      key2 = EditExpression(0, KEY_CTRL_RIGHT, 4, vBCD, (char*)sBCD, MAXEDITBUFFER - 1, "Lon?:", 0x04);
      lng = parsedms((char*)sBCD);
      lng = lng * DEG2RAD;

      //Call function that declared in mgrs.c
      err = Convert_Geodetic_To_MGRS(lat, lng, 5, (char*)mgrs);
      if (!err){
        sprintf(str, "MGRS= %s", mgrs);
        locate(1, 5);
        Print((unsigned char*)str);        
      }     
    }
    GetKey(&key1);
  } //while (1)
  free(A);
  free(B);
  free(C);
  free(D);
  free(E);
  free(F);
  free(H);
  free(I);
  free(Z);
  return 1;
}

#pragma section _BR_Size
unsigned long BR_Size;
#pragma section

#pragma section _TOP

int InitializeSystem(int isAppli, unsigned short OptionNum)
{
    return INIT_ADDIN_APPLICATION(isAppli, OptionNum);
}

#pragma section

#ifdef __cplusplus
}
#endif

การนำโปรแกรมไปติดตั้งบนเครื่องคิดเลข

เมื่อคอมไพล์และบิวด์แล้วจะได้ไฟล์ G1a ก็สามารถนำไปใช้บนเครื่องคิดเลขได้ วิธีการเอาโปรแกรมไปใส่เครื่องคิดเลขสามารถทำได้หลายวิธี ดูโพสต์เก่าแสดงวิธีการได้ตามลิ๊งค์นี้

สรุป

การพัฒนาโปรแกรมสำหรับเครื่องคิดเลขไม่มีอะไรยากเย็นมากนัก มีความรู้ภาษาซีขั้นพื้นฐานแบบผมก็ทำได้ เพียงแต่ถ้าต้องการคำนวณอะไรซับซ้อนอาจจะต้องหาไลบรารีที่ท่านอื่นได้พัฒนาเขียนไว้ แต่เครื่องมือพัฒนานี้มีข้อจำกัดอยู่บ้างเช่นคอมไพเลอร์นี้สนับสนุน c standard library ได้ไม่ครบทุกอย่าง ตัวอย่างเช่นฟังก์ชั่น strtok() ที่ตัดสตริงออกตามตัวคั่นก็ไม่สนับสนุน ดังนั้นการเลือกไลบรารีที่คนอื่นได้ทำไว้ก็ต้องพิจารณาส่วนนี้ด้วย ส่วนการรับข้อมูลจากผู้ใช้ สำหรับผมแล้วที่มีอยู่ตอนนี้เกือบจะเพียงพอ เพราะงานสำรวจก็จะมีแค่ป้อนมุม ระยะทาง เป็นหลัก ติดตามกันต่อไปครับ

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 2 โปรแกรมคำนวณค่าพิกัดจุดศูนย์กลางวงกลม (Circle Center Calc)

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 2 โปรแกรมคำนวณค่าพิกัดจุดศูนย์กลางวงกลม (Circle Center Calc)

จุดศูนย์กลางวงกลมนั้นสำคัญไฉน

ในงานสำรวจสำหรับการก่อสร้างเช่นเข็มเจาะ ในขั้นตอนแรกช่างสำรวจจะวางตำแหน่งจุดศูนย์กลางของเสาเข็ม จากนั้นจะวัด offset อย่างน้อยสามด้านตั้งฉากแล้วตอกเหล็กเช่นเหล็กข้ออ้อยลงไปเป็นหมาย ขั้นตอนต่อไปจะปักปลอกเหล็ก (Casing) ในชั้นดินอ่อนเพื่อกันดินทลายตัวลง ในขั้นตอนนี้ช่วงการปักปลอกเหล็กจะมีการวัดระยะจากหมายที่ offset ไว้เพื่อให้ปลอกเหล็กอยู่ในตำแหน่งทั้งทางราบและทางดิ่ง เมื่อปลอกเหล็กลงไปสุดแล้ว เพื่อความมั่นใจว่าได้ตำแหน่งที่ถูกต้องแล้ว จะสำรวจเพื่อเก็บค่าพิกัดคือจุดศูนย์กลางของปลอกเหล็ก แต่คำถามคือจะวัดค่าพิกัดจุดศูนย์กลางของปลอกเหล็กวงกลมได้อย่างไร ในทางปฏิบัติบางครั้งจะใช้ตะแกรงเหล็กปิดปากปลอกเหล็ก แล้วช่างสำรวจจะใช้ตลับเมตรวัดระยะครึ่งหนึ่งของเส้นผ่าศูนย์กลางสองด้านตั้งฉากกันแล้วทำเครื่องหมายไว้บนกระดานไม้ จากนั้นจึงจะวัดค่าพิกัดโดยการตั้งเป้าปริซึม ถ้าใช้มินิปริซึม ตั้งต่ำจะให้ค่าที่ถูกต้องดียิ่งขึ้น แต่ปัญหาคือตอนใช้ตลับเมตรวัดกึ่งกลาง (เส้นที่ผ่านจุดศูนย์กลางคือเส้นที่ยาวที่สุด) เพื่อหาตำแหน่งศูนย์กลางนั้นใช้เวลาพอสมควรและมี error จากการคาดคะเน

วิธีต่อไปที่จะนำเสนอเพื่อทำให้การวัดค่าพิกัดทำได้เร็วขึ้น จะใช้สูตรทางคณิตศาสตร์มาช่วย โดยการวัดค่าพิกัดสามจุดโดยแบ่งให้ระยะห่างแต่ละจุดเท่าๆกัน จากนั้นช่างสำรวจจะใช้เครื่องคิดเลข คำนวณหาค่าพิกัดจุดศูนย์กลาง วิธีการนี้จะใช้เวลารวดเร็วกว่าวิธีแรกพอสมควร ในความเป็นจริงวิธีนี้อยู่บนสมมติฐานว่าปลอกเหล็กต้องไม่บุบเบี้ยว เมื่อได้ค่าพิกัดจุดศุนย์กลางมาแล้วจะนำมาเทียบกับค่าพิกัดที่ได้จากแบบ drawing ถ้าพบว่าค่าต่างกันมากเกินที่กำหนดไว้ จะต้องถอนปลอกเหล็กและทำการปักใหม่

คำนวณได้ทั้ง 2D และ 3D

โปรแกรมที่ผมเขียนนั้นคำนวณได้ทั้ง 2D (ไม่ต้องป้อนค่าระดับ) และ 3D (ป้อนค่าระดับไปด้วย) ส่วนสูตรนั้นถ้าคำนวณแบบ 3D นั้นค่อนข้างซับซ้อน ผมใช้วิธีทางลัดคือไปดูโค้ดที่มีคนเขียนไว้ในอินเทอร์เน็ต โค้ดเดิมเป็น Visual Basic ผมแปลงเป็นโค้ดภาษาซี ส่วนการคำนวณ 2D นั้นซับซ้อนน้อยกว่ามาก ถ้าสนใจสูตรก็สามารถดูจากโค้ดของผมได้

int calcCircleCenter3D(double Ya, double Xa, double Za, 
                       double Yb, double Xb, double Zb, 
                       double Yc, double Xc, double Zc, 
                       double *YCen, double *XCen, double *ZCen, double *Radius){
    double AB, BC, AC;
    double ABi, ABj, ABk, ACi, ACj, ACk, CDi, CDj, CDk, Ni, Nj, Nk;
    double cosBAC, sinBAC;
    double AD, CD, Xd, Yd, Zd;
    double X2e, Y2e, Z2e;

	//if the two points are on the same coordinates stop and return.
    if (((Xa == Xb) && (Ya == Yb)) || ((Xa == Xc) && (Ya == Yc)) 
     || ((Xb == Xc) && (Yb == Yc)))
      return 0;

    //Xa = 80.779; Ya = 90.198; Za = 23.567;
    //Xb = 78.334; Yb = 66.990; Zb = 25.567;
    //Xc = 45.345; Yc = 67.623; Zc = 34.123;
    // Answer Radius = 21.778
    // N Center = 80.840, E Center = 61.890, Z Center = 29.037

    //Lengths of AB, AC, AC
    AB = sqrt(pow(Xa - Xb, 2) + pow(Ya - Yb, 2) + pow(Za - Zb, 2));
    BC = sqrt(pow(Xb - Xc, 2) + pow(Yb - Yc, 2) + pow(Zb - Zc, 2));
    AC = sqrt(pow(Xa - Xc, 2) + pow(Ya - Yc, 2) + pow(Za - Zc, 2));
    //Direction cosines of AB(ABi,ABj,ABk)
    ABi = (Xb - Xa) / AB;
    ABj = (Yb - Ya) / AB;
    ABk = (Zb - Za) / AB;
    //Direction cosines of AC(ACi,ACj,ACk)
    ACi = (Xc - Xa) / AC;
    ACj = (Yc - Ya) / AC;
    ACk = (Zc - Za) / AC;
    //Cosine of angle BAC
    cosBAC = (pow(AB, 2) + pow(AC, 2) - pow(BC, 2)) / (2 * AB * AC);
    AD = cosBAC * AC;
    CD = sqrt(pow(AC, 2) - pow(AD, 2));
    //Position of point D, which is C projected normally onto AB
    Xd = Xa + (AD * ABi);
    Yd = Ya + (AD * ABj);
    Zd = Za + (AD * ABk);
    //Direction cosines of CD(Cdi,CDj,CDk)
    CDi = (Xc - Xd) / CD;
    CDj = (Yc - Yd) / CD;
    CDk = (Zc - Zd) / CD;
    //Direction cosines of normal to AB and CD
    //to be used for rotations of circle centre
    Ni = (ABk * CDj) - (ABj * CDk);
    Nj = (ABi * CDk) - (ABk * CDi);
    Nk = (ABj * CDi) - (ABi * CDj);
    //# Diameter of circumscribed circle of a triangle is equal to the
    //the length of any side divided by sine of the opposite angle.
    //This is done in a coordinate system where X is colinear with AB, Y is // to CD,
    //and Z is the normal (N) to X and Y, and the origin is point A
    //  R = D / 2
    sinBAC = sqrt(1 - pow(cosBAC, 2));
    *Radius = (BC / sinBAC) / 2;
    //Centre of circumscribed circle is point E
    X2e = AB / 2;
    Y2e = sqrt((*Radius) * (*Radius) - X2e * X2e);
    Z2e = 0;
    //Transform matrix
    //                   Rotations                 Translations
    //           ——————————————————————————————————————————————
    //              ABi  ,   ABj  ,  ABk                 Xa
    //              CDi  ,   CDj  ,  CDk                 Ya
    //               Ni  ,    Nj  ,   Nk                 Za
    //           ——————————————————————————————————————————————
    //Position of circle centre in absolute axis system
    *XCen = Xa + (X2e * ABi) + (Y2e * CDi) + (Z2e * Ni);
    *YCen = Ya + (X2e * ABj) + (Y2e * CDj) + (Z2e * Nj);
    *ZCen = Za + (X2e * ABk) + (Y2e * CDk) + (Z2e * Nk);
    return 1;
}

int calcCircleCenter2D(double N1, double E1, double N2, double E2, 
                       double N3, double E3,
                       double *Nc, double *Ec, double *Radius){
    double midN12, midE12, midN23, midE23;
    double k, l, p, q, r, s;
    
    //1 23.432m 78.234m
    //2 45.323m 98.765m
    //3 67.334m 66.999m
    //Answer R=22.907, N Center = 75.876, E Center = 46.217

    if (((N2 == N1) && (E2 == E1)) ||
       ((N2 == N3) && (E2 == E3)) ||
       ((N1 == N3) && (E1 == E3)))
      return 0;

    midN12 = (N1 + N2) / 2.0;
    midE12 = (E1 + E2) / 2.0;
    midN23 = (N2 + N3) / 2.0;
    midE23 = (E2 + E3) / 2.0;


    k = atan((E2-E1)/(N2-N1)) + PI / 2.0;
    l = atan((E2-E3)/(N2-N3)) + PI / 2.0;
    p = 1.0 / tan(k);
    q = 1.0 / tan(l);
    r = tan(k);
    s = tan(l);
    *Ec = ((midE23*q)-(midE12*p)+midN12-midN23)/(q-p);
    *Nc = ((midN23*s)-(midN12*r)+midE12-midE23)/(s-r);
    *Radius = sqrt((E1-*Ec)*(E1-*Ec) + (N1-*Nc)*(N1-*Nc));
    return 1;
}

ดาวน์โหลดโปรแกรม

ไปดาวน์โหลดโปรแกรมได้ที่หน้าดาวน์โหลด  หาโปรแกรมชื่อ Circle Center Calc จะได้ไฟล์มาชื่อ “ARCCENPT.g1a” วิธีการติดตั้งสามารถทำได้หลายวิธี วิธีแรกผมเขียนไว้แล้วที่ตอนที่ 1 ด้วยการ  copy โปรแกรมลง SD card แล้วถ่ายเข้าเครื่องคิดเลขอีกที วิธีที่ 2 ใช้โปรแกรม FA-124 ของ casio

การใช้งาน FA-124

โปรแกรม FA-124 สามารถไปดาวน์โหลดได้ที่ ลิ๊งค์ นี้ จากนั้นแตก zip แล้วทำการติดตั้งง่ายๆ เป็นโปรแกรมเล็กๆ  ผมเข้าใจว่าช่วงติดตั้งน่าจะมีการติดตั้งไดรเวอร์ของ casio ลงไปด้วย เพราะหลังจากนั้นผมเปิดโปรแกรม FA-124 แล้วเอาสาย USB  มาเสียบเชื่อมต่อเครื่องคิดเลขกับคอมพิวเตอร์จะมองเห็นได้ทันที  ที่เครื่องคิดเลขกดคีย์บอร์ดปุ่ม “F1” เพื่อจะเข้าโหมดการโอนข้อมูล (Data Transfer) คำเตือนการเสียบสาย USB นี้ไม่ควรจะนานเกิน 15 นาที เพราะจอภาพเครื่องคิดเลขจะเสื่อมสภาพได้ 

ส่วนหน้าตาโปรแกรม FA-124 ก็ประมาณนี้

จากนั้นมองที่หน้าต่างด้านขวามือคลิกที่ไอคอนที่วงด้วยหมายเลข “1” จากนั้นมาคลิกขวาที่วงด้วยหมายเลข “2” ที่คำว่า Default เลือกเมนู “Import

จะมีไดอะล๊อกบ็อกซ์ ให้เลือกโฟลเดอร์และไฟล์ ไปที่ไฟล์ “ARCCENPT.g1a” ที่เก็บไว้ในเครื่องคอมพิวเตอร์ ตรง Files of type ต้องเลือกเป็น “G1A File (*.g1a)

จะเห็นไฟล์ “ARCCENPT.g1a” เข้ามาใต้ลิสต์ของคำว่า “Default” ดังรูป ที่หน้าต่างด้านซ้ายให้คลิกที่ไอคอนรูปเครื่องคิดเลข ตามที่ผมวงไว้หมายเลข “1” โปรแกรมจะอ่านไฟล์จาก Storage memory ของเครื่องคิดเลข มาแสดงใต้คำว่า “User1” จากนั้นลากไฟล์ “ARCCENPT.g1a” มาวางที่คำว่า User1 (เผอิญเครื่องคิดเลขผมมีไฟล์นี้อยู่แล้ว) โปรแกรมจะถามว่าต้องการทับหรือไม่ตอบ “Yes” 

ก็เป็นอันว่าขั้นตอนเกือบจะเสร็จ ตอนนี้โปรแกรมนี้จะไปอยู่ใน Storage memory ของเครื่องคิดเลขเรียบร้อย ไม่ลืมว่าขนาดของเมมโมรีนี้ 1.5 MB โปรแกรมขนาดนี้สามารถวางได้ประมาณ 30-40 โปรแกรม ซึ่งเหลือเฟือมาก จากนั้นคลิกที่ไอคอนเพื่อทำการ disconnect และอย่าลืมดึงสาย USB ออก

ทดสอบการใช้โปรแกรมคำนวณจุดศูนย์กลางวงกลม (Circle Center Calc)

ที่เครื่องคิดเลขกดคีย์ “MENU”  จากนั้นเลื่อนลงมาที่โปรแกรมดังรูปด้านล่าง

จะเห็นเมนูของโปรแกรม ซึ่งมีให้เลือก 3 โปรแกรมย่อย ส่วนโปรแกรมที่ 3 นั้นเป็นของแถม

    1. 3 Points in 3D  (Circle Center in 3D) – คำนวณหาค่าพิกัดและค่าระดับจุดศูนย์กลางวงกลม โดยค่าที่ป้อน 3 จุดต้องประกอบด้วยค่าพิกัดและค่าระดับ (X, Y, Z)
    2. 3 Points in 2D (Circle Center in 2D) – คำนวณหาค่าพิกัดของจุดศูนย์กลางวงกลม โดยค่าที่ป้อน 3 จุด เฉพาะค่าพิกัดทางราบเท่านั้น
    3. 2 Angles & 1 Dist – คำนวณหาค่าพิกัดของจุดศูนย์กลางวงกลม โดยวัดมุมสองมุมที่ขอบของวงกลมและวัดระยะราบที่ขอบวงกลมตรงจุดแบ่งครึ่งระหว่างขอบวงกลม อธิบายไม่เห็นภาพค่อยดูรูปอีกทีภายหลัง

คำนวณหาจุดศูนย์กลางวงกลมแบบ 3D (Circle Center in 3D)

ที่เมนูกดเลข “1” ป้อนค่าพิกัด N, E  ตอนถามค่า Z คือป้อนค่าระดับ โดยที่จุดที่เก็บค่าพิกัดและระดับมามี 3 จุด จุดไม่ต้องเรียงตามลำดับเส้นรอบวงก็ได้

จากนั้นกด “EXE” เพื่อคำนวณหาค่าพิกัดและค่าระดับของจุดศูนย์กลาง ผลลัพธ์ดังรูปด้านล่าง

คำนวณหาจุดศูนย์กลางวงกลมแบบ 2D (Circle Center in 2D)

ที่เมนูกดเลข “2” ทดสอบป้อนตัวเลขดังนี้ ป้อนค่าพิกัดจุดที่ 1, 2 และ 3

กด “EXE”  จะได้ผลลัพธ์ดังนี้

คำนวณหาจุดศูนย์กลางวงกลมแบบวัดมุมและระยะทาง

ในบางครั้งการเก็บ As-built เช่นเสากลม เราไม่สามารถวัดค่าพิกัดของศูนย์กลางได้ จึงต้องใช้วัดทางอ้อมและใช้สูตรทางคณิตศาสตร์ช่วย จากรูปด้านล่างจะวัดมุมที่ขอบด้านซ้ายและขอบด้านขวาป้อนเข้าโปรแกรม จากนั้นโปรแกรมจะให้เปิดมุมมาที่ตรงกลาง (ถ้าการวัดมุมมีความแม่นยำ มุมที่ตรงกลางนี้จะผ่านจุดศูนย์กลางวงกลมพอดี) แล้วทำการวัดระยะทาง สุดท้ายโปรแกรมจะคำนวณค่าพิกัดจุดศูนย์กลางให้

ที่เมนูหลักกดคีย์เลข “3” ทดสอบโปรแกรมด้วยการป้อนข้อมูลดังนี้ โดยที่ BS = Back Station คือจุดเป้าหลัง ส่วน STA คือ Station  จุดตั้งกล้องนั่นเอง

จากนั้นโปรแกรมจะให้ set มุมของกล้องไปที่กึ่งกลางวงกลม จากนั้นวัดระยะทาง

และป้อนค่าระยะทาง สุดท้ายโปรแกรมจะคำนวณหาค่าพิกัดจุดศูนย์กลางวงกลมและรัศมีวงกลมมาด้วย

สรุป

โปรแกรมนี้เป็นโปรแกรมลำดับที่ 2 ผมหวังว่าคงเป็นประโยชน์ในแวดวงสำรวจบ้านเราบ้างไม่มากก็น้อย โปรแกรมต่างๆเหล่านี้ จะถูกปรับปรุงแก้ไขในอนาคต ท่านผู้อ่านอาจจะสังเกตเห็นว่า เวลาเรียกโปรแกรมมาอีกครั้ง จะไม่เรียกค่าเดิมที่เคยป้อนไว้ ทำให้ต้องป้อนใหม่ทุกครั้ง ในตอนนี้ผมไม่สามารถอ่านหรือเขียนค่าลงตัวแปรอักษร A-Z ได้ เพราะ casio ไม่ได้เขียนเอกสารไว้ (undocumented) แต่สักพักผมคิดว่าคงหาทางได้ เพราะมีคนทำ reverse engineering เครื่องคิดเลขรุ่นนี้พอสมควร แต่ละโปรแกรมที่ใช้สามารถเก็บค่าที่ป้อนเข้าตัวแปรตัวอักษร A-Z เวลาเรียกโปรแกรมมาใช้อีกครั้งถ้าค่าในตัวแปรไม่ได้ถูกทับไปก็สามารถกด “EXE” ผ่านไปได้เลย ติดตามกันตอนต่อไปครับ

 

 

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 1 โปรแกรมแปลงพิกัดภูมิศาสตร์ (Geographic Calc)

ติดปีกเครื่องคิดเลขเทพ Casio fx 9860G II SD ด้วยโปรแกรมภาษาซีบน AddIn ตอนที่ 1 โปรแกรมแปลงพิกัดภูมิศาสตร์ (Geographic Calc)

รอคอยมานานแต่ไม่รู้ว่าสิ่งที่รอคอยมันคืออะไร

สำหรับคนที่เคยเขียนโปรแกรมลงเครื่องคิดเลขคาสิโอ ถ้าเคยเขียนโปรแกรมมิ่งบนระบบใหญ่ๆมาก่อนเช่นจาวา ซี หรือไพทอน จะรู้สึกว่าโดนมัดมือมัดเท้าทำอะไรไม่ถนัด ภาษาเบสิคของคาสิโอ (basic casio) ก็ดูจะหน่อมแน๊ม ตัวแปรก็จำกัดไม่กี่ตัว เมมโมรีสำหรับเก็บโปรแกรมก็น้อยนิดเดียว เขียนฟังก์ชั่นก็ไม่ถนัด ก็เลยได้แต่โปรแกรมอะไรที่ง่ายๆ ใช้ตัวแปรไม่มาก  แต่ไม่นานที่ผ่านมา เผอิญไปค้นหาในอินเทอร์เน็ต โดยที่หาโปรแกรมแบบ basic casio บนเครื่องคิดเลขระดับเทพในวงการสำรวจบ้านเราคือ fx-9860G II SD ที่ผมเคยร่ำๆจะซื้อหามาใช้หลายเที่ยวแต่ติดที่ความรู้สึกว่าแพงไปนิดเมื่อเทียบกับ fx-5800P ที่ใช้อยู่ โปรแกรมที่ค้นหาก็ไม่ได้มีอะไรมากแค่เอามาเปรียบเทียบอัลกอริทึ่มที่ผมมีอยู่ บังเอิญไปเจอว่าการเขียนโปรแกรม AddIn ต้องใช้ SDK (Software Development Kit) ที่ต้องใช้ภาษาซี ก็เลยสะดุดตา ลองค้นเข้าไปอีกหน่อย ก็พออนุมานได้ว่าสามารถเขียนโปรแกรมอะไรก็ได้แบบ AddIn ให้กับเครื่องคิดเลข ที่ไม่ติดจำกัดด้านโครงสร้างภาษาเพราะใช้ภาษาซี ที่คาสิโอเตรียมคอมไพเลอร์ ไลบรารีเครื่องมือพัฒนาโปรแกรมด้านภาษาซีมาพอประมาณ สุดท้ายผมก็เลยมานึกว่า ก่อนหน้านี้ผมคงต้องรอคอยอะไรบางอย่างมานานแต่ไม่รู้ว่าคืออะไร จนกระทั่งได้เจอสิ่งนี้ 🙂 มันใช่เลย ถึงแม้ตอนเจอดูเหมือนผมจะมาสายไปบ้างก็ตาม

อารมณ์มัน Back to school คือความสนุกสนานได้กลับมาอีกครั้ง ผมเคยพูดถึงว่าเครื่องรุ่นเทพสมัยแต่ก่อนคือ Casio fx-880P ที่เขียนภาษาเบสิค(แบบกำกับด้วยหมายเลขบรรทัด) เวลาพกเครื่องคิดเลขรุ่นนี้ ถ้าเอาเท่ห์ก็เอาเหน็บที่กระเป๋าหลังของกางเกงยีนส์ แต่บ่อยครั้งที่ลืมนั่งทับจนเครื่องพัง ที่สามารถเขึยนโปรแกรมได้พอประมาณ แต่ปัญหาคือเมมโมรีที่จัดเก็บโปรแกรมมาน้อย ถึงแม้สามารถซื้อแรมขนาด 32KB มาเพิ่มได้ก็ตาม เคยเขียนโปรแกรม Traverse เล่นๆลงไปเขมือบเมมโมรีไปเกินครึ่ง จนต้องลบโปรแกรมอื่นทิ้งไป ถึงจะใส่ได้ การจะโอนโปรแกรมไปหาเครื่องอื่นก็แสนยากเย็นกระไร เพราะต้องหาสายลิ๊งค์ สมัยก่อนไม่มีอีเบย์ ก็เลยใครอยากได้โปรแกรมอะไรก็ต้องพิมพ์เองสดๆลงไปในเครื่อง ประมวลผลดูผิดตรงไหนก็ตามไปแก้ สำหรับเครื่องคิดเลขในทศวรรษนี้ไม่ต้องทำแบบนั้นแล้วครับมีสายลิ๊งค์มาให้ หรือรุ่น fx-9860G II SD ก็มี SD card มาให้สามารถโอนโปรแกรมให้กันได้สะดวก

รู้จัก Casio fx-9860G II SD

เครื่องรุ่นนี้ออกเก็บเกี่ยวความสำเร็จตามหลัง fx-9750G โดยที่ผลิตออกมาสองรุ่น รุ่นแรกเคสสีเงินส่วนคีย์บอร์ดสีน้ำเงิน ใช้ CPU SH3 รุ่นที่สองเป็นรุ่นล่าสุดเคสสีน้ำเงินเข้มส่วนคีย์บอร์ดสีขาวใช้ CPU SH4a มีเมมโมรีใช้งาน 62 KB (ขนาดน่าสงสารมาก) มีพื้นที่จัดเก็บโปรแกรม (storage memory) เป็น 1.5 MB ที่ผมประเมินดูโปรแกรมขนาดกลางๆสำหรับเครื่องคิดเลขขนาด น่าจะประมาณ 50000 Bytes ถ้าพื้นที่จัดเก็บโปรแกรม 1.5 MB น่าจะใส่โปรแกรมได้ไม่ต่ำกว่า 30 โปรแกรมเลยทีเดียว โดยรวมการประมวลผลเร็วครับ ตามความเข้าใจผมตัว OS ของรุ่นนี้น่าจะกินเมมโมรีไม่มากนัก ที่ผมชอบอีกอย่างคือพื้นที่การแสดงผล ถ้าเอาแบบแสดงตัวอักษรอย่างเดียว ได้ทั้งหมด 8 แถว (row) และแถวละ 21 ตัวอักษร ถามว่าพอไหม ก็ตอบได้ว่าพอครับแบบเบียดเสียดไปหน่อย แต่ยังโอเคกว่ารุ่น fx-5800P ที่มีแค่ 2 บรรทัด แต่อย่างไรก็ตามยังมีโหมดกราฟฟิคมีความละเอียดกว้าง x สูง = 127 x 63 สำหรับวาดกราฟ ก็มาดูขนาดโปรแกรมแปลงพิกัดภูมิศาสตร์ของผม UTMGeo.g1a คือโปรแกรมที่คอมไพล์และบิวท์ (compile & build) มาแล้ว ขนาดประมาณตามรูป 78760 ไบต์ ส่วนโปรแกรมสองโปรแกรมด้านบน (ARCCENPT.g1a และ INTERSCT.g1a) ผมก็เขียนเหมือนกันแต่ขนาดเล็กกว่า

ตามล่าเครื่องมือพัฒนาโปรแกรม SDK (Software Development Kit)

เมื่อรู้ว่าใช้ภาษาซีเขียนได้ ผมก็ตามหาเครื่องมือเพื่อพัฒนาโปรแกรม แต่เนื่องจากรุ่นนี้ออกมาได้หลายปีร่วมๆสิบปีแล้ว (ออกมาปี 2009) เข้าไปในเว็บไซต์ของคาสิโอแต่กลับพบกับผิดหวัง ไม่มีลิ๊งค์ให้ดาวน์โหลด (Link ขาดไปนาน) ทั้งๆที่คู่มือต่างๆเช่นการใช้งาน SDK, ไลบรารี ต่างๆก็ยังมีให้ดาวน์โหลดปกติแต่เครื่องมือพัฒนาโปรแกรมตั้งแต่เขียนโปรแกรม คอมไพล์ บิวท์ กลับหายไป สุดท้ายต้องลงใต้ดินตามหา จนเจอยังมีคนปล่อยให้ดาวน์โหลดได้ แต่ต้องใช้ระยะเวลาความพยายามเป็นอาทิตย์เหมือนกัน ผมจะไม่แสดงลิ๊งค์นี้เพราะอาจติดขัดกับลิขสิทธิ์ของคาสิโอได้ (ถ้าใครอยากได้ก็ขอมาหลังไมค์ละกันครับ) เมื่อได้มาแล้วก็มาลงบนคอมพิวเตอร์โน๊ตบุ๊ค วินโดส์ 10 และจอของผมเป็น 4K ก็ไม่ได้มีปัญหาอะไร สามารถเปิดโปรแกรมมาได้ปกติ เครื่องมือพัฒนาโปรแกรมเรียกว่า integrated development environment (IDE) ตั้งแต่ปล่อยมาปี 2007 Casio ไม่เคยอัพเดทอีกเลย เครื่องมือนี้ใช้คอมไพเลอร์ของ Renesas SHC ซึ่งอิงภาษาซีของ ANSI C standard (C89)

เริ่มแรกใช้งานกับปัญหาที่ประสบ

แต่พอเริ่มคอมไพล์โปรแกรมทดสอบเล็กๆดูกลับมีปัญหาเล็กๆน้อยๆ เช่น ** L2011 (E) Invalid parameter specified in option “input” : “”C:\Program Files (x86)\CASIO\fx-9860G SDK\OS\FX\lib\setup.obj”” วิธีการแก้ไข ให้ถอนโปรแกรมไปติดตั้งใหม่ แต่ตอนติดตั้งให้ติดเลือกติดตั้งที่รากของไดรว์ C: (ไม่เลือกดีฟอลต์คือติดตั้งลง C:\Program fils(x86) เพราะโปรแกรมนี้รุ่นเก่าไม่ชอบ path ทีมีตัว space) ปัญหาเล็กๆน้อยๆ เหล่านี้พอหาได้ตามฟอรั่มที่เกี่ยวข้องกับเครื่องคิดเลขของคาสิโอครับ แต่แล้วเส้นทางนี้ไม่ได้โรยด้วยกลีบกุหลาบ ปัญหาที่นึกไม่ถึงคือ user interface ทางคาสิโอไม่ได้เตรียม document ไว้ให้เลย พวกสิ่งเหล่านี้ได้แก่การ input แม้กระทั่งการอ่านข้อมูลจากตัวแปรตัวอักษร A-Z ก็ไม่ได้ทำไว้ ข้อมูลเป็นตัวเลข เป็นสตริง ผมอาศัยไปอ่านตามฟอรั่มที่มีหลายคน hack ไว้ ตรงนี้เสียเวลาไปหลายสิบวันกว่าจะแกะและจูนได้

โปรแกรมแรกเป็นกรณีศึกษา -เขียนโปรแกรมแปลงพิกัดภูมิศาสตร์ (Geographic Calc)

จั่วหัวไปเหมือนโปรแกรมจะใหญ่โต แต่เปล่าเลยผมเคยเขียนโปรแกรมแปลงพิกัดระหว่าง UTM และค่าพิกัดภูมิศาสตร์ (Geographic) บน fx 5800P ก็ไม่ได้ยากเย็นอะไรมากเพราะการแปลงพิกัดเหลานี้มีสูตรที่แน่นอนถึงแม้สูตรจะยาวไปหน่อยก็ตาม แต่ก็ไม่ได้ยากเย็นอะไร ผมมีเรื่องการแปลงพิกัดค้างคาอยู่นิดหนึ่งคือในโปรแกรม Surveyor Pocket Tools ในส่วนการแปลงพิกัดจะสังเกตเห็นว่าไม่มีระบบพิกัด MGRS (Military Grid Reference System) ซึ่งสำหรับพลเรือนอย่างพวกเรา คงไม่มีโอกาสได้ใช้งานเท่าไหร่นัก ผมค้นดูไลบรารีที่สามารถแปลงพิกัดได้ตาม github ไปพบมาอันหนึ่งชื่อ mrgs พัฒนาโดย Howard Butler ซึ่งไลบรารีที่เขียนไว้ไม่ใหญ่มาก นอกจากแปลงพิกัด Transverse Mercator ได้ยังแปลง MGRS ได้ และโปรแกรมในรุ่นนี้ผมขอจำกัดแค่ดาตั้ม “WGS84

ส่วนผมเองต้องบอกก่อนว่าไม่ใช่แฟนพันธุ์แท้ภาษาซี พอจะเขียนได้แต่ไม่ได้เก่งกาจนัก ดังนั้นโปรแกรมที่เขียนขึ้นมาอาจจะมีส่วนใดส่วนหนึ่งที่เยิ่นเย้อไปบ้าง

ลอง Military Grid Reference System (MGRS) ดูสักตั้ง

ในส่วนระบบพิกัด MGRS ซึ่งผมเห็นว่ามันแปลกดีที่ระบบนี้เอาตัวอักษรและตัวเลขแบ่งเป็นกริดมาขมวดรวมกันก็กลายเป็นค่า coordinate ได้ ลองดูรูปแบบดังตัวอย่างด้านล่าง

    • 46Q …………………GZD only, precision level 6° × 8° (in most cases)
    • 46QFJ ……………….GZD and 100 km Grid Square ID, precision level 100 km
    • 46QFJ 1 6 ……………precision level 10 km
    • 46QFJ 12 67 ………….precision level 1 km
    • 46QFJ 123 678 ………..precision level 100 m
    • 46QFJ 1234 6789 ………precision level 10 m
    • 46QFJ 12345 67890 …….precision level 1 m

ในเบื้องต้นผมขอใช้ไลบรารีนี้เพื่อเป็นกรณีศึกษา เพื่อลองเขียนโปรแกรมแปลงพิกัด MGRS ดูบ้าง ซึ่งระบบพิกัดนี้เครื่องคิดเลข fx-5800P ทำไม่ได้แน่นอนครับเพราะเครื่องคิดเลขไม่มีระบบรับข้อมูลเป็นสตริง (ยาวสุดประมาณ 15 ตัวอักษร) นอกจากไม่มีระบบรับข้อมูลสตริงแล้ว ไม่มีไลบรารีตัดสตริงออกมาเป็นท่อนๆ

เส้นทางและระยะเวลาในการพัฒนา

เนื่องจากโปรแกรมแปลงพิกัดนี้เป็นโปรแกรมเล็กๆ ไลบรารีที่ผมไปเอามาใช้จาก github ก็ใช้ง่ายสะดวก แต่ติดปัญหาที่ผมบอกไปแล้วคือระบบติดต่อผู้ใช้รับข้อมูลตัวเลข ตัวอักษรทาง casio ไม่ได้เปิดเผยเอกสาร บางอย่างต้องเขียนเองเช่นการรับข้อมูลเป็นสายสตริงเช่นค่าพิกัด MGRS (ตัวอย่างเช่น “18SVK8588822509”) บางอย่างไปหาตามฟอรั่ม เลยใช้เวลาสำหรับโปรแกรมแรกนี้ประมาณหนึ่งอาทิตย์กว่าๆ ในตอนนี้โปรแกรมเล็กๆนี้ก็เสร็จพอใช้งานได้แล้ว คุณสมบัติของโปรแกรมนี้คือค่าพิกัด latitude/longitude ที่แปลงมาจาก MGRS หรือ UTM สามารถแสดงผลได้ในทศนิยมที่ห้า ซึ่งจะเทียบเท่ากับหน่วยมิลลิเมตร ที่เราชาวสำรวจที่ต้องใช้ ถ้าใครเคยใช้โปรแกรมแปลงพิกัด UTM <==> Geo ที่ผมเขียนด้วย fx-5800P จะสังเกตเห็นว่าคำนวณแล้วได้ทศนิยมแค่สองตำแหน่งเท่านั้น ข้อได้เปรียบของ fx-9860G II คือสถาปัตยกรรมของเครื่องรุ่นนี้สามารถใช้ตัวแปร double ได้ ซึ่งในงานสำรวจนั้นเพียงพออยู่แล้ว

มาดาวน์โหลดโปรแกรมไปทดสอบ

เมื่อผม compile และ build โปรแกรมในเครื่องมือพัฒนาโปรแกรมของคาสิโอ แล้วจะได้ไฟล์ที่นามสกุล G1A (ตัว A คงหมายความว่า AddIn) ถ้าสนใจก็ไปดาวน์โหลดได้ที่หน้าดาวน์โหลด เมื่อได้ไฟล์มาแล้วชื่อ “UTMGeo.G1A” จากนั้นให้ดึง SD card ที่เสียบอยู่ด้านบนเครื่องคิดเลข fx-9860G II SD แล้วนำมาเสียบที่เครื่องพีซีหรือโน๊ตบุ๊ค เมื่อเปิดด้วย windows explorer จากนั้นสร้างโฟลเดอร์ใหม่ อย่างของผมตั้งชื่อ “Survey Addin Programs” แล้วก็อปปี้ไฟล์ “UTMGeo.G1A” ไปไว้ที่โฟลเดอร์ดังกล่าวนี้

จากนั้นดึง SD card เอาไปเสียบที่เครื่องคิดเลขเหมือนเดิม จากนั้นกดปุ่ม “MENU” ที่คีย์บอร์ดของเครื่องคิดเลข จะเห็นไอคอนของโปรแกรม AddIn ขึ้นมาทั้งหมด ใช้คีย์บอร์ดลูกศรเลื่อนไปที่ “MEMORY” กด “EXE”

  • จะเห็นตัวหนังสือ Memory Manager พร้อมเมนูให้เลือก เลือกกดคีย์บอร์ด “F3” เพื่อเลือก F3:SD Card
  • จะเห็นโฟลเดอร์ ที่อยู่ในเครื่องคิดเลข จะเป็นชื่อสั้น 8.3 แบบระบบปฏิบัติการ DOS สมัยแต่ก่อน เลื่อนไปที่ [SURVEY~2] กด “EXE”
  • จะเห็นชื่อไฟล์ “UTMGeo.G1A” ที่เราก็อปปี้มาจากโน๊ตบุ๊คคอมพิวเตอร์นั่นเอง กด “F1” (SEL) และกดปุ่ม “F2” (COPY)
  • ที่นี้จะมีไดอะล็อกเล็กๆให้เลือกปลายทาง กดคีย์เลข 2 เลือกโฟลเดอร์ปลายทางเป็น “ROOT” กด “EXE” ถ้ามีไฟล์อยู่แล้วให้ยืนยันการเขียนทับ “Yes” ด้วยกดคีย์ “F1”
  • จากนั้นก็กดคีย์ “EXIT” หลายๆครั้ง สุดท้ายกดคีย์ “MENU” กดลูกศรเลื่อนลงไปด้านล่าง จะเห็นไอคอน “UTM Geo” จากนั้นกดปุ่ม “EXE”

ทดสอบการใช้งานโปรแกรมแปลงพิกัด Geographic Calc

เมื่อกด “EXE” เข้าไปแล้วจะเห็นบรรทัดบนสุดแสดงชื่อโปรแกรม “Geographic Calc” มีเมนูแบบง่ายๆ 4 เมนูให้เลือกคือ ต้องการเลือกตัวไหนก็กดตัวเลขตามเมนู

    1.  UTM to Geo – แปลงพิกัดจากระบบพิกัดฉากยูทีเอ็มไปยังค่าพิกัดภูมิศาสตร์ Latitude/Longitude
    2. Geo to UTM – แปลงพิกัดจากระบบพิกัดภูมิศาสตร์ไปยังระบบพิกัดฉากยูทีเอ็ม
    3. MGRS to Geo – แปลงพิกัดจากระบบพิกัด MGRS ไปยังระบบพิกัดภูมิศาสตร์
    4. Geo to MGRS – แปลงพิกัดจากระบบพิกัดภูมิศาสตร์ไปยังระบบพิกัด MGRS

แปลงพิกัดจากระบบพิกัดฉากยูทีเอ็มไปยังค่าพิกัดภูมิศาสตร์ (UTM to Geo)

ที่เมนูกดคีย์เลข “1” เข้าไปโปรแกรมจะถามค่าพิกัด North, East และตัวเลขของโซนยูทีเอ็ม ลองป้อนข้อมูลตามตัวอย่าง

จะได้ผลลัพธ์ดังต่อไปนี้ ครับตามที่กล่าวไปแล้วได้ทศนิยมค่าแลตติจูด ลองจิจูด ตำแหน่งที่ห้า

แปลงพิกัดจากพิกัดภูมิศาสตร์ไปยังระบบพิกัดฉากยูทีเอ็ม (Geo to UTM)

ที่เมนูกดเลข “2” โปรแกรมจะถามค่าพิกัดภูมิศาสตร์ สามารถป้อนทศนิยมได้มากกว่า 5 ตัว ป้อนค่ามุมตัวคั่นองศา ลิปดา ฟิลิปดาให้ใช้เครื่องหมายลบ (-) ค่าแลตติจูดลงท้ายให้ป้อนตัวอักษร ถ้าซึกโลกเหนือให้ป้อน “N” ตามหลัง ตามเป็นซีกโลกใต้ให้ป้อน “S” หรือค่าลองจิจูดซึกโลกตะวันตกให้ป้อนคำว่า “W” ลงท้าย ซีกโลกตะวันออกให้ป้อน “E” ลงท้าย ดูตัวอย่าง

เมื่อกด “EXE” จะได้ผลลัพธ์ดังนี้

แปลงค่าพิกัดจาก MGRS ไปยังค่าพิกัดภูมิศาสตร์ (MGRS to Geo)

ที่เมนูกดปุ่ม “3” เลือก โปรแกรมจะถามค่าพิกัด MGRS ป้อนไปดังรูปด้านล่าง

กด “EXE” จะได้ผลลัพธ์ค่าพิกัดภูมิศาสตร์

แปลงค่าพิกัดจากค่าพิกัดภูมิศาสตร์ ไปยัง MGRS  (Geo to MGRS)

ที่เมนูกดเลข “4” ลองป้อนค่าพิกัดแลตติจูด ลองจิจูดเข้าไปดังรูป

กด “EXE” จะได้ค่าผลลัพธ์ดังรูป

สรุป

ในขณะที่ลองเขียนโปรแกรมสำหรับเครื่องคิดเลข fx-9860G II นี้ ผมยังทำงานที่บังคลาเทศ ใช้เครื่องคิดเลขของน้องๆ แต่ด้วยความประทับใจเครื่องรุ่นนี้เลยสั่งซื้อเครื่องที่เมืองไทยส่งไปที่บ้านรอกลับไปค่อยไปลองเครื่องใหม่อีกที (สั่งจาก mr.finance ที่รับของแล้วค่อยโอนเงินอีกที บริการประทับใจครับ) ด้วยสนนราคาประมาณตอนนี้สี่พันบาทปลายๆ รวม SD card  มีความรู้สึกว่าคุ้มค่า ไม่ลังเลเหมือนก่อน ผมมีโครงการจะเขียนโปรแกรมเล็กๆด้วยภาษาซีอีกหลายโปรแกรมเพื่อแจกจ่ายเป็นโปรแกรมให้พี่ๆน้องๆในวงการสำรวจได้ใช้งานกันโดยไม่ได้คิดมูลค่า

ขอเพิ่มเติมอีกนิดครับ บทความที่นำเสนอมานี้ไม่ได้มีเจตนาส่งเสริมการขายเครื่องคิดเลขรุ่น fx-9860G II SD นี้ให้ขายดีขึ้นแต่อย่างใด สำหรับน้องๆนักศึกษาหรือช่างสำรวจที่จบมาทำงานใหม่ๆ เครื่องคิดเลข fx-5800P สามารถใช้งานได้ทั่วๆไปได้เพียงพอ โปรแกรมที่มีขายแและแจกจ่ายในวงการบ้านเราก็สามารถหามาใช้งานกันได้อย่างเหลือเฟือ และราคาเครื่องคิดเลข fx-5800P ก็พอจะซื้อหามาใช้งานได้ แต่สำหรับเครื่องคิดเลขรุ่น fx-9860G II SD นั้นราคามากกว่า fx-5800P ประมาณ 2-3 เท่า ถ้ามีเงินเหลือใช้ก็หาซื้อหามาใช้กันได้ สำหรับคนที่มีงานทำแล้วก็พอจะสามารถเก็บเงินซื้อได้

ผมเขียนบทความนี้เพื่อวงการศึกษาช่างสำรวจบ้านเราที่สนใจเรื่องโปรแกรมมิ่งสามารถจะพัฒนาโปรแกรมภาษาซีบนเครื่องคิดเลขรุ่นนี้ได้ โดยที่มีไม่มีข้อจำกัดด้านภาษาโปรแกรมมิ่งแต่อย่างใด เหมือนภาษา basic casio อาจจะส่งผลให้ในอนาคต มีโปรแกรมที่พัฒนาโดยบุคคลากรท่านอื่นๆ เข้ามาสู่วงการนี้มากขึ้น และได้ตัวโปรแกรมงานสำรวจก็มีความหลากหลายและความสามารถมากขึ้น ในบทความตอนหน้าไม่กี่ตอนจากนี้ไปจะมีบทความ แนะนำการใช้เครื่องมือพัฒนาโปรแกรม SDK (Software Development Kit) ของ casio และเทคนิคการใช้เครื่องมืออื่นๆที่ แฮกเกอร์เครื่องคิดเลขรุ่นนี้ได้ reverse-engineering เขียนเผยแพร่ไว้ หรือแม้กระทั่งใช้ฟังก์ชั่นที่ไม่ได้เปิดเผยจากทาง casio เองก็ตาม พบกันใหม่ครับ