CSC231 Lab 7
Back to CSC231 Weekly Schedule
CSC 231 Lab # 7
© D. Thiebaut, 2008
You do not need any of the files we created last week, so you can start fresh with Ubuntu.
You still need to login as root, though, and go to the /root directory, which is the place where you will store your C and ASM files.
Input/Output PC to Arduino: Part I
In this first part you will enter commands at the Linux prompt to set the Arduino LED 13 On and Off, or to read the status of various pins.
Don't miss the presentation that will be done in class. We'll go over the 3 programs involved in today's lab.
The Arduino program: arduino_loop.pde
- First take a close look at the program that runs on the arduino: arduino_loop.pde, whose code is available here. Notice how the loop function continuously store incoming characters in the buffer until a \n character is found, in which case the contents of the buffer is analyzed, the command identified, and executed.
- Cut and paste arduino_loop.pde in the arduino GUI on your Ubuntu machine.
- Compile it.
- Upload it to the Arduino.
The C-Program running on the Ubuntu: arduino-serial.c
- Take a close look at arduino-serial.c . It is the program running on the Ubuntu PC/laptop. You should copy/paste it into an emacs window and save it to your working directory.
- compile the program as follows:
gcc -o arduino-serial arduino-serial.c
- run it as follows:
./arduino-serial -b 9600 -p /dev/ttyUSB0 -s "w d 13 1"
- where -b is the switch used to set the communication speed (9600 baud--very slow), -p is used to set the port associated with the USB connection, and -s means Send a message to the arduino. Here the message is Write a 1 on Digital Pin 13 of the arduino.
- Try to read the digital pins, too:
./arduino-serial -b 9600 -p /dev/ttyUSB0 -s "r d" -r
- In this case you make the program send a string first (the request to read), and receive next. In receive mode, the arduino-serial program simply wait and fills a buffer with characters received until it gets a '\n' character. Then it displays what it has received.
EXERCISE #1 Modify the command line so that you will turn Pin 13 ON, then OFF, then ON, then OFF again. |
EXERCISE #2 Look at the code of serial-arduino.c and figure out how you can make the program wait for a few ms or seconds between commands. Once you have figure this out, repeat Exercise 1 but make the LED stay ON for a second before being turned OFF, and similarly make it stay OFF a second before being turnd ON again. |
EXERCISE #3
|
The Assembly Program
Step 1: C + asm = new program
You will have probably noticed the two commented lines in serial-arduino containing asm_main in them, one to indicate that asm_main is extern, i.e. defined somewhere else, and one to call it at the end of the loop that processes the command line arguments.
- Uncomment the two asm_main statements, please.
- On the Ubuntu PC, open emacs and create a file called talkToArduino.asm
;;; talkToArduino.asm
;;; D. Thiebaut
;;;
;;; nasm -f elf talkToArduino.asm
;;; gcc -o talkToArduino arduino-serial.c talkToArduino.o
;;;
;;; ----------------------- EXTERN LABELS -----------------------
extern serialport_writebyte ; int function
extern serialport_write ; int function
extern serialport_read_until ; int function
extern displayBuffer ; int function
extern buf
extern byte
;; -------------------------
;; data segment
;; -------------------------
section .data
msg1 db "w d 13 1", 0
msg1len equ $-msg1
;; -------------------------
;; code area
;; -------------------------
section .text
global asm_main
asm_main:
;; turn Pin 13 On
mov eax, msg1
mov ecx, msg1len
call copyMsg ;create copy of msg1 in buf, in C prog
call serialport_write ;call function in C prog
;; return to C program
ret
;;; ----------------------------------------------------------------
;;; copyMsg1: puts array whose address in eax in external buffer
;;; number of bytes shoudl be in ecx.
;;; ----------------------------------------------------------------
copyMsg:
pushad
mov esi, eax ; source buffer
mov edi, buf ; destination buffer in C program
.for mov al, [esi]
mov [edi], al
inc esi
inc edi
loop .for
popad
ret
- Assemble the program and link it with the C program:
nasm -f elf talkToArduino.asm gcc -o arduino-serial arduino-serial.c talkToArduino.o
- Make sure Pin 13 is off. Then run the program, but without specifying any options relating to the pins. This time we want the assembly program to do the work!
./arduino-serial -b 9600 -p /dev/ttyUSB0
- Did the pin turn off? If not, there's a problem with your setup. Double check everything we have done so far.
Step 2: More assembly
EXERCISE #4 Modify the assembly language program and add another message, msg2, that can be used to turn Pin 13 Off. Modify the body of the asm_main function so that it will turn Pin 13 ON and OFF a few times. |
We saw how to create a delay last week: if we know the speed of the processor in GHz, and if we assume it takes 1 cycle to execute an instruction (not a bad assumption), then we can create a delay that is fairly close to what we need.
For example, if we want to create a delay of 1 second, and the processor is a 2 GHz processor, then something like the function below would force the processor to wait about a tenth of a second:
;;; ----------------------------------------------------------------
;;; delay 100 ms, or 0.1 sec
;;; ----------------------------------------------------------------
delay100ms:
pushad
mov ecx, 100000000 ; 2 x 100,000,000 cycles (assuming 2GHz)
.for add eax, 1 ; 1 cycle
loop .for ; 1 cycle
popad
ret
- Note: this is a pretty bad way of creating a delay. The better solution is to use something like the sleep() or usleep() functions that use the system clock to measure the delay, and they actually do sleep most of the time, rather than consume processor cycles for no good reason.
EXERCISE #5 Add the delay function to your assembly program and make Pin 13 blink with a 0.1 sec delay between transitions. |
Step 3: reading the status of a pin
We are now going to do the same experiment of Exercise 3, but this time the assembly program will
- Pick a pin, say Pin 3, and connect a wire to it. Then connect this wire to GND, or to +5V.
- send a command to the Arduino to request the status of all the pins
- read a string from the Arduino
- figure out where Pin 3 appears in the string
- get the '0' or the '1' corresponding to Pin 3
- put this '0' or this '1' character at the 7th position of a string that contains "w d 13 ?"
- send this string to the Arduino to turn Pin 13 ON or OFF, depending on what Pin 3 is connected to.
Let's take it one step at a time. Reading the status of the pins requires 2 steps, illustrated below:
section .data
msg3 db "r d", 0
msg3len equ $-msg3
section .text
mov eax, msg3
mov ecx, msg3len ; "r d" read digital pins
call copyMsg ; now buf contains "r d"
call serialport_write
call serialport_read_until
call displayBuffer
DisplayBuffer is a C function that simply displays the string used to communicate with the Arduino. By looking at the string you should be able to figure out where the character for Pin 3 is located.
EXERCISE #6 Go ahead and make your assembly program implement all the steps required! |
Terribly Important Thing to Remember!
Make sure you copy the contents of the /root folder (containing the Arduino-0010 folder, and all your C and .asm programs) to your USB memory stick, otherwise you will have lost all your work when you restart your Ubuntu computer!
You may also send the code to yourself using a Web based mail-service (gmail, groupwise, etc...)
References and Useful Links
- The Arduino Reference Page if you need to debug your sketch...
- You may want to check what you did in Lab 6.