Skip to content

Instantly share code, notes, and snippets.

@jasongao97
Created November 3, 2021 06:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jasongao97/a62ca38fb93f0e5152428d2f3c51e19e to your computer and use it in GitHub Desktop.
Save jasongao97/a62ca38fb93f0e5152428d2f3c51e19e to your computer and use it in GitHub Desktop.
/*
'Time Globe' - A lamp clock that shows time by the angle of its light
Midterm for 'Time' by Jason Gao
10/25/2021
*/
#include <Servo.h>
#include <Adafruit_NeoPixel.h>
#include <IRremote.h>
// PINS
#define PIN_SPIN_DIR 0
#define PIN_SPIN_STEP 1
#define PIN_SPIN_RST 2
#define PIN_IR 3
#define PIN_SPIN_M2 4
#define PIN_SPIN_M1 5
#define PIN_SPIN_M0 6
#define PIN_TILT 9
#define PIN_LED 10
#define NUM_OF_MODE 5
#define NUM_OF_LED 13
#define STEP_PER_REVOLUTION 6400
// The step pin stay HIGH for 2 milliseconds
// according to https://www.ti.com/lit/ds/symlink/drv8825.pdf
#define STEP_LOW_DURATION 2
// IR protocol(s)
#define DECODE_NEC
Servo tilt;
Adafruit_NeoPixel pixels(NUM_OF_LED, PIN_LED, NEO_GRBW + NEO_KHZ800);
// https://en.wikipedia.org/wiki/Axial_tilt
// Earth (real) / Earth (present) / Venus / Jupiter / Neptune
const unsigned int milPerStep[NUM_OF_MODE] = {13500, 4, 8, 1, 2};
const unsigned int maxTilt[NUM_OF_MODE] = {66, 66, 7, 9, 80};
const bool rotateDir[NUM_OF_MODE] = {HIGH, HIGH, LOW, HIGH, HIGH};
const uint32_t oneColor[NUM_OF_MODE] = {0x01000000, 0xaa000000, 0x00d1bda9, 0x00a35f31, 0x001757cc};
byte mode = 0;
unsigned long lastMoment = 0;
byte currentStep = 0;
bool currentDir = rotateDir[mode];
uint32_t currentColor = oneColor[mode];
void setup() {
Serial.begin(9600);
Serial.println("Hello Planetime");
// declare pins as output
pinMode(PIN_SPIN_DIR, OUTPUT);
pinMode(PIN_SPIN_STEP, OUTPUT);
pinMode(PIN_SPIN_RST, OUTPUT);
pinMode(PIN_SPIN_M0, OUTPUT);
pinMode(PIN_SPIN_M1, OUTPUT);
pinMode(PIN_SPIN_M2, OUTPUT);
digitalWrite(PIN_SPIN_M0, HIGH);
digitalWrite(PIN_SPIN_M1, HIGH);
digitalWrite(PIN_SPIN_M2, HIGH);
digitalWrite(PIN_SPIN_RST, HIGH);
tilt.attach(PIN_TILT);
// init neopixels
pixels.begin();
for (int i = 0; i < NUM_OF_LED; i++) {
pixels.setPixelColor(i, oneColor[mode]);
}
pixels.show();
IrReceiver.begin(PIN_IR);
}
void loop() {
decodeCommand();
spin();
updateAttr();
}
/**
Decode IR command and update attributes
*/
void decodeCommand() {
if (IrReceiver.decode()) {
IrReceiver.printIRResultShort(&Serial);
IrReceiver.resume();
if (IrReceiver.decodedIRData.command == 0x45) {
// 1
mode = 0;
} else if (IrReceiver.decodedIRData.command == 0x46) {
// 2
mode = 1;
} else if (IrReceiver.decodedIRData.command == 0x47) {
// 3
mode = 2;
} else if (IrReceiver.decodedIRData.command == 0x44) {
// 4
mode = 3;
}
}
}
/**
Update Color and Direction
*/
void updateAttr() {
if (oneColor[mode] != currentColor) {
currentColor = oneColor[mode];
for (int i = 0; i < NUM_OF_LED; i++) {
pixels.setPixelColor(i, oneColor[mode]);
}
pixels.show();
}
if (rotateDir[mode] != currentDir) {
digitalWrite(PIN_SPIN_DIR, rotateDir[mode]);
currentDir = rotateDir[mode];
}
}
/**
Spin the light and adjust tilt
*/
void spin() {
unsigned long present = millis();
if (present - lastMoment > milPerStep[mode]) {
// one step
digitalWrite(PIN_SPIN_STEP, HIGH);
delayMicroseconds(STEP_LOW_DURATION);
digitalWrite(PIN_SPIN_STEP, LOW);
// adjust the tilt
int angle = sin(double(currentStep) / STEP_PER_REVOLUTION * 2 * PI) * maxTilt[mode] * 2 - maxTilt[mode] + 1520;
tilt.writeMicroseconds(angle);
// record the step
currentStep += 1;
if (currentStep >= STEP_PER_REVOLUTION) currentStep = 0;
lastMoment = present;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment