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:
joran
Date:
Wed Jun 15 07:25:53 2016 +0000
Revision:
40:1668630544c7
Parent:
38:930469a33001
Child:
44:7c932cc5991b
Do not raise alarm for temp if we are heating, do not raise alarm for salt if we are pumping. I might have broken testing.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sbouber1 28:f4a4ee58d57e 1 #include "PIDController.h"
sbouber1 35:c9261391a995 2 #include "testing.h"
sbouber1 35:c9261391a995 3
sbouber1 35:c9261391a995 4 DigitalOut heater(p18);
sbouber1 28:f4a4ee58d57e 5
sbouber1 32:1e4919a44196 6 DRV8825 mtr_fresh(p21, p27, p28, p29, p22, p23);
sbouber1 32:1e4919a44196 7 DRV8825 mtr_salt(p24, p27, p28, p29, p25, p26);
sbouber1 32:1e4919a44196 8
sbouber1 32:1e4919a44196 9
sbouber1 28:f4a4ee58d57e 10 // This is called in the main loop on every iteration
sbouber1 28:f4a4ee58d57e 11 void PIDController::update() {
sbouber1 35:c9261391a995 12
sbouber1 38:930469a33001 13 #ifndef RUN_TESTS
sbouber1 38:930469a33001 14 if(this->num_iters < STARTUP_ITERATIONS) {
sbouber1 38:930469a33001 15 printf("PIDController: not running, startup phase");
sbouber1 38:930469a33001 16 return;
sbouber1 38:930469a33001 17 }
sbouber1 38:930469a33001 18 #endif
sbouber1 38:930469a33001 19
sbouber1 35:c9261391a995 20 // Control the heater
sbouber1 35:c9261391a995 21 // This could be done in the pumping function as well, if needed
sbouber1 36:8aeb014bd651 22 this->set_heating(this->temp->getValue() < 32.0f);
sbouber1 35:c9261391a995 23
sbouber1 28:f4a4ee58d57e 24 float s = this->salt->getValue();
sbouber1 32:1e4919a44196 25 float sInGrams = this->getSaltInGrams();
sbouber1 30:cf12566013a5 26
sbouber1 32:1e4919a44196 27 if(s <= 6.0) {
sbouber1 30:cf12566013a5 28
sbouber1 32:1e4919a44196 29 float ml = this->getMlSaltyWater(sInGrams, this->proximity->getValue());
sbouber1 35:c9261391a995 30 int ml_int = static_cast<int>(ml);
sbouber1 30:cf12566013a5 31
sbouber1 35:c9261391a995 32 printf("PIDCONTROLLER: need to pump %d (%.3f) ml of salty water\r\n", ml_int, ml);
sbouber1 30:cf12566013a5 33
sbouber1 35:c9261391a995 34 //this->pump_salt_water(ml_int);
sbouber1 30:cf12566013a5 35
sbouber1 32:1e4919a44196 36 } else if(s >= 9.0) {
sbouber1 32:1e4919a44196 37
sbouber1 32:1e4919a44196 38 float ml = this->getMlFreshWater(s, this->proximity->getValue());
sbouber1 35:c9261391a995 39 int ml_int = static_cast<int>(ml);
sbouber1 32:1e4919a44196 40
sbouber1 35:c9261391a995 41 printf("PIDCONTROLLER: need to pump %d (%.3f) ml of fresh water\r\n", ml_int, ml);
sbouber1 35:c9261391a995 42
sbouber1 35:c9261391a995 43 //this->pump_fresh_water(ml_int);
sbouber1 32:1e4919a44196 44
sbouber1 30:cf12566013a5 45 }
sbouber1 28:f4a4ee58d57e 46 }
sbouber1 28:f4a4ee58d57e 47
sbouber1 28:f4a4ee58d57e 48 std::string PIDController::get_name() {
sbouber1 30:cf12566013a5 49 return "PIDController";
sbouber1 28:f4a4ee58d57e 50 }
sbouber1 28:f4a4ee58d57e 51
joran 29:2b256a7ce0ae 52 //get the salt in the body in grams
joran 29:2b256a7ce0ae 53 float PIDController::getSaltInGrams()
joran 29:2b256a7ce0ae 54 {
joran 29:2b256a7ce0ae 55 float currentppt = this->salt->getValue(); //in ppt
joran 29:2b256a7ce0ae 56 float currentvol = this->proximity->getValue(); //in ml
joran 29:2b256a7ce0ae 57
sbouber1 35:c9261391a995 58 return currentppt * (currentvol / 1000);
joran 29:2b256a7ce0ae 59 }
joran 29:2b256a7ce0ae 60
joran 29:2b256a7ce0ae 61
sbouber1 32:1e4919a44196 62 void PIDController::pump_salt_water(int ml) {
sbouber1 32:1e4919a44196 63 this->pump_water(&mtr_salt, ml);
sbouber1 32:1e4919a44196 64 }
sbouber1 32:1e4919a44196 65
sbouber1 32:1e4919a44196 66
sbouber1 32:1e4919a44196 67 void PIDController::pump_fresh_water(int ml) {
sbouber1 32:1e4919a44196 68 this->pump_water(&mtr_fresh, ml);
sbouber1 32:1e4919a44196 69 }
sbouber1 32:1e4919a44196 70
sbouber1 32:1e4919a44196 71 void PIDController::pump_water(DRV8825 *mtr, int ml) {
joran 40:1668630544c7 72 this->pumping = true;
sbouber1 32:1e4919a44196 73 int j = 5010 * (ml - 1);
sbouber1 32:1e4919a44196 74
sbouber1 32:1e4919a44196 75 for (int i = 500; i < MAX_SPEED; i += 5) {
sbouber1 32:1e4919a44196 76 mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, i);
sbouber1 32:1e4919a44196 77 }
sbouber1 32:1e4919a44196 78
sbouber1 32:1e4919a44196 79 for (int i = 0; i < 2010 + j; i += 1) {
sbouber1 32:1e4919a44196 80 mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, 8000);
sbouber1 32:1e4919a44196 81 }
sbouber1 32:1e4919a44196 82
sbouber1 32:1e4919a44196 83 for (int i = 8000; i > 500; i -= 5) {
sbouber1 32:1e4919a44196 84 mtr->settings(1 / MICROSTEPS_PER_STEP, LEFT, i);
sbouber1 32:1e4919a44196 85 }
sbouber1 32:1e4919a44196 86
sbouber1 32:1e4919a44196 87 wait(3);
sbouber1 32:1e4919a44196 88
sbouber1 32:1e4919a44196 89 for (int i = 500; i < MAX_SPEED; i += 5) {
sbouber1 32:1e4919a44196 90 mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, i);
sbouber1 32:1e4919a44196 91 }
sbouber1 32:1e4919a44196 92
sbouber1 32:1e4919a44196 93 for (int i = 0; i < 2010 + j; i += 1) {
sbouber1 32:1e4919a44196 94 mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, 8000);
sbouber1 32:1e4919a44196 95 }
sbouber1 32:1e4919a44196 96
sbouber1 32:1e4919a44196 97 for (int i = 8000; i > 500; i -= 5) {
sbouber1 32:1e4919a44196 98 mtr->settings(1 / MICROSTEPS_PER_STEP, RIGHT, i);
sbouber1 32:1e4919a44196 99 }
sbouber1 32:1e4919a44196 100
sbouber1 35:c9261391a995 101 wait(3);
joran 40:1668630544c7 102 this->pumping = false;
sbouber1 32:1e4919a44196 103 }
sbouber1 32:1e4919a44196 104
sbouber1 32:1e4919a44196 105
sbouber1 32:1e4919a44196 106 float PIDController::getMlSaltyWater(float gramsinbody, float volumeinbody) {
sbouber1 32:1e4919a44196 107
sbouber1 32:1e4919a44196 108 float solvolume = 10; // 10ml
sbouber1 32:1e4919a44196 109
sbouber1 32:1e4919a44196 110 float idealpptconstant = 0.007f; //7 ppt / 1000
sbouber1 32:1e4919a44196 111 float x1 = volumeinbody * idealpptconstant;
sbouber1 32:1e4919a44196 112 float x2 = solvolume * idealpptconstant;
sbouber1 32:1e4919a44196 113
sbouber1 32:1e4919a44196 114 x1 = x1 - gramsinbody;
sbouber1 32:1e4919a44196 115 x2 = 1 - x2;
sbouber1 32:1e4919a44196 116
sbouber1 32:1e4919a44196 117 float outputml = (x1 / x2 * solvolume);
sbouber1 32:1e4919a44196 118
sbouber1 32:1e4919a44196 119 return outputml; // amount in ml to get 7 ppt.
sbouber1 35:c9261391a995 120 }
sbouber1 35:c9261391a995 121
sbouber1 35:c9261391a995 122 bool PIDController::is_heating() {
sbouber1 35:c9261391a995 123 return this->heating;
sbouber1 35:c9261391a995 124 }
sbouber1 35:c9261391a995 125
joran 40:1668630544c7 126 bool PIDController::is_pumping() {
joran 40:1668630544c7 127 return this->pumping;
joran 40:1668630544c7 128 }
joran 40:1668630544c7 129
sbouber1 35:c9261391a995 130 void PIDController::set_heating(bool enabled) {
sbouber1 35:c9261391a995 131 if(enabled == this->heating) return;
sbouber1 35:c9261391a995 132
sbouber1 35:c9261391a995 133 this->heating = enabled;
sbouber1 35:c9261391a995 134 if(enabled) {
sbouber1 35:c9261391a995 135 #ifdef RUN_TESTS
sbouber1 35:c9261391a995 136 printf("Should set heater to 1\r\n");
sbouber1 35:c9261391a995 137 #else
sbouber1 35:c9261391a995 138 heater = 1;
sbouber1 35:c9261391a995 139 #endif
sbouber1 35:c9261391a995 140 } else {
sbouber1 35:c9261391a995 141 #ifdef RUN_TESTS
sbouber1 35:c9261391a995 142 printf("Should set heater to 0\r\n");
sbouber1 35:c9261391a995 143 #else
sbouber1 35:c9261391a995 144 heater = 0;
sbouber1 35:c9261391a995 145 #endif
sbouber1 32:1e4919a44196 146 }
sbouber1 35:c9261391a995 147 }
sbouber1 32:1e4919a44196 148
sbouber1 32:1e4919a44196 149 float PIDController::getMlFreshWater(float ppt, float volume) {
sbouber1 32:1e4919a44196 150 return (volume * (ppt / 7.0)) - volume;
sbouber1 32:1e4919a44196 151 }
sbouber1 32:1e4919a44196 152