#include <Arduino.h>
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"
#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
Adafruit_MPU6050 mpu;
#define TFT_DC 27
#define TFT_CS 5
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
bool timer_button_state = 0;
const int timer_button = 32;
bool display_button_state = 0;
const int display_button = 35;
volatile unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
unsigned long interval = (65 * 1000); // This is the interval for the timer
bool timer_up = 0; // This variable holds when the time is up
sensors_event_t event;
bool timer(unsigned long fn_interval, bool fn_button); // This is the function for the timer
void color(unsigned long currentTime, unsigned long totalTime); // This is the function for the time dependent color-changing LED
void ISR_button_timer(); // This holds the interupt service routine for button that has the attach interupt function
void ISR_button_display();
void temp_display_output(int fn_time_remaining);
void setup()
{
// Start the serial moniter
Serial.begin(115200);
Serial.println("start");
attachInterrupt(digitalPinToInterrupt(timer_button), ISR_button_timer, CHANGE); // Attach interupt to the button
attachInterrupt(digitalPinToInterrupt(display_button), ISR_button_display, CHANGE);
pinMode(19, INPUT);
tft.begin();
tft.setCursor(26, 120);
tft.setTextColor(ILI9341_WHITE);
tft.setTextSize(3);
tft.println("Timer Cube v.1");
while (!mpu.begin())
{
Serial.println("MPU6050 not connected!");
delay(1000);
}
mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_2000_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
}
void loop()
{
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
if (g.gyro.x > 0)
{
Serial.println("rotation");
timer_button_state = HIGH;
}
if (digitalRead(19) == HIGH)
{
timer_up = timer(interval, timer_button_state); // Set the timer counting to x_interval, and have it resettable by the button (var: y)
}
if (timer_up == 1) // If the timer is done, then display it in the serial moniter
{
Serial.println("Time's up");
}
}
bool timer(unsigned long fn_interval, bool fn_button)
{
/*
This function is a standalone timer
Record current time as the startup time
Current time - startup time = remaining time on the timer
If the button is pressed, then reset the "startup time" to the "current time"
Check whether the time remaining is more than x interval time
If so then return true
else keep checking everything
*/
static unsigned long fn_startup_time = millis(); // This records the first millis, then it'll remember that first value
if (fn_button == HIGH) // If the button is pressed then reset the variable "fn_startup_time" to the current time
// to reset the timer
{
fn_startup_time = millis();
Serial.println("reset");
timer_button_state = LOW;
}
unsigned long time_elapsed = (millis() - fn_startup_time);
color(time_elapsed, fn_interval);
// Serial.println("Time Left:");
// Serial.println(time_elapsed);
char time_display[40]; // Char array to hold characters for sprintf
/*
Only refresh the display when the user requests, trigger: pin35 button
If display_button (35) is pressed
Find the remaining time, whole interval - time elapsed = time remaining
Find the minutes and seconds of the time remaining (diving by 60000 b/c millis returns on milliseconds 1000ms = 1s)
Print this information on the screen and serial moniter
*not working if statement
reset the display button state (software toggle)
*/
if (display_button_state == HIGH)
{
int fn_time_remaining = fn_interval - time_elapsed;
int fn_min = fn_time_remaining / (60000);
int fn_sec = fn_time_remaining % (60000);
sprintf(time_display, "%02.2d : %02.2d", fn_min, (fn_sec / 1000));
Serial.print(" ");
// Serial.println(fn_time_remaining);
Serial.println(time_display);
tft.fillScreen(0);
tft.setCursor(50, 140);
tft.println(time_display);
static int timeout = fn_time_remaining + 2000;
if (fn_time_remaining >= timeout) // Doesn't work yet
{
tft.fillScreen(0);
}
display_button_state = LOW;
}
if (time_elapsed >= fn_interval)
{
return true;
}
else
{
return false;
}
}
void color(unsigned long fn_time_elapsed, unsigned long fn_total_time)
{
/*
color:
This function is a time dependent color-changing LED
It starts by taking both the remaining time of the function and the interval of the timer
Then divides it by 3 (to support 3 changes to colors)
The first stage is green -> (white) purple -> Blue
Each color's if statement:
check if it's in the correct time frame for the color
if it is, then map the remaining time to a value from 0-1028(max of led) (eg. 1/2 time left in time frame, color = 512 (1/2 brightness))
while decreasing the color of the previous time frame
change the LED to the corresponding color
-> purple (differs by changing both Red and Blue colors to a max of 512 (instead of 1028))
*/
unsigned long total_time_div_3 = (fn_total_time / ((unsigned long)3));
// Serial.println(fn_time_elapsed);
// Green
if (fn_time_elapsed < (total_time_div_3) && fn_time_elapsed >= 0) // Check if it's in the correct time frame
{
unsigned long time_remaining_mapped_1 = map(fn_time_elapsed, 0, total_time_div_3, 0, 1028); // Map the remaining time to a brightness of the LED
// map(value, fromLow, fromHigh, toLow, toHigh)
analogWrite(25, time_remaining_mapped_1); // Change the LED accordingly
// Serial.print("G:");
// Serial.println(time_remaining_mapped_1);
}
//-> purple
if (fn_time_elapsed < (total_time_div_3 * 2) && fn_time_elapsed >= (total_time_div_3)) // Check if it's in the correct time frame
{
unsigned long time_remaining_mapped_2 = map(fn_time_elapsed, (total_time_div_3), (total_time_div_3 * 2), 0, 512); // Map the remaining time to a (1/2) brightness of the LED
unsigned long green_temp = (1028 - (time_remaining_mapped_2 * 3)); // Reduce the Green LED's 3x faster then the Red, Blue LED's are increasing
if (green_temp <= 1028) // To avoid spikes in color, if it's over 1028 then just turn off the led
{
analogWrite(25, 1028 - (time_remaining_mapped_2 * 3));
// Serial.print("G:");
// Serial.print(1028 - (time_remaining_mapped_2 * 3));
}
else
{
analogWrite(25, 0);
}
analogWrite(33, time_remaining_mapped_2);
// Serial.print(" R:");
// Serial.print(time_remaining_mapped_2);
analogWrite(26, time_remaining_mapped_2);
// Serial.print(" B:");
// Serial.println(time_remaining_mapped_2);
}
//-> blue
if (fn_time_elapsed < (total_time_div_3 * 3) && fn_time_elapsed >= (total_time_div_3 * 2)) // Check if it's in the correct time frame
{
unsigned long time_remaining_mapped_3 = map(fn_time_elapsed, (total_time_div_3 * 2), (total_time_div_3 * 3), 0, 1028); // Map the remaining time to a brightness of the LED
// analogWrite(25, 1028-(time_remaining_mapped_3));
analogWrite(25, 0); // Keep the green turned off
// Serial.print("G:");
// Serial.print("0");
// //Serial.print(1028-(time_remaining_mapped_3));
analogWrite(33, 1028 - time_remaining_mapped_3); // Reduce the red proportional to the time remaining
// Serial.print(" R:");
// Serial.print(1028 - (time_remaining_mapped_3));
analogWrite(26, 512 + (time_remaining_mapped_3 / 1.5)); // increase the blue 0.5x slower than the other colors
// Serial.print(" B:");
// Serial.println(512 + (time_remaining_mapped_3 / 1.5));
}
// Green -> Purple -> Blue
// analogWrite(33, 0); //Red
// analogWrite(25, 0); //Green
// analogWrite(26, 0); //Blue
}
void ISR_button_timer()
{
// Toggle switch, whenever it changes, it'll go to the opposite state
// Check for debounce
if ((millis() - lastDebounceTime) > debounceDelay)
{
if (timer_button_state == HIGH)
{
timer_button_state = LOW;
}
else
{
timer_button_state = HIGH;
}
}
lastDebounceTime = millis();
}
void ISR_button_display()
{
// Toggle switch, whenever it changes, it'll go to the opposite state
// Check for debounce
if ((millis() - lastDebounceTime) > debounceDelay)
{
if (display_button_state == LOW)
{
display_button_state = HIGH;
}
else
{
display_button_state = LOW;
}
}
lastDebounceTime = millis();
}