|
在本篇文章中,我们将讨论如何使用Arduino开发板和OLED显示屏制作月相计算器。该项目在0.96英寸OLED显示屏上显示月相。显示了八个月相,并附有简短说明,还显示了临近满月的剩余天数。
本篇文章使用了实时时钟RTC模块DS3231或DS1307提供日期。该日期将转换为农历日期。通过选择一个已知满月的日期(在本例中为1972年1月1日),可以轻松计算从该起点到现在的天数。
为什么月亮有相位? 月球具有相位,因为它绕地球旋转,这导致我们看到的照明部分发生了变化。月球绕地球运行需要27.3天,但月相周期(从新月到新月)为29.5天。月球花费了额外的2.2天“追赶”时间,因为在月球完成绕地球一周的轨道运行期间,地球绕太阳行进了约4500万英里。
在新的月相中,月亮是靠近天空中的太阳,以至于没有一个面向地球的侧面被照亮(插图中的位置1)。换句话说,月亮在地球和太阳之间。在第一部分,半昏暗的月亮在日落时是天空中最高的,然后大约六个小时后落下(3)。在满月时,月球相对于太阳在太空中位于地球后面。随着太阳落山,月亮升起,而面对地球的一面则完全暴露在阳光下(5)。
所需的组件 ● 0.96英寸OLED显示屏 ● Arduino UNO开发板 ● RTC模块DS3231或DS1307 ● 面包板 ● 连接跳线
连接电路图
OLED和RTC模块DS3231均由5V电源供电。 OLED和DS3231的SCL和SDA引脚连接到Arduino的SCL和SDA引脚,即A4和A5。
设计月相计算器 月亮需要29.53天才能完成从一个满月到下一个满月的周期,因此,如果将1972年1月1日以来的天数除以29.53,则余数就是距离这一个满月剩余的天数。
程序代码将农历月份分为八个部分,从满月开始,然后是残月、下弦月、娥眉月、新月、上弦月、渐盈凸月、渐亏凸月,然后就是下一个满月。还显示到下一个满月的天数。
结果与显示 一旦将代码上传到Arduino UNO开发板上,将显示月相,并且日期也将显示为1、2、3、4……..28,如图所示下面。
源代码/程序 首先添加两个库,即U8glib库和RTC库,否则代码将无法编译。 ● 下载U8glib库 ● 下载RTClib库 - #include "U8glib.h"
- #include <SPI.h>
- #include <Wire.h>
- #include "RTClib.h"
- U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE); // I2C setup u8g object
- RTC_DS1307 RTC;
- static unsigned char full_moon_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x3f, 0x00,
- 0x80, 0xff, 0x7f, 0x00, 0xe0, 0xff, 0xff, 0x01, 0xf0, 0xff, 0xff, 0x03,
- 0xf0, 0xff, 0xff, 0x03, 0xf8, 0xff, 0xff, 0x07, 0xfc, 0xff, 0xff, 0x0f,
- 0xfc, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0f, 0xfe, 0xff, 0xff, 0x1f,
- 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f,
- 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0xff, 0x1f,
- 0xfe, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x0f,
- 0xfc, 0xff, 0xff, 0x0f, 0xf8, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x03,
- 0xf0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x01, 0x80, 0xff, 0x7f, 0x00,
- 0x00, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00 };
- static unsigned char waning_gibbous_bits[] = {
- 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x80, 0xff, 0xff, 0x00,
- 0xe0, 0xff, 0xff, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0xf8, 0xff, 0x7f, 0x00,
- 0xf8, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x1f, 0x00,
- 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x0f, 0x00,
- 0xff, 0xff, 0x0f, 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00,
- 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07, 0x00,
- 0xff, 0xff, 0x07, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x0f, 0x00,
- 0xfe, 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xf8, 0xff, 0x1f, 0x00,
- 0xf8, 0xff, 0x3f, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0x00,
- 0x80, 0xff, 0xff, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xf8, 0x1f, 0x00 };
- static unsigned char last_quarter_bits[] = {
- 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x80, 0xff, 0x01, 0x00,
- 0xe0, 0xff, 0x01, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00,
- 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
- 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
- 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
- 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00,
- 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
- 0xfe, 0x1f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00,
- 0xf8, 0x7f, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x01, 0x00,
- 0x80, 0xff, 0x01, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xf8, 0x0f, 0x00 };
- static unsigned char crescent_old_bits[] = {
- 0x00, 0xf8, 0x07, 0x00, 0x00, 0xff, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00,
- 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
- 0xf8, 0x01, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
- 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00,
- 0x3f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
- 0x7e, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
- 0xf8, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00,
- 0x80, 0x1f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00 };
- static unsigned char new_moon_bits[] = {
- 0x00, 0xf8, 0x07, 0x00, 0x00, 0x07, 0x38, 0x00, 0x80, 0x00, 0x40, 0x00,
- 0x60, 0x00, 0x80, 0x01, 0x10, 0x00, 0x00, 0x02, 0x08, 0x00, 0x00, 0x04,
- 0x08, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x08, 0x02, 0x00, 0x00, 0x10,
- 0x02, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x20,
- 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
- 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0x20,
- 0x01, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x10, 0x02, 0x00, 0x00, 0x10,
- 0x02, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x04,
- 0x08, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x02, 0x60, 0x00, 0x80, 0x01,
- 0x80, 0x00, 0x40, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0xf8, 0x07, 0x00 };
- static unsigned char crescent_new_bits[] = {
- 0x00, 0xf8, 0x07, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x7e, 0x00,
- 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xe0, 0x07,
- 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x1f,
- 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x3f,
- 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f,
- 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x3f,
- 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x80, 0x1f,
- 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xe0, 0x07,
- 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xfc, 0x01,
- 0x00, 0x00, 0x7e, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0xf8, 0x07, 0x00 };
- static unsigned char first_quarter_bits[] = {
- 0x00, 0xfc, 0x07, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xe0, 0x7f, 0x00,
- 0x00, 0xe0, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x03, 0x00, 0x80, 0xff, 0x07,
- 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f,
- 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xfc, 0x3f,
- 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f,
- 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xfc, 0x3f,
- 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xfe, 0x1f,
- 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0x07,
- 0x00, 0x80, 0xff, 0x07, 0x00, 0xc0, 0xff, 0x03, 0x00, 0xe0, 0xff, 0x01,
- 0x00, 0xe0, 0x7f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x07, 0x00 };
- static unsigned char waxing_gibbous_bits[] = {
- 0x00, 0xfc, 0x07, 0x00, 0x00, 0xff, 0x3f, 0x00, 0xc0, 0xff, 0x7f, 0x00,
- 0xc0, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0x07,
- 0x00, 0xff, 0xff, 0x07, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x1f,
- 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x3f,
- 0x00, 0xfc, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f,
- 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xf8, 0xff, 0x3f,
- 0x00, 0xf8, 0xff, 0x3f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfc, 0xff, 0x1f,
- 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0xfe, 0xff, 0x07,
- 0x00, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x01,
- 0xc0, 0xff, 0x7f, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0x07, 0x00 };
- //
- String nfm = ""; // days to next full moon
- void setup() {
- Serial.begin(9600);
- RTC.begin();
- if (! RTC.isrunning()) {
- Serial.println("RTC is NOT running!");
- }
- // following line sets the RTC to the date & time this sketch was compiled
- // un REM the line below to set clock, then re REM it
- // and upload this sketch again
- //RTC.adjust(DateTime(__DATE__, __TIME__));
- //
- Wire.begin();
- }
- void loop() {
- //draw loop
- u8g.firstPage();
- do {
- drawMoon();
- } while( u8g.nextPage() );
- // rebuild the picture after some delay
- delay(50);
- }
- void drawMoon(void){
- DateTime now = RTC.now();
- u8g.setFont(u8g_font_profont12);
- u8g.setFont(u8g_font_5x7);
- u8g.drawStr(15,10, "Moon Phase Calculator");
- u8g.drawLine(0,13,128,13);
- int mp = moon_phase();
- u8g.setFont(u8g_font_profont15);
- switch (mp){
- case 0:
- u8g.drawStr(15,61, " Full Moon ");
- u8g.drawXBM(45,18,30,30,full_moon_bits);
- break;
- case 1:
- u8g.drawStr(15,61, "Waning Gibbous");
- u8g.drawXBM(45,18,30,30,waning_gibbous_bits);
- break;
- case 2:
- u8g.drawStr(15,61, " Last Quarter ");
- u8g.drawXBM(45,18,30,30,last_quarter_bits);
- break;
- case 3:
- u8g.drawStr(15,61, " Old Crescent ");
- u8g.drawXBM(45,18,30,30,crescent_old_bits);
- break;
- case 4:
- u8g.drawStr(15,61, " New Moon ");
- u8g.drawXBM(45,18,30,30,new_moon_bits);
- break;
- case 5:
- u8g.drawStr(15,61, " New Crescent ");
- u8g.drawXBM(45,18,30,30,crescent_new_bits);
- break;
- case 6:
- u8g.drawStr(15,61, " First Quarter");
- u8g.drawXBM(45,18,30,30,first_quarter_bits);
- break;
- case 7:
- u8g.drawStr(15,61, "Waxing Gibbous");
- u8g.drawXBM(45,18,30,30,waxing_gibbous_bits);
- break;
- }
- const char* newNfm = (const char*) nfm.c_str();
- u8g.drawStr(110,30, newNfm);
- }
- int moon_phase(){
- // calculates the age of the moon phase(0 to 7)
- // there are eight stages, 0 is full moon and 4 is a new moon
- DateTime now = RTC.now();
- double jd = 0; // Julian Date
- double ed = 0; //days elapsed since start of full moon
- int b= 0;
- jd = julianDate(now.year(), now.month(), now.day());
- //jd = julianDate(1972,1,1); // used to debug this is a new moon
- jd = int(jd - 2244116.75); // start at Jan 1 1972
- jd /= 29.53; // divide by the moon cycle
- b = jd;
- jd -= b; // leaves the fractional part of jd
- ed = jd * 29.53; // days elapsed this month
- nfm = String((int(29.53 - ed))); // days to next full moon
- b = jd*8 +0.5;
- b = b & 7;
- return b;
- }
- double julianDate(int y, int m, int d){
- // convert a date to a Julian Date}
- int mm,yy;
- double k1, k2, k3;
- double j;
- yy = y- int((12-m)/10);
- mm = m+9;
- if(mm >= 12) {
- mm = mm-12;
- }
- k1 = 365.25 *(yy +4172);
- k2 = int((30.6001 * mm) + 0.5);
- k3 = int((((yy/100) + 4) * 0.75) -38);
- j = k1 +k2 + d + 59;
- j = j-k3; // j is the Julian date at 12h UT (Universal Time)
- return j;
- }
复制代码
|