Timelapse Setup:
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