Assembly Robot Lab 1 – An Introduction to 3DoT & Assembly
Table of Contents
- 1 Introduction
- 2 What Is New
- 3 Introduction to AVR Studio
- 4 3DoT Board Schematic & Block Diagram
- 5 The Robot3DoT.inc Include File
- 6 Quick Review and New Directives to the Assembler
- 7 Initialization Section
- 8 Experiment 1 – MOTORS_OFF
- 9 Lab 1 Demonstration
- 10 How to Create and Print-out a List (.lst) File
This lab is designed to introduce you to the 3DoT Board, Microchip’s Integrated Development Environment (IDE), and AVR Assembly Language programming. Plus, you will learn about the power of library files. Library files are simply files that you instruct AVR Studio to include in your program. In this lab you are going to include two library files. One is named m32U4def and the other is robot3DoT.
What Is New
AVR Assembly Instructions
in r7, PINC // Input port C pins (0x09) into register R7 out PORTB, r7 // Output to Port B from register R7 mov r8, r7 // Move data from register r7 into register r8
Arithmetic and Logic
clr r16 // Clear Register R16 ser r17 // Set Register R17
call Init3DoT // Subroutine Call rjmp loop // Jump to the label named loop
AVR Studio Assembly
; // /* */
Introduction to AVR Studio
In lab, you will be spending most of your time working within an Integrated Development Environment (IDE). For our labs, we will be working in the AVR Studio IDE. As shown in the figure below and discussed in the next few sections, the IDE lets us write our program in a human readable form, known as assembly, and then translate it into a machine readable form understood by the ATmega32U4.
Create a New Project
The best way to learn about the AVR Studio IDE is to start playing with it. So let’s get things started by launching AVR Studio and Opening a New Project.
Select Atmel AVR Assembler and check both check boxes(Create initial file and Create folder). Name your project (Lab1) and browse to location where you want it saved. Click Next >>.
In the next window select AVR Simulator. For the Device, select ATmega32U4. Click the Finish button.
Congratulations, you are ready to start programming within the AVR Studio IDE!
All assembly programs contain assembly directives and assembly instructions. Assembly directives are instructions to be read by the assembler. In our lab, the assembler is included with AVR Studio IDE. As you have seen, AVR Studio is a program that runs on your computer and is responsible for translating your human readable assembly program into the machine language of the microcontroller.
We begin our program with an Assembly Directive. First, locate the program window within the IDE. This is the blank window in the center of your AVR Studio application. The title bar should include the location of your program and end with the name of your program and the “.asm” extension. Enter the following lines into the program window.
You can probably guess that here we are telling the assembler that we would simply like to include some comments for the individual reading our code. To include comments, you can use the C language notation // comment line and /* block comment */ or unique to assembly a semicolon ; character.
Now let’s add some code which intended strictly for the assembler, not the reader or the microcontroller. The difference is important.
The “dots” tell the assembler that these lines are talking to the assembler and not to be turned into machine instructions.
Without overly complicating our first program, I will just note that the INCLUDE assembly directive tells the assembler to copy into our program all the text contained in a file named m328pdef.inc. For now, we do not need to know what is in this file, other than to note it will help us in writing a more human readable program.
The CSEG statement tells the AVR Studio Assembler to place the following material in the Code SEGment of memory. For the ATmega328P, this means Flash Program Memory. The ORG statement tells the assembler to start placing code at this address in Flash Program memory.
Programming Convention Because it is so important to remember when a line is intended for the Assembler (Assembly Directive) and when a line is to be converted to a machine instruction intended for ATMega328P microcontroller (Assembly Instruction), I always capitalize Assembly Directives and place in lower case letters Assembly Instructions. AVR Studio is not case sensitive, so this convention is not required for your assembly program to assemble correctly – it is however required by the instructor.
Now let’s add our first label. Enter the following line after the .ORG 0x0000 assembly directive:
The label RST_VECT stands for ReSeT VECTor and is only there as a point of programming style (i.e., it helps the reader know that the code to be executed on reset follows). What the assembler does is quite a different story. Whenever the assembly sees a label, it places the label name and its corresponding address, in this case we know it is 0x0000, into a look-up table.
|Label Name||Program Address|
Now if you ever want to reference this location in your program, you can use the name and let the assembler worry about the address.
Congratulations, you have for now completed your initial conversation with the assembler. You have asked it to include some comments, include more assembly directives located in another file, setup to write some code at address at 0x0000 in program memory, and finally to associate this address with the name RST_VECT. What you haven’t done is write anything that the AVR microcontroller will ever read. Once again it is important to know when you are talking to the assembler and when your code will be used to generate machine instructions to be run by the microcontroller. So let’s start generating assembly instructions intended for the microcontroller.
Just as you are reading the step-by-step instructions on this page so you can write your first program, the microcontroller in Figure 5 reads the step-by-step instructions contained in the program to learn what is intended by the programmer. This is the “Machine Language” of the computer. This language is comprised of only ones and zeros. For example, this binary sequence 0010011100000000 tells the AVR computer (aka microcontroller) to set all the bits in register 16 to zero. All these 0’s and 1’s are not very easy for us humans to understand. So instead we humans have created a human like language comprised of abbreviations (known as mnemonics). This is known as Assembly Language. By definition then, there is a one-to-one correspondence between a machine instruction and an assembly instruction. For our machine code example, the equivalent assembly instruction is clr r16.
Registers Our microcontroller contains 32 general purpose registers labeled R0 to R31. For now you can think of registers like variables which can hold up to 8-bits of information (000000002 = 010 to 111111112 = 25510). To learn more about number system read Chapter 1 “Introduction” in your textbook or Appendix A – Number Systems in my Lecture 1 notes.
It is finally time to write our first assembly instruction. Add the following assembly instructions to your program.
rjmp reset // jump over the IVT, tables and include file(s)
The assembly instruction rjmp reset instructs the microcontroller to jump to the yet to be defined label named “reset”. You will also see I have included a comment. The meaning of this comment will become more clear over the remainder of the semester.
The Anatomy of an Assembly Instruction
Each assembly instruction is defined by an operator and one or two operand fields. For our clr r16 example, the clear instruction’s operator is clr and it has one operand r16. Our first program line also contains a single operand instruction. In this case, the operator is rjmp and the operand is reset.
3DoT Board Schematic & Block Diagram
The end goal of these labs is to program a robot utilizing the 3DoT board and be able to navigate a maze autonomously. Shown below are the major features of the 3DoT board and the block diagram of the latest version.
3DoT is a micro-footprint 3.5 x 7 cm all-in-one Arduino compatible microcontroller board designed for robot projects.
- ATmega32U4 Microcontroller Unit (MCU)
- Power from a single CR123A 650mAh rechargeable Li-ion battery
- Integrated 3.7v Li-ion battery charger
- All digital logic powered from Low Dropout (LDO) 3.3v regulator with power and ground output header pins provided.
- Battery Level Sensor
- TB6612FNG Dual DC Motor Driver
- 5.0v Turbo Boost for driving DC and servo motors
- Reverse voltage and overvoltage protection circuitry
- Android and Apple iOS application software (HM‑11 Bluetooth BLE module required)
- 2×8 pin Arduino-like shield connectors
- One 8-pin forward facing sensor shield connector
- Two 100 mil standard Servo connectors
It would be ideal to spend some time analyzing the block diagram to get a better understanding of the capabilities of the 3DoT board but we will focus on the connections between the motor driver and IR sensors for Lab 1.
The main objective of Lab 1 is to develop the line following logic for your robot to move through the maze that was shown in the Mission PDF. We will handle what to do at intersections in later labs. For the line following algorithm, it will involve taking data in from the four IR sensors and deciding how the control signals being sent to the motor driver needs to change based on that information. The inner two IR sensors provide the most relevant data about your robot’s position as it follows the line and is what we will be focused on. You can utilize all four sensors if you want to. To start developing this code, you will need to configure the input and output pins.
The Robot3DoT.inc Include File
To simplify your life – it is after all the first lab – I have already written all the assembly code you need to work with the two DC motors included with your CSULB 3DoT board. This code is contained in a separate file named robot3DoT.inc. We will add this file to our program in the same way we included the m32U4def.inc “include” document in an earlier part of the lab. Let’s begin.
- Download and add to your Lab1 project folder my robot3DoT.inc file.
- Unlike, the m32u4def.inc file which contains equate assembly directives, the robot3DoT.inc file includes subroutines which need to be run by the microcontroller.
- Add the following lines of code to your Lab1 project file.
.ORG 0x0100 // Bypass IVT .INCLUDE "robot3DoT.inc" reset:
Quick Review and New Directives to the Assembler
Here is what your program should look like now.
- Can you identify the comments?
- Can you tell which lines contain Assembly Directives and which contain Assembly Instructions? Remember assembly directives typically, but not always start with a period and use upper case letters; while assembly instructions use lower case letters.
Do you remember the first INCLUDE assembly directive from earlier in the lab? The m32u4def.inc library is written by Atmel and allows you to use names in place of numbers. In the following example the mnemonic PINC is “equated” to the number 0x06 in the library. If you like, you can open the m32u4def.inc file in AVR Studio and using the find tool, locate this directive.
.equ PINC = 0x06
Up to this point our program has only contained comments, assembly directives, and labels. The first actual instruction is the previously discussed rjmp reset. So when you press the reset button, the AVR processor will first run the rjmp reset instruction. The rjmp instruction tells the processor to jump to the code starting at the reset label. This means the program will jump over (bypass) a table known as the IVT (to be covered later in the semester) and all the code included in m32u4def.inc. Which is a good thing; because we do not want to run any of the included programs until we are ready.
I wrote the robot3DoT.inc library. This library includes subroutines like Init3DoT, and WriteToMotors which allow you to work with the 3DoT board without knowing the details of how it works.
Why are the two include files placed at different locations in the program?
The m32U4def.inc library is written by Atmel and allows us to use mnemonics (abbreviations like PINC) in place of numbers (like hexadecimal 6). To allow us to use these mnemonic names as quickly as possible we insert this library at the beginning of the program. The Init3DoT library is written by the instructor and contains instructions. This code must not be executed at reset so the library is inserted after the first jump instruction (rjmp reset) and above the label reset.
If you have played around with the Arduino IDE, you know that all Arduino programs have an initialization section named setup() and a looping section named loop(). Our assembly program written within the AVR Studio IDE will be configured in a similar fashion. In our case, the initialization section is labeled reset: and the looping section is again named loop:. In the next section you will write the initialization section to be used throughout the semester.
How to Initialize the Stack
To accomplish almost anything useful in assembly you write a subroutine. To allow us to work with the 3DoT board I have written a number of ready-made subroutines for you to use. When you call a subroutine you need to save your current location on a stack. All computers have built-in hardware stack support. However, before we can save our return address on the stack we need to initialize our stack pointer (SP) register. You will learn more about stacks as the semester progresses. Add the following lines of code to your program right after the reset label.
reset: ldi r16, HIGH(RAMEND) out SPH, r16 ldi r16, LOW(RAMEND) out SPL, r16
How to Use the Init3DoT Subroutine
We are now ready to call our first subroutine. Add the following line to your program.
call Init3DoT // Initialize 3DoT board with both motors OFF
The Init3DoT subroutine takes care of all the initialization required to use the 3DoT board. You only need to call it once at the beginning of your program, just after stack initialization. That is it, you are now ready to work with the 3DoT board – allowing you to read IR sensors, run the motors, and more.
Controlling the Motors
The General Purpose Input and Output (GPIO) ports of a microcontroller (MCU) allow you to read pins and write to the pins of the MCU. To read a pin means – to record if the voltage on the pin corresponds to a logic 0 (Low) or logic 1 (High). To write to a pin means – output a voltage to the pin corresponding to a logic 0 (Low) or logic 1 (High). Figure 8 is a close-up picture of the interface between the ATmega and it GPIO ports and the TB6612 Motor Drive. The mnemonics inside the ATmega32U4 correspond to the GPIO port bits. The numbers outside the box correspond to the Arduino naming convention. We will be working directly with the GPIO ports.
Figure 9 is the truth table for the TB6612FNG Dual Motor Driver taken from the datasheet. As a practicing engineer, much of your time will be spent reading datasheets and translating that information into a schematic and software.
Unfortunately, depending on how your motors are wired and placed in the chassis, a CW (clock wise) direction in the datasheet may in fact result in your wheels rotating CCW (counter clock wise) and visa-versa. Ultimately, we want to know what settings make our robot go forward, backward, turn right, and turn left. Which brings us to our first experiment.
Experiment 1 – MOTORS_OFF
From Figure 1 we observe that the direction the motors turn is set by inputs IN1 and IN2. In this experiment we are going to complete Table 1 “Motor Control Settings” relative to our robot.
Step 1: Initialize your robot in a “Stop” state, as defined in Figure 5, by adding the following code to your robot program.
// stop tb6612 motor cbi PORTC,PC6 // AIN1 6 cbi PORTB,PB6 // AIN2 5 sbi PORTB,PB5 // PWMA 4 sbi PORTF,PF7 // STBY 3 cbi PORTF,PF6 // BIN1 2 cbi PORTF,PF5 // BIN2 1 sbi PORTD,PD7 // PWMB 0 loop: rjmp loop
The “rjmp loop” instruction keeps the MCU program looping on itself. If this instruction were removed, the program would run uncontrolled through Flash program memory.
All things being equal, you have a 25% chance of your robot moving forward. You have a 75% chance that you will need to change one or both motor setting to make forward progress.
Step 2: Experimentally set and clear bits IN1 and IN2 to discover what input setting result in the action described by each line (Forward, Turn Right, Turn Left, Backward) in Table 1.
For example; the following changes to motor bits 6 (AIN1), 5 (AIN2), 2 (BIN1), and 1 (BIN2) should, based on Figure 5 “Motor Control Truth Table” cause the robot to move forward.
// turn right tb6612 motor sbi PORTC,PC6 // AIN1 6 cbi PORTB,PB6 // AIN2 5 sbi PORTB,PB5 // PWMA 4 sbi PORTF,PF7 // STBY 3 sbi PORTF,PF6 // BIN1 2 cbi PORTF,PF5 // BIN2 1 sbi PORTD,PD7 // PWMB 0
Record your experimental results in your lab notebook. Once you have your robot figured out, complete the “Input” side of Table 1.
Step 3: Based on the “Inputs” as defined in Table 1 and the corresponding input conditions as defined in Figure 5 “Motor Control Truth Table,” fill-in the “Output” side of Table 1.
|Name / Mode||Input||Output|
|Motor Variable||7||6||5||4||3||2||1||0||Left Motor||Right Motor|
|GPIO Port Bit||PC6||PB6||PB5||PF7||PF6||PF5||PD7|
Step 4: Replace the don’t care conditions (X) in line 1, named “Motors OFF,” with bit settings to rotate both wheels clockwise, in other words move forward. Record the Motor OFF Input line here, with its corresponding value in hexadecimal.
|Name / Mode||Input||Hex Value|
|Motor OFF||0||X||X||0||1||X||X||0||= 0x____|
Step 5: After the m32u4def.inc INCLUDE assembly directive, add an equate assembly directive with the label MOTORS_OFF set equal to the hexadecimal value from Step 4. For example, if the hexadecimal value was 0x4C, you would write.
.EQU MOTORS_OFF = 0x4C // assign a value of 0x4C to label MOTOR_OFF
Now whenever, you need the bit settings for your robot to be configured to move forward, you do not need to remember to type 0x4C, instead you simple type MOTORS_OFF and the assembler will enter this constant value for you.
Design Challenge – Line Follower (5 points)
You can skip this section if you are happy receiving a passing or even a good grade on the lab. If you want to receive an excellent grade you will need to accept the challenge. Specifically, the maximum grade you can receive on the prelab 1 plus lab 1 if you do not accept the challenge is 25 points out of 30 (83%).
To accomplish this challenge you will need to learn a few new instructions: in, out, com, bst, and bld. a nice source of information on assembly instructions is the AVR Instruction Set Manual.
The objective of the design challenge is to teach your robot how to follow a straight line and stop at an intersection.
Using Figure 4 “Object Sensors to DC Motors” and Figure 5 “Motor Control Settings” (or Table 1) as a guide to complete the following table.
|Input||Condition||Action||Output to Motor|
|0||0||Walking down the path||forward||1||1|
|0||1||Right sensor over the path||veer right||1||0|
|1||0||Left sensor over the path||veer left||0||1|
If you filled in the table correctly, you should discover that all you need to do to implement the truth table is wire the complement of the input with its corresponding output. So let us get started.
Based on what you learned in the lab, configure the motors to be ready to move forward with PWM inputs set to zero (0).
// initialized tb6612 motor ___ PORTC,PC6 // AIN1 6 // enter values from experiment 1 ___ PORTB,PB6 // AIN2 5 cbi PORTB,PB5 // PWMA 4 sbi PORTF,PF7 // STBY 3 ___ PORTF,PF6 // BIN1 2 ___ PORTF,PF5 // BIN2 1 cbi PORTD,PD7 // PWMB 0 loop: /* wire complement of IR inputs to corresponding PWM output */ rjmp loop
Now all we need to do is wire the complement of each object IR sensor input to its corresponding PWM output. As a load-store architecture, we will need to input our sensor inputs into a register, wire them up, and then output to the motors.
loop: /* wire complement of IR inputs to corresponding PWM output */ in r16, PIND // IR sensor left = 6 and IR sensor right = 4 in r17, PORTB // Port B image in r18, PORTD // Port D image com r16 // complement IR inputs /* using the bst and bld instructions only, wire complement of IR sensor inputs in register 16 to their corresponding PWM outputs in PORTB bit 5 (PWMA) and PORTD bit 7 (PWMB). */ bst r16, PD6 // input left sensor /PD6 in r16 to the T-bit bld r17, PB5 // output T-bit to left motor in PB5 in r17 bst r16, PD4 // input right sensor /PD4 in r16 to the T-bit bld r18, PD7 // output T-bit to right motor in PD7 in r18 out PORTB, r17 // update image of Port B out PORTD, r18 // update image of Port D rjmp loop
Test your line follower by making a straight line on the floor using black tape ending with a short length of black tape perpendicular to the first, to form an intersection. If everything is working correctly, your robot should follow the straight line until it comes to the intersection where it will stop.
Lab 1 Deliverable(s)
All labs should represent your own work – DO NOT COPY.
Submit your list file as defined below. Make sure that the code compiles without any errors. Do not forget to comment your code.
Lab 1 Demonstration
How to Create and Print-out a List (.lst) File
At the end of each lab, you will turn in a List file version of your program. A list file contains both your assembly program and the machine program generated by the assembler. First let’s verify that AVR Studio is set to generate a List file. In the menu bar select Project and then Assembler Options
Now whenever you assemble your program, a file with a .lst extension will be created in your project folder. Assemble your program and then open the generated list file.
You will see that along with your program the list file includes a lot of other stuff. Most of this is the text from the included m328pdef.inc document. This is the document that includes all the equate Assemble Directives which allow us to use mnemonics for all our registers in place of their actual addresses. If you have not done so already browse this material to see how AVR Studio does it. You should see something like the following.
AVRASM ver. 2.2.7 c:usersDocumentsLab1Lab1.asm Tue Aug 21 13:05:53 2019 [builtin](2): Including file 'C:/Program Files (x86)AtmelStudio7.0PacksatmelATmega_DFP1.2.209avrasmincm328pdef.inc' c:usersDocumentsLab1Lab1.asm(10): Including file 'C:/Program Files (x86)AtmelStudio7.0PacksatmelATmega_DFP1.2.209avrasmincm328pdef.inc' c:usersDocumentsLab1Lab1.asm(16): Including file 'c:usersDocumentsLab1spi_shield.inc' /* Lab 1 - An Introduction to Assembly * Version x.0 <- update the version each time to print your program * Written By : Your name here * ID # : Your CSULB student ID number * Date : Date the lab report was turned in, NOT THE DATE DUE * Lab Section : Your day and time */ ;***** Created: 2011-02-19 12:03 ******* Source: ATmega328P.xml ********** ;************************************************************************* ;* A P P L I C A T I O N N O T E F O R T H E A V R F A M I L Y ;* ;* Number : AVR000 ;* File Name : "m32U4def.inc" ;* Title : Register/Bit Definitions for the ATmega32U4 ;* Date : 2011-02-19
There is a lot of extra material that is not useful, so there are several things to remove. Everything that comes from any include file must be removed since it is not a part of the main code. Delete material from this line…
;***** Created: 2019-12-11 15:36 ******* Source: ATmega32U4.xml ********** ;************************************************************************* up to and including this line. ; ***** END OF FILE ******************************************************
Your list file must include the AVR Studio Assembler version and time stamp!
AVRASM ver. 2.1.42 Tue Aug 23 16:57:15 2019
The “Resource Use Information” should also be deleted before you print out your list file.
Delete material from this line…
RESOURCE USE INFORMATION ------------------------
up to, but not including this line.
Assembly complete, 0 errors, 0 warnings
You can clean up and format the final version of your file in AVR Studio or your favorite text editor. Regardless of the text editor your final document should be formatted as follows.
Font: Courier or Courier New
Size: 9 or 10 point
Paragraph Spacing: 0 pt before and after
Line Spacing: Single
Page Layout: Landscape
Next, clean up unwanted spaces so your code is aligned and easy to read. DO NOT FORGET THIS STEP. Your touched up list file should now look something like this template.
AVRASM ver. 2.1.42 Tue Jan 10 11:24:47 2019 /* Lab 1 - An Introduction to Assembly * Version x.0 <- update the version each time to print your program * Written By : Your name here * ID # : Your CSULB student ID number * Date : Date the lab report was turned in, NOT THE DATE DUE * Lab Section : Your day and time */ .CSEG .INCLUDE .ORG 0x0000 RST_VECT: 00000 c131 rjmp reset // jump over IVT, tables, and include files .ORG 0x0100 // place all the code that follows starting at the address 0x0100. .INCLUDE "spi_shield.inc" reset: // Initialize the stack pointer 000132 e008 ldi r16, HIGH(RAMEND) // IO[0x3e] = 0x08 000133 bf0e out SPH, r16 000134 ef0f ldi r16, LOW(RAMEND) // IO[0x3d] = 0xFF 000135 bf0d out SPL, r16 000136 940e 0100 call InitShield loop: 000138 940e 0116 call ReadSwitches // read switches into r6 00013a 2c76 mov r7,r6 // wire switches to the 7 segment display 00013b 940e 0121 call WriteDisplay // write r7 to the 7 segment display 00013c cffb rjmp loop Assembly complete, 0 errors, 0 warnings
NOTE: THIS IS JUST AN EXAMPLE. YOUR LIST FILE SHOULD CONTAIN THE CODE FOR THE LAB YOU ARE SUBMITTING.
Finally, if you have not done so already, set your printer page layout to landscape mode. Preview your printout before you actually print it out to save paper. Double check your document to make sure there is no word wrap. Your printout should never include word-wrap. If you do see a line wrapping in the print-out, go back and correct the line and re-print your list file.
Lab 1 Deliverable(s) / Checklist
STOP Read the Lab READ ME document contained in the Labs Folder. Be absolutely sure you have followed all instruction in the “Lab Formatting” section of this document. Points will be deducted if you do not follow these instructions. You have been warned.
If you have not done so already, please purchase a Lab Notebook. Follow the guidelines provided in the “Lab Notebook” section of the Lab READ ME document.
Make sure you have read and understand the “Plagiarism” section of the Lab READ ME document.
All labs should represent your own work – DO NOT COPY.
Remember before you turn in your lab…
- Does your software program “wire” the switches to the 8 discrete LEDs and the 7 segment display?
- Your lab report includes a title page with your picture (one that will allow me to match a name with a face), lab number, your name, today’s date, and the day your lab meets
- The above information is duplicated in the title block of your assembly program as described in the lab. Do not forget to include the first line of your program containing the title of the lab. If you are not careful this line may be deleted and points deducted.
- Your list file should include the AVR Studio Assembler version and time stamp.
- Your list file should not include material from the m328pdef.inc or spi_shield libraries or Resource Use Information.
- Include the Assembly line indicating that your Assembly program contains no errors or warning in syntax.
- Your list file should be formatted as defined here.
Font: Courier or Courier New
Size: 9 to 10.5 point
Paragraph Spacing: 0 pt before and after
Line Spacing: Single
- All fields within the program area (address, machine instruction, label, operand, destination operand, source operand, comment) must be aligned.
- Your list file printout should be in landscape and not have any lines wrap from one line to the next.
- Never turn in a program that is not debugged (i.e., contains logical errors).