Articles Tagged projects, page 1
Blinking an LED - The C Way
Posted on February 29th, 2012 00:50:17
by landon
Comments
After doing a couple of projects in assembly, I've started over again in C, but this time I'll be publishing the projects. The purpose of this is to:
- Figure out how the usual C code translates into assembly and vice versa.
- Provide a series of simple projects building on each other for people interested in microcontrollers.
- Give employers some public examples to look through.
- Get started building an awesome project for Christmas gifts.
To start off this series of posts, I'll use the simplest example possible, which is blinking an LED. I'll be using the avr-gcc toolchain to compile. The microcontroller I'll be using is the Atmel AVR ATtiny2313 until I start to run out of space or pins. Unless an example requires it, the fuses will be set so that the microcontroller runs at 1MHz.
Hooking It Up

I have a two color LED with the common cathode connected to ground by a 1kΩ resistor. The two anodes are hooked up to the PA0 and PA1 pins on the microcontroller. It doesn't matter which color is hooked up to which pin for this example. Since I don't have a good bench power supply available, the microcontroller is powered by a 4xAA battery pack which provides around 5-5.3V (right under the maximum operating voltage of 6.0V for the microcontroller.)
The Terminology
Fuses - To change clockspeed and other basic features such as using the reset pin as IO, AVR microcontrollers uses fuses that are set when programming. Other microncontrollers may do things differently, right now my only experience has been with AVRs that uses fuses and a Freescale HCS08 chip where the clock was set in code. The fuse calculator provided by Engbedded is what I personally use to calculate what I need to set. Fuses only need to be set once, even if you program the chip multiple times.
Anode/Cathode - An anode is where current flows into an element, the cathode is where it flows out. In the LED I'm using, there is a common cathode, so I only need to connect that to ground (with the resistor of course). The two anodes of the LED are connected to their respective pins.
Design Considerations
One thing to note about using _delay_ms() is the resolution. From the <util/delay.h> reference page.
The maximal possible delay is 262.14 ms / F_CPU in MHz.
Uhoh. With our clock set at 1 MHz, this means the max delay is 262.14ms, just over a quarter of a second.
However,
When the user request delay which exceed the maximum possible one, _delay_ms() provides a decreased resolution functionality. In this mode _delay_ms() will work with a resolution of 1/10 ms, providing delays up to 6.5535 seconds (independent from CPU frequency). The user will not be informed about decreased resolution.
This isn't a problem, since we don't need such a small resolution.
But finally,
If the avr-gcc toolchain has __builtin_avr_delay_cycles(unsigned long) support, maximal possible delay is 4294967.295 ms/ F_CPU in MHz. For values greater than the maximal possible delay, overflows results in no delay i.e., 0ms.
Checking /usr/lib/avr/include/avr/builtins.h, this builtin is defined along with the accompanying __HAS_DELAY_CYCLES macro. So there's nothing to worry about in the first place.
The Code
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 1000000UL // 1MHz
int main(void)
{
DDRA |= 0x03; // Set PA0 and PA1 to be outputs
while (1)
{
PORTA ^= 0x03; // Toggle PA0 and PA1
_delay_ms(1000.0);
}
}
If the microcontroller is programmed properly, the LED should be flashing a combination of the two colors (an orange-y color in my case).
Interim Activities
Posted on February 28th, 2012 00:07:04
by landon
Comments
Since my last post I've put Cube IRC on the back burner and focused on finishing a few other projects:
Starting with Saints Row: The Third

Followed by Bastion

And then some Torchlight

With a little Super Meat Boy thrown in

Culminating in World of Warcraft

I dare say I'm all gamed out and ready to put up some awesome posts about avr-gcc!
My new project: Cube IRC
Posted on January 18th, 2012 17:23:18
by landon
Comments
What is it?
Cube IRC is a 3d IRC client that I've been working on for the last two weeks off and on. What I want to do is be able to connect to a chat room and visualize what's going on. Who are the frequent talkers? Who is lurking? Who are the talkative groups? Right now the client isn't at the stage where I can answer those questions, but it does connect to a room and create an avatar for everyone joining the room and talking in it.
The architecture
(so far)
Working with threads
There are two major elements so far, the graphics thread and the IRC thread. Threading is implemented using boost::thread, which ended up being very simple. The program starts off initializing the graphical client and setting the parameters of the IRC client, which is then started. Communication between the two threads is handled with a message queue that passes every IRC event to the graphics thread. The upside of this method is that it is very simple, but the downside is that the graphics thread has to do all the processing, the IRC thread only keeps state as much as it needs to to stay connected to the server.
IRC
The IRC client is implemented with libircclient in a custom C++ wrapper. There's not much more to it other than a configuration file read in using Ogre::ConfigFile. Currently there is support for joining a single server and multiple channels, although the graphics side does not really differentiate between channels. That's one more hurdle to jump, how I am going to deal with a user that is in more than one channel.
Graphics
I'm using Ogre3D for the graphics side of the client. Every time someone on IRC joins or talks to the channel, an avatar is created and if necessary a chat overlay will pop up over their head. When they quit the server or part a channel, the corresponding model is deleted. Right now this side doesn't have much depth, because most of my time spent so far was getting the basics to work, such as thread communications and popping up an overlay to represent a line from IRC.
Future Plans
I would like to use some of the animations available in the current model and attach those to specific phrases, such as starting the dancing animation when someone mentions dancing in the channel. I also want to have some sort of AI in the avatars that moves them closer to avatars they're addressing, but still maintaining a distance and not colliding with others. Also, ideally, when someone joins the channel, the avatar should enter from a "doorway" and walk over to their default position.
The Goods
Screenshots of current progress
Sooner or later I'll open up the git repo as well.
An LCD Gotcha
Posted on October 17th, 2011 12:38:08
by landon
Comments
Last week I posted some AVR gotchas, but now it's time for an LCD gotcha!
<rue_shop2> Landon, for over 6 years, everyone who gets a hd447880 screen has written their own library
Yep, that's what I did. I wrote some LCD helpers in assembly for this project. The big problem I encountered was my strings were getting truncated when I read them from the EEPROM and displayed them on the LCD. After verifying my EEPROM code was correct, I turned to my LCD code. I had just switched to waiting on the Busy Flag of the LCD instead of a max delay.
Assuming all of my ports are set up correctly (PortD6 is the Enable line of the LCD)
STILL_BUSY:
sbi PORTD, 6 ; enable
nop
in R16, PIND ; read in Data7 (attached to PortD3)
cbi PORTD, 6 ; disable
andi R16, 0x08 ; mask out all but pin 3
brne STILL_BUSY
Ok, you might not see the problem yet. Let me give you some more information. I was also working in 4 bit mode. Look again.
The gotcha is that with 4 bit, reads need to be done twice, otherwise you'll be reading part of the current address next time you strobe the Enable line. Duh! This wasn't apparent in the article I was using though, because 4 bit mode was almost an afterthought in the microcontroller implementation and there was no way you would be punching buttons fast enough by hand to need to wait on the Busy Flag.
Corrected code:
STILL_BUSY:
sbi PORTD, 6 ; enable
nop
in R16, PIND ; read in Data7 (attached to PortD3)
cbi PORTD, 6 ; disable
rcall PULSE_ENABLE ; need to call twice, because of 4 bit mode
andi R16, 0x08 ; mask out all but pin 3
brne STILL_BUSY
Common AVR Gotchas
Posted on October 10th, 2011 10:24:06
by landon
Comments
I'm going to list a few gotchas I encountered this weekend while fiddling around with my AVR projects.
The first:
Interrupts don't happen unless they're... enabled. I spent too long trying to figure out why the timer overflow in my previous test worked, but the timer compare match in my current test didn't. The reason it didn't work? Somewhere in there I had deleted sei from my init code. That's right, interrupts are so important that they have their own commands: cli and sei.
The second:
The commands cbr and sbr for registers are NOT the same as their I/O counterparts cbi and sbi. Let's take a peek at the instruction set manual.
CBI – Clear Bit in I/O Register
Description:
Clears a specified bit in an I/O Register. This instruction operates on the lower 32 I/O Registers - addresses 0-31.
Operation:
I/O(A,b) ← 0
This command is straightforward, it takes a bit number as the second operand and sets that bit to 0. Now let's see cbr.
CBR – Clear Bits in Register
Description:
Clears the specified bits in register Rd. Performs the logical AND between the contents of register Rd and the complement of the constant mask K. The result will be placed in register Rd.
Operation:
Rd ← Rd • ($FF - K)
I hope you read the instruction descriptions before blindly using this. In this command the complement of the second operand is ANDed with the register. So that means, while you can get away with cbi PORTA, 1 to clear the second bit in PORTA, you can't do cbr R16, 1 to clear the second bit in R16. Instead, you'll clear the first bit (0b11111111-0b01=0b11111110).
SBI – Set Bit in I/O Register
Description:
Sets a specified bit in an I/O Register. This instruction operates on the lower 32 I/O Registers - addresses 0-31.
Operation:
I/O(A,b) ← 1
This one is straightforward just like cbi.
SBR – Set Bits in Register
Description:
Sets specified bits in register Rd. Performs the logical ORI between the contents of register Rd and a constant mask K and places the result in the destination register Rd.
Operation:
Rd ← Rd v K
Just like cbi and sbi, sbr is the counterpart to cbr and works similarly. Instead of the second operand being a number from 0-7, it is a bitmask as in cbr.
Undoubtedly, I'll have more gotchas when I get back to work on my projects next weekend.
