New Project Under Wraps

wrapped package
I’ve been busy working on a new project. I am hesitant to publish any details yet. It has required making several PCBs in an iterative process, and I needed to learn SMD soldering. I will soon post about the lessons I learned. Here are a few photos:

ADXL-377 Eagle file:
adxl377bob

ADXL-377 Breakout Board:
adxl377bob

RXM418LR Breakout Board:
rxm418lr

xminilab SMD soldering:
xminilab

Secret Project:
HITsafe BoB

Posted in Uncategorized | Leave a comment

Great Cadsoft Eagle Starter Project Idea

starter
Here is a great starter project to try when attempting to learn Cadsoft Eagle. Make a simple breakout board for a SMD device.

For example, here I’m making a breakout for the SSOP-28 package with a .65mm pitch. This breakout will also accept SSOP-14, 16, 20 and 24 pin devices. I sent this design to OSPark for fabrication, and total cost for 3 PCBs, delivered was $7.80. To start out, you can easily copy a device from an existing library, or if you want to go all out, make a library part yourself.

Here is the SparkFun equivalent SSOP to DIP Adapter breakout board at $3.95 each. Adafruit sells a 3-pack double-sided breakout that will accept a SOIC-28 package on the bottom side here.

Here is my post about Cadsoft Eagle tutorials.

Posted in Uncategorized | Leave a comment

PCB Design Resources

A few good resources for PCB design and layout:

1. SparkFun According To Pete: PCB Layout video

2. David Jones (of EEVBlog fame) PCB Design Tutorial (pdf)

3. Electronics Design Checklist

Posted in Uncategorized | Leave a comment

My First Eagle PCB: An RN52 Breakout Board

train wreck

A few months ago I started to realize I needed to learn about designing and fabricating PCBs. And with the Cadsoft Eagle software package being the darling of the open source community, I decided I would start with it. I also found that studying the open source design files of my favorite SparkFun products accelerated my learning process. My post about Eagle tutorials is located here.

And now, for my first (very ambitious) project, I decided to design a breakout board for the Roving Networks RN-52 Bluetooth Audio Module. SparkFun started selling this module a few months back. At the time, they didn’t have a breakout board for it, however they have since started selling a very basic breakout board. SparkFun also publishes a great Hookup Guide for the RN-52.

rn52 module

The first problem I needed to overcome, was that there is no Eagle library part for the RN-52. So I made one for it (note: SparkFun now incorporates an RN-52 Module in their Eagle parts library).

rn52 part

There are a few things you need to be careful with when making a new part. One, you must get the pad layout 100% accurate, because your resultant PCB will be nothing but scrap if you get the dimensions wrong. The datasheet is a great resource for proper part dimensions. Eagle will reference all locations from an “x-y center”, which you define. This location can be placed in the center of the part, bottom edge, or even outside the part. This can create some “spatial disorientation” at times! It usually requires doing a little math to convert the datasheet dimensions in order to generate a correct layout. For larger parts, I suggest laying it all out on a scrap of paper first. The UNDO command comes in handy when you enter an incorrect pad dimension!

Additionally, you must link the pads to the correct functions/pins. For example if you mislabel a pad, your traces will link to the wrong pins-another disasterous mistake. Take the time to check and re-check any parts you make.

And unlike the basic BoB from SparkFun, I wanted to add more functionality for truly evaluating the RN-52 Module’s features. Luckily for me, I was able to use the Roving Networks Evaluation Board as the basis for my project, and I finally decided upon the following design:

The schematic:
schematic

The board:
schematic

I utilized OSH Park as the PCB fabricator. OSH Park makes an Eagle Design Rules (DRU) file available for checking your board prior to submission. The Eagle Design Rules Check is a necessity, and I highly encourage you to use a PCB Fab Shop that makes their DRU file available-at least until you become an accomplished PCB maker! Here are my results:

schematic

In the end, this was more time consuming (tedious?) than difficult. I highly urge to try it yourself. My design files are available for the asking.

Posted in Uncategorized | Tagged , , , , | 2 Comments

Arduino Disassembly: Who Put This Stuff Here?

too much stuff

Ever wonder what all of the code inserted at the beginning of your program that appears in a disassembly listing is about? Well it’s a bunch of required housekeeping routines that are linked into your program at compile time that come from several locations. Some of the files are Arduino specific while others are AVR GCC and libc code. Here is a breakdown of the basic “Blink” program running on a generic ATMega328.

First we see the interrupt vector table (IVT), which is a table of interrupt vectors that associates an interrupt handler with an interrupt request. More information can be found here and here.

	.macro	vector name
	.if (. - __vectors < _VECTORS_SIZE)
	.weak	\name
	.set	\name, __bad_interrupt
	XJMP	\name
	.endif
	.endm

__vectors:
	XJMP	__ctors_end
	__vector_1
	vector	__vector_2
	vector	__vector_3
...
	vector	__vector_125
	vector	__vector_126
	vector	__vector_127
	.endfunc

/* Handle unexpected interrupts (enabled and no handler), which
   usually indicate a bug.  Jump to the __vector_default function
   if defined by the user, otherwise jump to the reset address.

   This must be in a different section, otherwise the assembler
   will resolve "rjmp" offsets and there will be no relocs.
*/

__bad_interrupt:
	.weak	__vector_default
	.set	__vector_default, __vectors
	XJMP	__vector_default
	.endfunc

__ctors_end:

The blink disassembly will look something like this:

   0:	0c 94 61 00 	jmp	0xc2	; 0xc2 <__ctors_end>
   4:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
   8:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
...
  3c:	0c 94 7e 00 	jmp	0xfc	; 0xfc <__bad_interrupt>
  40:	0c 94 9d 00 	jmp	0x13a	; 0x13a <__vector_16>
...

Note the first vector, or reset vector is set to point to the code that begins at the label “__ctors_end”. With the exception of vector #16, the remaining vectors all point to the “bad interrupt code”. See this post for more information about bad interrupt handling. Vector #16 is the Timer0 overflow vector and is used by the Arduino millis timer. See here for more information on how millis works.

Next comes any program memory. For example, Arduino’s digitalWrite/Read functions use program memory for pin-mapping. Information on PROGMEM can be found here and here.

00000068 <port_to_mode_PGM>:
  68:	00 00 00 00 24 00 27 00 2a 00                       ....$.'.*.

00000072 <port_to_output_PGM>:
  72:	00 00 00 00 25 00 28 00 2b 00                       ....%.(.+.

0000007c <port_to_input_PGM>:
  7c:	00 00 00 00 23 00 26 00 29 00                       ....#.&.).

00000086 <digital_pin_to_port_PGM>:
  86:	04 04 04 04 04 04 04 04 02 02 02 02 02 02 03 03     ................
  96:	03 03 03 03                                         ....

0000009a <digital_pin_to_bit_mask_PGM>:
  9a:	01 02 04 08 10 20 40 80 01 02 04 08 10 20 01 02     ..... @...... ..
  aa:	04 08 10 20                                         ...

000000ae <digital_pin_to_timer_PGM>:
  ae:	00 00 00 07 00 02 01 00 00 03 04 06 00 00 00 00     ................
  be:	00 00 00 00                                         ....

Next, the r1 register is zeroed (it’s assumed to always be zero throughout the program), and the SREG register is zeroed. Then our stack is initialized. The stack is used primarily to keep track of program execution and data passing to/from functions.

	clr	__zero_reg__
	out	AVR_STATUS_ADDR, __zero_reg__
	ldi	r28,lo8(__stack)
	ldi	r29,hi8(__stack)
	out	AVR_STACK_POINTER_HI_ADDR, r29
	out	AVR_STACK_POINTER_LO_ADDR, r28

Next is data initialization code. First, the code copies global/static initialized variables into SRAM. Then, if any uninitialized variables exist, a copy BSS section is appended to your code. Finally, if there are any C++ constructor/destructors, a bit of additional code is inserted (none here). In the blink disassembly, 11 bytes of memory are copied: timer0_millis (4 bytes), timer0_overflow_count (4 bytes), timer0_fract (1 byte), and led (2 bytes).

__do_copy_data:
	ldi	r17, hi8(__data_end)
	ldi	r26, lo8(__data_start)
	ldi	r27, hi8(__data_start)
	ldi	r30, lo8(__data_load_start)
	ldi	r31, hi8(__data_load_start)
	rjmp	__do_copy_data_start
__do_copy_data_loop:
	lpm	r0, Z+
	st	X+, r0
__do_copy_data_start:
	cpi	r26, lo8(__data_end)
	cpc	r27, r17
	brne	__do_copy_data_loop

/* __do_clear_bss is only necessary if there is anything in .bss section.  */
__do_clear_bss:
	ldi	r17, hi8(__bss_end)
	ldi	r26, lo8(__bss_start)
	ldi	r27, hi8(__bss_start)
	rjmp	do_clear_bss_start
.do_clear_bss_loop:
	st	X+, __zero_reg__
.do_clear_bss_start:
	cpi	r26, lo8(__bss_end)
	cpc	r27, r17
	brne	do_clear_bss_loop

/*
  __do_global_ctors and __do_global_dtors are only necessary if there
  are any constructors/destructors.
*/
__do_global_ctors:
	ldi	r17, hi8(__ctors_start)
	ldi	r28, lo8(__ctors_end)
	ldi	r29, hi8(__ctors_end)
	rjmp	__do_global_ctors_start
__do_global_ctors_loop:
	sbiw	r28, 2
	mov_h	r31, r29
	mov_l	r30, r28
	XCALL	__tablejump__
__do_global_ctors_start:
	cpi	r28, lo8(__ctors_start)
	cpc	r29, r17
	brne	__do_global_ctors_loop

__do_global_dtors:
	ldi	r17, hi8(__dtors_end)
	ldi	r28, lo8(__dtors_start)
	ldi	r29, hi8(__dtors_start)
	rjmp	__do_global_dtors_start
__do_global_dtors_loop:
	mov_h	r31, r29
	mov_l	r30, r28
	XCALL	__tablejump__
	adiw	r28, 2
__do_global_dtors_start:
	cpi	r28, lo8(__dtors_end)
	cpc	r29, r17
	brne	__do_global_dtors_loop
Posted in Uncategorized | Tagged , , , , , , | 1 Comment

Learning Cadsoft EAGLE from online Tutorials

generic pcb
The Cadsoft Eagle schematic/PCB layout program is the favorite among the open source community. Because of that there are lots of component libraries available. While it is a commercial program, the company offers a freeware version which limits the PCB size and a maximum of 2 layers. However, it does have a steep learning curve.

If this steep leaning curve concerns you , as an alternative, I am reading good things about the DipTrace program.

Having just spent a considerable amount of time trying to learn the EAGLE PCB software, I’m very familiar with the available learning resources. I list below what I consider to be the most beneficial training videos and documents on the web.

There are two major program functions that need to be mastered, (1) schematic layout and, (2) board layout. There are many youtube videos that demonstrate these functions, however most are of dubious value. I consider the two best to cover these topics by Jeremy Blum: Schematic Layout Tutorial Video, and PCB Layout Tutorial Video.

Element 14 Cadsoft Webinar Video on board creation is also an excellent video.

The Sparkfun Eagle tutorial series covers the basics well: Schematics, and PCB Layout.

The Dangerous Prototypes series of tutorials are helpful.

A German individual who conducts Eagle training has posted his Power Point Slides which are useful.

And the best information on library part creation can be found here, here and here.

Update (7/6/2013): I just received the new book from Elektor, “Learning to Fly with Eagle“. In my opinion, the book is a good introduction to the Eagle software. It is up to date and covers most of the topics well (lacks library part creation). However, I find the above videos and websites are just as useful, if not better.

Posted in Uncategorized | Leave a comment

Profiling Code: More Than One Way to Skin A Cat

skinned cat
I found an excellent profiling library for the Arduino posted by the seemingly inexhaustible Arduino Forum poster Nick Gammon. You can find Nick’s code here.

Here is the program code from my cycle counting post with Nick’s profiling library inserted (minimal intrusion):

#include <ProfileTimer.h>

void setup() {
  Serial.begin(115200);
}

void loop() {
  asm volatile (
       "sbi %0, %1 \n\t" //LED on
	   :: "I" (_SFR_IO_ADDR(PORTB)), "I" (PORTB5)
  );

  {
    ProfileTimer t ("inline delay");
    asm volatile (
      "    ldi r20, 32  \n\t"
      "1:  ldi r21, 200 \n\t"
      "2:  ldi r22, 250 \n\t"
      "3:  nop          \n\t"
      "    nop          \n\t"
      "    dec r22      \n\t"
      "    brne 3b      \n\t"
      "    dec r21      \n\t"
      "    brne 2b      \n\t"
      "    dec r20      \n\t"
      "    brne 1b      \n\t"
      ::: "r20", "r21", "r22"
    );
  }

  asm volatile (
    "cbi %0, %1 \n\t" //LED off
    "    ldi r20, 32  \n\t"
    "1:  ldi r21, 200 \n\t"
    "2:  ldi r22, 250 \n\t"
    "3:  nop          \n\t"
    "    nop          \n\t"
    "    dec r22      \n\t"
    "    brne 3b      \n\t"
    "    dec r21      \n\t"
    "    brne 2b      \n\t"
    "    dec r20      \n\t"
    "    brne 1b      \n\t"
    :: "I" (_SFR_IO_ADDR(PORTB)), "I" (PORTB5)
    : "r20", "r21", "r22"
  );
}

Here is the output running Nick Gammon’s Profile Timer:

Start     : inline delay
Time taken: inline delay = 504196 uS.
Start     : inline delay
Time taken: inline delay = 504200 uS.
Start     : inline delay
Time taken: inline delay = 504196 uS.
Start     : inline delay
Time taken: inline delay = 504196 uS.
Start     : inline delay
Time taken: inline delay = 504200 uS.
Start     : inline delay
Time taken: inline delay = 504204 uS.
Start     : inline delay
Time taken: inline delay = 504196 uS.
Start     : inline delay
Time taken: inline delay = 504200 uS.
Start     : inline delay
Time taken: inline delay = 504196 uS.
Start     : inline delay
Time taken: inline delay = 504196 uS.
...
Posted in Uncategorized | Tagged , , , , , , | Leave a comment