Diagram:
Code:
Arduino.ino:
#include "Unit.h" #include "RunningAverage.h" #include "StopWatch.h" bool doprint=true; const int threshold=20; const int neg_threshold=-10; const int array_size=15; const int fill_array=200; unsigned int grow_time=36000; unsigned int break_time=7200; unsigned int wait_time=1200; const int unit_one_sensor=A0; const int unit_two_sensor=A1; const int unit_thr_sensor=A2; int unit_one_plus=4; int unit_one_minus=5; int unit_two_plus=6; int unit_two_minus=7; int unit_thr_plus=8; int unit_thr_minus=9; Unit one(unit_one_sensor, unit_one_minus, unit_one_plus, 1, threshold, array_size, fill_array); Unit two(unit_two_sensor, unit_two_minus, unit_two_plus, 2, threshold, array_size, fill_array); Unit thr(unit_thr_sensor, unit_thr_minus, unit_thr_plus, 3, threshold, array_size, fill_array); void setup(){ pinMode(unit_one_minus,OUTPUT); pinMode(unit_one_plus,OUTPUT); pinMode(unit_two_minus,OUTPUT); pinMode(unit_two_plus,OUTPUT); pinMode(unit_thr_minus,OUTPUT); pinMode(unit_thr_plus,OUTPUT); Serial.begin(19200); Serial.println("burnout_011"); one.wachse(); two.wachse(); thr.wachse(); } void loop(){ /* one.run(); two.run(); thr.run(); */ one.run_timed(grow_time, break_time, wait_time); two.run_timed(grow_time, break_time, wait_time); thr.run_timed(grow_time, break_time, wait_time); if(doprint) { one.do_print(); two.do_print(); thr.do_print(); Serial.println(); } delay(1); }
Unit.h
#ifndef Unit_h #define Unit_h #include "RunningAverage.h" #include "StopWatch.h" class Unit { public: Unit(void); Unit(int const& sensor, int const& minus, int const& plus, int const& unitid, int const& threshold, int const& size, int const& fillarray); ~Unit(); void wachse(); void breche(); void warte(); int state(); void run(); void run_timed(unsigned int const& grow_time, unsigned int const& break_time, unsigned int const& wait_time); void emergency_break(); void do_print(); void fill_spaces(int const& value); private: int m_sensor; int m_relais_minus; int m_relais_plus; int m_state; int m_unitid; int m_threshold; int m_fillarray; RunningAverage m_RA; RunningAverage m_delta_RA; StopWatch m_sw; int m_readings; }; #endif
Unit.cpp
#include "Unit.h" #include "RunningAverage.h" #include "StopWatch.h" #include <Arduino.h> Unit::Unit(int const& sensor, int const& r_minus, int const& r_plus, int const& unitid, int const& threshold, int const& size, int const& fillarray) { m_sensor=sensor; m_relais_minus = r_minus; m_relais_plus = r_plus; m_unitid=unitid; m_threshold=threshold; m_state=0; m_fillarray=fillarray; m_sw.start(); m_RA.init(size); m_delta_RA.init(size); digitalWrite(m_relais_minus, HIGH); digitalWrite(m_relais_plus, HIGH); } Unit::~Unit() { } void Unit::wachse() { digitalWrite(m_relais_minus, LOW); digitalWrite(m_relais_plus, HIGH); m_state=1; } void Unit::breche() { digitalWrite(m_relais_minus, HIGH); delay(10); digitalWrite(m_relais_plus, LOW); m_state=2; } void Unit::warte() { digitalWrite(m_relais_minus, HIGH); digitalWrite(m_relais_plus, HIGH); m_state=3; } int Unit::state() { return m_state; } void Unit::run() { m_readings=analogRead(m_sensor); emergency_break(); m_RA.addValue(m_readings); m_delta_RA.addValue(m_readings-m_RA.getAverage()); if(m_fillarray>0) { m_fillarray--; } else if(m_readings<=1000) { if(m_delta_RA.getAverage()>m_threshold) { breche(); } if(m_delta_RA.getAverage()<(-m_threshold)) { wachse(); } } } void Unit::run_timed(unsigned int const& grow_time, unsigned int const& break_time, unsigned int const& wait_time) { m_readings=analogRead(m_sensor); emergency_break(); m_RA.addValue(m_readings); m_delta_RA.addValue(m_readings-m_RA.getAverage()); if(m_fillarray>0) { m_fillarray--; } else if(m_readings<=1000) { if(m_delta_RA.getAverage()>m_threshold) { breche(); m_sw.reset(); m_sw.start(); } if(m_delta_RA.getAverage()<(-m_threshold)) { wachse(); m_sw.reset(); m_sw.start(); } if(m_state==1 && m_sw.elapsed()>grow_time) { breche(); } if(m_state==2 && m_sw.elapsed()>break_time) { wachse(); } if(m_state==3 && m_sw.elapsed()>wait_time) { wachse(); } } } void Unit::do_print() { Serial.print(" unit"); Serial.print(m_unitid); Serial.print(": "); Serial.print(m_state); fill_spaces(m_readings); Serial.print(m_readings); Serial.print(" "); fill_spaces(m_delta_RA.getAverage()); Serial.print(m_delta_RA.getAverage()); Serial.print("#"); fill_spaces(m_fillarray); Serial.print(m_fillarray); Serial.print("->"); fill_spaces(m_sw.elapsed()); Serial.print(m_sw.elapsed()); } void Unit::emergency_break() { if(m_readings>1000 && m_readings < 1010) { Serial.print(" | "); Serial.print(m_readings); Serial.print(" "); Serial.print("HIGH"); Serial.print(" E_1 UNIT"); Serial.print(m_unitid); Serial.print(": "); Serial.print(m_state); Serial.print(" | "); breche(); m_sw.reset(); m_sw.start(); } if(m_readings>=1010) { Serial.print(" # "); Serial.print(m_readings); Serial.print(" # "); Serial.print("HIGH"); Serial.print(" E_2 UNIT"); Serial.print(m_unitid); Serial.print(": "); Serial.print(m_state); Serial.print(" # "); wachse(); delay(10); breche(); m_sw.reset(); m_sw.start(); } if(m_readings>1022) { Serial.print(" | "); Serial.print(m_readings); Serial.print(" "); Serial.print("HIGH"); Serial.print(" E_3 UNIT"); Serial.print(m_unitid); Serial.print(": "); Serial.print(m_state); Serial.print(" | "); warte(); m_sw.reset(); m_sw.start(); } } void Unit::fill_spaces(int const& value) { if(value<1000 && value>=0) { Serial.print(" "); if(value<100) { Serial.print(" "); if(value<10) { Serial.print(" "); } } } if(value>-1000 && value<0) { if(value>-100) { Serial.print(" "); if(value>-10) { Serial.print(" "); } } } }
RunningAverage.h
#ifndef RunningAverage_h #define RunningAverage_h // // FILE: RunningAverage.h // AUTHOR: Rob dot Tillaart at gmail dot com // PURPOSE: RunningAverage library for Arduino // URL: http://playground.arduino.cc/Main/RunningAverage // HISTORY: See RunningAverage.cpp // // Released to the public domain // // backwards compatibility // clr() clear() // add(x) addValue(x) // avg() getAverage() #define RUNNINGAVERAGE_LIB_VERSION "0.2.02" class RunningAverage { public: RunningAverage(); RunningAverage(int); ~RunningAverage(); void clear(); void init(int n); void addValue(int); int getAverage(); void fillValue(int, int); protected: int _size; int _cnt; int _idx; int _sum; int * _ar; }; #endif // END OF FILE
RunningAverage.cpp
// // FILE: RunningAverage.cpp // AUTHOR: Rob Tillaart // VERSION: 0.2.02 // PURPOSE: RunningAverage library for Arduino // // The library stores the last N individual values in a circular buffer, // to calculate the running average. // // HISTORY: // 0.1.00 - 2011-01-30 initial version // 0.1.01 - 2011-02-28 fixed missing destructor in .h // 0.2.00 - 2012-??-?? Yuval Naveh added trimValue (found on web) // http://stromputer.googlecode.com/svn-history/r74/trunk/Arduino/Libraries/RunningAverage/RunningAverage.cpp // 0.2.01 - 2012-11-21 refactored // 0.2.02 - 2012-12-30 refactored trimValue -> fillValue // // Released to the public domain // #include "RunningAverage.h" #include <stdlib.h> RunningAverage::RunningAverage() { } RunningAverage::RunningAverage(int n) { _size = n; _ar = (int*) malloc(_size * sizeof(int)); clear(); } RunningAverage::~RunningAverage() { free(_ar); } // resets all counters void RunningAverage::clear() { _cnt = 0; _idx = 0; _sum = 0.0; for (int i = 0; i< _size; i++) _ar[i] = 0.0; // needed to keep addValue simple } void RunningAverage::init(int n) { _size = n; _ar = (int*) malloc(_size * sizeof(int)); clear(); } // adds a new value to the data-set void RunningAverage::addValue(int f) { _sum -= _ar[_idx]; _ar[_idx] = f; _sum += _ar[_idx]; _idx++; if (_idx == _size) _idx = 0; // faster than % if (_cnt < _size) _cnt++; } // returns the average of the data-set added sofar int RunningAverage::getAverage() { if (_cnt == 0) return 0; // NaN ? math.h return _sum / _cnt; } // fill the average with a value // the param number determines how often value is added (weight) // number should preferably be between 1 and size void RunningAverage::fillValue(int value, int number) { clear(); for (int i = 0; i < number; i++) { addValue(value); } } // END OF FILE
Stopwatch.h
#ifndef StopWatch_h #define StopWatch_h // // FILE: StopWatch.h // AUTHOR: Rob Tillaart // PURPOSE: Simple StopWatch library for Arduino // HISTORY: See StopWatch.cpp // URL: http://playground.arduino.cc/Code/StopWatchClass // // Released to the public domain // #define STOPWATCH_LIB_VERSION "0.1.03" #if ARDUINO >= 100 #include "Arduino.h" #else #include "WProgram.h" #endif class StopWatch { public: enum State { RESET, RUNNING, STOPPED }; enum Resolution { MILLIS, MICROS, SECONDS }; StopWatch(enum Resolution res = SECONDS); void start(); void stop(); void reset(); unsigned long value(); unsigned long elapsed() { return value(); }; bool isRunning(); enum State state(); enum Resolution resolution() { return _res; }; private: enum State _state; enum Resolution _res; unsigned long _starttime; unsigned long _stoptime; unsigned long (*_gettime)(void); static unsigned long seconds() { return millis()/1000; }; }; #endif // END OF FILE
StopWatch.cpp
// // FILE: StopWatch.cpp // AUTHOR: Rob Tillaart // VERSION: 0.1.03 // PURPOSE: Simple StopWatch library for Arduino // // The library is based upon millis() and therefore // has the same restrictions as millis() has wrt overflow. // // HISTORY: // 0.1.00 - 2011-01-04 initial version // 0.1.01 - 2011-01-04 Added better state // 0.1.02 - 2011-06-15 Added state() + #defines + lib version // 0.1.03 - 2012-01-22 Added several improvements // By mromani & Rob Tillaart // // Released to the public domain // #include "StopWatch.h" StopWatch::StopWatch(enum Resolution res) { _res = res; switch(_res) { case MICROS: _gettime = micros; break; case MILLIS: _gettime = millis; break; case SECONDS: _gettime = seconds; break; default: _gettime = millis; break; } reset(); } void StopWatch::reset() { _state = StopWatch::RESET; _starttime = _stoptime = 0; } void StopWatch::start() { if (_state == StopWatch::RESET || _state == StopWatch::STOPPED) { _state = StopWatch::RUNNING; unsigned long t = _gettime(); _starttime += t - _stoptime; _stoptime = t; } } unsigned long StopWatch::value() { if (_state == StopWatch::RUNNING) _stoptime = _gettime(); return _stoptime - _starttime; } void StopWatch::stop() { if (_state == StopWatch::RUNNING) { _state = StopWatch::STOPPED; _stoptime = _gettime(); } } bool StopWatch::isRunning() { return (_state == StopWatch::RUNNING); } enum StopWatch::State StopWatch::state() { return _state; } // END OF FILE