Skip to content
This repository
Browse code

Initial import

  • Loading branch information...
commit 53115b4a4ed748d81c66f7cf03e66e58bdf2a10f 0 parents
Elliot West teabot authored

Showing 1 changed file with 214 additions and 0 deletions. Show diff stats Hide diff stats

  1. +214 0 spacensus.pde
214 spacensus.pde
... ... @@ -0,0 +1,214 @@
  1 +#include <LiquidCrystal.h>
  2 +
  3 +const int BEAM_IN = 2; // interrupt
  4 +const int BEAM_OUT = 3; // interrupt
  5 +const int BEAM_ENABLE = 4;
  6 +
  7 +const int ALARM = 5; // PWM
  8 +
  9 +const int LCD_RS = 12;
  10 +const int LCD_RW = 11;
  11 +const int LCD_ENABLE = 10;
  12 +const int LCD_D4 = 9;
  13 +const int LCD_D5 = 8;
  14 +const int LCD_D6 = 7;
  15 +const int LCD_D7 = 6;
  16 +
  17 +const int INTERRUPT_IN = 0;
  18 +const int INTERRUPT_OUT = 1;
  19 +const int BREAK_MODE = FALLING;
  20 +const int BREAK_VAL = LOW;
  21 +
  22 +const int SERIAL_BAUD = 9600;
  23 +
  24 +const long ALARM_TONE_HZ = 9000;
  25 +
  26 +const int READY = 0;
  27 +const int WAIT_IN = 1;
  28 +const int WAIT_OUT = 2;
  29 +const int DELAY = 3;
  30 +
  31 +const long LOOP_WAIT_MS = 50;
  32 +
  33 +const long MIN_PERSON_INTERVAL_MS = 200;
  34 +const long MAX_PERSON_INTERVAL_MS = 800;
  35 +const long DELAY_BEFORE_RESET_MS = 1000;
  36 +const long OBSTRUCTION_INTERVAL_MS = 5000;
  37 +
  38 +boolean updateDisplay = true;
  39 +int people = 0;
  40 +int state = DELAY;
  41 +boolean alarm = false;
  42 +
  43 +long beamInDurationMs = 0;
  44 +long beamOutDurationMs = 0;
  45 +long breakIntervalMs = 0;
  46 +long resetIntervalMs = 0;
  47 +
  48 +LiquidCrystal lcd(LCD_RS, LCD_RW, LCD_ENABLE, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
  49 +
  50 +
  51 +void setup()
  52 +{
  53 + Serial.begin(SERIAL_BAUD);
  54 +
  55 + pinMode(BEAM_ENABLE, OUTPUT);
  56 + pinMode(BEAM_IN, OUTPUT);
  57 + pinMode(BEAM_OUT, OUTPUT);
  58 + digitalWrite(BEAM_ENABLE, LOW);
  59 + digitalWrite(BEAM_IN, LOW);
  60 + digitalWrite(BEAM_OUT, LOW);
  61 + pinMode(BEAM_IN, INPUT);
  62 + pinMode(BEAM_OUT, INPUT);
  63 +
  64 + lcd.print("spacensus v0.1");
  65 +}
  66 +
  67 +void loop()
  68 +{
  69 + switch (state) {
  70 + case DELAY:
  71 + handleResetDelay();
  72 + break;
  73 + case WAIT_OUT:
  74 + handleBreakInterval();
  75 + break;
  76 + case WAIT_IN:
  77 + handleBreakInterval();
  78 + break;
  79 + }
  80 + checkBeamsForObstructions();
  81 + updateScreenIfRequired();
  82 + delay(LOOP_WAIT_MS);
  83 +}
  84 +
  85 +void handleBreakInterval() {
  86 + breakIntervalMs += LOOP_WAIT_MS;
  87 + if (breakIntervalMs > DELAY_BEFORE_RESET_MS) {
  88 + ready();
  89 + }
  90 +}
  91 +
  92 +void ready() {
  93 + updateDisplay = true;
  94 + state = READY;
  95 + breakIntervalMs = 0;
  96 + attachInterrupt(INTERRUPT_IN, breakIn, BREAK_MODE);
  97 + attachInterrupt(INTERRUPT_OUT, breakOut, BREAK_MODE);
  98 +}
  99 +
  100 +void breakIn() {
  101 + handleBeamBreak(INTERRUPT_IN, WAIT_IN, WAIT_OUT, -1);
  102 +}
  103 +
  104 +void breakOut() {
  105 + handleBeamBreak(INTERRUPT_OUT, WAIT_OUT, WAIT_IN, 1);
  106 +}
  107 +
  108 +void handleBeamBreak(int interrupt, int gotoState, int waitingForState, int increment) {
  109 + if (state == READY) {
  110 + detachInterrupt(interrupt);
  111 + state = gotoState;
  112 + }
  113 + else if (state == waitingForState) {
  114 + detachInterrupt(interrupt);
  115 + if (isBreakIntervalWithinLimits()) {
  116 + people += increment;
  117 + if (people < 0) {
  118 + people = 0;
  119 + }
  120 + updateDisplay = true;
  121 + }
  122 + state = DELAY;
  123 +
  124 + }
  125 +}
  126 +
  127 +boolean isBreakIntervalWithinLimits() {
  128 + return breakIntervalMs >= MIN_PERSON_INTERVAL_MS && breakIntervalMs <= MAX_PERSON_INTERVAL_MS;
  129 +}
  130 +
  131 +void handleResetDelay() {
  132 + resetIntervalMs += LOOP_WAIT_MS;
  133 + if (resetIntervalMs >= DELAY_BEFORE_RESET_MS) {
  134 + resetIntervalMs = 0;
  135 + ready();
  136 + }
  137 +}
  138 +
  139 +void checkBeamsForObstructions() {
  140 + beamInDurationMs = calculateBeamBreakInterval(BEAM_IN, beamInDurationMs);
  141 + beamOutDurationMs = calculateBeamBreakInterval(BEAM_OUT, beamOutDurationMs);
  142 +
  143 + if (beamInDurationMs >= OBSTRUCTION_INTERVAL_MS || beamOutDurationMs >= OBSTRUCTION_INTERVAL_MS) {
  144 + alarmOn();
  145 + }
  146 + else {
  147 + alarmOff();
  148 + }
  149 +}
  150 +
  151 +long calculateBeamBreakInterval(int beam, long currentInterval) {
  152 + if (isBeamBroken(beam)) {
  153 + return currentInterval + LOOP_WAIT_MS;
  154 + }
  155 + else {
  156 + return 0;
  157 + }
  158 +}
  159 +
  160 +boolean isBeamBroken(int beam) {
  161 + return (digitalRead(beam) == BREAK_VAL);
  162 +}
  163 +
  164 +void alarmOn () {
  165 + if (!alarm) {
  166 + alarm = true;
  167 + tone(ALARM, ALARM_TONE_HZ);
  168 + updateDisplay = true;
  169 + }
  170 +}
  171 +
  172 +void alarmOff() {
  173 + if (alarm) {
  174 + alarm = false;
  175 + noTone(ALARM);
  176 + updateDisplay = true;
  177 + }
  178 +}
  179 +
  180 +void updateScreenIfRequired() {
  181 + if (updateDisplay) {
  182 + if (alarm) {
  183 + lcd.clear();
  184 + lcd.print("Beam obstructed!");
  185 + }
  186 + else if (state != DELAY) {
  187 + lcd.clear();
  188 + lcd.print("Occupancy: ");
  189 + lcd.print(people, DEC);
  190 + }
  191 + updateDisplay = false;
  192 + }
  193 +}
  194 +
  195 +
  196 +
  197 +
  198 +
  199 +
  200 +
  201 +
  202 +
  203 +
  204 +
  205 +
  206 +
  207 +
  208 +
  209 +
  210 +
  211 +
  212 +
  213 +
  214 +

0 comments on commit 53115b4

Please sign in to comment.
Something went wrong with that request. Please try again.