0

I need to get my robot to be able to use the bump switches so that either one can be pressed and the motor corresponding to that bumpswitch will run for as long as the bump switch is pressed. The problem I'm having is getting the LEDs to light up correctly. While the bump switch code block is running, I need the LEDs to light up and go off seven times for one second every time the Light sensor value gets higher than 400. How do I do it? Please Help! My Code is posted below:

#pragma config(Sensor, in2,    lightSensor,    sensorReflection)
#pragma config(Sensor, dgtl3,  bumpSwitch,     sensorTouch)
#pragma config(Sensor, dgtl4,  bumpSwitch2,    sensorTouch)
#pragma config(Sensor, dgtl10, ledGreen,       sensorLEDtoVCC)
#pragma config(Sensor, dgtl11, ledRed,         sensorLEDtoVCC)
#pragma config(Motor,  port1,           leftMotor,     tmotorVex269, openLoop)
#pragma config(Motor,  port10,          rightMotor,    tmotorVex269, openLoop)

task main() {

while(true) {

    if (SensorValue(lightSensor) > 400) {
        int count = 0;
        while (count < 7) {
            turnLEDOn(ledGreen);
            turnLEDOn(ledRed);
            wait(1);
            turnLEDOff(ledGreen);
            turnLEDOff(ledRed);
            count++;
        }
    }

    while (SensorValue(bumpSwitch) == 0 && SensorValue(bumpSwitch2) == 0) {
        stopMotor(rightMotor);
        stopMotor(leftMotor);
    }

    while (SensorValue(bumpSwitch2) == 1) {
        startMotor(rightMotor, 55);
        startMotor(leftMotor, 55);
    }

    while (SensorValue(bumpSwitch) == 1){
        startMotor(rightMotor, -55);
        startMotor(leftMotor, -55);
    }
}
}
Jerry101
  • 12,157
  • 5
  • 44
  • 63
user3376956
  • 21
  • 1
  • 4

2 Answers2

0

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):

  1. 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.
  2. 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.

Jerry101
  • 12,157
  • 5
  • 44
  • 63
  • @user3376956 Glad to help. Do remember to accept the answer if it answers the question. – Jerry101 Mar 21 '14 at 16:26
  • BTW I looked through the Robot C tutorial and it never mentioned any features that would enable a robot to do multiple things at a time! The main control loop could use one `wait()` at the end of the loop to set a lower bound on how much time it takes per iteration, but it'd be much better to read a clock. Is there a way to fork a thread? I didn't find its reference docs. – Jerry101 Mar 21 '14 at 17:04
0

You should put in a subprogram.

//*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//

task blink()
{
// 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);
    }

}


    task main()
    {
        startTask(blink);
        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);
            }
        }
    }
phil
  • 1