The rc-time circuits in this tutorial can work under a variety of lighting conditions. Now we need some code that can adapt as well. An example of script code that cannot adapt to change would be:
if qt_left > 2500)... # Not good for navigation.
That statement might work well for turning away from shadows in one room, but take it to another with brighter lights, and it might never detect a shadow. Or, take it to a darker room, and it might think it’s seeing shadows all the time.
For the cyber:bot to navigate with phototransistors, the exact light levels measured aren't really important. What matters is which sensor detects the brightest light.
The next example script takes a light level measurement from each sensor. Then, it uses an equation to turn the two measurements into a single value between -0.5 and +0.5. A value of zero means the two photoresistors are detecting equal brightness.
Let's run the script first, then examine what it is doing.
ERROR FALSE ALARM! On line 11 of the script flash norm_diff_shade_value, you may see a compiler error warning "Operator "+" not supported for this combination of types." This is just a false alarm. The script actually works just fine, so go ahead and send it to the micro:bit.
# norm_diff_shade_value from cyberbot import * while True: bot(8).write_digital(1) qt_left = bot(8).rc_time(1) bot(6).write_digital(1) qt_right = bot(6).rc_time(1) norm_diff_shade = (qt_right / (qt_right + qt_left)) - 0.5 display.scroll(norm_diff_shade) sleep(500)
For navigation, what matters is the difference in how much light the two photoresistors detect, so the robot can turn toward the sensor seeing brighter light (or away from it, depending on what you want.) The script norm_diff_shade_value finds this difference by dividing the right sensor measurement into the sum of both. The result will always be in the 0 to 1 range. This technique is an example of a normalized differential measurement. Here’s what this technique looks like as an equation:
For example, a normalized differential measurement of 0.25 would mean “the light is 1/2 as bright over the right sensor as it is over the left.” The actual values for qt_right and qt_left might be small in a bright room or large in a dark room, but the answer will still be 0.25 if the light is 1/2 as bright over the right sensor. A measurement of 0.5 would mean that the qt_right and qt_left values are equal. They could both be large, or both be small, but if the result is 0.5, it means the sensors are detecting the same level of brightness.
But, the script norm_diff_shade_value adds one more step: it subtracts 0.5 from the normalized differential shade measurement. That way, the results range from –0.5 to +0.5 instead of 0 to 1, and a measurement of 0 means equal brightness. The result is a zero-justified normalized differential shade measurement, that looks like this as an equation:
But why bother with the extra step? The value range –0.5 to +0.5 is great for navigation scripts because the positive and negative values can be used to scale the wheels speeds. Here is how the zero-justified normalized differential shade equation appears in the script:
norm_diff_shade = (qt_right / (qt_right + qt_left)) - 0.5
This line is used in the next two example scripts, which will show its usefulness.
The micro:bit module’s display can be used to show which side of the cyber:bot is detecting brighter light. The following program shows a visual display of where the brigher light is hitting, reflecting the value of the norm_diff_shade variable. If the light is on the right side, the display will light up a pixel on the right side, if the light is in the middle it will light up a pixel in the middle, and so on.
ERROR FALSE ALARM! On line 11 of the script norm_diff_shade_display, you may see a compiler error warning "Operator "+" not supported for this combination of types." This is just a false alarm. The script actually works just fine, so go ahead and send it to the micro:bit.
# norm_diff_shade_display from cyberbot import * while True: bot(8).write_digital(1) qt_left = bot(8).rc_time(1) bot(6).write_digital(1) qt_right = bot(6).rc_time(1) norm_diff_shade = (qt_right / (qt_right + qt_left)) - 0.5 display.clear() if norm_diff_shade > -0.5 and norm_diff_shade <= -0.35: display.set_pixel(0, 2, 9) elif norm_diff_shade > -0.35 and norm_diff_shade <= -0.1: display.set_pixel(1, 1, 9) elif norm_diff_shade > -0.1 and norm_diff_shade <= 0.1: display.set_pixel(2, 0, 9) elif norm_diff_shade > 0.1 and norm_diff_shade <= 0.35: display.set_pixel(3, 1, 9) elif norm_diff_shade > 0.35 and norm_diff_shade < 0.5: display.set_pixel(4, 2, 9) sleep(50)