Program for the water play project for the course Software Testing Practical 2016 given at the VU University
Dependencies: mbed DRV88255 TextLCD Ping mbed-rtos
PIDController.cpp
- Committer:
- sbouber1
- Date:
- 2016-06-24
- Revision:
- 80:38e274c4dafa
- Parent:
- 78:a44ad011dd41
File content as of revision 80:38e274c4dafa:
#include "PIDController.h"
#include "LCDController.h"
static DigitalOut heater(p18);
static DRV8825 mtr_fresh(p21, p27, p28, p29, p22, p23);
static DRV8825 mtr_salt(p24, p27, p28, p29, p25, p26);
// Make sure heater is off
PIDController::~PIDController() {
printf("PIDController destructor called, heater = 0\r\n");
heater = 0;
}
// This is called in the main loop on every iteration
void PIDController::update() {
#ifndef TEST_MODE
if(this->num_iters < STARTUP_ITERATIONS) {
printf("PIDController: not running, startup phase");
return;
}
#endif
// Control the heater
// This could be done in the pumping function as well, if needed
if (this->isHeating() && this->temp->getValue() >= TEMP_MIN_UNDESIRED + 1.0f) {
this->setHeating(false);
} else if (!this->isHeating() && this->temp->getValue() < TEMP_MIN_UNDESIRED) {
this->setHeating(true);
}
float s = this->salt->getValue();
float s_in_grams = this->getSaltInGrams();
if(s < MIN_VALID_SALINITY) {
cout << "PIDController: Salinity NC, no stabilizing action";
} else if(s <= SALT_MIN_UNDESIRED) {
float ml = this->getMlSaltyWater(s_in_grams, this->proximity->getValue());
int ml_int = std::min(static_cast<int>(ml), 30);
ml_int = std::max(1, ml_int);
cout << "PIDCONTROLLER: need to pump " << ml_int << " (" << ml << ")" << " ml of salty water\r\n";
printf("need to pump %d ml of salty water\r\n",ml_int);
this->pumpSaltWater(ml_int);
} else if(s >= SALT_MAX_UNDESIRED) {
float ml = this->getMlFreshWater(s, this->proximity->getValue());
int ml_int = std::min(static_cast<int>(ml), 30);
ml_int = std::max(1, ml_int);
cout << "PIDCONTROLLER: need to pump " << ml_int << " (" << ml << ")" << " ml of fresh water\r\n";
printf("need to pump %d ml of fresh water\r\n",ml_int);
this->pumpFreshWater(ml_int);
}
}
std::string PIDController::getName() {
return "PIDController";
}
//get the salt in the body in grams
float PIDController::getSaltInGrams() {
float current_ppt = this->salt->getValue(); //in ppt
float current_vol = this->proximity->getValue(); //in ml
return current_ppt * (current_vol / 1000);
}
void PIDController::pumpSaltWater(int ml) {
this->pumpWater(&mtr_salt, ml);
}
void PIDController::pumpFreshWater(int ml) {
this->pumpWater(&mtr_fresh, ml);
}
void PIDController::pumpWater(DRV8825 *mtr, int ml) {
LCDController::showPumping();
this->pumping = true;
int j = 5010 * (ml - 1);
for (int i = 500; i < MAX_SPEED; i += 5) {
mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, i);
}
for (int i = 0; i < 2010 + j; i += 1) {
mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, 8000);
}
for (int i = 8000; i > 500; i -= 5) {
mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, i);
}
wait(5);
for (int i = 500; i < MAX_SPEED; i += 5) {
mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, i);
}
for (int i = 0; i < 2010 + j; i += 1) {
mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, 8000);
}
for (int i = 8000; i > 500; i -= 5) {
mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, i);
}
wait(5);
this->pumping = false;
}
float PIDController::getMlSaltyWater(float grams_in_body, float volume_in_body) {
float solution_gram_per_ten = 1.16f; // 1.0f for our solution
float sol_volume = 10; // 10ml
float ideal_ppt_constant = 0.007f; //7 ppt / 1000
float x1 = volume_in_body * ideal_ppt_constant;
float x2 = sol_volume * ideal_ppt_constant;
x1 = x1 - grams_in_body;
x2 = solution_gram_per_ten - x2;
float output_ml = (x1 / x2 * sol_volume);
return output_ml; // amount in ml to get 7 ppt.
}
bool PIDController::isHeating() {
return this->heating;
}
bool PIDController::isPumping() {
return this->pumping;
}
void PIDController::setHeating(bool enabled) {
if(enabled == this->heating) return;
this->heating = enabled;
if(enabled) {
#ifdef TEST_MODE
printf("Should set heater to 1\r\n");
#else
heater = 1;
#endif
} else {
#ifdef TEST_MODE
printf("Should set heater to 0\r\n");
#else
heater = 0;
#endif
}
}
float PIDController::getMlFreshWater(float ppt, float volume) {
return (volume * (ppt / 7.0)) - volume;
}
void PIDController::doTestingStuff(int ml) {
while(1) {
this->pumpSaltWater(ml);
//this->pumpFreshWater(ml);
}
}