Schedule‎ > ‎

Lab 08: Using Sensor Data

Objectives

  • Practice using binary numbers of different sizes 
  • Understand how to make sense of real world input 

Academic Honesty

Read the Scholastic Honesty Policy and Assignment Integrity policies of the syllabus. Here are some clarifications for this particular assignment:
  • You may discuss the algorithm problem with other students but your solution must be significantly different from any other student in the class.
  • You may get help from others installing the compiler, as long as you actually perform all the steps yourself.

Part 1: Setup

Build the Pressure Sensor Project shown in the picture on the right. It contains a pressure sensor and an LED. The LED is connected to an "analog" output. The analogWrite() function uses PWM to approximate analog behavior. That's perfect for driving an LED to different levels of brightness. The code simply reads the analog input from the pressure sensor and writes the same value to the analog output.
name your file:  SqueezeTest.ino
Here's the code:

const int LED_PIN = 5;
const int SENSOR_PIN = 1;

void setup() {
  Serial.begin(9600);
}

void loop() {
  int value;
  value = analogRead(SENSOR_PIN);
  analogWrite(LED_PIN, value);

}


Put the circuit together to make sure it works. If it's correct the LED will be on when there's no pressure on the sensor.

Questions

  1. With no pressure on the sensor what does the LED do? 
  2. When you squeeze the sensor what happens to the LED?

Part 2: Compensating for Sensors

If you wired the circuit correctly the LED will behave strangely. Update your loop statement to print out the pressure sensor reading:


Open the serial monitor and do the following experiment:
    3.  What is the reading when there is no pressure?
    4.  What is the reading when you squeeze hard?

What's wrong with the LED circuit is that the input to analogWrite() is an 8-bit number but the analogRead() function returns a 10-bit number. In order to shrink the 10-bit number to an 8-bit number you have to shift the reading right by two positions. Here's how you do that:

value = value >> 2;

Changing the bit-ness of value should give you a nice, smooth transition. Let's make the light get brighter the harder you squeeze the sensor. Instead of reading from 0 to 255 we want to read from 255 to 0. Add this statement to reverse the reading: 

value = 255 - value; 

Now your LED should get brighter when you squeeze.

In Depth: Hysteresis

What if you wanted to make the pressure sensor work like a simple button? When you push the button you get a single click. In order to understand the next part you should understand hysteresis which is a way to use computer memory to correct problems with physical sensors. Try adding the following code to the end of your loop() function so it looks like this:


You will see a lot of PUSH! come up when you squeeze the sensor. No matter how quickly you squeeze the sensor it's impossible to see just one PUSH! Try it. When you squeeze the sensor the output fluctuates like the graph shown below: 

 
If you simply compare the value to a threshold you'll have "bouncy" readings (you'll turn on and off rapidly at times). But the problem is easy to fix if you have two thresholds. If the signal goes above the high threshold it turns on, if it goes below the low threshold it turns off, otherwise it stays the same. Keeping it the same means you will have to store information in a variable. 

Part 3: Making Decisions with Variables 

Start with your code from Part 2.  Declare two new global constant integers:  one for the low threshold and one for the high threshold.  Set the low threshold to 50 and the high threshold to 100. 

Add the code to check if the value is less than the low threshold.  If so,  turn the led off.
If the value is greater than the high threshold,  turn the led on.
Adjust your thresholds to work well with the sensitivity of your squeeze sensor.

Now the LED has a nice "click" behavior. Even if you gently squeeze you can't make it blink or flitter easily.

Submit your final code in a file called SqueezeTest.ino to Canvas.  Make sure that your answers to the 4 questions are in the comment section in Canvas.

EXTRA CREDIT:  3 points:  Binary division

Modify SqueezeTest.ino to perform binary division as follows:  

Ask the user to enter two numbers.  the first number is the number he/she wants divided.  The 2nd number, num2, is the number to raise 2 to.  The program will divide the first number by pow(2,num2).

You must use binary shifting to perform the division.  For example:  value = value >> 1;  will divide whatever is in value by 2 (2 raised to the 1st power). 

                                                                                                                    value = value >> 2; will divide value by 4 (2 raised to the 2nd power)

Example output (with some notes in black):

Enter two numbers separated by a space (the 2nd number must be the power you want 2 raised to):    256   3    (Note:  this means you want to divide 256 by 8   since 2^3 = 8)

256 divided by 8 is 32


Grading Criteria (12)

Grading:  SqueezeTest.ino 12 points  (Header 1pt, Compiles 2 pts, Proper Formatting 1 pt,  Works as Specified 6 pts)
                Extra Credit:  3 pts

Submit your files to Canvas

Completed Code:
#include <ArduinoSTL.h>
using namespace std;
const int LED_PIN = 5;
const int SENSOR_PIN = 1;
const int HIGH_THRESHOLD = 100;
const int LOW_THRESHOLD = 50;

void setup() {
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
}

void loop() {
  int value;
  value = analogRead(SENSOR_PIN); //reads 0-1024
  value = value >> 2;
  value = 255 - value;
  cout << "value is " << value << endl;
  analogWrite(LED_PIN, value);  //value can be 0-255 for duty cycle
  if (value < LOW_THRESHOLD) {
    value = 0;
  } else if (value > HIGH_THRESHOLD) {
    value = 255;
  }
  cout << "value is " << value << endl;
  analogWrite(LED_PIN, value);  //value can be 0-255 for duty cycle
}

Completed EXTRA CREDIT code:
#include <ArduinoSTL.h>
using namespace std;

const int LED_PIN = 5;
const int SENSOR_PIN = 1;
const int HIGH_THRESHOLD = 100;
const int LOW_THRESHOLD = 50;

void setup() {
  Serial.begin(9600);
  cout << "Enter 2 integers separated by a space: " << endl;
  cout << "The first number is what you want to divide by 2^second number." << endl;
  cout << "The 2nd number must be the power you want to raised two to" << endl;

}

void loop() {
  while (Serial.available()) {
    int num1 = 0;
    int answer = 0;
    int powerOfTwo = 0;
    cin >> num1 >> powerOfTwo;
    while (Serial.available())  {  //put this after your cin statement
      Serial.read();
    }
    cout << "you entered: " << num1 << " " << powerOfTwo << endl;
    answer = num1 >> powerOfTwo;
    cout << num1 << " divided by " << pow(2, powerOfTwo) << " is " << answer << endl;

    int value;
    value = analogRead(SENSOR_PIN);
    value = value >> 2;
    value = 255 - value;
    cout << "value is " << value << endl;
    if (value < LOW_THRESHOLD) {
      analogWrite(LED_PIN, 0);
    }  else if (value > HIGH_THRESHOLD) {
      analogWrite(LED_PIN, 255);
    }
  }
}