Two workstations, tko-dhcp-70.cs.hut.fi and tko-dhcp-71.cs.hut.fi, are reserved for this exercise. These workstations are located in the room A243 in the computing science building. The door to this room is locked even during the office hours, but you can get the magnetic key from the janitor's office. The workstations run RedHat 6.1 and each groups has a group account. Your working methods are up to you, but you should probably at least make a working directory for each of your group members. For synchronisation, CVS and RCS are available. Notice that the workstations are completely separate, and do not share home directories, passwords, or any other such information.
The workstations are accessible remotely by ssh. It is preferred that you try to do as much work from elsewhere, e.g., Niksula, as possible. Try to write and compile your program remotely, and only then come to A243 to test and debug it. And please be careful with Netscape.
Avr-gcc is a C compiler for the micro-controller used in the cars. It is based on egcs, which in turn is based on gcc, so gccisms should work, and because of the nature of the exercise, are allowed. The avr-gcc is run much like gcc (or any other UNIX cc for that matter): "avr-gcc <switches> <files> -o <executable>". Mandatory switches are:
Other switches:
The files may contain C and assembler sources and object files. The files are linked to the final executable in the same order they are given for the avr-gcc. The C runtime crt1 must always be the first file. An already compiled crt1 can be found at /usr/local/avr/lib/crt1-4414.o, or if you feel like it, you can write your own. The order of the other files is irrelevant. For example, your compilation could look something like this:
[apl@tko-dhcp-70 sularit]$ avr-gcc -mmcu=at90s4414 -Os /usr/local/avr/lib/crt1-4414.o /usr/local/avr/lib/mul_16_8.o esim.c eeprom.s -o esim Warning: Virtual symbol `__interrupt0_' is assigned new value. Warning: Virtual symbol `__interrupt1_' is assigned new value. Warning: Virtual symbol `__output_compare1a_' is assigned new value. Warning: Virtual symbol `__output_compare1b_' is assigned new value. Warning: Virtual symbol `__overflow0_' is assigned new value.
The mul_16_8.o is a multiplication routine for a 16-bit and an 8-bit integers, esim.c is the actual program, and eeprom.s is an assembler file containing the data to be written into the EEPROM. This will produce the final executable esim, which can then be uploaded into the car.
The warnings are normal and just tell you that your program overrides some default interrupt handlers, which it should do anyway.
Signed and unsigned char are 8 bits, and signed and unsigned int are 16 bits. You can use normal arithmetics (+, -, *, and /), but you will need to link against /usr/local/lib/gcc-lib/avr/egcs-2.91.66/libgcc.o if you use multiplication or division. (libcgcc should work, but I haven't tested it yet.)
Uisp is the program used to upload the software into the car. It is invoked with the command "uisp /dev/cua0 --AtmelTAvr S8515A", after which you will get a terminal for issuing commands. The important commands are:
For example:
[apl@tko-dhcp-70 sularit]$ uisp /dev/cua0 --AtmelTAvr S8515A Micro In-System Programmer Version 0.1.6, Uros Platise Programmer Info: Software Version: 2.0, Hardware Version: 1.0 Device at90s4414 found. FLASH: 4096 bytes EEPROM: 256 bytes Entering the AVR Terminal. ?-help, q-quit. avr>ce avr>ul esim Uploading: 6eh bytes to flash at 0h Uploading: 3eh bytes to flash at f7ah Uploading: f0ch bytes to flash at 6eh Uploading: fh bytes to eeprom at 0h avr>q Ouch.
Your program starts executing immediatly after you quit uisp, so again, make sure you have the wheels off the ground or table or anything. Even a working program may cause the rear wheels to rotate suddenly.
An example program can be found in /usr/local/lcdexample in both workstations. Copy this directory for yourself, read through the lcdexample.c and hardware.h files, compile it with make, and try it by uploading it into the car. You can use the Makefile as a basis for your own Makefile. It is quite simplistic, but since this is a very small program that is probably all in just one source file, it is enough.
Read the header files io.h, interrupt.h, signal.h, and eeprom.h located in /usr/local/avr/include too.
As you have noticed, the cars are not very sturdy, so please handle them carefully. To lift the cars, grab them from the bottom plate. Avoid grabbing them from the front "bumper" where the sensors are. The top speed of the cars is probably about 50km/h and the accelerate almost instanteniously, so be careful with your program's speed control and when testing, try to have someone ready to grab the car (from the bottom plate!) at all times. If you break one or suspect one is broken, email Antti-Pekka Liedes immediatly.
There are altogether six batteries available for the cars. There are two types: five and six celled. The six celled batteries may drive the cars a bit faster, but other than that, the batteries are equal. When you are using the cars, connect the battery's cable to the car's corresponding cable. Note that black and red leads are on the same side for each connector. To charge the batteries, plug them into one of the two small black boxes that say "Type 9315" on them. Here the charger's white and black lead goes to the same side with the battery's red lead, and the charger's black lead goes to the same side with the battery's black lead. The chargers are automatic, you can leave the batteries charging without fearing they will overcharge. Every time you leave, unless another group is coming in immediatly after you, leave the battery you have used charging.
The car contains the following hardware:
See the data-sheet for a complete description of the micro-controller. The controller has only 4kB of program memory, which is very little. As some kind of a guideline, a program of 851 lines of C source just fits into the memory, but of course this depends on how much functions you use etc. For variables, 256 bytes of SRAM is used. In addition, 256 bytes of preprogrammable EEPROM are usable with the functions eeprom_rb and eeprom_wb, defined in the eeprom.h (located in /usr/local/avr/include).
The other hardware is connected to the four 8-pin I/O ports of the microcontroller:
The ports are controlled by the following functions:
Important: sbi and cbi work only for external I/O, i.e., the ports A, B, C, and D. The registers of the controller must be accessed with outp and inp.
To select which pins are input and which are output, the outp function described above is used, but to write to addresses DDRA, DDRB, DDRC, and DDRD. The value is 8 bits, each bit describing the function of the corresponding pin: 1 for output, and 0 for input.
The SIGNAL macro is used to set different interrupt handlers. For example, to define the handler for overflowing of the counter 0:
SIGNAL(SIG_OVERFLOW0) { /* Make your program react somehow. */ ... }
The interrupt handlers are really just functions that receive no arguments and return nothing. For more information and a complete list of the available interrupts, see the data-sheet.
A complete description of the LCD-controller can be found in its data-sheet. Using the LCD is by no means required, but it is a handy tool while testing and debugging. The LCD is controlled by setting the register select, the read/write signals, and the I/O bus to right values for the command, and giving a HIGH pulse with the LCD enable. For an example code, see /usr/local/lcdexample in the workstations. Connections for the LCD are:
The keyboard is a 4x4 switch matrix, which can be accessed using the PA bus after enabling it with PD7 LOW. Before enabling the keyboard, pins PA0...PA3 must be configured as inputs, and the pins PA4...PA7 as outputs. After doing this and enabling the keyboard, you can check which button(s) are pressed by probing one line at a time using PA4...PA7 outputs and checking which of the PA0...PA3 inputs are set. The matrix is connected like this:
PA0 | PA1 | PA2 | PA3 | |
PA4 | "A" | "0" | "B" | "C" |
PA5 | "7" | "8" | "9" | "D" |
PA6 | "4" | "5" | "6" | "E" |
PA7 | "1" | "2" | "3" | "F" |
The front bumper contains two sets of IR-transmitters and one set of IR-receivers. The transmitter sets are enabled with PB0 and PB1 HIGH. To save the battery, the transmitters should be turned on only when needed.
The divider is used to set the modulation frequency of the transmitters. The receivers are most sensitive to the modulation frequency of 30kHz, but a more practical value is probably 15kHz. The divider shares the PA-bus along with the LCD and the keyboard. To set the divider value, set PA to the value you want, and enable and disable the divider. Keep the LCD and the keyboard disable during this.
The divider does not use a normal 8-bit integer, but a BCD number. The value is (4 MSB * 10 + 4 LSB), though values other than 0-9 are legtimate in both MSB and LSB. The final modulation frequency is the system clock (2MHz), divided by 2 * the divider value (because it's driven through an extra D-flipflop).
The IR-receivers are connected to the PC-bus, one receiver per bit. The receivers are active LOW (meaning they give 0 when they think they detect something), but the signal is never all HIGH or all LOW, but rather, it's more LOW than HIGH on the average. You'll have to add together a number of input values for each of the sensors and from the sums deduce where the tape is.
Important: The green car acts the way it's supposed to, but the blue car's IR-sensors give more HIGH than LOW when they detect the tape. It's always good if you can get the same program to work with both cars (with slight modifications; my own program requires an extra bitwise NOT for one car), but you are not required to do this, it is enough if your program can drive one car.
The tachometer is located to the right rear wheel of the car. It has two ports connected to PD2 and PD1. The port in PD2 gives the interrupt INT0 at both edges of the signal, i.e., when a black line comes into or leaves from the port. The best way to measure speed is probably to count the number of pulses over a certain time interval.
The car has two servos, one for steering and one for motor power control. The power control "servo" is actually an electronic speed controller, but for all practical purposes, you can think of it as just another servo. Both of the servos are controlled by a pulse width modulation signal. The length of one cycle of the signal is 20ms. The signal stays HIGH for some time X from the beginning of the cycle, and then LOW for the rest of the cycle, i.e., 20ms - X. The position of the servo depends on the time time X. The center position is 1.5ms, and the edges 1.25ms and 1.75ms.
When steering the car, set the minimum and maximum positions for the servo so that it does not stress the mechanics of the car. If you try to steer more than the wheels can actually turn, the servo may partially or completely detach from the bottom plate! The edge values you should use at first are 1.3ms and 1.7ms
When controlling the motor power, give it a slight nudge at a high power value, but then lower the power immediatly. If you keep the power high, the car will accelerate very rapidly. The nudge may be necessary to get the car moving. But do not turn the power completely off when the car starts moving, or you will stop the car.
The micro-controllers of the cars operate at 2MHz. Look at what the on-chip counter 1 can do for you.
More about the hardware available soon in an Internet near you. Meanwhile, you can read the hardware documentation from Tampere.
The document should contain the following:
/* SPEED CONTROL */
to
different areas to distinguish the code belonging to these
components.
Your document doesn't need to be long, a few pages with good information content is probably the best, excluding the front page and source code. Write it with something that produces readable text (LaTeX etc.), and use enscript only for the source code printing. A good picture is always nice, where relevant. Return the document in your demo, or in the seminar.
Antti-Pekka Liedes
2000-02-15