aboutsummaryrefslogtreecommitdiff
path: root/arduino
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2021-12-04 22:22:47 -0800
committer3gg <3gg@shellblade.net>2021-12-04 22:22:47 -0800
commite62be3b12d3c94d709a77d89f52c31f7c4ac475d (patch)
treebb351f85960443086730f0354f829958b2d03190 /arduino
parent48481ba9032689e1bceba05c98bc69972e1a2d3b (diff)
Initial commit.
Diffstat (limited to 'arduino')
-rwxr-xr-xarduino/Counter.cc98
-rwxr-xr-xarduino/Counter.h45
-rwxr-xr-xarduino/Makefile4
-rwxr-xr-xarduino/config.cc61
-rwxr-xr-xarduino/config.h12
-rwxr-xr-xarduino/rpmcount.ino147
6 files changed, 367 insertions, 0 deletions
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 @@
1#include "Counter.h"
2
3#include <Arduino.h>
4
5void Counter::init (unsigned long startDelay, unsigned long rpmCount, unsigned long signalsPerRPM)
6{
7 this->startDelay = startDelay;
8 this->rpmCount = rpmCount;
9 this->signalsPerRPM = signalsPerRPM;
10 reset();
11}
12
13void Counter::setStartDelay (unsigned long val)
14{
15 startDelay = val;
16}
17
18void Counter::setRPMCount (unsigned long val)
19{
20 rpmCount = val;
21}
22
23void Counter::setSignalsPerRPM (unsigned long val)
24{
25 signalsPerRPM = val;
26}
27
28void Counter::start (unsigned long startTime)
29{
30 if (state == READY)
31 {
32 this->startTime = startTime;
33 state = WAITING_FOR_TIMEOUT;
34 }
35}
36
37void Counter::reset ()
38{
39 state = READY;
40}
41
42void Counter::update (unsigned long t, int rpmSignal)
43{
44 switch (state)
45 {
46 case WAITING_FOR_TIMEOUT:
47 {
48 if (t - startTime >= startDelay)
49 {
50 startTime = t; // Update start time for counting state
51 signals = 0;
52 state = COUNTING;
53 }
54 break;
55 }
56 case COUNTING:
57 {
58 // Count signals in 1 second intervals
59 if (lastRpmSignal != rpmSignal && rpmSignal == HIGH)
60 {
61 signals++;
62 }
63 // 1 second interval reached
64 if (t - startTime >= 1000)
65 {
66 float rpm = ((float) signals / (float) signalsPerRPM) * 60.0f;
67 if (rpm <= rpmCount)
68 {
69 startTime = t; // Update start time for signaling state
70 state = SIGNALING;
71 }
72 else
73 {
74 // RPM threshold not reached.
75 // Count signals per second from scratch.
76 //Serial.print("rpm: \r\n"); Serial.print(rpm); Serial.print("\r\n");
77 startTime = t;
78 signals = 0;
79 }
80 }
81 break;
82 }
83 case SIGNALING:
84 {
85 if (t - startTime >= 3000)
86 {
87 state = READY;
88 }
89 }
90 default: break;
91 }
92 lastRpmSignal = rpmSignal;
93}
94
95Counter::State Counter::getState () const
96{
97 return state;
98}
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 @@
1#pragma once
2
3class Counter
4{
5public:
6
7 enum State
8 {
9 READY,
10 WAITING_FOR_TIMEOUT,
11 COUNTING,
12 SIGNALING
13 };
14
15public:
16
17 void init (unsigned long startDelay, unsigned long rpmCount, unsigned long signalsPerRPM);
18
19 void setStartDelay (unsigned long);
20
21 void setRPMCount (unsigned long);
22
23 void setSignalsPerRPM (unsigned long);
24
25 void start (unsigned long startTime);
26
27 void reset ();
28
29 void update (unsigned long time, int rpmSignal);
30
31 State getState () const;
32
33private:
34
35 State state;
36
37 unsigned long startDelay;
38 unsigned long rpmCount;
39 unsigned long signalsPerRPM;
40 unsigned long startTime;
41
42 unsigned long signals;
43
44 bool lastRpmSignal;
45};
diff --git a/arduino/Makefile b/arduino/Makefile
new file mode 100755
index 0000000..54884fa
--- /dev/null
+++ b/arduino/Makefile
@@ -0,0 +1,4 @@
1#ARDUINO_LIBS =
2BOARD_TAG = uno
3MONITOR_PORT = /dev/ttyACM0
4include /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 @@
1#include "config.h"
2
3#include <Arduino.h>
4#include <EEPROM.h>
5
6#define ROM_INITIALISED 17
7
8#define DEFAULT_SIGNALS_PER_RPM 133
9#define DEFAULT_START_DELAY_MILLIS 1000
10#define DEFAULT_RPM_COUNT 5000
11
12static Config config;
13
14int writeLong (int address, unsigned long val)
15{
16 const char* p = (char*) &val;
17 int i = 0;
18 for (; i < sizeof(val); ++i, ++p)
19 {
20 EEPROM.write(address + i, *p);
21 }
22 return address + i;
23}
24
25int readLong (int address, unsigned long& val)
26{
27 char* p = (char*) &val;
28 int i = 0;
29 for (; i < sizeof(val); ++i, ++p)
30 {
31 *p = EEPROM.read(address + i);
32 }
33 return address + i;
34}
35
36const Config& readConfig ()
37{
38 byte initialised = EEPROM.read(0);
39 if (initialised != ROM_INITIALISED)
40 {
41 int addr = 1;
42 addr = writeLong(addr, DEFAULT_START_DELAY_MILLIS);
43 addr = writeLong(addr, DEFAULT_RPM_COUNT);
44 addr = writeLong(addr, DEFAULT_SIGNALS_PER_RPM);
45 EEPROM.write(0, ROM_INITIALISED);
46 }
47 int addr = 1;
48 addr = readLong(addr, config.startDelay);
49 addr = readLong(addr, config.rpmCount);
50 addr = readLong(addr, config.signalsPerRPM);
51 return config;
52}
53
54void writeConfig (const Config& config)
55{
56 int addr = 1;
57 addr = writeLong(addr, config.startDelay);
58 addr = writeLong(addr, config.rpmCount);
59 addr = writeLong(addr, config.signalsPerRPM);
60 EEPROM.write(0, ROM_INITIALISED);
61}
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 @@
1#pragma once
2
3struct Config
4{
5 unsigned long startDelay; // Start delay in milliseconds
6 unsigned long rpmCount; // Number of RPM ticks to count
7 unsigned long signalsPerRPM; // Number of signal ticks per RPM tick
8};
9
10const Config& readConfig ();
11
12void 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 @@
1#include "config.h"
2#include "Counter.h"
3
4#define RPM_INPUT 2
5#define START_BUTTON 3
6#define COUNTING_LED 4
7#define TIMEOUT_LED 5
8#define READY_LED 6
9#define SIGNAL_PIN 7
10
11enum ErrorCode
12{
13 Ok,
14 Error
15};
16
17enum MessageHeader
18{
19 ReadConfig,
20 UpdateStartDelay,
21 UpdateRPMCount,
22 UpdateSignalsPerRPM
23};
24
25Config config;
26Counter counter;
27
28void setup ()
29{
30 Serial.begin(9600);
31
32 pinMode(RPM_INPUT, INPUT);
33 pinMode(START_BUTTON, INPUT);
34 pinMode(COUNTING_LED, OUTPUT);
35 pinMode(TIMEOUT_LED, OUTPUT);
36 pinMode(READY_LED, OUTPUT);
37 pinMode(SIGNAL_PIN, OUTPUT);
38 config = readConfig();
39 counter.init(config.startDelay, config.rpmCount, config.signalsPerRPM);
40 digitalWrite(READY_LED, HIGH);
41}
42
43void updateSerial ()
44{
45 unsigned long val = -1;
46 bool sendACK = false;
47 byte code;
48
49 while (Serial.available() > 0)
50 {
51 MessageHeader header = (MessageHeader) Serial.read();
52 switch (header)
53 {
54 case ReadConfig:
55 code = Ok;
56 Serial.write(code);
57 Serial.write((const uint8_t*) &config.startDelay, sizeof(config.startDelay));
58 Serial.write((const uint8_t*) &config.rpmCount, sizeof(config.rpmCount));
59 Serial.write((const uint8_t*) &config.signalsPerRPM, sizeof(config.signalsPerRPM));
60 Serial.flush();
61 break;
62
63 case UpdateStartDelay:
64 Serial.readBytes((char*)&val, sizeof(val));
65 config.startDelay = val;
66 writeConfig(config);
67 sendACK = true;
68 break;
69
70 case UpdateRPMCount:
71 Serial.readBytes((char*)&val, sizeof(val));
72 config.rpmCount = val;
73 writeConfig(config);
74 sendACK = true;
75 break;
76
77 case UpdateSignalsPerRPM:
78 Serial.readBytes((char*)&val, sizeof(val));
79 config.signalsPerRPM = val;
80 writeConfig(config);
81 sendACK = true;
82 break;
83
84 default:
85 code = Error;
86 Serial.write(code);
87 Serial.flush();
88 break;
89 }
90 }
91
92 if (sendACK)
93 {
94 code = Ok;
95 Serial.write(code);
96 Serial.write((const uint8_t*) &val, sizeof(val));
97 Serial.flush();
98 }
99}
100
101void loop ()
102{
103 Counter::State state = counter.getState();
104 if (state == Counter::READY)
105 {
106 if (digitalRead(START_BUTTON) == HIGH)
107 {
108 unsigned long t = millis();
109 counter.start(t);
110 digitalWrite(READY_LED, LOW);
111 digitalWrite(TIMEOUT_LED, HIGH);
112 }
113 else updateSerial();
114 }
115 else if (state == Counter::WAITING_FOR_TIMEOUT)
116 {
117 unsigned long t = millis();
118 int rpmSignal = digitalRead(RPM_INPUT);
119 counter.update(t, rpmSignal);
120 if (counter.getState() == Counter::COUNTING)
121 {
122 digitalWrite(TIMEOUT_LED, LOW);
123 digitalWrite(COUNTING_LED, HIGH);
124 }
125 }
126 else if (state == Counter::COUNTING)
127 {
128 unsigned long t = millis();
129 int rpmSignal = digitalRead(RPM_INPUT);
130 counter.update(t, rpmSignal);
131 if (counter.getState() == Counter::SIGNALING)
132 {
133 digitalWrite(COUNTING_LED, LOW);
134 digitalWrite(SIGNAL_PIN, HIGH);
135 }
136 }
137 else if (state == Counter::SIGNALING)
138 {
139 unsigned long t = millis();
140 counter.update(t, LOW);
141 if (counter.getState() == Counter::READY)
142 {
143 digitalWrite(SIGNAL_PIN, LOW);
144 digitalWrite(READY_LED, HIGH);
145 }
146 }
147}