experimenting with a incremental encoder switch

September 8th, 2010

Here is a simple example of how to use a incremental encoder. It nicely shows how to handle buttons and interrupts with the MSP430. The particular encoder I am using is a Bourns PEC11-4020F-S0024 ( http://www.bourns.com/PDFs/pec11.pdf ) incremental encoder with push button.

The encoder has 5 pins.  The two pins on the top are the push button function when the encoder is pressed in the switch closes and is working like any oher push button. The three pins on the bottom are the encoder with the function A, Common and B. The common pin needs to be connected to ground and the pins A and B need to be connected to a pull up resistor. I opted to use the internal pull up resistors in the MSP430 to safe external components. But like with all mechanical buttons we need a debounce circuit (or do it in software). I personally prefer using a simple RC debounce circuit.

To visualize the encoder I choose to output the current state of the encoder on P1.0 to P1.5 with P1.0 toggling every time the encoder is pushed and P1.1 to P1.5 moving left and right based on the rotation of the encoder. I used a 74LS06 hex inverter / driver chip to drive the LED.

So here is the complete circuit:

encoder_circuit.png

The diagram shows the signals of the encoder signals A and B. I choose to use the low to high transition on encoder pin A to trigger a interrupt. Based on the rotation direction the signal on enc oder pin B will be either low for clockwise turns or high for counter clockwise turns.

encoder_signal1.png

So with all this here is the code (main.c):


/* Enoder example

Simple program to test a rotary encoder with pushbutton

Setup:

+—————-+
LED — | P1.0 P2.6 | — NC
LED — | P1.1 P2.7 | — Push Button
LED — | P1.2 |
LED — | P1.3 |
LED — | P1.4 P1.7 | — Encoder B
LED — | P1.5 P1.6 | — Encoder A
+—————-+

Function:
* Every time the encoder is pushed the LED on P1.0 will be toggled
* The LED on P1.1 to P1.5 will move left/right according to the encoder
* The script uses the internal pullup resistors

*/

#include
#include

unsigned char encoder_pos = BIT3; // Set starting pos to P1.3
unsigned char push_pos = 0;

// interrupt function toggling P1.0 on every push of encoder
interrupt (PORT2_VECTOR) p1_encoder_int(){
dint();

if( P2IFG & 0x80 ) {
push_pos ^= BIT0;
P1OUT = BIT7 | BIT6 | encoder_pos | push_pos; // output P1 with push status and encoder pos
}
P2IFG = 0x00;
eint();
}

// interrupt function moving positin bit per encoder
interrupt (PORT1_VECTOR) p1_encoder_move(){
dint();

if( P1IFG & 0x40 ) {
if ( P1IN & BIT7 ) { // b is high -> counter clockwise
if ( encoder_pos > BIT1 ) { // only move down if not already at bottom
encoder_pos = encoder_pos >> 1;
}
} else { // b is low -> clockwise
if ( encoder_pos < BIT5 ) {
encoder_pos = encoder_pos << 1;
}
}
P1OUT = BIT7 | BIT6 | encoder_pos | push_pos; // output P1 with push status and encoder pos
}
P1IFG = 0x00;
eint();
}

int main(void) {
WDTCTL = WDTPW | WDTHOLD;

// Setup port
P1SEL = 0x00; // select io function for all ports (this is actually default for P1)
P1REN = 0xC0; // select pullup resistors for pin 1.7 and 1.6
P1DIR = 0x3F; // iioo oooo
P1OUT = 0xC8; // need to set P1.6 and P1.7 to high so PULLUP resistor will be selected
P1IES = 0x00; // select low to high transition for interrupts on all port pins (this actually the default)
P1IE = 0x40; // enable interrupt for P1.6 to reader status of encoder every time Encoder sigal A goes high
P1IFG = 0x00; // clear interrupt register

P2SEL = 0x00; // selection io function for all ports (default is actually XIN.XOUT for P2.7/2.6)
P2REN = 0x80; // select pullup resistors for pin 2.7
P2DIR = 0x7F; // iooo oooo
P2OUT = 0x80; // need to set P2.7 to high so PULLUP resistor will be selected
P2IES = 0x00; // select low to high transition for interrupts on all port pins
P2IE = 0x80; // enable interrupt P2.7 for push button
P2IFG = 0x00; // clear interrupt register

eint();

for (;;) {
// loop forever
}

}

Blog problems

August 29th, 2010

yesterday I had the unpleasant experience of a dead hard-drive. Fortunately nothing important was lost, but when I tried to get a Makefile example from my blog I noticed that the code section on the blog actually erases sections like the import filenames, replaces some of the code from 0x to 0* and other problems.

Loading code onto target msp and debugging

August 16th, 2010

In the last post I finally compiled the blinked led example and created a makefile. Now we want to load program onto the target and let it run.

First you need to connect your EZ430 to your computer. It will start running the whatever was loaded last.

Then connect mspdebug to your ez430 with ‘mspdebug -d /dev/ttyUSB0‘. If this gives you an error you will need to find the correct device. You can see if the device is recognized by your system by watching your /var/log/message file when you connect the EX430 and via the lsusb command. Below is the output I get on my system for both commands.

$ lsusb
Bus 006 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 005 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 004 Device 005: ID 0451:f430 Texas Instruments, Inc. MSP-FET430UIF JTAG Tool
Bus 004 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 003 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 002 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
$ tail -f /var/log/messages
Aug 15 22:26:56 linux-desktop kernel: [21806.152048] usb 4-1: new full speed USB device using ohci_hcd and address 4
Aug 15 22:26:56 linux-desktop kernel: [21806.337313] usb 4-1: configuration #1 chosen from 1 choice
Aug 15 22:26:56 linux-desktop kernel: [21806.341196] ti_usb_3410_5052 4-1:1.0: TI USB 3410 1 port adapter converter detected
Aug 15 22:26:56 linux-desktop kernel: [21806.341216] usb 4-1: firmware: requesting ti_usb-v0451-pf430.fw
Aug 15 22:26:56 linux-desktop kernel: [21806.345078] usb 4-1: firmware: requesting ti_3410.fw
Aug 15 22:26:56 linux-desktop kernel: [21807.028065] usb 4-1: reset full speed USB device using ohci_hcd and address 4
Aug 15 22:26:57 linux-desktop kernel: [21807.193080] usb 4-1: device firmware changed
Aug 15 22:26:57 linux-desktop kernel: [21807.193140] ti_usb_3410_5052: probe of 4-1:1.0 failed with error -5
Aug 15 22:26:57 linux-desktop kernel: [21807.193231] usb 4-1: USB disconnect, address 4
Aug 15 22:26:57 linux-desktop kernel: [21807.332049] usb 4-1: new full speed USB device using ohci_hcd and address 5
Aug 15 22:26:57 linux-desktop kernel: [21807.549300] usb 4-1: configuration #1 chosen from 2 choices
Aug 15 22:26:57 linux-desktop kernel: [21807.552564] ti_usb_3410_5052 4-1:1.0: TI USB 3410 1 port adapter converter detected
Aug 15 22:26:57 linux-desktop kernel: [21807.552604] ti_usb_3410_5052: probe of 4-1:1.0 failed with error -5
Aug 15 22:26:57 linux-desktop kernel: [21807.557526] ti_usb_3410_5052 4-1:2.0: TI USB 3410 1 port adapter converter detected
Aug 15 22:26:57 linux-desktop kernel: [21807.557729] usb 4-1: TI USB 3410 1 port adapter converter now attached to ttyUSB0
^C

If your system connects correctly you can load the code via ‘prog led.hex’ and use mspdebug as a gdb proxy via the ‘gdb’ command.

$ mspdebug -d /dev/ttyUSB0 uif
MSPDebug version 0.10 - debugging tool for MSP430 MCUs
Copyright (C) 2009, 2010 Daniel Beer
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Trying to open UIF on /dev/ttyUSB0…
Initializing FET…
FET protocol version is 10002000
Configured for Spy-Bi-Wire
Set Vcc: 3000 mV
Device: MSP430F20x3
Code memory starts at 0xf800
Number of breakpoints: 2

Available commands:
= dis hexout opt reset step
break erase isearch prog run sym
cgraph gdb md read set
delbreak help mw regs setbreak

Available options:
color gdb_loop

Type “help ” for more information.
Press Ctrl+D to quit.

(mspdebug) prog led.hex
Erasing…
Writing 104 bytes to f800…
Writing 32 bytes to ffe0…
(mspdebug) gdb
Bound to port 2000. Now waiting for connection…

Now you can call ddd via ‘ ddd –debugger msp430-gdb led.elf‘ which tells ddd to use the msp430-gdb debugger and we are debugging led.elf. To connect I typed ‘target remote :2000‘ in the command window followed by a ‘continue‘ and then pressing the interrupt command but. I also found out that it is best to remove all breakpoints in ddd before connecting the target and always first issue the continue command otherwise the connection would be lost. Now you can single step the code, visualize your data and iron out the last bugs.

Finally to stop the ddd session use the ‘disconnect‘ command.

DDD session screenshot

Compiling the first program

August 12th, 2010

So now that we have mspgcc compiler and mspdebug tool installed we finally can write our own programs.

To start we create the blinking led example.

Here is the source code for main.c

/* Blink LED example */

#include 

/** Delay function. **/
delay(unsigned int d) {
  int i;
  for (i = 0; i<d; i++) {
    nop();
  }
}

int main(void) {
  WDTCTL = WDTPW | WDTHOLD;
  P1DIR = 0xFF;
  P1OUT = 0x01;

  for (;;) {
    P1OUT = ~P1OUT;
    delay(0x4fff);
  }
}

Now you can compile the program via:

msp430-gcc -Os -mmcu=msp430x2013 -o led.elf main.c

msp430-objdump -DS led.elf > led.lst

msp430-objcopy -o ihex led.elf > led.hex

The first command while compile the c source code into an executable in elf format. The second command will generate an assembler listing of your program. The third command will give a hexdump of the opcodes in Intel Hex Format. You can actually look at the led.lst and led.hex files they are human readable.

Now it would be cumbersome to actually do this every time manually. The better way is to create a make file and let make take of this.

Here is a example for the makefile:

# makefile configuration

NAME = led
OBJECTS = main.o
CPU = msp430x2013
CFLAGS = -mmcu=${CPU} -Os -Wall -g

#switch the compiler (for the internal make rules)
CC = msp430-gcc
.PHONY: all FORCE clean download dist

#all should be the first target. it's built when make is run without args
all: ${NAME}.elf ${NAME}.hex ${NAME}.lst

#additional rules for files
${NAME}.elf: ${OBJECTS}
  ${CC} -mmcu=${CPU} -o $@ ${OBJECTS}

${NAME}.hex: ${NAME}.elf
  msp430-objcopy -O ihex $^ $@

${NAME}.lst: ${NAME}.elf
  msp430-objdump -dSt $^ >$@

clean:
  rm -f ${NAME}.elf ${NAME}.hex ${NAME}.lst ${OBJECTS}

#backup archive
dist:
  tar czf dist.tgz *.c *.h *.txt makefile

#dummy target as dependecy if something has to be build everytime
FORCE:

#project dependencies
main.o: main.c

If you are coping the file make replace the indention spaces with a <tab> otherwise the file will not be correct ( sorry I could not figure out how blogilo would not convert them). As you can see this actually does a few more things than 3 commands before. First how to use this makefile:

You can build all via ‘make‘ or ‘make all‘ since ‘all’ is the first rule defined it will be the default.

The first lines NAME defines the common part of all the files to create (here led.*). The OBJECT variable lists all object files. The CPU sets the target cpu type and CFLAGS sets all the compiler options. CC tells make what compile it should use. All the following lines starting at position 0 define a build rule (e.g. all/clean). The names listed after the ‘:’ define the dependencies for the rule which also need to be called. If the build rule has some idented lines (need to start with a <tab>) it defines the command this rule executes, e.g. the clean rule executes the rm command.

Next step is to load the program on the target and debug the code.

Installing MSPGCC4 and MSPDEBUG on Kubuntu 10.04

June 21st, 2010

A few weeks ago I decided to upgrade my PC from an older version of OpenSuse to Kubuntu 10.04. Here are my steps to install on Kunbuntu 10.04.

I installed following packages via System Settings->Add and Remove Software but I believe it would just as easy to use apt-get on the command line.

  • subversion
  • gcc-4.4
  • texinfo
  • patch
  • libncurses5-dev
  • zlibc
  • zlib1g-dev
  • libx11-dev
  • libusb-dev
  • libreadline6-dev

With those packages installed I could install mspgcc4 with following steps:

  1. check out mspgcc4 from sourceforge via “svn checkout https://mspgcc4.svn.sourceforge.net/svnroot/mspgcc4”
  2. change directory into newly created mspgcc4 via “cd mspgcc”
  3. run the build script via “sudo sh buildgcc.sh”
    I basicly used all the default answers by pressing ENTER only selecting “Build now” with yes (default there is no)
    This installed all the tools under /opt/msp430-gcc-4.4.3.
  4. Next I added /opt/msp430-gcc-4.4.3/bin to the path in /etc/profiles (“export PATH=${PATH}:/opt/msp430-gcc-4.4.3/bin”)

Next I downloaded the tar file for mspdebug from sourceforge ( http://mspdebug.sourceforge.net/download.html ).

Then I was able to install the mspdebug via:

  1. tar xvfz mspdebug-version.tar.gz
  2. cd mspdebug-version
  3. make
  4. sudo make install

I can start mspdebug for the ez430F2013 with “mspdebug -u /dev/ttyUSB0” Update: in version 0.10 the -u option is not there anymore. Instead I had to use “mspdebug -d /dev/ttyUSB0 uif” to connect to my EZ430

Next to come build the blinking LED example for the ez430F2013.

Optional:

If you don’t like the msp-insight you can use ddd with msp430-gdb via installing the ddd package and starting it with “ddd msp430-gdb”.

Still alive

June 14th, 2010

Ok so I wasn’t kidding when I posted not to expect something anytime soon. Well here we are over a year later with only the second post.

Anyway even I wasn’t posting anything on the blog I did play with a few things.

The first thing was deciding on what microprocessor platform to use. I decided to try my luck with Texas Instruments MSP430 platform since they offer this neat little platform EZ430 ( see EZ430 at TI.com ). This uses the newer Spy-BiWire programming and debugging interface found on the new chips. Another reasons were the very low power consumption of the MSP430 architecture, wide selection of devices, from 14 pin MSP430F20xx to 113 pin version, from 128Byte to 16KB of RAM, 512Byte to 256KByte of Flash and a wide selection of integrated peripherals.

The Ez430 development platform comes in different version. Options range from the EZ430F21013 which is one of the cheapest commercial platforms you can find anywhere (at the time of writing TI sold this for US$20 in their web shop) to complete ZigBee solutions (EZ430-RF2480). Those little kits contain a little USB stick as programmer and debugger and a 6pin header to connect the target boards to. Some of the target boards can be bought independent of the complete kit ( eZ430-T2012 or eZ430-RF2500T ) which is a nice option if you want to expand you project.

I bought the eZ430F2013 and eZ430-RF2500. Both included a CD with the IAR Kickstart Compiler and Ti’s CCS compile based on Eclipse. Both compilers have a code size limit but you will not exceed them with the MSP430F2013 and is sufficient for the MSP430F2274 used on the ez430-RF2500. The programmer/debugger interface support programming the FLASH (so no bootloader required), breakpoints, single stepping and reading the registers/memory of the processor which is a real blessing when you try new features or have a bug in your code.

I did use the IAR compiler to test the programmer and target boards but ultimately I wanted to use the open source compiler mspgcc.

First of I love the TI shop. I bought both kits with the standard shipping but received both the next day. I first bought the ez430F2013. This kit comes in a usb stick housing which contains the programmer and the target board. Since at some point you want to go beyond blinking the one LED you will need to prey the housing open which can be difficult but a small screwdriver will work fine. The RF2500 stick is a little bit bigger and has a cap for the target board. I wished TI would have used a normal 0.1 spaced header for connecting the target boards since the 0.05 spaced connector are expensive and hard to find but overall I like the programmers and target boards.

Ok, this was a little update on the microprocessor platform. But I still wanted to use an open source tool chain for compilation and debugging. Fortunately in the last year a lot happened. First there is a port of mspgcc to gcc4 (most current Linux distros use gcc 4.x for a while so installing gcc3.x just for msp would be a pain) and a new mspdebug tool was written replacing the closed source msp-gdbproxy. I will describe the install of the two tools for kubuntu 10.04 in the next post.

Starting

April 30th, 2009

So I started this blog because I got interested in home automation. After many Google searches I found the current commercial product either overpriced or functional very limited. I had some simple sensors / actuators in mind which could be controlled via a PC application or web page with a smart remote control added later. Obviously those searches lead into multiple directions and soon I realized that it should be possible to build a simple system from scratch.

Since I mostly use Linux at work and home the challenge would be to find/build a complete development system for one of the highly integrated system on a chip on Linux. This includes a CAD program for the electrical circuit including PCB design. A cross compiler and debug environment as well as a programmer.

As a secondary goal I would like to do this completely with free/open content way. There are multiple reasons for this. Obviously this keeps the costs down (as long as I don’t count my time as cost) and second I believe in sharing ideas as a way to create something bigger.

Anyway to cut this short, as a first step I needed to have a place to sort my thoughts and collect information so the easiest way was to just set up a blog on my web hosting account. So here we go.

PS: Don’t expect any working hardware/software any time soon. This whole project is planned as a hobby project and to refresh my hardware skills. Also I can not guarantee the correctness of any information on this site use on your own risk.