Tuesday, December 13, 2011

Two Steps Forward, One Step Back

        Some good news, some not so good news. We were able to find solutions to both the breadboard and water bottle issues! That's a huge relief. It turns out I actually did know what I was doing when I was using the breadboard. I was right about the entire circuit the only problem was I had used a resister with a resistance much larger than was necessary. My friend explained to me I = V/R and that I need to use the right resistance in order for the LED to get enough current to actually turn on. I also will need to use resistors when ever I use sensors that have varying values in order to get an accurate reading. Also, I found out that if I connect the Ground pin to one of the rows at the bottom and the 5V pin to the other row then the entire row will be ground and the other one will all be 5V. That's a huge relief because I was really getting worried about how we'd fit all these wires into the single pin on the Arduino. Once I changed the resistor on the circuit I had made I was able to get the entire system to work! Now all we had to do was use the water level sensor instead of the force sensor.
        In the meantime, Sophie had figured out how we're going to get our water bottle working. It turns out Camelbak water bottles have breathable lids that allow air in while letting water out. This way, when we drink out of the container the amount of air in the pack won't change. We bought a Nalgene water pack that has a regular water bottle lid on it, switched it with a Camelbak lid, and connected it to a long tube to drink through. We also cut a hole in the side of the pack and inserted our water level sensor. The whole system seemed to be working when we used our test code! :)
        Next, Sophie and I walked through how we wanted the programming side of the system to work. She had a rather complicated suggestion that involved using different classes for different sensors but I was convinced we could come up with something quite simple and elegant that would hopefully work just as well. I definitely understand now why Takis always told us it's better to spend hours planning out code and only thirty minutes actually writing it because if we had just written our first idea it would have been a huge headache to debug the code and figure out what was wrong. Instead, Sophie and I brainstormed how the program should run, wrote and re-wrote pseudocode on the board, and walked through every line of the pseudocode until we felt confident it would work. Once I actually sat down to write the code it took less than thirty minutes to write and it worked the first time I compiled and uploaded it! I'm quite proud of myself for that one. 
        I came up with a relatively simple way of tracking how much water had been drunk. I decided we should have keep track of the initial water level and then check every five minutes if the water level has dropped. If the water level has dropped, the amount it has fallen is added to a cupsdrunk integer and the new water level is saved to be compared to next time. Every five minutes, when the water level is tested, the program checks if the water level changes a significant amount over a five second interval to determine whether the value is a reliable datapoint or if the wearer is likely just moving around a lot and causing the water level to rise and fall. It has been proven that drinking eight cups of water a day is considered healthy and we want the wearer to have a grace-period for when they have to drink all their water so, every six hours, the program subtracts the liquid level sensor's equivalent of two cups of water from the cupsdrunk variable. If the cupsdrunk integer is negative, that means the wearer has not drunk two cups of water in the last two hours and the LED changes from blue to pink. If at anytime the integer is positive, the LED will change back from pink to blue. 
        Something I really like about this implementation is that it can easily be transferred from the water bottle to measuring exercise and sleep. It also allows the wearer to drink an excess amount of water and not be reminded to drink water until much later. The way I think of it, the program almost works like a bank. If you are in water-intake debt you will need to drink extra in order to make up for it. If, however, you drink a lot of water all at once, you will have a surplus and will not have to worry about drinking water again until your savings run out. Below is the code for the water intake sensor and LEDs:


    #define LSR 0
    #define blueLED 11
    #define redLED 2
    #define SliSwi 0 
    
    #include <Time.h>  
    
    #define TIME_MSG_LEN  11   // time sync to PC is HEADER followed by Unix time_t as ten ASCII digits
    #define TIME_HEADER  'T'   // Header tag for serial time sync message
    #define TIME_REQUEST  7    // ASCII bell character requests a time sync message 
    
    int lsrReading;
    int lastWaterLevel;
    int cupsdrunk;
    int fivmin;
    int sixhrs;
    
    void setup(void)
    {
      Serial.begin(9600);
      pinMode(LSR, INPUT); 
      pinMode(blueLED, OUTPUT); 
      pinMode(redLED, OUTPUT);
      pinMode(SliSwi, INPUT);
      lastWaterLevel = analogRead(LSR);
      cupsdrunk = 0;
      fivmin = 0;
      sixhrs = 0;
    }
    
    void loop(void)
    {
      lsrReading = analogRead(LSR);
      
      if (second()==0)
      {
        fivmin++; 
        sixhrs++;
      }
      if (fivmin==5)
      {
        getLiquidChange();
      }
      if (sixhrs == 360)
      {
       cupsdrunk = (cupsdrunk - 90);
      sixhrs = 0;
     if (cupsdrunk >= 0)
    {
      digitalWrite(blueLED, HIGH);
      digitalWrite(redLED, LOW);
    } else {
      digitalWrite(blueLED, LOW);
      digitalWrite(redLED, HIGH);
    }
      }
      if (cupsdrunk >= 0) 
      {
        digitalWrite(blueLED, HIGH);
      digitalWrite(redLED, LOW);
      }
      
    /*  if (lsrReading > 500)
      {
        digitalWrite(blueLED, HIGH);
        digitalWrite(redLED, LOW);
      } else if (lsrReading < 500)
      {
        digitalWrite(blueLED, LOW);
        digitalWrite(redLED, HIGH);
      }*/
      
      Serial.print("Analog reading = ");
      Serial.println(lsrReading);
        
      digitalClockDisplay();  
      Serial.println(second());
      
      Serial.print("cupsdrunk = ");
      Serial.println(cupsdrunk);
      
      Serial.print("lastWaterLevel = ");
      Serial.println(lastWaterLevel);
      
      Serial.print("fivmin = ");
      Serial.println(fivmin);
      
      Serial.print("sixhrs = ");
      Serial.println(sixhrs);
      
      delay(950);
    }
    
    void getLiquidChange()
    {
      int level1 = analogRead(LSR);
      int lwrbnd = (level1 - 10);
      int uprbnd = (level1 + 10);
      delay(4000); 
      int level2 = analogRead(LSR);
      if (level2 >= lwrbnd && level2 <= uprbnd)
      {
        if (level2 < lastWaterLevel) 
        {
          Serial.print("level2 = ");
          Serial.println(level2);
          cupsdrunk = cupsdrunk + (lastWaterLevel - level2);
        }
        lastWaterLevel = level2;
      }
      fivmin = 0;
    }
    
    void digitalClockDisplay(){
      // digital clock display of the time
      Serial.print(hour());
      printDigits(minute());
      printDigits(second());
      Serial.print(" ");
      Serial.print(day());
      Serial.println(); 
    }
    
    void printDigits(int digits){
      // utility function for digital clock display: prints preceding colon and leading 0
      Serial.print(":");
      if(digits < 10)
        Serial.print('0');
      Serial.print(digits);
    }

        Unfortunately, in the middle of the night after Sophie and I had finally gotten everything to work, we watched tragically as the input from the water level sensor suddenly dropped from its normal reading down to zero. Whenever we tried to adjust anything, the sensor simply gives in completely random data that doesn't make any sense given the thresholds we calculated while it was still working. It was extremely discouraging for both of us, especially because we had just gotten it to work and we had no idea what went wrong. 
        The next morning I talked with Orit and she explained to me the difference between working with hardware and programming only on the computer. When working with the computer, it is fairly predictable and you can debug and know when it doesn't work it is likely something you have done wrong. When working with hardware, however, you spend a lot of your time troubleshooting and trying to determine whether you've made the error or whether your hardware is simply malfunctioning. In our case, it seems fairly clear the problem lies with the hardware, especially since it was working perfectly and then all of a sudden it stopped right before our eyes even though we didn't make any changes to it. We will be ordering a new water level sensor and implementing that as soon as we can. 
        In the meantime, I installed a flex sensor instead in order to give a demo to our class of reading input and getting feedback using the blue and pink LEDs. I only had to change a few thresholds in the code and it was good to go. Whenever I hold the flex sensor so that the reading is below the last reading, the program thinks I've drunk water. But if the flex sensor stays at the same level or gets higher for too long the LEDs turn pink and I need to drink some more water in order for them to turn blue. Here is a picture of me wearing the feasibility prototype that we presented during class. One person in the hallway asked me if I was a human time bomb. Hehe. 
IMG_2585.jpgIMG_2586.jpg

No comments:

Post a Comment