Friday, July 27, 2018

It Counts! The Trip Timer Lives

I'm closing in on a functional trip timer. I've got the hardware and software more or less figured out. All that was left to do was write the code to implement a stopwatch like display.

And without further ado, here it is:

/*
 * See:
 *  https://raw.githubusercontent.com/adafruit/Adafruit_ILI9341/master/examples/touchpaint_featherwing/touchpaint_featherwing.ino
 * https://learn.adafruit.com/adafruit-2-4-tft-touch-screen-featherwing/resistive-touch-screen
 */
 

#include <Adafruit_STMPE610.h>
#include <SPI.h>
#include <Wire.h>      // this is needed even tho we aren't using it

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ILI9341.h> // Hardware-specific library
#include <Adafruit_STMPE610.h>

#define STMPE_CS 32
#define TFT_CS   15
#define TFT_DC   33
#define SD_CS    14

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);


long started = millis() / 1000;

void setup(void) {
  Serial.begin(115200);

  delay(10);
  Serial.println("Timer Time!");
  

  if (!ts.begin()) {
    Serial.println("Couldn't start touchscreen controller");
    while (1);
  }
}

void loop(void) {
  long remaining = (millis() / 1000) - started;
  int hours = remaining / (60 * 60);
  remaining = hours == 0 ? remaining : remaining % (hours * 60 * 60);
  int minutes = remaining / 60;
  remaining = minutes == 0 ? remaining : remaining % (60 * minutes);
  int seconds = remaining;

  int fg = textFg(hours, minutes, seconds);
  int bg = textBg(hours, minutes, seconds);
  
  tft.begin();
  tft.setRotation(3);
  tft.fillScreen(fg);
  tft.setCursor(10,(tft.height() / 2) - 30);
  tft.setTextColor(bg);
  tft.setTextSize(7);

  tft.print(hours);
  tft.print(":");
  if(minutes < 10) {
    tft.print("0");
  }
  tft.print(minutes);
  tft.print(":");
  if(seconds < 10) {
    tft.print("0");
  }
  tft.print(seconds);

  delay(750);
}

int textFg(int hours, int minutes, int seconds) {
  int red = minutes/2;
  int green = 61 - minutes;
  int blue = 31;
  return ((red) << 11) | ((green) << 6) | blue;
}

int textBg(int hours, int minutes, int seconds) {
  return ~ textFg(hours, minutes, seconds);
}

And here's the timer doing it's thing:

A few notes on the code:

1. Having the code from my micro:bit prototype was a big help. I'd already figured out a number of math and formatting challenges, and was able to reuse this code.

2. I used this sample as the basis for my code. It told me that I needed the GFX, ILI9341 and SMPE610 libraries, and how to initialize them to properly drive my 2.4 TFT FeatherWing screen. I was eager to avoid the type of confusion I ran into when I mixed up the ESP8266 with the ESP32.

3. You can see I'm deriving the background and text color from the current value of minutes. This is my attempt to make the timer gracefully fade from one color to another throughout an hour. It works, though the color choices need to be smarter.

4. The timer seemed to work great, but when I'd come back after a few hours it had reset itself. The problem was that I was relying on a call to micros() which rolls over every 70 minutes. I switched to calling millis which resets every 50 days.

Up next, I need to take this guy for a road test and see how it does in the car. Then I need to build an enclosure to keep my new baby safe. And then I believe I'll be able to call this complete!

No comments:

Post a Comment