DIY แนวการสร้างระบบหาตำแหน่งดาว GOTO #4


ต้องไปอ่าน DIY แนวการสร้างระบบหาตำแหน่งดาว GOTO #1, #2, #3ก่อนนะครับ
#1
https://ppantip.com/topic/37233072
#2
https://ppantip.com/topic/37235270
#3
https://ppantip.com/topic/37236971
#4
https://ppantip.com/topic/37238646
#5
https://ppantip.com/topic/37238689

*********************************************************************************
กระทู้อื่นเดิมๆที่ใครเผื่อสนใจครับ
การสร้างอุปกรณ์ตามดาวด้วยตัวเอง DIY star tracking #1
http://ppantip.com/topic/35228265
การสร้างอุปกรณ์ตามดาวด้วยตัวเอง DIY star tracking #2
http://ppantip.com/topic/35233329
การสร้างอุปกรณ์ตามดาวด้วยตัวเอง DIY star tracking #3
http://ppantip.com/topic/35237413
การสร้างวงจรขับ motor สำหรับ การถ่ายภาพดาราศาสตร์,high accuracy motor driver for star tracker
http://ppantip.com/topic/35222366
การใช้งานวงจรขับ และอุปกรณ์ตามดาวแบบติดมอเตอร์เบื้องต้น Basic Motor Drive Barn Door Tracker
http://ppantip.com/topic/35244410
การสร้าง และอุปกรณ์ขับมอเตอร์ในสิบนาที
https://ppantip.com/topic/36658223/comment1
DIY เลนส์ ฮีทเตอร์กันฝ้าสำหรับนักถ่ายดาว
https://ppantip.com/topic/35745572
**********************************************************************************


ในส่วนนี้จะพูดถึงฟังค์ขั่นย่อยๆ ของการหาตัวแปรแต่ละตัว เพื่อการแปลงค่า RA, DEC เป็น Az, Alt ตอนต้นว่าจะข้ามไปดีไหม เพราะ สุดท้ายจะเอาไปรวมกันในถอนถัดไป เกรงว่าจะงง ก็เป็นเอาว่าอ่านผ่านๆไปในส่วนโปรแกรมก็ได้ ยกเว้นอยากรู้ว่ามันคำนวณอย่างไรครับ

ตามที่เราสรุปก่อนหน้านี้ว่าขบวนการทำงานจะเป็นแบบนี้

Stellarium ส่งพิกัดดาว > อุปกรณ์ Goto คำนวณตำแหน่งดาว > สั่งกล้องหมุน Motor ไปที่ดาว > Track ตำแหน่งกล้อง > ส่งข้อมูลพิกัดกล้องกลับไปยัง Stellarium > Stellarium แสดงผลบนจอ

ใน Lesson 1 เราทดลองสื่อสารกับ Stellarium และสมมุติ กล้องดูดาวเราหมุนไปที่ตำแหน่งนั้น ซึ่งความจริงยังไม่ใช่ ในความเป็นจริงกล้องดูดาวจะค่อยๆเคลื่อนไป เราก็ต้องตามกล้องไปเรื่อยๆว่าอยู่จุดไหนแล้ว
ทีนี้เราอย่าลืมว่าระบบกล้องดูดาวของเราที่จะทำนั้นเป็นระบบ Az, Alt ซึ่งแน่นอนมันไม่รู้จักค่า RA, DEC ที่ส่งมา เราจึงต้องมีการแปลงพิกัดดังที่อธิบายในเบื้องต้นแล้ว ขั้นตอนจึงจะกลายเป็นแบบนี้

Stellarium ส่งพิกัดดาว  RA,DEC > อุปกรณ์ Goto แปลงพิกัดเป็น Az,Alt > อุปกรณ์ Goto คำนวณตำแหน่งดาว > สั่งกล้องหมุน Motor ไปที่มุม Az, Alt> Track ตำแหน่งกล้อง Az, Alt ขณะเคลื่อนไป > อุปกรณ์ Goto แปลงพิกัด Az Alt เป็น RA, DEC  > ส่งข้อมูลพิกัดกล้องกลับไปยัง Stellarium > Stellarium แสดงผลบนจอ

อย่าลืมว่าก่อนจะแปลงค่าเราต้องรู้เวลา และพิกัด GPS ที่เรายืนอยู่ และ หาจาก

J2000 >  LST > HA > A > AZ > ALT


ฟังค์ชั่นต่อไปนี้ให้รู้การคำนวณแต่ละส่วนเท่านั้น เราจะเอาไปประกอบ กันอีกทีใน Lesson2

******************************************************************************************

การหา J2000
ฟังค์ชั่นในการหาค่าก็ง่ายๆ เหมือนนับนิ้วนั่นแหละ นับไปเรื่อยๆจากวันที่ 1 Jan 2000 มาถึงวันนี้ว่ามีกี่วัน ต้องมีการระบุ Timezone ด้วยเพื่อหาเศษของวัน


//**********************************************************************************************
double J2000(byte h, byte mi, byte s, byte d, byte mo, int y, double TZ)
// input  hour, minute, second, date, month, year (2017=17), Timezone
{
  double TotalDay = 0;
  int Yday = 0;
  int MoDay = 0;
  double UT;
  for (int i = 0; i <= y; i++)
  {
    if (((int(i) + 1999) % 4) == 0)
    {
      Yday = Yday + 366;
    }
    else
    {
      Yday = Yday + 365;
    }
  }

  for (int i = 1; i < mo; i++)
  {
    MoDay = MoDay + mday(i, y);
  }
  UT = (h + (double(mi) / 60.0000) + (double(s) / 3600.0000)) - TZ;
  TotalDay = (Yday - 366.5 + MoDay + d) + (UT / 24);
  return TotalDay;

}
//---------------------------------------------------------------------------------------return days of month---------
int mday(byte m, byte y)//return day of month
{
  int i[13];
  i[0] = 0;// Not use
  i[1] = 31; //Jan
  if (((int(y) + 2000) % 4) == 0)
  {
    i[2] = 29; //Feb
  }
  else
  {
    i[2] = 28; //Feb
  }
  i[3] = 31; // Mar
  i[4] = 30; //Apr
  i[5] = 31; //May
  i[6] = 30; //Jun
  i[7] = 31; //Jul
  i[8] = 31; //Aug
  i[9] = 30; //Sep
  i[10] = 31; //Oct
  i[11] = 30; //Nov
  i[12] = 31; //Dec

  return i[m];

}


//**********************************************************************************



จะเห็นว่าเราต้องใส่เวลาลงไปทุกครั้งในบางทีเราอาจต้องใช้ พวก Module มาช่วย ยกตัวอย่างเช่น Tiny RTC จะสะดวกกว่ามากเลย

Tiny RTC

การมีวงจรพวกนี้ทำให้เราไม่ต้องมาใส่ค่าเวลาตลอดเวลาซึ่งจำเป็นมาก แต่หากไม่มีเราสามารถเขียนโปรแกรมเองก็ได้ แต่ไม่สะดวกในการใช้งานเลย

การใช้งานหาซื้อ อาจต้องลองหาจากร้านขายใน internet หรือขายอุปกรณ์ Controller ตัวอย่าง Code ตั้งนาฬิกา ต้องทำครั้งแรก

//*******************************************************************************************
#include <Wire.h>
#define DS1307_I2C_ADDRESS 0x68  // the I2C address of Tiny RTC

byte second, xminute, xhour, dayOfWeek, DateOfMonth, month, xyear;
boolean RelayType;//Type of Relay HIGH=ON or LOW=ON
unsigned long xTimeSerial; //convert Hr, Min, Sec to serial
unsigned long SetTime,StartTime, CurTime;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  setDateDs1307(00,26,9,3,5,10,17);//-----Change Clock Here อย่าลืมแก้ไขเวลาตรงนี้  วินาที นาที ขั่วโมง วันของสัปดาห์ วันที่ เดือน ปี
getDateDs1307();
SetTime=((xhour*3600)+(xminute*60)+second)*1000;//in micro sec
StartTime=millis();
CurTime=0;

}

void loop()
{
getDateDs1307();
Serial.print("RTC:");
Serial.print(xhour);Serial.print(":");Serial.print(xminute);Serial.print(":");Serial.print(second);Serial.print("\t");
Serial.print(DateOfMonth);Serial.print(":");Serial.print(month);Serial.print(":");Serial.print(xyear);Serial.print("\t");
CurTime=SetTime+(millis()-StartTime);
  Serial.print(" InnerClock:");
Serial.print("  ");Serial.print(Sec2Hr(CurTime/1000));Serial.println("\t");

delay(1000);

}


// Function to set the current time, change the second&xminute&hour to the right time
void setDateDs1307(byte xsec, byte xmin, byte xhr, byte xday, byte xdate, byte xmonth, byte xyear)
{
  second = xsec;
  xminute = xmin;
  xhour  = xhr;
  dayOfWeek = xday;
  DateOfMonth = xdate;
  month = xmonth;
  xyear = xyear;
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(decToBcd(0));
  Wire.write(decToBcd(second));    // 0 to bit 7 starts the clock
  Wire.write(decToBcd(xminute));
  Wire.write(decToBcd(xhour));      // If you want 12 hour am/pm you need to set
  // bit 6 (also need to change readDateDs1307)
  Wire.write(decToBcd(dayOfWeek));
  Wire.write(decToBcd(DateOfMonth));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(xyear));
  Wire.endTransmission();
}

//------------------------------------------------------------------------------
// Function to gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
  // Reset the register pointer
  Wire.beginTransmission(DS1307_I2C_ADDRESS);
  Wire.write(decToBcd(0));
  Wire.endTransmission();
  Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
  second     = bcdToDec(Wire.read() & 0x7f);// bitwise to remove bit 7 (data only bit 0-6)
  xminute     = bcdToDec(Wire.read());
  xhour       = bcdToDec(Wire.read() & 0x3f);  // Need to change this if 12 hour am/pm, read only bit 0-5 for 24 Hr format
  dayOfWeek  = bcdToDec(Wire.read());
  DateOfMonth = bcdToDec(Wire.read());
  month      = bcdToDec(Wire.read());
  xyear       = bcdToDec(Wire.read());
}


//*****************************************************************************************************


ถ้ามี RTC Module ก็สะดวกไม่ต้องตั้งค่าเวลาใหม่ทุกครั้ง เวลาจะอ่านจาก Function getDateDS1307  อย่าลืมว่าตั้งนาฬิกาแล้ว อย่าสั่ง Upload โปรแกรมนี้อีกเพราะมันจะตั้งนาฬิกาไปที่เดิม Upload โปรแกรมอื่นเข้าไปแทน หรือถอด RTC ออกก่อน ทำแค่ครั้งเดียวมันจะอยู่ได้ตลอดจนกว่าแบตหมด หากเวลาเพี้ยนก็ตั้งใหม่


การหา LST

//******************************************************************************************************
double LST(double J2000d, long Ctime, double TimeZone, double LongT)
                // J2000 day, current time in sec, time zone Hr, Logtitude in sec
{
//Reture Local Sidereal Time in sec of Hr, if need to change to degree multiplied by 15

  double LSx;
  double UTx;
  UTx = Ctime - (double(TimeZone) * 3600);
  LSx = 100.46 + (0.985647 * J2000d) + (LongT / 3600) + (UTx / 240); // in degree
  while (LSx > (360))// in degree
  { LSx = LSx - (360);
  }
  while (LSx < 0)
  { LSx = LSx + (360);
  }

  return (LSx * 240); // change to sec of Hr *3600/15
}

//***************************************************************


กาหาค่า HA และแปลง RA, DEC เป็น Az, Alt (หรือแปลงจากระบบ EQ เป็น Az)

Function ต่อไปนี้จะแปลง ค่า RA และ DEC เป็น Azimuth, Altitude ค่าทุกค่าที่ใช้ในการส่งผ่านนั้นจะแปลงให้อยู่ในรูป วินาที หรือ ฟิลิบดา เพื่อสะดวกในการส่งผ่าน และจำเป็นต้องแปลงกลับในการคำนวณ มุมต้องเป็นเรเดียนเนื่องจากคำสั่งทางคณิตศาสตร์จะไม่รับหน่วยองศา โดย
1 ชม = 60 นาที = 3,600 วินาที
1 องศา = 60ลิปดา = 3,600 ฟิลิบดา
1 วัน = 24ชม = 86,400 วินาที
360 องศา = 1,296,000 ฟิลิบดา
โลกหมุน 1 รอบ =24 ชม = 360 องศา
หรือ 1 ชม โลกหมุนไป 15องศา
360 องศา = 2pi radian = 1,296,000 ฟิลิบดา
1pi = 3.14159265359 = 180 องศา = 648,000

ในการคำนวณจะแปลงกลับไปกลับมา อาจจะสับสนเล็กน้อย ผมเองก็งงไปงงมาไปหลายตลบกว่ามันจะคำนวณถูกใช้เวลาหลายวันเพราะเรื่องหน่วยนี่แหละ มีทั้งองศา เรเดียน ฟิลิบดา วินาที
การคำนวณควรใช้ Double แม้ว่า MCU Arduino จะรับแค่ floating point ก็ตาม ให้ใส่เป็น double เผื่ออนาคต และหากใช้ MCU พวก Raspberry Pi หรือ ESP นั้นจะสามารถใช้ Double ได้ (ผมไม่เคยใช้ Raspberry Pi แต่ทราบว่ามันรองรับ)
อย่างไรก็ตามข้อมูลใน Internet ทั้งหมดมักบอกและเชื่อต่อๆกันมาว่าว่า Floating point ของ Arduino ไม่ละเอียดพอที่จะใช้งานได้กับงานนี้ เนื่องจากคนส่วนใหญ่นั้นเขียนโปรแกรมโดยไม่เข้าใจลักษณะบางประการของตัวแปรซึ่งแม้แต่การเรียงลำดับของคำสั่งก็มีผล ใน function ข้างล่างนี้ได้แก้ไขหมดแล้วโดยสามารถคำนวณได้ถูกต้องใช้งานได้แม้แต่บน Arduino MCU

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