CSC231 Lab 7

From dftwiki3
Revision as of 14:55, 21 October 2010 by Thiebaut (talk | contribs) (The C-Program running on the Ubuntu: arduino-serial.c)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

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

  • Take a wire and connect it between Pin 3 of the Arduino connector and Ground.
  • Use serial-arduino to request a list of the values currently on the digital pins.
  • Identify Pin 3 in the list of 0s and 1s (you will need to see how arduino_loop.pde generates the string of 1s and 0s).
  • Now connect Pin 3 to Vcc using the same wire. Now Pin 3 sees a high voltage.
  • Use serial-arduino to read the digital pins
  • Verify that you can read the changing value of Pin 3 this way.nbsp;                                                                                                                                     




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

  1. Pick a pin, say Pin 3, and connect a wire to it. Then connect this wire to GND, or to +5V.
  2. send a command to the Arduino to request the status of all the pins
  3. read a string from the Arduino
  4. figure out where Pin 3 appears in the string
  5. get the '0' or the '1' corresponding to Pin 3
  6. put this '0' or this '1' character at the 7th position of a string that contains "w d 13 ?"
  7. 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