Programming Embedded Systems (2006) - lab1at BTH, Fall 2006
Lab Assignment 1 - The Higher Striker Experiment
This lab assignment is about programming the real-time control experiment "Higher-Striker". The experiment consists of a tube of glass surrounded by 7 electromagnets. In the experiment an iron cylinder has to be accelerated by switching the magnets on and off in an adequate order. Position information can be aquired from light barriers among the tube. The experiment relies on a dual-ported FIFO memory to buffer experiment data. Hard deadlines of the control software for buffer refill can be configured by varying the used buffer size from 0 to 255. Because of the sampling frequency of 38,4 KHz the max. deadline of the controlling task is 6 ms. Because of the high speed of the cylinder this control delay caused by the buffer must be reduced.
The experiment hardware is connected to a X86-PC running Windows Ce.NET 4.2 as operating system. The experiment hardware is connected via the parallel port interface. Details about the architecture and programming of the parallel port interface can be found here. The parallel port can be programmed using memory mapped I/O via 3 registers namely data, control, and status register. On the experiment they are configured as follows:
The following picture shows the layout of the experiment's control hardware. On the bottom of the picture you can see the three 8-Bit lines of the parallel port, which are conntected to the control PC. The data lines are directly connected to the data pins of the dual-ported FIFO memory chips.
The lines of the status line, shown in the middle of the picture, are connected to:
|bit 3||full flag of magnet buffer|
|bit 4||empty flag of light barrier buffer|
|bit 5||generell hardware error flag|
|bit 6||half full flag of ligth barrier buffer|
|bit 7||empty flag of magnet buffer|
As an example the empty flag of the light barrier buffer can be checked like this: if((IO.ReadByte(0x03BD) & 0x10) == 0)
Because of the restricted number of bits, the control line is connected to a demultiplexer, providing access to the control pins of the FIFO-buffers and the frequency generator (timer). In order to access e.g. the READ_ENABLE-pin of the magnet FIFO buffer, it must be selected via the demultiplexer and the data line conntected to Pin 0 must be programmed in parallel. The following table shows the coding of the multiplexer:
|0x02||RESET pin of both FIFO chips|
|0x0C||READ_ENABLE pin of ligth barrier buffer|
|0x06||WRITE_ENABLE pin of magnet buffer|
|0x00||frequency generator (timer) start|
|0x0E||frequency generator (timer) stop|
As an example the RESET-pin can be selected by: IO.WriteByte(0x03BE, 0x02 | DATA). DATA can be 0 or 1 and causes a HIGH or LOW voltage on the pin.
The experiment data is sampled synchronously with a frequency of 38,4 kHz into the dual-ported FIFO memory. The data can be read/writen asynchronously via the parallel port by sending control signals via the control line and reading/writing the data register. Reading and writing is indicated by raising the voltage of the READ_ENABLE / WRITE_ENABLE-pin of the dual-ported memory chip. The technical specification of the chip can be found here. Please read the specification carefully and understand the functioning of the chip.
In order to control the experiment correct values must be inserted into the magnet buffer, while content of the ligth barrier buffer must be evaluated. During start-up the two memories must be reset as described in the chip specification. Afterwards initial values must be stored in the magnet buffer. After the start of the timer, data from the magnet buffer is transfered to the magnets, while in parallel information of the light barriers is sampled into the ligth barrier buffer. The control program must continously read/write new data to/from the memories. The buffers must never run empty. Otherwise the experiment run will fail, while false data is send to the magnets. Depending on the number of initially provided data in the magnet buffer, the memory must be refilled slower or faster. For example an initial buffer size of 10 causes a deadline of 0,26 ms for buffer refill. The higher the initial buffer size is, the higher the deadline, but on the other hand the control delay is higher as well.
The magnets among the tube are numbered and coded as follows (the provided values must be written into the buffers) (only one magnet can be enabled at a time):
|0x00||No magnet enabled|
|0x02||magnet 1 enabled (top of tube)|
|0x04||magnet 2 enabled|
|0x06||magnet 3 enabled|
|0x08||magnet 4 enabled|
|0x0a||magnet 5 enabled|
|0x0c||magnet 6 enabled|
|0x0e||magnet 7 enabled (bottom of tube : should be enabled first)|
The light barriers are positioned in the middle of two magnets with a distance of 18 cm and coded as follows:
|0x00||no ligth barrier enabled|
|0x01||ligth barrier 1 enabled (top of tube)|
|0x02||ligth barrier 2 enabled|
|0x04||ligth barrier 3 enabled|
|0x08||ligth barrier 4 enabled|
|0x16||ligth barrier 5 enabled|
|0x32||ligth barrier 6 enabled (bottom of tube)|
The experiment can be accessed via the Distributed Control Lab. In
the lab a prototype of the Real-Time.Net framework is installed,
allowing to implement the control application in C#. In order to
develop a control application you should read about the language C#
first. Introductions to C# can easily be found in the Internet. C#
is quite similar to Java.
HigherStrikerController. HDLAccess provides basic I/O operations such as reading one entry from the ligth barrier buffer, writing one entry to the magnet buffer, starting/stopping the timer, resetting the memories and reading the status line. The class uses the method ReadByte and
WriteByte, which are implemented nativily and are provided in the experiment setup.
HDLPerformprovides a higher level of abstraction. There are methods for initializing the buffer with an array of entries, and most importent the method Perform. This method write one entry to the magnet and reads one entry from the ligth barriers, keeping the number of read/written bytes synchronized. Finally the class HigherStrikerController contains the control algorithm. The controller logic uses the methods of the class HDLPerform.
- Please go through the provided code and implement the missing
methods of the
Reset. All neccessary constants are provided in the code.
- Implement the method
Initializeof the class
- Implement the main loop of the control algorithm by executing
HDLPerformas long as there are entries in the light barrier buffer. Use the status register to check the empty flag of the ligth barrier buffer. If the buffer is empty recheck the empty flag using sleepy wait:
Make sure that there is no error condition at the other flags (e.g. empty flag of magnet buffer is on). Please write only 0 to the magnet's buffer until you are sure that the main-loop-algorithm is working. For debugging the can use the
Console.WriteLine()methods. But be aware that you are using a prototype compiler. Not all versions of
Console.WriteLine()are implemented. Remind that the usage of
Console.WriteLinecauses unpredictable timely behavior. Write debug output at the end of the experiment run.
Be aware that there is a watch dog running in the experiment-PC that reboots the computer if the watch dog is not signalled for 5 sec. Don't use busy wait anywhere! After a reboot you will not get any debug output.
- After the implementation of the main I/O loop try to shoot the cylinder up using the first magnet only. A good time for the first magnet is about 1000 time units. The cylinder will fly up ca. 20 cm. Try to change the time and evaluate the speed of the cylinder at the first light barrier.
- Implement an algorithm that accerlates the cylinder using position information from the light barriers. Please think about the physics of the experiment first. Consider an accelerated movement including gravity.
- Have fun! And please ask if you have any problems!
created by Andreas Rasche