Friday, July 19, 2013

NHD-C12832 Breakout

This is a breakout board for NewHaven's NHD-C12832 graphic display, a 128 x 32 pixels display with an SPI interface. I like this display mainly because it's cheap (about $11) I think it was the cheapest one I could find with this resolution, and it also looks great. However, it has an unusual package (tight pitch pins and four holes, two for the backlight and two for the screen) so I had to spend some time working on the footprint and PCB, but the end result was good.

I placed all components on the backside of the PCB to keep it as small as possible, the board has a 3.3v 150mA LDO regulator (the display operates from 2.6v to 3.3v) and a level shifter (74VHC541) to convert the logic signals to the operating voltage, so it's compatible with 5.0v logic and can be powered from 3.3v up to the maximum rating of the voltage regulator. The backlight is connected to the regulator via a MOSFET (it draws 45mA maximum) which can be controlled with PWM. The display has an SPI interface and draws about 0.45mA maximum.
The display controller is supported by u8glib, so I wrote small Arduino sketch to test drawing a bitmap,  to generate the bitmap, I used gimp to convert the image to black and white (1-bit) and then exported it to hex (save as .xbm) and then included that as a header in the sketch...



Sources:
The repository includes the Eagle files and the Arduino sketch.

hg clone https://code.google.com/p/nhd-c12832-breakout
Read more ...

Tuesday, July 9, 2013

In Search of a Better Serial Camera Module

So I've been looking everywhere for a cheap serial camera to use in my projects, preferably with some basic image processing, like object or motion detection etc.. The cheapest one I could find that barely meets my needs is sold on adafruit for $35, it has a 640x480 pixels sensor and can do some motion detection but nothing more. Then there is the more expensive modules which cost around $40 that do nothing at all and finally there's the CMUcam, which has some really nice features, but way too big and expensive (costs $100) for my needs...

So I decided to make my own serial camera, keeping in mind the basic set of features that I want:
  • Low cost
  • Small form
  • Basic image processing
  • Open source (duh!)
First, I had to choose an image sensor to use, I was inclined to use the TCM8230MD, which I'm familiar with, however, the sensor alone costs $10 and I can't seem to find it any where else other than sparkfun. So, I've decided to try the Omnivision sensors, the cheapest one I could find is the OV9650 (1280x1024 pixels) sold on ebay for $2... The nice thing about this sensors is that it connects to the board with an FPC cable (that flexible yellow cable), which means it's possible to replace it later with another one (assuming it has the same pinout) and it also has a higher resolution than the TCM8230MD. The downside with this particular sensor is that it doesn't have JPEG compression, but I could live with RGB/RAW output, after all I plan to use it mainly for image processing, or I could try to implement the JPEG compression on the micro.

Moving on to the microcontroller, a powerful micro is needed to interface with this sensor, preferably with a DCMI hardware interface, I implemented a DCMI before in software with an LPC1768/TCM8230MD and it could barely keep up, so I decided to go with something faster. 

Fortunately, I had a couple of STM32F4 micros laying around, which seemed perfect for the job since it  runs at 168MHz, has a hardware DCMI (should make it a lot easier to interface the camera) and as an added bonus, it has a floating point unit and vector processing (SIMD), making it perfect for image processing... Unfortunately, the DCMI only comes with the LQFP-100 package, so I couldn't use a smaller one. 

I started working on the PCB, first, I made a footprint for the sensor and its connector, which seems to fit nicely:
And then I moved to the layout, however, shortly after that, I realized that it's impossible to fit the sensor and micro (let alone the debugging header and interface) on a 2 layer PCB, which is what I had in mind initially to reduce the costs. So a 4 layer PCB seemed inevitable If I wanted to make it as small as possible, there's also some inherit benefits to the extra layers such as better power planes and decoupling, easier routing etc... Anyway, the first version of the PCB (25x37mm) costs around $5


The board has a triple output LDO 3.3v/2.5v/1.5v (the one I had at hand came in a QFN package) and a micro USB connector, which can be used to power the board or update the firmware with DFU. The  SWD pins are broken out for debugging (I'm currently working on a JTAG debugger too) I also throw in an RGB led (not sure if it's too close to the sensor to be visible or not)

The STM32F4 micro costs $11.79 per one, and $7.31 per 500, this adds up to around $20 for one piece and could go as low as $15 for 500 pieces,  it's much higher than I expected, but It should make up for it with some cool image processing, and still almost $15 cheaper than the adafruit camera :)

I still haven't received the PCBs yet, will post an update when I do and when I get it working I will release all the sources. I'm also giving away one for free, leave a comment if you're interested :)
Read more ...

Sunday, May 5, 2013

Running OLinuXino-MAXI on Battery


Finally I've had some time to play with my new Olimex iMX233-OLinuXino-MAXI board, the board is similar to the Raspberry pi, almost the same size and cost, however, this one has an ARM iMX233 running at 454Mhz, less RAM and no GPU.

I played with the board for a while then I decided to test it using batteries, I found out that the USB/Ethernet physical is disabled when running on batteries ! After some digging around in the datasheet, there seems to be a way around this, by swapping two jumpers (3.3V_E and 3.3VIO_E) located near the reset button that control which DC-DC converter is used, the two possible configurations for those jumpers are:
  1.  External DC-DC: 3.3V_E closed (soldered), 3.3VIO_E open (unsoldered/cut)
  2.  On-chip DC-DC: 3.3V_E open (unsoldered/cut), 3.3VIO_E closed (soldered)

Note that the datasheet mentions that the maximum current that can safely be drawn from the on-chip convertor is 200ma and you need to make sure that you don't draw more than that, I'm not sure how exactly, but you should probably use one USB device at a time and either the USB or LAN.

It also mentions that the internal DC-DC makes the chip heat a little bit, so you may want to place a small heat sink on the processor.
Read more ...

Monday, September 24, 2012

Routing Differential Signals

Differential Signalling uses a pair of complementary signals to cary data, that is each wire is carrying the opposite signal, those signals are subtracted at the receiving end and the result is either 0 for noise or 1 for a valid signal. This technique is used with high speed signals to reduce crosstalk and EMI, examples of differential signalling include the twisted pairs inside Ethernet cables, HDMI and USB.
When routing differential signals, each pair should have the exact same length, because the signals are subtracted from each other so they need to arrive at the exact same time, otherwise it's useless, the same requirement applies to other high-speed non-deferential signals such as the signals of this DRAM, note the wiggly tracks on the PCB which are used to make the tracks of equal length:

Eagle 6 has some facilities to help with differential routing, if you use an older version you could still do it manually. For Eagle 6, first give both signals the same name with one ending with _N and the other with _P, so for example USB_N and USB_P, now when you start routing either one of the signals they both will be routed together as you can see: 

If you can't route both signals together, if there's not enough space, then one will be shorter than the other, and that's when you will need the wiggly traces, or formally the Meander function. After you finish routing the signals as usual, run the meander function with the length you wish to add to the shorter trace, then click on the trace and move the mouse it will start adding wiggles to the trace:

You can also use the length.ulp to find out the difference between the tracks before using the meander function:
run length USB*
Read more ...

Saturday, September 1, 2012

STM32F4 Discovery Quick Start Guide

I finally got my hands on an STM32F4 Discovery board, those are super cheap STM32F407 ARM Cortex-M4 boards from ST. The Cortex-M4 is perfect for DSP applications as it has SIMD and an FPU and it also runs at 168Mhz. As for the board, it seems okay given its price, I really hate the headers though and it only has a few components namely, an audio DAC, a chip microphone, an accelerometer and a few LEDs.


There's also an STLINK debugger on board, which means you don't need anything else to program and debug the chip. This is a quick tutorial on how to setup a toolchain and the necessary software.

Setting up a toolchain
First thing you need to do is build or install a toolchain, I couldn't get myself to use any of the toolchains/IDEs that work with the board, as they are all propriety and they all have some sort of limitations on the free editions.

There's always the CodeSourcry toolchain, while it works fine, however, it was not built with hard-float enabled only soft and softfp, which means you have a choice between slow FP and really slow FP emulation. I also tried the summon-arm-toolchain, but it seems to have the same problem no hard-float...

I then accidentally stumbled upon a gcc toolchain which seems to be maintained by ARM and it supports soft, softfp and hard-float, I think I will be using this toolchain for every ARM Cortex I have from now on, anyway, now that you have a working toolchain you can start compiling programs but you still need drivers.

Building the drivers library:
ST provides a package that includes drivers for all the peripherals, a DSP library, API documentation and lots of examples, if you look at the examples you will see that you have to copy all the *.c files you need to your project directory along with the linker script, system initialization and startup code, personally, I like to build a monolithic library and just link with that, so you can skip this step if you want:

First download and extract the STM32F4 DSP and standard peripherals Library then copy the startup and initialization code to the src directory:
$ cp Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates/system_stm32f4xx.c Libraries/STM32F4xx_StdPeriph_Driver/src/ 
$ cp Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates/TrueSTUDIO/startup_stm32f4xx.s Libraries/STM32F4xx_StdPeriph_Driver/src/
Before you build the library, note that most of the drivers use a macro called assert_param, this macro is defined in stm32fxx_conf.h when you build a project you can enable/disable assertions, but since we're compiling this into a library the macro has to be seen at compile time, otherwise the compiler will just assume it's an external symbol and you'll get undefined references later, so you need to add this macro to the stm32f4xx header
#Libraries/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h
#ifdef  USE_FULL_ASSERT
  #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
  void assert_failed(uint8_t* file, uint32_t line);
#else
  #define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
if you #define USE_FULL_ASSERT it will enable assertions or you can compile two libraries one for normal use and the other for debugging.

Finally, copy this Makefile into the src directory and compile the library, I'm assuming here that you have the new toolchain in the path:
#Libraries/STM32F4xx_StdPeriph_Driver/src/Makefile
LIB     =  libcm4.a 
SRCS    = $(wildcard *.c) 
LIB_OBJS= $(SRCS:.c=.o)
AFLAGS  = -mcpu=cortex-m4 -mthumb -mthumb-interwork -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16 
CFLAGS  = -mcpu=cortex-m4 -mthumb -mthumb-interwork -mlittle-endian -mfloat-abi=hard -mfpu=fpv4-sp-d16 -O2 \
-I../inc -I../../CMSIS/Include/ -I../../CMSIS/Device/ST/STM32F4xx/Include/

CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
AR = arm-none-eabi-ar

all:: $(LIB)

$(LIB): $(LIB_OBJS)
    $(AR) -r $(LIB) $(LIB_OBJS)
    echo $(LIB_OBJ)

clean:
    $(RM) *.o *.a

.c.o :
    $(CC) $(CFLAGS) -c $<

.s.o :
    $(AS) $(AFLAGS) $< -o $@
When it's done, copy all the headers (including the CMSIS headers) and the library to somewhere like /opt or /usr/local. There's just one last piece of the puzzle missing, the linker script, you can find one in the many templates included with the library or use the one here, it also includes a Makefile template.

Blinky... Well not exactly!
To keep this simple, this example just lights up one of the LEDs on the board

#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
GPIO_InitTypeDef  GPIO_InitStructure;
int main(void)
{
    /* GPIOG Periph clock enable */
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    /* Configure PD12 in output mode */
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /* Set PD12 high */
    GPIO_SetBits(GPIOD, GPIO_Pin_12);

    /* Do nothing */
    while (1) {
    }
}
Programming and debugging
There's no "official" stlink utility for Linux, so I used this one instead:
$ git clone https://github.com/texane/stlink.git
$ cd stlink
$ ./autogen.sh
$ ./configure
$ make
This will build two binaries, the st-util a gdb server, and st-flash which is supposed to let you write the binary to flash but it doesn't really work! anyway, the project includes a udev rules, you should use that instead of sudo each time:
$ cp 49-stlinkv2.rules /etc/udev/rules.d/
$ udevadm control --reload-rules

Now just run st-util and in another terminal run gdb:
$ arm-none-eabi-gdb blinky.elf
$ tar ext :4242
$ load
$ continue

Notes
Take care not to remap the USB pins used by the STLINK debugger, if you do so the debugger won't be able to talk to the chip and you could actually brick the board :) if you do find yourself in this situation, pull the BOOT0 pin high, there's a VDD pin right next to it so just place a jumper on those pins, when you do that, the board will run the bootloader instead and you can erase the entire flash.

The library is configured for a 25MHz oscillator and the Discovery board has an 8MHz oscillator, you will need to change two values to fix that, the HSE_VALUE in stm32f4xx.h set that to (8000000) and the PLL_M in system_stm32f4xx.c to (8).
Read more ...