Tuesday, December 24, 2013

using madparts for making electronics footprints: an eleborate example

In this blog post I'm discussing a more complex footprint I've made and how I made it with madparts based on the vendor's specification. More specifically I'm making a footprint for the Bluegiga BLE113 Bluetooth Low Energy module.

Lets start by collecting all the needed data.

The physical dimensions of the module are found in the spec page 16:

This will be used to define the physical boundaries of the package.

Next is the landing pattern. It can be found on page 17 of the specification:

 This is used to define the pads for the module.

The order of the pins can be found on page 7:

Finally the specification also gives a clearance for the antenna on page 20:

This means we'll have to add a restrict area to the part for this clearance area.

let's write code!

Define the size of the module as found in the physical dimensions:

  module_dx = 9.15
  module_dy = 15.74

Define the size of the pad as found in the recommended landing pattern:

  pad_dx = 2
  pad_dy = 0.5

The horizontal pads need an adjustment from the center of the module. The landing pattern defines 5.35mm between the two columns of pads, and we orient from the center of the pad so in total this gives and adjustment value of:

  pad_hadj = (5.35+pad_dx)/2

The landing pattern tells us the distance between pads:

  pad_between = 0.8

The pinout description gives the number of pins:

  n_left = 18
  n_down = 6
  n_right = 12

The physical dimension tells us the distance from the bottom of the module to the center of the bottom left and right pad. This works because the pad centers are the same for the physical diagram and the landing pattern.

  lr_pad_from_bottom = 1.45

Now this gets a bit tricky. We need to calculate the vertical adjustment needed for the column of pads, but this is relative to the center of the module. The trick is to take pad 18, move it to the 0 point, then to the bottom of the module, and then use the lr_pad_to_bottom adjust value specified in the spec.

  pad_vadj = ((n_left-1)/2)*pad_between  # move pad 18 to 0
  pad_vadj -= module_dy/2                # move pad 18 down to bottom
  pad_vadj += lr_pad_from_bottom         # and back up by 1.45

Let's draw a rectangle to document the module shape, and draw a silk around it to make it easily visible on the board later.

  r1 = make_rect module_dx, module_dy, 0.1, 'docu'
  r2 = make_rect module_dx+0.2, module_dy+0.2, 0.1, 'silk'

Let's define the pad shape with the earlier defined constant. we want 100% round corners.

  pad = new Smd 
  pad.dx = pad_dx
  pad.dy = pad_dy
  pad.ro = 100

Now lets make the left row of pads. First make them, then adjust the x and y by the values we calculated earlier.

  l1 = single pad, n_left, pad_between
  l1 = adjust_x l1, -pad_hadj
  l1 = adjust_y l1 , pad_vadj

Next the bottom row. clone and rotate the pad, and create a horizontal row of pads. Adjust the y as specified in the landing pattern figure. Finally renumber starting with the number after the last number we used for the first column of pads.

  l2 = rot_single (rotate90pad clone pad), n_down, pad_between
  l2 = adjust_y l2, -module_dy/2+lr_pad_from_bottom-0.55
  l2 = generate_names l2, n_left

Finally the right row. Again a single row of pads. Reverse the order. Renumber starting after the last number used for the down pads.

  l3 = single pad, n_right, pad_between
  l3 = reverse l3
  l3 = generate_names l3, n_left+n_down
  l3 = adjust_x l3, pad_hadj
  l3 = adjust_y l3, pad_vadj+(n_right-n_left)/2*pad_between

Let's add a name somewhere inside the module, a bit below the top:

  name = new Name (module_dy/2-1)

Let's add a rectangular for the restrict area. This is a but messy but it boils down to placing it right above pas 36 and 3.5mm on the right of the left side of the module.

  k = new Rect
  k.type = 'restrict'
  k.dx = module_dx
  k.dy = module_dy/2-l3[n_right-1].y
  k.x = -module_dx/2+3.5+k.dx/2
  k.y = l3[n_right-1].y+pad_dy/2+k.dy/2

Finally combine it all in a list and we're done.

  combine [name, r1,r2, l1, l2,l3, k]

The latest version of the full file can be found at https://github.com/andete/madparts-parts/blob/master/3ca17b8bc41648d2b968c33ae8f35092.coffee

This is a screenshot:


And this is the part in eagle cad:


And in kicad:


Saturday, December 21, 2013

a look inside the shielding can of the BLE112 Bluetooth Low Energy module

Given that I accidentally damaged this Bluetooth Low Energy anyway, I thought it interesting to take a look what is inside the shielding can with a macro lens.

Here you see the bluegiga BLE112 module on a board with the shield still in place:



And here I removed the metal shielding can:


As you can see no real surprises here:

The central unit is a Texas Instruments CC2540 SoC Bluetooth Low Energy module.
On the lower right of it sits a 32 Mhz crystal for the main clock.
Above it is what I assume the 32.768 kHz low speed clock crystal.

The antenna was already visible with the can in place, but what's interesting is the second companion chip inside the can. I assume it is some kind of filter for the antenna.

Besides that just a few passives and that is it!

Sunday, December 15, 2013

madparts release 1.2.1

This is mostly a bug-fix release, mainly fixing bugs to do with rotation of certain parts, especially in combination with KiCAD export.

Builds are available for Debian Jessie and Wheezy, Ubuntu Saucy, MacOSX and Win32.

Go download one of them at http://madparts.org/footprint.html#download !






Saturday, December 14, 2013

stm32f105 cortex-m3 getting to blink

This is not going to be a detailed post. All the code can be found in github at https://github.com/andete/blog-stuff/tree/master/STM32F105 .

In my quest for more experience with different microcontrollers I made a little breakout for the ST STM32F105 ARM Cortex-M3 micro-controller.

The breakout provides a 8Mhz external clock, which is multiplied by 9 by the internal PLL to give a nice 72Mhz clock.


The MCU is programmed with the STLINK V2 programmer via SWD. It should also be possible to program it via DFU but I have not tried that yet.

I cobbled some code together from all over the internet to make a simple blink file.


#include "stm32f10x.h"

// loosely based on
// http://www.overtracks.com/stm32/baby-steps.htm
// http://dics.voicecontrol.ro/dicsEE-IP/chapter/Setting%20GPIO%20manually
// http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/BGBEEJHC.html
// https://forum.sparkfun.com/viewtopic.php?f=11&t=21107
// http://en.radzio.dxp.pl/stm32vldiscovery/

// LED is connected to PC0, so first bit on GPIOC
#define LED_BITMASK          1 << 0 // bit 0

#define USE_SYSTICK

#ifdef USE_SYSTICK
void SysTick_Handler(void) {
  GPIOC->ODR ^= LED_BITMASK; // toggle LED state
}
#else
void TIM3_IRQHandler(void) {
  // why the check for UIF ?
  if (TIM3->SR & TIM_SR_UIF) // if UIF flag is set
  {
    TIM3->SR &= ~TIM_SR_UIF; // clear UIF flag
    GPIOC->ODR ^= LED_BITMASK; // toggle LED state
  }
}
#endif

int main() {

  // enable GPIOC
  RCC->APB2ENR |= RCC_APB2ENR_IOPCEN;
  // configure GPIOC port 0 as output; 4 bits per pin
  // 4+0 -> (0) input mode, (4) floating (reset state)
  // 0+2 -> (2) output mode, (0) generic push-pull
  GPIOC->CRL = 0x44444442;

#ifdef USE_SYSTICK
  // 1 second = 72000000 / 8000000 = 9000000
  SysTick->LOAD = 9000000;
  // start counting from zero
  SysTick->VAL = 0;
  // enable and enable interrupt
  SysTick->CTRL |= (SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk);
#else
  // enable clock for timer3
  RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
  // Set prescaler to 24 000 (PSC + 1) // why?
  TIM3->PSC = 23999;
  // // Auto reload value 1000
  TIM3->ARR = 1000;
  // Enable update interrupt (timer level)
  TIM3->DIER = TIM_DIER_UIE; // Enable update interrupt (timer level)
  TIM3->CR1 = TIM_CR1_CEN;   // Enable timer

  NVIC_EnableIRQ(TIM3_IRQn);
#endif

  // sleep till the end of time
  while (1) { __WFI(); }
  return 0;
}
It does blinking via the SysTick interrupt or alternatively via the TIM3 timer interrupt. It is also possible to do this without interrupts at all, just using the timers, but this is not shown here.