#include <stdint.h>
#include <TFTv2.h>
#include <SPI.h>
#include <SD.h>
#include <IRremote.h>
#include <ThreeWire.h>
#include <RtcDS1302.h>
#include "Adafruit_VL53L0X.h"
ThreeWire myWire(32,30,34); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);
Adafruit_VL53L0X lox = Adafruit_VL53L0X();
int RECV_PIN = 19;
char buff1[32];
char buff2[32];
char prevLabel1[3];
char label1[3];
char label2[3];
char label3[3];
char buff[32];
int DELAY_INTERVAL = 200;
IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long oldID = 0;
unsigned long prevID = 0;
unsigned long prevIDTime = 0;
unsigned long oldDistance = 0;
unsigned long prevLevelChangeTime = 0;
unsigned long lastIRDetected = 0;
unsigned long idleTime = 1600;
unsigned long currentID = 0;
unsigned long finalFlag = 0xc9ffffff;
unsigned long doubleFlag = 0xc9e1ffff;
unsigned long doubleFlagTime = 0;
char IDStr[11];
const int maximum = 100;
const int minimum = 5;
int prevMark = 0;
uint16_t measures[20];
int b_h = 1;
int b_t = 0;
int textx = 0, texts = 3;
//File myFile;
int unit_size = 3;
int oldLevel = (int)(maximum - minimum)/unit_size + 2;
int savedLevel = -1;
int sensitivity = 0.2 * 29 * 2;
const int pingPin = 16; // Trigger Pin of Ultrasonic Sensor
const int echoPin = 15; // Echo Pin of Ultrasonic Sensor
const int PIN_SD_CS = 4;
bool drawingButton = false;
bool prompting = false;
unsigned long promptingTime = 0;
unsigned long promptingTimeout = 4000;
unsigned long lastTimeIRDetected = 0;
bool displayingSelection = false;
char buttonLetter[][12] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#"};
int highlightedButton = -1;
int digit1 = -1;
int digit2 = -1;
int digit3 = -1;
int prevDigit1 = -1;
int prevDigit2 = -1;
int prevDigit3 = -1;
unsigned long buttonHighlightedTime = 0;
bool hasHighlightedButton = false;
void drawButton(int bn, unsigned int bc, unsigned int fc){
drawButton(20 + (bn%3) * 80, 80 + ((int)bn/3) * 65, buttonLetter[bn], bc, fc);
}
void drawButton(int x, int y, char *s, unsigned int bc, unsigned int fc){
Tft.fillRectangle(x, y, 40, 40, bc);
Tft.drawString(s, x+7, y+5, 4, fc);
}
void drawButtons(){
Tft.drawString(buff2, textx, 100, texts, BLACK);
for (int i = 0; i < 12; i++){
drawButton(i, WHITE, BLUE);
}
}
void clearButtons(){
for (int i = 0; i < 12; i++){
drawButton(i, BLACK, BLACK);
}
}
void inputSelected(){
int level = 0;
//this is going to level selected
if (digit1 != 10){
//the first digit is not zero
level = level + (digit1 + 1) * 100;
}
if (digit2 != 10){
//the first digit is not zero
level = level + (digit2 + 1) * 10;
}
if (digit3 != 10){
//the first digit is not zero
level = level + (digit3 + 1);
}
if (level == 0){
return;
}
clearButtons();
levelSelected(level);
digit1 = -1;
digit2 = -1;
digit3 = -1;
}
void levelSelected(int level){
char t[32];
if (level == 0){
return;
}
String s = String("Going to level ") + String(level);
s.toCharArray(t, s.length() + 1);
//Tft.fillScreen(MIN_X, MAX_X, MIN_Y, MAX_Y, GREEN);
//clearButtons();
Tft.drawString(t,5,155,2, WHITE);
delay(2000);
//Tft.fillScreen();
Tft.drawString(t,5,155,2, BLACK);
//drawButtons();
saveLevelForID(IDStr, level);
strcpy(IDStr, "Default");
prevLevelChangeTime = millis();
}
void clearScreen(){
clearButtons();
digit1 = -1;
digit2 = -1;
digit3 = -1;
updateInputBuffer();
Tft.drawString(buff2, textx, 100, texts, BLACK);
Tft.drawString(label1, 10, MAX_Y-30, 2, BLACK);
Tft.drawString(label2, MAX_X/2, MAX_Y-30, 2, BLACK);
Tft.drawString(label3, MAX_X-20, MAX_Y-30, 2, BLACK);
Tft.drawVerticalLine(prevMark, MAX_Y - 15, 15, BLACK);
for(int i = 0; i < 20; i++){
Tft.drawHorizontalLine(MAX_X - 15, measures[i], 15, BLACK);
}
}
int cmToLevel(int cm){
int level = (int)(cm - minimum)/unit_size + 1;
return level;
}
#define countof(a) (sizeof(a) / sizeof(a[0]))
void saveIDForTracing(char* ID){
RtcDateTime dt = Rtc.GetDateTime();
char dateString[20];
snprintf_P(dateString,
countof(dateString),
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
dt.Month(),
dt.Day(),
dt.Year(),
dt.Hour(),
dt.Minute(),
dt.Second() );
if (strlen(ID) != 8){
return;
}
char* fn = "tracing.csv";
File tracing = SD.open(fn, FILE_WRITE);
if (tracing) {
Serial.println("Writing to file: ");
Serial.println(fn);
tracing.print(dateString);
tracing.print(",");
tracing.println(ID);
Serial.print(dateString);
Serial.print(",");
Serial.println(ID);
// close the file:
tracing.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.print("error opening tracing file: ");
Serial.println(fn);
}
}
void displayTracingData(){
File tracing = SD.open("tracing.csv");
if (tracing) {
Serial.println("tracing.csv");
// read from the file until there's nothing else in it:
while (tracing.available()) {
Serial.write(tracing.read());
}
// close the file:
tracing.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening tracing.csv");
}
}
void saveLevelForID(char* ID, int level){
if (strlen(ID) != 8){
Serial.println("Error: ID size is wrong.");
Serial.println(ID);
return;
}
char fn[13];
strcpy(fn, ID);
strcat(fn, ".txt");
if (SD.exists(fn)){
SD.remove(fn);
}
File saveLevel = SD.open(fn, FILE_WRITE);
if (saveLevel) {
Serial.print("Writing to file: ");
Serial.print(fn);
saveLevel.println(level);
// close the file:
saveLevel.close();
Serial.println("done.");
} else {
// if the file didn't open, print an error:
Serial.print("error opening file: ");
Serial.println(fn);
}
}
int getSavedLevel(char* ID){
char fn[13];
String level = "";
strcpy(fn, ID);
strcat(fn, ".txt");
File myFile = SD.open(fn);
if (myFile) {
Serial.print("reading from file: ");
Serial.println(fn);
// read from the file until there's nothing else in it:
while (myFile.available()) {
char c = myFile.read();
if( c == '\n'){
break;
}
level = level + c;
}
// close the file:
myFile.close();
return level.toInt();
} else {
// if the file didn't open, print an error:
Serial.print("error opening file: ");
Serial.println(fn);
return -1;
}
}
void updateInputBuffer(){
if (digit1 == -1){
if (prevDigit1 == -1){
//do nothing
}
else {
//to erase the old one
//Tft.drawString(buttonLetter[prevDigit1], 80, 5, 4, BLACK);
drawButton(80, 5, buttonLetter[prevDigit1], BLACK, BLACK);
prevDigit1 = -1;
}
}
else {
if (prevDigit1 != -1 & prevDigit1 != digit1){
//erase the old one
//Tft.drawString(buttonLetter[prevDigit1], 80, 5, 4, BLACK);
drawButton(80, 5, buttonLetter[prevDigit1], BLACK, BLACK);
//draw the new one
//Tft.drawString(buttonLetter[digit1], 80, 5, 4, BLUE);
drawButton(80, 5, buttonLetter[digit1], WHITE, BLUE);
//remember the new one.
prevDigit1 = digit1;
}
else if (prevDigit1 != digit1){
//draw the new one
drawButton(80, 5, buttonLetter[digit1], WHITE, BLUE);
//remember the new one.
prevDigit1 = digit1;
}
}
if (digit2 == -1){
if (prevDigit2 == -1){
//do nothing
}
else {
//to erase the old one
//Tft.drawString(buttonLetter[prevDigit2], 110, 5, 4, BLACK);
drawButton(110, 5, buttonLetter[prevDigit2], BLACK, BLACK);
prevDigit2 = -1;
}
}
else {
if (prevDigit2 != -1 & prevDigit2 != digit2){
//erase the old one
//Tft.drawString(buttonLetter[prevDigit2], 110, 5, 4, BLACK);
drawButton(110, 5, buttonLetter[prevDigit2], BLACK, BLACK);
//draw the new one
//Tft.drawString(buttonLetter[digit2], 110, 5, 4, BLUE);
drawButton(110, 5, buttonLetter[digit2], WHITE, BLUE);
//remember the new one.
prevDigit2 = digit2;
}
else if (prevDigit2 != digit2) {
//draw the new one
//Tft.drawString(buttonLetter[digit2], 110, 5, 4, BLUE);
drawButton(110, 5, buttonLetter[digit2], WHITE, BLUE);
//remember the new one.
prevDigit2 = digit2;
}
}
if (digit3 == -1){
if (prevDigit3 == -1){
//do nothing
}
else {
//to erase the old one
//Tft.drawString(buttonLetter[prevDigit3], 140, 5, 4, BLACK);
drawButton(140, 5, buttonLetter[prevDigit3], BLACK, BLACK);
prevDigit3 = -1;
}
}
else {
if (prevDigit3 != -1 & prevDigit3 != digit3){
//erase the old one
//Tft.drawString(buttonLetter[prevDigit3], 140, 5, 4, BLACK);
drawButton(140, 5, buttonLetter[prevDigit3], BLACK, BLACK);
//draw the new one
//Tft.drawString(buttonLetter[digit3], 140, 5, 4, BLUE);
drawButton(140, 5, buttonLetter[digit3], WHITE, BLUE);
//remember the new one.
prevDigit3 = digit3;
}
else if (prevDigit3 != digit3){
//draw the new one
//Tft.drawString(buttonLetter[digit3], 140, 5, 4, BLUE);
drawButton(140, 5, buttonLetter[digit3], WHITE, BLUE);
//remember the new one.
prevDigit3 = digit3;
}
}
}
void clearPrompting(){
Tft.drawString(buff1, textx, 100, texts, BLACK);
Tft.drawString(buff2, textx, 150, texts, BLACK);
}
void setup(){
buff[0] = 0;
strcpy(IDStr, "Default");
Serial.begin(9600);
pinMode(pingPin, OUTPUT);
pinMode(echoPin, INPUT);
strcpy(label1, "");
strcpy(label2, "");
strcpy(label3, "");
irrecv.enableIRIn(); // Start the receiver
for(int i = 0; i < 20; i++){
measures[i] = 0;
}
Serial.println("Adafruit VL53L0X test");
if (!lox.begin()) {
Serial.println(F("Failed to boot VL53L0X"));
while(1);
}
pinMode(PIN_SD_CS,OUTPUT);
digitalWrite(PIN_SD_CS,HIGH);
TFT_BL_ON; // turn on the background light
Tft.TFTinit();
Sd2Card card;
card.init(SPI_FULL_SPEED, PIN_SD_CS);
if(!SD.begin(PIN_SD_CS))
{
Serial.println("failed!");
while(1); // init fail, die here
}
Serial.println("SD OK!");
Rtc.Begin();
//RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__);
if (!Rtc.IsDateTimeValid())
{
// Common Causes:
// 1) first time you ran and the device wasn't running yet
// 2) the battery on the device is low or even missing
Serial.println("RTC lost confidence in the DateTime!");
// Rtc.SetDateTime(compiled);
}
if (!Rtc.GetIsRunning())
{
Serial.println("RTC was not actively running, starting now");
Rtc.SetIsRunning(true);
}
}
void loop()
{
long duration, inches, cm, mark;
int level;
int kx, ky;
bool hasIRValue = false;
unsigned long current = millis();
if (prompting & promptingTime + promptingTimeout < current){
Tft.drawString(buff1, textx, 100, texts, BLACK);
Tft.drawString(buff2, textx, 150, texts, BLACK);
prompting = false;
}
//Hover over a button has timed out for selection.
if (highlightedButton != -1 & buttonHighlightedTime + idleTime < current){
buttonHighlightedTime = current;
drawButton(highlightedButton, WHITE, BLUE);
//delay(1000);
//button is selected
if (highlightedButton == 9){
//Erase input buffer
digit1 = -1;
digit2 = -1;
digit3 = -1;
}
else if (highlightedButton == 11){
inputSelected();
buttonHighlightedTime = millis();
highlightedButton = -1;
//drawButtons();
}
else {
digit1 = digit2;
digit2 = digit3;
digit3 = highlightedButton;
}
highlightedButton = -1;
}
//Update input buffer display
updateInputBuffer();
// Check IR input
if (irrecv.decode(&results)) {
if (results.value >= 0xC9000000 & results.value <= 0xC9FFFFFF ){
lastTimeIRDetected = millis();
Serial.print(results.value, HEX);
Serial.print(" ");
Serial.println(results.value, BIN);
String o = String(results.value, HEX);
//this is final flag
if (results.value == finalFlag){
Serial.println("Handling Final Flag.");
inputSelected();
buttonHighlightedTime = millis();
highlightedButton = -1;
delay(100);
irrecv.resume(); // Receive the next value}
return;
}
if (results.value == doubleFlag){
Serial.println("Handling double Flag.");
doubleFlagTime = millis();
if (prompting){
clearPrompting();
}
prevID = 0;
irrecv.resume(); // Receive the next value}
return;
}
if ((results.value > 0xc9000000 & results.value < 0xc9FFFFFF) & !(results.value > 0xc9e10000 & results.value < 0xc9e1FFFF)){
//this is an ID code
if (results.value == prevID & prevIDTime + 5000 > millis()){
RtcDateTime dt = Rtc.GetDateTime();
char dateString[20];
snprintf_P(dateString,
countof(dateString),
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
dt.Month(),
dt.Day(),
dt.Year(),
dt.Hour(),
dt.Minute(),
dt.Second() );
Serial.print("Recieved second ID at ");
Serial.println(dateString);
Tft.drawString(buff1, textx, 100, texts, BLACK);
Tft.drawString(buff2, textx, 150, texts, BLACK);
levelSelected(savedLevel);
prompting = false;
prevID = 0;
}
else {
RtcDateTime dt = Rtc.GetDateTime();
char dateString[20];
snprintf_P(dateString,
countof(dateString),
PSTR("%02u/%02u/%04u %02u:%02u:%02u"),
dt.Month(),
dt.Day(),
dt.Year(),
dt.Hour(),
dt.Minute(),
dt.Second() );
Serial.print("Recieved ID at ");
Serial.println(dateString);
currentID = results.value;
String s = String(results.value, HEX);
s.toCharArray(IDStr, 11);
saveIDForTracing(IDStr);
if (doubleFlagTime + 3000 < millis()){
savedLevel = getSavedLevel(IDStr);
}
else {
savedLevel = -1;
}
Serial.print("Current ID: ");
Serial.println(IDStr);
if (savedLevel != -1){
//promptUser(savedLevel);
clearScreen();
strcpy(buff1,"Press Button");
strcpy(buff2, "To Go To Level:");
char temp[11];
String s = String(savedLevel);
s.toCharArray(temp, 11);
strcat(buff2, temp);
textx = 5;
texts = 2;
prompting = true;
promptingTime = millis();
clearButtons();
Tft.drawString(buff1, textx, 100, texts, WHITE);
Tft.drawString(buff2, textx, 150, texts, WHITE);
}
}
prevIDTime = millis();
prevID = results.value;
}
if (results.value > 0xc9e10000 & results.value < 0xc9e1FFFF){
if (prompting){
clearScreen();
prompting = false;
drawButtons();
}
if (!drawingButton){
drawButtons();
drawingButton = true;
}
lastIRDetected = millis();
unsigned long encoded = results.value - 0xc9e10000;
unsigned long y = (unsigned long) encoded / 256;
unsigned long x = encoded % 256;
/*
Serial.print("x = ");
Serial.print(x);
Serial.print(", y = ");
Serial.print(y);
Serial.println();
*/
cm = map(x, 0, 255, 0, 80);
duration = map(x, 0, 255, 0, 80 * 29 * 2);
hasIRValue = true;
if (x < 115){
x = 115;
}
else if (x > 175){
x = 175;
}
x = 175 - x;
if (y < 95){
y = 95;
}
else if (y > 155){
y = 155;
}
y = y - 95;
ky = map(x, 0, 60, 0, 3);
kx = map(y, 0, 60, 0, 2);
int bi = ky*3 + kx;
Serial.print("kx = ");
Serial.print(kx);
Serial.print(" kY = ");
Serial.print(ky);
Serial.print(" bi = ");
Serial.println(bi);
//
if (highlightedButton != -1 & highlightedButton != bi){
buttonHighlightedTime = millis();
drawButton(highlightedButton, WHITE, BLUE);
drawButton(bi, GREEN, YELLOW);
highlightedButton = bi;
}
else if (highlightedButton == -1) {
drawButton(bi, GREEN, YELLOW);
buttonHighlightedTime = millis();
highlightedButton = bi;
}
delay(10);
irrecv.resume(); // Receive the next value}
}
/*
else {
if (!drawingButton){
o.toCharArray(buff, o.length() + 1);
buff[o.length()+1] = 0;
Tft.drawString(buff,60,220,3, WHITE);
}
delay(200);
irrecv.resume(); // Receive the next value}
}
*/
}
irrecv.resume(); // Receive the next value}
}
if (!prompting & drawingButton & lastTimeIRDetected + idleTime < millis()){
drawingButton = false;
clearScreen();
}
if (!(drawingButton | prompting)) {
VL53L0X_RangingMeasurementData_t measure;
// Serial.print("Reading a measurement... ");
lox.rangingTest(&measure, false); // pass in 'true' to get debug data printout!
if (measure.RangeStatus != 4) { // phase failures have incorrect data
//Serial.print("Distance (mm): "); Serial.println(measure.RangeMilliMeter);
} else {
// Serial.println(" out of range ");
}
// irrecv.resume(); // Receive the next value}
measures[b_t] = map(measure.RangeMilliMeter, 0, 400, MIN_Y, MAX_Y);
Tft.drawHorizontalLine(MAX_X - 15, measures[b_t], 15, RED);
Tft.drawHorizontalLine(MAX_X - 15, measures[b_h], 15, BLACK);
b_t++;
b_h++;
if (b_t == 15){
b_t = 0;
}
if (b_h == 15){
b_h = 0;
}
cm = measure.RangeMilliMeter/10;
duration = measure.RangeMilliMeter * 29 * 2 / 10;
}
if (drawingButton | prompting){
return;
}
if (cm <= maximum & cm >= minimum){
level = cmToLevel(cm);
String d = String(level);
if (oldLevel == level){
unsigned long currentTime = millis();
if (prevLevelChangeTime + idleTime < currentTime & level < 48){
Tft.drawString(buff2, textx, 100, texts, BLACK);
prevLevelChangeTime = currentTime;
levelSelected(level);
}
// Tft.drawString(buff2, textx, 100, texts, WHITE);
mark = map(duration, ((level-1)*unit_size + minimum)*2*29, ((level-1)*unit_size + minimum + unit_size)*2*29, MIN_X, MAX_X);
//
if (abs(mark - prevMark) > sensitivity){
Tft.drawVerticalLine(prevMark, MAX_Y - 15, 15, BLACK);
//
Tft.drawVerticalLine(mark, MAX_Y - 15, 15, GREEN);
//
prevMark = mark;
delay(10);
}
return;
}
else {
prevLevelChangeTime = millis();
oldDistance = cm;
oldLevel = level;
}
Tft.drawString(buff2, textx, 100, texts, BLACK);
Tft.drawString(label1, 10, MAX_Y-30, 2, BLACK);
Tft.drawString(label2, MAX_X/2, MAX_Y-30, 2, BLACK);
Tft.drawString(label3, MAX_X-20, MAX_Y-30, 2, BLACK);
d.toCharArray(buff2, d.length() + 1);
strcpy(label2, buff2);
Tft.drawString(label2, MAX_X/2, MAX_Y-30, 2, WHITE);
d = String(level+1);
d.toCharArray(label3, d.length() + 1);
Tft.drawString(label3, MAX_X-20, MAX_Y-30, 2, WHITE);
d = String(level-1);
d.toCharArray(label1, d.length() + 1);
Tft.drawString(label1, 10, MAX_Y-30, 2, WHITE);
textx = MAX_X/2 - 60;
texts = 18;
if (strlen(buff2) == 2){
textx = textx - 50;
}
}
else if (lastIRDetected + idleTime < millis() & strcmp(buff2, "Not Detected") != 0){
Tft.drawString(buff2, textx, 100, texts, BLACK);
Tft.drawString(label1, 10, MAX_Y-30, 2, BLACK);
Tft.drawString(label2, MAX_X/2, MAX_Y-30, 2, BLACK);
Tft.drawString(label3, MAX_X-20, MAX_Y-30, 2, BLACK);
strcpy(buff2, "Not Detected");
textx = 5;
cm = 101;
level = 48;
texts = 3;
}
mark = map(duration, ((level-1)*unit_size + minimum)*2*29, ((level-1)*unit_size + minimum + unit_size)*2*29, MIN_X, MAX_X);
Tft.drawVerticalLine(prevMark, MAX_Y - 15, 15, BLACK);
Tft.drawVerticalLine(mark, MAX_Y - 15, 15, GREEN);
prevMark = mark;
oldID = results.value;
Tft.drawString(buff, 60, 220, 3, WHITE);
if (!drawingButton){
Tft.drawString(buff2, textx, 100, texts, WHITE);
}
Tft.drawHorizontalLine(MIN_X, MAX_Y, MAX_X, RED);
Tft.drawString(buff2, textx, 100, texts, WHITE);
delay(100);
}
Comments