makernestOrigins · all chapters

Origins · Flagship

The Doorkeeper

Everything you have learnt, at one door, for a week.

Sketch D The Doorkeeper

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
// D The Doorkeeper
// The Maker's Book of Origins, chapter flagship one. Upload it, then turn back to the book.
// makernest.com/origins/d
// 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)); }
}

bool wasCold = false;
bool tooManyFired = false;

void setup() {
  machine.begin(13, "D|DOOR-|KEEPER");
  machine.homeShows(SHOW_A | SHOW_B | SHOW_COUNT | SHOW_NOTEBOOK);
  machine.useScreen(SCR_TOO_MANY);
  machine.useScreen(SCR_LOG);
  machine.useScreen(SCR_SEQUENCE);
  machine.useScreen(SCR_RUN_NOW);
  machine.useScreen(SCR_START_WITH);
  machine.useScreen(SCR_COLD_LINE);
  machine.useScreen(SCR_STOP_AT);
  machine.useScreen(SCR_SETTLE);
  machine.useScreen(SCR_KEEP_COUNT);
  machine.useScreen(SCR_WRITE_EVERY);
  machine.useScreen(SCR_APART_BY);
  machine.useScreen(SCR_WATCHES);
  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);

  // TOO MANY openings in the last hour: run the sequence once. Then wait until it calms down by your gap (chapter 04).
  if (machine.settings.tooMany) {
    int start = machine.settings.coldLine == NOT_SET ? 0 : machine.settings.coldLine;
    int stop = machine.settings.stopAt == NOT_SET ? start : machine.settings.stopAt;
    int gap = max(1, stop - start);
    uint8_t n = machine.openingsInLastHour();
    if (!tooManyFired && n >= machine.settings.tooMany) { tooManyFired = true; machine.runSequence(); }
    if (tooManyFired && n + gap <= machine.settings.tooMany) tooManyFired = false;
  }
  if (machine.settings.startWith == 1 && cold && !wasCold) machine.runSequence();
  wasCold = cold;
  // The notebook writes A, B and the openings since the last record, every WRITE EVERY.
}

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

Wiring

Nothing new to wire in this chapter. Here is the whole shield, so you can check every wire.

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 doorbell that plays a different tune after dark

The same press can mean two things. The board reads a second sensor before deciding what to do.

You need

On the breadboard

TOPBOTTOMLDR10k12 S12 GA0 VA0 SA0 G1234567891011121314151617

Build it

  1. Button across the middle gap, legs in columns 3 and 5. Row 12 S to column 3 top, row 12 G to column 5 bottom.
  2. Light sensor in the bottom half, columns 9 and 12. A 10 kΩ from column 12 to column 16, bottom half.
  3. Jumpers: A0 V to column 9 bottom, A0 S to column 12 bottom, A0 G to column 16 bottom.
  4. Passive buzzer straight from the shield: row 13 S to its S, row 13 G to its −.
  5. Upload bench sketch D.
Download .ino
// MakerNest Origins · bench D · a doorbell that plays a different tune after dark
// Button on row 12, passive buzzer on row 13, light sensor on A0.
// In the day it plays a loud ding-dong. After dark it plays three soft, low notes.

const int BUTTON_PIN = 12;
const int BUZZER_PIN = 13;
const int SENSOR_PIN = A0;
const int DARK = 300;          // below this, it counts as night

void dayTune() {
  tone(BUZZER_PIN, 784, 400);  // ding
  delay(450);
  tone(BUZZER_PIN, 587, 600);  // dong
  delay(650);
}

void nightTune() {
  tone(BUZZER_PIN, 392, 200);
  delay(260);
  tone(BUZZER_PIN, 330, 200);
  delay(260);
  tone(BUZZER_PIN, 262, 300);
  delay(360);
}

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(BUZZER_PIN, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  if (digitalRead(BUTTON_PIN) == LOW) {        // somebody pressed it
    int light = analogRead(SENSOR_PIN);
    Serial.println(light);
    if (light < DARK) {
      nightTune();
    } else {
      dayTune();
    }
    while (digitalRead(BUTTON_PIN) == LOW) {   // wait for the finger to come off
      delay(10);
    }
    delay(50);
  }
}
What you'll see

Press it in daylight: ding-dong. Cover the sensor and press: three soft notes.

Break it on purpose

Set DARK to 0. It is never night any more, and the soft tune never plays.

Then try

Write a third tune for when somebody presses it twice quickly.

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.

← Chain ReactionStakeout →