Smaller screens (1100px<) might have website design issues.
Assemble + Read
We have removed our analog A3 wire from the circuit. How is this circuit getting an input?
Digital pins-ish. We change it from OUTPUT (5V) to INPUT (LOW/0V) and then check how long it takes for the capacitor to discharge.
What does ‘QT’ stand for?
"A common abbreviation for charge transfer is QT.
The letter Q refers to electrical charge (an accumulation of electrons), and T is for transfer. "
What does ‘us’ stand for?
Microseconds,
What is our circuit measuring now? ( you may look this information up and put it in your own words)
Microseconds since capacitor discharges. The more light the phototransistor receives, the less resistance there will be on the current, decreasing the discharge time of the capacitor.
Challenge 1: Two Eyes Are Better Than One
Assemble the second eye if you haven’t already ✅
Read the normalized differential shade equation. What does it mean in your own words?
Using constants to detect high or low light is not good because code/constants that work in one room might not in another. The NDS equation provides a ratio of how much brighter the right sensor is than the left sensor. The ZJNDS equation provides a range from negative to positive, which is more useful for Arduino sketches (especially servos).
Use this code with your two eyes. When the serial is working, show Mr Green.
Read the code and the comments. What does this code do?
long time = micros();
while(digitalRead(pin));
time = micros() - time;
return time;
More light -> lower resistance -> faster discharge (short time)
Less light -> higher resistance -> slower discharge (long time)
The code above measures how long it takes for the capacitor to discharge from HIGH to LOW (I think). First we get the initial time, then we wait until the pin is LOW (while(digitalRead(Pin) == HIGH)), then we return the time difference.
Challenge 2: Go into the Light (Re: Robot Heaven)
Turn smoothly towards bright light.
Move forwards unless
Everything is dark
Everything is super bright
#include <Servo.h> // Include servo library
Servo servoLeft; // Declare left and right servos
Servo servoRight;
float tLeft;
float tRight;
void setup() // Built-in initialization block
{
tone(4, 3000, 1000); // Play tone for 1 second
delay(1000); // Delay to finish tone
Serial.begin(9600);
servoLeft.attach(12); // Attach left signal to pin 12
servoRight.attach(13); // Attach right signal to pin 13
}
void loop() // Main loop auto-repeats
{
float tLeft = float(rcTime(8)); // Get left light & make float
float tRight = float(rcTime(6)); // Get right light & make float
float averageLight = (tLeft + tRight) / 2;
Serial.println(averageLight);
//if too bright or too dark, stop
if (averageLight < 130.0 or averageLight > 25000.0) {
maneuver(0, 0, -1);
}
float ndShade; // Normalized differential shade
ndShade = tRight / (tLeft+tRight) - 0.5; // Calculate it and subtract 0.5
int speedLeft, speedRight; // Declare speed variables
if (ndShade > 0.0) // Shade on right?
{ // Slow down left wheel
speedLeft = int(200.0 - (ndShade * 1000.0));
speedLeft = constrain(speedLeft, -200, 200);
speedRight = 200; // Full speed right wheel
}
else // Shade on Left?
{ // Slow down right wheel
speedRight = int(200.0 + (ndShade * 1000.0));
speedRight = constrain(speedRight, -200, 200);
speedLeft = 200; // Full speed left wheel
}
maneuver(speedLeft, speedRight, 20); // Set wheel speeds
}
long rcTime(int pin) // rcTime measures decay at pin
{
pinMode(pin, OUTPUT); // Charge capacitor
digitalWrite(pin, HIGH); // ..by setting pin ouput-high
delay(5); // ..for 5 ms
pinMode(pin, INPUT); // Set pin to input
digitalWrite(pin, LOW); // ..with no pullup
long time = micros(); // Mark the time
while(digitalRead(pin)); // Wait for voltage < threshold
time = micros() - time; // Calculate decay time
return time; // Returns decay time
}
// maneuver function
void maneuver(int speedLeft, int speedRight, int msTime)
{
servoLeft.writeMicroseconds(1500 + speedLeft); // Set left servo speed
servoRight.writeMicroseconds(1500 - speedRight); // Set right servo speed
if(msTime==-1) // if msTime = -1
{
servoLeft.detach(); // Stop servo signals
servoRight.detach();
}
delay(msTime); // Delay for msTime
}
Challenge 3: Don't Crash
Set up your sensors to avoid obstacles that are too close by turning to go around them. Use your existing code to set it up.
Run a gamut of chair and table legs. Can you make it through without crashing?
Install LED indicators to light up when an obstacle is in view.
Reflect: Why doesn’t the robot avoid robots successfully using this code? Can it be made to “See” obstacles better with these sensors?
There are many problems the robot can run into when trying to avoid obstacles.
If you are solely running the code based off the normalized differential shade equation, objects might not give enough shade, so you can detect where the shadow is, but the robot will not turn enough.
There is a commented block of code which detects if a constant of 1800us or greater is detected, but this is also flawed, for in a dark room, you're screwed.
Can it be made to "See" obstacles? I do not think it can with these sensors. Unless you mix the if statement code I wrote and use the NDSE to detect which side the shadow is on. But the if statement constant that checks has to be different for different light levels.
By the way, when solely using the if statement code, if there's a shadow it will run the maneuver when it is not supposed to.
#include <Servo.h>
Servo servoLeft;
Servo servoRight;
float tLeft;
float tRight;
#define LEFT_INDICATOR_PIN 11
#define RIGHT_INDICATOR_PIN 3
void setup()
{
tone(4, 3000, 1000);
delay(1000);
Serial.begin(9600);
pinMode(LEFT_INDICATOR_PIN, OUTPUT);
pinMode(RIGHT_INDICATOR_PIN, OUTPUT);
servoLeft.attach(12);
servoRight.attach(13);
}
void loop()
{
float tLeft = float(rcTime(8)); // Get left light & make float
float tRight = float(rcTime(6)); // Get right light & make float
float averageLight = (tLeft + tRight) / 2;
//Greater than 1800 do basic maneuver? Average light, so up ahead?
// if (averageLight > 1800) {
// digitalWrite(LEFT_INDICATOR_PIN, HIGH);
// digitalWrite(RIGHT_INDICATOR_PIN, HIGH);
//
// forwardsOrBackwards('B', 600); //clearance
// rotateLeftOrRight('R'); //turn right
// forwardsOrBackwards('F', 500); //go straight in right direction
// rotateLeftOrRight('L'); //turn left
// }
// Serial.println(averageLight);
// delay(1000);
//if too bright or too dark, stop
// if (averageLight < 130.0 or averageLight > 25000.0) {
// maneuver(0, 0, -1);
// }
float ndShade; // Normalized differential shade
ndShade = tRight / (tLeft+tRight) - 0.5; // Calculate it and subtract 0.5
int speedLeft, speedRight; // Declare speed variables
// Shade on right?
if (ndShade > 0.0)
{
digitalWrite(LEFT_INDICATOR_PIN, HIGH);
digitalWrite(RIGHT_INDICATOR_PIN, LOW);
speedLeft = int(200.0 - (ndShade * 1000.0)); // Slow down left wheel
speedLeft = constrain(speedLeft, -200, 200); //Constrain
speedRight = 200; // Full speed right wheel (turn left)
}
// Shade on Left?
else
{
digitalWrite(LEFT_INDICATOR_PIN, LOW);
digitalWrite(RIGHT_INDICATOR_PIN, HIGH);
speedRight = int(200.0 + (ndShade * 1000.0)); // Slow down right wheel
speedRight = constrain(speedRight, -200, 200); //Constrain it
speedLeft = 200; // Full speed left wheel (turn right)
}
maneuver(1500 + speedLeft, 1500 - speedRight, 20); // Set wheel speeds
}
long rcTime(int pin) // rcTime measures decay at pin
{
pinMode(pin, OUTPUT); // Charge capacitor
digitalWrite(pin, HIGH); // ..by setting pin ouput-high
delay(5); // ..for 5 ms
pinMode(pin, INPUT); // Set pin to input
digitalWrite(pin, LOW); // ..with no pullup
long time = micros(); // Mark the time
while(digitalRead(pin)); // Wait for voltage < threshold
time = micros() - time; // Calculate decay time
return time; // Returns decay time
}
void forwardsOrBackwards (char forwardOrBackwards, int delayTime) {
if (forwardOrBackwards == 'F') {
maneuver(1700, 1300, delayTime); // drive straight
} else {
maneuver(1300, 1700, delayTime); // Turn right
}
}
void rotateLeftOrRight (char leftOrRightOrSLOrSR) {
if (leftOrRightOrSLOrSR == 'L') {
maneuver(1300, 1300, 625); // Turn left 625
} else if (leftOrRightOrSLOrSR == 'R'){
maneuver(1700, 1700, 655); // Turn right 648
}
}
// maneuver function
void maneuver(int speedLeft, int speedRight, int msTime)
{
servoLeft.writeMicroseconds(speedLeft); // Set left servo speed
servoRight.writeMicroseconds(speedRight); // Set right servo speed
if(msTime==-1) // if msTime = -1
{
servoLeft.detach(); // Stop servo signals
servoRight.detach();
}
delay(msTime); // Delay for msTime
}