Project Lab 7 - Distributer Platform and Loader

Date: 10/06/2013
Duration of activity: 09:00-17:00 and 19:00-22:00 --> 11 hours
Group members participating: Ole Rasmussen and Kasper Føns

1. Goal

 The goal today is to continue work on the distributor platform and to construct a new Loader system.

2. Plan

Our plan is to work in parallel on the following
  • To continue work on the distributor platform.
  • To create a new system, the Loader, which will hold back Lego bricks until the distributor is in position to receive them
  • To incorporate the loader with the rest of the LegoSorter systems

3. Loader

We wanted to build a small cargo unit for transferring Lego bricks from the sorters to the distributer. It should be able to hold one brick (axle or beam) back while waiting for the distributer to signal that it is ready to receive it.

3.1 Brick or no brick?

Our first problem is to detect if the loader has a brick to transfer or not. Our initial idea was to use an old RCX touch sensor, since these are easier to press then the newer NXT ones. The sensor should be situated in a gate that we could pull up and down just like the car tray. Figure 1 shows our first test where a beam is being driven forward using the conveyor belt from the BeamCounter. Notice that the beam is not pushing the switch down, and thus the touch sensor is unable to register it. We could therefore not use the touch sensor to detect if there is a brick or not.

Figure 1: Old touch sensor from Lego RCX where a Beam is being pushed against it.
Our second and final solution was to use two RCX light sensors to detect the presence of a brick. We figured that we did not need the same light intensity as for the BeamCounter and incorporating the old type light sensor into normal bricks was much easier. We figured that we did not need a gate, as we could simply stop the conveyor belt when a brick was detected. The system on Figure 2 worked.
Figure 2: Two light sensors is used to detect Lego bricks in the Loader subsystem.

3.2 Example run

Below is an example run of our Loader. Our software will drive the conveyor belt until a brick is detected. When detected it is written on the NXT LCD and the Loader waits 3 seconds to simulate the the distributor gets into place and signals it is ready. It then ejects the Lego brick (driving the belt for two seconds) and again waits. The process then repeats.


3.3 Incorporating Loader

At this point we were happy with the Loader subsystem. We then connected the Loader to the BeamCounter. Figure 3 shows our Loader connected to our BeamCounter and the distributor located just below the Loader, simulating that it is ready to receive a brick.

Figure 3: System overview with Loader, BeamCounter and Distributer.

4. Distributor platform continued

We need to alter our distributor platform such that the distributor car only needs to drop off bricks in one direction. The current platform can only have trays in one position, but this implies that beams and axles needs to be dropped in different directions.

Our solution was to create a distributor platform that could fit a tray in either direction. We could then rotate one of the trays when we position the platform around it such that the car only needed to drop the bricks in one direction. Now that the platform was larger then the tray, we needed a new way to hold the tray in place. Our solution was a set of hooks that went down on the inside of the tray. See Figure 3. We used six hooks for each tray. Figure 4 shows the platform from above on both trays side by side.

Figure 3: A set of six hooks holds the tray in place inside the distributor platform. Above two of them are shown, there are three one each side of the platform for a total of 12 hooks.
Figure 4: Tray platform used on axles (left) and beams (right). Notice that only six hooks is used at a time. Also notice that the largest axles and beams both needs to be dropped vertically, meaning that the distributor car only needs to drop bricks in on direction.

5. Conclusion

We have constructed the Loader subsystem. It was easy to construct and works perfectly. We have incorporated it into the BeamCounter subsystem, so that beams coming from the BeamCounter will travel to the Loader system.

We now have a distributor platform that only requires the car to drop bricks off in one direction. We need to change tray each time we shift from sorting axles to beams or vice versa.

6. Next lab

In the next lab session we should make the different subsystems communicate with each other over Bluetooth, transferring information about what brick is coming (from Sorter, to Loader and then to the Distributor). We also need to incorporate the AxleSorter into the system, as pointed out on Figure 3, and construct the distributor bridge that the distributor car controls and on which the car drives.
Posted on 9:47 AM | Categories:

Project lab 6 - Distributor platform construction

Date: 08/06/2013
Duration of activity: 15:00-18:00: --> 3 hours
Group members participating: Ole Rasmussen and Kasper Føns

1. Goal

The goal of today is to rebuild the best car found by experimentation from the previous lab report (the car from experiment 2a). We will also build the distributor platform around the tray on which the distributor car is to move on.

2. Plan

The plan for this session:
  • First we will rebuild the best distributor car, which was the one from experiment 2a.
  • Build the distributor platform

3. Rebuild the best distributor car

We found that the car from experiment 2a was the best. Since we have dismantled it for use in later experiments, we needed to rebuild it again. It was quite easy to rebuild though.

4. Distributor platform

We need some kind of platform around the Lego tray so that we can drive on top of it and deliver the bricks in the correct compartments. Our first idea is depicted in Figure 1. Our idea is that the car drives on two distinct pieces:
  1. The distributor platform, standing on the ground. The tray fits neatly inside and cannot move in any direction.
  2. The distributor bridge, which drives on top of the distributor platform. The car controls both the distributor bridge and the car itself, and the distributor platform is stationary.
Figure 1: First platform idea. The distributor platform stands on the ground and the trays fits in. The distributor car drives on the distributor bridge which in turn drives on the distributor platform.
After having built the distributor platform, we discovered one major obstacle. Figure 2 shows the problem. We found that trays are not rectangular, which does not have to be a problem it itself. However, it becomes a problem when the longest axles need to point in one direction while the longest beams need to point in another. That means that if we position the trays in the same direction, the car would need to drop the beams in one direction and the axles in a direction perpendicular to the beam direction. This is simply not an option, so we need to come up with a better solution, but we don't have more time in this lab so we'll look at it the next time.

Figure 2: Tray problem. Trays are not rectangular. Both trays are positioned with the long side horizontally. We found that the largest axles would then point vertically while the beams would point horizontally.

5. Conclusion

We constructed the distributor platform but discovered that it cannot actually be used since positioning the trays in the same position implies that axles and beams needs to be dropped in different directions, something the distributor car cannot handle.

6. Next lab

In the next lab we will look at a solution to the platform problem.
Posted on 9:47 AM | Categories:

Project lab 5 - Distributor car design & build


Date: 06/06/2013-07/06/2013
Duration of activity: 10:00-24:00 (06/06), 09:00 --> 13:00 (07/06) --> 16 hours
Group members participating: Ole Rasmussen and Kasper Føns

1. Goal

The goal of this activity is to design and build the distributor car of the distributor module.

2. Plan

  • Design & build the transporter car by experimenting with car speeds (e.g gearing vs. precision) and find out which one is the most precise while still being fast.

3. Design & build the transporter car

The transporter car is the unit that will be transporting the tray with the Lego pieces around. To ensure it's as fast as possible we'll conduct a few experiments with different gearing ratios. In these experiments we will measure the precision of the car while keeping track of its speed.

3.1 Experiment setup

The setup for the experiments is quite simple. What we want to test is the precision and speed of the car.  We construct the simplest car possible built around an NXT. We attach the tray to this car, and construct a track with toothed bars that the car can drive on, and place it on some rubbers to avoid sliding. This is illustrated in Figure 1.

To measure precision we put a piece of paper underneath the car where it starts. We attach a beam to the side of the car, and put a mark on the paper representing the cars starting position. The precision of the car is measured by letting the car drive forward and backward a few times and measuring how far aware from the starting mark the beam is when it's done. This setup is shown in Figure 2.

There's an issue of what speed and acceleration values to use for the RegulatedMotor. What we do is to use the maximum speed and default acceleration. If the car runs fine with these settings we'll not touch them. However, if the car turns out to be unstable or too fast we'll adjust the values to see if we can make it better. The actual values we use isn't important since we will perform extensive tests for the best acceleration and speed values in a later lab. The only reason we want to adjust them in these experiments is to see if its possible to obtain a somewhat precise and fast car with a specific gear ratio. 
Figure 1: The setup for all experiments consists of the car with tray attached and a track for it to drive on.
Figure 2: The precision of the car is measured by how far away the car ends from the starting point after having driven forward and backward a few times.

3.2 Experiment 1 - Gear ratio of 5

We start with down-gearing the car to 1/5th of the original speed with a Z8 gearwheel driving a Z40 gearwheel. This is equivalent to a gear ratio of 40/8 = 5. The gear construction can be seen on Figure 3. A run of the car can be seen in the video in Figure 4. Figure 5 shows the result (i.e. deviation from the starting point). 

While the car seems to be 100% precise with this gearing (Figure 5) it's also really really slow (Figure 4). Therefore, we'll decrease the gear ratio for the next experiment.
Figure 3: Experiment 1 uses a car with a gear ratio of  5.
Figure 4: With a gear ratio of 1/5 the car is really slow

Figure 5: Experiment 1 result. The deviation from the starting position is zero, meaning the car is 100% precise.

3.3 Experiment 2 - Gear ratio of 1

In this experiment we change the car so that the we have a Z24 gearwheel driving another Z24 gearwheel. This results in a gear ratio of 1. The gear construction can be seen on Figure 6. A run of the car can be seen in the video in Figure 7.
Figure 6: Experiment 2 uses a car with a gear ratio of 1
Figure 7: With a gear ratio of 1 and acceleration of 6000 the car wobbles a bit when it changes direction.
As can be seen from video in Figure 7 the car wobbles a lot when it switches direction. This is fixed in experiment 2a.

3.3.1 Experiment 2a - Wobble fix

To fix the wobbling we decreased the acceleration from the default value of 6000 to 2800. Figure 8 shows the result. With the new acceleration value the car is much more stable. Figure 9 shows the precision measurement. Compared to experiment 1 this car is much faster (5 times actually) but it's still just as precise. In the next experiment we will decrease the gear ratio again to see if we can make it even faster.
Figure 8: Setting the acceleration to 2800 fixed the wobbling.

Figure 9: Experiment 2a result. The deviation from the starting position is zero, meaning the car is 100% precise

3.4 Experiment 3: gear ratio of 1/5

In this experiment the car is driving the wheels with a Z40 gearwheel connected to a Z8 gearwheel. The result is a gear ratio of 8/40 = 1/5. The gear construction can be seen on Figure 10. A run of the car can be seen in the video in Figure 11.
Figure 10: Experiment 3 uses a car with a gear ratio of 1/5.
Figure 11: With a gear ratio of 1/5 the default acceleration is too high.

As can be seen in the video in Figure 11 this test didn't go so well. It turns out that with a gearing ratio of 1/5 the car is so fast that it drives off the track. We fix this in experiment 3a.

3.4.1 Experiment 3a - Fixing acceleration

To fix the off-track driving, we decreased the acceleration from the default 6000 to 450. Figure 12 shows the result.

Figure 12: With a gear ratio of 1/5 and acceleration 450 the car drives much better. However,  it still isn't completely smooth when changing directions.
Figure 12 shows a much better run with the car. At least it stays within the track now while still being faster than the car in experiment 2a. Figure 13 shows the precision result; it's not very good. The car consistently doesn't return to the same initial position where it started. If we look closer at the video in Figure 12 we can see why. There's a slight oddity with the way the car drives. Instead of stopping and switching direction instantly it seems to use a bit of time to adjust to its final position and then it changes direction. This is actually because the low gear ratio puts a huge amount of force on the surrounding Lego, especially the axles through which the force is transferred. What can't be seen in the video is that even though the seems to stop for a while before switching directions, this isn't programmed behavior. To illustrate the problem we reset the acceleration and decreased the speed to 1/6 of the maximum. Figure 14 shows what is actually happening.
Figure 13: The precision of the car in experiment 3 is not very good.
Figure 14: Decreasing the speed to 1/6th of the original emphasizes the  problem with this car; the Lego can't handle so much acceleration, so it's being transferred in chunks.
Notice that in Figure 14 the car seems to move in bursts. The funny thing is that the program used to control the car is the exact same as for all the other experiments. The only thing that has changed is the gearing and the speed. Thus, what's actually happening here is a result of the force-transfer from the motors to the surrounding Lego: the motor transfers so much force to the wheels in such a short time that it physically bends the Lego axles. When all this force reaches the wheels the car is pushed quickly forward, but it also releases the force from the Lego. This is what causes the chopping movement. Figure 15 shows a slow-motion video of this behavior. Looking closely it can be seen that when the car is standing still the motor is actually still rotating, but the force just doesn't get transferred to the wheels fast enough to move the car instantly.
Figure 15: Slow-motion run of the car. Shows the force-transfer problem more clearly.

The cause of the problem is, as mentioned before, that the Lego axles can't handle the amount of force that is transferred through them. To alleviate this problem we'll try to construct a car specifically designed to minimize force transfer through Lego axles.

3.5 Experiment 4: gear ratio of 1/5, special design

In this experiment we construct a car designed specifically to avoid transferring force through long Lego axles. The design of this car is shown in Figure 16. It uses two motors to avoid the need for a long axle to reach out to each side of the car.
Figure 16: The new car uses 2 motors to eliminate the need for a long axle going out to each side of the wheels.
To minimize the force transfer through single axles we design a custom solution for attaching the gear wheels to the motor. This is shown in Figure 17. We have attached the gear wheels directly to the motors by the means of several 2-length axles. This ensures that all the force from the motor isn't transferred through a single axle like it usually is. Instead the force is distributed through each of the axles. Also, since the axles are so small they can store much less energy than longer axles.
Figure 17: Our custom design for transferring force between the motor and the gearwheel. This ensures almost no energy can be stored in the axles due to their short length.

A run of the new car can be seen in Figure 18. It's obvious that this car doesn't have the force transfer problem from experiment 3. Actually, now it almost transfers too much force too quickly to the wheels; it's almost so aggressive that it runs itself off the track!

Figure 18: The specialized car is a wild beast.

Just for fun we added a set of "guiders" to the car that graps underneath the track and keeps the car steady. The result can be seen in Figure 19. This helps a lot. What we have created here is a car that is super fast but nowhere near any kind of precision. This last experiment was mostly just for fun, to see how fast we could make the car without thinking about precision. 

Figure 19:  The specialized car with guiders. It's like taming a wild tiger with fishnets; it could (and will) break out any minute now...

4. Conclusion

In experiment 1 we constructed a car with a gear ratio of 5. This car turned out to be very precise but too slow. In experiment 2 we made the car faster with a gear ratio of 1, but it was a bit wobbly so we changed the acceleration and ended up with a car must faster but just as precise as in experiment 1. To see if we could make the car even faster we decreased the gear ratio further down to 1/5 in experiment 3. This introduced the problem with force transfer and energy storage in the Lego axles; the car was faster but not nearly as precise as the one in experiment 2. In experiment 4 we fixed the force transfer problem by constructing a car specifically built to minimize force transfer through Lego axles. It turned out to be extremely fast but also extremely imprecise. We had to add guiders that graps around the track just to keep the car steady.

The final result is that the car from experiment 2a was the most precise while still being relatively fast. Thus that is the car we will be using in the final distributor construction.

5. Next lab

In the next lab we will design and build the remaining parts of the distributor.
Posted on 10:17 AM | Categories:

Project lab 4b - BeamCounter refinement

Date: 04/06/2013
Duration of activity: 09:00-21:00 --> 12 hours
Group members participating: Ole Rasmussen and Kasper Føns

1. Goal

The goal of this activity is to refine the BeamCounter.
We would like our BeamCounter to reliably handle all beam sizes - from a length of two to a length of fifteen. Our current solution does not handle beams of length two or three very well, since they are able to get stuck in the intersections between belts.

2. Plan

Our plan is to look at the conveyor belt design and use available Lego bricks to see if it is possible to adapt it to handle beams of length two and three as well as longer beams. If we succeed in doing so, we would add our light sensing system to the new conveyor belt and add supporting walls so that beams are not able to fall off the conveyor belt system and such that they will always pass the sensors in a straight line. Notice that this project lab was conducted in parallel with project lab 4a.

3. New conveyor belt design

We wanted to test if a new conveyor belt design could alleviate the problem with small beams. We wanted to change the belt from the tank threads (left on Figure 1) to another type of belt (right on Figure 1). The idea is that the new ones are thinner and could potentially reduce the gab between belts and therefore allow smaller beams to cross the intersections.

Figure 1: Old tank conveyor threads on the left (inside-out and normal) and new ones on the right (normal and inside-out). 
By adding our rotating axle to our new conveyor belt design as well (See Figure 2), we are able to transport beams of length two. As can also be seen in Figure 2, the gaps are much smaller compared to the ones seen in our preliminary experiments, here reproduced as Figure 3.
Figure 2: Rotating Axle added to our system so that it supports beams of length two.
Figure 3: Old conveyor belt design. There is a much larger gap between intersections.
Our system is driven by two motors, since this system has more friction because the belts are tighter. Our gearing system can be seen in Figure 4 and 5. The Figures shows an intersection of two belts. On both belts an axle is connected to a z24 gear. When driving the gear, the belt is driven forward. The two gears are connected with a z8 gear, so that driving one of the belts drives them both. The axle on top is then connected with the z8 gear. The axle is thus rotating three times (24/8=3) as fast as the belts. The motors are driven by using NXTRegulatedMotor.forward() and in a sense is a very simple open-loop control [1].

Figure 4: Gearing system for driving conveyor belt and rotating axle. The intersection of the belts is just below the axle.
Figure 5: Gearing system close up. The two z24 gears are connected by a z8 gear. The axle that has the z8 gear is also connected to the rotating axle by another z8gear and a small flywheel type gear.

4. Adding light sensors

We used a new design for holding the belts. In our preliminary design we used Lego beams, but our new design uses normal Lego bricks. This allows us to easier build walls around the track to make sure that our lightsensors would be able to count the holes correctly. Our design can be seen in Figure 6.
Figure 6: Our new design using standard Lego bricks for outer design and new conveyor belt types.
There were no walls where we had located our sensors and this presented a new problem. Larger beams would easily pass our sensors since they were supported by the walls in both ends as in Figure 7. However, smaller beams could become stuck as in Figure 8. Our solution to the problem was to add small "windows" for our lightensors. This allowed us to support the bricks while being able to count the holes. A brick passing by the windows can be seen in Figure 9.

Figure 7: Larger beams are supported by walls while going through our sensing platform.

Figure 8. Smaller beams are not supported and can get stuck like above.

Figure 9. Added support walls with windows allowing  light to pass through but still having beams supported.

5. Program source code

At this point our BeamCounter code is pretty stable and we will here explain how our counter program works. Below is our source code for the counter.
It uses two sensors, one to emit a light ray (the floodLight) and one to sense if it is being broken by a brick (the sensor . It also uses a BeltDrive instance, which is an encapsulation of one or multiple NXTRegulatedMotors, which can be asked to drive the belt forward. The BeltDrive class then knows which motors to run and in which direction for all motors to drive the belt the same way.

When the BeamCounter is instantiated it will setup the lightsensors and wait for the receiving sensor to sense the light from the sending sensor. If we don't do this the BeamCounter could register a beam hole at the moment it starts, since it takes a small amount of time for the floodlight to actually light up.

Our Run() method starts the beltDrive and begins sampling the sensor. We sense each time the lightbeam is broken and for a brick of length n, it will be broken exactly n+1 times. We play a small sound for each hole we count (excluding the first time the lightbeam is broken to account for the +1 term). When the light beam has not been broken for BRICK_END_TIME_THRESHOLD_IN_MS time, we believe the brick has ended and write to the screen how many holes were found.

 import lejos.nxt.LCD; 
 import lejos.nxt.LightSensor;  
 import lejos.nxt.Sound;  
 import lejos.util.Delay;  
   
 public class BeamHoleCounter  
 {  
   private static final long BRICK_END_TIME_THRESHOLD_IN_MS = 200;  
   private static final int LIGHT_THRESHOLD = 550;  
   
   private final LightSensor sensor;  
   private final BeltDrive beltDrive;  
   private int brickCount = 0;  
   
   public BeamHoleCounter(LightSensor floodLight,LightSensor sensor, 
                             BeltDrive beltDrive)  
   {  
     this.sensor = sensor;  
     this.beltDrive = beltDrive;  
   
     floodLight.setFloodlight(true);  
     this.sensor.setFloodlight(false);  
     waitForFloodLightOn();  
   }  
   
   private void waitForFloodLightOn()  
   {  
     LCD.drawString("Waiting for", 3, 5);  
     LCD.drawString("Floodlight ON", 2, 6);  
     while(getLightValue() < LIGHT_THRESHOLD)  
     {  
       Delay.msDelay(5);  
     }  
     LCD.clear();  
   }  
   
   private int getLightValue()  
   {  
     return sensor.getNormalizedLightValue();  
   }  
   
   public void run()  
   {  
     beltDrive.forward();  
   
     int lightBeamBrokenCount = 0;  
     boolean stateAboveLightThreshold = true;  
   
     LCD.drawString("Light sensed: ", 0, 0);  
     LCD.drawString("Bricks: ", 0, 2);  
     LCD.drawString("Holes : ", 0, 3);  
     drawCounts(lightBeamBrokenCount);  
   
     long lastTimeLightBelowThreshold = System.currentTimeMillis();  
     while(true)  
     {  
       if(lastTimeLightBelowThreshold + BRICK_END_TIME_THRESHOLD_IN_MS 
            < System.currentTimeMillis() && lightBeamBrokenCount >= 1)  
       {  
         brickCount++;  
         int holesInBrick = lightBeamBrokenCount - 1;  
         drawCounts(holesInBrick);  
         lightBeamBrokenCount = 0;  
       }  
       int lightValue = getLightValue();  
       LCD.drawInt(lightValue, 3, 3, 1);  
   
       if(lightValue > LIGHT_THRESHOLD && !stateAboveLightThreshold)  
       {  
         stateAboveLightThreshold = true;  
         if(lightBeamBrokenCount != 1)  
           playLightBeamBrokenSound();  
       } else if(lightValue < LIGHT_THRESHOLD && stateAboveLightThreshold)  
       {  
         lightBeamBrokenCount++;  
         lastTimeLightBelowThreshold = System.currentTimeMillis();  
         stateAboveLightThreshold = false;  
       }  
     }  
   }  
   
   private void playLightBeamBrokenSound()  
   {  
     int volume = Sound.getVolume();  
     Sound.setVolume(50);  
     Sound.playTone(4000, 50, 100);  
     Sound.setVolume(volume);  
   }  
   
   private void drawCounts(int holesInBrick)  
   {  
     LCD.drawInt(brickCount, 2, 9, 2);  
     LCD.drawInt(holesInBrick, 2, 9, 3);  
   }  
 }  

Below is a slow-motion run where a beam passes through our sensors. Just below the camera is the floodLight and on the opposite side of the belt is the sensor. Look closely at the sensor while the brick is passing through. You should notice the light being broken and hear the sound from our program registering a hole.


Below is another run through our system where the NXT can be seen. Beams of length two and fifteen are going through our system. We could only find a black beam of length two, its pretty hard to see on the video, sorry. The display shows how many beams have passed and the length of the last one.

One key benefit with the design of the BeamCounter light sensor system, is that it is nearly independent on time. Time is only used for detecting if a brick has completely passed the sensors. If our conveyor belt speed changes, as could be the result of a depleting battery or because more friction was added to the system, our BeamCounter would still work as long as one beam hole would pass the light sensor faster than BRICK_END_TIME_THRESHOLD_IN_MS milliseconds. We believe we have built a very robust BeamCounter implementation.

6. Conclusion

We are very happy with the result so far. We have tested it with a lot of beams with different lengths, and so far the BeamCounter have been all correct. Beams are no longer getting stuck and small beams of length two can also be transported on the system and walls have been added to help guide beam past the light sensors.

7. Next lab

In the next lab we'll start working on the distributor car that should carry the car tray.

8. References

[1] “Embedded Systems, Embodied Agents - Lecture slides week 2.” [Online]. Available: http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lectures/Lecture2/Lecture.pdf. [Accessed: 05-Jun-2013].

Posted on 9:41 AM | Categories:

Project lab 4a - Distributor car tray


Date: 04/06/2013
Duration of activity: 9 hours
Group members participating: Ole Rasmussen and Kasper Føns

1. Goal

The goal of this activity is to design, build and code the car tray of the distributor module used to transport and release the Lego pieces.

2. Plan

First, we will design and build the tray. When the design is satisfactory, we will code the software. Notice that this project lab was conducted in parallel with project lab 4b.

3. Physical design

To design the car tray we must keep the following requirements in mind:
  1. It should be as lightweight as possible. The less the tray weighs the faster and more precisely it can be moved.
  2. It should be able to handle the largest Lego pieces we can sort; a 12M axle and a 15M beam.
  3. It should have a close/release mechanism to enable holding onto a Lego piece for an indefinite amount of time and then dropping it when required. This mechanism should be quite fast to not slow the whole system down (i.e. in the milliseconds range, not seconds).
Figure 1: The physical design of the car tray. The main parts are: motor (1), chassis (2), gate (3) and gear wheels (4).
Our car tray can be seen in Figure 1. The main parts shown on the figure are:
  1. An NXT motor to drive the gate mechanism
  2. The chassis consisting of several different beams and pins
  3. A gate with two teethed bars connecting to the gear wheels and motor
  4. Two 40T gear wheels through which the motor can move the gate
The physical operation of the car is simple. When the motor (1) rotates it turns the gear wheels (4) which drives the gate (3). This is demonstrated in the video in Figure 2.

Figure 2: A video demonstrating the car tray in action .
With regards to the weight (requirement 1) we have tried to make it as light as possible. It weighs about half an NXT brick. The most heavy part is the motor while the chassis is the second-most heavy part. The weight of the motor is not something we can change (unless we don't use a motor at all) and therefore the only other part that may be improved is the chassis. However, one must keep in mind that the chassis should be large enough to support both 12M axles and 15M beam which establishes some physical constraints for the build.

Figure 3 shows the car tray dimensions (requirement 2) compared to an 12M axle and a 15M beam. As can be seen the chassis is a good deal wider and a bit longer than is needed to support these pieces. This is due to the requirement for extensibility. If the system should be easily extensible to sort other pieces than axles and beams, the car tray should be built from the start to handle most types of pieces. The system is not extensible if the car tray needs to be rebuilt every time a new sorter module is added.
Figure 3: The car tray is longer and wider than both the longest axles (12M) and beams (15M) we support to ensure it can be used with other pieces in the future (e.g. it is extensible).
Requirement 3 imposes restrictions on the speed of the gate mechanism. It must be able to open/close quite fast (i.e. in the milliseconds range). The 40T gear wheels gears the motor up so it doesn't have to rotate as far to open/close the gate as it would have to without. We could have added more gears after the 40T wheel, but it would require more supporting structure in the chassis which increases weight and complicates the build. Furthermore, more gearing isn't necessarily going to make the gate open/close faster as the motor needs a certain amount of time to accelerate to full power. Thus, we believe the single 40T gear is a good compromise between speed, weight, and complexity.

To ensure the tray meets the time requirement for the close/release mechanism (4), we want to measure how fast the the tray can open and close with the current design. To do this we set up the tray next to a cell phone with a millisecond timer and then captured that setup with another cell phone. The recording cell phone captures 30 frames per second which means it will capture a frame each 1000ms/30 = 33ms. This means the resolution of our experiment is 33ms - e.g. the timer will seem to increase in ~33ms increments (where in reality it's 1ms). A resolution of 33ms should be enough to capture the movement of the tray as we don't expect it to be anywhere near as fast as 33ms. The result can be seen in the slow-motion video in Figure 4. We can see that the tray starts opening at the 472 millisecond mark and is closed completely again at the 981 millisecond mark. Thus the time it took to open and close the tray is 981ms-472ms=509ms which is approximately half a second. This is a pretty good result and meets the requirement of being in the milliseconds range.

Figure 4: A timed slow motion video of the tray opening and closing. Recorded with 30FPS, the timing resolution is thus 1000ms/30=33ms.
Below is a series of pictures of the tray from different angles.



4. Software

4.1 Control mechanism

The tray software should basically be able to open and close the tray gate. Since the gate is controlled by a motor (called the gate motor from now on) we need to decide which control mechanism to use.

With an open-loop controller [1] there would basically be only one implementation choice for controlling the gate: it would be controlled by simple power and sleep combinations (e.g. close gate = drive forward with 70% power in 1 second). The problem with this approach is that without feedback (e.g. tachometer) there is no way to know if the motor has actually moved the amount it was hoping to. Even worse it would be dependent on environmental factors and so it probably wouldn't move the correct amount in most cases due to different battery levels, motor load etc. Based on this we conclude that the tray software should be a closed-loop controller [1]. In the next section we will describe how we have implemented the closed-loop controller.

4.2 The CarTray class

We have encapsulated the functionality of the car tray in a CarTray Java class. It has the following API:
  • CarTray(RegulatedMotor gateMotor)
  • void releaseItem()
The constructor takes as argument the motor that drives the gate. Note the type, RegulatedMotor [2]. This class provides methods to control the motor using closed-loop control such as rotate(degrees). The rotate method will rotate the motor a specific amount of degrees, and internally it uses the tachometer to ensure the motor rotates the requested amount. This means it works regardless of battery voltage, motor load etc and is a good example of closed-loop control. The CarTray class uses the rotate method to ensure it consistently moves the gate the proper distance.

The code for the constructor can be seen in Figure 5. The interesting part here is the resetGateToStartPos() method call which we will explained in section 4.2.2.


Figure 5: The code for the CarTray constructor.

4.2.1 releaseItem()

Figure 6: The code for the CarTray.releaseItem method.
The releaseItem() method can be seen in Figure 6. Assuming that the gate is closed when the method is called (which it will always be per the invariant discussed in the next section) it will rotate the gate motor the specified amount of degrees, and then rotate it the exact same negative amount. This is equivalent to opening and then closing the gate. GATE_UP_ROTATE_ANGLE is the rotation angle that corresponds to opening the gate the required amount. We found this value (-60) by experimentation.

4.2.2 Gate invariant

As mentioned in the preceding section it's important that the gate is closed when releaseItem() is called. If it's not the tray may physically break due to excessive force from the motors. Of course we cannot control what happens outside the car tray class, so we can only prove that the class itself conforms to the invariant. To prove the invariant we need to argue for two cases:

  1. The gate is closed before releaseItem() is called
  2. The gate is closed after releaseItem() is called
It's easy to argue for the second case: releasteItem() always closes the gate before it returns. In the first case it's a bit harder because we have no idea which state the gate is in the first time releaseItem() is called. It may be fully open, closed or anywhere in between. For example if the NXT runs out of power just as the car tray is opening the gate it may leave it open. When the NXT is recharged it will start with the gate open unless it's manually pushed back to the start position. For a fully automatic sorting system manually resetting the gate position every time something goes wrong is not an option.

Instead what we have done is to automatically close the gate before releaseItem() is called the first time. This is what the call to resetGateToStartPos() in the constructor does. The code for this method can be seen in Figure 7. What this code does is that first it sets some values for the motor (the stall values discussed in a moment). Then it tells the gate motor to drive forward and waits for the gate to be closed (we discuss how it does this in a moment). When the gate is closed we move it just a bit up again in the moveGateToAvoidMakingWeirdSoundWhenClosing method. The reason we do this is, as the method says, to avoid that the gate makes a "klonk" sound when it closes. If the gate is leaning against the bottom, then when it's told to open and close, it will hit the bottom when closing. There's nothing wrong with that other than it's an annoying sound, so we'd rather avoid it.

Figure 7: The code for the CarTray.resetGateToStartPos method.

Waiting for the gate to close is not as easy as it sounds: basically it's a matter of rotating the motor until the gate is closed, but how do we know when the gate is closed when we don't know it's starting position and all we have for sensing the environment is the tachometer inside the motor? It turns out RegulatedMotor has two methods that can help us deal with this: isStalled() and setStallThreshold(). The isStalled method detects whether the motor is currently stalled. A motor is stalled if it's trying to move but can't (e.g. if rotate is called but the motor can't rotate due to being stuck). setStallThreshold allows setting some parameters that affects when a motor is considered to be stalled. This sounds simple but in practice it was a real challenge to figure out exactly what the parameters to the setStallThreshold method do. The JavaDoc for the method states the setStallThreshold takes two parameters; the first is error which is the amount the motor should lag behind the regulated position before being considered stalled. The second parameter is time which is the time that the error threshold needs to be exceeded for to be considered stalled. It took a few tries to figure out what values we should use for these parameters but in the end we settled at error=1 and time=100. As can be seen from Figure 8, with these values the gate closes perfectly.

Figure 8: With stall threshold values error=1 and time=100 the gate closes perfectly.

5. Conclusion

We have carefully designed the car tray to meet the requirements for the physical construction. In particular we were able to make the gate close in only half a second. This is a good result.
Regarding the software, it was challenging to correctly use the leJOS API for stall detection. We tried with different stall detection values, and ended up with error=1 and time=100ms.

6. Next lab

In the next lab we'll start working on the distributor car that should carry the tray.

7. References

[1] “Embedded Systems, Embodied Agents - Lecture slides week 2 - Slide 3.” [Online]. Available: http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lectures/Lecture2/Lecture.pdf. [Accessed: 05-Jun-2013].
[2] “RegulatedMotor (leJOS NXJ PC-API documentation).” [Online]. Available: http://lejos.sourceforge.net/nxt/pc/api/lejos/robotics/RegulatedMotor.html. [Accessed: 24-Jun-2013].

Posted on 9:00 AM | Categories:

Project lab 3 - Distributor ideas

Date: 03/06/2013
Duration of activity: 12:00-16:00 --> 4 hours
Group members participating: Ole Rasmussen and Kasper Føns

1. Goal

The goal of this lab sessions is to think about how we should store the sorted bricks, how we should get a sorted brick to its storage and what type of actuators and sensors we need. In one sentence, we need to think about how we will implement the distributor submodule.

2. Plan

Our plan is to start figuring out how we want to store the bricks. We will then find out how we get the bricks into the storage unit.

3. Storage

We first needed to figure out how we should store the sorted Lego bricks.

3.1 Wooden construction

One idea was to use a pre-built wooden construction that included compartments at the sides as seen on Figure 1. The distributor should then drive to the designated area and drop off the brick.

Figure 1: Wooden construction with storage units for sorted bricks at the side. The distributor would deliver pieces to the correct compartment by using the black lines as guide.
We believe such a setup would be slow, since we need a robot that can drive on the wooden plate, turn to the correct side and eject the item while making sure that it is following the black lines. The compartments are also very large, too few and when they begin to get full, the bricks could begin to fall out onto the driving area.

3.2 Conveyor belt

Another idea we had, was to have a conveyor belt bringing bricks forward, have storage units at each side of the belt and have motor controlled arms to push bricks into the correct storage units. A sketch can be seen in Figure 2. We also discussed removing the statically placed arms and replacing them with a single car that should drive on a track on top of the conveyor belt. It would then need to drive back and forth to the correct compartments and push bricks down when they were passing the designated compartment. This would remove a lot of motors and would allow us to use a PID controlled car [1].

Figure 2: A system where a conveyor belt transport bricks and arms pushes them down into their designated storage units based on their lengths.

3.3 Driving on top of Lego trays

In the end we settled on a solution where we could use the Lego trays seen on Figure 3 which were already used as storage units in the Lego Lab. The compartments have a perfect size and we could use a tray for each sorted brick type, i.e. one for beams and one for axles. The next step was to find a way to put the pieces into the correct tray compartment.

Figure 3: Lego Tray already used in the Lego Lab. This particular tray stores beams.

4. Distributing bricks to correct tray compartments

An idea for distributing bricks into the correct compartment, was to have a crane-type system, where a brick would be picked up and then dropped into the right compartment by a crane. Axles are very small and slippery and could pose a problem for our pick-up mechanism. We were therefore unsure if we could create a robust crane solution. 

We ended up deciding to build a platform around the tray instead. A car driving on top of the platform should be able to move both sideways and back and forth. The car should have a tray mechanism to transport and release the bricks at the correct compartments.

We needed to create a construction where the car could make sure that it was at the correct location before dropping a brick. We first thought about an open-loop control program [2], powering the motors for a certain amount of time. We discarded the idea since we could build a far more robust solution if we used feedback from the environment, which could be sensed by light sensors, touch sensors or tachocounters. We therefore choose to implement a closed-loop control program [2] where we would use only tachocounters, simplifying the construction considerably compared to adding touch sensors or light sensors. We decided to use toothed bars and gearwheels as wheels to drive the car around to give us maximum traction.

5. Conclusion

We settled on constructing a platform around the normal Lego Trays seen in Figure 3, which are already being used in the Lego Lab. To do this we need to construct a car that can move on the platform and when given a brick can place it in the correct tray compartment.

6. Next lab

We need to make sure that we can build a car that can move precisely on a toothed bar platform. We also need to make the tray holding mechanism for the car. In the next lab we will start with that.

7. References

[1] “Embedded Systems, Embodied Agents - Lecture slides week 2 - Slide 7-17.” [Online]. Available: http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lectures/Lecture2/Lecture.pdf. [Accessed: 05-Jun-2013].
[2] “Embedded Systems, Embodied Agents - Lecture slides week 2 - Slide 3.” [Online]. Available: http://legolab.cs.au.dk/DigitalControl.dir/NXT/Lectures/Lecture2/Lecture.pdf. [Accessed: 05-Jun-2013].

Posted on 9:40 AM | Categories: