The personal website of Scott W Harden

AVR Programming in Linux

It is not difficult to program ATMEL AVR microcontrollers with linux, and I almost exclusively do this because various unofficial (inexpensive) USB AVR programmers are incompatible with modern versions of windows (namely Windows Vista and Windows 7). I am just now setting-up a new computer station in my electronics room (running Ubuntu Linux 12.04), and to make it easy for myself in the future I will document everything I do when I set-up a Linux computer to program microcontrollers.

Install necessary software

sudo apt-get install gcc-avr avr-libc uisp avrdude

Connect the AVR programmer

This should be intuitive for anyone who has programmed AVRs before. Visit the datasheet of your MCU, identify pins for VCC (+), GND (-), MOSI, MISO, SCK, and RESET, then connect them to the appropriate pins of your programmer.

Write a simple program in C

I made a file "main.c" and put the following inside. It's the simplest-case code necessary to make every pin on PORTD (PD0, PD1, ..., PD7) turn on and off repeatedly, sufficient to blink an LED.

#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
 DDRD = 255; // MAKE ALL PORT D PINS OUTPUTS

 while(1) {
  PORTD = 255;_delay_ms(100); // LED ON
  PORTD = 0;  _delay_ms(100); // LED OFF
 }

 return 0;
}

Compile the code (generate a HEX file)

avr-gcc -w -Os -DF_CPU=2000000UL -mmcu=atmega8 -c -o main.o main.c
avr-gcc -w -mmcu=atmega8 main.o -o main
avr-objcopy -O ihex -R .eeprom main main.hex

note that the arguments define CPU speed and chip model - this will need to be customized for your application

Program the HEX firmware onto the AVR

sudo avrdude -F -V -c avrispmkII -p ATmega8 -P usb -U flash:w:main.hex

note that this line us customized based on my connection (-P flag, USB in my case) and programmer type (-c flag, AVR ISP mkII in my case)

When this is run, you will see something like this:

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9307
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: input file main.hex auto detected as Intel Hex
avrdude: writing flash (94 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 94 bytes of flash written

Your Program should now be loaded!

Sit back and watch your LED blink.

  • TIP 1: I'm using a clone AVRISP mkII from Fun4DIY.com which is only $11 (shipped!). I glued it to a perf-board with a socket so I can jumper its control pins to any DIP AVR (80 pins or less). I also glued a breadboard for my convenience, and added LEDs (with ground on one of their pins) for easy jumpering to test programs. You can also build your own USB AVR ISP (free schematics and source code) from the USBtinyISP project website.

  • TIP 2: Make a shell script to run your compiling / flashing commands with a single command. Name them according to architecture. i.e., "build-m8" or "build-t2313". Make the first line delete all .hex files in the directory, so it stalls before it loads old .hex files if the compile is unsuccessful. Make similar shell scripts to program fuses. i.e., "fuse-m8-IntClock-8mhz", "fuse-m8-IntClock-1mhz", "fuse-m8-ExtCrystal".

  • TIP 3: Use a nice text editor well suited for programming. I love Geany.

Markdown source code last modified on January 18th, 2021
---
title: AVR Programming in Linux
date: 2013-01-06 14:51:19
tags: microcontroller, old
---

# AVR Programming in Linux

__It is not difficult to program ATMEL AVR microcontrollers with linux, and I almost exclusively do this because various unofficial (inexpensive) USB AVR programmers are incompatible with modern versions of windows (namely Windows Vista and Windows 7).__ I am just now setting-up a new computer station in my electronics room (running Ubuntu Linux 12.04), and to make it easy for myself in the future I will document everything I do when I set-up a Linux computer to program microcontrollers.

<div class="text-center img-border">

[![](mcu-programmer-far_thumb.jpg)](mcu-programmer-far.jpg)

</div>

### Install necessary software

```bash
sudo apt-get install gcc-avr avr-libc uisp avrdude
```

### Connect the AVR programmer

This should be intuitive for anyone who has programmed AVRs before. Visit the datasheet of your MCU, identify pins for VCC (+), GND (-), MOSI, MISO, SCK, and RESET, then connect them to the appropriate pins of your programmer.

### Write a simple program in C

I made a file "main.c" and put the following inside. It's the simplest-case code necessary to make every pin on PORTD (PD0, PD1, ..., PD7) turn on and off repeatedly, sufficient to blink an LED.

```c
#include <avr/io.h>
#include <util/delay.h>

int main (void)
{
 DDRD = 255; // MAKE ALL PORT D PINS OUTPUTS

 while(1) {
  PORTD = 255;_delay_ms(100); // LED ON
  PORTD = 0;  _delay_ms(100); // LED OFF
 }

 return 0;
}
```

### Compile the code (generate a HEX file)

```bash
avr-gcc -w -Os -DF_CPU=2000000UL -mmcu=atmega8 -c -o main.o main.c
avr-gcc -w -mmcu=atmega8 main.o -o main
avr-objcopy -O ihex -R .eeprom main main.hex
```

_note that the arguments define CPU speed and chip model - this will need to be customized for your application_

### Program the HEX firmware onto the AVR

```bash
sudo avrdude -F -V -c avrispmkII -p ATmega8 -P usb -U flash:w:main.hex
```

_note that this line us customized based on my connection (-P flag, USB in my case) and programmer type (-c flag, AVR ISP mkII in my case)_

When this is run, you will see something like this:

```
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9307
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: input file main.hex auto detected as Intel Hex
avrdude: writing flash (94 bytes):

Writing | ################################################## | 100% 0.04s

avrdude: 94 bytes of flash written
```

### Your Program should now be loaded!

Sit back and watch your LED blink.

<div class="text-center img-border">

[![](mcu-programmer-close_thumb.jpg)](mcu-programmer-close.jpg)

</div>

* __TIP 1:__ I'm using a clone AVRISP mkII from [Fun4DIY.com](http://fun4diy.com/AVRISP_mkII.htm) which is only $11 (shipped!). I glued it to a perf-board with a socket so I can jumper its control pins to any DIP AVR (80 pins or less). I also glued a breadboard for my convenience, and added LEDs (with ground on one of their pins) for easy jumpering to test programs. You can also build your own USB AVR ISP (free schematics and source code) from the [USBtinyISP](http://www.ladyada.net/make/usbtinyisp/) project website.

* __TIP 2:__ Make a shell script to run your compiling / flashing commands with a single command. Name them according to architecture. i.e., "build-m8" or "build-t2313". Make the first line delete all .hex files in the directory, so it stalls before it loads old .hex files if the compile is unsuccessful.  Make similar shell scripts to program fuses. i.e., "fuse-m8-IntClock-8mhz", "fuse-m8-IntClock-1mhz", "fuse-m8-ExtCrystal".

* __TIP 3:__ Use a nice text editor well suited for programming. I love [Geany](http://www.geany.org/).

My DIY Bench Power Supply

Another thing everybody needs (and has probably built) is a simple laboratory bench power supply. A lot of people use things like modified PC power supplies but I wasn't in favor of this because I wanted something smaller, lower current, and cleaner (from an RF perspective). My needs are nothing particularly high power, just something to provide a few common voltages for digital logic and small RF circuits. This is what I came up with!

In the image above you can see an ordinary LED being powered directly from the a 5V hook-up. There is no current limiting resistor, so a lot of current is travelling through the LED, burning it up as I photographed it. The ammeter (blue number) shows it's drawing 410 mA - whoa! The layout is pretty simple. Each red banana plug hook-up supplies a voltage (5, 5, 12, and variable respectively). Black hook-ups are ground. The black hook-up on the top left is a current-sensing ground, and current travelling through it will be displayed on the blue dial. The right dial shows the voltage of the variable voltage supply, and can go from about 3.5 - 30.5 V depending on where the potentiometer is set. All voltage outputs are designed to put-out approximately 1A of current.

I built this using a lot of (eBay) components I had on hand. I often save money where I can by stocking my workbench with components I buy in bulk. Here's what I used:

  • 4.5-3.0V DC volt meter - $2.08 (shipped) eBay
  • 0-9.99 A ampere meter - $4.44 (shipped) eBay
  • L7805 5V voltage regulator - 10 for $3.51 ($.35 ea) (shipped) eBay
  • L7812 12V voltage regulator - 20 for $3.87 ($.19 ea) (shipped) eBay
  • LM317 variable voltage regulator - 20 for $6.15 ($0.30 ea) (shipped) eBay
  • 10k linear potentiometer - 10 for 4.00 ($.40 ea) (shipped) eBay
  • banana plug hook-ups - 20 for $3.98 ($.20 ea) (shipped) eBay
  • aluminum enclosure - $3.49 (radioshack)

TOTAL: $13.60

Does the variable voltage actually work? Is the voltmeter accurate? Let's check it out.

I'd say it's working nicely! I now have a new took on my workbench.

A note about the yellow color: The enclosure I got was originally silver aluminum. I sanded it (to roughen the surface), then sprayed it with a yellow rustoleum spray paint. I figured it was intended to go on metal, so I might as well give it a shot. I sprayed it once, then gave it a second coat 20 minutes later, then let it dry overnight. In the future I think I would try a lacquer finish, because it's a bit easy to scratch off. However, it looks pretty cool, and I'm going to have to start spray-painting more of my enclosures in the future.

A note about smoothing capacitors. Virtually all diagrams of linear voltage regulators like the LM7805 show decoupling capacitors before and after the regulator. I added a few different values of capacitors on the input (you can see them in the circuit), but I intentionally did not include smoothing capacitors on the output. The reason was that I always put smoothing capacitors in my breadboards and in my projects, closer to the actual circuitry. If I included (and relied) on output capacitors at the level of the power supply, I would be picking-up 60Hz (and other garbage) RF noise in the cables coming from the power supply to my board. In short, no capacitors on the output, so good design must always be employed and decoupling capacitors added to whatever circuits are being built.

The input of this circuit is a 48V printer power supply from an archaic inkjet printer. It's been attached to an RCA jack to allow easy plugging and unplugging.

Markdown source code last modified on January 18th, 2021
---
title: My DIY Bench Power Supply
date: 2012-12-18 11:30:27
tags: circuit
---

# My DIY Bench Power Supply

__Another thing everybody needs (and has probably built) is a simple laboratory bench power supply.__ A lot of people use things like [modified PC power supplies](http://web2.murraystate.edu/andy.batts/ps/powersupply.htm) but I wasn't in favor of this because I wanted something smaller, lower current, and cleaner (from an RF perspective).  My needs are nothing particularly high power, just something to provide a few common voltages for digital logic and small RF circuits.  This is what I came up with!

<div class="text-center img-border">

[![](5_thumb.jpg)](5.jpg)

</div>

In the image above you can see an ordinary LED being powered directly from the a 5V hook-up.  There is no current limiting resistor, so a lot of current is travelling through the LED, burning it up as I photographed it. The ammeter (blue number) shows it's drawing 410 mA - whoa!  The layout is pretty simple. Each red banana plug hook-up supplies a voltage (5, 5, 12, and variable respectively). Black hook-ups are ground. The black hook-up on the top left is a current-sensing ground, and current travelling through it will be displayed on the blue dial.  The right dial shows the voltage of the variable voltage supply, and can go from about 3.5 - 30.5 V depending on where the potentiometer is set. All voltage outputs are designed to put-out approximately 1A of current.

<div class="text-center img-border">

[![](1_thumb.jpg)](1.jpg)

</div>

__I built this using a lot of (eBay) components I had on hand.__ I often save money where I can by stocking my workbench with components I buy in bulk. Here's what I used:

*   4.5-3.0V DC volt meter - $2.08 (shipped) eBay
*   0-9.99 A ampere meter - $4.44 (shipped) eBay
*   L7805 5V voltage regulator - 10 for $3.51 ($.35 ea) (shipped) eBay
*   L7812 12V voltage regulator - 20 for $3.87 ($.19 ea) (shipped) eBay
*   LM317 variable voltage regulator - 20 for $6.15 ($0.30 ea) (shipped) eBay
*   10k linear potentiometer - 10 for 4.00 ($.40 ea) (shipped) eBay
*   banana plug hook-ups - 20 for $3.98 ($.20 ea) (shipped) eBay
*   aluminum enclosure - $3.49 (radioshack)

TOTAL: $13.60

<div class="text-center">

![](LM317.gif)

</div>

Does the variable voltage actually work? Is the voltmeter accurate? Let's check it out.

<div class="text-center img-border">

[![](4_thumb.jpg)](4.jpg)

</div>

I'd say it's working nicely!  I now have a new took on my workbench.

<div class="text-center img-border">

[![](6_thumb.jpg)](6.jpg)

</div>

__A note about the yellow color:__ The enclosure I got was originally silver aluminum. I sanded it (to roughen the surface), then sprayed it with a yellow rustoleum spray paint. I figured it was intended to go on metal, so I might as well give it a shot. I sprayed it once, then gave it a second coat 20 minutes later, then let it dry overnight. In the future I think I would try a lacquer finish, because it's a bit easy to scratch off.  However, it looks pretty cool, and I'm going to have to start spray-painting more of my enclosures in the future.

<div class="text-center">

![](rust.jpg)

</div>

__A note about smoothing capacitors.__ Virtually all diagrams of linear voltage regulators like the LM7805 show decoupling capacitors before and after the regulator. I added a few different values of capacitors on the input (you can see them in the circuit), but I intentionally did _not_ include smoothing capacitors on the output. The reason was that I always put smoothing capacitors in my breadboards and in my projects, closer to the actual circuitry. If I included (and relied) on output capacitors at the level of the power supply, I would be picking-up 60Hz (and other garbage) RF noise in the cables coming from the power supply to my board. In short, no capacitors on the output, so good design must always be employed and decoupling capacitors added to whatever circuits are being built.

__The input__ of this circuit is a 48V printer power supply from an archaic inkjet printer. It's been attached to an RCA jack to allow easy plugging and unplugging.

Single Wavelength Pulse Oximeter

⚠️ Check out my newer ECG designs:

I want to create a microcontroller application which will utilize information obtained from a home-brew pulse oximeter. Everybody and their cousin seems to have their own slant how to make DIY pulse detectors, but I might as well share my experience. Traditionally, pulse oximeters calculate blood oxygen saturation by comparing absorbance of blood to different wavelengths of light. In the graph below (from Dildy et al., 1996 that deoxygenated blood (dark line) absorbs light differently than oxygenated blood (thin line), especially at 660nm (red) and 920nm (infrared). Therefore, the ratio of the difference of absorption at 660nm vs 920nm is an indication of blood oxygenation. Fancy (or at least well-designed) pulse oximeters continuously look at the ratio of these two wavelengths. Analog devices has a nice pulse oximeter design using an ADuC7024 microconverter. A more hackerish version was made and described on this non-english forum. A fail-at-the-end page of a simpler project is also shown here, but not well documented IMO.

That's not how mine works. I only use a single illumination source (~660nm) and watch it change with respect to time. Variability is due to a recombination effect of blood volume changes and blood oxygen saturation changes as blood pulses through my finger. Although it's not quite as good, it's a bit simpler, and it definitely works. Embedded-lab has a similar project but the output is only a pulsing LED (not what I want) and a voltage output that only varies by a few mV (not what I want).

Here's what the device looks like assembled in a breadboard:

I made a sensor by drilling appropriately-sized holes in a clothespin for the emitter (LED) and sensor (phototransistor). I had to bend the metal spring to make it more comfortable to wear. Light pressure is better than firm pressure, not only because it doesn't hurt as much, but because a firm pinch restricts blood flow considerably.

An obvious next step is microcontroller + LCD (or computer) digitization, but for now all you can do is check it out on my old-school analog oscilloscope. Vertical squares represent 1V (nice!). You can see the pulse provides a solid 2V spike.

Here's some video of it in action:

I'm holding-back the circuit diagram until I work through it a little more. I don't want to mislead people by having them re-create ill-conceived ideas on how to create analog amplifiers. I'll post more as I develop it.

Markdown source code last modified on January 18th, 2021
---
title: Single Wavelength Pulse Oximeter
date: 2012-12-06 08:13:41
tags: circuit, diyECG, old
---

# Single Wavelength Pulse Oximeter

> **⚠️ Check out my newer ECG designs:** 
* [**Sound Card ECG with AD8232**](https://swharden.com/blog/2019-03-15-sound-card-ecg-with-ad8232/)
* [**Single op-amp ECG**](https://swharden.com/blog/2016-08-08-diy-ecg-with-1-op-amp/)

__I want to create a microcontroller application__ which will utilize information obtained from a home-brew pulse oximeter. Everybody and their cousin seems to have their own slant how to make DIY pulse detectors, but I might as well share my experience. Traditionally, pulse oximeters calculate blood oxygen saturation by comparing absorbance of blood to different wavelengths of light. In the graph below (from [Dildy et al., 1996](http://www.ncbi.nlm.nih.gov/pubmed/8694032) that deoxygenated blood (dark line) absorbs light differently than oxygenated blood (thin line), especially at 660nm (red) and 920nm (infrared). Therefore, the ratio of the difference of absorption at 660nm vs 920nm is an indication of blood oxygenation. Fancy (or at least well-designed) pulse oximeters continuously look at the ratio of these two wavelengths. Analog devices has a [nice pulse oximeter design using an ADuC7024 microconverter](http://www.analog.com/library/analogDialogue/archives/41-01/pulse_oximeter.html). A more hackerish version was made and described [on this non-english forum](http://www.elektroda.pl/rtvforum/viewtopic.php?p=8025042). A fail-at-the-end page of a simpler project is also shown [here](http://blog.energymicro.com/2012/11/21/create-a-simple-pulse-oximeter-with-tiny-gecko/), but not well documented IMO.

<div class="text-center">

![](pulse-oximeter-wavelength.jpg)

</div>

That's not how mine works. I only use a single illumination source (~660nm) and watch it change with respect to time. Variability is due to a recombination effect of blood volume changes and blood oxygen saturation changes as blood pulses through my finger. Although it's not quite as good, it's a bit simpler, and it definitely works. [Embedded-lab has a similar project](http://embedded-lab.com/blog/?p=5508) but the output is only a pulsing LED (not what I want) and a voltage output that only varies by a few mV (not what I want).

__Here's what the device looks like assembled in a breadboard:__


<div class="text-center img-border img-medium">

[![](IMG_5919_thumb.jpg)](IMG_5919.jpg)

</div>

__I made a sensor__ by drilling appropriately-sized holes in a clothespin for the emitter (LED) and sensor (phototransistor). I had to bend the metal spring to make it more comfortable to wear. Light pressure is better than firm pressure, not only because it doesn't hurt as much, but because a firm pinch restricts blood flow considerably.

<div class="text-center img-border img-small">

[![](IMG_5920_thumb.jpg)](IMG_5920.jpg)
[![](IMG_5924_thumb.jpg)](IMG_5924.jpg)

</div>

__An obvious next step__ is microcontroller + LCD (or computer) digitization, but for now all you can do is check it out on my old-school analog oscilloscope. Vertical squares represent 1V (nice!). You can see the pulse provides a solid 2V spike.

<div class="text-center img-border img-medium">

![](pulse-scope.jpg)

</div>

__Here's some video of it in action:__

![](https://www.youtube.com/embed/MwkR_Vv0wMA)

I'm holding-back the circuit diagram until I work through it a little more. I don't want to mislead people by having them re-create ill-conceived ideas on how to create analog amplifiers. I'll post more as I develop it.

Geek Spin - ATTiny44 Project Prototype

Some days you feel like working on projects to benefit humanity. The day I made this clearly wasn't one of those days. A little over a year ago, I got into a troll war with my friend Mike Seese. The joke, similar to that of rick rolling, was to get each other to unexpectedly click a link to the Hatsune Miku version of the leekspin song. After several weeks of becoming beyond annoying, I decided to make an actual Hatsune Miku which would spin her leek and bobble her head to the techno version of the Levan Polka for his birthday.

The goal was to create a minature Miku which would perform perfectly in sync with audio coming from a portable music player (iPod or something) and NOT require a computer connection. I accomplished it by sending some creative control beeps out of the left channel of the stereo signal. Although I didn't finish the project, I got pretty far with the prototype, so I decided to dig it out of the archives and share it with the world because it's pretty entertaining!

(look how close I came to replicating the original:

How did I do it? First off, I used servos. If you're not familiar with them, I suggest you look up how servos work. Perhaps check out how to control servos with AVR microcontrollers. Basically, their position along a rotational axis is determined by the width of a pulse on a 20ms time window. Anyhow, if I only had 1 servo to control (i.e., leek only), I'd have controlled the servo directly with PWM signals in the left channel - no microcontroller needed, easy as pie, problem solved. However, since I needed to control two servos, I had to come up with something a bit more creative. Although I could have probably done this ten different ways, the way I chose to do it was using a series of pre-encoded leek spin and head bobble motions, triggered by control beeps in the left channel of the audio cable. (The right channel was patched through to the speakers.) Below is a diagram of what I believe I did, although I didn't thoroughly document it at the time, so you might have to use your imagination if you decide to re-create this project.

The idea is that by sending bursts of sine waves, the circuit can rectify them and smooth them out to have them look to a microcontroller like a brief "high" signal. Each signal would tell the microcontroller to proceed to the next pre-programmed (and carefully timed) routine. With enough practice listening, watching, and tweaking the code, I was able to make a final version which worked pretty darn well!

LISTEN to the music with control beeps (it's a surprisingly fun listen)

A few technical details are that I used an ATTiny44a microcontroller (it may have been an ATTiny2313, I can't remember for sure, but they're so similar it's virtually negligable). The servos I used were cheap (maybe $4?) from eBay. They looked like the one pictured below. The servo position was controlled by PWM, but I manually sent the pulses and didn't actually use the integrated PWM in the microcontroller. I can't remember why I did it this way - perhaps because it was so simple to use the _delay_us() and _delay_ms() functions? I also used an operational amplifier (if I remember, it was a LM741) to boost the left channel control signals rather than rectifying/assessing the left channel directly.

This is the video which I mimiced to create my prototype (note how the leek in her arm and her head move exactly the same as the prototype I made - score!)

And how did I find out about this song? I actually saw it on the video below which was hosted on wimp.com. I thought the song was catchy, looked it up, and the rest was history. It's worth noting that (perhaps to avoid copyright issues?) the key was shifted two half-steps up. I get a kick out of the way the girl waves her arm in the beginning, mimicking the leek :)

Here are some of the images I made which I printed, glued to foam board, and cut out with a razor blade. I'm not sure how useful they are, but they're provided just in case.

... but sometimes Japan takes it a bit too far and things get awkward ...

Below is the code I used. Note that PWM that controls the servos isn't the integrated PWM, but rather a couple pins I manually pulse on and off to control the arm and head positions. Also notice how, in the main routine, I wait for the control beeps before continuing the next sequences.


// leek spin code - designed for ATTiny
// by Scott Harden, www.SWHarden.com

#include <avr/io.h>
#include <avr/delay.h>

void go_high(){
    // sets the arm to the highest position
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA0);
        _delay_us(1400);
        PORTA&=~(1<<PA0);
        _delay_us(20000-1200);
        }
    }

void go_low(){
    // sets the leek to the middle position
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA0);
        _delay_us(1900);
        PORTA&=~(1<<PA0);
        _delay_us(20000-1900);
        }
    }

void go_lowest(){
    // sets the leek to the lowest position
    for (char i=0;i<5;i++){ // takes 100ms total
        PORTA|=(1<<PA0);
        _delay_us(2300);
        PORTA&=~(1<<PA0);
        _delay_us(20000-2500);
        }
    }

void go_slow(char times){
    // does one slow leek down/up
    // beat is 500ms
    for (char i=0;i<times;i++){
        go_low();
        _delay_ms(10);
        go_high();
        _delay_ms(290);
        PORTA^=(1<<PA2);
        PORTA^=(1<<PA3);
    }
}

void go_fast(char times){
    // does one fast leek down/up
    // beat is 250ms
    for (char i=0;i<times;i++){
        go_low();
        _delay_ms(10);
        go_high();
        _delay_ms(15);
        PORTA^=(1<<PA2);
        PORTA^=(1<<PA3);
    }
}
void head_left(){
    // tilts the head to the left
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA1);
        _delay_us(1330);
        PORTA&=~(1<<PA1);
        _delay_us(20000-1200);
        }
    }

void head_right(){
    // tilts the head to the right
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA1);
        _delay_us(1500);
        PORTA&=~(1<<PA1);
        _delay_us(20000-1200);
        }
    }

void head_center(){
    // centers the head
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA1);
        _delay_us(1400);
        PORTA&=~(1<<PA1);
        _delay_us(20000-1200);
        }
    }

void head_go(char times){
    // rocks the head back and forth once
    for (char i=0;i<(times-1);i++){
        head_left();
        _delay_ms(400);
        PORTA^=(1<<PA2);
        PORTA^=(1<<PA3);
        head_right();
        _delay_ms(400);
        PORTA^=(1<<PA2);
        PORTA^=(1<<PA3);
    }
    head_center(); // returns head to center when done
    _delay_ms(400);
    PORTA^=(1<<PA2);
    PORTA^=(1<<PA3);
}

int main(void) {
    while (1){
        DDRA=255; // set port A (servos) as outputs
        DDRB=0; // set port B (listening pins) as inputs

        go_lowest();head_center();// set starting positions

        while ((PINB & _BV(PB0))){} // wait for beep que
        PORTA=(1<<PA3);
        go_high();_delay_ms(1000);
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(31); // tilt leek slowly 31 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(31); // tilt leek slowly 31 times

        while ((PINB & _BV(PB0))){} // wait for beep que
        _delay_ms(200);
        head_go(16); // rock head 16 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_fast(68); // tilt leek rapidly 68 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(24); // tilt leek slowly 24 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_fast(17); // tilt leek rapidly 17 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(31); // tilt leek slowly 31 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(31); // tilt leek slowly 31 times

        while ((PINB & _BV(PB0))){} // wait for beep que
        _delay_ms(200);
        head_go(16); // rock head 16 times
        go_lowest(); // reset position
        PORTA=0;
    }
  return 0;
}

Finally, I'd like to take a moment to indicate one of the reasons this project is special to me. My wife, Angelina Harden, died one year ago today. This project was the last one she worked on with me. She died a few days after the video was taken, and in the process of moving out of our apartment I threw away almost everything (including this project). Although I never finished it, I remember working on it with Angelina - we went to wal-mart together to buy the foam board I used to make it, and she told me that I should make her head rock back and forth rather than just move her arm. I remember that, once it was all done, I let her sit in the chair in front of it and played it through, and she laughed nearly the whole time :) I'll always miss her.

Markdown source code last modified on January 18th, 2021
---
title: Geek Spin - ATTiny44 Project Prototype
date: 2012-08-18 15:28:38
tags: microcontroller, old
---

# Geek Spin - ATTiny44 Project Prototype

__Some days you feel like working on projects to benefit humanity. The day I made this clearly wasn't one of those days.__ A little over a year ago, I got into a troll war with my friend [Mike Seese](http://www.mikeseese.com/). The joke, similar to that of [rick rolling](http://www.youtube.com/watch?v=oHg5SJYRHA0), was to get each other to unexpectedly click a link to the [Hatsune Miku version of the leekspin song](http://www.youtube.com/watch?v=kbbA9BhCTko&feature=player_embedded). After several weeks of becoming beyond annoying, I decided to make an _actual_ Hatsune Miku which would spin her leek and bobble her head to the techno version of the [Levan Polka](http://www.youtube.com/watch?v=1ygdAiDxKfI) for his birthday.

<div class="text-center img-border">

![](leek-spin.gif)

</div>

__The goal was to create a minature Miku which would perform perfectly in sync with audio coming from a portable music player (iPod or something) and _NOT_ require a computer connection.__ I accomplished it by sending some creative control beeps out of the left channel of the stereo signal. Although I didn't finish the project, I got pretty far with the prototype, so I decided to dig it out of the archives and share it with the world because it's pretty entertaining!

![](https://www.youtube.com/embed/RzqdL5gqaHM)

(look how close I came to replicating the original:

![](https://www.youtube.com/embed/6ZWwqTnqxdk)

__How did I do it?__ First off, I used servos. If you're not familiar with them, I suggest you look up [how servos work](http://www.servocity.com/html/how_do_servos_work_.html). Perhaps check out [how to control servos with AVR microcontrollers](http://www.engineersgarage.com/embedded/avr-microcontroller-projects/atmega16-servo-motor-circuit). Basically, their position along a rotational axis is determined by the width of a pulse on a 20ms time window. Anyhow, if I only had 1 servo to control (i.e., leek only), I'd have controlled the servo directly with PWM signals in the left channel - no microcontroller needed, easy as pie, problem solved. However, since I needed to control two servos, I had to come up with something a bit more creative. Although I could have probably done this ten different ways, the way I chose to do it was using a series of pre-encoded leek spin and head bobble motions, triggered by control beeps in the left channel of the audio cable. (The right channel was patched through to the speakers.)  Below is a diagram of what I believe I did, although I didn't thoroughly document it at the time, so you might have to use your imagination if you decide to re-create this project.

<div class="text-center img-border">

![](2012-08-18-15.21.34-525x289.jpg)

</div>

__The idea is that by sending bursts of sine waves,__ the circuit can rectify them and smooth them out to have them look to a microcontroller like a brief "high" signal. Each signal would tell the microcontroller to proceed to the next pre-programmed (and carefully timed) routine.  With enough practice listening, watching, and tweaking the code, I was able to make a final version which worked pretty darn well!


<div class="text-center img-border">

![](geek_spin.gif)

</div>

__LISTEN__ to the [music with control beeps](http://www.SWHarden.com/blog/images/2012/08/GOLEEKGO.mp3) (it's a surprisingly fun listen)

__A few technical details__ are that I used an ATTiny44a microcontroller (it may have been an ATTiny2313, I can't remember for sure, but they're so similar it's virtually negligable).  The servos I used were cheap (maybe $4?) from eBay. They looked like the one pictured below. The servo position was controlled by PWM, but I manually sent the pulses and didn't actually use the integrated PWM in the microcontroller.  I can't remember why I did it this way - perhaps because it was so simple to use the _delay_us() and _delay_ms() functions? I also used an operational amplifier (if I remember, it was a LM741) to boost the left channel control signals rather than rectifying/assessing the left channel directly.

<div class="text-center img-border img-micro">

[![](01_findpic_thumb.jpg)](01_findpic.png)
[![](02_dropbg_thumb.jpg)](02_dropbg.jpg)
[![](08_hairtop_thumb.jpg)](08_hairtop.jpg)
[![](06_blockskirt_thumb.jpg)](06_blockskirt.jpg)
[![](body_thumb.jpg)](body.png)
[![](hairtop_thumb.jpg)](hairtop.png)

</div>

[This is the video](https://www.youtube.com/embed/kbbA9BhCTko) which I mimiced to create my prototype (note how the leek in her arm and her head move exactly the same as the prototype I made - score!)

__And how did I find out about this song?__ I actually saw it on the video below which was hosted on wimp.com. I thought the song was catchy, looked it up, and the rest was history. It's worth noting that (perhaps to avoid copyright issues?) the key was shifted two half-steps up. I get a kick out of the way the girl waves her arm in the beginning, mimicking the leek :)

![](https://www.youtube.com/embed/Pk1CTYszDFU)

__Here are some of the images I made__ which I printed, glued to foam board, and cut out with a razor blade. I'm not sure how useful they are, but they're provided just in case.

... but sometimes Japan takes it a bit too far and things get awkward ...

__Below is the code I used.__ Note that PWM that controls the servos isn't the integrated PWM, but rather a couple pins I manually pulse on and off to control the arm and head positions. Also notice how, in the main routine, I wait for the control beeps before continuing the next sequences.

```c

// leek spin code - designed for ATTiny
// by Scott Harden, www.SWHarden.com

#include <avr/io.h>
#include <avr/delay.h>

void go_high(){
    // sets the arm to the highest position
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA0);
        _delay_us(1400);
        PORTA&=~(1<<PA0);
        _delay_us(20000-1200);
        }
    }

void go_low(){
    // sets the leek to the middle position
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA0);
        _delay_us(1900);
        PORTA&=~(1<<PA0);
        _delay_us(20000-1900);
        }
    }

void go_lowest(){
    // sets the leek to the lowest position
    for (char i=0;i<5;i++){ // takes 100ms total
        PORTA|=(1<<PA0);
        _delay_us(2300);
        PORTA&=~(1<<PA0);
        _delay_us(20000-2500);
        }
    }

void go_slow(char times){
    // does one slow leek down/up
    // beat is 500ms
    for (char i=0;i<times;i++){
        go_low();
        _delay_ms(10);
        go_high();
        _delay_ms(290);
        PORTA^=(1<<PA2);
        PORTA^=(1<<PA3);
    }
}

void go_fast(char times){
    // does one fast leek down/up
    // beat is 250ms
    for (char i=0;i<times;i++){
        go_low();
        _delay_ms(10);
        go_high();
        _delay_ms(15);
        PORTA^=(1<<PA2);
        PORTA^=(1<<PA3);
    }
}
void head_left(){
    // tilts the head to the left
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA1);
        _delay_us(1330);
        PORTA&=~(1<<PA1);
        _delay_us(20000-1200);
        }
    }

void head_right(){
    // tilts the head to the right
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA1);
        _delay_us(1500);
        PORTA&=~(1<<PA1);
        _delay_us(20000-1200);
        }
    }

void head_center(){
    // centers the head
    for (char i=0;i<5;i++){
        PORTA|=(1<<PA1);
        _delay_us(1400);
        PORTA&=~(1<<PA1);
        _delay_us(20000-1200);
        }
    }

void head_go(char times){
    // rocks the head back and forth once
    for (char i=0;i<(times-1);i++){
        head_left();
        _delay_ms(400);
        PORTA^=(1<<PA2);
        PORTA^=(1<<PA3);
        head_right();
        _delay_ms(400);
        PORTA^=(1<<PA2);
        PORTA^=(1<<PA3);
    }
    head_center(); // returns head to center when done
    _delay_ms(400);
    PORTA^=(1<<PA2);
    PORTA^=(1<<PA3);
}

int main(void) {
    while (1){
        DDRA=255; // set port A (servos) as outputs
        DDRB=0; // set port B (listening pins) as inputs

        go_lowest();head_center();// set starting positions

        while ((PINB & _BV(PB0))){} // wait for beep que
        PORTA=(1<<PA3);
        go_high();_delay_ms(1000);
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(31); // tilt leek slowly 31 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(31); // tilt leek slowly 31 times

        while ((PINB & _BV(PB0))){} // wait for beep que
        _delay_ms(200);
        head_go(16); // rock head 16 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_fast(68); // tilt leek rapidly 68 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(24); // tilt leek slowly 24 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_fast(17); // tilt leek rapidly 17 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(31); // tilt leek slowly 31 times
        while ((PINB & _BV(PB0))){} // wait for beep que
        go_slow(31); // tilt leek slowly 31 times

        while ((PINB & _BV(PB0))){} // wait for beep que
        _delay_ms(200);
        head_go(16); // rock head 16 times
        go_lowest(); // reset position
        PORTA=0;
    }
  return 0;
}

```

__Finally, I'd like to take a moment to indicate one of the reasons this project is special to me.__ My wife, Angelina Harden, died one year ago today. This project was the last one she worked on with me. She died a few days after the video was taken, and in the process of moving out of our apartment I threw away almost everything (including this project). Although I never finished it, I remember working on it with Angelina - we went to wal-mart together to buy the foam board I used to make it, and she told me that I should make her head rock back and forth rather than just move her arm. I remember that, once it was all done, I let her sit in the chair in front of it and played it through, and she laughed nearly the whole time :) I'll always miss her.

Introduction to PIC Programming for AVR users

I'm not ashamed to say it: I'm a bit of an ATMEL guy. AVR microcontrollers are virtually exclusively what I utilize when creating hobby-level projects. Wile I'd like to claim to be an expert in the field since I live and breathe ATMEL datasheets and have used many intricate features of these microchips, the reality is that I have little experience with other platforms, and have likely been leaning on AVR out of habit and personal convention rather than a tangible reason.

Although I was initially drawn to the AVR line of microcontrollers because of its open-source nature (The primary compiler is the free AVR-GCC) and longstanding ability to be programmed from non-Windows operating systems (like Linux), Microchip's PIC has caught my eye over the years because it's often a few cents cheaper, has considerably large professional documentation, and offers advanced integrated peripherals (such as native USB functionality in a DIP package) more so than the current line of ATTiny and ATMega microcontrollers. From a hobby standpoint, I know that ATMEL is popular (think Arduino), but from a professional standpoint I usually hear about commercial products utilizing PIC microcontrollers. One potential drawback to PIC (and the primary reason I stayed away from it) is that full-featured C compilers are often not free, and as a student in the medical field learning electrical engineering as a hobby, I'm simply not willing to pay for software at this stage in my life.

I decided to take the plunge and start gaining some experience with the PIC platform. I ordered some PIC chips (a couple bucks a piece), a PIC programmer (a Chinese knock-off clone of the Pic Kit 2 which is <$20 shipped on eBay), and shelved it for over a year before I got around to figuring it out today. My ultimate goal is to utilize its native USB functionality (something at ATMEL doesn't currently offer in DIP packages). I've previously used bit-banging libraries like V-USB to hack together a USB interface on AVR microcontrollers, but it felt unnecessarily complex. PIC is commonly used and a bit of an industry standard, so I'm doing myself a disservice by not exploring it. My goal is USB functionality, but I have to start somewhere: blinking a LED.

Here's my blinking LED. It's a bit anticlimactic, but it represents a successful program design from circuit to writing the code to programming the microchip.

Based on my limited experience, it seems you need 4 things to program a PIC microcontroller with C:

The first thing I did was familiarize myself with the pin diagram of my PIC from its datasheet. I'm playing with an 18F2450 and the datasheet is quite complete. If you look at the pin diagram, you can find pins labeled MCLR (reset), VDD (+5V), VSS (GND), PGC (clock), and PGD (data). These pins should be connected to their respective counterparts on the programmer. To test connectivity, install and run the PICkit2 installer software and it will let you read/verify the firmware on the chip, letting you know connectivity is solid. Once you're there, you're ready to start coding!

I wish I were friends with someone who programmed PIC, such that in 5 minutes I could be shown what took a couple hours to figure out. There are quite a few tutorials out there - borderline too many, and they all seem to be a bit different. To quickly get acquainted with the PIC programming environment, I followed the "Hello World" Program in C tutorial on PIC18F.com. Unfortunately, it didn't work as posted, likely because their example code was based on a PIC 18F4550 and mine is an 18F2450, but I still don't understand why such a small difference caused such a big problem. The problem was in their use of LATDbits and TRISDbits (which I tried to replace with LATBbits and TRISBbits). I got around it by manually addressing TRISB and LATB. Anyway, this is what I came up with:

#include <p18f2450.h> // load pin names
#include <delays.h>   // load delay library

#pragma config WDT = OFF // disable watchdog timer
#pragma config FOSC = INTOSCIO_EC // use internal clock

void main() // this is the main program
{
    TRISB=0B00000000; // set all pins on port B as output
    while(1) // execute the following code block forever
    {
        LATB = 0b11111111; // turn all port B pins ON
        Delay10KTCYx(1);   // pause 1 second
        LATB = 0b00000000; // turn all port B pins OFF
        Delay10KTCYx(1);   // pause 1 second
    }
}

A couple notes about the code: the WDT=OFF disables the watchdog timer, which if left unchecked would continuously reboot the microcontroller. The FOSC=INTOSCIO_EC section tells the microcontroller to use its internal oscillator, allowing it to execute code without necessitating an external crystal or other clock source. As to what TRIS and LAT do, I'll refer you to basic I/O operations with PIC.

Here is what the MPLAB IDE looked like after I successfully loaded the code onto the microcontroller. At this time, the LED began blinking about once per second. I guess that about wraps it up! This afternoon I pulled a PIC out of my junk box and, having never programmed a PIC before, successfully loaded the software, got my programmer up and running, and have a little functioning circuit. I know it isn't that big of a deal, but it's a step in the right direction, and I'm glad I've taken it.

Markdown source code last modified on January 18th, 2021
---
title: Introduction to PIC Programming for AVR users
date: 2012-06-24 20:29:03
tags: microcontroller, old
---

# Introduction to PIC Programming for AVR users

__I'm not ashamed to say it: I'm a bit of an ATMEL guy.__ [AVR microcontrollers](http://en.wikipedia.org/wiki/Atmel_AVR) are virtually exclusively what I utilize when creating hobby-level projects. Wile I'd like to claim to be an expert in the field since I live and breathe ATMEL datasheets and have used many intricate features of these microchips, the reality is that I have little experience with other platforms, and have likely been leaning on AVR out of habit and personal convention rather than a tangible reason.

<div class="text-center">

![](150-28-DIP1-200x128.jpg)

</div>

**Although I was initially drawn to the AVR line of microcontrollers** because of its open-source nature (The primary compiler is the free AVR-GCC) and longstanding ability to be programmed from non-Windows operating systems (like Linux), [Microchip's PIC](http://en.wikipedia.org/wiki/PIC_microcontroller) has caught my eye over the years because it's often a few cents cheaper, has considerably large professional documentation, and offers advanced integrated peripherals (such as native USB functionality in a DIP package) more so than the current line of ATTiny and ATMega microcontrollers. From a hobby standpoint, I know that ATMEL is popular (think [Arduino](http://en.wikipedia.org/wiki/Arduino)), but from a professional standpoint I usually hear about commercial products utilizing PIC microcontrollers. One potential drawback to PIC (and the primary reason I stayed away from it) is that full-featured C compilers are often not free, and as a student in the medical field learning electrical engineering as a hobby, I'm simply not willing to pay for software at this stage in my life.

__I decided to take the plunge and start gaining some experience with the PIC platform.__ I ordered some PIC chips (a couple bucks a piece), a PIC programmer (a Chinese knock-off clone of the [Pic Kit 2](http://en.wikipedia.org/wiki/PICKit) which is <$20 shipped on eBay), and shelved it for over a year before I got around to figuring it out today. My ultimate goal is to utilize its native USB functionality (something at ATMEL doesn't currently offer in DIP packages). I've previously used bit-banging libraries like [V-USB](http://www.obdev.at/products/vusb/index.html) to hack together a USB interface on AVR microcontrollers, but it felt unnecessarily complex. PIC is commonly used and a bit of an industry standard, so I'm doing myself a disservice by not exploring it. My goal is USB functionality, but I have to start somewhere: blinking a LED.

<div class="text-center">

![](2012-06-24-15.57.56-525x393.jpg)

</div>

__Here's my blinking LED__. It's a bit anticlimactic, but it represents a successful program design from circuit to writing the code to programming the microchip.
>  _Based on my limited experience, it seems you need 4 things to program a PIC microcontroller with C:_
>
> *   __[PIC microcontroller](http://en.wikipedia.org/wiki/PIC_microcontroller)__ compatible with your programmer and your software (I'm using [18F2450](http://ww1.microchip.com/downloads/en/DeviceDoc/39760d.pdf))
> *   __PIC programmer__ (I'm using a clone [PicKit 2](http://en.wikipedia.org/wiki/PICKit), [$19.99 shipped on eBay](http://www.ebay.com/sch/i.html?_trksid=p5197.m570.l1313&_nkw=pic+kit+2&_sacat=0)) - get the PICkit2 installer [here](http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023805)
> *   Install __[MPLAB IDE](http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en019469&part=SW007002)__ (programming environment for PIC) - has a free version
> *   Install a __C compiler__: I'm using [PIC18 C Compiler for MPLAB](http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en010014) Lite - has a free version
>
>
__The first thing I did was familiarize myself with the pin diagram of my PIC from its datasheet__. I'm playing with an [18F2450](http://ww1.microchip.com/downloads/en/DeviceDoc/39760d.pdf) and the [datasheet is quite complete](http://ww1.microchip.com/downloads/en/DeviceDoc/39760d.pdf). If you look at the pin diagram, you can find pins labeled __MCLR__ (reset), __VDD__ (+5V), __VSS__ (GND), __PGC__ (clock), and __PGD__ (data). These pins should be connected to their respective counterparts on the programmer. To test connectivity, install and run the [PICkit2 installer software](http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1406&dDocName=en023805) and it will let you read/verify the firmware on the chip, letting you know connectivity is solid. Once you're there, you're ready to start coding!

__I wish I were friends with someone who programmed PIC, such that in 5 minutes I could be shown what took a couple hours to figure out.__ There are quite a few tutorials out there - borderline too many, and they all seem to be a bit different. To quickly get acquainted with the PIC programming environment, I followed the ["Hello World" Program in C tutorial](http://www.pic18f.com/18f4550-c-tutorial/2009/11/16/tutorial-4-hello-world-program-in-c/) on [PIC18F.com](http://www.pic18f.com/). Unfortunately, it didn't work as posted, likely because their example code was based on a PIC 18F4550 and mine is an 18F2450, but I still don't understand why such a small difference caused such a big problem. The problem was in their use of LATDbits and TRISDbits (which I tried to replace with LATBbits and TRISBbits). I got around it by manually addressing TRISB and LATB. Anyway, this is what I came up with:

```c
#include <p18f2450.h> // load pin names
#include <delays.h>   // load delay library

#pragma config WDT = OFF // disable watchdog timer
#pragma config FOSC = INTOSCIO_EC // use internal clock

void main() // this is the main program
{
    TRISB=0B00000000; // set all pins on port B as output
    while(1) // execute the following code block forever
    {
        LATB = 0b11111111; // turn all port B pins ON
        Delay10KTCYx(1);   // pause 1 second
        LATB = 0b00000000; // turn all port B pins OFF
        Delay10KTCYx(1);   // pause 1 second
    }
}
```

__A couple notes about the code:__ the WDT=OFF disables the [watchdog timer](http://en.wikipedia.org/wiki/Watchdog_timer), which if left unchecked would continuously reboot the microcontroller. The FOSC=INTOSCIO_EC section tells the microcontroller to use its internal oscillator, allowing it to execute code without necessitating an external crystal or other clock source. As to what TRIS and LAT do, I'll refer you to [basic I/O operations with PIC](http://www.mikroe.com/eng/chapters/view/4/chapter-3-i-o-ports/).

<div class="text-center img-medium">

[![](pic-ledblink_thumb.jpg)](pic-ledblink.png)

</div>

__Here is what the MPLAB IDE looked like after I successfully loaded the code onto the microcontroller.__ At this time, the LED began blinking about once per second. I guess that about wraps it up! This afternoon I pulled a PIC out of my junk box and, having never programmed a PIC before, successfully loaded the software, got my programmer up and running, and have a little functioning circuit. I know it isn't _that_ big of a deal, but it's a step in the right direction, and I'm glad I've taken it.
Pages