Water System

Table of Contents

Week 18

Tube Adjustments and Water System Demo

  • Completion of soldering (pumps)
  • All power supplies plugged in.
  • Handling water ripple and splashing. Tested metal mesh which sunk. Tested foam board which still caused splashing. Decided to have tubes push against interior container wall to spill down instead of drip to negate splashing.
  • Further tweaking of program speeds and ranges.

Week 17

First full running test of water system.

  • Adjusted planter brace from Week 5 to hook onto water container.
  • Adjusting pump speeds and sensor ranges.
  • Reprinted all pump mount lids with vent holes. Reprinted main lid with white filament to reduce heat retained from sensors/pcb (compared to black filament).
  • Splashing from the water surface causes error with water level sensor readings due to rippling. Also poses risk of getting the sensor wet when the water level is high. Considering using mesh to dull ripples or act as a cover directly in front of the sensor.

Week 16

Water Level Detection Re-testing

  • Recalibrating (new) sensors after resoldering
  • Adjusting mounts and covers for pumps (vent holes and lenghtened cover)
  • Confirming water level sensor still behaves properly (video)

Week 15

  • Altered pump mount from https://www.thingiverse.com/thing:3356513
  • Mock set-up of overall project
  • Color-coded pump mounts
  • Adding ventilation to water container lids to balance humidity
  • Damaged sensors due to incorrect voltage provided. Reordered sensors.

Week 14

Video showcases extreme case testing on soldered circuit.

Extreme Case Main Loop if-else statement snippet. Reordered which extreme cases are checked first as only one can be fulfilled at once (Prioritizing Hydrate/Water Level to avoid overflow). Replaced generalizing function for checking water level condition with direct code due to logic errors in generalization.:

if(hydLowActive){ // case for LOW water level
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 255;
        removeWater = false;
        // checkExtremeCaseWaterDist(midWaterDistance);
        if(lastWaterDistReading <= midWaterDistance){ // checking for water rising, so it needs to meet at or above it (since water lvl starts already farther dist)
          setNormalState(); // reset extreme active cases and sensor timers
          bufferedOut.println("Finished extreme case.");
        }
      }
      else if(hydHighActive){ // case for HIGH water level
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 255;
        removeWater = true;
        // checkExtremeCaseWaterDist(midWaterDistance);
        if(lastWaterDistReading >= midWaterDistance){ // checking for water lowering, so it needs to meet at or below it (since water lvl starts already shorter dist)
          setNormalState(); // reset extreme active cases and sensor timers
          bufferedOut.println("Finished extreme case.");
        }
      }
      else if(socMaxActive){
        // set socialize at max behaviors
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 255;
        removeWater = true;
        // checkExtremeCaseWaterDist(waterDistToReach);
        if(lastWaterDistReading >= waterDistToReach){ // checking for water to reach down to so at or below it
          setNormalState(); // reset extreme active cases and sensor timers
          bufferedOut.println("Finished extreme case.");
        }
      }
      else if(socMinActive){
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 255;
        removeWater = true;
        // checkExtremeCaseWaterDist(waterDistToReach);
        if(lastWaterDistReading >= waterDistToReach){ // checking for water to reach down to so at or below it
          setNormalState(); // reset extreme active cases and sensor timers
          bufferedOut.println("Finished extreme case.");
        }
      }
      else if(creMaxActive){ // yellow runs alone at max
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 255;
        waterSpeed = 0;
        removeWater = true;
      }
      else if(creMinActive){
        magentaSpeed = 255;
        cyanSpeed = 255;
        yellowSpeed = 0;
        waterSpeed = 0;
        removeWater = true;
      }
      else{
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 0;
        removeWater = true;
      }
    }

RGB LED indicator is set when extreme case is set. However, if more than one extreme were to be triggered in the same loop iteration, the last to be called would be set (Socialize-->Hydrate-->Create) even if the extreme case that runs does not match the color coding (Hydrate>Socialize>Create):

void setExtremeState(int delayTime){
  extremeCaseActive = true;
 
  pirSonarDelay.stop();
  // waterSonarDelay.stop(); // dont use, never stop sonar bc itll be used to determine length of extreme state
  floatDelay.stop();
  printOutTimer.stop(); // stopped in an extreme case to reflect the cut off of communication in an overwhelmed or underwhelmed system
  extremeBlockDelay.start(delayTime);
}

if (socialize > SOCIALIZERANGE) { 
    // upper bound
    socialize = (BASESOCIALIZE * 9) / 10; // reduce to slightly below base 90%

    socMaxActive = true;
    setExtremeState(0);
    // water is going to be removed
    if(lastWaterDistReading >= (farthestDistanceToWater - 6)){ // 6mm error; bc water is to be removed, have to check if the water is too low or not
      setNormalState(); // water is too low to remove any further, skip extreme case (should trigger water case instead)
    }
    else{
      waterDistToReach = (lastWaterDistReading * 3) / 2;
      if(waterDistToReach >= farthestDistanceToWater){
        waterDistToReach = farthestDistanceToWater;
      }
      bufferedOut.println("Max Socialize Set");
      digitalWrite(REDPIN, HIGH); //red led
      digitalWrite(GREENPIN, LOW);
      digitalWrite(BLUEPIN, LOW);
    }
    
  }
  else if (socialize < 0) { 
    // hit the lower bound
    socialize = BASESOCIALIZE / 10; // it learned some self love or smth
   
    socMinActive = true;
    setExtremeState(0);
    // water to be removed
    if(lastWaterDistReading >= (farthestDistanceToWater - 6)){ // 6mm error; bc water is to be removed, have to check if the water is too low or not
      setNormalState(); // water is too low to remove any further, skip extreme case (should trigger water case instead)
    }
    else{
      waterDistToReach = (lastWaterDistReading * 5) / 4;
      if(waterDistToReach >= farthestDistanceToWater){
        waterDistToReach = farthestDistanceToWater;
      }
      bufferedOut.println("Min Socialize Set");
      digitalWrite(REDPIN, HIGH); //magenta led
      digitalWrite(GREENPIN, LOW);
      digitalWrite(BLUEPIN, HIGH);
    }
}

Week 13

Week 12

  • Temporary lids printed for testing purposes. Filed-down to fit sensors and pumps due to mis-sizing.
  • Makerspace helped resize the original mason jar pump lid by horizontally scaling it, though the holes in the lid have to be sized back to the original lid size.
  • Issues with the MB sonar sensor mount due to placement of the sensor and screws. Altered the PIR mount file for the sonar file. Opened back of sensor mount to allow wires to go through.
  • Redesigned main tank lid and fixed mason jar lid holes.

Week 11

Adjustments:

  • Use a tank larger than the total liquid volume possible for each dye container and main tank as a backup tank holding water that gets added to and removed from the main tank (a 5 gallon water container as opposed to a jar that would have been the same size as the dye containers), in order to avoid an additional sensor for checking for overflow in the backup container.
  • Decision to use 64oz mason jars to hold dyes and a tall, narrow vase as the main tank (to allow for the water level to change more given an amount of volume added).
  • Alterations to pump mounting lids and sensor mounts for 3D print due to size mismatches and missing features.

Sensor 3D Models:

Week 10

Testing MB1644 sensor.

Code also corrected for manual button on/off and overflow detection due to misplaced function calls.

Water level measuring code:

int readWaterSonar(){ 
  // hrlv shortrange mb1644
  if(waterSonarDelay.justFinished()){ // mb1644
    waterSonarDelay.repeat();
    int distancemm = (analogRead(WATERSONARPIN) * 6) - 300; // directly from maxbotix doc; mm reading
    lastWaterDistReading = distancemm; // always record last reading in global var
    return distancemm;
  }
  else{
    return -1;
  }
}

Code for extreme cases with escape conditions based on water level or time elapsed (Extreme case main loop if-else statement snippet). Unsuccessful implementation until later testing (See Week 14):

if(socMaxActive){
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 255;
        removeWater = true;
        checkExtremeCaseWaterDist();
      }
      else if(socMinActive){
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 255;
        removeWater = true;
        checkExtremeCaseWaterDist();
      }
      else if(hydLowActive){ // case for LOW water level
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 255;
        removeWater = false;
        checkExtremeCaseWaterDist();
      }
      else if(hydHighActive){ // case for HIGH water level
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 255;
        removeWater = true;
        checkExtremeCaseWaterDist();
      }
      else if(creMaxActive){
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 255;
        waterSpeed = 90; 
        removeWater = true;
      }
      else if(creMinActive){
        magentaSpeed = 255;
        cyanSpeed = 255;
        yellowSpeed = 0;
        waterSpeed = 90;
        removeWater = true;
      }
      else{
        magentaSpeed = 0;
        cyanSpeed = 0;
        yellowSpeed = 0;
        waterSpeed = 0;
        removeWater = true;
      }

Week 9

Ultrasonic Sensor Incorporation into PIR sensor reading function for sensing proximity of visitors (snippet):

void readPIRSonar(){
  // read PIR and sonar at the same time
  if(pirSonarDelay.justFinished()){
    pirSonarDelay.repeat();
    int pirState = digitalRead(PIRPIN);
    // distance accord to https://maxbotix.com/blogs/blog/arduino-guide
    int distance = analogRead(PPLSONARPIN) / 2; // inches, distance
    pirSonarInfo[0] = pirState; // 0/1
    pirSonarInfo[1] = distance; // inches
  }
  else{
    pirSonarInfo[0] = -1;
    pirSonarInfo[1] = -1;
  }
}

3D Print Mason Jar Pump Mount: https://www.thingiverse.com/thing:4823002

Week 8

Video of testing magenta and yellow pumps running and add/remove water pump.

Week 7

Video of LED-tested two-pump behavior with manual system on/off button.

Major changes:

  1. Planning to use short-range ultrasonic sensor for measuring water level instead of calculating in program due to challenging variables in calculating water volume vs. water level mathematically (different shapes of tanks, unideal variations in pumps running).
  2. Planning to use long-range ultrasonic sensor for detecting proximity of people in the gallery space (for affecting socialization factor/variable) instead of capacitive sensor because it would be more straightforward and precise.

Week 6

Video of LED-tested incrementing PWM output and code for continuous pump running.

Major Change: Shifting code from custom libraries to all written in Arduino IDE with non-blocking delays and continuously running pumps.

Week 5

Week 5 Code Progress tested on one pump and one LED acting in place of a second pump.

Week 4

Pump incrementally turns up its speed based on PIR sensor input, stays on for a period of time to add the liquid (to-be dye), then decrements to turn off.