aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rwxr-xr-xdesktop/main.cc215
-rwxr-xr-xdesktop/rpmcount.pro15
-rwxr-xr-xdesktop/serial_utils.h33
-rwxr-xr-xdesktop/term.cc28
-rwxr-xr-xdesktop/term.h3
-rwxr-xr-xdesktop/types.h27
12 files changed, 688 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}
diff --git a/desktop/main.cc b/desktop/main.cc
new file mode 100755
index 0000000..ba77e4b
--- /dev/null
+++ b/desktop/main.cc
@@ -0,0 +1,215 @@
1#include "serial_utils.h"
2#include "term.h"
3#include "types.h"
4
5#include <SerialStream.h>
6#include <iostream>
7#include <cstdio>
8#include <cstdlib>
9
10using namespace std;
11using namespace LibSerial;
12
13enum ErrorCode
14{
15 Ok,
16 Error
17};
18
19enum MessageHeader
20{
21 ReadConfig,
22 UpdateStartDelay,
23 UpdateRPMCount,
24 UpdateSignalsPerRPM
25};
26
27struct Config
28{
29 U32 startDelay; // Start delay in milliseconds
30 U32 rpmCount; // Number of RPM ticks to count
31 U32 signalsPerRPM; // Number of signal ticks per RPM tick
32};
33
34template <typename T>
35bool writeSafe (SerialStream& serial, MessageHeader header, const T& val)
36{
37 write<U8>(serial, (U8)header);
38 write<T>(serial, val);
39
40 U8 errorCode = read<U8>(serial);
41 T x = read<U32>(serial);
42
43 fprintf(stderr, "error code: %d\n", errorCode);
44 fprintf(stderr, "val: %d\n", x);
45
46 return errorCode == Ok && x == val;
47}
48
49bool configureStartDelay (SerialStream& serial, Config& config)
50{
51 printf("Tiempo de retardo (milisegundos)\n");
52 printf("--------------------------------\n");
53 printf("\n");
54 printf("Valor actual : %d\n", config.startDelay);
55 printf("\n");
56 printf("Nuevo valor : ");
57
58 U32 x;
59 cin >> x;
60
61 bool result = writeSafe<U32>(serial, UpdateStartDelay, x);
62 if (result)
63 {
64 config.startDelay = x;
65 }
66 return result;
67}
68
69bool configureRPMCount (SerialStream& serial, Config& config)
70{
71 printf("RPM maximo\n");
72 printf("----------\n");
73 printf("\n");
74 printf("Valor actual : %d\n", config.rpmCount);
75 printf("\n");
76 printf("Nuevo valor : ");
77
78 U32 x;
79 cin >> x;
80
81 bool result = writeSafe<U32>(serial, UpdateRPMCount, x);
82 if (result)
83 {
84 config.rpmCount = x;
85 }
86 return result;
87}
88
89bool configureSignalsPerRPM (SerialStream& serial, Config& config)
90{
91 printf("Impulsos/RPM\n");
92 printf("------------\n");
93 printf("\n");
94 printf("Valor actual : %d\n", config.signalsPerRPM);
95 printf("\n");
96 printf("Nuevo valor : ");
97
98 U32 x;
99 cin >> x;
100
101 bool result = writeSafe<U32>(serial, UpdateSignalsPerRPM, x);
102 if (result)
103 {
104 config.signalsPerRPM = x;
105 }
106 return result;
107}
108
109void loop (SerialStream& serial, Config& config)
110{
111 int option = -1;
112
113 while (option != 0)
114 {
115 system("clear");
116 printf("Configuracion\n");
117 printf("-------------\n");
118 printf("Tiempo de retardo : %d\n", config.startDelay);
119 printf("RPM maximo : %d\n", config.rpmCount);
120 printf("Impulsos/rpm : %d\n", config.signalsPerRPM);
121 printf("\n");
122 printf("Menu\n");
123 printf("----\n");
124 printf("[0] Salir\n");
125 printf("[1] Configurar tiempo de retardo\n");
126 printf("[2] Configurar RPM maximo\n");
127 printf("[3] Configurar impulsos/RPM\n");
128 printf("\n");
129 printf("> ");
130
131 option = getch() - '0';
132 system("clear");
133
134 bool error = false;
135
136 switch (option)
137 {
138 case 1: error = !configureStartDelay(serial, config); break;
139 case 2: error = !configureRPMCount(serial, config); break;
140 case 3: error = !configureSignalsPerRPM(serial, config); break;
141 default: break;
142 }
143
144 if (error)
145 {
146 fprintf(stderr, "Error al escribir valor\n");
147 return;
148 }
149 }
150}
151
152void readConfig (SerialStream& serial, Config& config)
153{
154 write<U8>(serial, (U8)ReadConfig);
155
156 U8 errorCode = read<U8>(serial);
157 if (errorCode == Ok)
158 {
159 config.startDelay = read<U32>(serial);
160 config.rpmCount = read<U32>(serial);
161 config.signalsPerRPM = read<U32>(serial);
162 }
163}
164
165void openArduino (const char* serialDevice, SerialStream& serial)
166{
167 if (serial.IsOpen()) serial.Close();
168 serial.Open(serialDevice);
169 serial.SetBaudRate(SerialStreamBuf::BAUD_9600);
170 serial.SetCharSize(SerialStreamBuf::CHAR_SIZE_8);
171 serial.SetNumOfStopBits(1);
172 serial.SetParity(SerialStreamBuf::PARITY_DEFAULT);
173 serial.SetFlowControl(SerialStreamBuf::FLOW_CONTROL_DEFAULT);
174}
175
176void usage (const char* argv0)
177{
178 fprintf(stderr, "Uso:\n");
179 fprintf(stderr, "\n");
180 fprintf(stderr, "%s <args>\n", argv0);
181 fprintf(stderr, "\n");
182 fprintf(stderr, "Args:\n");
183 fprintf(stderr, "\n");
184 fprintf(stderr, "dispositivo - Nombre de dispositivo serie\n");
185}
186
187int main (int argc, char** argv)
188{
189 if (argc != 2)
190 {
191 usage(argv[0]);
192 exit(0);
193 }
194
195 const char* serialDevice = argv[1];
196
197 SerialStream serial;
198 printf("Conectando con %s...\n", serialDevice);
199 openArduino(serialDevice, serial);
200 if (serial.IsOpen())
201 {
202 sleep(2); // Wait for arduino to wake up
203 printf("Leyendo configuracion...\n");
204 Config config;
205 readConfig(serial, config);
206 loop(serial, config);
207 }
208 else
209 {
210 printf("Error al conectar con %s\n", serialDevice);
211 cin.get();
212 }
213
214 return 0;
215}
diff --git a/desktop/rpmcount.pro b/desktop/rpmcount.pro
new file mode 100755
index 0000000..794ae42
--- /dev/null
+++ b/desktop/rpmcount.pro
@@ -0,0 +1,15 @@
1TEMPLATE = app
2CONFIG += console
3CONFIG -= app_bundle
4CONFIG -= qt
5
6LIBS += -lserial
7
8SOURCES += \
9 main.cc \
10 term.cc
11
12HEADERS += \
13 types.h \
14 serial_utils.h \
15 term.h
diff --git a/desktop/serial_utils.h b/desktop/serial_utils.h
new file mode 100755
index 0000000..8c351e4
--- /dev/null
+++ b/desktop/serial_utils.h
@@ -0,0 +1,33 @@
1#pragma once
2
3#include "types.h"
4
5#include <SerialStream.h>
6
7template <typename T>
8T read (LibSerial::SerialStream& serial)
9{
10 T x;
11 serial.read((char*) &x, sizeof(T));
12 return x;
13}
14
15template <>
16U32 read<U32> (LibSerial::SerialStream& serial)
17{
18 U32 x = 0;
19 for (int i = 0; i < 4; ++i)
20 {
21 U8 b;
22 serial.read((char*)&b, 1);
23 x = x >> 8;
24 x |= (b << 24);
25 }
26 return x;
27}
28
29template <typename T>
30void write (LibSerial::SerialStream& serial, const T& val)
31{
32 serial.write((const char*) &val, sizeof(T));
33}
diff --git a/desktop/term.cc b/desktop/term.cc
new file mode 100755
index 0000000..a72f1e9
--- /dev/null
+++ b/desktop/term.cc
@@ -0,0 +1,28 @@
1#include "term.h"
2
3#include <cstdio>
4#include <unistd.h> //_getch*/
5#include <termios.h> //_getch*/
6
7char getch ()
8{
9 char buf=0;
10 struct termios old={0};
11 fflush(stdout);
12 if(tcgetattr(0, &old)<0)
13 perror("tcsetattr()");
14 old.c_lflag&=~ICANON;
15 old.c_lflag&=~ECHO;
16 old.c_cc[VMIN]=1;
17 old.c_cc[VTIME]=0;
18 if(tcsetattr(0, TCSANOW, &old)<0)
19 perror("tcsetattr ICANON");
20 if(read(0,&buf,1)<0)
21 perror("read()");
22 old.c_lflag|=ICANON;
23 old.c_lflag|=ECHO;
24 if(tcsetattr(0, TCSADRAIN, &old)<0)
25 perror ("tcsetattr ~ICANON");
26 printf("%c\n",buf);
27 return buf;
28 }
diff --git a/desktop/term.h b/desktop/term.h
new file mode 100755
index 0000000..356992f
--- /dev/null
+++ b/desktop/term.h
@@ -0,0 +1,3 @@
1#pragma once
2
3char getch ();
diff --git a/desktop/types.h b/desktop/types.h
new file mode 100755
index 0000000..da462d4
--- /dev/null
+++ b/desktop/types.h
@@ -0,0 +1,27 @@
1#pragma once
2
3#include <stdint.h>
4
5/*
6File: Types
7*/
8
9#if defined(__GNUC__) || defined(__GNUG__) //Compiling with GNU C/C++ compiler
10 typedef __INT8_TYPE__ I8;
11 typedef __INT16_TYPE__ I16;
12 typedef __INT32_TYPE__ I32;
13 typedef __INT64_TYPE__ I64;
14 typedef __UINT8_TYPE__ U8;
15 typedef __UINT16_TYPE__ U16;
16 typedef __UINT32_TYPE__ U32;
17 typedef __UINT64_TYPE__ U64;
18#else //Visual Studio
19 typedef __int8 I8;
20 typedef __int16 I16;
21 typedef __int32 I32;
22 typedef __int64 I64;
23 typedef unsigned __int8 U8;
24 typedef unsigned __int16 U16;
25 typedef unsigned __int32 U32;
26 typedef unsigned __int64 U64;
27#endif