Thursday, 25 December 2014

Device Tree Blog

Today I would be talking about device tree:

Device Tree is a data structure by which bootloaders pass
hardware layout to Linux in a device-independent manner, simplifying hardware
probing.
Mailing list for device tree is mailing list at:
https://lists.ozlabs.org/listinfo/devicetree-discuss

Introduction:
During development of Linux/ppc64 kernel it was decided to enforce some strict rules regarding the kernel entry point and bootloader <-> kernel interface,in order to avoid degeneration that become the ppc32 kernel entry point and the way a new platform should be added to the kernel.

-device-tree whose format is defined after Open Firmware specification.
-To make easy the kernel does not required the device tree to represent  every device.Only some nodes and properties to be present.
-For example the kernel does not require to create a node for every PCI device.It will create node for PCI Host bridges which provides information for interrupt routing information and memory I/O ranges among others.
-It is recomended to specify nodes for chip devices and other devices and other Bus that does not fit into existing OF specification.
-This creates the flexibility in the way the kernel can then probe those and match drivers to device,without having hard code all sorts of tables.
-Also makes flexible for board vendors to do minor hardware upgrades without significanltly impacting the kernel code or clustering it with special cases.

1)Entry point for arch/arm:
There is single entry point to the kernel,at the start of the kernel image.That entry point has two calling convention.

a)ATAGS interface:
Minimal information is passed from firmware ->kernel with a tagged list of predefined parameters.
r0=0
r1=Machine type number
r2=Physical address of tagged list in system RAM

b)entry of device tree.Firmware loads the physical address of the device tree block(dtb) into r2.R1 is not used but it is considers as good practice to use valid machine number.
 r0=0
r1=valid machine type number. When using device tree a single machine type number will often be assigned to represent a class or family of SOCs.
r2=physical pointer to the device tree in RAM.It can be located on anywhere in system RAM, but it should be aligned on 64-bit boundary.

-Kernel will differentiate between ATAGS and device tree booting by reading the memory pointed to by r2 and looking for either the device tree Block magic value(0xd00dfeed) or the ATAG_CORE value at offset 0x4 from r2(0x54410001)


 The kernel is passed the physical address pointing to an area of memory
   that is roughly described in include/linux/of_fdt.h by the structure
   boot_param_header:

struct boot_param_header {
        u32     magic;                  /* magic word OF_DT_HEADER */
        u32     totalsize;              /* total size of DT block */
        u32     off_dt_struct;          /* offset to structure */
        u32     off_dt_strings;         /* offset to strings */
        u32     off_mem_rsvmap;         /* offset to memory reserve map
                                           */
        u32     version;                /* format version */
        u32     last_comp_version;      /* last compatible version */

        /* version 2 fields below */
        u32     boot_cpuid_phys;        /* Which physical CPU id we're
                                           booting on */
        /* version 3 fields below */
        u32     size_dt_strings;        /* size of the strings block */

        /* version 17 fields below */
        u32     size_dt_struct;         /* size of the DT structure block */
};

/* Definitions used by the flattened device tree */
#define OF_DT_HEADER            0xd00dfeed      /* 4: version,4: total size */
#define OF_DT_BEGIN_NODE        0x1             /* Start node: full name*/
#define OF_DT_END_NODE          0x2             /* End node */
#define OF_DT_PROP                    0x3             /* Property: name off,size, content */
#define OF_DT_END                       0x9

   - magic

     This is a magic value that "marks" the beginning of the
     device-tree block header. It contains the value 0xd00dfeed and is
     defined by the constant OF_DT_HEADER

- totalsize

     This is the total size of the DT block including the header. The
     "DT" block should enclose all data structures defined in this
     chapter (who are pointed to by offsets in this header). That is,
     the device-tree structure, strings, and the memory reserve map.

 -off_dt_struct

     This is an offset from the beginning of the header to the start
     of the "structure" part the device tree.   

 - off_dt_strings

     This is an offset from the beginning of the header to the start
     of the "strings" part of the device-tree

 - off_mem_rsvmap

     This is an offset from the beginning of the header to the start
     of the reserved memory map. This map is a list of pairs of 64-
     bit integers. Each pair is a physical address and a size. The
     list is terminated by an entry of size 0. This map provides the
     kernel with a list of physical memory areas that are "reserved"
     and thus not to be used for memory allocations, especially during
     early initialization. The kernel needs to allocate memory during
     boot for things like un-flattening the device-tree, allocating an
     MMU hash table, etc... Those allocations must be done in such a
     way to avoid overriding critical things like, on Open Firmware
     capable machines, the RTAS instance, or on some pSeries, the TCE
     tables used for the iommu. Typically, the reserve map should
     contain _at least_ this DT block itself (header,total_size). If
     you are passing an initrd to the kernel, you should reserve it as
     well. You do not need to reserve the kernel image itself. The map
     should be 64-bit aligned.

   - version

     This is the version of this structure. Version 1 stops
     here. Version 2 adds an additional field boot_cpuid_phys.
     Version 3 adds the size of the strings block, allowing the kernel
     to reallocate it easily at boot and free up the unused flattened
     structure after expansion. Version 16 introduces a new more
     "compact" format for the tree itself that is however not backward
     compatible. Version 17 adds an additional field, size_dt_struct,
     allowing it to be reallocated or moved more easily (this is
     particularly useful for bootloaders which need to make
     adjustments to a device tree based on probed information). You
     should always generate a structure of the highest version defined
     at the time of your implementation. Currently that is version 17,
     unless you explicitly aim at being backward compatible.

 - last_comp_version

     Last compatible version. This indicates down to what version of
     the DT block you are backward compatible. For example, version 2
     is backward compatible with version 1 (that is, a kernel build
     for version 1 will be able to boot with a version 2 format). You
     should put a 1 in this field if you generate a device tree of
     version 1 to 3, or 16 if you generate a tree of version 16 or 17
     using the new unit name format.

   - boot_cpuid_phys

     This field only exist on version 2 headers. It indicate which
     physical CPU ID is calling the kernel entry point. This is used,
     among others, by kexec. If you are on an SMP system, this value
     should match the content of the "reg" property of the CPU node in
     the device-tree corresponding to the CPU calling the kernel entry
     point (see further chapters for more information on the required
     device-tree contents)

   - size_dt_strings

     This field only exists on version 3 and later headers.  It
     gives the size of the "strings" section of the device tree (which
     starts at the offset given by off_dt_strings).

   - size_dt_struct

     This field only exists on version 17 and later headers.  It gives
     the size of the "structure" section of the device tree (which
     starts at the offset given by off_dt_struct).


             ------------------------------
     base -> |  struct boot_param_header  |
             ------------------------------
             |      (alignment gap) (*)   |
             ------------------------------
             |      memory reserve map    |
             ------------------------------
             |      (alignment gap)       |
             ------------------------------
             |                            |
             |    device-tree structure   |
             |                            |
             ------------------------------
             |      (alignment gap)       |
             ------------------------------
             |                            |
             |     device-tree strings    |
             |                            |
      -----> ------------------------------
      |
      |
      --- (base + totalsize)

  (*) The alignment gaps are not necessarily present; their presence
      and size are dependent on the various alignment requirements of
      the individual data blocks.

2:Device Tree generalites
This device-tree itself is separate in two different blocks:
1)structure block
2)string block
Both are alinged to 4 byte boundary

 What is device-tree?
-Its basically a tree of nodes, each node having two or more named properties.A property can have value or not.
-It is a tree so each node has one parent while otherwise they dont have node.
-Node has two names.
Actual node name is generally contained in the property "name" in the node property list(whose value is zero terminated and it is mandatory in for version 1 to 3)
-from version 16 its optional.(it generates from unit name defined below)
-Another name is "unit name" that is used to differentiate nodes with same name at the same level.
-It is usually made of "nodes name" then @ then "unit address",which defination is specific to bus type the node sits on.
-Unit name does not exist as property per-se but it is included in device tree structure.That is typically used to represent path in device-tree.
-Kernel generic code does not uses unit address so the only real requirment here for unit address is to ensure uniqueness of the node unit name at the given level of the tree.
-The node with no notion of address and no possible sibling of the same name may omit the unit address in the context of the specification or use "@0" defualt unit address.
- The unit name is used to define a node "full path", which is the concatenation of all parent node unit names separated with "/".
Root node
-The root node doesn't have a defined name.It also has no unit address.The root node unit name is thus an empty string. The full path to the root node is "/".


-Every node which actually represents an actual device is also required to have a "compatible" property indicating the specific hardware and an optional list of devices it is fully backwards compatible with.
-every node that can be referenced from a property in another node is required to have either a "phandle" or a "linux,phandle"




-Here is the example of the device tree


/ o device-tree
      |- name = "device-tree"
      |- model = "MyBoardName"
      |- compatible = "MyBoardFamilyName"
      |- #address-cells = <2>
      |- #size-cells = <2>
      |- linux,phandle = <0>
      |
      o cpus
      | | - name = "cpus"
      | | - linux,phandle = <1>
      | | - #address-cells = <1>
      | | - #size-cells = <0>
      | |
      | o PowerPC,970@0
      |   |- name = "PowerPC,970"
      |   |- device_type = "cpu"
      |   |- reg = <0>
      |   |- clock-frequency = <0x5f5e1000>
      |   |- 64-bit
      |   |- linux,phandle = <2>
      |
      o memory@0
      | |- name = "memory"
      | |- device_type = "memory"
      | |- reg = <0x00000000 0x00000000 0x00000000 0x20000000>
      | |- linux,phandle = <3>
      |
      o chosen
        |- name = "chosen"
        |- bootargs = "root=/dev/sda2"
        |- linux,phandle = <4>



o -represents the device tree. Followed by the node unit name
property are followed by the name and then followed by the content.
"content"-represents as ACSII type
<>-represents a 32 bit value in decimal or hexadecimal.

3:Structure Block
The structure of the device tree is linearized tree structure.
"OF_DT_BEGIN_NODE" token starts a new node
"OF_DT_END_NODE" ends that node definition
Child nodes are simply defined before "OF_DT_END_NODE"

Here's the basic structure of a single node:

     * token OF_DT_BEGIN_NODE (that is 0x00000001)
     * for version 1 to 3, this is the node full path as a zero
       terminated string, starting with "/". For version 16 and later,
       this is the node unit name only (or an empty string for the
       root node)
     * [align gap to next 4 bytes boundary]
     * for each property:
        * token OF_DT_PROP (that is 0x00000003)
        * 32-bit value of property value size in bytes (or 0 if no
          value)
        * 32-bit value of offset in string block of property name
        * property value data if any
        * [align gap to next 4 bytes boundary]
     * [child nodes if any]
     * token OF_DT_END_NODE (that is 0x00000002)

So the node content can be summarized as a start token,full path, a list of properties, a list of child nodes, and a end token.Every child node is the full structure itself as defined above.

4:Device tree "string" block
-In order to save space,property names,which are generally redundant are stored seperatly in the "strings" block.
-This block is simply whole bunch of zero terminated strings for all properties name concatenated together.
-The device-tree property definition in the stucture block will contain offset values from beginning of the string block.
--------------------------------------------------------------------------------------------------------------------
Required content of the device tree:
WARNING:All 'linux' properties defined in this document apply to device tree.If your platform uses a real implementation of open firmware or an implementation compatible with the open firmware client interface,those properties will be created by the trampoline code in the kernel prom_init() file For example, that's where you'll have to add code to detect your board model and set the platform number. However, when using the flattened device-tree entry point, there is no prom_init() pass, and thus you have to provide those properties yourself.
1)Note about cells and address representation:
The general rule is documentaed in open firmware documentation.
-If you choose a bus with the device tree and there exit OP bus binding,then you should follow specification.However kernel does not need to describe every device in device tree.

Format of address is defined my the parent bus type,based on #address-cell and #size-cell. These address are not inherited from parent so note that so every node with children must specify them.

What is cell?
Those 2 properties define 'cells' for representing an address and a size. A "cell" is a 32-bit number. For example, if both contain 2 like the example tree given above, then an address and a size are both composed of 2 cells, and each is a 64-bit number (cells are concatenated and expected to be in big endian format). Another example
is the way Apple firmware defines them, with 2 cells for an address and one cell for a size.  Most 32-bit implementations should define #address-cells and #size-cells to 1, which represents a 32-bit value. Some 32-bit processors allow for physical addresses greater than 32 bits; these processors should define #address-cells as 2.





2)Note about "compatiblle" property
These properties are optional, but recommended in device and the root node. The format of "compatible" property is a list of concatenated zero terminated strings. They allow a device to express its compatibility with family of similar device.n some cases,allowing a single driver to match against several devices regardless
of their actual names.
3)Note on "name" property
-While earlier users of Open Firmware like OldWorld macintoshes tended
to use the actual device name for the "name" property, it's nowadays
considered a good practice to use a name that is closer to the device
class (often equal to device_type). For example, nowadays, Ethernet
controllers are named "ethernet", an additional "model" property
defining precisely the chip type/model, and "compatible" property
defining the family in case a single driver can driver more than one
of these chips. However, the kernel doesn't generally put any
restriction on the "name" property; it is simply considered good
practice to follow the standard and its evolutions as closely as
possible.

-Note also that the new format version 16 makes the "name" property
optional. If it's absent for a node, then the node's unit name is then
used to reconstruct the name. That is, the part of the unit name
before the "@" sign is used (or the entire unit name if no "@" sign
is present).

4) Note about node and property names and character set
-------------------------------------------------------
 The root node requires some properties to be present:

    - model : this is your board name/model
    - #address-cells : address representation for "root" devices
    - #size-cells: the size representation for "root" devices
    - compatible : the board "family" generally finds its way here,
      for example, if you have 2 board models with a similar layout,
      that typically get driven by the same platform code in the
      kernel, you would specify the exact board model in the
      compatible property followed by an entry that represents the SoC
      model.

  The root node is also generally where you add additional properties
  specific to your board like the serial number if any, that sort of
  thing. It is recommended that if you add any "custom" property whose
  name may clash with standard defined ones, you prefix them with your
  vendor name and a comma.

  b) The /cpus node

  This node is the parent of all individual CPU nodes. It doesn't
  have any specific requirements, though it's generally good practice
  to have at least:

               #address-cells = <00000001>
               #size-cells    = <00000000>

  This defines that the "address" for a CPU is a single cell, and has
  no meaningful size. This is not necessary but the kernel will assume
  that format when reading the "reg" properties of a CPU node, see
  below

 c) The /cpus/* nodes
-So under /cpus, you are supposed to create a node for every CPU on
  the machine.
-So under /cpus, you are supposed to create a node for every CPU on
  the machine
-So under /cpus, you are supposed to create a node for every CPU on
  the machine
-the Generic Names convention suggests that it would be
  better to simply use 'cpu' for each cpu node and use the compatible
  property to identify the specific cpu core.


 Required properties:
- device_type : has to be "cpu"
    - reg : This is the physical CPU number, it's a single 32-bit cell
      and is also used as-is as the unit number for constructing the
      unit name in the full path. For example, with 2 CPUs, you would
      have the full path:
        /cpus/PowerPC,970FX@0
        /cpus/PowerPC,970FX@1
      (unit addresses do not require leading zeroes)
    - d-cache-block-size : one cell, L1 data cache block size in bytes (*)
    - i-cache-block-size : one cell, L1 instruction cache block size in
      bytes
    - d-cache-size : one cell, size of L1 data cache in bytes
    - i-cache-size : one cell, size of L1 instruction cache in bytes

(*) The cache "block" size is the size on which the cache management instructions operate. Historically, this document used the cache "line" size here which is incorrect. The kernel will prefer the cache block size and will fallback to cache line size for backward compatibility.














Recommended properties:

    - timebase-frequency : a cell indicating the frequency of the
      timebase in Hz. This is not directly used by the generic code,
      but you are welcome to copy/paste the pSeries code for setting
      the kernel timebase/decrementer calibration based on this
      value.
    - clock-frequency : a cell indicating the CPU core clock frequency
      in Hz. A new property will be defined for 64-bit values, but if
      your frequency is < 4Ghz, one cell is enough. Here as well as
      for the above, the common code doesn't use that property, but
      you are welcome to re-use the pSeries or Maple one. A future
      kernel version might provide a common function for this.
    - d-cache-line-size : one cell, L1 data cache line size in bytes
      if different from the block size
    - i-cache-line-size : one cell, L1 instruction cache line size in
      bytes if different from the block size



Monday, 22 December 2014

Git Problem solved

I wanted a kernel to download from git so I install
$zypper install git
It got installed
But at my work there is problem of certificate authentication
So to solve that I  export GIT_SSL_NO_VERIFY=1

This solved the problem half.Still I was not able to solve the problem as there was network connection error. So I went into patch.sh file .I changed git/ to http: or https: and it started to work


Cheers

Thank you

 

Thursday, 11 December 2014

Make Command in Linux

What does "make check" command do ?
Ans.
Strictly speaking, it doesn't necessarily do anything.
If a Makefile has a target named check, then make check will "build" that target. It's typically a phony target, meaning that it is a make-scripted command rather than a file named "check" that gets created.
The gnu project advises that all gnu software should include a make check target that runs post-build tests in the build directory, so make check can be used frequently on packages distributed from the FSF. Other projects will sometimes follow this convention as well.
 
What does "make oldconfig" do ?
ans:
It reads the existing .config file and prompts the user for options in the current kernel source that are not found in the file. This is useful when taking an existing configuration and moving it to a new kernel.
 
 

Cross compile kernel modules from rootfs to target ARM


If you are compiling for x86 should specify the kernel headers directory as /lib/modules/linux-3.7.2-2-ARCH/build. For cross-compiling either we will be downloading the linux source or use the linux source provided by the SOC manufacturer. Kernel header of the downloaded linux source has to be specified for compilation. Suppose have your downloaded linux source under /opt directory then sample "Makefile" would look like this obj-m += name-of-driver.o make -C /opt/linux(specify full version) M=${PWD} modules. Have to install the cross compiler and export i.e. export PATH=$PATH:/absolute path where your cross-compiler binaries are present. While compiling using make utility provide make ARCH=arm(Target for which you are compiling) CROSS_COMPILE=arm-none-linux-gnueabi-. Once all these procedure are followed you will be successfully compiling your kernel module for target.





Tuesday, 9 December 2014

what is the difference between ELF files and bin files

A Bin file is a pure binary file with no memory fix-ups or relocations, more than likely it has explicit instructions to be loaded at a specific memory address. Whereas....
ELF files are Executable Linkable Format which consists of a symbol look-ups and relocatable table, that is, it can be loaded at any memory address by the kernel and automatically, all symbols used, are adjusted to the offset from that memory address where it was loaded into. Usually ELF files have a number of sections, such as 'data', 'text', 'bss', to name but a few...it is within those sections where the run-time can calculate where to adjust the symbol's memory references dynamically at run-time


A bin file is just the bits and bytes that go into the rom or a particular address from which you will run the program. You can take this data and load it directly as is, you need to know what the base address is though as that is normally not in there.
An elf file contains the bin information but it is surrounded by lots of other information, possible debug info, symbols, can distinguish code from data within the binary. Allows for more than one chunk of binary data (when you dump one of these to a bin you get one big bin file with fill data to pad it to the next block). Tells you how much binary you have and how much bss data is there that wants to be initialised to zeros (gnu tools have problems creating bin files correctly).
The elf file format is a standard, arm publishes its enhancements/variations on the standard. I recommend everyone writes an elf parsing program to understand what is in there, dont bother with a library, it is quite simple to just use the information and structures in the spec. Helps to overcome gnu problems in general creating .bin files as well as debugging linker scripts and other things that can help to mess up your bin or elf output.

Monday, 8 December 2014

PREFIX and DESTDIR

PREFIX determines where the port will be installed. It defaults to /usr/local, but can be set by the user to a custom path like /opt. The port must respect the value of this variable.

DESTDIR, if set by the user, determines the complete alternative environment, usually a jail or an installed system mounted somewhere other than /. A port will actually install into DESTDIR/PREFIX, and register with the package database in DESTDIR/var/db/pkg. As DESTDIR is handled automatically by the ports infrastructure with chroot

The value of PREFIX will be set to LOCALBASE (defaulting to /usr/local). If USE_LINUX_PREFIX is set, PREFIX will be LINUXBASE (defaulting to /compat/linux).
Avoiding hard-coded /usr/local paths in the source makes the port much more flexible and able to cater to the needs of other sites. Often, this can be accomplished by replacing occurrences of /usr/local in the port's various Makefiles with ${PREFIX}. This variable is automatically passed down to every stage of the build and install processes.
Make sure the application is not installing things in /usr/local instead of PREFIX. A quick test for such hard-coded paths is:
% make clean; make package PREFIX=/var/tmp/`make -V PORTNAME`
If anything is installed outside of PREFIX, the package creation process will complain that it cannot find the files.
In addition, it is worth checking the same with the stage directory support (see Section 6.1, “Staging”):
% make stage && make check-plist && make stage-qa && make package
  • check-plist checks for files missing from the plist, and files in the plist that are not installed by the port.
  • stage-qa checks for common problems like bad shebang, symlinks pointing outside the stage directory, setuid files, and non-stripped libraries...
These tests will not find hard-coded paths inside the port's files, nor will it verify that LOCALBASE is being used to correctly refer to files from other ports. The temporarily-installed port in /var/tmp/`make -V PORTNAME` must be tested for proper operation to make sure there are no problems with paths.
PREFIX must not be set explicitly in a port's Makefile. Users installing the port may have set PREFIX to a custom location, and the port must respect that setting.
Refer to programs and files from other ports with the variables mentioned above, not explicit pathnames. For instance, if the port requires a macro PAGER to have the full pathname of less, do not use a literal path of /usr/local/bin/less. Instead, use ${LOCALBASE}:
-DPAGER=\"${LOCALBASE}/bin/less\"
The path with LOCALBASE is more likely to still work if the system administrator has moved the whole /usr/local tree somewhere else.


I am trying to make software install to a specific directory. I found several ways, but not sure what are the differences between them?
  1. ./configure --prefix=*
  2. make install --prefix=*
  3. make install DESTDIR=*                                                                                                                                                                                                                case 1 determines where the package will go when it is installed, and where it will look for its associated files when it is run. It's what you should use if you're just compiling something for use on a single host. 
  4.  case 3 is for installing to a temporary directory which is not where the package will be run from. For example this is used when building deb packages. The person building the package doesn't actually install everything into its final place on his own system. He may have a different version installed already and not want to disturb it, or he may not even be root. So he uses configure --prefix=/usr so the program will expect to be installed in /usr when it runs, then make install DESTDIR=debian/tmp to actually create the directory structure.                     
  5.   case 2: make install prefix=/foo/bar/baz. That's going to install it to a different place but not create all the directories as DESTDIR=/foo/bar/baz would. It's commonly used with GNU stow via ./configure --prefix=/usr/local && make && sudo make install prefix=/usr/local/stow/foo, which would install binaries in /usr/local/stow/foo/bin. (make install DESTDIR=/usr/local/stow/foo, by comparison, would install binaries in /usr/local/stow/foo/usr/local/bin.)

Friday, 5 December 2014

Installing Latext on opensuse 13.1

This guide explains how to install LaTeX in opensuse 13.1 Linux. LaTeX is a document preparation system for high-quality typesetting. It is most often used for medium-to-large technical or scientific documents but it can be used for almost any form of publishing.
LaTeX is not a word processor! Instead, LaTeX encourages authors not to worry too much about the appearance of their documents but to concentrate on getting the right content.
Installing LaTeX is also compatible to any hosting, Just make sure that the hosting you have is a reliable one.

How to install LaTeX in Opensuse 13.1

$ sudo zypper install texlive
 
$ sudo zypper install texlive-full 

Gedit LaTeX Plugin

Gedit has a plugin for LaTeX which converts Gedit into a LaTeX editor. You can install the Gedit LaTeX plugin as follows :
$ sudo apt-get install gedit-latex-plugin Once you install the plug-in, you will have to enable the plug-in in Gedit to begin using it. This is achieved by opening Gedit Preferences (GEdit > Edit > Preferences). Then clicking on the Plugins tab and turning on the “Gedit LaTeX plugin”. Now when ever you open a TeX file, you will have access to the LaTeX menu in Gedit.

Recommended LaTeX Packages

  • latex-beamer – Beamer package is used to create presentations. It is an excellent LaTeX class that supports dynamic effects.
  • TeXPower – Is a bundle of style and class files for creating dynamic online presentations with LaTeX.
  • Prosper – A LaTeX class for writing transparencies.
  • texlive-pictures – This is a LaTeX package for drawing graphics. It contain several classes such as ‘curve’ (for creating resumes), ‘bardiag’ (for bar graphs), ‘pmgraph’ (poor man’s graphics) and so on.
  • texlive-latex-extra – This is a large collection of addon packages for LaTeX. Th
This is the full command I used to install LaTeX on my machine running Ubuntu Linux.
$ sudo zypper install gedit-latex-plugin texlive-fonts-recommended latex-beamer texpower texlive-pictures texlive-latex-extra texpower-examples imagemagick
 
 
 
Now to get GUI support for you can use Texmaker
 
$zypper install Texmaker
 
For running LaTex we need to run from /usr/bin
./latex
./texmaker 

Now you are ready to go.....Keep smiling and use Linux

Wednesday, 3 December 2014

Minicon Linux Command

Setup minicom

The -s option use to setup minicom. Type the following command at shell prompt:
$minicom -s
minicom color
$minicom -s -c on
  • Serial port setup
  • menu
    • type "A" and edit serial device to /dev/ttyS0 for COM1
    • type "E" to enter Bps/par/Bits
    • submenu
      • type "I" for 115200 baud then <return>
    • type "F" until hardware flow control is "No"
    • type "G" until software flow control is "No"
    • <enter> to leave menu             
  • modem and dialing
  • menu
    • type "A" and edit Init String to make it blank then <enter>
    • <enter> to leave menu
  • save setup as dfl menu
  • exit menu

Monday, 1 December 2014

Gyroscope vs Accelerometer

Introduction

This guide is intended to everyone interested in in using Accelerometers and Gyroscopes as well as combination IMU devices (Inertial Measurement Unit) in their electronics projects
We'll cover:
  • What does an accelerometer measure?
  • What does a gyroscope (aka gyro) measure?
  • How to convert analog-to-digital (ADC) readings that you get from these sensor to physical units (those would be g for accelerometer, deg/s for gyroscope)
  • How to combine accelerometer and gyroscope readings in order to obtain accurate information about the inclination of your device relative to the ground plane
Throughout the article I will try to keep the math to the minimum. If you know what Sine/Cosine/Tangent are then you should be able to understand and use these ideas in your project no matter what platform you're using: Arduino, Propeller, Basic Stamp, Atmel chips, Microchip PIC, etc.

There are people out there who believe that you need complex math in order to make use of an IMU unit (complex FIR or IIR filters such as Kalman filters, Parks-McClellan filters, etc). You can research all those and achieve wonderful but complex results. My way of explaining things require just basic math. I am a great believer in simplicity. I think a system that is simple is easier to control and monitor, besides many embedded devices do not have the power and resources to implement complex algorithms requiring matrix calculations.
I'll use as an example a new IMU unit, the Acc_Gyro Accelerometer + Gyro IMU. We'll use parameters of this device in our examples below. This unit is a good device to start with because it consists of 2 devices:
- LIS331AL (data sheet) - a triaxial 2G accelerometer
- LPR550AL (data sheet) - a dual-axis pitch and roll, 500 deg/sec gyroscope
Together they represent a 5-Degrees of Freedom Inertial Measurement Unit. Now that's a fancy name! Nevertheless, behind the fancy name is a very useful combination device that we'll cover and explain in detail in this guide.

 
Remove these adsRemove these ads by Signing Up

Step 1: The Accelerometer

To understand this unit we'll start with the accelerometer. When thinking about accelerometers it is often useful to image a box in shape of a cube with a ball inside it. You may imagine something else like a cookie or a donut , but I'll imagine a ball:accelerometer model If we take this box in a place with no gravitation fields or for that matter with no other fields that might affect the ball's position - the ball will simply float in the middle of the box. You can imagine the box is in outer-space far-far away from any cosmic bodies, or if such a place is hard to find imagine at least a space craft orbiting around the planet where everything is in weightless state . From the picture above you can see that we assign to each axis a pair of walls (we removed the wall Y+ so we can look inside the box). Imagine that each wall is pressure sensitive. If we move suddenly the box to the left (we accelerate it with acceleration 1g = 9.8m/s^2), the ball will hit the wall X-. We then measure the pressure force that the ball applies to the wall and output a value of -1g on the X axis.
accelerometer model
Please note that the accelerometer will actually detect a force that is directed in the opposite direction from the acceleration vector. This force is often called Inertial Force or Fictitious Force . One thing you should learn from this is that an accelerometer measures acceleration indirectly through a force that is applied to one of it's walls (according to our model, it might be a spring or something else in real life accelerometers). This force can be caused by the acceleration , but as we'll see in the next example it is not always caused by acceleration.
If we take our model and put it on Earth the ball will fall on the Z- wall and will apply a force of 1g on the bottom wall, as shown in the picture below:
accelerometer model
In this case the box isn't moving but we still get a reading of -1g on the Z axis. The pressure that the ball has applied on the wall was caused by a gravitation force. In theory it could be a different type of force - for example, if you imagine that our ball is metallic, placing a magnet next to the box could move the ball so it hits another wall. This was said just to prove that in essence accelerometer measures force not acceleration. It just happens that acceleration causes an inertial force that is captured by the force detection mechanism of the accelerometer.
While this model is not exactly how a MEMS sensor is constructed it is often useful in solving accelerometer related problems. There are actually similar sensors that have metallic balls inside, they are called tilt switches, however they are more primitive and usually they can only tell if the device is inclined within some range or not, not the extent of inclination.
So far we have analyzed the accelerometer output on a single axis and this is all you'll get with a single axis accelerometers. The real value of triaxial accelerometers comes from the fact that they can detect inertial forces on all three axes. Let's go back to our box model, and let's rotate the box 45 degrees to the right. The ball will touch 2 walls now: Z- and X- as shown in the picture below:
accelerometer model
The values of 0.71 are not arbitrary, they are actually an approximation for SQRT(1/2). This will become more clear as we introduce our next model for the accelerometer.
In the previous model we have fixed the gravitation force and rotated our imaginary box. In last 2 examples we have analyzed the output in 2 different box positions, while the force vector remained constant. While this was useful in understanding how the accelerometer interacts with outside forces, it is more practical to perform calculations if we fix the coordinate system to the axes of the accelerometer and imagine that the force vector rotates around us.
accelerometer model
Please have a look at the model above, I preserved the colors of the axes so you can make a mental transition from the previous model to the new one. Just imagine that each axis in the new model is perpendicular to the respective faces of the box in the previous model. The vector R is the force vector that the accelerometer is measuring (it could be either the gravitation force or the inertial force from the examples above or a combination of both). Rx, Ry, Rz are projection of the R vector on the X,Y,Z axes. Please notice the following relation:
R^2 = Rx^2 + Ry^2 + Rz^2     (Eq. 1)
which is basically the equivalent of the Pythagorean theorem in 3D.
Remember that a little bit earlier I told you that the values of SQRT(1/2) ~ 0.71 are not random. If you plug them in the formula above, after recalling that our gravitation force was 1 g we can verify that:
1^2 = (-SQRT(1/2) )^2 + 0 ^2 + (-SQRT(1/2))^2
simply by substituting R=1, Rx = -SQRT(1/2), Ry = 0 , Rz = -SQRT(1/2) in Eq.1
After a long preamble of theory we're getting closer to real life accelerometers. The values Rx, Ry, Rz are actually linearly related to the values that your real-life accelerometer will output and that you can use for performing various calculations.
Before we get there let's talk a little about the way accelerometers will deliver this information to us. Most accelerometers will fall in two categories: digital and analog. Digital accelerometers will give you information using a serial protocol like I2C , SPI or USART, while analog accelerometers will output a voltage level within a predefined range that you have to convert to a digital value using an ADC (analog to digital converter) module. I will not go into much detail about how ADC works, partly because it is such an extensive topic and partly because it is different from one platform to another. Some microcontroller will have a built-in ADC modules some of them will need external components in order to perform the ADC conversions. No matter what type of ADC module you use you'll end up with a value in a certain range. For example a 10-bit ADC module will output a value in the range of 0..1023, note that 1023 = 2^10 -1. A 12-bit ADC module will output a value in the range of 0..4095, note that 4095 = 2^12-1.
Let's move on by considering a simple example, suppose our 10bit ADC module gave us the following values for the three accelerometer channels (axes):
AdcRx = 586
AdcRy = 630
AdcRz = 561
Each ADC module will have a reference voltage, let's assume in our example it is 3.3V. To convert a 10bit adc value to voltage we use the following formula:
VoltsRx = AdcRx * Vref / 1023
A quick note here: that for 8bit ADC the last divider would be 255 = 2 ^ 8 -1 , and for 12bit ADC last divider would be 4095 = 2^12 -1.
Applying this formula to all 3 channels we get:
VoltsRx = 586 * 3.3V / 1023 =~ 1.89V (we round all results to 2 decimal points)
VoltsRy = 630 * 3.3V / 1023 =~ 2.03V
VoltsRz = 561 * 3.3V / 1023 =~ 1.81V
Each accelerometer has a zero-g voltage level, you can find it in specs, this is the voltage that corresponds to 0g. To get a signed voltage value we need to calculate the shift from this level. Let's say our 0g voltage level is VzeroG = 1.65V. We calculate the voltage shifts from zero-g voltage as follows::
DeltaVoltsRx = 1.89V - 1.65V = 0.24V
DeltaVoltsRy = 2.03V - 1.65V = 0.38V
DeltaVoltsRz = 1.81V - 1.65V = 0.16V
We now have our accelerometer readings in Volts , it's still not in g (9.8 m/s^2), to do the final conversion we apply the accelerometer sensitivity, usually expressed in mV/g. Lets say our Sensitivity = 478.5mV/g = 0.4785V/g. Sensitivity values can be found in accelerometer specifications. To get the final force values expressed in g we use the following formula:
Rx = DeltaVoltsRx / Sensitivity
Rx = 0.24V / 0.4785V/g =~ 0.5g
Ry = 0.38V / 0.4785V/g =~ 0.79g
Rz = 0.16V / 0.4785V/g =~ 0.33g
We could of course combine all steps in one formula, but I went through all the steps to make it clear how you go from ADC readings to a force vector component expressed in g.
Rx = (AdcRx * Vref / 1023 - VzeroG) / Sensitivity (Eq.2)
Ry = (AdcRy * Vref / 1023 - VzeroG) / Sensitivity
Rz = (AdcRz * Vref / 1023 - VzeroG) / Sensitivity
We now have all 3 components that define our inertial force vector, if the device is not subject to other forces other than gravitation, we can assume this is the direction of our gravitation force vector. If you want to calculate inclination of device relative to the ground you can calculate the angle between this vector and Z axis. If you are also interested in per-axis direction of inclination you can split this result into 2 components: inclination on the X and Y axis that can be calculated as the angle between gravitation vector and X / Y axes. Calculating these angles is more simple than you might think, now that we have calculated the values for Rx,Ry and Rz. Let's go back to our last accelerometer model and do some additional notations:

The angles that we are interested in are the angles between X,Y,Z axes and the force vector R. We'll define these angles as Axr, Ayr, Azr. You can notice from the right-angle triangle formed by R and Rx that:
cos(Axr) = Rx / R , and similarly :
cos(Ayr) = Ry / R
cos(Azr) = Rz / R
We can deduct from Eq.1 that R = SQRT( Rx^2 + Ry^2 + Rz^2).
We can find now our angles by using arccos() function (the inverse cos() function ):
Axr = arccos(Rx/R)
Ayr = arccos(Ry/R)
Azr = arccos(Rz/R)
We've gone a long way to explain the accelerometer model, just to come up to these formulas. Depending on your applications you might want to use any intermediate formulas that we have derived. We'll also introduce the gyroscope model soon, and we'll see how accelerometer and gyroscope data can be combined to provide even more accurate inclination estimations.
But before we do that let's do some more useful notations:
cosX = cos(Axr) = Rx / R
cosY = cos(Ayr) = Ry / R
cosZ = cos(Azr) = Rz / R
This triplet is often called Direction Cosine , and it basically represents the unit vector (vector with length 1) that has same direction as our R vector. You can easily verify that:
SQRT(cosX^2 + cosY^2 + cosZ^2) = 1
This is a nice property since it absolve us from monitoring the modulus(length) of R vector. Often times if we're just interested in direction of our inertial vector, it makes sense to normalize it's modulus in order to simplify other calculations.

Step 2: Gyroscope

We're not going to introduce any equivalent box model for the gyroscope like we did for accelerometer, instead we're going to jump straight to the second accelerometer model and we'll show what does the gyroscope measure according to this model.
Each gyroscope channel measures the rotation around one of the axes. For instance a 2-axes gyroscope will measure the rotation around (or some may say "about") the X and Y axes. To express this rotation in numbers let's do some notations. First let's define:
Rxz - is the projection of the inertial force vector R on the XZ plane
Ryz - is the projection of the inertial force vector R on the YZ plane
From the right-angle triangle formed by Rxz and Rz, using Pythagorean theorem we get:
Rxz^2 = Rx^2 + Rz^2 , and similarly:
Ryz^2 = Ry^2 + Rz^2
also note that:
R^2 = Rxz^2 + Ry^2 , this can be derived from Eq.1 and above equations, or it can be derived from right-angle triangle formed by R and Ryz
R^2 = Ryz^2 + Rx^2
We're not going to use these formulas in this article but it is useful to note the relation between all the values in our model.
Instead we're going to define the angle between the Z axis and Rxz, Ryz vectors as follows:
Axz - is the angle between the Rxz (projection of R on XZ plane) and Z axis
Ayz - is the angle between the Ryz (projection of R on YZ plane) and Z axis
Now we're getting closer to what the gyroscope measures. Gyroscope measures the rate of changes of the angles defined above. In other words it will output a value that is linearly related to the rate of change of these angles. To explain this let's assume that we have measured the rotation angle around axis Y (that would be Axz angle) at time t0, and we define it as Axz0, next we measured this angle at a later time t1 and it was Axz1. The rate of change will be calculated as follows:
RateAxz = (Axz1 - Axz0) / (t1 - t0).
If we express Axz in degrees, and time in seconds , then this value will be expressed in deg/s . This is what a gyroscope measures.
In practice a gyroscope(unless it is a special digital gyroscope) will rarely give you a value expressed in deg/s. Same as for accelerometer you'll get an ADC value that you'll need to convert to deg/s using a formula similar to Eq. 2 that we have defined for accelerometer. Let's introduce the ADC to deg/s conversion formula for gyroscope (we assume we're using a 10bit ADC module , for 8bit ADC replace 1023 with 255, for 12bit ADC replace 1023 with 4095).
RateAxz = (AdcGyroXZ * Vref / 1023 - VzeroRate) / Sensitivity Eq.3
RateAyz = (AdcGyroYZ * Vref / 1023 - VzeroRate) / Sensitivity
AdcGyroXZ, AdcGyroYZ - are obtained from our adc module and they represent the channels that measure the rotation of projection of R vector in XZ respectively in YZ planes, which is the equivalent to saying rotation was done around Y and X axes respectively.

Vref - is the ADC reference voltage we'll use 3.3V in the example below

VzeroRate - is the zero-rate voltage, in other words the voltage that the gyroscope outputs when it is not subject to any rotation, for the Acc_Gyro board it is for example 1.23V (you can find this values in the specs)

Sensitivity - is the sensitivity of your gyroscope it is expressed in mV / (deg / s) often written as mV/deg/s , it basically tells you how many mV will the gyroscope output increase , if you increase the rotation speed by one deg/s. The sensitivity of Acc_Gyro board is for example 2mV/deg/s or 0.002V/deg/s
Let's take an example, suppose our ADC module returned following values:
AdcGyroXZ = 571
AdcGyroXZ = 323
Using the above formula, and using the specs parameters of Acc_Gyro board we'll get:
RateAxz = (571 * 3.3V / 1023 - 1.23V) / ( 0.002V/deg/s) =~ 306 deg/s
RateAyz = (323 * 3.3V / 1023 - 1.23V) / ( 0.002V/deg/s) =~ -94 deg/s
In other words the device rotates around the Y axis (or we can say it rotates in XZ plane) with a speed of 306 deg/s and around the X axis (or we can say it rotates in YZ plane) with a speed of -94 deg/s. Please note that the negative sign means that the device rotates in the opposite direction from the conventional positive direction. By convention one direction of rotation is positive. A good gyroscope specification sheet will show you which direction is positive, otherwise you'll have to find it by experimenting with the device and noting which direction of rotation results in increasing voltage on the output pin. This is best done using an oscilloscope since as soon as you stop the rotation the voltage will drop back to the zero-rate level. If you're using a multimeter you'd have to maintain a constant rotation rate for at least few seconds and note the voltage during this rotation, then compare it with the zero-rate voltage. If it is greater than the zero-rate voltage it means that direction of rotation is positive.

Step 3: Combining the Accelerometer and Gyro

Putting it all together - Combining accelerometer and gyroscope data.

If you're reading this article you probably acquired or are planning to acquire a IMU device, or probably you're planning to build one from separate accelerometer and gyroscope devices.
The first step in using a combination IMU device that combines an accelerometer and a gyroscope is to align their coordinate systems. The easiest way to do it is to choose the coordinate system of accelerometer as your reference coordinate system. Most accelerometer data sheets will display the direction of X,Y,Z axes relative to the image of the physical chip or device. For example here are the directions of X,Y,Z axes as shown in specifications for the Acc_Gyro board:
acc_gyro axes
Next steps are:
  • Identify the gyroscope outputs that correspond to RateAxz , RateAyz values discussed above.Determine if these outputs need to be inverted due to physical position of gyroscope relative to the accelerometer
Do not assume that if a gyroscope has an output marked X or Y, it will correspond to any axis in the accelerometer coordinate system, even if this output is part of an IMU unit. The best way is to test it. Assuming you have fixed the position of gyroscope relative to the accelerometer. It is assumed that the gyro and accelerometer borders are parallel to each other, i.e. you're placing the gyro at an angle multiple of 90deg relative to the accelerometer chip. If you acquired an IMU board chances are that they are already aligned this way. We're not going to discuss in this article models where gyroscope is placed at an irregular angle relative to accelerometer (let's say 45 or 30 degrees), although this might be useful in some applications.
Here is a sample sequence to determine which output of gyroscope corresponds to RateAxz value discussed above.
- start from placing the device in horizontal position. Both X and Y outputs of accelerometer would output the zero-g voltage (for example for Acc_Gyro board this is 1.65V)

- next start rotating the device around the Y axis, another way to say it is that you rotate the device in XZ plane, so that X and Z accelerometer outputs change and Y output remains constant.

- while rotating the device at a constant speed note which gyroscope output changes, the other gyroscope outputs should remain constant

- the gyroscope output that changed during the rotation around Y axis (rotation in XZ plane) will provide the input value for AdcGyroXZ, from which we calculate RateAxz

- the final step is to ensure the rotation direction corresponds to our model, in some cases you may have to invert the RateAxz value due to physical position of gyroscope relative to the accelerometer

- perform again the above test, rotating the device around the Y axis, this time monitor the X output of accelerometer (AdcRx in our model). If AdcRx grows (the first 90 degrees of rotation from horizontal position), then AdcGyroXZ should also grow. Otherwise you need to invert RateAxz , you can achieve this by introducing a sign factor in Eq.3, as follows:
RateAxz = InvertAxz * (AdcGyroXZ * Vref / 1023 - VzeroRate) / Sensitivity , where InvertAxz is 1 or -1
same test cane be done for RateAyz , by rotating the device around the X axis, and you can identify which gyroscope output corresponds to RateAyz, and if it needs to be inverted. Once you have the value for InvertAyz, you should use the following formula to calculate RateAyz:
RateAyz = InvertAyz * (AdcGyroYZ * Vref / 1023 - VzeroRate) / Sensitivity
If you would do these tests on Acc_Gyro board you would get following results:
- the output pin for RateAxz is GX4 and InvertAxz = -1.
- the output pin for RateAyz is GY4 and InvertAyz = -1
From this point on we'll consider that you have setup your IMU in such a way that you can calculate correct values for Axr, Ayr, Azr (as defined Part 1. Accelerometer) and RateAxz, RateAyz (as defined in Part 2. Gyroscope). Next we'll analyze the relations between these values that turn out useful in obtaining more accurate estimation of the inclination of the device relative to the ground plane.
You might be asking yourself by this point, if accelerometer model already gave us inclination angles of Axr,Ayr,Azr why would we want to bother with the gyroscope data ? The answer is simple: accelerometer data can't always be trusted 100%. There are several reason, remember that accelerometer measures inertial force, such a force can be caused by gravitation (and ideally only by gravitation), but it might also be caused by acceleration (movement) of the device. As a result even if accelerometer is in a relatively stable state, it is still very sensitive to vibration and mechanical noise in general. This is the main reason why most IMU systems use a gyroscope to smooth out any accelerometer errors. But how is this done ? And is the gyroscope free from noise ?
The gyroscope is not free from noise however because it measures rotation it is less sensitive to linear mechanical movements, the type of noise that accelerometer suffers from, however gyroscopes have other types of problems like for example drift (not coming back to zero-rate value when rotation stops). Nevertheless by averaging data that comes from accelerometer and gyroscope we can obtain a relatively better estimate of current device inclination than we would obtain by using the accelerometer data alone.
In the next steps I will introduce an algorithm that was inspired by some ideas used in Kalman filter, however it is by far more simple and easier to implement on embedded devices. Before that let's see first what we want our algorithm to calculate. Well , it is the direction of gravitation force vector R = [Rx,Ry,Rz] from which we can derive other values like Axr,Ayr,Azr or cosX,cosY,cosZ that will give us an idea about the inclination of our device relative to the ground plane, we discuss the relation between these values in Part 1. One might say - don't we already have these values Rx, Ry , Rz from Eq.2 in Part 1 ? Well yes, but remember that these values are derived from accelerometer data only, so if you would be to use them directly in your application you might get more noise than your application can tolerate. To avoid further confusion let's re-define the accelerometer measurements as follows:
Racc - is the inertial force vector as measured by accelerometer, that consists of following components (projections on X,Y,Z axes):
RxAcc = (AdcRx * Vref / 1023 - VzeroG) / Sensitivity
RyAcc = (AdcRy * Vref / 1023 - VzeroG) / Sensitivity
RzAcc = (AdcRz * Vref / 1023 - VzeroG) / Sensitivity
So far we have a set of measured values that we can obtain purely from accelerometer ADC values. We'll call this set of data a "vector" and we'll use the following notation.
Racc = [RxAcc,RyAcc,RzAcc]
Because these components of Racc can be obtained from accelerometer data , we can consider it an input to our algorithm.
Please note that because Racc measures the gravitation force you'll be correct if you assume that the length of this vector defined as follows is equal or close to 1g.
|Racc| = SQRT(RxAcc^2 +RyAcc^2 + RzAcc^2),
However to be sure it makes sense to update this vector as follows:
Racc(normalized) = [RxAcc/|Racc| , RyAcc/|Racc| , RzAcc/|Racc|].
This will ensure the length of your normalized Racc vector is always 1.
Next we'll introduce a new vector and we'll call it
Rest = [RxEst,RyEst,RzEst]
This will be the output of our algorithm , these are corrected values based on gyroscope data and based on past estimated data.
Here is what our algorithm will do:
- accelerometer tells us: "You are now at position Racc"
- we say "Thank you, but let me check",
- then correct this information with gyroscope data as well as with past Rest data and we output a new estimated vector Rest.
- we consider Rest to be our "best bet" as to the current position of the device.
Let's see how we can make it work.
We'll start our sequence by trusting our accelerometer and assigning:
Rest(0) = Racc(0)
By the way remember Rest and Racc are vectors , so the above equation is just a simple way to write 3 sets of equations, and avoid repetition:
RxEst(0) = RxAcc(0)
RyEst(0) = RyAcc(0)
RzEst(0) = RzAcc(0)
Next we'll do regular measurements at equal time intervals of T seconds, and we'll obtain new measurements that we'll define as Racc(1), Racc(2) , Racc(3) and so on. We'll also issue new estimates at each time intervals Rest(1), Rest(2), Rest(3) and so on.
Suppose we're at step n. We have two known sets of values that we'd like to use:
Rest(n-1) - our previous estimate, with Rest(0) = Racc(0)
Racc(n) - our current accelerometer measurement
Before we can calculate Rest(n) , let's introduce a new measured value, that we can obtain from our gyroscope and a previous estimate.
We'll call it Rgyro , and it is also a vector consisting of 3 components:
Rgyro = [RxGyro,RyGyro,RzGyro]
We'll calculate this vector one component at a time. We'll start with RxGyro.
gyro model
Let's start by observing the following relation in our gyroscope model, from the right-angle triangle formed by Rz and Rxz we can derive that:
tan(Axz) = Rx/Rz => Axz = atan2(Rx,Rz)
Atan2 might be a function you never used before, it is similar to atan, except it returns values in range of (-PI,PI) as opposed to (-PI/2,PI/2) as returned by atan, and it takes 2 arguments instead of one. It allows us to convert the two values of Rx,Rz to angles in the full range of 360 degrees (-PI to PI). You can read more about atan2 here.
So knowing RxEst(n-1) , and RzEst(n-1) we can find:
Axz(n-1) = atan2( RxEst(n-1) , RzEst(n-1) ).
Remember that gyroscope measures the rate of change of the Axz angle. So we can estimate the new angle Axz(n) as follows:
Axz(n) = Axz(n-1) + RateAxz(n) * T
Remember that RateAxz can be obtained from our gyroscope ADC readings. A more precise formula can use an average rotation rate calculated as follows:
RateAxzAvg = ( RateAxz(n) + RateAxz(n-1) ) / 2
Axz(n) = Axz(n-1) + RateAxzAvg * T
The same way we can find:
Ayz(n) = Ayz(n-1) + RateAyz(n) * T
Ok so now we have Axz(n) and Ayz(n). Where do we go from here to deduct RxGyro/RyGyro ? From Eq. 1 we can write the length of vector Rgyro as follows:
|Rgyro| = SQRT(RxGyro^2 + RyGyro^2 + RzGyro^2)
Also because we normalized our Racc vector, we may assume that it's length is 1 and it hasn't changed after the rotation, so it is relatively safe to write:
|Rgyro| = 1
Let's adopt a temporary shorter notation for the calculations below:
x =RxGyro , y=RyGyro, z=RzGyro
Using the relations above we can write:
x = x / 1 = x / SQRT(x^2+y^2+z^2)
Let's divide numerator and denominator of fraction by SQRT(x^2 + z^2)
x = ( x / SQRT(x^2 + z^2) ) / SQRT( (x^2 + y^2 + z^2) / (x^2 + z^2) )
Note that x / SQRT(x^2 + z^2) = sin(Axz), so:
x = sin(Axz) / SQRT (1 + y^2 / (x^2 + z^2) )
Now multiply numerator and denominator of fraction inside SQRT by z^2
x = sin(Axz) / SQRT (1 + y^2  * z ^2 / (z^2 * (x^2 + z^2)) )
Note that z / SQRT(x^2 + z^2) = cos(Axz) and y / z = tan(Ayz), so finally:
x = sin(Axz) / SQRT (1 + cos(Axz)^2 * tan(Ayz)^2 )
Going back to our notation we get:
RxGyro = sin(Axz(n)) / SQRT (1 + cos(Axz(n))^2 * tan(Ayz(n))^2 )
same way we find that
RyGyro = sin(Ayz(n)) / SQRT (1 + cos(Ayz(n))^2 * tan(Axz(n))^2 )
Now, finally we can find:
RzGyro  =  Sign(RzGyro)*SQRT(1 - RxGyro^2 - RyGyro^2).
Where Sign(RzGyro) = 1 when RzGyro>=0 , and Sign(RzGyro) = -1 when RzGyro<0.
One simple way to estimate this is to take:
Sign(RzGyro) = Sign(RzEst(n-1))
In practice be careful when RzEst(n-1) is close to 0. You may skip the gyro phase altogether in this case and assign:  Rgyro = Rest(n-1). Rz is used as a reference for calculating Axz and Ayz angles and when it's close to 0, values may oveflow and trigger bad results. You'll be in domain of large floating point numbers where tan() / atan() function implementations may lack precision.

So let's recap what we have so far, we are at step n of our algorithm and we have calculated the following values:
Racc - current readings from our accelerometer
Rgyro - obtained from Rest(n-1) and current gyroscope readings
Which values do we use to calculate the updated estimate Rest(n) ? You probably guessed that we'll use both. We'll use a weighted average, so that:
Rest(n) = (Racc * w1 + Rgyro * w2 ) / (w1 + w2)
We can simplify this formula by dividing both numerator and denominator of the fraction by w1.
Rest(n) = (Racc * w1/w1 + Rgyro * w2/w1 ) / (w1/w1 + w2/w1)
and after substituting w2/w1 = wGyro we get:
Rest(n) = (Racc + Rgyro * wGyro ) / (1 + wGyro)
In the above forumula wGyro tells us how much we trust our gyro compared to our accelerometer. This value can be chosen experimentally usually values between 5..20 will trigger good results.
The main difference of this algorithm from Kalman filter is that this weight is relatively fixed , whereas in Kalman filter the weights are permanently updated based on the measured noise of the accelerometer readings. Kalman filter is focused at giving you "the best" theoretical results, whereas this algorithm can give you results "good enough" for your practical application. You can implement an algorithm that adjusts wGyro depending on some noise factors that you measure, but fixed values will work well for most applications.
We are one step away from getting our updated estimated values:
RxEst(n) = (RxAcc + RxGyro * wGyro ) / (1 + wGyro)
RyEst(n) = (RyAcc + RyGyro * wGyro ) / (1 + wGyro)
RzEst(n) = (RzAcc + RzGyro * wGyro ) / (1 + wGyro)
Now let's  normalize this vector again:
R = SQRT(RxEst(n) ^2 + RyEst(n)^2 +  RzEst(n)^2 )
RxEst(n) = RxEst(n)/R
RyEst(n) = RyEst(n)/R
RzEst(n) = RzEst(n)/R
And we're ready to repeat our loop again.

This guide originally appeared on starlino.com, I've made a few light edits and re-posted it with permission. Thanks Starlino!

Reading analog (ADC) values on BeagleBone black

ADC value on BBB
There are 7 analog inputs on the BeagleBone.

ADC properties:
 - 12 bits (Output values in the range 0-4095)
 - 125ns sample time
 - 0-1.8V range (do not exceed!)
 - 2 uA current flows into the ADC pin in this range
 - If using a voltage divider, the lower leg (the one connected to ground) should be <= 1k Ohm
 - Since we are measuring millivolts, resistors with 0.1% error tolerance should be used in a voltage divider.
 - There is a 1.8V reference voltage VDD_ADC at Port 9 Pin 32.
 - There is a GNDA_ADC that should be grounded on Port9 Pin 34.
NamePin # Pin # Name
32 VDD_ADC
AIN433 34GNDA_ADC
AIN635 36 AIN5 
AIN2 37 38 AIN3 
AIN0 39 40 AIN1 
 The ADC values can be read very easily:

Original BeagleBone, later builds:
    beaglebone:~# cat /sys/devices/platform/omap/tsc/ain1
    1807
Original BeagleBone, older builds: 
    beaglebone:~# cat /sys/devices/platform/tsc/ain1
    1807
(Note that the path "ain1" maps to the pin "AIN0", the path "ain2" maps to the pin "AIN1", etc.)


BeagleBone black:
FIrst enable the ADC ports, then find out where they are and finall read them:

    sh-4.2# echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots
    sh-4.2# find /sys/ -name '*AIN*'
    /sys/devices/ocp.2/helper.14/AIN0
    /sys/devices/ocp.2/helper.14/AIN1
    /sys/devices/ocp.2/helper.14/AIN2
    /sys/devices/ocp.2/helper.14/AIN3
    /sys/devices/ocp.2/helper.14/AIN4
    /sys/devices/ocp.2/helper.14/AIN5
    /sys/devices/ocp.2/helper.14/AIN6
    /sys/devices/ocp.2/helper.14/AIN7
    sh-4.2# cat /sys/devices/ocp.2/helper.14/AIN1                         
    1588







The Analog to Digital Converter (ADC) on the BeagleBone is both a Touch Screen Controller (TSC) and a general purpose ADC. Depending on how many of the lines are reserved for the TSC (4, 5, or 8), the remaining lines can be used for reading analog values. One of the lines is connected to the power Management Integrated Circuit (PMIC, TPS65217) of the white Bone,  in order to sense the power used by the board. This does not appear to be the case for the new BeagleBone Black.
The basics 
To read the analog inputs on your BeagleBone Black, first enable the driver:
echo cape-bone-iio > /sys/devices/bone_capemgr.*/slots
The analog inputs should now be activated and exported to the filesystem. To read their values, just cat the files:
cat /sys/devices/ocp.2/helper.11/AIN1
This will read the analog value of AIN1 (The pin is P9_40). What you see is a voltage between 0 and 1.8V, but in millivolts (0 to 1799). If you tie the pin high by shorting the pin to the analog VDD (P9_32), you will see a 1799. If you tie the pin low to (P9_34, Analog ground), you will see a 0. There is a bug in the driver, so the value you read is actually the previous value you read. For now, just read the value twice. More on that later.
Bug in the ADC driver
Note: This was tested on kernel 3.8.6, the one that came with the early BeagleBone Black.
The driver for the ADC was riddled with errors early on. This manifested itself as getting weird values from the ADC when reading from one or several pins in rapid succession:
adc_failing
Clearly, a negative value is not right. The reason why this occurs is that there is no test to make sure the ADC is finished with sampling the pin. Furthermore, when one pin is read, the reading of this pin triggers the ADC to sample a new value (for all the pins) for the next reading. For further reading, consult the Linux mainline source: ti_am335x_adc.c. This will probably be fixed in later veriosn of the kernel, but if you need a solution now, have a look at these adc-patches and see if you can’t figure it out : )
Troubleshooting
If your analog inputs do not show up at the above spot, make sure the helper module is loaded:
lsmod
This shows a list of loaded kernel modules, make sure “bone_iio_helper” shows up in the list.
If the helper modules is loaded, but the fiels are not in the right place, try searching for them:
find /sys -name *AIN*
This should show you a list of the analog input files. If not, go to forum and rant. Make sure you include the kernel version you are using:
root@beaglebone:~# uname -a
Linux beaglebone 3.8.6 #1 SMP Sat Apr 13 09:10:52 CEST 2013 armv7l GNU/Linux