Introduction to Physical Computing with AVR microcontrollers (Arduino)

http://arduino.cc/en/uploads/Main/ArduinoDuemilanove.jpghttp://arduino.cc/en/uploads/Main/ArduinoDuemilanove.jpghttp://arduino.cc/en/uploads/Main/ArduinoDuemilanove.jpghttp://arduino.cc/en/uploads/Main/ArduinoDuemilanove.jpg

 

VXewU^ Hw vHw

Responsable: Alvaro Cassinelli, (alvaro@k2.t.u-tokyo.ac.jp)

Student assistants: ^(Kazuma_Murao@ipc.i.u-tokyo.ac.jp)

   

 Dates:  13/5 ... 14:45-16:15

Material for the class:

o  Each student needs a PC or MAC (it has to be a PC if the student wants to play with AVR Studio - which is an optional task); one Arduino board (Arduino Duemilanove); one USB cable; one jumper cable.

o  Internet connection to look for information and download software.

o  A projector would be helpful to explain things on the classroom.

Tasks (ۑ): Tasks that you are required to perform are indicated by red arrows (*). These are divided in three categories:

o   Tasks 1-3: Introduction: AVR architecture generalities and brief introduction to Assembler using AVR Studio;

 

o   Tasks 4-17: Practice with the Arduino/Processing platform;

 

o   Task 18: complete project for those motivated enough or having previous knowledge on Arduino/Processing.

 

You can skip tasks if you like – in particular those marked as optional. We are not going to evaluate this course by the ability to complete all the tasks, but rather by the way you treat them, understand the problems and look for solutions in a creative way. We will also evaluate your capacity of looking for the right information among many sources (internet, manuals, etc) - many of them in English. This is a very important skill today, perhaps more important today than in the past.

 

In particular, if you are not interested on low level features of the AVR microcontroller, you can skip tasks 1-3 and start directly by task 4 (Arduino/Processing platform).

 

Plan of the course:

I) Introduction

II) Arduino and Arduino IDE

III) First steps on the Arduino platform

IV) Processing and Arduino

V) Designing a complete physical computing application

 

Language: will be (mainly) English.


I) Introduction

a) About this course

This course will introduce you to programming AVR microcontrollers under the Arduino/Processing physical computing environment, which is an ideal platform for prototyping high-level microcontroller applications capable of communicating with a PC and displaying interactive graphics - and this without the need to know anything about the inner working of the AVR microcontroller or the details of the USB protocol.

 

Indeed, using the Arduino IDE, microcontroller code can be written in C/C++, using a high-level library that enables the use of advanced instructions including mathematical functions, complex input/output, etc. On the other hand, with the Processing IDE, one can easily write graphical interactive applications on the PC that receive data and communicate with the Arduino platform through the USB port, but using a simple serial communication protocol.

 

Arduino and Processing languages have been conceived to resemble each other in many ways; moreover, the projects are open source and multi-platform (Linux, Windows and MAC OS).

 

The Arduino and Processing platforms are used today by a large community of people; you will find on the web a lot of resources and inspiring examples. Check in the Resources section for the links.

 

Note 1: This is not a course on Assembler for PIC or AVR microcontrollers, but the first task will deal with Assembler. If you are particularly interested on assembler, please check last yearfs microcontroller class (dealing with PIC programming using the MPLAB IDE): http://www.k2.t.u-tokyo.ac.jp/~okusan/courseMaterials/programming/index.html

b) The Atmel AVR microcontroller

Before introducing the Arduino/Processing platform, letfs learn a little about microcontrollers in general and AVR microcontrollers in particular.

Note: the prefix g0xh means that the following alphanumeric string represent a number in hexadecimal base (for instance, 0x0A corresponds to 10, and 0xFF to 255 in decimal). Hexadecimal base is very useful when programming in Assembler, because each digit corresponds to exactly 4 bits, two digits to a whole byte, etc. 

 

[TASK 1] Generalities about the AVR microcontrollers.

Answer to the following questions (in a few lines): 

*     What is a RISC microprocessor?

*    Expose three main differences between the Atmel™ AVR family and the Microchip™ PIC family.

*   Briefly explain what are the uses of the Flash, Eeprom and SRAM memory on the AVR microcontroller.

*    Describe the main use of the SRAM. What is stored in the first 32 locations address of the SRAM in the Atmega168/328 microprocessor?

*   Whatfs the size of a normal register in the AVR-8bit microcontrollers?

*     Whatfs the difference between indirect and direct data memory addressing?

*   What is an interrupt vector? Where are the interrupt vectors stored (Flash program memory or volatile SRAM?). In which memory location is the interrupt vector for RESET?

*    Describe the difference between LDI R1, 0x60 and LDS R1, 0x0060. In particular, whatfs the content of R1 after the instruction is executed? (hint: check p.347 of Atmega168 datasheet, or the general instruction set of 8-bit AVRs here). 

c) Assembler on AVR microcontrollers

As explained before, this course is not about Assembler, but about the Arduino platform which is programmed in C, and provides many high level functions (the resulting language is sometimes called gArduino languageh). However, for those wanting to gain more basic understanding and control over the AVR microcontroller using Assembler, I recommend to download and try the AVR Studio IDE. It can be downloaded for free at ATMEL website (latest version may need registration).

 

A nice feature of the AVR Studio is the ability to simulate the microprocessor for debugging purposes. For those interested, this course will offer optional tasks using the AVR Studio. Of course, in order to upload your code into the AVR microcontroller, you will need some hardware interface (Atmel STK500, PPI - parallel port interface). The Arduino board does not provides functionality as is to upload machine code compiled by the AVR Studio into the microcontroller, so if you want to play with assembler, you will be using the AVR Simulator included in the AVR Studio IDE.

 

AVR Studio also has a C/C++ compiler that generates machine code for the AVR series of RISC microcontrollers. That means that you can write your code in C/C++, as well as embed assembler into your C code.

 

Note: To program the AVR under Windows, you also have the option to download the WinAVR open source software. It is not an integrated IDE, but a suite of executables including the AVR-GNU GCC compiler for C and C++ (i.e., it is a compiler that takes C language high level code, and creates a binary – or .hex file - that you can program into your AVR microcontroller), the AVRDUDE (open source utility to download/upload/manipulate the ROM and EEPROM contents of AVR microcontrollers using the in-system programming technique (ISP). AVRDUDE supports two basic programmer types: Atmel's STK500 and the PPI (parallel port interface).Check here for details: http://savannah.inetbridge.net/avrdude/avrdude-doc-5.5.pdf.

 

[TASK 2] Assembler with AVR Studio.

 

This is an overview of assembler programming using the AVR Studio.

*       Download AVR Studio (see References at the end of this document), install it, and create a new project as follows:

o    Select Project>New Project. A dialog window will open. 

o    Choose gProject typeh: Atmel AVR Assembler

o    Choose Project name: gTest1h

o    Choose 'AVR Simulator' from the 'Debug Platform' list, and select 'ATmega168' from the Device list. Click Finish. 

o     Copy/paste the following code into the empty test1.asm file (the file that will contain the assembler code) and compile (Build>Build). Verify that there is no error.

o     Start debuging (Debug>Start Debugging).

 

 .include "m168def.inc"
 
.cseg
.org 0x0000
 
            ldi ZH,0x01     ;Assuming the two numbers are stored
            ldi ZL,0x00     ;at location 0x0100 in RAM
            ld R17,Z+      ;Load first number and increment Z
            ld R18,Z       ;Load second number
            mov R16,R17    ;copy num1 to temp
            mov R17,R18    ;copy num2 to num1
            mov R18,R16    ;copy temp to num2
            ldi ZH,0x01     ;load the RAM location back
            ldi ZL,0x00     ;load the RAM location back
            st Z+,R17      ;store the first number
            st Z, R18      ;store the second number
end:
            rjmp end    ;end of prog
 

* Check the SRAM memory (View>Memory, and select 'Data' from the list). On location 0x0100 and 0x0101 in SRAM, insert two numbers - say 01 and 02. Execute the program step by step (this is Debug>"Step Into", or by pressing F11), and describe what it does. Check the register values (Processor window, +Registers).

*  What the instructions ldi ZH,0x01 and ldi ZL,0x00  do? (hint: X,Y,Z are gIndirect Address Registersh, in fact each is formed by a pair of gnormalh 8-bit registers:  X=(R27:R26), Y=(R29:R28) and Z=(R31:R30). They are used to address Data memory indirectly.)

*  What ld R18, Z does? What kind of memory addressing is this? (direct or indirect?).  Why do we use two registers to address the SRAM memory? 

*  What st Z, R18 does? Is this direct or indirect storage?

* What is .cseg? is it a 'mnemonic' or an 'assembler directive'?

 

[TASK 3 - Advanced] This task is for those who have previous knowledge of Assembler and wish to demonstrate it. (If you donft have previous knowledge, it is better to skip this task for the time being because this course is nor about assembler and low-level details of the AVR microcontroller.)

* Write the code for summing up the content of the SRAM memory from 0x100 to 0x10A, and store the result in register R0. Use a conditional loop and a register pointer to fetch the data. (hint: A good resource for beginners on AVR microcontrollers is: http://www.avrbeginners.net/ ; for programming in assembler on the AVR, here: http://www.avr-asm-tutorial.net/avr_en/beginner/index.html. You can get inspiration from here: http://www.avr-asm-tutorial.net/avr_en/beginner/CALC.html)

 

 


II) Arduino and Arduino IDE

1) Introduction

 

Arduino is a physical computing platform based on a simple I/O board using an AVR microcontroller and a development environment that uses the Wiring library to simplify writing C/C++ programs that run on the board. Arduino can be used to develop stand-alone interactive objects or can be connected to software running on a computer (e.g., Adobe Flash, Processing, Max/MSP, Pure Data, SuperCollider).

The Arduino platform you have is the Arduino Duemilanove ("2009"), using the Atmega168 (Atmega328 for newer version) and powered via USB/DC power (switching automatically from one power source to the other).  

2) Hardware (the board)

http://arduino.cc/en/uploads/Main/ArduinoDuemilanove.jpgAn Arduino board consists of an 8-bit Atmel AVR microcontroller with complementary components to facilitate programming and incorporation into other circuits. All boards include a 5-volt linear regulator and a 16MHz crystal oscillator.

An Arduino's microcontroller is also pre-programmed with a bootloader that simplifies uploading of programs to the on-chip flash memory, compared with other devices that typically need an external chip programmer.

At a conceptual level, all boards are programmed over an RS-232 serial connection, but the way this is implemented in hardware varies by version. Current Arduino boards are programmed via USB, implemented using an USB-to-serial adapter chip.

The Arduino board exposes most of the microcontroller's I/O pins for use by other circuits. Several plug-in application boards known as "shields" are also commercially available.

In this class you will be working with the Arduino Duemilanove ("2009"). It is a microcontroller board based on the ATmega168 (datasheet) or ATmega328 (datasheet). It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery when using in gstand aloneh mode.

[TASK 4] Characteristics of the Arduino Duemilanove board.

*  How much memory does the ATmega328 have for storing programs, knowing that 2KB are taken by the bootloader?

*   How many digital I/O does the board have? At what voltage they operate?

*  How many analog inputs? Whatfs the resolution of the A/D conversion? (i.e., how many bits represent a sample).

*  How many analog outputs? Whatfs PWM? (draw a simple graphical representation of the signal).

3) Programming (Arduino IDE and Arduino language)

image014The Arduino Duemilanove can be programmed with the Arduino language through the Arduino IDE (figure on the right). The Arduino IDE is a cross-platform application written in Java which is derived from the IDE made for the Processing programming language and the Wiring project. It is designed to introduce programming to artists and other newcomers unfamiliar with software development. It is capable of compiling and uploading programs to the board with a single click. There is typically no need to edit Makefiles or run programs on the command line.

The ATmega168/ATmega328 on the Arduino Duemilanove board comes preburned with a bootloader that allows you to upload new code to it without the use of an external hardware programmer. It communicates using the original STK500 protocol. Rather then requiring a physical press of the reset button before an upload, the Arduino Duemilanove is designed in a way that allows it to be reset by software running on a connected computer. To upload your code, first compile using left-most button on the top of the Arduino IDE: compileButton), and then upload the code by just pressing the upload button uploadButton on the IDE.

Note (advanced): if needed, you can also bypass the bootloader and program the microcontroller through the ICSP (In-Circuit Serial Programming) header, always using the Arduino IDE (i.e., the gone press buttonh); see these instructions for details. This may be useful in case you need all the memory and donft care about the bootloader.

The Arduino IDE comes with a C/C++ library called "Wiring" (from the project of the same name), which makes many common input/output operations much easier (you donft need to explicitly include this library on your code, the IDE does it for you). Arduino programs are written in C/C++, although users only need to define two functions in order to make a runnable program:

  • setup() – a function run once at the start of a program which can be used to initialize settings, and
  • loop() – a function called repeatedly until the board is powered off.

A typical first program for a microcontroller is to simply blink a light-emitting diode on and off. In the Arduino environment, the user might write a program like this:

#define LED_PIN 13
 
void setup () {
    pinMode (LED_PIN, OUTPUT); set pin 13 as digital output
}
 
void loop () {
    digitalWrite (LED_PIN, HIGH);  // turn on the LED
    delay (1000);       // wait one second (1000 milliseconds)
    digitalWrite (LED_PIN, LOW);   // turn off the LED
    delay (1000);                  // wait one second
}

Note: The Arduino IDE uses the GNU toolchain and AVR Libc to compile programs, and uses avrdude to upload programs to the board - the GNU C Compiler (gcc) can compile code for the AVR chips as well: it's open source and cross-platform (Windows, OSX, Linux). The above code would not be seen by the compiler as a valid program, so when the user clicks the "Upload to I/O board" button in the IDE, a copy of the code is written to a temporary file with an extra include header at the top and a very simple main() function at the bottom:

#include "WProgram.h"
#define LED_PIN 13
 
void setup () {
    pinMode (LED_PIN, OUTPUT); // set pin 13 as digital output
}
 
void loop () {
    digitalWrite (LED_PIN, HIGH);  // turn on the LED
    delay (1000);        // wait one second (1000 milliseconds)
    digitalWrite (LED_PIN, LOW);   // turn off the LED
    delay (1000);                  // wait one second
}
 
int main(void)
{
    init();
    setup();
    for (;;) loop();
    return 0;
}

"WProgram.h" is the main header for the Wiring library, and the main() function only makes three distinct calls: init(), defined in the library itself, and the setup() and loop() functions defined by the user.

3) Assembler on Arduino IDE?

As it may be clear by now, the Arduino platform is not designed for programming in assembler; however, it is possible to insert assembler Arduino code without the need to compile it on AVR Studio or WinAVR. This is a nice feature in case you need to access low level hardware functions (this may be used for manually optimizing time critical parts of the software or to use specific processor instruction, which are not available in the C language). The nice thing is that all standard C and C++ constructs supported by AVR-GCC should work directly in Arduino IDE (because the Arduino IDE is based on the AVR-GCC compiler). This means that you can gmixh assembler on your Arduino code.

A way of doing this is inserting inline assembling on your code using the asm() function: it takes a string containing all the opcodes separated by newlines, for example:

asm("cli\n nop\n nop\n nop\n sei\n");

This may be useful to set some ALU registers or to optimize certain portions of the code. If we have time or you are interested, an example of this will be explained when setting the microcontroller gprescalersh (clock frequency dividers) in order to properly set the PWM frequencies for controlling servos for instance (page 88 in ATmega168 datasheet).


III) First steps on the Arduino platform

1) Physical computing gHello World!h

 The Arduino platform has many pins that can be configured as digital or analog inputs. In the following, you will explore the use of digital and analog input/outputs.

 

image016[TASK 5] Writing a physical computing gHello World!h

*       Start by downloading and installing the Arduino IDE on your PC/MAC computer. 

*     Connect the board to the computer using the USB cable; Windows will prompt for drivers: install them from the drivers/FTDI USB Drivers directory of the Arduino distribution. The gFTDI USB-Serialh drivers are needed so that the PC recognizes the board and the Arduino IDE application can communicate with the Atmega chip using a serial protocol.  (You can also download the latest drivers from the web at the FTDI website)

*     On the Arduino IDE, choose Tools>Board>Arduino Duemilanove (see image on the right). Also, set the proper USB port: Tools>Serial Port>COMxx (note: you may need to proceed by trial and error here, unless you check the port number for the FTDI USB <- > Serial bus contoller under Computer Management>Device Manager> Universal Serial Bus Controller>(right click: Properties)> Details>Device Instance Id, and check the last number on the displayed string... Easier to just guess!

*    Write, compile and upload microcontroller code for blinking the built-in LED connected to digital pin 13. After uploading, the program will start automatically after a few seconds. You can press greseth to make it start again.  

Note: Digital I/O pins can be configured as input or output using pinMode(). They operate at 5 volts. Each pin can provide or receive a maximum of 40 mA and has an internal pull-up resistor (disconnected by default) of 20-50 kOhms. 

 

[TASK 6] Blinking LED code in Assembler using AVR Studio.

In this example, we will write the same code directly in Assembler. However, we are not going to upload it into the microcontroller, nor seeing a real LED blinking - instead we will run the simulator in the AVR Studio and watch how the pin 7 in PORTB I/O register toggles itfs value (open the I/O View window and run the debugger, one step at a time).

*       Create a new project: Project -> new -> [give it a name] / [pick AVR assembler]. 
*       Give a name to the new assembler file (*.asm) and copy the following code: 
 
#include "m168def.inc"
 
.ORG 0x0000
           rjmp RESET         ; reset interrupt vector
 
.ORG INT_VECTORS_SIZE
RESET:     LDI r18,0b10000000 ; this means that bit 7 of r18 is set to 1 (the register has 8 bits, numbered from 0 to 7(
           OUT ddrb,r18       ; sets pin 7 on portB to "output"
 
            ; preload data to be output:
           LDI r18,0b10000000; set register to pin 7 HIGH
           LDI r19,0b00000000; set register to all pins as LOW
 
MAINLOOP:
           out portb,r18
           out portb,r19
           rjmp MAINLOOP    
 


*      Compile and run the debugger using gstep intoh function (or F11). Check the PORTB I/O register on the I/O View window (select PORTB and click "Show Register Pane"). What does it happens with bit 7?. Explain why bit seven of PINB also changes (check ATmega168 datasheet).

*      Check Frequency and Stop Watch (timer) in the Processor window. At what frequency the pin is toggling? (note processor frequency, ex: 4MHz, and calculate the number of cycles needed to complete the operations in the MAINLOOP).

*      OPTIONAL (Advanced + Work to finish at home!): build a "barebones" microcontroller board, program and use an ATmega168 to blink an LED. Check here for reference: [minimal arduino]. You will need some hardware parts for this, ask the professor.



Notes:

o    The Atmega8 has three ports labeled BCD which are responsible for looking after 23 IO general purpose IO lines/pins: PortB looks after 8 I/O lines (PB7-0); PortC looks after 7 I/O lines (PC6-0) (PC6 is special, it can be used as an IO pin or a reset; PortD looks after 8 I/O lines (PD7-0). Each gport pinh is controlled by the corresponding bit on three registers, DDRx, PORTx, PINx (x stands here for B, C or D). DDRx bits set the pin direction (input or output), the PORTx bits sets the data to be output, and the PINx bits (read only) store the read data. See p.70 of Atmel168 datasheet for details.

o    Without the directive-mnemonic ORG XXX (directive mnemonics does not generate code, and are preceded by e.f), the program is loaded at program memory address 0x0000 by default. This will erase the interrupt vector table. To avoid that, we can start the program at 0x034, right after all the interrupt vectors (in fact, the compiler can do that automatically using the .org INT_VECTORS_SIZE – code will start right after all interrupt vectors whatever the AVR type). Also, when the BOOTRST Fuse is programmed, the device will jump to the Boot Loader address at reset. Attn: to preserve the bootloader one must avoid writing code on the Boot Flash Section (0x0FFF to 0x1FFF, i.e., 2Kbytes in the Atmega168).

 
[TASK 7 (optional)] Embedding assembler into the Arduino language. 

The following code is an example of how to setup the I/O pins to switch the LED using assembler embedded in your Arduino code (this is a rather artificial example, since the Wiring C library provides functions ready at hand). The code configures an AVR pin as output using inline assembler:

 

void setup()
{
    asm volatile(
   "ldi r16,(1<<5)\n"
          "out 0x04,r16\n"
    );
}
 
void loop()
{
    asm volatile(
      "sbr r16,(1<<5)\n"
      "out 0x05,r16\n"
     );
    delay(1);
    asm volatile(
      "cbr r16,(1<<5)\n"
      "out 0x05,r16\n"
    );
    delay(1);
}

*       What is at address 0x04? Are we referring to Flash or SRAM memory? What PORT and what bit in this port has been configured as output?

*       Check to which physical pin in the Arduino Duemilanove corresponds the register bit that was set as OUTPUT (check here: mapping between Arduino pins and ATmega168 ports).

*       What do the lines sbr r16,(1<<5) and cbr r16,(1<<5) stands for?  

 

Note: since the Wiring library includes useful definitions (register names for instance), it is possible to set register values as if they were variables in C. This means that in order to set DDRB bit 5 to 1, we only need to do:

 

#define PB5 5
void setup() {
    DDRB |= (1<<5); // PORTB5 pin is set as OUTPUT (others are unchanged)
}
 
void loop() {
PORTB ^= (1<<PB5);
delay(1);   
}
 

*       DDRB |= (1<<PB5) is the equivalent to which instruction in Arduino language? (hint: itfs equal to pinMode(?,?)).

*       What PORTB ^= (1<<PB5) stands for in C?

 

Note: Apart from gdelay(1)h, which is a function defined in the Wiring library (i.e, itfs pure gArduino languageh), all the rest is just C code. In fact, the equivalent code in AVR Studio (using the C compiler) would read something like:

 

#include <avr/io.h>
#include <avr/delay.h> 
 
#define PB5 5
int main (void) {
         DDRB = 0xff; //sets all bits of port B for output
         while(1) { 
         PORTB ^= (1<<PB5);
         }
         return 1;
} 

 

[TASK 8] Generation of a square wave of a given frequency.

Now that you have gained understanding on how to generate a digital signal on a pin, letfs make something only a little bit more challenging and interesting.

*       Always under the Arduino IDE, modify the LED blinking code so that the blinking takes place at a certain frequency - letfs say 440Hz (square wave, 50% HIGH and 50% low). For doing that you will need to generate a proper delay right after setting the LED ON, and the same delay after the LED OFF, and do that inside an infinite loop. Check on the Arduino IDE gHelp>Referenceh to find the proper delay function (millisecond or microsecond?). 

*       Ask the teacher for a piezo-speaker, and hear to the sound.

 

Note 1: since you donft know how many opcodes are generated by compilation of the digitalWrite() function and the rest of the program, it is not possible to perfectly estimate the right delay (this would be easier to do in assembler, because you know that each opcode in the AVR microcontroller takes two clock cycles, and the clock frequency in the Arduino Duemilanove is 16MHz). Just assume that the instructions are executed instantly (which is a good approximation since the clock ticks much faster than 440Hz).

 

This is not the best way to generate a periodic signal using the microcontroller: it takes all the resources of the microprocessor. Even though the board does not have a dedicated signal generator chip, it is possible to generate tones using the on-chip TIMERS (i.e. programmable hardware counters). In the following we will go through the basics of this (we won't be using assembler to set the signal-generation hardware of the microcontroller to the proper frequency (prescalers, etc), but instead we will use the high level instructions provided by the Arduino IDE). 

b) gAnalogh output

[TASK 9] Analog output with PWM.

In this task you will modulate the LED intensity, as well as measure the default PWM frequency of the ganalogh output pins in the Arduino board.

*    Explain whatfs a PWM signal (make a simple drawing of the signal)

*    Modify the code so that the LED will not just blink, but instead will fade in and out using a PWM output (look in the Arduino website for information). Make it fade in and out with a frequency of 1 second.

*      Download and install the software oscilloscope gSoundcard Scopeh on your PC. This will be used to analyze the signal generated by the Arduino board (when you are ready to do this, you will need a speaker plug and some resistors – ask the teacher, the material is already prepared). Observe how the pulse width is slowly modulated, and measure the PWM period. Attn: do not attempt to connect directly the PWM output pin into the LINE IN of your computer (the PWM signal is a TTL square signal, and you may damage the input circuitry which accepts peak-to-peak signals of about 1V).

Note1: PWM stands for gPulse Width Modulationh. It is one of the simplest forms of signal modulation (also called gdelta-modulationh). It is the most elementary form of differential PCM (gpulse code modulationh – the sound synthesis technique popularized during the 80fs).   

 

Note2: a PWM signal with a period of about 20ms and a pulse width between 1 and 2 ms is the standard pulse control for servo motors. The servo positions itself based on the width of positive pulses fed to it. The rate at which pulses are sent to the servo is relatively unimportant (40 per second seems typical). A pulse width of 1.5 milliseconds positions the servo at its center, with 1 millisecond and 2 milliseconds being the accepted limits to either side.

 

*      [optional (little advanced)] Control a servo motor using the Arduino (ask for a servo motor to the teacher if you want to work this example).

c) Digital input

Reading a digital pin is no more complicated than writing to it. In this section you will read digital information from a pin (letfs say, digital pin 2), and blink a LED on digital pin 13 accordingly.

Note: by default, input pins are set in ghigh impedanceh mode, meaning that they wonft drive any significant amount of current from the load. This also means however that input pins with nothing connected to them (or when connected with a high impedance load) will report seemingly random changes in pin state, picking up electrical noise from the environment, or capacitively coupling the state of a nearby pin. To avoid this when necessary, one can set internal pullup resistors on the pin by software - they will steer an input pin to a known state if no input is present. Indeed, the Atmega chip contain convenient 20KOhm pullup resistors that can be set by treating a pin (previously configured as INPUT) as an OUTPUT: 

pinMode(pin, INPUT);           // set pin to input
digitalWrite(pin, HIGH);       // turn on pullup resistors (note that the pin has been previously configured as INPUT)
 

[TASK 10] Basic interaction with a button switch.

*       Open the example in File>Sketchbook>Examples>Digital>Button, and save it with another name. Upload to the board and verify that it works fine (you will need a jumper cable to act as a switch, by connecting/disconnecting the 5V pin in the board to the digital pin 2). 

*       Modify the code so that the LED does not just copy the state of the switch, but instead toggles its state when the pin goes HIGH (define a boolean gstateh variable for this).

*       [Optional] You may notice that this is not working very well sometimes: because the switching is not perfect, when you connect/disconnect the cable from pin 2 there may be some gbouncingh effects (i.e. very fast repetitive connection/disconnections). To remedy this, add a timer control that blocks the change if it took place in less than 100 ms. 

*      [Optional] If you want to do some electronic hacking, ask a phototransistor, a resistor and a small breadboard to the teacher, and build this circuit:

Use the code for the button switch to try this glight switchh.

d) External interrupts

You will notice that in order to check if the switch has changed its state, the microcontroller keeps reading the input pin in an infinity loop; this way of checking input data is called gcontinuous pollingh and is very inefficient (your code is taking all the resources of the microprocessor for this simple task). A much more efficient way to deal with input events is by using external interrupts. The digital pins 2 and 3 in the Arduino Duemilenove board can be configured as interrupt pins (triggered by a particular state of the pin or even by a change of the pin value) using the command attachInterrupt(pin, callbackFunction, CHANGE).
 
[TASK 11] In this task you will use the external interrupt to check the switch and control the LED light. 

*     Using this Aduino reference example, write the code for checking a RISING change on the switch (and then toggle the LED state) all using interrupts. (Hint: it may be important to gdebounceh the switch by disabling the interrupt for a hundred milliseconds right after entering the interrupt function.)

e) Analog input

The Arduino board also has analog inputs used to sample analog signals (voltage). The analog to digital conversion (A/D) is done by a specialized circuit inside the AVR microcontroller; each sample is converted to a number between 0 and 1023 (A/D conversion has 10 bit resolution), corresponding to a range of voltages from 0 to 5V (by default, but it is possible to set the max reference voltage using the command analogReference(): in this case, the reference voltage will be taken from pin AREF on the board.)

 

Note: By default, the analog pins are set as input pins – there is no need to set them as inputs in the setup() function. However, these pins can be configured as input or outputs – and also be used as normal digital I/O if required. Note however that the command analogRead(pin) will not work correctly if a pin has been previously set to an output, so if this is the case, set it back to an input before using analogRead. It takes about 100 us (0.0001 s) to read an analog input, so the maximum sampling rate is about 10kHz.

 

[TASK 12] In this task you will read the voltage generated by a piezo-speaker (also called gpiezo-transducer) that can be used as a gknock-sensorh. This electronic component is often used to detect the hit on electronic drummers.

*     Modify the gbutton switch codeh so as to detect a gknockh that will light up the LED (on a digital output pin). You will need to adjust a voltage threshold by hand (or by using an oscilloscope).

*      You may notice that this knock sensor is quite unreadable – in fact the piezo-sensor output goes to maximum and decays extremely fast. In order to get a more smooth output for the LED, letfs write a simple gpeak detectorh with smoothing (just smoothing would make the detector incapable of sensing rapid changes in the signal). Explain (graphically) what the following code does, and insert it into the main loop() function in order to control a LED (on an analog output):    

...
 
newReading = analogRead(pinPiezo);
 
if( newReading > lastReading )                   
    lastReading = newReading;                       // Peak detection
else
    lastReading = (lastReading*7 + newReading) / 8; // Smoothing out the decay giving more importance to the last reading
 
ledLevel = lastReading / 4; // PWM outputs are from 0 to 255 (8 bits), while analog input gives values from 0 to 1023 (10 bits)
 
...
 

Note: about pullup resistors on the analog pins: the analog pins also have pullup resistors, which work identically to pullup resistors on the digital pins. They are enabled by issuing a command such as:

              digitalWrite(14, HIGH);  // set pullup on analog pin 0 

while the pin is an input. Be aware however that turning on a pullup will affect the value reported by analogRead() when using some sensors if done inadvertently. Most users will want to use the pullup resistors only when using an analog pin in its digital mode.

f) Serial communication Arduino < - > PC

The Arduino Duemilanove has a number of facilities for communicating with a computer, another Arduino, or other microcontrollers. The ATmega168 provides UART TTL (5V) serial communication, which is available on digital pins 0 (RX) and 1 (TX). An FTDI FT232RL on the board channels this serial communication over USB and the FTDI drivers (included with the Arduino software) provide a virtual com port to software on the computer. The Arduino software includes a serial monitor which allows simple textual data to be sent to and from the Arduino board. The RX and TX LEDs on the board will flash when data is being transmitted via the FTDI chip and USB connection to the computer (but not for serial communication on pins 0 and 1).

Note: A SoftwareSerial library allows for serial communication on any of the Duemilanove's digital pins. The ATmega168 also supports I2C (TWI) and SPI communication. The Arduino software includes a Wire library to simplify use of the I2C bus. To use the SPI communication, please see the ATmega168 datasheet.

In this task you will play with the default Serial communication library. You donft need to include it when using the Arduino IDE; just initialize it using Serial.begin(baud rate) on the setup(), and then read or write data by just calling to  Serial.println(data) or the like on the main loop.

Check here for details and examples on how to use the library. 

[TASK 13] Communication from the Arduino board to the computer (using Arduino IDE gSerial monitorh to check data).

*  Use the Serial library to print the sensor values (from any of the previous examples worked above - digital or analog sensors) on the serial buffer.

*  Check the values read by the photoresistor on the Arduino IDE gSerial Monitorh (serialMonitorButton). Note: it is important that the serial monitor is opened at the speed at which the Serial port was configured in the Arduino.

[TASK 14 (advanced)] Communication from the computer to the microcontroller.

*    Generate tones with the Arduino commanded by the serial interface of the Arduino IDE (numbers 0 to 9, in order to generate a square wave with a frequency from 0 to 9kHz, using the delay function (in microseconds) and a square wave on a digital output pin. 


IV) Processing and Arduino

As defined in the Processing website, hProcessing is an open source programming language and environment for people who want to program images, animation, and interactions. It is used by students, artists, designers, researchers, and hobbyists for learning, prototyping, and productionh. Processing interacts well with the Arduino platform. Although Processing is basically java, the gProcessing languageh is a close cousin to the Arduino language (the most disorienting thing at first may be the different syntax for declaring and allocating memory for arrays). For instance:

 

Writing the following in Arduino language:

int a[8]; // Declare
a[0] = 1; // Initialize

or

int a[] = {5, 10, 11}; // Declare
a[0] = 12;  // Reassign

 

cwould be written in Processing language as:

int[] a = new int[8]; // Declare
a[0] = 1; // Initialize  

and

int[] a = {5, 10, 11}; // Declare
a[0] = 12;  // Reassign

 

The main structure of the program is very similar (the loop() function is called draw() though). A more complete comparison of the different syntaxes is given here.   

 

[TASK 15] First steps with Processing.

        *   Download the Processing IDE, and run some examples (from the File>Examples>Basicsc).   

 

image017         http://www.k2.t.u-tokyo.ac.jp/members/alvaro/courseMaterials/MicroProgramming/MicroProgramming_files/image018.jpg

 

[TASK 16] Graphical representation on the computer screen of values read by the Arduino board.

   *   In this task, you will choose one of the examples worked before (digital or analog input), and write a graphical representation of the light level on the computer screen using Processing (for instance, a rectangle with height proportional to the sensor level).

 

[TASK 17] Computer-to-Arduino communication.

*       Control tone generation from mouse input. Use the X coordinate to change the delay between HIGH and LOW pin output (advanced: alternatively, use PWM signals and change the value of register ICR1 which is the gTOPh counter register determining the pulse width – check page 88 on ATmega168 datasheet).


V) Designing a complete interactive application.

 [TASK 18] Although this may be too complicated for this short course on physical computing, I will appreciate all the same if you consider original applications and discuss about the technical challenges involved. Moreover, if you are really motivated and want to continue the project, then you can keep the Arduino board.  

* You are given two options:

o    Either suggest your own application (consult with me).

o    Or choose an application among the following suggestions:

1.  Intervalometer/Metronome. Build a stand-alone intervalometer for doing gtime-lapseh photography or a metronome (using a potentiometer to adjust the time-lapse). You can show the time-lapse and the number of pictures taken on an LCD screen using the serial interface (ask the teacher), or use led displays (check here for details).

2.  Accelerometer based gpongh. The goal is to build a system to interact with a virtual ball through the tilting of a real table. Acceleration data collected by the Arduino is sent to a computer – using the USB cable or a wireless Bluetooth modem. This application is described in detail here.

3.  Physical Pixels: Create a simple protocol for transmitting information over a free-space optical link between Arduinos, using LEDs and Phototransistors. Any Arduino can generate a gwaveh of light that will spread among the other (the trigger can be a knock, sound, a capacitive sensor or just light); or  modify the code to run the Game of Life using several Arduinos.

4.  Work any example on Tom Igoefs book gMaking Things Talk: Practical Methods for Connecting Physical Objectsh


References and useful resources

 Useful resources:

  • WinAVR (AVR-GCC for windows based on GNU gcc compiler for C and C++): http://winavr.sourceforge.net/

 

http://www.k2.t.u-tokyo.ac.jp/members/alvaro/courseMaterials/MicroProgramming/MicroProgramming_files/image019.jpg

 

Useful References:

  • Tom Igoefs books:
    •  Making Things Talk: Practical Methods for Connecting Physical Objects, by Tom Igoe.
    •  Physical Computing: Sensing and Controlling the Physical World with Computers, by Tom Igoe, Dan O'Sullivan
  • Getting Started with Arduino (Make: Projects), by Massimo Banzi
  • The Best of Instructables Volume I: Do-It-Yourself Projects from the World's Biggest Show & Tell (v. 1), by The editors MAKE magazine and Instructables.com

 



Glossary (in construction)

 

Physical (or embedded) computing, in the broadest sense, means building interactive physical systems by the use of software and hardware that can sense and respond to the analog world.