Arduino Timer Test Code

For my second program for the Arduino/TouchShield, I experimented with some simple timer code, which includes a pre-calculated trig lookup table (for placing things rotated like a clock around the central point), a custom vector-font for drawing the text, and monitoring of the touch pad so it changes color when you click, and the little fast dot changes direction — awkwardly — when you double click. I’m just using a plastic straw as a stylus, so it takes a few tries to get the clicks sometimes, as you may notice in the video.

I think next I’ll do something “real” and useful rather than just testing functions — I feel fairly comfortable writing code. I think I’ll do a kitchen timer, and then after that, start experimenting with sensors and motors and LEDs and so on… Definitely fun!

Code follows after the break.

//Defines
#define kMaxTimeBetweenMultiTaps 250
 
//Coordinate lookup table for clock rotation, in seconds,
//center on 0,0 with 64 pix radius
int xClockLookup[] = {0, 7, 13, 20, 26, 32, 38, 43, 48, 52, 55, 58, 61, 63, 64,
64, 64, 63, 61, 58, 55, 52, 48, 43, 38, 32, 26, 20, 13, 7, 0, -7, -13, -20, -26,
-32, -38, -43, -48, -52, -55, -58, -61, -63, -64, -64, -64, -63, -61, -58, -55,
-52, -48, -43, -38, -32, -26, -20, -13, -7};
int yClockLookup[] = {-64, -64, -63, -61, -58, -55, -52, -48, -43, -38, -32,
-26, -20, -13, -7, 0, 7, 13, 20, 26, 32, 38, 43, 48, 52, 55, 58, 61, 63, 64, 64,
64, 63, 61, 58, 55, 52, 48, 43, 38, 32, 26, 20, 13, 7, 0, -7, -13, -20, -26, -32,
-38, -43, -48, -52, -55, -58, -61, -63, -64};
 
//Various global vars (probably some don't have to be)
long timeOfLastTap = 0;
unsigned char tapCount = 0;
 
int inreverse = 0;
 
unsigned long time;
int xlocsec;
int ylocsec;
int xlocmsec;
int ylocmsec;
 
unsigned long oldNum;
unsigned long thisNum;
unsigned long digOne;
unsigned long digTwo;
 
int textcolorR = 255;
int textcolorG = 255;
int textcolorB = 255;
int secballcolorR = 255;
int secballcolorG = 0;
int secballcolorB = 0;
 
void setup()
{
   background(0);
   drawMiddle();
}
 
void loop()
{
  POINT tapPoint;
  drawSeconds();
  if (touch_get_cursor(&tapPoint))
  {
    handleTap(&tapPoint);
  }
}
 
void drawSeconds()
{
  //seconds
  time = (millis() / 1000) % 60;
  xlocsec = xClockLookup[time] + 64;
  ylocsec = yClockLookup[time] + 64;
  stroke(secballcolorR, secballcolorG, secballcolorB);
  fill(secballcolorR, secballcolorG, secballcolorB);
  ellipse(xlocsec, ylocsec, 10, 10);
  //"milliseconds"
  time = (millis() / 17) % 60;
  if (inreverse == 1)
  {
    time = 59 - time;
  }
  xlocmsec = xClockLookup[time] + 64;
  ylocmsec = yClockLookup[time] + 64;
  stroke(255, 255, 0);
  fill(255, 255, 0);
  ellipse(xlocmsec, ylocmsec, 5, 5);
  //Seconds text counter
  thisNum = (millis() / 1000) % 60;
  if (thisNum != oldNum)
  {
    stroke(0);
    drawNum(digOne, 20, 30, 39, 49);
    drawNum(digOne, 20, 30, 40, 50);
    drawNum(digTwo, 20, 30, 69, 49);
    drawNum(digTwo, 20, 30, 70, 50);
 
    digOne = thisNum / 10;
    digTwo = thisNum % 10;
 
    stroke(textcolorR, textcolorG, textcolorB);
    drawNum(digOne, 20, 30, 39, 49);
    drawNum(digOne, 20, 30, 40, 50);
    drawNum(digTwo, 20, 30, 69, 49);
    drawNum(digTwo, 20, 30, 70, 50);
     
    oldNum = thisNum;
  }
  //pause and then erase
  delay(16);
  stroke(0);
  fill(0);
  ellipse(xlocsec, ylocsec, 10, 10);
  ellipse(xlocmsec, ylocmsec, 5, 5);
}
 
void drawMiddle()
{
  int xloc;
  int yloc;
  int xloc2;
  int yloc2;
  stroke(255);
  for (int i=0; i <= 11; i++)
  {
    xloc = (xClockLookup[i * 5] / 2) + 64;
    yloc = (yClockLookup[i * 5] / 2) + 64;
    xloc2 = (xClockLookup[i * 5] * 2 / 3) + 64;
    yloc2 = (yClockLookup[i * 5] * 2 / 3) + 64;
    line(xloc2, yloc2, xloc, yloc);
    stroke(128);
  }
}
 
int drawNum(unsigned long num, int sizex, int sizey, int x, int y)
{
  int x1;
  int x2;
  int x3;
  int y1;
  int y2;
  int y3;
  x1 = x;
  x2 = x + (sizex / 2);
  x3 = x + sizex;
  y1 = y;
  y2 = y + (sizey / 2);
  y3 = y + sizey;
  switch(num)
  {
    case 0:
      line(x1, y1, x3, y1);
      line(x3, y1, x3, y3);
      line(x3, y3, x1, y3);
      line(x1, y3, x1, y1);
      break;
    case 1:
      line(x2, y1, x2, y3);
      break;
    case 2:
      line(x1, y1, x3, y1);
      line(x3, y1, x3, y2);
      line(x3, y2, x1, y3);
      line(x1, y3, x3, y3);
      break;
    case 3:
      line(x1, y1, x3, y1);
      line(x3, y1, x1, y2);
      line(x1, y2, x3, y2);
      line(x3, y2, x1, y3);
      break;
    case 4:
      line(x2, y1, x1, y2);
      line(x1, y2, x3, y2);
      line(x3, y1, x3, y3);
      break;
    case 5:
      line(x3, y1, x1, y1);
      line(x1, y1, x1, y2);
      line(x1, y2, x3, y2);
      line(x3, y2, x1, y3);
      break;
    case 6:
      line(x3, y1, x1, y2);
      line(x1, y2, x1, y3);
      line(x1, y3, x3, y3);
      line(x3, y3, x3, y2);
      line(x3, y2, x1, y2);
      break;
    case 7:
      line(x1, y1, x3, y1);
      line(x3, y1, x1, y3);
      break;
    case 8:
      line(x1, y1, x3, y1);
      line(x3, y1, x3, y3);
      line(x3, y3, x1, y3);
      line(x1, y3, x1, y1);
      line(x1, y2, x3, y2);
      break;
    case 9:
      line(x1, y1, x3, y1);
      line(x3, y1, x3, y2);
      line(x3, y2, x1, y2);
      line(x1, y2, x1, y1);
      line(x3, y2, x1, y3);
      break;
  }  
}
 
//Borrowed in part from code by Josh Freeman
void handleTap(POINT *tapPoint)
{
    long currentTime = millis();
    long timeBetweenLastTwoTaps = currentTime - timeOfLastTap;
 
    // should the tap be considered part of a previous tap sequence?
    if (timeBetweenLastTwoTaps < kMaxTimeBetweenMultiTaps)
    {
        // tap is soon enough after previous tap
        // to continue the current tap sequence
        tapCount++;
         
        // restart the sequence if it's reached the limit
        if (tapCount > 2)
        {
            tapCount = 1;
        }
    }
    else
    {
        // too long since last tap - begin a new tap sequence
        tapCount = 1;
    }
 
    timeOfLastTap = currentTime;
 
    switch (tapCount)
    {
        case 1: // single-tap: change text and ball color
        {
            textcolorR = random(100, 255);
            textcolorG = random(100, 255);
            textcolorB = random(100, 255);
            secballcolorR = random(100, 255);
            secballcolorG = random(100, 255);
            secballcolorB = random(100, 255);
            //force redraw of digit
            oldNum = -1;
        }
        break;
 
        case 2: // double-tap: reverse mini-second rotator
        {
            if (inreverse == 1)
              {
              inreverse = 0;
              }
            else
              {
              inreverse = 1;
              }
        }
        break;
 
        default:
        {
            tapCount = 0;
        }
        break;
    }  
}

6 Comments

  1. Scienkoptic wrote:

    You make it look too easy.
    I’ll take comfort in knowing that I can do a few things you can’t do…. for now.

    Tuesday, May 12, 2009 at 1:21 pm | Permalink
  2. Soroush wrote:

    Shannon, for a tiny device this is impressive! I’m feeling itchy to try this out myself. Maybe also put the PCB together in my uni lab.

    What “real” application do you have in mind?

    Tuesday, May 12, 2009 at 3:19 pm | Permalink
  3. Shannon wrote:

    I’m doing a kitchen timer.

    Tuesday, May 12, 2009 at 3:28 pm | Permalink
  4. CutThroat wrote:

    I have some Arduino chips waiting to get messed with. Neat to see other people messing with ’em too.

    My buddy Jason has made some fancy midi controllers with his that he uses to control the music production in our show.

    Tuesday, May 19, 2009 at 9:58 am | Permalink
  5. Jean wrote:

    Hi, i’m looking for someone who can do arduino codes like you to help me in my project.

    I’m doing a personal tracker using arduino and adxl345. I am able to produce serial values of x, y and z-axis on my serial monitor. Now instead of values, i need to come up with sentences indicating the movement. Do u have any idea?

    Tuesday, November 2, 2010 at 2:02 am | Permalink
  6. Shannon wrote:

    What you’re describing, using the Arduino to convert the x,y,z vectors/locations into sentences (presumably describing them?) would be really easy. I’m not doing Arduino dev work these days but even with my limited experience with the chip I know that what you’re describing would not be a lot of work. I’m sure you’ll have no difficulty finding someone. Assuming you’re willing to pay for the work, just post in one of the various Arduino forums online with your proposal.
    Good luck.

    Tuesday, November 2, 2010 at 4:45 am | Permalink
Wow Shannon, that's really annoying! What is it, 1997 on Geocities? Retroweb is NOT cool!

Post a Comment

Your email is never published nor shared. Required fields are marked *
*
*