FreeformAstronomyClock/Firmware/Astroclock.ino

317 lines
6.6 KiB
C++

#include <Arduino.h>
#include <TM1637Display.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
//display pins
#define CLK 8
#define DIO 9
//varibles to calculate LST
double M,Y,D,MN,H,S,A,B;
double LST_hours,LST_degrees;
//define GPS pins and The serial connection to the GPS device
static const int RXPin = 3, TXPin = 2;
static const uint32_t GPSBaud = 9600;
TinyGPSPlus gps;
SoftwareSerial ss(RXPin, TXPin);
int gpsOld = gps.time.minute();
//define 7-digit display pins
TM1637Display display(CLK, DIO);
//----------------------8x8 matrix display--------------------
int INTENSITYMIN = 0; // minimum brightness, valid range [0,15]
int INTENSITYMAX = 8; // maximum brightness, valid range [0,15]
int DIN_PIN = 4; // data in pin
int CS_PIN = 5; // load (CS) pin
int CLK_PIN = 6; // clock pin
// MAX7219 registers
byte MAXREG_DECODEMODE = 0x09;
byte MAXREG_INTENSITY = 0x0a;
byte MAXREG_SCANLIMIT = 0x0b;
byte MAXREG_SHUTDOWN = 0x0c;
byte MAXREG_DISPTEST = 0x0f;
//----------------------Moon phases--------------------------
unsigned char fullMoon[] =
{
B00111100,
B01111110,
B11111111,
B11111111,
B11111111,
B11111111,
B01111110,
B00111100
};
const unsigned char newMoon[] =
{
B00111100,
B01000010,
B10000001,
B10000001,
B10000001,
B10000001,
B01000010,
B00111100
};
const unsigned char firstQuarter[] =
{
B00001100,
B00001110,
B00001111,
B00001111,
B00001111,
B00001111,
B00001110,
B00001100
};
const unsigned char thirdQuarter[] =
{
B00110000,
B01110000,
B11110000,
B11110000,
B11110000,
B11110000,
B01110000,
B00110000
};
const unsigned char waningCrescent[] =
{
B00111100,
B01110000,
B11100000,
B11100000,
B11100000,
B11100000,
B01110000,
B00111100
};
const unsigned char waxingCrescent[] =
{
B00111100,
B00001110,
B00000111,
B00000111,
B00000111,
B00000111,
B00001110,
B00111100
};
unsigned char waxingGibbous[] =
{
B00111100,
B01011110,
B10111111,
B10111111,
B10111111,
B10111111,
B01011110,
B00111100
};
unsigned char waningGibbous[] =
{
B00111100,
B01111010,
B11111101,
B11111101,
B11111101,
B11111101,
B01111010,
B00111100
};
//-----------------------------------------------------------
void setup() {
Serial.begin(115200); //Serial communication
ss.begin(GPSBaud); //Serial communication for GPS
pinMode(DIN_PIN, OUTPUT);
pinMode(CLK_PIN, OUTPUT);
pinMode(CS_PIN, OUTPUT);
// initialization of the MAX7219
setRegistry(MAXREG_SCANLIMIT, 0x07);
setRegistry(MAXREG_DECODEMODE, 0x00); // using an led matrix (not digits)
setRegistry(MAXREG_SHUTDOWN, 0x01); // not in shutdown mode
setRegistry(MAXREG_DISPTEST, 0x00); // no display test
setRegistry(MAXREG_INTENSITY, 0x0f & INTENSITYMAX);
}
void loop() {
smartDelay(0);
display.setBrightness(0x0f);
if(gps.time.minute()!=gpsOld){
LST_time();
int rHours =(int) LST_hours;
int rMinutes = ((int)floor((LST_hours-rHours)*60));
display.clear(); //reset display
display.showNumberDecEx(((rHours*100)+rMinutes),0b01000000,true,4,0);
int moonAge = ConwayMoon(gps.date.year(),gps.date.month(),gps.date.day());
drawMoon(moonAge); //draw the moon to 8x8 display
gpsOld = gps.time.minute();
//Serial print for debuging
/*
Serial.print("UTC: ");
Serial.print(gps.time.hour());
Serial.print(":");
Serial.println(gps.time.minute());
Serial.print("Sidereal: ");
Serial.println(LST_hours);
Serial.print("Moon age: ");
Serial.println(moonAge);
*/
}
}
//smart delay for GPS
static void smartDelay(unsigned long ms){
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
void LST_time(){
//Calculates local sidereal time based on this calculation,
//http://www.stargazing.net/kepler/altaz.html
M = (double) gps.date.month();
Y = (double) gps.date.year();
D = (double) gps.date.day();
MN = (double) gps.time.minute();
H = (double) gps.time.hour();
S = (double) gps.time.second();
A = (double)(Y-2000)*365.242199;
B = (double)(M-1)*30.4368499;
double JDN2000=A+B+(D-1)+gps.time.hour()/24;
double decimal_time = H+(MN/60)+(S/3600) ;
double LST = 100.46 + 0.985647 * JDN2000 + gps.location.lng() + 15*decimal_time;
LST_degrees = (LST-(floor(LST/360)*360));
LST_hours = LST_degrees/15;
}
void setRegistry(byte reg, byte value){
digitalWrite(CS_PIN, LOW);
putByte(reg); // specify register
putByte(value); // send data
digitalWrite(CS_PIN, LOW);
digitalWrite(CS_PIN, HIGH);
}
void putByte(byte data){
byte i = 8;
byte mask;
while (i > 0)
{
mask = 0x01 << (i - 1); // get bitmask
digitalWrite( CLK_PIN, LOW); // tick
if (data & mask) // choose bit
digitalWrite(DIN_PIN, HIGH); // send 1
else
digitalWrite(DIN_PIN, LOW); // send 0
digitalWrite(CLK_PIN, HIGH); // tock
--i; // move to lesser bit
}
}
int ConwayMoon(int cYear,int cMonth,int cDay){
int s;
int yy;
int d;
s = cYear % 100;
s = s % 19;
if (s>9){
s -= 19;
}
s = ((s * 11) % 30) + cMonth + cDay;
if (cMonth<3){
s += 2;
}
s = ((int)floor(s-7.8))%30;
if(s<0){
s = s+30;
}
return s;
}
int drawMoon(int s){
//drawing the moon
switch (s) {
case 0: case 1: case 29:
// New moon
for (int i = 0; i < 8; i++){
setRegistry(i+1,newMoon[i]);
}
break;
case 2: case 3: case 4: case 5: case 6:
// waxing crescent
for (int i = 0; i < 8; i++){
setRegistry(i+1,waxingCrescent[i]);
}
break;
case 7: case 8:
// first quarter
for (int i = 0; i < 8; i++){
setRegistry(i+1,firstQuarter[i]);
}
break;
case 9: case 10: case 11: case 12: case 13:
// waxing gibbous
for (int i = 0; i < 8; i++){
setRegistry(i+1,waxingGibbous[i]);
}
break;
case 14: case 15: case 16:
// full moon
for (int i = 0; i < 8; i++){
setRegistry(i+1,fullMoon[i]);
}
break;
case 17: case 18: case 19: case 20: case 21:
// waning gibbous
for (int i = 0; i < 8; i++){
setRegistry(i+1,waningGibbous[i]);
}
break;
case 22: case 23:
// third quarter
for (int i = 0; i < 8; i++){
setRegistry(i+1,thirdQuarter[i]);
}
break;
case 24: case 25: case 26: case 27: case 28:
// waning crescent
for (int i = 0; i < 8; i++){
setRegistry(i+1,waningCrescent[i]);
}
default:
// empty moon
break;
}
}