231a-ab Lab 7

From CSclasswiki
Jump to: navigation, search

Objective

The objective of this lab is to investigate how to read input from Arduino and output to the Arduino from and to a PC.

Necessary files

  • arduino_loop.pde : to be saved as an Arduino sketchbook so need to copy to Arduino GUI. After copying, compile the file then upload to Arduino.
  • arduino-serial.c : to be saved and compiled in terminal
  • talkToArduino.asm : to be saved and compiled in terminal

If working in Ubuntu, save files regularly to secondary memory.

Using C to talk to the Arduino

Make sure that Arduino is connected and the file arduino_loop.pde has been uploaded.

Compile arduino-serial.c as follows

gcc  -o  arduino-serial  arduino-serial.c 

Then try the following command

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

where -b is used to set communication speed (9600 baud=very slow), -p is used to set the port associated with the USB connection, and -s is used to send a message to the arduino. Here the message is Write a 1 on Digital Pin 13 of the Arduino.
After running the command, LED pin 13 should light up. Try another command

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

The message sent here is Read Digital pins. The arduino-serial.c program is set to Receive mode where it receives characters and put it in a buffer until it receives "\n" then it displays what it received.
The output on the terminal is as follows:

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

To turn pin 13 ON, then OFF, then ON, then OFF again, type the following in the command line:

./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"

What happens? Well, if the pin 13 LED was on, it just seemed that it just turned off. This is because there was no delay between the pin 13 going on and off. The program arduino-serial.c has a delay function which can be used in this way to create a one-second delay between the pin 13 going on and off:

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

Now, pin 13 really seems like it is blinking.

For the next exercise, take a wire and connect pin 3 to Gnd. Then type the following command in the terminal to read all the digital pins:

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

The output should look something like this:

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

Before, the last output was a "1" because pin 13 was on and now, since pin 13 is off, the last digit is "0". The program arduino_loop.pde which output corresponds to which pin. In the function "readPins", the first pin read is 2 so from the output above, it can be concluded that the second "0" corresponds to pin 3. There is an easy way to check this. Instead of connecting pin 3 and Gnd, connect pin 3 and 5V then run the same command to read the digital pins. The output should now look something like this:

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

Since pin 3 is now connected to 5V, it is receiving a high voltage which makes the output "1".

Using C and Assembly to talk to the Arduino

In the program, arduino-serial.c, uncomment the two asm_main statements. Then, assemble the talkToArduino.asm and link it to arduino-serial.c:

nasm -f elf talkToArduino.asm
gcc -o arduino-serial  arduino-serial.c  talkToArduino.o

Make sure that pin 13 is off, then run the following command:

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

If the setup is properly done, pin 13 should now be on.


For pin 13 to turn on and off, both the data and the body sections of the assembly program need to be modified. An example to do this is using the following code (extern labels and copyMsg remain unchanged):

        ;; -------------------------
        ;; data segment
        ;; -------------------------
        section .data 
msg1	db	"w d 13 1", 0
msg1len	equ	$-msg1
msg2	db	"w d 13 0", 0
msg2len	equ	$-msg2
	
        ;; -------------------------
        ;; code area
        ;; -------------------------
        section .text
        global  asm_main
asm_main: 
      ;; turn pin 13 on and off 20 times
	push	ebx
	mov	ebx, 20
blink:	
      ;; 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 msg2 in buf, in C prog
 	call	serialport_write		;call function in C prog
  
  	dec	ebx
 	cmp	ebx, 0
 	jne	blink
  	pop 	ebx
        ;; return to C program
         ret

Reassemble the talkToArduino.asm file and relink it with arduino-serial.c. Run it the same way as before.


If pin 13 was off, it seems that it turns on for some milliseconds and turn off again. The problem is that the LED is blinking too fast. To solve this, add a delay to see that the LED is actually turning on and off. Add the following code to the end of talkToArduino.asm:

;;; ----------------------------------------------------------------
;;; 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

Then, call the delay function between turning the LED on and turning it off:

;; turn Pin 13 On
...
call serialport_write

call delay100ms

;; turn Pin 13 Off
...

For a challenge, do the following steps:
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.

An example solution:

;;; ----------------------- 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
msg	db	"w d 13 "
onePin	db	'?', 0
msglen	equ	$-msg
       
        ;; -------------------------
        ;; code area
        ;; -------------------------
        section .text
        global  asm_main
asm_main:
	call	readPin
	call	setPin
        ;; 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

;;; ----------------------------------------------------------------
;;; readPin: reads the value of pin 3
;;; ----------------------------------------------------------------
readPin:
      ;; writes reading msg
	mov	eax, msg
	mov	ecx, msglen
	call	copyMsg
	call	serialport_write
      ;; reads input and output result on screen
	call	serialport_read_until
	call	displayBuffer
      ;; move value of pin 3 to al
	mov	al, [buf+4]
	ret

;;; ----------------------------------------------------------------
;;; setPin: set the value of pin 13 with whatever value pin 3 has
;;; ----------------------------------------------------------------
setPin:
	pushad
      ;; add value of pin to write msg that will either turn pin 13 on or off
	mov	[onePin], al
	mov	eax, msg4
	mov	ecx, msg4len
	call	copyMsg
	call	displayBuffer
	call	serialport_write
	popad
	ret


An important thing to remember, the buffer contains spaces, therefore to access pin 2, it is buf+2, to access pin 3, it is buf+4 and so on. If pin 3 is connected to Gnd and pin 13 is on, it should turn off when the program is run. If pin 13 is connected to 5V and pin 13 is off, it should turn on when the program is run.

Navigation

  • Click here to go back to main page.