Xem mẫu

150 Put the joystick, from Step 5, into the assemblies from Step 6. Fasten it together with the two yellow plates. Then put the whole thing on the remote assembly. When you wiggle the joystick back and forth, it pushes one or the other touch sensor. Step 8 might not look like much, but it`s important. It`s the slider that controls Minerva`s arm. It slides past the light sensor, presenting either a yellow or a black brick to the sensor. This is how the RCX knows if you`ve moved the slider. In Step 9, the slider gets mounted on the remote. Make sure it slides freely, and note that it`s upside-down with respect to the rest of the construction. The orientation of the yellow and black bricks in the slider will make a difference in how the arm is controlled. If you don`t like how it works when it`s all together, you can always switch it around later. 151 Programming the Remote Control The remote control doesn`t really have to do much. It responds to its sensors by sending commands to Minerva. The joystick control triggers the two touch sensors; the remote responds to these by telling Minerva to move forward or spin. The slider control is used to move Minerva`s arm up or down. One final feature is a ``heartbeat"—a special message that the remote periodically sends to Minerva. If Minerva doesn`t hear this message, it knows it has lost contact with the remote. The remote uses three different tasks to get everything done. One task monitors the touch sensors, one task monitors the light sensor, and the third task sends the heartbeat signal. Here is the code for those tasks: #define FORWARD_MESSAGE 16 #define SPIN_MESSAGE 17 #define STOP_MESSAGE 18 #define GRAB_MESSAGE 19 #define RELEASE_MESSAGE 20 #define HEARTBEAT_MESSAGE 21 #define HEARTBEAT_TIME 20 task main() { SetSensor(SENSOR_1, SENSOR_LIGHT); SetSensor(SENSOR_2, SENSOR_TOUCH); SetSensor(SENSOR_3, SENSOR_TOUCH); 152 start lightWatcher; start touchWatcher; start heartbeat; } task touchWatcher() { while (true) { if (SENSOR_2 == 1) { SendMessage (FORWARD_MESSAGE); Wait(10); until (SENSOR_2 == 0); SendMessage (STOP_MESSAGE); } if (SENSOR_3 == 1) { SendMessage (SPIN_MESSAGE); Wait(10); until (SENSOR_3 == 0); SendMessage (STOP_MESSAGE); } } } #define TOLERANCE 3 int current; int minimum; int maximum; int midline; int lastArmMessage; task lightWatcher() { minimum = 100; maximum = 0; while (true) { current = SENSOR_1; if (current < minimum) minimum = current; if (current > maximum) maximum = current; midline = minimum + (maximum - minimum) / 2; if (SENSOR_1 <= (midline - TOLERANCE) && lastArmMessage != RELEASE_MESSAGE) { PlayTone(494, 10); PlayTone(660, 10); SendMessage (RELEASE_MESSAGE); lastArmMessage = RELEASE_MESSAGE; } if (SENSOR_1 >= (middle + TOLERANCE) && lastArmMessage != GRAB_MESSAGE) { PlayTone(660, 10); PlayTone(494, 10); SendMessage(GRAB_MESSAGE); lastArmMessage = GRAB_MESSAGE; } 153 } } task heartbeat() { while (true) { SendMessage (HEARTBEAT_MESSAGE); Wait (HEARTBEAT_TIME); } } The main task configures the inputs on the remote control and starts up the other tasks. The touchWatcher task is fairly straightforward. It listens for a touch on either touch sensor. When one is detected, the remote sends out an IR command to Minerva to go forward or to spin in place. Then the task waits for the touch sensor to be released and sends a stop command to Minerva. The call to Wait(10) deserves more mention; it`s an example of a technique called debouncing. Debouncing is a way of making touch sensors (and buttons in general) work reliably. The basic problem occurs just at the point where you press the touch sensor enough to make its state change from off to on. Tiny motions or electrical variations can cause the touch sensor`s output to switch back and forth very quickly between on and off. This effect is called bounce, and it occurs while you`re pressing or releasing the switch, between the steady states of off and on. Bounce can be eliminated with an electronic circuit or by special programming, as I`ve done here. The call to Wait(10)gives the touch sensor signal a chance to settle down before touchWatcher starts looking for the release of the touch sensor. The slider on the remote changes the value of the light sensor. lightWatcher is the task that monitors the light sensor. If the sensor value changes from light to dark, the remote tells Minerva to release the grabber. A dark-to-light transition causes the remote to send a grab command to Minerva. Just what exactly what "light" and "dark" are is a little tricky to define. I had originally hard-coded light values, but then the remote had to be reprogrammed depending on whether I was using it in daylight or at night. Instead, the remote uses a scheme to calibrate itself on the fly. It keeps track of its minimum and maximum light readings in the minimum and maximum variables, as shown here: current = SENSOR_1; if (current < minimum) minimum = current; if (current > maximum) maximum = current; midline = minimum + (maximum - minimum) / 2; Then lightWatcher calculates the midpoint of the minimum and maximum values. This value is used to determine exactly what light and dark values cause the remote to fire commands to Minerva. lightWatcher also keeps track of the last grabber arm command it sent to avoid unnecessarily sending the same command twice. 154 To provide some feedback to the human operator, lightWatcher plays tones when it sends the grab or release commands. The hearbeat task is very simple. It repeatedly sends the heartbeat command to the IR port. Programming Minerva Minerva`s program, then, must listen for incoming messages on the IR port and respond to them. This is fairly simple, but it`s complicated by two things: 1. Minerva should listen for the heartbeat commands from the remote. If she doesn`t hear them, she should stop what she`s doing until the IR link is established again. 2. The human operator should be able to change the direction of the arm as it is moving, without waiting for an entire grab or release cycle to be completed. This feature, however, should not interfere with Minerva`s ability to stop the arm when it moves up as far as it can go. Minerva`s program is split into four primary tasks: message Watcher The messagewatcher task examines the IR port for incoming messages. When one arrives, it is examined and the appropriate action is taken. grab and release The grab and release tasks are kicked off by messageWatcher to control Minerva`s arm. They are separate tasks so that messageWatcher can continue to receive commands from the remote while the arm is moving. You could, for example, start driving forward while the arm was grabbing. grab and release have the ability to interrupt each other, so you can change the direction of the arm as it`s moving. heartbeatWatcher This task keeps count of missing heartbeats. When messageWatcher receives a heartbeat, it subtracts one from a tally of missing heartbeats, kept in the missedBeats variable. The heartbeatWatcher adds one to this count; if it`s ever more than one, heartbeatWatcher assumes it has lost contact with the remote. It then stops the messageWatcher task and shuts down the robot`s motors. When the heartbeat is heard again, heartbeatWatcher starts up messageWatcher once again. Here`s the entire program. I`ll describe more of the details after the listing. ... - tailieumienphi.vn
nguon tai.lieu . vn