« First ‹ Prev 1 2 Next › Last »

Articles Tagged blog, page 1

The importance of a good library

Posted on March 30th, 2012 00:26:19 by landon
Comments

While working on the latest project for the blog (a small game using an HD44780 display), I realized that my code was going to be a mess! Instead of delaying for another half month, I think the next few posts will be for supporting libraries. Soon I'll have a decent library up for detecting button presses (or other single bit port changes). One of the more recent additions to my technical library, [Making Embedded Systems](http://shop.oreilly.com/product/0636920017776.do), is getting me off to a good start. It's already given me a couple of good ideas, so I just need to give in and start the project over from scratch.

Introducing the Keypad

Posted on March 1st, 2012 22:18:54 by landon
Comments

For this project, I'm going to introduce a 4x3 (3x4?) keypad. The 0-9 keys will determine the frequency of the flashing LED, from 0Hz to 9Hz. In addition, the * and # keys will determine which LED I'm setting the frequency for.

The Terminology

State Machine - A state machine is a collection of different states. For example, you could have two states IN_WORD and OUT_OF_WORD, which both process a string. While in the IN_WORD state, you could, for example, increment a word length counter. When a space appears, you'll set the state to OUT_OF_WORD. While you're in the OUT_OF_WORD state, you could set the word length counter to 0, but when you encounter something that's not a space, you switch to the state IN_WORD.

Example State Machine

Debounce - One annoying feature of keypads and switches in general is that when they're pressed they will bounce from open to closed. To account for this, my code has a built in delay in the state machine to filter out rapid changes that would come from debouncing.

Design Considerations

There are two main parts to this project:

  • Keypad Entry
  • LED Flashing

There's a fairly simple state machine that I can implement to decode the key presses. (The one in the code has been modified a bit from the picture to loop in decode_state a bit to debounce the keypad, but is basically the same.)

Keypad State Machine

Once a key is decoded, I'll stick it in a buffer so it can be processed in the main loop.

To get LED flashing correct, the timer will be set to interrupt so all of the toggle frequencies are multiples of the interrupt frequency. The exact multiples will be stored in a lookup table indexed by the keypad numbers.

Working With the Keypad

The 3x4 keypad has 8 pins. 4 pins are for the rows and 3 for the columns, along with one pin that won't be connected. There are a couple of ways to decode it, but since I have plenty of free pins, I'll hook them all up to a port and continuously poll that for changes and then scan it for the row/column combination. When a button on the keypad is pressed, it connects the corresponding row and column lines. So what I'll do is set the pins connected to the row lines as inputs with the pullup resistor enabled (this sets them high when there's no other signal). The pins connected to the column lines will be set as outputs and all will be set low. When a button is pressed, a single one of the row inputs will also go low. Once this change is detected, then for each column I toggle the output high until I find one that makes all of the rows read high. Then I use the column number as an index into a short lookup table to determine which button was pressed. The code should make the process clear!

Getting the Right LED Frequency

To simplify matters, I'm going to use a separate timer for LED flashing interrupts. I've decided the interrupt should trigger every millisecond. This isn't perfect for all frequencies. However, the greatest calculated error is only .2% for 6Hz, which is acceptable because I won't be able to tell the difference with my eye. (For reference, the errors from 1Hz to 9Hz are: 0%, 0%, .1%, 0%, 0%, .2%, .1%, 0%, .1%).

Hooking It Up

Schematic

Keypad Off

Keypad On

Keypad Pins

The Code

Unfortunately code length is quickly growing larger than I want to keep directly in the blog post. If you want syntax highlighting, you'll have to open it into the editor of your choice.

keypad.h

keypad.c

main.c

The Video

Coming soon!


Blinking an LED - This time with interrupts

Posted on March 1st, 2012 01:12:02 by landon
Comments

In this example, I'll switch over to using the ATtiny2313's 8-bit timer module for toggling the LEDs. Everything is still connected exactly as it was in the last example.

Before I get too far along with my examples, I'm going to introduce a new section. Ideally people with little experience in microcontrollers should be able to follow along and pick up useful tips (if not just able to take and compile my code). So, I'll be introducing the new pieces as I understand it.

The Terminology

Timer module - The ATtiny2313 has many modules that will do a lot of the hard work for you, one set of these is the 8-bit timer and the 16-bit timer. The most basic operation involves setting up a prescaler

Prescaler - The prescaler effectively divides the clock. So, with a prescaler setting of /64 on the timer module, the timer will not tick on every clock cycle, but only every 64 cycles.

Interrupts - One of the more powerful features of working at a low level, interrupts allow modules to stop all code execution and jump to their own interrupt subroutine (ISR). When the ISR returns, everything will pick up as it left off. More precautions have to be taken with interrupts in assembly than in C, such as making sure registers, especially the status register, are preserved. If the status register isn't preserved, then an interrupt could potentially foul up the results of a simple statement such as "if (foo==3)".

What's new

I'll be using the 8-bit timer module and interrupts to count off the 1 second LED changes.

The other major change from the previous example is that I decided that one of the LEDs should flash twice as slow. To do this, I'm going to simply XOR its current state with the other LEDs new state. No seperate counters required.

Design Considerations

One of the main concerns with using the 8-bit timer to count off seconds is getting it to divide evenly into the clock frequency. The clock frequency is a power of 10, but the prescalers and various division methods are powers of 2.

As you can see in the code comments, I set the timer up to have a prescaler of 64 and interrupt on overflow (256) as well as only toggling the LEDs when another counter hit 61. All told, this gets to 1 second with .06% error. One thing I could have done differently was to change the value the timer would interrupt on. Keeping the prescaler the same (64), the factorization of 1000000/64 is 5^6. If you split that into 5^3*5^3, then you can have the timer interrupt at 125 and toggle when the counter in the code equals 125. That equals exactly 1000000, so it should be as close to 1 second as you can get.

The Code

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

#define F_CPU 1000000UL // Running at 1 MHz

char counter;

int main(void)
{
    DDRA = 0x03; // Set PA0 and PA1 to be outputs
    TCCR0B |= (1<<CS01)|(1<<CS00); //set prescaler to /64, which divides evenly into 1MHz

TIMSK |= (1<<TOIE0); // Enable timer 0 interrupts

counter = 0;

sei(); // Enable interrupts

while (1)
    {
        // Do nothing. Alternatively, a sleep instruction could be used so the CPU only wakes
        // on interrupts and immediately goes back to sleep.
    }
}

// Set an interrupt on the Timer0 Overflow vector
ISR(TIMER0_OVF_vect)
{
    counter++;
    if (counter == 61) // This gets VERY close to 1 second
                       // The timer prescaler (64) * 8 bit overflow (256) * 61 = .999424 seconds
                       // .06% error should be close enough for this application
    {
        char led1, led2;
        led1 = PINA & 0x01; // Get PA0's pin value
        led1 ^= 0x01; // Toggle PA0
        led2 = (PINA>>1) & 0x01; // Get PA1's pin value
        led2 ^= led1; // Xor PA1 with the current state of PA0, effectively doubling the period
        PORTA = (led2 << 1) | led1;
        counter = 0;
    }
}

Closing Thoughts

Some improvements I've noticed so far using C over assembly? Control flow is much less effort. I don't need to figure out what label I'm going to use or how I'm going to set up a loop or if statement. Setting bits in registers is more concise and using the << and >> syntax, I can easily determine which bits are being set/cleared.


Another blog change

Posted on October 8th, 2011 17:08:25 by landon
Comments

I changed my blog yet again and spent all day copying over posts (hopefully for the last time!)

I'm now using django-articles and have an awesome disqus comment system set up, so have at!


Hard drive replacement

Posted on November 1st, 2009 13:57:51 by landon
Comments

Over the past year I've put off replacing some dying drives (2*750gb) I have. Lately they've started to have a lot of problems so I went ahead and bought some replacements. For future reference, if you don't plan on using dd to copy over the drive then rsync -avP -H --numeric-ids /mnt/src /mnt/dst should work just as well. (I need the hard links especially for my backups drive, which is where Dirvish dumps everything to. Without the hard link copying, rsync would try to copy many many many more terabytes of backups than I can reasonably hold!