Monday, July 23, 2012

Hacking the OV7670 camera module (SCCB cheat sheet inside)

An in-depth look of the OV7670 camera module

The OV7670 is a low cost image sensor + DSP that can operate at a maximum of 30 fps and 640 x 480 ("VGA") resolutions, equivalent to 0.3 Megapixels. The captured image can be pre-processed by the DSP before sending it out. This preprocessing can be configured via the Serial Camera Control Bus (SCCB).  You can see the full datasheet here.

There are many camera modules, that come with standard 0.1" spaced headers, in eBay with prices under $10. I'll be using the one shown below, it comes WITHOUT a FIFO buffer.



HARDWARE


The camera module comes with a 9x2 header, the pin diagram is shown below:

VDD GND
SDIOC SDIOD
VSYNC HREF
PCLK XCLK
D7 D6
D5 D4
D3 D2
D1 D0
RESET PWDN

Now, I'll cover the meaning of these pins.

Pin Type Description
VDD** Supply Power supply
GND Supply Ground level
SDIOC Input SCCB clock
SDIOD Input/Output SCCB data
VSYNC Output Vertical synchronization
HREF Output Horizontal synchronization
PCLK Output Pixel clock
XCLK Input System clock
D0-D7 Output Video parallel output
RESET Input Reset (Active low)
PWDN Input Power down (Active high)

**A note about supply voltage and I/O voltage.


As stated in the datasheet:

  • VDDA can range from 2.45V to 3.00V.
  • VDDC can range from 1.62V to 1.98V.
  • VDDIO can range from 1.7V to 3.00V.

You can (hopefully) see here (sorry, it's buried among other files) the schematic of the model I'm using in this post. As you can see U1 and U2 are LDO regulators, one is a 2.8V regulator for VDDA and VDDIO and the other is a 1.8V regulator for VDDC. The actual regulator that gets soldered on the module seems to vary between modules.

In conclusion, for the same model I'm using:

  • You can safely supply 3.3V (3.0V - 3.6V) to the OV7670 VDD. (I used this configuration)
  • You can safely use a maximum of 3.0V for the I/O pins. However the module I/O pins will work at 2.8V.
  • A 5V supply for the OV7670 VDD might work (try at your own risk), it depends on the maximum input voltage of the LDO regulators your module has.
  • You can use 3.3V on the I/O pins, the internal I/O protection diodes will clamp the I/O voltage to 2.8V. However, this may degrade the OV7670 faster and/or cause more power loss. (I used this configuration)


STRUCTURE OF AN IMAGE


Before going into the signaling, it's necessary to understand how video and images are representend in digital format.

A video is a succession of frames, a frame is a still image taken at an instant of time. A frame is compromised of lines, and a line is compromised of pixels. A pixel is the smallest part of a digital image, and it looks like a colored dot.

P0 P1 P2 P3 P4
L0
L1
L2
L3
L4
A 5x5 image

For example, the image above has 5 lines, and each line has 5 pixels. This means the image has a resolution of 5x5 pixels. This image is monochrome, there are also color image. This color can be encoded in various formats, in the next section we'll cover the most relevant formats for the OV7670.

PIXEL FORMATS


Monochrome


In monochromes images, each pixel is stored as 8 bits, representing gray scale levels from 0 to 255. Where 0 is black, 255 is white and the intermediate values are grays.

RGB


Is a fact that any color can be decomposed in red, green and blue light at different intensities. This approach is known as the RGB color model. Using this model, each pixel must be stored as three intensities of these red, green and blue lights.

RGB color model. Image from wikipedia.


The most common format is RGB888, in this format each pixel is stored in 24 bits, the red, green and blue channels are stored in 8 bits each. This means that the intensity of each light can go from 0 to 255, where 0 is the absence of light, and 255 is the maximum intensity.

The formats used by the OV7670 are the RGB565, RGB555 and RGB444. The difference with the RGB888 format, is the number of bits assigned to each channel. For example, in the RGB565 format, the red channel is stored as 5 bits, the green channel as 6 bits and the blue channel as 5 bits. These formats take less memory when stored but in exchange sacrifice the number of colors available.

YCbCr


YCbCr is a format in which a RGB color can be encoded. The Y or luminance component is the amount of white light of a color, and the Cb and Cr are the chroma components, which respectly encode the blue and red levels relative to the luminance component.

Decomposition of an image into its Y, Cb and Cr components. Image from wikipedia.

As you can see the Y channel encodes the gray scale levels of the image. Therefore, the easiest way to get a monochrome image from the OV7670 is to extract the Y channel of the YCbCr format.

As the RGB format, the YCbCr also stores each channel as 8 bits (from 0 to 255) and we can convert from YCbCr to RGB using the following expression.


The OV7670 uses the YCbCr422 format, this format is stored as follows:


Byte 0 Byte 1 Byte 2 Byte 3
Word 0
Cb0
Y0
Cr0
Y1
Word 1
Cb2
Y2
Cr2
Y3
Word 2
Cb4
Y4
Cr4
Y5
Data stored as words (4 bytes)

Or equivalently, the data arrives in the following order:

N
Byte
1st
Cb0
2nd
Y0
3rd
Cr0
4th
Y1
5th
Cb2
6th
Y2
7th
Cr2
8th
Y3
...
...

And the actual pixels are the following:

Pixel 0 Y0 Cb0 Cr0
Pixel 1 Y1 Cb0 Cr0
Pixel 2 Y2 Cb2 Cr2
Pixel 3 Y3 Cb2 Cr2
Pixel 4 Y4 Cb4 Cr4
Pixel 5 Y5 Cb4 Cr4

Notice each pixel is 3 byte long (e.g. Y0, Cb0 and Cr0), as in the RGB format. But, in the YCbCr422 format, the Cb and Cr channels are shared between two consecutive pixels (e.g. pixels 0 and 1 share Cb0 and Cr0). Therefore two pixels are "compressed" into 4 bytes or 32 bits, this means that in average each pixel is stored as 2 bytes or 16 bits. From the example above, 3 words (12 bytes) store 6 pixels.

The extra advantage of YCbCr is that the Y channel is the grayscale image, whereas in RGB you'll need to average the 3 channels to get the grayscale image.

SIGNALING


The OV7670 sends the data in a parallel synchronous format. First of all, to get any data out of the OV7670, is necessary to supply a clock signal on the XCLK pin. According to the datasheet, this clock must have a frequency between 10 and 48 MHz. However, I have successfully used a 8 MHz clock with some configuration via the SCCB.

If you are using a microcontroller that has clock output, you can use that to clock the OV7670, these can generally output their inner system clock prescaled by some factor. If your microcontroller doesn't have clock output capability, but you're using an external crystal, then you can connect the OSC_OUT pin to the OV7670.

After a clock signal has been applied to the XCLK pin, the OV7670 will start driving its VSYNC, HREF and D0-D7 pins. Let's take a look at these signals.

Horizontal Synchronization

First thing to notice, the D0-D7 must be sampled at the rising edge of the PCLK signal. Number two, D0-D7 must be sampled only when HREF is high. Also, the rising edge of HREF signals the start of a line, and the falling edge of HREF signals the end of the line.

All these bytes sampled when HREF was high, correspond to the pixels in one line. Note that one byte is not a pixel, it depends on the format chosen. By default, the format is YCbCr422, this means that in average two bytes correspond to a pixel.

VGA timing

The image above shows the signals for a "VGA" (640 x 480) frame. During HSYNC high state, we must capture 640 pixels, equivalent to a line. The 480 lines, equivalent to a frame, are captured during the low state of VSYNC. This means that the falling edge of VSYNC signals the start of a frame, and its rising edge signals the end of a frame.

That covers all the process of obtaining one frame, the remaining question is how fast are frames sent. By default, the PCLK will have the same frequency of XCLK, however prescalers and PPLs can be configured using the SCCB, to produce a PCLK of different frequency.

A PCLK of 24 MHz will produce 30 fps, a PCLK of 12 MHz will produce 15 fps and so on. All this is independent of the format of the image (VGA, CIF, QCIF, etc).

SCCB (Serial Camera Control Bus)


What makes the OV7670 so versatile is its inner DSP, that can pre-process the image before its sent. This DSP can be accessed via a SCCB interface. This SCCB protocol is very similar to the I2C protocol. You can see the SCCB specification here.

I couldn't get my STM32 microcontroller's I2C module to work with the OV7670's SCCB interface, so I implemented a bit bang version of the SCCB specification. This implementation is my peripheral library libstm32pp.

After making sure the SCCB is working, we can tweak the OV7670.

Changing the FPS


To change the frames per second (fps), we need to change the frequency of PCLK. And for that we need to modify the following registers via the SCCB.

Register Address Default Description
CLKRC 0x11 0x80
Bit[6]:

0: Apply prescaler on input clock
1: Use external clock directly
Bit[0-5]:


Clock prescaler
F(internal clock) = F(input clock) / (Bit[0-5] + 1)
Range [0 0000] to [1 1111]
DBLV 0x6B 0x0A
Bit[7-6]:




PLL control
00: Bypass PLL
01: Input clock x4
10: Input clock x6
11: Input clock x8
Bit[4]:


Regulator control
0: Enable internal regulator
1: Bypass internal regulator

Now that you know the involved registers, the process is straightforward. For example, say we have a 8 MHz input clock and we want a 24 MHz PCLK. The only possible configuration is prescaler by 2, and PLL x6.
  • CLKRC Bit[6] must be 0, to enable prescaler.
  • CLKRC Bit[0-5] must be 1, to enable prescaler by 2.
  • DBLV Bit[7-6] must be 10, to enable PLL x6
Pseudocode:

Changing the frame format/resolution


The OV7670 can use various frame formats:
  • VGA (640 x 480)
  • QVGA (320 x 240)
  • CIF (352 x 240)
  • QCIF (176 x 144)
  • Manual scaling
By default, the OV7670 uses the VGA format, if you want to do image processing on a microcontroller with the OV7670 output, this may be way too much data, and you might want the QCIF format instead. To change the format we need to modify the following registers.

Register Address Default Description
COM3 0x0C 0x00
Bit[6]: 0: Nothing
1: Swap the data MSB and LSB.
Bit[5]:


On powedown
0: Tri-state the output clock
1: Do not tri-state the output clock
Bit[4]:

On powerdown
0: Tri-state the output data
1: Do not tri-state the output data
Bit[3]: 0: Disable scaling
1: Enable scaling
Bit[2]: 0: Disable downsampling, cropping, windowing
1: Enable downsampling, cropping, windowing
COM7 0x12 0x00
Bit[7]:

0: Nothing
1: Reset all the registers to default values
Bit[5]:

0: Nothing
1: Use CIF format
Bit[4]:

0: Nothing
1: Use QVGA format
Bit[3]:

0: Nothing
1: Use QCIF format
Bit[1]:

0: Disable color bar
1: Enable color bar
Bit[2, 0]:



00: YUV
01: RGB
10: Bayer raw
11: Processed bayer raw

Example, say we want to use the QCIF format, we'll need to enable the scaling, and select the QCIF format.
  • COM3 Bit[3] must be 1, to enable scaling
  • COM7 Bit[3] must be 1, to use the QCIF format
Pseudocode:

I'll add more possible configurations as I explore other features.

MY RESULTS


I have tested my OV7670 module, with a STM32F4 microcontroller. This microcontroller comes with a Digital CaMera Interface (DCMI) and a Direct Memory Access (DMA) controller, these two can capture the frames without the intervention of the processor.

I used an XCLK of 8 MHz, but configured the OV7670 to output a PCLK of 24 MHz, this means I was capturing 30 fps. I used the QCIF format, however I was receiving 174 x 144 pixels instead of 176 x 144. Color format was the default YCbCr422. One of every six frames was sent to a PC using a UART communication at 3 Mbps.

On the PC side, I received the frames using a modded version of qSerialTerm, only the Y channel (gray scale version) of the incoming frames was used. The result is shown in the following image.

A ninja star servo horn captured by the OV7670 camera module.

Now you can use qSerialTerm to visualize images streamed through the Serial Port. Check this post for more info.

TROUBLESHOOTING


SCCB:
  • Make sure the SCCB is working properly, the OV7670 will answer with an ACK, after it has been address properly.
  • The 7 bit SCCB/I2C address is 0x21, this translates to 0x42 for write address and 0x43 for read address.
  • For debugging purposes, try reading some registers and check that they contain their default values. e.g. reading the 0x01 register should return 0x80.
  • Always read a register first, modify the desired bits and then write it back to the OV7670.

Image sensor
  • Check wiring, pin configuration and clock configuration.
  • Start only grabbing a snapshot (only one frame), this is from VSYNC falling edge to VSYNC rising edge. Repeat this procedure multiple times, and make sure the number of bytes per snapshot, is constant.
  • Cover the camera lens, and verify that the snapshot have the following information (in bytes): 128 0 128 0 128 0 128 0 ... i.e. every even byte should be 128 and every odd byte should be 0. This correspond to a pitch black image.
  • If the two previous experiments fail, your uC might be too slow to grab the OV7670 stream, either increase its clock speed or get a faster uC. If you are using a DMA controller, then give it high priority, clock it as fast as possible and/or dedicate it to this task.
  • If you are visualizing the grabbed snapshot in a PC, for starters only use the luminance (Y) channel, i.e. only use the even bytes of the snapshot. On the PC, assign R = G = B = Y for each pixel.
  • At this point, all the electrical/software part should be working. The only remaining issue is the camera focus (distance from the camera lens to the image sensor), you will have to vary the camera focus by trial and error until you get a clear image.
 Varying the camera focus

UPDATE: Check this post about 3 demos that involve the STM32F4, the OV7670 and qSerialTerm. Full code available.

qSerialTerm displaying a frame sent by the STM32F4 and was captured by the OV7670

Saturday, July 7, 2012

Windows: Communicating with a HC-06 bluetooth module

On this post, I'll cover the PC-side configuration needed to communicate with a HC-06 bluetooth module. For more information about the HC-06 module per se (pinout, recommended electrical connection, AT commands and more) check this post.

The process is straightforward in Windows.

Discovery


Double click the Bluetooth icon in your taskbar. Or alternatively, go to Control Panel > Hardware and Sound > Devices and Printers > Add a device.

On this new window, click on the "Add a device" button in the menu.

Discovery of bluetooth devices.

Windows will start searching for nearby bluetooth devices (your HC-06 module should be powered by now).

Pairing


From the list of discovered devices, select your HC-06 module. You should be able to see it's name (linvor is the default name) and it should be listed under the Other category.

On the new window, select the "Pair without using a code" option.

Pairing with the HC-06 module

Checking


You should see the "Installing device driver software" bubble by now. When the installation is done, we'll be able to check the properties of the HC-06 module. Right click on the device and select properties. The important information is under the "Services" tab of the properties window.

Checking the HC-06 module properties.

Communication


After pairing with the HC-06 module, it will be registered as a "COM" port, and you'll be able to communicate with it, using any serial port emulator (e.g. qSerialTerm)

On the first connection to the module, you'll be asked for the pin (the default pin is 1234).

Inserting the pin on the first connection.

Enjoy


That's all, go ahead and play with your bluetooth module.

Testing the bluetooth module.


Windows: Installing Qt Creator

Qt Creator is a great cross-platform IDE for open source development of Qt-based applications. The cross-platform Qt framework allows you to create amazing GUI applications for Windows, Linux, Mac, Symbian, etc.

In this post, I'll cover the installations steps of Qt Creator and the Qt libraries.

Get the MinGW compiler collection


First of all, we need a C compiler. The Qt libraries for Windows have been compiled using the MinGW 4.4 compiler collection. So we need to install the very same version, which is available here(ftp.qt.nokia).

After downloading the zip file, extract it under the "C:\" path (or any other place you want).

Unzipping the MinGW compiler collection in the C:/ drive.

Get the Qt libraries


Grab the latest Qt library (the MinGW version one) from here(qt.nokia.com), and execute the installer. When asked for the path to the MinGW folder, use the same path you used in the last step.

Qt-library installation: Selecting the MinGW installation path.

Get Qt creator


Get the latest version of Qt creator from here(qt.nokia.com). Follow the installer's instructions. When done, launch Qt creator and move to the next step.

Qt Creator: Start-up window.

Select a C compiler in Qt creator


Go to Menu > Tools > Options.

Click on the "Build and Run" section and go under the "Tool Chains" tab, then click on the "Add" button and select the MinGW option. Configure the C compiler as in the following example.

Selecting a toolchain.

Select a Qt library in Qt creator


Go to Menu > Tools > Options.

Click on the "Build and Run" section and go under the "Qt Versions" tab, then click on the "Add" button. Browse to the "qmake" binary as in the following example.

Selecting the Qt library.

Enjoy!


That's all. Now, take a look at the various tutorials available on the WWW, and start coding. Or take a look at my Qt-based serial port emulator (qSerialTerm) as an example.

Hello World example in Qt creator.

Ubuntu Tip 03: Quickly switch through applications using workspaces

If you are like me and use many applications(e.g. an IDE, a web browser, an email client, a virtual machine, a pdf viewer, another IDE, etc) everyday. Then you are going to love these tips to keep everything organized using workspaces.

What is a workspace?

A workspace is an exact copy of what most of us know as a "Desktop" (see image below for an idea).

The workspace switcher, showing 9 workspaces in a 3x3 matrix.

Ubuntu has this cool feature of maintaining various of these virtual desktops, where you can store applications and keep them isolated one from another, reducing the clutter.

The Idea

Keep only one (maybe two?) application inside each workspace, and switch through workspaces instead of Alt-Tabbing through a bunch of applications. There are a few shortcuts you need to learn to switch through workspaces at ninja speed:

Shortcut Description
Ctrl+Alt+Arrow-key Move through the workspace matrix.
Ctrl+Alt+Shift+Arrow-key Drag an application from a workspace to another.
Super+S Open the workspace switcher.

Configuring the number of workspaces


There are various ways to achieve this, I'll explain how to use the CompizConfig Setting Manager.

First, get the application, if you haven't installed it yet.

sudo apt-get install compizconfig-setting-manager

Now launch the application from dash (press the Super key and type compiz).

Select "General Options".

Go to the tab "Desktop Size".

Modify the "Horizontal virtual size" and the "Vertical virtual size" as per your needs.


Keeping all organized


The last workspace trick I'll show you, consist on forcing an application to launch in an specific workspace, this keeps the applications organized in various workspaces.

We'll use the CompizConfig-settings-manager, but this time we'll go to "Window Management" > "Place Windows".

Under the "Fixed Window Placement" tab and in the "Windows with fixed viewport" section we can add a series of rules that'll force the applications to launch in the selected workspace.


You can specify these rules using the application name, its title, etc. From experience, it seems to me that using the application title is both easier and more robust that using the application name.

That's all, if you use any other way to quickly switch through applications and/or use another method for organizing your applications, please share it with all of us via the comments.




Monday, July 2, 2012

Open Source: Template Peripheral Library for the STM32 microcontrollers


Today I'm releasing a library that I developed for the STM32 microcontrollers (currently there is support for the F1, F2 and F4 families). This library is written in C++0x, and addresses some issues I run into when I used other free peripheral C libraries.

The library is named libstm32pp, and it's available in this repository. libstm32pp makes heavy use of template metaprogramming, enumerators, static assertions, templates and namespaces. (Most of these are C++ exclusive features)

All these features allow a memory efficient implementation, compile-time error checking, a clean global namespace, highly organized functions in classes,  and a overall enjoyable programming experience.

I use this library along with bareCortexM, an Eclipse-based bare metal development enviroment, but you can use any other IDE, toolchain, etc. Although, I recommend having a auto-complete/content-assist feature, to get the most of this library.

Now, I'll go into some details of why this C++ library is better than other C peripheral libraries.

Enumerators instead of MACROS for constant values


Rationale: Enumerators can be used as function arguments, MACROS can't. Enumerators don't waste memory at run-time, like MACROS, in contrast with "const" variables. Enumerators are the best friends of template metaprogramming.

Hierarchical organization using namespaces and classes


Rationale: Nobody wants to call the content-assist/auto-complete and get hundreds of suggestions of enumerators and functions, a hierarchical organization using namespaces makes easier to find what your are looking for. Functions are stored inside classes as static members.


Verbose configuration, minimalistic implementation


Rationale: Template metaprogramming, allows the creation of advanced functions, that can get resolved at compile time, reducing the number of instructions at run time (which means faster execution and smaller memory footprint).


Highly configurable clock initialization


Rationale: Selecting between internal clock, external clock or PLL, and setting the bus prescalers is as easy as commenting a macro or filling an enumerator.


Static assertions


Rationale: Kills the bugs at compile time. Eliminates the chance of making impossible configurations. Template arguments are the best friends of static assertions.


Compile-time functions


Rationale: Get more done at compile-time, run less instructions at run-time, save power and memory. My favorite is the compile-time print, you can see values at compile time. (They appear as errors though)


Easy aliasing of peripherals


Rationale: The default name of the peripherals are nice, but sometimes giving them an alias name makes the program clearer.


That sums it all, I hope this library will be useful for all the STM32 hackers out there. I'll love to get feedback on this library. See you around.

Acknowledgements

  • Federico Terraneo, his post inspired the creation of this library.

Updates

  • I figured how to activate optimization without destroying the microcontroller exceptions and interrupts.
  •  The library now contains various demos to help you get started.
  • Added system calls, now the new / delete operators can be used. printf is also supported.

 How to use


Check this post, which offers a detailed tutorial on how to use this library alongside bareCortexM.

Wednesday, June 27, 2012

Bare metal development for ARM Cortex M microcontrolllers

What is bare metal?


Bare metal means running software directly on hardware, instead of running it on top of an Operating System (OS).

And why would you do that? Because sometimes OSes take way too much resources (RAM + Flash), especially when the target device is a low cost microcontroller (uC). Or maybe the application is not very complex and an OS is overkill. Also many OSes are created to run on targets that have a Memory Management Unit (MMU), and your target device might not have one.

Now, using an OS is not a bad thing, quite the opposite it has many advantages. It's highly probable that you are viewing this blog using a device that's running an OS (PC, laptop, smartphone, tablet, etc). And thanks to the OS you can do multitasking in that device, also you can easily add, remove or run software on that device. It's also (almost?) impossible to break or hang the device while developing/running applications, because the OS won't grant other applications access to core/low-level areas of the device.

If you have worked on 8-bit uC from Microchip (a PIC16F877A was my first contact with the world of embedded systems) or AVR (e.g. Arduino) then you have already done bare metal development and have (hopefully) enjoyed the process of controlling at 100% the hardware of a microcontroller.

The ARM world


Today, we have access to more powerful uCs like the ARM-based microcontrollers. Many companies have developed microcontrollers based on the ARM Cortex-M architecture, so there are hundreds of differents uCs, some with more peripherals, others are lower power, but all of them are unified by the ARM architecture, which simplifies the development on these devices.

Specifically, I'm working with the STM32F407VE uC, based on the Cortex-M4 architecture, that has an integrated FPU, which makes operating floating point numbers a snap. Trying to do a multiplication of floats in a 8-bit uC takes way too much Flash and runs way slower. Forget about doing many trigonometric operations or multiplying matrices.


Around 550 bytes needed to mutiply two floats in a 8-bit uC.

Bare metal development on ARM


If you have used IDEs like MPLABX, AVRStudio, etc. Then you have skipped  the (fun) part of setting up the memory distribution, and went straight to code up your application in the main function, after that you clicked the build button to create a hex file or similar, which later you flashed onto your uC to blink a LED, move a motor, etc.

Before jumping into the development, I want you to understand some basics. First, the ARM processor only knows binary (1011...), and in this case that binary is stored in an ELF file. To build this binary from source code (C/C++), which is more human readable, we need a toolchain and a linker script.

The toolchain, contains tools like the compiler and the linker to build the binary; and also provides a debugger, which allow us to run the program in the uC step by step, while observing the inner variables and registers of the uC.

The linker script is basically a map that tells the toolchain how to distribute the memory of the uC, and you can take a glimpse of it's implementation in the following image.

A small part of a linker script.

Obviously, we also need some hardware to flash the ELF file into the uC, and to debug the program in the uC. This hardware needs some connection to the uC, in the case of the ARM microcontrollers this can be via a JTAG or a SWD header. This hardware can be parallel port based or USB based, the latter is far more popular and is sometimes called JTAG dongle.

For example, I started with ARM uCs using a Bus Blaster (JTAG dongle) and a STM32F4Discovery, today I use a custom board for the F4 and a custom JTAG adapter for my projects. (you can see a picture of my hardware, in this post about Kicad)

I have created an Eclipse project template named bareCortexM that wraps all the needed tools, and the source code is available in this repository, go there for hands on experience in bare metal development. The project makes use of the following tools:

+ Eclipse, the IDE that wraps all the tools.
+ GNU Tools for ARM Embedded Processors, the toolchain.
+ openOCD, the glue between the JTAG dongle and the host PC.

On the following image you can see the full setup.

Debugging a STM32F407VE uC using bareCortexM.

Notice that a multiplication of floats takes only 5 instructions, 20 bytes, in constrast with the 500+ bytes of the  multiplication algorithm of the 8-bit uC.

Now that you know how to do bare metal development, you can go ahead and build your own OS or grab a peripheral library and start developing projects. I'll release a template peripheral library for the STM32 microcontrollers later this week. Check my post about libstm32pp, a template peripheral library.

Hands on experience


If you have a STM32 microcontroller + JTAG dongle or a development board like the STM32F4DISCOVERY, then go to this post for a detailed tutorial on how to set up the bareCortexM environment and the libstm32pp peripheral library and start developing on ARM right away.

Saturday, June 23, 2012

3D and footprint libraries for KiCad

KiCad is a Free Open Source Software (FOSS) suite for Electronics Design Automation (EDA). It contains various tools that facilitate the creation of schematics and the design of Printed Circuit Boards (PCB).

In Ubuntu you can get Kicad using the following command:

sudo apt-get install kicad

KiCad can be used without restrictions on PCB size and it's free for non-commercial and commercial purposes. I have used KiCad for a few projects and I'm satisfied with the results.



One of the downsides of KiCad is the small library that comes with it. Luckily, there are quite a few libraries available on the net. Of these libraries, the most helpful one IMO is the Walter Lain's library that contains hundreds of footprints and 3d models.

The aforementioned library comes in two flavors: one for Windows and one for Linux, but I noticed that this wasn't necessary, so I modified the structure of the library to make it work under Windows and Linux at the same time. I have named this modified library "libKiCad" and it's available in the following repository.

For now libKiCad contains the same footprints and 3d models that the original library, but I'll be adding more components as per my needs and as time permits.

Now for the schematics symbols, I think the best place to start is the latest KiCad official library and then create the additional components you need.

I'll try to contact with the maintainers of the KiCad official library and see if I can contribute some schematics symbols I have created.