For the electronics units in the Fab Academy, you will need:
Open Terminal and type:
sudo apt-get install flex byacc bison gcc libusb-dev avrdudeThen type:
sudo apt-get install gcc-avr- type "y" when asked to do so by your system
sudo apt-get install avr-libcThen type (may already be installed):
sudo apt-get install libc6-dev
Move to the desktop
cd ~/Desktop
Download the firmware from the Fab Academy Electronics Production page.
wget http://fab.cba.mit.edu/classes/863.16/doc/tutorials/fabisp_programming/fabISP_0.8.2_firmware.zip
Unzip the firmware
unzip fabISP_0.8.2_firmware.zip
Download the firmware (right click on the link below and save it to your desktop):
Open terminal navigate to the desktop:
cd ~/Desktop/
Unzip the fabISP_0.8.2_firmware.zip directory:
unzip fabISP_0.8.2_firmware.zip
Move into the newly created firmware directory on your desktop
cd ~/Desktop/firmware
nano Makefile
Open the Makefile with TextEdit.
Open the Makefile with Notepad++.
A window will open containing the Makefile. Go to the line that says:
#AVRDUDE = avrdude -c usbtiny -p $(DEVICE) # edit this line for your programmer
AVRDUDE = avrdude -c avrisp2 -P usb -p $(DEVICE) # edit this line for your programmer
- If using the USBtiny programmer or another FabISP
- Remove the "#" in front of the line with "usbtiny" in it
- Add a "#" to beginning the line with the "avrisp2" in it to comment it out.
- save the Makefile
Navigate to the directory where you saved the FabISP firmware. If you followed the instructions above, this will be the desktop.
Ubuntu / Windows type:
cd Desktop/firmware
For Mac users who downloaded the modified firmware:
cd Desktop/fabISP_mac.0.8.2_firmware
Type:
make cleanIf you are successful - you will see this response from the system:
akaziuna@Titan:~/Desktop/firmware$ make cleanType:
rm -f main.hex main.lst main.obj main.cof main.list main.map main.eep.hex
main.elf *.o usbdrv/*.o main.s usbdrv/oddebug.s usbdrv/usbdrv.s
make hex
If you are successful - you will see this response from the system:
akaziuna@Titan:~/Desktop/firmware$ make hex avr-gcc -Wall -Os -DF_CPU=20000000 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -c usbdrv/usbdrv.c -o usbdrv/usbdrv.o avr-gcc -Wall -Os -DF_CPU=20000000 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -x assembler-with-cpp -c usbdrv/usbdrvasm.S -o usbdrv/usbdrvasm.o avr-gcc -Wall -Os -DF_CPU=20000000 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -c usbdrv/oddebug.c -o usbdrv/oddebug.o avr-gcc -Wall -Os -DF_CPU=20000000 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -c main.c -o main.o avr-gcc -Wall -Os -DF_CPU=20000000 -Iusbdrv -I. -DDEBUG_LEVEL=0 -mmcu=attiny44 -o main.elf usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o rm -f main.hex main.eep.hex avr-objcopy -j .text -j .data -O ihex main.elf main.hex avr-size main.hex text data bss dec hex filename 0 2020 0 2020 7e4 main.hex
Type:
make fuseIf you are successful - you will see the following response from the system:
akaziuna@Titan:~/Desktop/firmware$ sudo make fuse avrdude -c usbtiny -p attiny44 -U hfuse:w:0xDF:m -U lfuse:w:0xFF:m avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.01s avrdude: Device signature = 0x1e9207 avrdude: reading input file "0xDF" avrdude: writing hfuse (1 bytes): Writing | ################################################## | 100% 0.00s avrdude: 1 bytes of hfuse written avrdude: verifying hfuse memory against 0xDF: avrdude: load data hfuse data from input file 0xDF: avrdude: input file 0xDF contains 1 bytes avrdude: reading on-chip hfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of hfuse verified avrdude: reading input file "0xFF" avrdude: writing lfuse (1 bytes): Writing | ################################################## | 100% 0.01s avrdude: 1 bytes of lfuse written avrdude: verifying lfuse memory against 0xFF: avrdude: load data lfuse data from input file 0xFF: avrdude: input file 0xFF contains 1 bytes avrdude: reading on-chip lfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of lfuse verified avrdude: safemode: Fuses OK avrdude done. Thank you.
Then type:
make programIf you are successful - you will see the following response from the system.
akaziuna@Titan:~/Desktop/firmware$ sudo make program [sudo] password for akaziuna: avrdude -c usbtiny -p attiny44 -U flash:w:main.hex:i avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.01s avrdude: Device signature = 0x1e9207 avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed To disable this feature, specify the -D option. avrdude: erasing chip avrdude: reading input file "main.hex" avrdude: writing flash (2020 bytes): Writing | ################################################## | 100% 5.68s avrdude: 2020 bytes of flash written avrdude: verifying flash memory against main.hex: avrdude: load data flash data from input file main.hex: avrdude: input file main.hex contains 2020 bytes avrdude: reading on-chip flash data: Reading | ################################################## | 100% 3.36s avrdude: verifying ... avrdude: 2020 bytes of flash verified avrdude: safemode: Fuses OK avrdude done. Thank you. avrdude -c usbtiny -p attiny44 -U hfuse:w:0xDF:m -U lfuse:w:0xFF:m avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.01s avrdude: Device signature = 0x1e9207 avrdude: reading input file "0xDF" avrdude: writing hfuse (1 bytes): Writing | ################################################## | 100% 0.00s avrdude: 1 bytes of hfuse written avrdude: verifying hfuse memory against 0xDF: avrdude: load data hfuse data from input file 0xDF: avrdude: input file 0xDF contains 1 bytes avrdude: reading on-chip hfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of hfuse verified avrdude: reading input file "0xFF" avrdude: writing lfuse (1 bytes): Writing | ################################################## | 100% 0.00s avrdude: 1 bytes of lfuse written avrdude: verifying lfuse memory against 0xFF: avrdude: load data lfuse data from input file 0xFF: avrdude: input file 0xFF contains 1 bytes avrdude: reading on-chip lfuse data: Reading | ################################################## | 100% 0.00s avrdude: verifying ... avrdude: 1 bytes of lfuse verified avrdude: safemode: Fuses OK avrdude done. Thank you.
Type:
lsusbIf your FabISP has been successfully programmed, you should see a list of the USB devices plugged into your computer. The FabISP will be listed in a line like the following:
Bus 002 Device 004: ID 1781:0c9f Multiple Vendors USBtiny
Go to the System Profiler > Hardware > USB > Hub:
Step - By - Step:
Go to the Start Menu > Hardware and Sound. The FabISP should be listed.
Remove the 0 ohm resistor and solder bridge as shown in the picture below. Now you can use it as a programmer to program other boards.
The USBtiny (on which the FabISP is based), the original FabISP, and all of the many variants and improvements use a library called V-USB to handle the USB communication. USB is a fairly complex protocol, and usually is implemented with dedicated hardware on a microcontroller with USB support. V-USB implements USB entirely in software, which enables USB on practically any AVR microcontroller just using the GPIO pins. The timing requirements are met by using hand-optimized assembly code.
V-USB works incredibly well, considering how much of a hack it is. However, USB still has fairly stringent timing requirements in order to work properly. V-USB implements a low-speed USB device, with signaling at 1.5 MHz, which is the least demanding type of USB device. However, if the timing is too far off, this can cause USB communication problems.
Over the years, many people have iterated on the FabISP design to reduce the component count, use cheaper components, and use more readily available values. For example, a ceramic resonator isn't something you'd usually find on a microcontroller that's speaking USB, since the frequency might be too inaccurate for reliable communication. Yet several FabISP designs use ceramic resonators, and appear to work. This raises questions about how far tolerances can be stretched before a programmer is no longer a reliable USB device. As USB ports get faster and faster, USB controllers can also be less tolerant of timing and frequency variations.
To investigate whether some of the FabISP designs have deviated far enough from the USB spec to start causing widespread problems, I probed several different FabISP variants with a high-speed oscilloscope. The results are below.
The oscilloscope capture shows the differential USB signals from three different FabISP variants. The vertical lines are a 3MHz reference clock. Since low-speed USB signaling occurs at 1.5MHz, each bit should last for two vertical lines. If the timing is accurate, the transitions should happen right on the lines, not before or after.
These captures show the beginning of a packet on the USB bus, sent from the FabISP to the computer. This starts with a synchronization sequence (the high/low/high/low/high/low pattern) followed by four bits identifying the type of packet (in this case, it's an acknoweldgement from the FabISP that the last message from the computer was received).
The three traces, from top to bottom, are:
The transitions for the original FabISP, which used 49Ω bus termination resistors, are noticeably faster and more square. In later designs, the termination resistors changed to 100Ω for some reason, leading to the more rounded edges.
While the timing has gotten measurably worse from the original 12MHz design, the current 20MHz crystal versions shouldn't cause any problems. Crystal resonators are still probably not the best idea for a USB device (the frequency inaccuracy is easily seen on the bottom trace), they do seem to work in most cases. The risk is the luck of the draw getting a resonator that's far enough on the edge of its tolerance that it causes problems.
Fortunately, all of the USB transfers used by the FabISP are very short; there isn't very much time for the error to accumulate.
If you're making a new FabISP design, I'd strongly recommend using a crystal. The slight extra cost is well worth the accuracy.
Another option: Zaerc's FabTinyStar is perhaps the best combination of minimal component count, lowest cost, and timing accuracy. It uses the internal RC oscillator—normally, a rather inaccurate frequency reference—but calibrates it on-the-fly. A new USB frame begins precisely every 2 ms—by tuning the RC oscillator in software based on the start-of-frame packets every 2ms, the microcontroller's clock can be fairly well synchronized to the host's. A scope capture from the data lines on the FabTinyStar is shown below, and the timing is spot-on.
Note the nice sharp edges. In part this is due to the 49Ω resistors rather than 100Ω, but also due to a much shorter cable.