GMU:CyberSpace/electrochemical closed circuit system

From Medien Wiki

Electrochemicalsystem.01.JPG

Material:

Wood
Plexiglas cylinder
Copperbar massive
Coppersulfatesolution
Arduino Uno
Powersupply 12V 2.1A DC
3x Resitor 2.2Ω
6x Relais


Diagram:

Diagram cb.png



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