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

Committer:
sbouber1
Date:
Fri Jun 24 13:51:42 2016 +0000
Revision:
80:38e274c4dafa
Parent:
78:a44ad011dd41
final

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sbouber1 28:f4a4ee58d57e 1 #include "PIDController.h"
sbouber1 46:7e4c1f2ab76c 2 #include "LCDController.h"
sbouber1 35:c9261391a995 3
sbouber1 57:8dc3192ff150 4 static DigitalOut heater(p18);
sbouber1 28:f4a4ee58d57e 5
sbouber1 57:8dc3192ff150 6 static DRV8825 mtr_fresh(p21, p27, p28, p29, p22, p23);
sbouber1 57:8dc3192ff150 7 static DRV8825 mtr_salt(p24, p27, p28, p29, p25, p26);
joran 44:7c932cc5991b 8
joran 44:7c932cc5991b 9
sbouber1 78:a44ad011dd41 10 // Make sure heater is off
sbouber1 78:a44ad011dd41 11 PIDController::~PIDController() {
sbouber1 78:a44ad011dd41 12 printf("PIDController destructor called, heater = 0\r\n");
sbouber1 78:a44ad011dd41 13 heater = 0;
sbouber1 78:a44ad011dd41 14 }
sbouber1 78:a44ad011dd41 15
sbouber1 28:f4a4ee58d57e 16 // This is called in the main loop on every iteration
sbouber1 28:f4a4ee58d57e 17 void PIDController::update() {
sbouber1 35:c9261391a995 18
sbouber1 57:8dc3192ff150 19 #ifndef TEST_MODE
sbouber1 38:930469a33001 20 if(this->num_iters < STARTUP_ITERATIONS) {
sbouber1 38:930469a33001 21 printf("PIDController: not running, startup phase");
sbouber1 38:930469a33001 22 return;
sbouber1 38:930469a33001 23 }
sbouber1 38:930469a33001 24 #endif
sbouber1 38:930469a33001 25
sbouber1 35:c9261391a995 26 // Control the heater
sbouber1 35:c9261391a995 27 // This could be done in the pumping function as well, if needed
joran 63:59335eb8bdbc 28 if (this->isHeating() && this->temp->getValue() >= TEMP_MIN_UNDESIRED + 1.0f) {
sbouber1 57:8dc3192ff150 29 this->setHeating(false);
joran 62:52cceb263591 30 } else if (!this->isHeating() && this->temp->getValue() < TEMP_MIN_UNDESIRED) {
sbouber1 57:8dc3192ff150 31 this->setHeating(true);
joran 49:ca6fb19fc280 32 }
sbouber1 35:c9261391a995 33
sbouber1 28:f4a4ee58d57e 34 float s = this->salt->getValue();
sbouber1 57:8dc3192ff150 35 float s_in_grams = this->getSaltInGrams();
sbouber1 30:cf12566013a5 36
sbouber1 65:b277b4067d4a 37 if(s < MIN_VALID_SALINITY) {
sbouber1 65:b277b4067d4a 38 cout << "PIDController: Salinity NC, no stabilizing action";
sbouber1 65:b277b4067d4a 39 } else if(s <= SALT_MIN_UNDESIRED) {
sbouber1 30:cf12566013a5 40
sbouber1 57:8dc3192ff150 41 float ml = this->getMlSaltyWater(s_in_grams, this->proximity->getValue());
sbouber1 70:642153418c6e 42 int ml_int = std::min(static_cast<int>(ml), 30);
sbouber1 70:642153418c6e 43 ml_int = std::max(1, ml_int);
sbouber1 30:cf12566013a5 44
sbouber1 65:b277b4067d4a 45 cout << "PIDCONTROLLER: need to pump " << ml_int << " (" << ml << ")" << " ml of salty water\r\n";
sbouber1 71:38bb6bf09933 46 printf("need to pump %d ml of salty water\r\n",ml_int);
sbouber1 30:cf12566013a5 47
sbouber1 71:38bb6bf09933 48 this->pumpSaltWater(ml_int);
sbouber1 30:cf12566013a5 49
joran 63:59335eb8bdbc 50 } else if(s >= SALT_MAX_UNDESIRED) {
sbouber1 32:1e4919a44196 51
sbouber1 32:1e4919a44196 52 float ml = this->getMlFreshWater(s, this->proximity->getValue());
sbouber1 70:642153418c6e 53 int ml_int = std::min(static_cast<int>(ml), 30);
sbouber1 70:642153418c6e 54 ml_int = std::max(1, ml_int);
sbouber1 32:1e4919a44196 55
sbouber1 65:b277b4067d4a 56 cout << "PIDCONTROLLER: need to pump " << ml_int << " (" << ml << ")" << " ml of fresh water\r\n";
sbouber1 71:38bb6bf09933 57 printf("need to pump %d ml of fresh water\r\n",ml_int);
sbouber1 35:c9261391a995 58
sbouber1 71:38bb6bf09933 59 this->pumpFreshWater(ml_int);
sbouber1 32:1e4919a44196 60
sbouber1 30:cf12566013a5 61 }
sbouber1 28:f4a4ee58d57e 62 }
sbouber1 28:f4a4ee58d57e 63
sbouber1 57:8dc3192ff150 64 std::string PIDController::getName() {
sbouber1 30:cf12566013a5 65 return "PIDController";
sbouber1 28:f4a4ee58d57e 66 }
sbouber1 28:f4a4ee58d57e 67
joran 29:2b256a7ce0ae 68 //get the salt in the body in grams
sbouber1 57:8dc3192ff150 69 float PIDController::getSaltInGrams() {
sbouber1 57:8dc3192ff150 70 float current_ppt = this->salt->getValue(); //in ppt
sbouber1 57:8dc3192ff150 71 float current_vol = this->proximity->getValue(); //in ml
joran 29:2b256a7ce0ae 72
sbouber1 57:8dc3192ff150 73 return current_ppt * (current_vol / 1000);
joran 29:2b256a7ce0ae 74 }
joran 29:2b256a7ce0ae 75
joran 29:2b256a7ce0ae 76
sbouber1 57:8dc3192ff150 77 void PIDController::pumpSaltWater(int ml) {
sbouber1 57:8dc3192ff150 78 this->pumpWater(&mtr_salt, ml);
sbouber1 32:1e4919a44196 79 }
sbouber1 32:1e4919a44196 80
sbouber1 32:1e4919a44196 81
sbouber1 57:8dc3192ff150 82 void PIDController::pumpFreshWater(int ml) {
sbouber1 57:8dc3192ff150 83 this->pumpWater(&mtr_fresh, ml);
sbouber1 32:1e4919a44196 84 }
sbouber1 32:1e4919a44196 85
sbouber1 57:8dc3192ff150 86
sbouber1 57:8dc3192ff150 87 void PIDController::pumpWater(DRV8825 *mtr, int ml) {
joran 44:7c932cc5991b 88 LCDController::showPumping();
sbouber1 57:8dc3192ff150 89
joran 40:1668630544c7 90 this->pumping = true;
sbouber1 57:8dc3192ff150 91
sbouber1 32:1e4919a44196 92 int j = 5010 * (ml - 1);
sbouber1 32:1e4919a44196 93
sbouber1 32:1e4919a44196 94 for (int i = 500; i < MAX_SPEED; i += 5) {
sbouber1 46:7e4c1f2ab76c 95 mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, i);
sbouber1 46:7e4c1f2ab76c 96 }
sbouber1 46:7e4c1f2ab76c 97
sbouber1 46:7e4c1f2ab76c 98 for (int i = 0; i < 2010 + j; i += 1) {
sbouber1 46:7e4c1f2ab76c 99 mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, 8000);
sbouber1 46:7e4c1f2ab76c 100 }
sbouber1 46:7e4c1f2ab76c 101
sbouber1 46:7e4c1f2ab76c 102 for (int i = 8000; i > 500; i -= 5) {
sbouber1 46:7e4c1f2ab76c 103 mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, i);
sbouber1 46:7e4c1f2ab76c 104 }
sbouber1 46:7e4c1f2ab76c 105
sbouber1 46:7e4c1f2ab76c 106 wait(5);
sbouber1 46:7e4c1f2ab76c 107
sbouber1 46:7e4c1f2ab76c 108 for (int i = 500; i < MAX_SPEED; i += 5) {
sbouber1 32:1e4919a44196 109 mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, i);
sbouber1 32:1e4919a44196 110 }
sbouber1 32:1e4919a44196 111
sbouber1 32:1e4919a44196 112 for (int i = 0; i < 2010 + j; i += 1) {
sbouber1 32:1e4919a44196 113 mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, 8000);
sbouber1 32:1e4919a44196 114 }
sbouber1 32:1e4919a44196 115
sbouber1 32:1e4919a44196 116 for (int i = 8000; i > 500; i -= 5) {
sbouber1 32:1e4919a44196 117 mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, i);
sbouber1 32:1e4919a44196 118 }
sbouber1 32:1e4919a44196 119
sbouber1 46:7e4c1f2ab76c 120 wait(5);
joran 40:1668630544c7 121 this->pumping = false;
sbouber1 32:1e4919a44196 122 }
sbouber1 32:1e4919a44196 123
sbouber1 32:1e4919a44196 124
sbouber1 57:8dc3192ff150 125 float PIDController::getMlSaltyWater(float grams_in_body, float volume_in_body) {
sbouber1 32:1e4919a44196 126
sbouber1 57:8dc3192ff150 127 float solution_gram_per_ten = 1.16f; // 1.0f for our solution
sbouber1 57:8dc3192ff150 128 float sol_volume = 10; // 10ml
sbouber1 32:1e4919a44196 129
sbouber1 57:8dc3192ff150 130 float ideal_ppt_constant = 0.007f; //7 ppt / 1000
sbouber1 57:8dc3192ff150 131 float x1 = volume_in_body * ideal_ppt_constant;
sbouber1 57:8dc3192ff150 132 float x2 = sol_volume * ideal_ppt_constant;
sbouber1 32:1e4919a44196 133
sbouber1 57:8dc3192ff150 134 x1 = x1 - grams_in_body;
sbouber1 57:8dc3192ff150 135 x2 = solution_gram_per_ten - x2;
sbouber1 32:1e4919a44196 136
sbouber1 57:8dc3192ff150 137 float output_ml = (x1 / x2 * sol_volume);
sbouber1 32:1e4919a44196 138
sbouber1 57:8dc3192ff150 139 return output_ml; // amount in ml to get 7 ppt.
sbouber1 35:c9261391a995 140 }
sbouber1 35:c9261391a995 141
sbouber1 57:8dc3192ff150 142 bool PIDController::isHeating() {
sbouber1 35:c9261391a995 143 return this->heating;
sbouber1 35:c9261391a995 144 }
sbouber1 35:c9261391a995 145
sbouber1 57:8dc3192ff150 146 bool PIDController::isPumping() {
joran 40:1668630544c7 147 return this->pumping;
joran 40:1668630544c7 148 }
joran 40:1668630544c7 149
sbouber1 57:8dc3192ff150 150 void PIDController::setHeating(bool enabled) {
sbouber1 35:c9261391a995 151 if(enabled == this->heating) return;
sbouber1 35:c9261391a995 152
sbouber1 35:c9261391a995 153 this->heating = enabled;
sbouber1 35:c9261391a995 154 if(enabled) {
sbouber1 57:8dc3192ff150 155 #ifdef TEST_MODE
sbouber1 35:c9261391a995 156 printf("Should set heater to 1\r\n");
sbouber1 35:c9261391a995 157 #else
sbouber1 35:c9261391a995 158 heater = 1;
sbouber1 35:c9261391a995 159 #endif
sbouber1 35:c9261391a995 160 } else {
sbouber1 57:8dc3192ff150 161 #ifdef TEST_MODE
sbouber1 35:c9261391a995 162 printf("Should set heater to 0\r\n");
sbouber1 35:c9261391a995 163 #else
sbouber1 35:c9261391a995 164 heater = 0;
sbouber1 35:c9261391a995 165 #endif
sbouber1 32:1e4919a44196 166 }
sbouber1 35:c9261391a995 167 }
sbouber1 32:1e4919a44196 168
sbouber1 32:1e4919a44196 169 float PIDController::getMlFreshWater(float ppt, float volume) {
sbouber1 32:1e4919a44196 170 return (volume * (ppt / 7.0)) - volume;
sbouber1 32:1e4919a44196 171 }
sbouber1 32:1e4919a44196 172
sbouber1 46:7e4c1f2ab76c 173 void PIDController::doTestingStuff(int ml) {
sbouber1 71:38bb6bf09933 174 while(1) {
sbouber1 57:8dc3192ff150 175 this->pumpSaltWater(ml);
sbouber1 71:38bb6bf09933 176 //this->pumpFreshWater(ml);
sbouber1 71:38bb6bf09933 177 }
sbouber1 46:7e4c1f2ab76c 178 }
sbouber1 46:7e4c1f2ab76c 179