makernestOrigins · all chapters

Origins · Chapter 06 · Count

The Witness

Count what nobody was watching.

Sketch 06 The Witness

Copy it, open File, New Sketch, select everything in the new window and paste over it. Check Tools, Board says Arduino Uno and Tools, Port shows your board, then press Upload.

Download .ino
// 06 The Witness
// The Maker's Book of Origins, chapter 06. Upload it, then turn back to the book.
// makernest.com/origins/06
// MakerNest Origins is a brand of Innointel Global Private Limited.

#include <MakerNestOrigins.h>

// ---- the cold rule, with its gap (chapter 04)
bool coldNow() {
  static bool alarm = false;
  if (machine.settings.coldLine == NOT_SET) return false;      // no line chosen yet: no opinion
  int start = machine.settings.coldLine;
  int stop = (machine.settings.stopAt == NOT_SET) ? start : machine.settings.stopAt;
  float t = machine.watchedTemperature();                      // sensor A, or B if you chose B (chapter 05)
  if (!alarm && t < start) alarm = true;                       // below START: it starts
  if (alarm && t >= stop) alarm = false;                       // back up to STOP AT: it stops
  return alarm;
}

// ---- two places, one gap (chapter 05)
bool apartNow() {
  if (machine.settings.apartBy == 0) return false;             // no gap chosen yet
  float gap = machine.settings.apartBy / 2.0;                  // stored in half degrees
  return fabs(machine.temperatureA() - machine.temperatureB()) > gap;
}

// ---- what it does about it (chapters 02 and 03)
void showIt(bool cold, bool apart) {
  uint8_t w = machine.settings.whenCold;
  if (apart) {                                                 // apart: orange, and the buzzer
    machine.ring(ORANGE);
    machine.buzzerBeep(true);
    return;
  }
  if (cold && (w == WHEN_RING || w == WHEN_BOTH)) machine.ring(RED); else machine.ringNormal();
  if (w == WHEN_ALWAYS) machine.buzzer(true);                  // always on: it has stopped asking
  else { machine.buzzer(false); machine.buzzerBeep(cold && (w == WHEN_BUZZER || w == WHEN_BOTH)); }
}

void setup() {
  machine.begin(6, "06|THE|WITNESS");
  machine.homeShows(SHOW_A | SHOW_B | SHOW_COUNT);
  machine.useScreen(SCR_SETTLE);
  machine.useScreen(SCR_KEEP_COUNT);
  machine.useScreen(SCR_APART_BY);
  machine.useScreen(SCR_WATCHES);
  machine.useScreen(SCR_COLD_LINE);
  machine.useScreen(SCR_STOP_AT);
  machine.useScreen(SCR_NORMAL_COLOUR);
  machine.useScreen(SCR_WHEN_COLD);
  machine.useScreen(SCR_TEST);
}

void loop() {
  machine.update();
  bool cold = coldNow();
  bool apart = apartNow();
  showIt(cold, apart);
  // The count happens inside update(): every time the door opens, after SETTLE seconds of ignoring the switch.
}

Your settings and your notebook stay saved on the board when you upload.

Wiring

Red is power, black is the way back, and every signal has its own colour. On the shield, black goes to G, red to V, the signal to S. Every time.

New this chapter

MDOOR SWITCHUNDER THE BASE1 M LEADROW 8GVSTHE SHIELD2345678910111213A4A5USEDTODAY

The whole shield, by the end of the book

GVSROW 2SENSOR AROW 3DIALROW 4DIALROW 5DIALROW 6BUZZERROW 7SENSOR BROW 8DOOR SWITCHROW 9SWITCH BOARDROW 11LIGHT RINGA4DISPLAYA5DISPLAYPOWER 3V3DISPLAY

On the bench: A push button that counts, and a second one that undoes

A button doesn't close cleanly. For a few thousandths of a second it bounces, and a fast board sees several presses. That is the Witness's double count, on a breadboard.

You need

On the breadboard

TOPBOTTOM12 S12 G10 S10 G1234567891011121314151617

Build it

  1. Put button one across the middle gap, its legs in columns 3 and 5. Push it in until it clicks flat.
  2. Put button two across the gap, its legs in columns 10 and 12.
  3. Button one: row 12 S to column 3 top, row 12 G to column 5 bottom. Always diagonally opposite corners.
  4. Button two: row 10 S to column 10 top, row 10 G to column 12 bottom.
  5. Upload bench sketch 06 and open the Serial Monitor.
Download .ino
// MakerNest Origins · bench 06 · a push button that counts, and a second one that undoes
// Button one on row 12 adds one. Button two on row 10 takes one away.
// No resistors: the board's own pull-up keeps each pin HIGH until a button pulls it to G.

const int ADD_PIN = 12;
const int UNDO_PIN = 10;
const unsigned long SETTLE = 30;   // milliseconds to ignore after a press. Try 0.

int count = 0;
bool addWasDown = false;
bool undoWasDown = false;
unsigned long lastChange = 0;

void setup() {
  pinMode(ADD_PIN, INPUT_PULLUP);
  pinMode(UNDO_PIN, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println("Count: 0");
}

void loop() {
  bool addDown = digitalRead(ADD_PIN) == LOW;     // pressed pulls the pin LOW
  bool undoDown = digitalRead(UNDO_PIN) == LOW;

  if (millis() - lastChange >= SETTLE) {
    if (addDown && !addWasDown) {
      count = count + 1;
      Serial.print("Count: ");
      Serial.println(count);
      lastChange = millis();
    }
    if (undoDown && !undoWasDown && count > 0) {
      count = count - 1;
      Serial.print("Count: ");
      Serial.println(count);
      lastChange = millis();
    }
    addWasDown = addDown;
    undoWasDown = undoDown;
  }
}
What you'll see

Press button one: the count goes up by one. Button two takes one away. It never goes below zero.

Break it on purpose

Set SETTLE to 0 and upload. Press button one ten times, counting yourself. The board's count is higher than yours.

Then try

Find the smallest SETTLE that never double counts on your buttons.

How the bench works

Bench sketches replace your chapter sketch while you use them. Your settings and your notebook stay saved on the board. When you finish, upload the chapter's sketch again and your machine is back exactly as it was.

While a bench sketch runs, the display and the ring freeze on whatever they last showed. That is normal.

If the light ring is still lit from your chapter sketch, switch everything off and on again before you start. It goes dark and stops using power the bench needs.

The breadboard has 17 numbered columns and two halves, top and bottom. The five holes in one column of one half are joined underneath. Nothing joins across the gap in the middle.

Every jumper from the shield has a female end: push it onto a shield pin. The male end goes into the breadboard. G, V and S are the same three pins you have used all book: ground, power, signal.

Never put a wire straight from V to G. That is a short circuit.

Ask Milo

Stuck, curious, or something looks wrong? Tell me what you see.

You can paste your code or an error message here too.

← Sensor DuelThe Night Shift →