WEEK 9
EMBEDDED PROGRAMMING

ASSIGNMENT DETAILS
Read a microcontroller data sheet. Program your board to do something, with as many different programming languages and programming environments as possible. Extra credit: experiment with other architectures.



ATTINY 44

The Data sheet for the ATTiny44 can be found HERE.

The ATTiny 44 is an 8bit AVR microcontroller. It has:

---> 32 x 8bit registers ---> 2k (t24) / 4k (t24) / 8k (t84) of Flash Memory. This is where programs are stored.
---> 128 (t24) / s456 (t44) / 512 (t84) bytes of SRAM. This is used to hold the data that is processed during runtime.
--->128 (t24) / s456 (t44) / 512 (t84) of EEPROM which is data that is stored but can also be changed.

There are 12 data pins on the ATTiny 44.


---> 8 x PORTA Pins. Can be input or output, also have analog to digital converters (ADC)
---> 4 x PORTB Pins. Can be programmed as input or output also have special functions
---> Special pins on PORTB include: CLKI on PB0 for external clock in // XTAL on PB1 for manipulation of an internal oscillator // RESET on PB3 to reset programs and perfrom timing functions // and CLKO on PB2 to output system clock data.


The following pages from the ATTiny data sheet (pages 65 & 66) represent the bit registers on the ATTiny. Each port has three registers DDR, PORT, and PIN. Smaller chips like the ATTiny45 only have one port. Understanding what the three registers do is helpful if not necessary when setting up your code outside the Arduino IDE environment.

---> DDR: Data Direction Register. Decides whether a pin is an INPUT or an OUTPUT. When set to 0: pin is set as n OUTPUT. When set to 1: pin is set as INPUT.
---> PORT: An Output register that is used to set the output value on a pin HIGH or LOW 1 or 0 (5v or 0). It can also be used to set a pull-up or pull-down to cancel noise on an input.
---> PIN: Input register used to read the voltage at the pin.


Understanding registers and how to switch them is important but somewhat cryptic. Below is an example of Logo code that Brian Silverman showed me to turn a light on and off. I was completely confused until I drew it out. I learned 2 things about binary. One is to use it as a map to locate the setiings on a particular register. The second thing I learned is to use it as a value in itself. In this little bit code we are using decimals to represent the locations on the register that we need to set. You need the datasheet to understand it.

What I needed to do was to figure out which pins on the ATTiny were setup as outputs so that we know how to make our blink code and to turn an LED that was attached to PA7 on and off. Here is the code that tells us which pin is an output and how we can turn that pin on and off:

prhb readb ddra
82
bsetb porta $80
bclrb porta $80

First thing that really confused me was remembering that 8 = 7 and 2 = 1 in the register. The second is to remember that we read from right to left.

What the above code means is:
---> prhb = print as a hex byte
---> readb = read the byte value
---> ddra = data direction register on port A

In english, reading right to left, this says: On the data direction register for port A, read the byte value, print it as a hex byte. The return was 82 which means that in the DDR register in PORT A PA7 and PA1 are set to HIGH making them OUTPUT pins.

Remembering that 82 is a map, it tells me the location on the Data Direction Register. Here is a diagram I made to help me visualize this:

To understand how the binary relates to a HEX or DECIMAL type:

To turn the LED on and off:

---> bsetb porta $80 = set a bit on pin7 in the PORTA register. It will go from 0 >> 1 = HIGH
---> bclrb porta $80 = clear the bit on pin7 in the PORTA register so it will go from 1 >> 0 = LOW.

For the register on PORTA this looks like 10000000. The only place where $80 is adressing is PA7.



PROGRAMMING WITH ARDUINO

I was eager to see if my board would work so I decided to run a quick sketch from the Arduino IDE. I followed instructions in the Fab Academy Tutorial HERE.


I opened up the Arduino IDE and set the following.
- Board: “ATtiny 24/44/84”
- Processor: “ATtiny44”
- Clock: “External 20 MHz”
- Port: “/dev/usbserial-….”
_________
- Programmer: “USBtinyISP”




---> burning the bootloader


When first running using your board and setting it up using the Arduino IDE as opposed to using a makefile you need to run "BURN BOOTLOADER" in order to setup the fuses in the chip. I did not do this and my board did not cycle time properly. The Arduino Blink sketch loaded fine but 1000 ms delay in the blinking LED code was more like 20 000 ms.

The ATTiny44 ships pre-configured with the 1 mhz internal clock activated. When I set the Arduino to use the 20mhz external clock without burning the bootloader the code is expecting 20mhz cycles but using only the 1mhz internal. The effect is multiplying by 20.

The bootloader process only needs to be done once. It is the equivalent of running make fuse with a makefile.



---> testing the boards

With the bootloader burnt, the code ran as it should. 1000ms was 1000ms. At this point, my board was running like an Arduino. Not much for me to learn from using the Arduino IDE but I get to verify that my first microcontrollers work. I tried the Arduino blink and button sketches making necessary changes before uploading. LED on pin 7 and the button on pin 3




It was very exciting to see my board working



Having made 2 boards, I decided to try this on my second one which was my weaker of the two soldering jobs. I was happy to see it also worked.




My first attempt at pressing the button on my second board generated some smoke at the VCC pin on the header. I tried to recreate this experience but it seemed to work fine. I probably shorted something when my finger pressed the button. The design of this board is less than ideal as it has VCC and GND positioned very close to each other and around where your finger will be located.



FTDI

I did not have on hand an FTDI to USB converter so I used my Sparkfun Redboard as a Serial to USB converter and a power supply for my Hello board. This was pretty easy. I was able to power the board and test uploading sketches with the Arduino IDE. In this case, all the work was done with the FabISP. The redboard was just used to power the Hello board by connecting the GND and VCC between them. I was thrilled to see that sending information through my FabISP seems to work without a problem.




COMMUNICATING WITH THE BOARD

To setup an Arduino or equivalent board as a Serial to USB converter, you need to do the following:

- RESET to GND

NOTE:Sending reset to ground bypassses the board's microcontroller which is like taking the brain out of the device so it just performs a sync from USB to serial.

- GND to GND
- VCC to 5v
- TX to RX
- RX to TX

I followed an AVR tutorial from Ladyada (HERE) and also the excellent tutorials by Ana Kaziunas. Next I needed to try and get the board to communicate using C.



PROGRAMMING WITH C

With my FabISP attached to my Hello board, I wanted to test loading code to the board using AVR-GCC and I decided to try Niel's echo code. Using Terminal, I navigated to a folder containing the makefile and C code that I got off of the Fab Academy Embedded Programming page HERE. Once in the right directory I typed:

make hello.ftdi.44.make

This seemed to work. Next I needed to program the board. The makefile that we just called upon generates two files, .hex and a .out.. I needed to push the .hex file onto the board. I learned there are two ways:

---> A) Calling upon the makefile to send the .hex file to the ATTiny through the usbtiny(FabISP) programmer.

make -f hello.ftdi.44.echo.c.make program-usbtiny

---> B) Using AVRDUDE to push the .hex file onto the flash memory of the ATTiny using the usbtiny programmer.

avrdude -c usbtiny -p attiny44 -U flash:w:hello.ftdi.44.echo.c.hex

To understand this:

---> avrdude = the toolset used to program your avr chip
---> -p = the type of chip (attiny44)
---> -c = programmer type (usbtiny/FabISP)
---> -U = targeted memory (flash):action (w=write): title of your hex file.

I looked at several examples from FabAcademy students and most of them used the method mentioned in A. I tend to prefer the slightly longer B route. It is clear in my head what is happening. Using Avrdude I was able to push the .hex file onto the board with no problem.


Once the programmed was loaded on the ATTiny, I opened up the serial communication monitor in Arduino to see if the echo code worked. I was supposed to get a return character from what I enter in the command line. This did not work. It took me a bit of looking around and I realized that maybe my RX and TX were reversed. I switched them on my board so that TX from the Hello board was going to RX on the redboard and vice verca, it worked fine





SOFTWARE SERIAL

One of the main tools I have used in the past is MAX MSP/Jitter and I was curious to see if I could use it to control my Hello FTDI board the way I would an Arduino. Using the Arduino IDE I was able to communicate using Software Serial. It took a bit of jigging but I was able to make a simple connection between a virtual button in Max and the LED on my Hello FTDI board using RX and TX.

As per this MAX tutorial posted on youtube by Programming for People, you should normally be able to communicate with Max and Arduino using Serial.Read, Serial.Available, and Serial.println. This did not work for me. I came across this helpful tutorial on Instructables, and a couple of forum discussions that suggested that Arduino's SoftwareSerial library needs to be included and that I use mySerial.begin, mySerial.read, mySerial.available. I also had to define the TX, and RX pins and link them to mySerial. Other than that, I needed to make sure my Baud rate was 115200. Once I uploaded the following code to the Hello board, I as able to make it work.



#include "SoftwareSerial.h"

const int LED = 7;  

const int BUTTON = 3; 

const int Rx = 0; 

const int Tx = 1; 

SoftwareSerial mySerial(Rx, Tx);

int val = 0; // val from Max

void setup(){

pinMode(LED, OUTPUT);

pinMode(Rx, INPUT);

pinMode(Tx, OUTPUT);

mySerial.begin(115200); 

}

void loop()

{

//mySerial.read; // read MAX

if (mySerial.available()>0) {
  
  val = mySerial.read();
  if (val == 1) {
   digitalWrite(LED,HIGH);
    }
   else {
   digitalWrite(LED, LOW);
    }
  }
}