asp.net c# pdf viewer : Break pdf into single pages control application platform web page azure .net web browser NXC_tutorial3-part375

-31-
VIII.More about motors
There are a number of additional motor commands that you can use to control the motors more precisely. In this 
chapter we discuss them: ResetTachoCount, Coast (Float), OnFwdReg, OnRevReg, OnFwdSync, OnRevSync, 
RotateMotor, RotateMotorEx, and basic PID concepts.
Stopping gently
When you use the 
Off()
command, the servo motor stops immediately, braking the shaft and holding position. 
It is also possible to stop the motors in a more gentle way, not using the brake. For this use 
Float()
or 
Coast()
command indifferently, that simple cut the power flowing to motor. Here is an example. First the robot 
stops using the brakes; next without using the brakes. Note the difference. Actually the difference is very small 
for this particular robot. But it makes a big difference for some other robots.
task main()
{
OnFwd(OUT_AC75);
Wait(500);
Off(OUT_AC);
Wait(1000);
OnFwd(OUT_AC75);
Wait(500);
Float(OUT_AC);
}
Advanced commands
The commands 
OnFwd()
and 
OnRev()
are the simplest routines to move motors.
The NXT servomotors have a built-in encoder that allows you to control precisely shaft position and speed; 
NXT firmware implements a PID (Proportional Integrative Derivative) closed-loop controller to control motors' 
position and speed using encoders as feedback. 
If you want your robot to go perfectly straight, you can use a synchronization feature that makes the selected 
couple of motors run together and wait for each other in case one of them is slowed down or even blocked; in a 
similar way, you can set a couple of motors to run together in sync, with a percentage of steering to turn left, 
right or spin in place, but always keeping sync. There are many commands to unleash servomotors' full power!
OnFwdReg(‘ports',‘speed',‘regmode') 
drives the motors specified by ‘ports' at the ‘speed' power 
applying the regulation mode that can be either 
OUT_REGMODE_IDLEOUT_REGMODE_SPEED
or
OUT_REGMODE_SYNC
. If IDLE is selected, no PID regulation will be applied; if SPEED mode is selected, the 
NXT regulates single motor to get a constant speed, even if load on motor varies; finally, if SYNC is selected, 
the couple of motors specified by ‘ports' move in sync as explained before. 
OnRevReg()
acts as the precedent command, reversing direction.
Break pdf into single pages - Split, seperate PDF into multiple files in C#.net, ASP.NET, MVC, Ajax, WinForms, WPF
Explain How to Split PDF Document in Visual C#.NET Application
pdf splitter; a pdf page cut
Break pdf into single pages - VB.NET PDF File Split Library: Split, seperate PDF into multiple files in vb.net, ASP.NET, MVC, Ajax, WinForms, WPF
VB.NET PDF Document Splitter Control to Disassemble PDF Document
break apart a pdf; break apart pdf pages
-32-
task main()
{
OnFwdReg(OUT_AC,50,OUT_REGMODE_IDLE);
Wait(2000);
Off(OUT_AC);
PlayTone(4000,50);
Wait(1000);
ResetTachoCount(OUT_AC);
OnFwdReg(OUT_AC,50,OUT_REGMODE_SPEED);
Wait(2000);
Off(OUT_AC);
PlayTone(4000,50);
Wait(1000);
OnFwdReg(OUT_AC,50,OUT_REGMODE_SYNC);
Wait(2000);
Off(OUT_AC);
}
This program shows well different regulation if you try to stop wheels holding the robot in your hand: first 
(IDLE mode), stopping a wheel you will not notice anything; then (SPEED MODE), trying to slow down a 
wheel, you'll see that NXT increases motor's power to overcome your hold, trying to keep speed constant; finally 
(SYNC mode), stopping a wheel will cause the other one to stop, waiting for the blocked one.
OnFwdSync(‘ports',‘speed',‘turnpct') 
is the same as 
OnFwdReg()
command in SYNC mode, but 
now you can also specify the 'turnpct' steering percentual (from -100 to 100).
OnRevSync() 
is the same as before, simply reversing the motor's direction. The following program shows 
these commands: try changing steering number to see how it behaves.
task main()
{
PlayTone(5000,30);
OnFwdSync(OUT_AC,50,0);
Wait(1000);
PlayTone(5000,30);
OnFwdSync(OUT_AC,50,20);
Wait(1000);
PlayTone(5000,30);
OnFwdSync(OUT_AC,50,-40);
Wait(1000);
PlayTone(5000,30);
OnRevSync(OUT_AC,50,90);
Wait(1000);
Off(OUT_AC);
}
Finally, motors can be set to turn by a limited number of degrees (remember that a full turn is 360°).
For both following commands, you can act on motor's direction changing either the sign of the speed or the sign 
of the angle: so, if speed and angle have the same sign, motor will run forwards, if their sign is opposite, the 
motor will run backwards.
RotateMotor(‘ports',‘speed',‘degrees') 
rotates the motor shaft specified by ‘ports' by a ‘degrees' 
angle at ‘speed' power (in 0-100 range). 
C# PDF Convert: How to Convert Tiff Image to PDF File
Your Tiff image can be with single page or multi-pages. Console.WriteLine("Fail: can not convert to PDF, file type unsupport"); break; case ConvertResult
acrobat separate pdf pages; pdf will no pages selected
C# TWAIN - Acquire or Save Image to File
you want to acquire an image directly into the C# RasterEdge.XDoc.PDF.dll. Group4) device.Compression = TwainCompressionMode.Group3; break; } } acq.FileTranfer
break pdf; pdf insert page break
-33-
task main()
{
RotateMotor(OUT_AC50,360); 
RotateMotor(OUT_C50,-360);
}
RotateMotorEx(‘ports',‘speed',‘degrees',‘turnpct',‘sync', 'stop') 
is an extension of the 
precedent command, that lets you synchronize two motors (e.g. 
OUT_AC
) specifying a 
‘turnpct' 
steering 
percentage (from -100 to 100) and a boolean flag 
‘sync' 
(that can be set to true or false).  It also lets you 
specify whether the motors should brake after the angle of rotation has completed using the boolean flag 'stop'.
task main()
{
RotateMotorEx(OUT_AC503600true, true);
RotateMotorEx(OUT_AC5036040true, true);
RotateMotorEx(OUT_AC50360, -40true, true);
RotateMotorEx(OUT_AC50360100true, true);
}
PID control
NXT firmware implements a digital PID (proportional integrative derivative) controller to regulate servomotors' 
position and speed with precision. This controller type is one of the simplest yet most effective closed loop 
feedback controller known is automation, and is often used.
In rough words, it works so (I'll talk about position regulation for a discrete time controller): 
Your program gives the controller a set point R(t) to reach; it actuates the motor with a command U(t) , 
measuring its position Y(t) with the built-in encoder and calculates an error E(t) = R(t) – Y(t): here's why it is 
called a "closed loop controller", because the output position Y(t) is brought back to the controller's input to 
calculate the error. The controller transforms the error E(t) into the command U(t) so: 
U(t) = P(t) + I(t) + D(t), where
P(t) = K
P
·
E(t), 
I(t) = K
I
·
( I(t–1) +  E(t) )
and D(t) = K
D
·
(E(t) – E(t –1)). 
It could seem quite hard for a novice, but I'll try to explain this mechanism as best as I can.
The command is the sum of three contributes, the proportional part P(t), the integrative part I(t) and the 
derivative part D(t) .
P(t) makes the controller quick in time, but it does not assure a null error at equilibrium;
I(t) gives “memory” to the controller, in the sense that it takes trace of accumulated errors and compensates 
them, with the guarantee of a zero error at equilibrium;
D(t) gives “future prediction” to the controller (as derivation in math), speeding up response.
I know this can still be confusing, consider that entire academic books have been written on this argument! But 
we can still try it online, with our NXT brick! The simple program to fix things into memory is the following.
-34-
#define P 50
#define I 50
#define D 50
task main(){
RotateMotorPID(OUT_A100180, P, I, D);
Wait(3000);
}
The RotateMotorPID(port,speed, angle, Pgain,Igain,Dgain) let you move a motor setting different PID gains 
from the default ones. Try setting the following values 
(50,0,0): the motor does not rotate 180° exactly, since an uncompensated error remains
(0,x,x): without proportional part, the error is very big
(40,40,0): there's an overshoot, that means the motor shaft moves beyond the set point and then turns back
(40,40,90): good precision and raising time (time to reach the set point)  
(40,40,200): the shaft oscillate, since derivative gain is too high
Try other values to discover how these gains influence a motor's performance.
Summary
In this chapter you learned about the advanced  motor commands available: 
Float(),Coast()
that stop the 
motor gently; 
OnXxxReg()
, and  
OnXxxSync()
that allow feedback control on motors' speed and sync; 
RotateMotor()
and 
RotateMotorEx()
are used to turn motor's shaft by a precise number of degrees. You 
learned something about PID control too; it has not been an exhaustive explanation, but maybe I have caused a 
bit of curiosity in you: search the web about it!
-35-
IX.More about sensors
In Chapter V we discussed the basic aspects of using sensors. But there is a lot more you can do with sensors. In 
this chapter we will discuss the difference between sensor mode and sensor type, we will see how to use the old 
compatible RCX sensors, attaching them to NXT using Lego converter cables.
Sensor mode and type
The 
SetSensor()
command that we saw before does actually two things: it sets the type of the sensor, and it 
sets the mode in which the sensor operates. By setting the mode and type of a sensor separately, you can control 
the behavior of the sensor more precisely, which is useful for particular applications. 
The type of the sensor is set with the command 
SetSensorType()
.  There are many different types, but I will 
report the main ones: 
SENSOR_TYPE_TOUCH
, which is the touch sensor, 
SENSOR_TYPE_LIGHT_ACTIVE
, which 
is the light sensor (with led on), 
SENSOR_TYPE_SOUND_DB
, which is the sound sensor, and 
SENSOR_TYPE_LOWSPEED_9V
, which is the Ultrasonic sensor. Setting the type sensor is in particular important 
to indicate whether the sensor needs power (e.g. to light up led in the light sensor), or to indicate NXT that the 
sensor is digital and needs to be read via I
2
C serial protocol. It is possible to use old RCX sensor with NXT: 
SENSOR_TYPE_TEMPERATURE
, for the temperature sensor, 
SENSOR_TYPE_LIGHT
for old light sensor, 
SENSOR_TYPE_ROTATION
for RCX rotation sensor (this type will be discussed later).
The mode of the sensor is set with the command 
SetSensorMode()
 There are eight different modes. The most 
important one is 
SENSOR_MODE_RAW
. In this mode, the value you get when checking the sensor is a number 
between 0 and 1023. It is the raw value produced by the sensor. What it means depends on the actual sensor. For 
example, for a touch sensor, when the sensor is not pushed the value is close to 1023. When it is fully pushed, it 
is close to 50. When it is pushed partially the value ranges between 50 and 1000. So if you set a touch sensor to 
raw mode you can actually find out whether it is touched partially. When the sensor is a light sensor, the value 
ranges from about 300 (very light) to 800 (very dark). This gives a much more precise value than using the 
SetSensor()
command. For details, see the NXC Programming Guide.
The second sensor mode is 
SENSOR_MODE_BOOL
. In this mode the value is 0 or 1. When the raw value is above 
562 the value is 0, otherwise it is 1. 
SENSOR_MODE_BOOL
is the default mode for a touch sensor, but can be used 
for other types, discarding analogic informations. The modes 
SENSOR_MODE_CELSIUS
and 
SENSOR_MODE_FAHRENHEIT
are useful with temperature sensors only and give the temperature in the indicated 
way. 
SENSOR_MODE_PERCENT
turns the raw value into a value between 0 and 100. 
SENSOR_MODE_PERCENT
is 
the default mode for a light sensor. 
SENSOR_MODE_ROTATION
is used only for the rotation sensor (see below).
There are two other interesting modes: 
SENSOR_MODE_EDGE
and 
SENSOR_MODE_PULSE
. They count transitions, 
that is, changes from a low to a high raw value or opposite. For example, when you touch a touch sensor this 
causes a transition from high to low raw value. When you release it you get a transition the other direction. 
When you set the sensor mode to 
SENSOR_MODE_PULSE
, only transitions from low to high are counted. So each 
touch and release of the touch sensor counts for one. When you set the sensor mode to 
SENSOR_MODE_EDGE
both transitions are counted. So each touch and release of the touch sensor counts for two. So you can use this to 
count how often a touch sensor is pushed. Or you can use it in combination with a light sensor to count how 
often a (strong) lamp is switched on and off. Off course, when you are counting edges or pulses, you should be 
able to set the counter back to 0. For this you use the command 
ClearSensor()
, that clears the counter for the 
indicated sensor.
Let us look at an example. The following program uses a touch sensor to steer the robot. Connect the touch 
sensor with a long wire to input one. If touch the sensor quickly twice the robot moves forwards. It you touch it 
once it stops moving. 
-36-
task main()
{
SetSensorType(IN_1SENSOR_TYPE_TOUCH);
SetSensorMode(IN_1SENSOR_MODE_PULSE);
while(true)
{
ClearSensor(IN_1);
until (SENSOR_1 0);
Wait(500);
if (SENSOR_1 == 1) {Off(OUT_AC);}
if (SENSOR_1 == 2) {OnFwd(OUT_AC75);}
}
}
Note that we first set the type of the sensor and then the mode. It seems that this is essential because changing 
the type also affects the mode. 
The rotation sensor
The rotation sensor is a very useful type of sensor: it is an optical encoder, almost the same as the one built 
inside NXT servomotors. The rotation sensor contains a hole through which you can put an axle, whose relative 
angular position is measured. One full rotation of the axle counts 16 steps (or –16 if you rotate it the other way), 
that means a 22.5 degrees resolution, very rough respect to the 1-degree resolution of the servomotor. This old 
kind of rotation sensor can be still useful to monitor an axle without the need to waste a motor; also consider that 
using a motor as encoder requires a lot of torque to move it, while old rotation sensor is very easy to rotate.
If you need finer resolution than 16 steps per turn, you can always use gears to mechanically increase the number 
of ticks per turn.
Next example is inherited from old tutorial for RCX.
One standard application is to have two rotation sensors connected to the two wheels of the robot that you 
control with the two motors. For a straight movement you want both wheels to turn equally fast. Unfortunately, 
the motors normally don't run at exactly the same speed. Using the rotation sensors you can see that one wheel 
turns faster. You can then temporarily stop that motor (best using 
Float()
) until both sensors give the same 
value again. The following program does this. It simply lets the robot drive in a straight line. To use it, change 
your robot by connecting the two rotation sensors to the two wheels. Connect the sensors to input 1 and 3.
task main()
{
SetSensor(IN_1SENSOR_ROTATION); ClearSensor(IN_1);
SetSensor(IN_3SENSOR_ROTATION); ClearSensor(IN_3);
while (true)
{
if (SENSOR_1 SENSOR_3)
{OnFwd(OUT_A75); Float(OUT_C);}
else if (SENSOR_1 SENSOR_3)
{OnFwd(OUT_C75); Float(OUT_A);}
else  
{OnFwd(OUT_AC75);}
}
}
The program first indicates that both sensors are rotation sensors, and resets the values to zero. Next it starts an 
infinite loop. In the loop we check whether the two sensor readings are equal. If they are the robot simply moves 
forwards. If one is larger, the correct motor is stopped until both readings are again equal. 
Clearly this is only a very simple program. You can extend this to make the robot drive exact distances, or to let 
it make very precise turns. 
-37-
Putting multiple sensors on one input
A little disclaimer is needed at the top of this section! Due to the new structure of improved NXT sensors and 6-
wires cables, it is not easy as before (as was for RCX) to connect more sensors to the same port. In my honest 
opinion, the only reliable (and easy to do) application would be to build a touch sensor analog multiplexer to use 
in combination with a converter cable. The alternative is a complex digital multiplexer that can manage I
2
communication with NXT, but this is not definitely an affordable solution for beginners.
The NXT has four inputs to connect sensors. When you want to make more complicated robots (and you bought 
some extra sensors) this might not be enough for you. Fortunately, with some tricks, you can connect two (or 
even more) sensors to one input. 
The easiest is to connect two touch sensors to one input. If one of them (or both) is touched the value is 1, 
otherwise it is 0. You cannot distinguish the two but sometimes this is not necessary. For example, when you put 
one touch sensor at the front and one at the back of the robot, you know which one is touched based on the 
direction the robot is driving in. But you can also set the mode of the input to raw (see above). Now you can get 
a lot more information. If you are lucky, the value when the sensor is pressed is not the same for both sensors. If 
this is the case you can actually distinguish between the two sensors. And when both are pressed you get a much 
lower value (around 30) so you can also detect this.
You can also connect a touch sensor and a light sensor to one input (RCX sensors only). Set the type to light 
(otherwise the light sensor won't work). Set the mode to raw. In this case, when the touch sensor is pushed you 
get a raw value below 100. If it is not pushed you get the value of the light sensor, which is never below 100. 
The following program uses this idea. The robot must be equipped with a light sensor pointing down, and a 
bumper at the front connected to a touch sensor. Connect both of them to input 1. The robot will drive around 
randomly within a light area. When the light sensor sees a dark line (raw value > 750) it goes back a bit. When 
the touch sensor touches something (raw value below 100) it does the same. Here is the program:
-38-
mutex moveMutex;
int ttt,tt2;
task moverandom()
{
while (true)
{
ttt = Random(500) + 40;
tt2 = Random();
Acquire(moveMutex);
if (tt2 > 0)
OnRev(OUT_A, 75); OnFwd(OUT_C, 75); Wait(ttt); }
else
OnRev(OUT_C, 75); OnFwd(OUT_A, 75); Wait(ttt); }
ttt = Random(1500) + 50;
OnFwd(OUT_AC75); Wait(ttt);
Release(moveMutex);
}
}
task submain()
{
SetSensorType(IN_1SENSOR_TYPE_LIGHT);
SetSensorMode(IN_1SENSOR_MODE_RAW);
while (true)
{
if ((SENSOR_1 100) || (SENSOR_1 750))
{
Acquire(moveMutex);
OnRev(OUT_AC75); Wait(300);
Release(moveMutex);
}
}
}
task main()
{
Precedes(moverandom, submain);
}
I hope the program is clear. There are two tasks. Task 
moverandom
makes the robot move around in a random 
way. The main task first starts 
moverandom
, sets the sensor and then waits for something to happen. If the 
sensor reading gets too low (touching) or too high (out of the white area) it stops the random moves, backs up a 
little, and start the random moves again.
Summary
In this chapter we have seen a number of additional issues about sensors. We saw how to separately set the type 
and mode of a sensor and how this could be used to get additions information. We learned how to use the 
rotation sensor. And we saw how multiple sensors can be connected to one input of the NXT. All these tricks are 
extremely useful when constructing more complicated robots. Sensors always play a crucial role there. 
-39-
X.Parallel tasks
As has been indicated before, tasks in NXC are executed simultaneously, or in parallel as people usually say. 
This is extremely useful. In enables you to watch sensors in one task while another task moves the robot around, 
and yet another task plays some music. But parallel tasks can also cause problems. One task can interfere with 
another. 
A wrong program
Consider the following program. Here one task drives the robot around in squares (like we did so often before) 
and the second task checks for the touch sensor. When the sensor is touched, it moves a bit backwards, and 
makes a 90-degree turn.
task check_sensors()
{
while (true)
{
if (SENSOR_1 == 1)
{
OnRev(OUT_AC75);
Wait(500);
OnFwd(OUT_A75);
Wait(850);
OnFwd(OUT_C75);
}
}
}
task submain()
{
while (true)
{
OnFwd(OUT_AC75); Wait(1000);
OnRev(OUT_C75); Wait(500);
}
}
task main()
{
SetSensor(IN_1,SENSOR_TOUCH);
Precedes(check_sensors, submain);
}
This probably looks like a perfectly valid program. But if you execute it you will most likely find some 
unexpected behavior. Try the following: Make the robot touch something while it is turning. It will start going 
back, but immediately moves forwards again, hitting the obstacle. The reason for this is that the tasks may 
interfere. The following is happening. The robot is turning right, that is, the first task is in its second sleep 
statement. Now the robot hits the sensor. It start going backwards, but at that very moment, the main task is 
ready with sleeping and moves the robot forwards again; into the obstacle. The second task is sleeping at this 
moment so it won't notice the collision. This is clearly not the behavior we would like to see. The problem is 
that, while the second task is sleeping we did not realize that the first task was still running, and that its actions 
interfere with the actions of the second task.
Critical sections and mutex variables
One way of solving this problem is to make sure that at any moment only one task is driving the robot. This was 
the approach we took in Chapter VI. Let me repeat the program here. 
-40-
mutex moveMutex;
task move_square()
{
while (true)
{
Acquire(moveMutex);
OnFwd(OUT_AC75); Wait(1000);
OnRev(OUT_C75); Wait(850);
Release(moveMutex);
}
}
task check_sensors()
{
while (true)
{
if (SENSOR_1 == 1)
{
Acquire(moveMutex);
OnRev(OUT_AC75); Wait(500);
OnFwd(OUT_A75); Wait(850);
Release(moveMutex);
}
}
}
task main()
{
SetSensor(IN_1,SENSOR_TOUCH);
Precedes(check_sensors, move_square);
}
The crux is that both the 
check_sensors
and 
move_square
tasks can control motors only if no other task is 
using them: this is done using the Acquire statement that waits for the moveMutex mutual exclusion variable 
to be released before using motors. The Acquire command counterpart is the Release command, that frees the 
mutex variable so other tasks can use the critical resource, motors in our case. The code inside the acquire-
release scope is called critical region: critical means that shared resources are used. In this way tasks cannot 
interfere with each other.
Using semaphores
There is a hand-made alternative to mutex variables that is the explicit implementation of the Acquire and 
Release commands.
A standard technique to solve this problem is to use a variable to indicate which task is in control of the motors. 
The other tasks are not allowed to drive the motors until the first task indicates, using the variable, that it is 
ready. Such a variable is often called a semaphore. Let 
sem
be such a semaphore (same as mutex). We assume 
that a value of 0 indicates that no task is steering the motors (resource is free). Now, whenever a task wants to do 
something with the motors it executes the following commands:
until (sem == 0);
sem = 1; //Acquire(sem);
// Do something with the motors
// critical region
sem = 0;  //Release(sem);
Documents you may be interested
Documents you may be interested