风筝
发表于: 2020-4-11 17:36:13 | 显示全部楼层

在本篇文章中,我们将讨论如何使用Arduino开发板和OLED显示屏制作月相计算器。该项目在0.96英寸OLED显示屏上显示月相。显示了八个月相,并附有简短说明,还显示了临近满月的剩余天数。


本篇文章使用了实时时钟RTC模块DS3231或DS1307提供日期。该日期将转换为农历日期。通过选择一个已知满月的日期(在本例中为1972年1月1日),可以轻松计算从该起点到现在的天数。


为什么月亮有相位?

月球具有相位,因为它绕地球旋转,这导致我们看到的照明部分发生了变化。月球绕地球运行需要27.3天,但月相周期(从新月到新月)为29.5天。月球花费了额外的2.2天“追赶”时间,因为在月球完成绕地球一周的轨道运行期间,地球绕太阳行进了约4500万英里。

phases-of-moon.gif


在新的月相中,月亮是靠近天空中的太阳,以至于没有一个面向地球的侧面被照亮(插图中的位置1)。换句话说,月亮在地球和太阳之间。在第一部分,半昏暗的月亮在日落时是天空中最高的,然后大约六个小时后落下(3)。在满月时,月球相对于太阳在太空中位于地球后面。随着太阳落山,月亮升起,而面对地球的一面则完全暴露在阳光下(5)。


所需的组件

●    0.96英寸OLED显示屏

●    Arduino UNO开发板

●    RTC模块DS3231或DS1307

●    面包板

●    连接跳线


连接电路图

Circuit-Diagram.png

OLED和RTC模块DS3231均由5V电源供电。 OLED和DS3231的SCL和SDA引脚连接到Arduino的SCL和SDA引脚,即A4和A5。


设计月相计算器

月亮需要29.53天才能完成从一个满月到下一个满月的周期,因此,如果将1972年1月1日以来的天数除以29.53,则余数就是距离这一个满月剩余的天数。

moon-phase.jpg

程序代码将农历月份分为八个部分,从满月开始,然后是残月、下弦月、娥眉月、新月、上弦月、渐盈凸月、渐亏凸月,然后就是下一个满月。还显示到下一个满月的天数。


结果与显示

一旦将代码上传到Arduino UNO开发板上,将显示月相,并且日期也将显示为1、2、3、4……..28,如图所示下面。

1.jpg


源代码/程序

首先添加两个库,即U8glib库和RTC库,否则代码将无法编译。

●    下载U8glib库

●    下载RTClib库

  1. #include "U8glib.h"
  2. #include <SPI.h>
  3. #include <Wire.h>
  4. #include "RTClib.h"

  5. U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // I2C setup u8g object

  6. RTC_DS1307 RTC;

  7. static unsigned char full_moon_bits[] = {
  8. 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x3f, 0x00,
  9. 0x80, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0x01, 0xf0, 0xff, 0xff, 0x03,
  10. 0xf0, 0xff, 0xff, 0x03, 0xf8, 0xff, 0xff, 0x07, 0xfc, 0xff, 0xff, 0x0f,
  11. 0xfc, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0x1f,
  12. 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f,
  13. 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f,
  14. 0xfe, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0f,
  15. 0xfc, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x03,
  16. 0xf0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x01, 0x80, 0xff, 0x7f, 0x00,
  17. 0x00, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 };

  18. static unsigned char waning_gibbous_bits[] = {
  19. 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xff, 0x00,
  20. 0xe0, 0xff, 0xff, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0x7f, 0x00,
  21. 0xf8, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x1f, 0x00,
  22. 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x0f, 0x00,
  23. 0xff, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00,
  24. 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00,
  25. 0xff, 0xff, 0x07, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x0f, 0x00,
  26. 0xfe, 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xf8, 0xff, 0x1f, 0x00,
  27. 0xf8, 0xff, 0x3f, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0x00,
  28. 0x80, 0xff, 0xff, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0x1f, 0x00 };

  29. static unsigned char last_quarter_bits[] = {
  30. 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x80, 0xff, 0x01, 0x00,
  31. 0xe0, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00,
  32. 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
  33. 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
  34. 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
  35. 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
  36. 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
  37. 0xfe, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00,
  38. 0xf8, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x01, 0x00,
  39. 0x80, 0xff, 0x01, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xf8, 0x0f, 0x00 };

  40. static unsigned char crescent_old_bits[] = {
  41. 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00,
  42. 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
  43. 0xf8, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
  44. 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
  45. 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
  46. 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
  47. 0x3f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
  48. 0x7e, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
  49. 0xf8, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00,
  50. 0x80, 0x1f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00 };

  51. static unsigned char new_moon_bits[] = {
  52. 0x00, 0xf8, 0x07, 0x00, 0x00, 0x07, 0x38, 0x00, 0x80, 0x00, 0x40, 0x00,
  53. 0x60, 0x00, 0x80, 0x01, 0x10, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x04,
  54. 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x10,
  55. 0x02, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x20,
  56. 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
  57. 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
  58. 0x01, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10,
  59. 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04,
  60. 0x08, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x02, 0x60, 0x00, 0x80, 0x01,
  61. 0x80, 0x00, 0x40, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0xf8, 0x07, 0x00 };

  62. static unsigned char crescent_new_bits[] = {
  63. 0x00, 0xf8, 0x07, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x7e, 0x00,
  64. 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x07,
  65. 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x1f,
  66. 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x3f,
  67. 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f,
  68. 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f,
  69. 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x80, 0x1f,
  70. 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xe0, 0x07,
  71. 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xfc, 0x01,
  72. 0x00, 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf8, 0x07, 0x00 };

  73. static unsigned char first_quarter_bits[] = {
  74. 0x00, 0xfc, 0x07, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xe0, 0x7f, 0x00,
  75. 0x00, 0xe0, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x07,
  76. 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f,
  77. 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfc, 0x3f,
  78. 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f,
  79. 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f,
  80. 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x1f,
  81. 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x07,
  82. 0x00, 0x80, 0xff, 0x07, 0x00, 0xc0, 0xff, 0x03, 0x00, 0xe0, 0xff, 0x01,
  83. 0x00, 0xe0, 0x7f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x07, 0x00 };

  84. static unsigned char waxing_gibbous_bits[] = {
  85. 0x00, 0xfc, 0x07, 0x00, 0x00, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0x7f, 0x00,
  86. 0xc0, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0x07,
  87. 0x00, 0xff, 0xff, 0x07, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x1f,
  88. 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x3f,
  89. 0x00, 0xfc, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f,
  90. 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f,
  91. 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x1f,
  92. 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x07,
  93. 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x01,
  94. 0xc0, 0xff, 0x7f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0x07, 0x00 };
  95. //
  96. String nfm = ""; // days to next full moon

  97. void setup() {
  98. Serial.begin(9600);
  99. RTC.begin();
  100. if (! RTC.isrunning()) {
  101. Serial.println("RTC is NOT running!");
  102. }
  103. // following line sets the RTC to the date & time this sketch was compiled
  104. // un REM the line below to set clock, then re REM it
  105. // and upload this sketch again
  106. //RTC.adjust(DateTime(__DATE__, __TIME__));
  107. //
  108. Wire.begin();
  109. }

  110. void loop() {
  111. //draw loop
  112. u8g.firstPage();
  113. do {
  114. drawMoon();
  115. } while( u8g.nextPage() );
  116. // rebuild the picture after some delay
  117. delay(50);
  118. }

  119. void drawMoon(void){
  120. DateTime now = RTC.now();
  121. u8g.setFont(u8g_font_profont12);
  122. u8g.setFont(u8g_font_5x7);
  123. u8g.drawStr(15,10, "Moon Phase Calculator");
  124. u8g.drawLine(0,13,128,13);
  125. int mp = moon_phase();
  126. u8g.setFont(u8g_font_profont15);
  127. switch (mp){
  128. case 0:
  129. u8g.drawStr(15,61, " Full Moon ");
  130. u8g.drawXBM(45,18,30,30,full_moon_bits);
  131. break;
  132. case 1:
  133. u8g.drawStr(15,61, "Waning Gibbous");
  134. u8g.drawXBM(45,18,30,30,waning_gibbous_bits);
  135. break;
  136. case 2:
  137. u8g.drawStr(15,61, " Last Quarter ");
  138. u8g.drawXBM(45,18,30,30,last_quarter_bits);
  139. break;
  140. case 3:
  141. u8g.drawStr(15,61, " Old Crescent ");
  142. u8g.drawXBM(45,18,30,30,crescent_old_bits);
  143. break;
  144. case 4:
  145. u8g.drawStr(15,61, " New Moon ");
  146. u8g.drawXBM(45,18,30,30,new_moon_bits);
  147. break;
  148. case 5:
  149. u8g.drawStr(15,61, " New Crescent ");
  150. u8g.drawXBM(45,18,30,30,crescent_new_bits);
  151. break;
  152. case 6:
  153. u8g.drawStr(15,61, " First Quarter");
  154. u8g.drawXBM(45,18,30,30,first_quarter_bits);
  155. break;
  156. case 7:
  157. u8g.drawStr(15,61, "Waxing Gibbous");
  158. u8g.drawXBM(45,18,30,30,waxing_gibbous_bits);
  159. break;
  160. }
  161. const char* newNfm = (const char*) nfm.c_str();
  162. u8g.drawStr(110,30, newNfm);
  163. }

  164. int moon_phase(){
  165. // calculates the age of the moon phase(0 to 7)
  166. // there are eight stages, 0 is full moon and 4 is a new moon
  167. DateTime now = RTC.now();
  168. double jd = 0; // Julian Date
  169. double ed = 0; //days elapsed since start of full moon
  170. int b= 0;
  171. jd = julianDate(now.year(), now.month(), now.day());
  172. //jd = julianDate(1972,1,1); // used to debug this is a new moon
  173. jd = int(jd - 2244116.75); // start at Jan 1 1972
  174. jd /= 29.53; // divide by the moon cycle
  175. b = jd;
  176. jd -= b; // leaves the fractional part of jd
  177. ed = jd * 29.53; // days elapsed this month
  178. nfm = String((int(29.53 - ed))); // days to next full moon
  179. b = jd*8 +0.5;
  180. b = b & 7;
  181. return b;

  182. }
  183. double julianDate(int y, int m, int d){
  184. // convert a date to a Julian Date}
  185. int mm,yy;
  186. double k1, k2, k3;
  187. double j;

  188. yy = y- int((12-m)/10);
  189. mm = m+9;
  190. if(mm >= 12) {
  191. mm = mm-12;
  192. }
  193. k1 = 365.25 *(yy +4172);
  194. k2 = int((30.6001 * mm) + 0.5);
  195. k3 = int((((yy/100) + 4) * 0.75) -38);
  196. j = k1 +k2 + d + 59;
  197. j = j-k3; // j is the Julian date at 12h UT (Universal Time)

  198. return j;
  199. }
复制代码

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1479



手机版|

GMT+8, 2024-3-29 05:00 , Processed in 0.094061 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表