Browse Source

Initial commit.

main
3gg 1 year ago
parent
commit
e62be3b12d
  1. 98
      arduino/Counter.cc
  2. 45
      arduino/Counter.h
  3. 4
      arduino/Makefile
  4. 61
      arduino/config.cc
  5. 12
      arduino/config.h
  6. 147
      arduino/rpmcount.ino
  7. 215
      desktop/main.cc
  8. 15
      desktop/rpmcount.pro
  9. 33
      desktop/serial_utils.h
  10. 28
      desktop/term.cc
  11. 3
      desktop/term.h
  12. 27
      desktop/types.h

98
arduino/Counter.cc

@ -0,0 +1,98 @@
#include "Counter.h"
#include <Arduino.h>
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;
}

45
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;
};

4
arduino/Makefile

@ -0,0 +1,4 @@
#ARDUINO_LIBS =
BOARD_TAG = uno
MONITOR_PORT = /dev/ttyACM0
include /usr/share/arduino/Arduino.mk

61
arduino/config.cc

@ -0,0 +1,61 @@
#include "config.h"
#include <Arduino.h>
#include <EEPROM.h>
#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);
}

12
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&);

147
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);
}
}
}

215
desktop/main.cc

@ -0,0 +1,215 @@
#include "serial_utils.h"
#include "term.h"
#include "types.h"
#include <SerialStream.h>
#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;
using namespace LibSerial;
enum ErrorCode
{
Ok,
Error
};
enum MessageHeader
{
ReadConfig,
UpdateStartDelay,
UpdateRPMCount,
UpdateSignalsPerRPM
};
struct Config
{
U32 startDelay; // Start delay in milliseconds
U32 rpmCount; // Number of RPM ticks to count
U32 signalsPerRPM; // Number of signal ticks per RPM tick
};
template <typename T>
bool writeSafe (SerialStream& serial, MessageHeader header, const T& val)
{
write<U8>(serial, (U8)header);
write<T>(serial, val);
U8 errorCode = read<U8>(serial);
T x = read<U32>(serial);
fprintf(stderr, "error code: %d\n", errorCode);
fprintf(stderr, "val: %d\n", x);
return errorCode == Ok && x == val;
}
bool configureStartDelay (SerialStream& serial, Config& config)
{
printf("Tiempo de retardo (milisegundos)\n");
printf("--------------------------------\n");
printf("\n");
printf("Valor actual : %d\n", config.startDelay);
printf("\n");
printf("Nuevo valor : ");
U32 x;
cin >> x;
bool result = writeSafe<U32>(serial, UpdateStartDelay, x);
if (result)
{
config.startDelay = x;
}
return result;
}
bool configureRPMCount (SerialStream& serial, Config& config)
{
printf("RPM maximo\n");
printf("----------\n");
printf("\n");
printf("Valor actual : %d\n", config.rpmCount);
printf("\n");
printf("Nuevo valor : ");
U32 x;
cin >> x;
bool result = writeSafe<U32>(serial, UpdateRPMCount, x);
if (result)
{
config.rpmCount = x;
}
return result;
}
bool configureSignalsPerRPM (SerialStream& serial, Config& config)
{
printf("Impulsos/RPM\n");
printf("------------\n");
printf("\n");
printf("Valor actual : %d\n", config.signalsPerRPM);
printf("\n");
printf("Nuevo valor : ");
U32 x;
cin >> x;
bool result = writeSafe<U32>(serial, UpdateSignalsPerRPM, x);
if (result)
{
config.signalsPerRPM = x;
}
return result;
}
void loop (SerialStream& serial, Config& config)
{
int option = -1;
while (option != 0)
{
system("clear");
printf("Configuracion\n");
printf("-------------\n");
printf("Tiempo de retardo : %d\n", config.startDelay);
printf("RPM maximo : %d\n", config.rpmCount);
printf("Impulsos/rpm : %d\n", config.signalsPerRPM);
printf("\n");
printf("Menu\n");
printf("----\n");
printf("[0] Salir\n");
printf("[1] Configurar tiempo de retardo\n");
printf("[2] Configurar RPM maximo\n");
printf("[3] Configurar impulsos/RPM\n");
printf("\n");
printf("> ");
option = getch() - '0';
system("clear");
bool error = false;
switch (option)
{
case 1: error = !configureStartDelay(serial, config); break;
case 2: error = !configureRPMCount(serial, config); break;
case 3: error = !configureSignalsPerRPM(serial, config); break;
default: break;
}
if (error)
{
fprintf(stderr, "Error al escribir valor\n");
return;
}
}
}
void readConfig (SerialStream& serial, Config& config)
{
write<U8>(serial, (U8)ReadConfig);
U8 errorCode = read<U8>(serial);
if (errorCode == Ok)
{
config.startDelay = read<U32>(serial);
config.rpmCount = read<U32>(serial);
config.signalsPerRPM = read<U32>(serial);
}
}
void openArduino (const char* serialDevice, SerialStream& serial)
{
if (serial.IsOpen()) serial.Close();
serial.Open(serialDevice);
serial.SetBaudRate(SerialStreamBuf::BAUD_9600);
serial.SetCharSize(SerialStreamBuf::CHAR_SIZE_8);
serial.SetNumOfStopBits(1);
serial.SetParity(SerialStreamBuf::PARITY_DEFAULT);
serial.SetFlowControl(SerialStreamBuf::FLOW_CONTROL_DEFAULT);
}
void usage (const char* argv0)
{
fprintf(stderr, "Uso:\n");
fprintf(stderr, "\n");
fprintf(stderr, "%s <args>\n", argv0);
fprintf(stderr, "\n");
fprintf(stderr, "Args:\n");
fprintf(stderr, "\n");
fprintf(stderr, "dispositivo - Nombre de dispositivo serie\n");
}
int main (int argc, char** argv)
{
if (argc != 2)
{
usage(argv[0]);
exit(0);
}
const char* serialDevice = argv[1];
SerialStream serial;
printf("Conectando con %s...\n", serialDevice);
openArduino(serialDevice, serial);
if (serial.IsOpen())
{
sleep(2); // Wait for arduino to wake up
printf("Leyendo configuracion...\n");
Config config;
readConfig(serial, config);
loop(serial, config);
}
else
{
printf("Error al conectar con %s\n", serialDevice);
cin.get();
}
return 0;
}

15
desktop/rpmcount.pro

@ -0,0 +1,15 @@
TEMPLATE = app
CONFIG += console
CONFIG -= app_bundle
CONFIG -= qt
LIBS += -lserial
SOURCES += \
main.cc \
term.cc
HEADERS += \
types.h \
serial_utils.h \
term.h

33
desktop/serial_utils.h

@ -0,0 +1,33 @@
#pragma once
#include "types.h"
#include <SerialStream.h>
template <typename T>
T read (LibSerial::SerialStream& serial)
{
T x;
serial.read((char*) &x, sizeof(T));
return x;
}
template <>
U32 read<U32> (LibSerial::SerialStream& serial)
{
U32 x = 0;
for (int i = 0; i < 4; ++i)
{
U8 b;
serial.read((char*)&b, 1);
x = x >> 8;
x |= (b << 24);
}
return x;
}
template <typename T>
void write (LibSerial::SerialStream& serial, const T& val)
{
serial.write((const char*) &val, sizeof(T));
}

28
desktop/term.cc

@ -0,0 +1,28 @@
#include "term.h"
#include <cstdio>
#include <unistd.h> //_getch*/
#include <termios.h> //_getch*/
char getch ()
{
char buf=0;
struct termios old={0};
fflush(stdout);
if(tcgetattr(0, &old)<0)
perror("tcsetattr()");
old.c_lflag&=~ICANON;
old.c_lflag&=~ECHO;
old.c_cc[VMIN]=1;
old.c_cc[VTIME]=0;
if(tcsetattr(0, TCSANOW, &old)<0)
perror("tcsetattr ICANON");
if(read(0,&buf,1)<0)
perror("read()");
old.c_lflag|=ICANON;
old.c_lflag|=ECHO;
if(tcsetattr(0, TCSADRAIN, &old)<0)
perror ("tcsetattr ~ICANON");
printf("%c\n",buf);
return buf;
}

3
desktop/term.h

@ -0,0 +1,3 @@
#pragma once
char getch ();

27
desktop/types.h

@ -0,0 +1,27 @@
#pragma once
#include <stdint.h>
/*
File: Types
*/
#if defined(__GNUC__) || defined(__GNUG__) //Compiling with GNU C/C++ compiler
typedef __INT8_TYPE__ I8;
typedef __INT16_TYPE__ I16;
typedef __INT32_TYPE__ I32;
typedef __INT64_TYPE__ I64;
typedef __UINT8_TYPE__ U8;
typedef __UINT16_TYPE__ U16;
typedef __UINT32_TYPE__ U32;
typedef __UINT64_TYPE__ U64;
#else //Visual Studio
typedef __int8 I8;
typedef __int16 I16;
typedef __int32 I32;
typedef __int64 I64;
typedef unsigned __int8 U8;
typedef unsigned __int16 U16;
typedef unsigned __int32 U32;
typedef unsigned __int64 U64;
#endif
Loading…
Cancel
Save