Thursday, April 21, 2011

Interfacing a motor

We cannot interface a DC motor directly with our micro-controller board as we will end up blowing up our board due to the back emf generated by the motor. As for robotics hobbyists, generally two types of DC motors are available in the market, a 12v or a 6v DC motor. Therefore driving a 6/12v device from a 5v micro-controller will lead to driving of a large amount of extra current from the device leading to burning up of its circuitry.In order to prevent the board from blowing up, we normally use an H-bridge to drive and control a motor from the micro-controller board. H-bridges use the direction of flow of current to drive and control a DC motor, as is shown in the figure below.But H-bridges suffer from the problem of complexity of the circuit.


Hence, in order to address this issue, L293D- a dual h-bridge motor driver IC was introduced. With one such IC, we can interface 2 DC motors which can be controlled in both clockwise and anticlockwise direction. Datasheet can be found here.
Just follow the schematic and the truth table shown below to interface a motor with L293D and you will be good to go.

Tuesday, April 12, 2011

A small tip for troubleshooting with sensors

One of the best way to detect the malfunctioning of sensors is to test them with Oscilloscope . Many times sensors don't gives desired output when interfaced with micro-controller. The use of oscilloscope gives you the correct voltage response against time. This will help you to select scaling factor of Voltage to make it work for 0-5V (required for most of micro-controller). In addition to this the frequency response of voltage will enable you to select best sampling rate for your ADC.

Friday, April 8, 2011

Resources for embedded hardware

This blog compiles all the sources (online as well as actual shops in Delhi) from where we procured our components:
  • Rhydolabz - http://www.rhydolabz.com/
    • Stuff Procured:
    1. 5 Amp Current Sensor - http://www.rhydolabz.com/index.php?main_page=product_info&products_id=506: Works nicely, sensitivity becomes a problem for measuring low current values
    2. RF (433 MHz) Transmitter
  • Lajpat Rai Market Shop Number 415 (Contact Person - Mr. Dhariwal, 9313544213)
    • Stuff Procured:
    1. 555 Timer Chip - Cost - Rs 30: Works nicely; Tried a version with 3.3V as well as 5V and was able to integrate both of them in my circuitry easily.

Thursday, March 31, 2011

Compiling TinyOS on Ubuntu Maverick (10.10)

  1. Ensure that you have uninstalled all the TinyOS related packages that you had previously installed. The following command should help:
    sudo apt-get --purge remove tinyos*
  2. Add the TinyOS repository to your sources.list (we will use the lucid packages since packages for maverick aren't available):
    echo "deb http://tinyos.stanford.edu/tinyos/dists/ubuntu lucid main" | sudo tee -a /etc/apt/sources.list
    sudo apt-get update
  3. Install the required TinyOS toolchain:
    sudo apt-get install tinyos-required-msp430
  4. Download the TinyOS source into ~/tinyos using SVN: 
    mkdir ~/tinyos
    cd ~/tinyos
    svn checkout http://tinyos-main.googlecode.com/svn/trunk/ tinyos-2.x
    Note: This does not work on the institute's internet due to certain blocking schemes.  If you're trying this from the institute's internet, download and extract this into ~/tinyos.
  5. Compile and install the tools:
    cd tinyos-2.x/tools
    ./Bootstrap
    ./configure --prefix=$HOME/tinyos/install
    make install
  6. Set the environment variables by adding the following to your ~/.bashrc:
    export PATH=$HOME/tinyos/install/bin:$PATH
    export TOSROOT=$HOME/tinyos/tinyos-2.x
    export TOSDIR=$TOSROOT/tos
    export MAKERULES=$TOSROOT/support/make/Makerules
    export CLASSPATH=$TOSROOT/support/sdk/java/tinyos.jar:.
    export PYTHONPATH=.:$TOSROOT/support/sdk/python:$PYTHONPATH
    export PATH=$HOME/tinyos/tinyos-2.x/support/sdk/c:$PATH
  7. Compile the Blink app to test:
    cd ~/tinyos/tinyos-2.x/apps/Blink
    make micaz sim

      Friday, February 18, 2011

      Accessing internal EEPROM on ATmega328P

      As we know, ATmega328P contains an internal EEPROM memory of 1KB in size. Since the internal EEPROM is a non-volatile memory, it can retain the stored information even after powering down the controller. In general, EEPROM is used to store any device specific parameters which will be read first to initialize external components after booting. This tutorial will explain how to write and read data on EPROM by giving an example code.

      What do we have on our plate?

      We can access the internal EEPROM using
      1. EEPROM library functions available in AVR-GCC.
      2. EEPROM access registers available in ATmega328P

      The first method is simple and straight forward by just calling the library functions available in eeprom.h. Whereas, the second method is slightly complicated by directly accessing the EEPROM's address/data/control registers and is preferred for time critical applications. I will explain both briefly.

      1. Using EEPROM library functions availabe in AVR-GCC
      AVR-GCC library provides set of library functions to access EEPROM. All interface functions are declared in avr/eeprom.h, and thus, we have to include this header in our code.

      Lets look at couple of functions which read and write a byte on EEPROM. Their prototype is as below.
      uint8_t eeprom_read_byte(const uint8_t * pAddress)
      Returns a byte of data read from address pAddress. 

      void eeprom_write_byte(uint8_t *pAddress, uint8_t value)
      Write a byte of data, value, at address pAddress.

      The documentation of full list of EEPROM access functions are listed here.
      The below example code demonstrates the use of few functions.

      /*
      * 328_eeprom.c
      * ATMega328P Internal EEPROM read/write
      * Created on: 20-Mar-2011
      * Author: samy
      */

      #define F_CPU 16000000UL
      #define BAUD 9600
      #define MYUBRR F_CPU/16/BAUD-1

      #include <stdio.h>
      #include <avr/io.h>
      #include <avr/eeprom.h>
      #include "delay_x.h"
      #include "USART328.c" /* Shared by Abhishek for USART interface */
      //#include <avr/sfr_defs.h>

      int main (void)
      {
      char buf[20];
      unsigned int addr;

      uint8_t rb8, wb8 = 'a';
      uint16_t rw16, ww16 = 12345;
      uint32_t rdw32, wdw32 = 1234567;
      float rfloat, wfloat = 123.45f;
      char rblk[5], wblk[5] = "abcd";

      USART_init(MYUBRR);

      for(;;) // Loop Forever
      {
      addr = 0;
      /* Read and Write a word */
      eeprom_write_word( (uint16_t*)addr, ww16 );
      rw16 = eeprom_read_word((uint16_t*)addr);
      sprintf( buf, "R/W %d @ %d\r\n", rw16, addr);
      USART_String(buf);

      /* Read and Write a double word */
      eeprom_write_dword( (uint32_t*)addr, wdw32 );
      rdw32 = eeprom_read_dword((uint32_t*)addr);
      sprintf( buf, "R/W %ld @ %d\r\n", rdw32, addr);
      USART_String(buf);

      /* Read and Write a float */
      eeprom_write_float( (float*)addr, wfloat );
      rfloat = eeprom_read_float((float*)addr);
      sprintf( buf, "R/W %d.%d @ %d\r\n", (int)rfloat, ((int)(rfloat*100))%100, addr);
      USART_String(buf);

      /* Read and Write a block */
      eeprom_write_block(wblk, (void*)addr, sizeof(wblk) );
      eeprom_read_block (rblk, (void*)addr, sizeof(wblk) );
      sprintf( buf, "R/W %s @ %d\r\n", rblk, addr);
      USART_String(buf);
      _delay_s(3);

      while( addr <= E2END ) /* E2END : last valid address in Internal EEPROM */
      {
      /* Read and Write a byte */
      eeprom_write_byte( (uint8_t*)addr, wb8 );
      rb8 = eeprom_read_byte((uint8_t*)addr);
      sprintf( buf, "R/W %c @ %d\r\n", rb8, addr);
      USART_String(buf);
      ++addr;
      }
      _delay_s(3);
      }
      }

      2. Using EEPROM access registers available in ATmega328P

      ATMega328P provides 3 registers to control the operation of EEPROM.
      1. Address Register (EEAR)
      2. Data Register (EEDR)
      3. Control Register (EECR)

      The below table explains the purpose and function of each register/bit.

      Name

      Length/Bit#

      Purpose/Function

      EEAR

      10(remaining 6bits unused)

      Address register. Contains EEPROM address to which data is read/written

      EEARH

      2 (Bits 0 to 1)

      Address high order bits

      EEARL

      8

      Address low order byte

      EEDR

      8

      Data register. Contains data to be read/written

      EECR

      6 (Bits 0 to 5)

      Control register.

      EEPM1

      EEPM0

      Bit 5

      Bit 4

      Together controls the programming mode.

      0 – Erase and write, 1 – Erase only, 2 – Write only, 3 - unused

      EERIE

      Bit 3

      Ready Interrupt Enable

      1 – Enable Ready interrupt, 0 – Disables

      EEMPE

      Bit 2

      Master Write Enable. Must be set to one to write and will be reset after 4 clock cycles.

      EEPE

      Bit 1

      Write Enable. When set to one, writes the content of EEDR at EEPROM address EEAR. EEMPE must be set to one.

      EERE

      Bit 0

      Read Enable. When set to one, trigger the Read operation. Reads the data at address EEAR and store to EEDR.

      More detailed information such as number of clock cycles for each operation, interrupt controlled EEPROM access, etc are explained in the datasheet.
      Below is the implementation of simple read/write operation for a byte and string. These functions can be interfaced with above code. Also, please note that these functions assume interrupts are disabled, if not, you have to call cli() function (clear global interrupt mask in avr/interrupt.h) first before invoking any one of the below functions.
      void eeprom_write_byte1(uint16_t addr, uint8_t data)
      {
      while(EECR & (1<<EEPE)) /*wait until previous write any*/
      ;
      EEAR = addr;
      EEDR = data;
      EECR |= (1<<EEMPE);
      EECR |= (1<<EEPE);
      }

      uint8_t eeprom_read_byte1(uint16_t addr)
      {
      while(EECR & (1<<EEPE))/*wait until previous write any*/
      ;
      EEAR = addr;
      EECR |= (1<<EERE);
      return EEDR;
      }

      /*assumes s is a proper null terminated string*/
      void eeprom_write_string(uint16_t addr, char *s)
      {
      while(*s)
      {
      eeprom_write_byte1(addr, *s );
      ++s;
      ++addr;
      }
      }

      /* read a string of len characters maximum starting at addr.
      * modify according to your need!
      */
      void eeprom_read_string(uint16_t addr, char *s, int len)
      {
      while(len)
      {
      *s = eeprom_read_byte1(addr);
      if( *s == '\0' )
      return;
      --len;
      ++s;
      }
      *s = '\0';
      return;
      }
      References:

      Wednesday, January 26, 2011

      Synchronization Problem while burning the code

      I got a avrdude: stk500_getsync(): not in sync error while uploading the code to the micro-controller using avrdude. I tried different ways like changing the com port, reconnecting the USB cable as suggested by our TA but it didn't work for me.

      Finally, i realised that the problems comes up when i try to burn the code with LCD connected to the respective pins . So, i tried with removing the LCD connectors during uploading the code and it worked out fine . This piece of text can help if others are facing such problem.

      Do not let the connecting cables to touch each other. This can blow up the main IC.

      Tuesday, January 25, 2011

      LCD doubt

      While I was making the program for LCD I figured out that the accuracy of LCD is pretty low. If I make the program dispaly "tanmay" it shows "vounmay" and for "abcd" it was showing "abcd" in one blink and "afgf" in another and also random charcters some time. Has anyone else also been experiencing something and what could be the possible error?