231a-ac Lab7

From CSclasswiki
Jump to: navigation, search

Input/Output PC to Arduino: Part I

In this lab, I first enter commands at the Linux prompt to send/receive Arduino pin status via arduino-serial.c. Then I modify the assembly program talkToArduino.asm, which is compatible to arduino-serial.c, to directly "talk" to Arduino.

My lab partner is Rae.

The Arduino program: arduino_loop.pde

We cut and paste arduino_loop.pde in the arduino GUI on our Ubuntu machine, then compile it and upload it to the Arduino.

The C-Program running on the Ubuntu: arduino-serial.c

We compiled arduino-serial.c as follows:

gcc  -o  arduino-serial  arduino-serial.c

and 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.

Pin 13 of Arduino is now on.

Then we try to read the digital pins, too:

./arduino-serial -b 9600 -p /dev/ttyUSB0 -s "r d" -r

This makes 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

The command line as following turns Pin 13 ON, then OFF, then ON, then OFF again:

./arduino-serial -b 9600 -p /dev/ttyUSB0  -s "w d 13 1" -s "w d 13 0" -s "w d 13 1" -s "w d 13 0"

Exercise #2

The command line option -d [time] makes the program wait for a few ms between commands. The following command makes the LED stay ON for a second before being turned OFF.

./arduino-serial -b 9600 -p /dev/ttyUSB0  -s "w d 13 1" -d 1000 -s "w d 13 0"

The following command makes the LED stay OFF a second before being turnd ON again.

./arduino-serial -b 9600 -p /dev/ttyUSB0  -s "w d 13 0" -d 1000 -s "w d 13 1"

Exercise #3

We take a wire and connect it between Pin 3 of the Arduino connector and Ground. The command-line option -s "r d" -r is used to request a list of the values currently on the digital pins. The output is:

d 0 0 0  0 0 0  0 0 0  0 0 0

Pin 3 is the second zero in the list. Now we connect Pin 3 to Vcc using the same wire. Now Pin 3 sees a high voltage. The output for reading digital pins using serial-arduino.c is:

d 1 1 1 0 0 1 1 1 1 1 0 0 0

Notice that the status of Pin 3 changes from 0 to 1.

The assembly program

Step 1: C + asm = new program

First we uncomment the two asm_main statements in arduino-serial.c, one to indicate that asm_main is extern, and one to call it at the end of the loop that processes the command line arguments.

We assemble talkToArduino.asm and link it with the C program:

nasm -f elf talkToArduino.asm

gcc -o arduino-serial  arduino-serial.c  talkToArduino.o

We make sure Pin 13 is turned off before running this program:

./arduino-serial -b 9600 -p /dev/ttyUSB0

Now Pin 13 is turned on.

Step 2: More assembly

EXERCISE #4

We add to the assembly program another message, msg2, that can be used to turn Pin 13 Off. With the following modification in the asm_main function, the assembly language program turn Pin 13 ON and OFF 5 times.

asm_main:
	mov  ecx,5
for:	
	;; 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

        ;;	turn Pin 13 off
  	mov	eax, msg2
  	mov	ecx, msg2len
  	call	copyMsg                     ;create copy of msg1 in buf, in C prog
  	call	serialport_write           ;call function in C prog
	loop	for

        ;; return to C program
        ret

EXERCISE #5

The below function creates a delay of 1 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

We add this delay function to the assembly program to make Pin 13 blink with a 0.1 sec delay between transitions:

asm_main:
	mov  ecx,5
for:	
	;; 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

	call	delay100ms                ;delay .1 second

        ;;	turn Pin 13 off
  	mov	eax, msg2
  	mov	ecx, msg2len
  	call	copyMsg                     ;create copy of msg1 in buf, in C prog
  	call	serialport_write           ;call function in C prog
	loop	for

        ;; return to C program
        ret

Step 3: reading the status of a pin

EXERCISE #6

Now I do the same experiment of Exercise 3, but this time using a assembly program.

I connect a wire to Pin 3, then connect it to +5V.

To send a command to the Arduino to request the status of all the pins, I called the below function in asm_main.

;;; ---------------------------------------------------------------
;;; read_buffer: read and display buffer
;;; modified registers: eax,ecx
;;; ---------------------------------------------------------------
read_buffer:
	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   ; display the buffer
	ret

msg3 is defined in the data section as following:

section .data
msg3	db	"r d", 0
msg3len	equ	$-msg3

The program prints:

buffer = [d 0 1 1 0 0 0 0 0 0 0 1 1 

When I change the wire to GND, the program prints

buffer = [d 0 0 0 0 1 0 1 1 1 1 1 1 

Pin 3 is the second number.


The following modifications in the data section and in asm_main turns Pin 13 ON or OFF, depending on what Pin 3 is connected to.

To get the '0' or the '1' corresponding to Pin 3, I need to get the byte that represents Pin3's status in memory. Since buf is the buffer array in the C program, the byte that represents Pin3's status is at [buf+4]. (spaces between each 0 and 1 are counted). By putting this '0' or this '1' character at the 7th position of msg, a command that contains "w d 13 ?", the program can sends Pin 3's status to Pin 13.

        ;; -------------------------
        ;; data segment
        ;; -------------------------
        section .data
msg	db	"w d 13 ?",0
msglen	equ	$-msg

        ;; -------------------------
        ;; code area
        ;; -------------------------

	;; turn Pin13 on/off based on Pin3
	mov	dl,[buf+4]	;    get 0 or 1 from pin3
	mov	byte[msg+7],dl	;    set character '?' in msg to 0 or 1
	mov	eax,msg		;    write msg to buffer
	mov	ecx,msglen	    
	call	copyMsg		
	call    serialport_write

        ret