From e62be3b12d3c94d709a77d89f52c31f7c4ac475d Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 4 Dec 2021 22:22:47 -0800 Subject: Initial commit. --- arduino/Counter.cc | 98 ++++++++++++++++++++++++++++++++++ arduino/Counter.h | 45 ++++++++++++++++ arduino/Makefile | 4 ++ arduino/config.cc | 61 +++++++++++++++++++++ arduino/config.h | 12 +++++ arduino/rpmcount.ino | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 367 insertions(+) create mode 100755 arduino/Counter.cc create mode 100755 arduino/Counter.h create mode 100755 arduino/Makefile create mode 100755 arduino/config.cc create mode 100755 arduino/config.h create mode 100755 arduino/rpmcount.ino (limited to 'arduino') diff --git a/arduino/Counter.cc b/arduino/Counter.cc new file mode 100755 index 0000000..abf7c27 --- /dev/null +++ b/arduino/Counter.cc @@ -0,0 +1,98 @@ +#include "Counter.h" + +#include + +void Counter::init (unsigned long startDelay, unsigned long rpmCount, unsigned long signalsPerRPM) +{ + this->startDelay = startDelay; + this->rpmCount = rpmCount; + this->signalsPerRPM = signalsPerRPM; + reset(); +} + +void Counter::setStartDelay (unsigned long val) +{ + startDelay = val; +} + +void Counter::setRPMCount (unsigned long val) +{ + rpmCount = val; +} + +void Counter::setSignalsPerRPM (unsigned long val) +{ + signalsPerRPM = val; +} + +void Counter::start (unsigned long startTime) +{ + if (state == READY) + { + this->startTime = startTime; + state = WAITING_FOR_TIMEOUT; + } +} + +void Counter::reset () +{ + state = READY; +} + +void Counter::update (unsigned long t, int rpmSignal) +{ + switch (state) + { + case WAITING_FOR_TIMEOUT: + { + if (t - startTime >= startDelay) + { + startTime = t; // Update start time for counting state + signals = 0; + state = COUNTING; + } + break; + } + case COUNTING: + { + // Count signals in 1 second intervals + if (lastRpmSignal != rpmSignal && rpmSignal == HIGH) + { + signals++; + } + // 1 second interval reached + if (t - startTime >= 1000) + { + float rpm = ((float) signals / (float) signalsPerRPM) * 60.0f; + if (rpm <= rpmCount) + { + startTime = t; // Update start time for signaling state + state = SIGNALING; + } + else + { + // RPM threshold not reached. + // Count signals per second from scratch. + //Serial.print("rpm: \r\n"); Serial.print(rpm); Serial.print("\r\n"); + startTime = t; + signals = 0; + } + } + break; + } + case SIGNALING: + { + if (t - startTime >= 3000) + { + state = READY; + } + } + default: break; + } + lastRpmSignal = rpmSignal; +} + +Counter::State Counter::getState () const +{ + return state; +} diff --git a/arduino/Counter.h b/arduino/Counter.h new file mode 100755 index 0000000..f832023 --- /dev/null +++ b/arduino/Counter.h @@ -0,0 +1,45 @@ +#pragma once + +class Counter +{ +public: + + enum State + { + READY, + WAITING_FOR_TIMEOUT, + COUNTING, + SIGNALING + }; + +public: + + void init (unsigned long startDelay, unsigned long rpmCount, unsigned long signalsPerRPM); + + void setStartDelay (unsigned long); + + void setRPMCount (unsigned long); + + void setSignalsPerRPM (unsigned long); + + void start (unsigned long startTime); + + void reset (); + + void update (unsigned long time, int rpmSignal); + + State getState () const; + +private: + + State state; + + unsigned long startDelay; + unsigned long rpmCount; + unsigned long signalsPerRPM; + unsigned long startTime; + + unsigned long signals; + + bool lastRpmSignal; +}; diff --git a/arduino/Makefile b/arduino/Makefile new file mode 100755 index 0000000..54884fa --- /dev/null +++ b/arduino/Makefile @@ -0,0 +1,4 @@ +#ARDUINO_LIBS = +BOARD_TAG = uno +MONITOR_PORT = /dev/ttyACM0 +include /usr/share/arduino/Arduino.mk diff --git a/arduino/config.cc b/arduino/config.cc new file mode 100755 index 0000000..a46c663 --- /dev/null +++ b/arduino/config.cc @@ -0,0 +1,61 @@ +#include "config.h" + +#include +#include + +#define ROM_INITIALISED 17 + +#define DEFAULT_SIGNALS_PER_RPM 133 +#define DEFAULT_START_DELAY_MILLIS 1000 +#define DEFAULT_RPM_COUNT 5000 + +static Config config; + +int writeLong (int address, unsigned long val) +{ + const char* p = (char*) &val; + int i = 0; + for (; i < sizeof(val); ++i, ++p) + { + EEPROM.write(address + i, *p); + } + return address + i; +} + +int readLong (int address, unsigned long& val) +{ + char* p = (char*) &val; + int i = 0; + for (; i < sizeof(val); ++i, ++p) + { + *p = EEPROM.read(address + i); + } + return address + i; +} + +const Config& readConfig () +{ + byte initialised = EEPROM.read(0); + if (initialised != ROM_INITIALISED) + { + int addr = 1; + addr = writeLong(addr, DEFAULT_START_DELAY_MILLIS); + addr = writeLong(addr, DEFAULT_RPM_COUNT); + addr = writeLong(addr, DEFAULT_SIGNALS_PER_RPM); + EEPROM.write(0, ROM_INITIALISED); + } + int addr = 1; + addr = readLong(addr, config.startDelay); + addr = readLong(addr, config.rpmCount); + addr = readLong(addr, config.signalsPerRPM); + return config; +} + +void writeConfig (const Config& config) +{ + int addr = 1; + addr = writeLong(addr, config.startDelay); + addr = writeLong(addr, config.rpmCount); + addr = writeLong(addr, config.signalsPerRPM); + EEPROM.write(0, ROM_INITIALISED); +} diff --git a/arduino/config.h b/arduino/config.h new file mode 100755 index 0000000..cb3bf93 --- /dev/null +++ b/arduino/config.h @@ -0,0 +1,12 @@ +#pragma once + +struct Config +{ + unsigned long startDelay; // Start delay in milliseconds + unsigned long rpmCount; // Number of RPM ticks to count + unsigned long signalsPerRPM; // Number of signal ticks per RPM tick +}; + +const Config& readConfig (); + +void writeConfig (const Config&); diff --git a/arduino/rpmcount.ino b/arduino/rpmcount.ino new file mode 100755 index 0000000..51e6bfe --- /dev/null +++ b/arduino/rpmcount.ino @@ -0,0 +1,147 @@ +#include "config.h" +#include "Counter.h" + +#define RPM_INPUT 2 +#define START_BUTTON 3 +#define COUNTING_LED 4 +#define TIMEOUT_LED 5 +#define READY_LED 6 +#define SIGNAL_PIN 7 + +enum ErrorCode +{ + Ok, + Error +}; + +enum MessageHeader +{ + ReadConfig, + UpdateStartDelay, + UpdateRPMCount, + UpdateSignalsPerRPM +}; + +Config config; +Counter counter; + +void setup () +{ + Serial.begin(9600); + + pinMode(RPM_INPUT, INPUT); + pinMode(START_BUTTON, INPUT); + pinMode(COUNTING_LED, OUTPUT); + pinMode(TIMEOUT_LED, OUTPUT); + pinMode(READY_LED, OUTPUT); + pinMode(SIGNAL_PIN, OUTPUT); + config = readConfig(); + counter.init(config.startDelay, config.rpmCount, config.signalsPerRPM); + digitalWrite(READY_LED, HIGH); +} + +void updateSerial () +{ + unsigned long val = -1; + bool sendACK = false; + byte code; + + while (Serial.available() > 0) + { + MessageHeader header = (MessageHeader) Serial.read(); + switch (header) + { + case ReadConfig: + code = Ok; + Serial.write(code); + Serial.write((const uint8_t*) &config.startDelay, sizeof(config.startDelay)); + Serial.write((const uint8_t*) &config.rpmCount, sizeof(config.rpmCount)); + Serial.write((const uint8_t*) &config.signalsPerRPM, sizeof(config.signalsPerRPM)); + Serial.flush(); + break; + + case UpdateStartDelay: + Serial.readBytes((char*)&val, sizeof(val)); + config.startDelay = val; + writeConfig(config); + sendACK = true; + break; + + case UpdateRPMCount: + Serial.readBytes((char*)&val, sizeof(val)); + config.rpmCount = val; + writeConfig(config); + sendACK = true; + break; + + case UpdateSignalsPerRPM: + Serial.readBytes((char*)&val, sizeof(val)); + config.signalsPerRPM = val; + writeConfig(config); + sendACK = true; + break; + + default: + code = Error; + Serial.write(code); + Serial.flush(); + break; + } + } + + if (sendACK) + { + code = Ok; + Serial.write(code); + Serial.write((const uint8_t*) &val, sizeof(val)); + Serial.flush(); + } +} + +void loop () +{ + Counter::State state = counter.getState(); + if (state == Counter::READY) + { + if (digitalRead(START_BUTTON) == HIGH) + { + unsigned long t = millis(); + counter.start(t); + digitalWrite(READY_LED, LOW); + digitalWrite(TIMEOUT_LED, HIGH); + } + else updateSerial(); + } + else if (state == Counter::WAITING_FOR_TIMEOUT) + { + unsigned long t = millis(); + int rpmSignal = digitalRead(RPM_INPUT); + counter.update(t, rpmSignal); + if (counter.getState() == Counter::COUNTING) + { + digitalWrite(TIMEOUT_LED, LOW); + digitalWrite(COUNTING_LED, HIGH); + } + } + else if (state == Counter::COUNTING) + { + unsigned long t = millis(); + int rpmSignal = digitalRead(RPM_INPUT); + counter.update(t, rpmSignal); + if (counter.getState() == Counter::SIGNALING) + { + digitalWrite(COUNTING_LED, LOW); + digitalWrite(SIGNAL_PIN, HIGH); + } + } + else if (state == Counter::SIGNALING) + { + unsigned long t = millis(); + counter.update(t, LOW); + if (counter.getState() == Counter::READY) + { + digitalWrite(SIGNAL_PIN, LOW); + digitalWrite(READY_LED, HIGH); + } + } +} -- cgit v1.2.3