Experience with robot programming (although I haven't used Robot C) shows that to make the robot run two or more sensor reactions in parallel, you have to structure the program very differently than for just one reaction. The Robot C tutorial does not cover this or even introduce the language and library features needed to do it.
In this case, you want the light sensor to trigger an LED on/off sequence that lasts for 1 second, while the bump sensors trigger motor actions that last until those sensors are no longer bumping.
The problem here is your motor control's inner while
loops are blocking up the thread, mostly keeping it from getting around to running the LED control loop. The LED control loop likewise blocks up the thread for 7 seconds, delaying it from running the motor control loop.
In general, each iteration of a robot control loop should read sensors, send output commands, remember any state that it needs to process later, then loop again so all parts of the control loop get to run each cycle (as often as possible or at a controlled rate). Don't block the control flow by staying in an inner while
loop until a sensor changes.
The first step is to unblock the motor control loop:
while (true) {
// Light sensor LED control code ...
// Bumper/motor control
if (SensorValue(bumpSwitch) == 1) {
startMotor(rightMotor, -55);
startMotor(leftMotor, -55);
} else if (SensorValue(bumpSwitch2) == 1){
startMotor(rightMotor, 55);
startMotor(leftMotor, 55);
} else {
stopMotor(rightMotor);
stopMotor(leftMotor);
}
}
Now your current LED control code still calls wait(1)
7 times. According to http://www.robotc.net/support/nxt/ROBOTC-for-Beginners/ wait(1)
waits for 1.0 seconds, so this part of the code currently takes 7 seconds to run. That's a long time between checking the bump switches.
Furthermore, your code has no significant delay between turning the LEDs off and back on again, so you won't actually notice the LEDs turn off until the end of that sequence.
So the second step is to fix the LED control code from blocking the control loop. Basically there are two approaches (I don't know if Robot C supports the first choice, but it's simpler):
- When the light sensor is above-threshold and it was below-threshold in the previous iteration, i.e. it just transitioned, then start [or "fork"] a thread (or task) to run a LED on/off loop. That thread should loop 7 times: {turn the LEDs on,
wait(1.0/14.0)
seconds, turn the LEDs off, then wait(1.0/14.0)
seconds}. That way, 7 cycles around the loop will take 7 * (1/14 + 1/14) = 1.0 seconds. I wrote that as 1.0/14.0
rather than 1/14
because many programming languages compute 1/14
in integer math, yielding 0
, while 1.0/14.0
uses floating point math. I don't know about Robot C. Or, you could use wait1Msec(71)
to wait 71 msec, which is about 1/14 second.
- Use variables to track the sequencing through the flash-LED loop. Each cycle around the main loop, use
if
statements to check those variables, do the next step in the flash-LED cycle if it's time, and update those variables. The steps are: turn on the LEDs when it was in the initial state and the light sensor is above-threshold, turn off the LEDs when it's 1/14 of a second later, turn on the LEDs when it's 1/14 of a second later, ... turn off and set the tracking variables back to the initial state after 14 of those steps. The simplest tracking variable would be a counter from 0 (initial state) to 14 (doing the last LED "OFF" phase) and the value of the system clock from the last change, to let you detect when the clock is 71 msec later than that. Once it finishes step 14, go back to 0. There are alternatives for the tracking variables, such as 3 separate variables for whether it's currently flashing, which of the 7 flash cycles it's currently doing, whether it's in the ON or OFF phase of that cycle, and the clock reading.
Approach #2 is trickier because doing two things at once is tricky. (People who think they can multitask by texting while driving are dangerously wrong.)
A much simpler approach works if the robot doesn't need to run the bumper/motor control loop while flashing the LEDs, that is, if it doesn't mind being unresponsive to the bumpers while flashing the LEDs for 1 second. If those bumper sensors are keeping the robot from running off the end of the table, being unresponsive for 1 second is bad news. But if it's OK for the robot to press against the bumper for 1 second while flashing the lights, then the light sensor LED part of the code could go something like this:
while (true) {
// Light sensor LED control code
if (SensorValue(lightSensor) > 400) {
for (int i = 0; i < 7; ++i) {
turnLEDOn(ledGreen);
turnLEDOn(ledRed);
wait1Msec(71); // 1/14 second
turnLEDOff(ledGreen);
turnLEDOff(ledRed);
wait1Msec(71);
}
}
// Bumper/motor control code ...
}
This makes another simplifying assumption: That if the light sensor is still bright after finishing the 1 second LED flashing loop, it's OK to do another 1 second flashing loop next time around the main control loop, which occurs very soon. So as long as the light sensor is bright, the LEDs will keep flashing and the motors will only check the bumpers once per second. To fix that, use a variable to figure out when the light sensor goes from dark to bright.