mercredi 9 octobre 2013

Integrating with the social Jungle

We really need to integrate ourselves in the middle of social life, a person that cannot integrate in his society would be qualified as non normal or with no regular behavior.
The fact is, that integrating in the society is a very relative concept, a person that cannot integrate himself in a specific society could be the most popular in another society, and we take the example of gamers or real geeks that bunch of guys that are so addicted to a video game or hacking computer software, have real problem with integrating within a society where the one who can use MSWord is qualified as a one who masters the computer. But the same Geeky person would be so popular in a society of geeks.

Here we go back to the point that in order to be popular or at least can integrate in a society, a person MUST share with the society its common believes, practices, way of thinking and looking to the world.
To integrate with a society a person must talk like they talk even if there is actually nothing wrong with hes talking and way of reasoning, a person must joke like they do, eat like they do even if it'is not healthy for him to eat the food they eat or the way they eat not eating like them take a -1 from his popularity mark.

The problem is not integrating could be very harmful for some people, the fact that they loose connection with their entourage and surrounding colleagues, the fact that they are not respected or acknowledged for what they do best. For example a person who masters fishing would have no value in a society of hunters. And here we conclude that to integrate in a society, you must actual do something that is relevant and useful for them, otherwise a person with deviated skills cannot easily integrate with a society.

But any person in the world no matter how intelligent, crazy, ugly, beautiful, rich or poor need to have people surrounding him, that can talk with him ask for him and worry about him. It is a natural need and it's very harmful to take it from someone which hes only curse that he was born with a deviated skills.

So any person in this world must be conscious of this fact, and therefore open his mind to different ideas and different believes. respect the other competence even if it is not relevant to him it could be relevant for someone else, it could help other societies.
Any person should not judge other people way of thinking as bizarre or weird, he could actual look more bizarre in another Time and Place Circumstances.

Finally, I would like to invite you to be more opened with weird people, they are actually more interesting than the typical believes.

Mazen


vendredi 20 septembre 2013

Controlling 2*16 LCD with STM32F4 discovery board

LCD can be a very useful part in any microcontroller based project. It helps to monitor variables and program status with simple texts or numbers.

For this application I used a JHD 162 A alphanumeric LCD, like the picture above.
It hast 16 pins specified like this
VEE is used for contrast, so attache it to a potentiometer  and choose your best contrast. Or simply plug it to 5V if you need maximum contrast.
D0, D1, D2, D3 are grounded
I managed to find a library for STM32VL, so I needed to bring some changes to it before it works. This library works both for JHD 162A and the hd44780.

lcd_hd44780.h
//******************************************************************************
//    THE SOFTWARE INCLUDED IN THIS FILE IS FOR GUIDANCE ONLY.
//    AUTHOR SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT
//    OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
//    FROM USE OF THIS SOFTWARE.
//******************************************************************************

//##############################################################################
// lcd_hd44780.h
//##############################################################################

//****************************************************************************//
#include "main.h"


#define LCD_GPIO GPIOD
#define LCD_CLK_LINE RCC_AHB1Periph_GPIOD

#define LCD_D4 GPIO_Pin_1
#define LCD_D5 GPIO_Pin_3
#define LCD_D6 GPIO_Pin_5
#define LCD_D7 GPIO_Pin_7

#define LCD_RS GPIO_Pin_0
#define LCD_RW GPIO_Pin_2
#define LCD_EN GPIO_Pin_4
//******************************************************************************//


#define HD44780_CLEAR                                          0x01

#define HD44780_HOME                                           0x02

#define HD44780_ENTRY_MODE                                 0x04
        #define HD44780_EM_SHIFT_CURSOR          0
        #define HD44780_EM_SHIFT_DISPLAY         1
        #define HD44780_EM_DECREMENT               0
        #define HD44780_EM_INCREMENT               2

#define HD44780_DISPLAY_ONOFF                      0x08
        #define HD44780_DISPLAY_OFF                  0
        #define HD44780_DISPLAY_ON                         4
        #define HD44780_CURSOR_OFF                         0
        #define HD44780_CURSOR_ON                            2
        #define HD44780_CURSOR_NOBLINK     0
        #define HD44780_CURSOR_BLINK               1

#define HD44780_DISPLAY_CURSOR_SHIFT 0x10
        #define HD44780_SHIFT_CURSOR               0
        #define HD44780_SHIFT_DISPLAY              8
        #define HD44780_SHIFT_LEFT                         0
        #define HD44780_SHIFT_RIGHT                  4

#define HD44780_FUNCTION_SET                       0x20
        #define HD44780_FONT5x7                              0
        #define HD44780_FONT5x10                             4
        #define HD44780_ONE_LINE                             0
        #define HD44780_TWO_LINE                             8
        #define HD44780_4_BIT                                  0
        #define HD44780_8_BIT                                  16

#define HD44780_CGRAM_SET                                    0x40

#define HD44780_DDRAM_SET                                    0x80

//##############################################################
void lcd_init(void);
void lcd_cls(void);
void lcd_str(unsigned char * text);
void lcd_strxy(unsigned char * text, unsigned char x, unsigned char y);
void lcd_locate(unsigned char x, unsigned char y);
void lcd_int(int n);
void lcd_intxy(int n, unsigned char x, unsigned char y);

//###############################################################

void lcd_writedata(unsigned char dataToWrite);
void lcd_writecommand(unsigned char commandToWrite);
void lcd_writebinary(unsigned int var, unsigned char bitCount);
void lcd_addchar (unsigned char chrNum, unsigned char n, const unsigned char *p);


lcd_hd44780.c
#include "lcd_hd44780.h"
#include "stm32f4xx_gpio.h"
#include 
#include 
#include 
#include "stm32f4_discovery.h"

GPIO_InitTypeDef GPIO_InitStructure;

//-----------------------------------------------------------------------------
void lcd_writenibble(unsigned char nibbleToWrite)
{
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_SET);
  GPIO_WriteBit(LCD_GPIO, LCD_D4,(BitAction) (nibbleToWrite & 0x01));
  GPIO_WriteBit(LCD_GPIO, LCD_D5,(BitAction)(nibbleToWrite & 0x02));
  GPIO_WriteBit(LCD_GPIO, LCD_D6,(BitAction)(nibbleToWrite & 0x04));
  GPIO_WriteBit(LCD_GPIO, LCD_D7,(BitAction)(nibbleToWrite & 0x08));
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_RESET);
}


//-----------------------------------------------------------------------------
unsigned char LCD_ReadNibble(void)
{
  unsigned char tmp = 0;
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_SET);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D4) << 0);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D5) << 1);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D6) << 2);
  tmp |= (GPIO_ReadInputDataBit(LCD_GPIO, LCD_D7) << 3);
  GPIO_WriteBit(LCD_GPIO, LCD_EN, Bit_RESET);
  return tmp;
}


//-----------------------------------------------------------------------------
unsigned char LCD_ReadStatus(void)
{
  unsigned char status = 0;

    GPIO_InitStructure.GPIO_Pin   =  LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
    GPIO_InitStructure.GPIO_Mode  =  GPIO_Mode_IN;
    GPIO_Init(LCD_GPIO, &GPIO_InitStructure);

    GPIO_WriteBit(LCD_GPIO, LCD_RW, Bit_SET);
    GPIO_WriteBit(LCD_GPIO, LCD_RS, Bit_RESET);

    status |= (LCD_ReadNibble() << 4);
    status |= LCD_ReadNibble();

    GPIO_InitStructure.GPIO_Pin   =  LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_Init(LCD_GPIO, &GPIO_InitStructure);

  return status;
}


//-----------------------------------------------------------------------------
void lcd_writedata(unsigned char dataToWrite)
{
  GPIO_WriteBit(LCD_GPIO, LCD_RW, Bit_RESET);
  GPIO_WriteBit(LCD_GPIO, LCD_RS, Bit_SET);

  lcd_writenibble(dataToWrite >> 4);
  lcd_writenibble(dataToWrite & 0x0F);

  while(LCD_ReadStatus() & 0x80);
}


//-----------------------------------------------------------------------------
void lcd_writecommand(unsigned char commandToWrite)
{
  GPIO_WriteBit(LCD_GPIO, LCD_RW | LCD_RS, Bit_RESET);
  lcd_writenibble(commandToWrite >> 4);
  lcd_writenibble(commandToWrite & 0x0F);

  while(LCD_ReadStatus() & 0x80);
}


//-----------------------------------------------------------------------------
void lcd_str(unsigned char * text)
{
  while(*text)
    lcd_writedata(*text++);
}


//-----------------------------------------------------------------------------
void lcd_locate(unsigned char x, unsigned char y)
{
  lcd_writecommand(HD44780_DDRAM_SET | (x + (0x40 * y)));
}


//-----------------------------------------------------------------------------
void lcd_strxy(unsigned char * text, unsigned char x, unsigned char y)
{
  lcd_locate(x,y);
  while(*text)
    lcd_writedata(*text++);
}


//-----------------------------------------------------------------------------
void lcd_writebinary(unsigned int var, unsigned char bitCount)
{
  signed char i;

  for(i = (bitCount - 1); i >= 0; i--)
     {
     lcd_writedata((var & (1 << i))?'1':'0');
     }
}


//-----------------------------------------------------------------------------
void LCD_ShiftLeft(void)
{
  lcd_writecommand(HD44780_DISPLAY_CURSOR_SHIFT | HD44780_SHIFT_LEFT | HD44780_SHIFT_DISPLAY);
}


//-----------------------------------------------------------------------------
void LCD_ShiftRight(void)
{
  lcd_writecommand(HD44780_DISPLAY_CURSOR_SHIFT | HD44780_SHIFT_RIGHT | HD44780_SHIFT_DISPLAY);
}


//-----------------------------------------------------------------------------
void lcd_init(void)
{
  volatile unsigned char i = 0;
  volatile unsigned int delayCnt = 0;
  RCC_AHB1PeriphClockCmd(LCD_CLK_LINE, ENABLE);
  GPIO_InitStructure.GPIO_Pin = LCD_D4|LCD_D5|LCD_D6|LCD_D7|LCD_RS|LCD_RW|LCD_EN;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

  GPIO_Init(LCD_GPIO, &GPIO_InitStructure);

  GPIO_ResetBits(LCD_GPIO, LCD_RS | LCD_EN | LCD_RW);

  for(delayCnt = 0; delayCnt < 300000; delayCnt++);

  for(i = 0; i < 3; i++) {
    lcd_writenibble(0x03);
    for(delayCnt = 0; delayCnt < 30000; delayCnt++);
  }

  lcd_writenibble(0x02);

  for(delayCnt = 0; delayCnt < 6000; delayCnt++);

  lcd_writecommand(HD44780_FUNCTION_SET |
                   HD44780_FONT5x7 |
                   HD44780_TWO_LINE |
                   HD44780_4_BIT);

  lcd_writecommand(HD44780_DISPLAY_ONOFF |
                   HD44780_DISPLAY_OFF);

  lcd_writecommand(HD44780_CLEAR);

  lcd_writecommand(HD44780_ENTRY_MODE |
                   HD44780_EM_SHIFT_CURSOR |
                   HD44780_EM_INCREMENT);

  lcd_writecommand(HD44780_DISPLAY_ONOFF |
                   HD44780_DISPLAY_ON |
                   HD44780_CURSOR_OFF |
                   HD44780_CURSOR_NOBLINK);

}


//-----------------------------------------------------------------------------
void lcd_addchar (unsigned char chrNum, unsigned char n, const unsigned char *p)
{
        lcd_writecommand(HD44780_CGRAM_SET | chrNum * 8);
        n *= 8;
        do
                lcd_writedata(*p++);
        while (--n);
}


//-----------------------------------------------------------------------------
void lcd_cls(void){
        lcd_writecommand(HD44780_CLEAR);
}



unsigned char* intToStr(int n){
     int i = 0;
     int j = 0;
   char *tmp = (char*)malloc(sizeof(char));
     unsigned char *ret = (unsigned char*)malloc(12);
   if(n<0 data-blogger-escaped-i="" data-blogger-escaped-j="" data-blogger-escaped-n="" data-blogger-escaped-ret="-" data-blogger-escaped-while="">9){
 *tmp = n%10+48;
 n-=n%10;
 n/=10;
 tmp++;
 i++;
}
*tmp = n+48;
i++;
while(i--){
 ret[j++] = *tmp--;
}
return ret;
}
void lcd_int(int a){
 unsigned short ch,
                    first; //you need this to display 0 if there was any char

    //Get first char
    ch = a/10000;
    if(ch){
     lcd_writedata(48+ch);
     first = 1;
    }

    //Get second char
    ch = (a/1000)%10;
    if(ch || first){
     lcd_writedata(48+ch);
     first = 1;
    }

    //Get third char
    ch = (a/100)%10;
    if(ch || first){
     lcd_writedata(48+ch);
     first = 1;
    }

    //Get fourth char
    ch = (a/10)%10;
    if(ch || first){
     lcd_writedata(48+ch);
     //first = 1;                   //q
    }

    //Get fifth char
    ch = a%10;
    //if(ch || first)   //you dont need to check las one if ch is 0 then just display it, unless you dont want to then uncomment this line ("//q" line too)
     lcd_writedata(48+ch);
       // lcd_str(intToStr(n));
}

void lcd_intxy(int n, unsigned char x, unsigned char y){
        lcd_locate(x,y);
        lcd_int(n);
}



main.c
lcd_init();

        while (1)
          {

                  lcd_locate(1,0);
                  lcd_str("Mazen");
                  lcd_locate(7,0);
                  lcd_str("A.");
                  lcd_locate(0,1);
                  lcd_str("-3125");

          }

Update:
Number display function is fixed

lundi 12 août 2013

Resistor Calculator Android application

This is my first android application, it consists of something that I actually need during making electronic projects where there are so many resistors in the table and I can't just figure out the value of each one of them at a glance.
Resistors used code colors, and each color according to its position has a specific value.


A resistor can have 4, 5 or 6 color bands just like the following picture:

Each color rank have a specific meaning in each Resistor type. For example the third band (from the left) of a 4 band resistor is a multiplier digit, but in the 5 band resistor it is the unity digit.

The previous picture shows a resistor with 4 color bands, organized as follow (from left to right)
Brown, Black, Red, Gold
10*10^ 2 +/- 5%  = 1K ohm with 5% tolerance

For more information about how to calculate resistor color code, please refer to this wonderful wekipedia article:
http://fr.wikipedia.org/wiki/CEI_60757
I actually use this mnemonic in french "ne mange rien ou jeuner voila bien votre grande bétise" to remember the mean of each color in the resistance' but sometimes that could be very confusing, so I thought to create an android app that help with that.
I know that there is many android app doing that, but I did wanted to learn android too :D

The Android application:

In the Main activity, there are 3 buttons for each kind of resistor:
Each button open a new Activity through a simple intent in its OnClickListener() as follow:
btn4BandResistance.setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    Intent intent4 = new Intent(MainActivity.this,BandResistor4.class);
    startActivity(intent4);
   }
  });
A new Activity opens, I used The Spinner View to choose from one of the predefined colors, and TextViews to show result:

I used a function that is called in each OnItemSelectedListener() of each spinner to update the results:
spin1Band4.setOnItemSelectedListener(new OnItemSelectedListener() {

   @Override
   public void onItemSelected(AdapterView arg0, View arg1,
     int arg2, long arg3) {
    
    update4BandResistance();
   }

   @Override
   public void onNothingSelected(AdapterView arg0) {
    // TODO Auto-generated method stub
    
   }
  });
the update function link the position of each selected Item to a value already defined in an Array:
 public void update4BandResistance(){
  String unity;
  TotalResistance = (ColorArrayBand[spin1Band4.getSelectedItemPosition()]+ColorArrayBand2[spin2Band4.getSelectedItemPosition()]) * ColorArrayMultiplier[spinMultiply4.getSelectedItemPosition()];
  Tolerance = TotalResistance * ColorArrayTolerance[spin1Tolerance4.getSelectedItemPosition()];
  if(TotalResistance>=1000000){
   TotalResistance/=1000000;
   unity = "M Ohm";
  }
  else if (TotalResistance>=1000){
   TotalResistance /= 1000;
   unity = "K Ohm";
  }
  else {
   unity = "Ohm";
  }
  txtTolerance.setText(String.valueOf(TotalResistance + Tolerance)+"/"+String.valueOf(TotalResistance - Tolerance));
  txtResistance.setText("R = "+String.valueOf(TotalResistance)+unity);  
 }

Finally I added some modification to the result for a more readable value:

The hole project can be found in github:
https://github.com/Mazen21/ResistanceCalculator

I'm looking forward for your suggestions:



  





lundi 15 juillet 2013

Reading Accelerometer and Gyroscope data from STM32F3 discovery board

I've made some experiments using the STM32F3 discovery board, which is amazing by the way, and the mems(Micro ElectroMechnical Systems) in the board.


For more information about the board check this link where you will find all the technical hardware and software examples made with many IDEs.
The main idea of this article is to make a standalone IMU (Inertial Measurement Unit) using only the STM32F3 board, because it has all the necessary hardware for making a complete 9 DOF IMU.

To do so I need to read both of the Gyroscope and the accelerometer data collected in a way so I can send later to the PC using VCP (USB CDC).

I started with the VCP example for the STM32303c eval board, you can find here
And then I add both of stm32f3_discovery_lsm303dlhc.c and stm32f3_discovery_l3gd20.c, this two file could be found in the utitli folder of the firmware support for the STM32F3 board can be found here.

Then later I found this great files to give more abstract function to deal with the mems.

The complete project from here

Accelerometer.c
#ifndef _ACC_C_
#define _ACC_C_

#define LSM_Acc_Sensitivity_2g     (float)     1.0f            /*!< accelerometer sensitivity with 2 g full scale [LSB/mg] */
#define LSM_Acc_Sensitivity_4g     (float)     0.5f            /*!< accelerometer sensitivity with 4 g full scale [LSB/mg] */
#define LSM_Acc_Sensitivity_8g     (float)     0.25f           /*!< accelerometer sensitivity with 8 g full scale [LSB/mg] */
#define LSM_Acc_Sensitivity_16g    (float)     0.0834f         /*!< accelerometer sensitivity with 12 g full scale [LSB/mg] */

#include "Accelerometer.h"
#include "stm32f3_discovery_lsm303dlhc.h"
/**
  * @brief  Configure the Mems to Accelerometer MEMS.
  * @param  None
  * @retval None
  */
void Acc_Config(void)
{
  LSM303DLHCAcc_InitTypeDef LSM303DLHCAcc_InitStructure;
  LSM303DLHCAcc_FilterConfigTypeDef LSM303DLHCFilter_InitStructure;
    
   /* Fill the accelerometer structure */
  LSM303DLHCAcc_InitStructure.Power_Mode = LSM303DLHC_NORMAL_MODE;
  LSM303DLHCAcc_InitStructure.AccOutput_DataRate = LSM303DLHC_ODR_50_HZ;
  LSM303DLHCAcc_InitStructure.Axes_Enable= LSM303DLHC_AXES_ENABLE;
  LSM303DLHCAcc_InitStructure.AccFull_Scale = LSM303DLHC_FULLSCALE_2G;
  LSM303DLHCAcc_InitStructure.BlockData_Update = LSM303DLHC_BlockUpdate_Continous;
  LSM303DLHCAcc_InitStructure.Endianness=LSM303DLHC_BLE_LSB;
  LSM303DLHCAcc_InitStructure.High_Resolution=LSM303DLHC_HR_ENABLE;
  /* Configure the accelerometer main parameters */
  LSM303DLHC_AccInit(&LSM303DLHCAcc_InitStructure);
  
  /* Fill the accelerometer LPF structure */
  LSM303DLHCFilter_InitStructure.HighPassFilter_Mode_Selection =LSM303DLHC_HPM_NORMAL_MODE;
  LSM303DLHCFilter_InitStructure.HighPassFilter_CutOff_Frequency = LSM303DLHC_HPFCF_16;
  LSM303DLHCFilter_InitStructure.HighPassFilter_AOI1 = LSM303DLHC_HPF_AOI1_DISABLE;
  LSM303DLHCFilter_InitStructure.HighPassFilter_AOI2 = LSM303DLHC_HPF_AOI2_DISABLE;

  /* Configure the accelerometer LPF main parameters */
  LSM303DLHC_AccFilterConfig(&LSM303DLHCFilter_InitStructure);
}

/**
* @brief Read LSM303DLHC output register, and calculate the acceleration ACC=(1/SENSITIVITY)* (out_h*256+out_l)/16 (12 bit rappresentation)
* @param pnData: pointer to float buffer where to store data
* @retval None
*/
void Acc_ReadData(float* pfData)
{
  int16_t pnRawData[3];
  uint8_t ctrlx[2];
  float LSM_Acc_Sensitivity = LSM_Acc_Sensitivity_2g;
  uint8_t buffer[6], cDivider;
  uint8_t i = 0;
  
  /* Read the register content */
  LSM303DLHC_Read(ACC_I2C_ADDRESS, LSM303DLHC_CTRL_REG4_A, ctrlx,2);
  LSM303DLHC_Read(ACC_I2C_ADDRESS, LSM303DLHC_OUT_X_L_A, buffer, 6);
 
  
  if(ctrlx[1]&0x40)
    cDivider=64;
  else
    cDivider=16;

  /* check in the control register4 the data alignment*/
  if(!(ctrlx[0] & 0x40) || (ctrlx[1] & 0x40)) /* Little Endian Mode or FIFO mode */
  {
    for(i=0; i<3 data-blogger-escaped-0x30="" data-blogger-escaped-8="" data-blogger-escaped-all="" data-blogger-escaped-and="" data-blogger-escaped-axis="" data-blogger-escaped-basic="" data-blogger-escaped-big="" data-blogger-escaped-block="" data-blogger-escaped-break="" data-blogger-escaped-brief="" data-blogger-escaped-buffer="" data-blogger-escaped-case="" data-blogger-escaped-cc_sensitivity="" data-blogger-escaped-cdivider="" data-blogger-escaped-communication="" data-blogger-escaped-content="" data-blogger-escaped-crtl4="" data-blogger-escaped-ctrlx="" data-blogger-escaped-else="" data-blogger-escaped-endian="" data-blogger-escaped-endif="" data-blogger-escaped-fifo="" data-blogger-escaped-float="" data-blogger-escaped-for="" data-blogger-escaped-i="" data-blogger-escaped-if="" data-blogger-escaped-in="" data-blogger-escaped-int16_t="" data-blogger-escaped-lsm303dlhc_ctrl_reg4_a="" data-blogger-escaped-lsm303dlhc_fullscale_16g:="" data-blogger-escaped-lsm303dlhc_fullscale_2g:="" data-blogger-escaped-lsm303dlhc_fullscale_4g:="" data-blogger-escaped-lsm303dlhc_fullscale_8g:="" data-blogger-escaped-lsm303dlhc_read="" data-blogger-escaped-lsm303dlhc_timeout_usercallback="" data-blogger-escaped-lsm_acc_sensitivity="LSM_Acc_Sensitivity_16g;" data-blogger-escaped-management="" data-blogger-escaped-mg="" data-blogger-escaped-mode="" data-blogger-escaped-none.="" data-blogger-escaped-normal="" data-blogger-escaped-obtain="" data-blogger-escaped-of="" data-blogger-escaped-param="" data-blogger-escaped-pfdata="" data-blogger-escaped-pnrawdata="" data-blogger-escaped-pre="" data-blogger-escaped-processes="" data-blogger-escaped-read="" data-blogger-escaped-register="" data-blogger-escaped-retval="" data-blogger-escaped-sensitivity="" data-blogger-escaped-set="" data-blogger-escaped-situation.="" data-blogger-escaped-switch="" data-blogger-escaped-the="" data-blogger-escaped-three="" data-blogger-escaped-timeout="" data-blogger-escaped-uint16_t="" data-blogger-escaped-uint32_t="" data-blogger-escaped-value="" data-blogger-escaped-void="" data-blogger-escaped-while="" data-blogger-escaped-x40="">
Gyro.c



#ifndef _GYRO_C_
#define _GYRO_C_

#define L3G_Sensitivity_250dps     (float)   114.285f         /*!< gyroscope sensitivity with 250 dps full scale [LSB/dps] */
#define L3G_Sensitivity_500dps     (float)    57.1429f        /*!< gyroscope sensitivity with 500 dps full scale [LSB/dps] */
#define L3G_Sensitivity_2000dps    (float)    14.285f       /*!< gyroscope sensitivity with 2000 dps full scale [LSB/dps] */

#include "Gyro.h"
#include "stm32f3_discovery_l3gd20.h"

/**
  * @brief  Configure the Mems to gyroscope application.
  * @param  None
  * @retval None
  */
void GyroConfig(void)
{
  L3GD20_InitTypeDef L3GD20_InitStructure;
  L3GD20_FilterConfigTypeDef L3GD20_FilterStructure;
  
  /* Configure Mems L3GD20 */
  L3GD20_InitStructure.Power_Mode = L3GD20_MODE_ACTIVE;
  L3GD20_InitStructure.Output_DataRate = L3GD20_OUTPUT_DATARATE_1;
  L3GD20_InitStructure.Axes_Enable = L3GD20_AXES_ENABLE;
  L3GD20_InitStructure.Band_Width = L3GD20_BANDWIDTH_4;
  L3GD20_InitStructure.BlockData_Update = L3GD20_BlockDataUpdate_Continous;
  L3GD20_InitStructure.Endianness = L3GD20_BLE_LSB;
  L3GD20_InitStructure.Full_Scale = L3GD20_FULLSCALE_500; 
  L3GD20_Init(&L3GD20_InitStructure);
   
  L3GD20_FilterStructure.HighPassFilter_Mode_Selection =L3GD20_HPM_NORMAL_MODE_RES;
  L3GD20_FilterStructure.HighPassFilter_CutOff_Frequency = L3GD20_HPFCF_0;
  L3GD20_FilterConfig(&L3GD20_FilterStructure) ;
  
  L3GD20_FilterCmd(L3GD20_HIGHPASSFILTER_ENABLE);
}

/**
  * @brief  Calculate the angular Data rate Gyroscope.
  * @param  pfData : Data out pointer
  * @retval None
  */
void GyroReadAngRate (float* pfData)
{
  uint8_t tmpbuffer[6] ={0};
  int16_t RawData[3] = {0};
  uint8_t tmpreg = 0;
  float sensitivity = 0;
  int i =0;

  L3GD20_Read(&tmpreg,L3GD20_CTRL_REG4_ADDR,1);
  
  L3GD20_Read(tmpbuffer,L3GD20_OUT_X_L_ADDR,6);
  
  /* check in the control register 4 the data alignment (Big Endian or Little Endian)*/
  if(!(tmpreg & 0x40))
  {
    for(i=0; i<3 data-blogger-escaped-0="" data-blogger-escaped-0x00:="" data-blogger-escaped-0x10:="" data-blogger-escaped-0x20:="" data-blogger-escaped-0x30="" data-blogger-escaped-8="" data-blogger-escaped-awdata="" data-blogger-escaped-basic="" data-blogger-escaped-break="" data-blogger-escaped-brief="" data-blogger-escaped-by="" data-blogger-escaped-case="" data-blogger-escaped-crtl4="" data-blogger-escaped-divide="" data-blogger-escaped-else="" data-blogger-escaped-endif="" data-blogger-escaped-float="" data-blogger-escaped-for="" data-blogger-escaped-i="" data-blogger-escaped-in="" data-blogger-escaped-int16_t="" data-blogger-escaped-l3gd20_timeout_usercallback="" data-blogger-escaped-management="" data-blogger-escaped-none.="" data-blogger-escaped-of="" data-blogger-escaped-param="" data-blogger-escaped-pfdata="" data-blogger-escaped-pre="" data-blogger-escaped-rawdata="" data-blogger-escaped-return="" data-blogger-escaped-retval="" data-blogger-escaped-sensitivity="" data-blogger-escaped-set="" data-blogger-escaped-situation.="" data-blogger-escaped-switch="" data-blogger-escaped-the="" data-blogger-escaped-timeout="" data-blogger-escaped-tmpbuffer="" data-blogger-escaped-tmpreg="" data-blogger-escaped-uint16_t="" data-blogger-escaped-uint32_t="" data-blogger-escaped-value="" data-blogger-escaped-void="">
main.c
/**
  ******************************************************************************
  * @file    main.c
  * @author  MCD Application Team
  * @version V4.0.0
  * @date    21-January-2013
  * @brief   Virtual Com Port Demo main file
  ******************************************************************************
  * @attention
  *
  **
  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
  * You may not use this file except in compliance with the License.
  * You may obtain a copy of the License at:
  *
  *        http://www.st.com/software_license_agreement_liberty_v2
  *
  * Unless required by applicable law or agreed to in writing, software 
  * distributed under the License is distributed on an "AS IS" BASIS, 
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
  ******************************************************************************
  */


/* Includes ------------------------------------------------------------------*/
#include "hw_config.h"
#include "usb_lib.h"
#include "usb_desc.h"
#include "usb_pwr.h"
#include "Accelerometer.h"
#include "Gyro.h"
#include 
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
float AccData[3];
float GyroData[3];
char data[9];
 int i =0;
/* Extern variables ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/*******************************************************************************
* Function Name  : main.
* Description    : Main routine.
* Input          : None.
* Output         : None.
* Return         : None.
*******************************************************************************/
int main(void)
{
// data[0] = 'K';

  Set_System();
  Set_USBClock();
  USB_Interrupts_Config();
  USB_Init();
  Acc_Config();
  GyroConfig();
  while (1)
  {
   Acc_ReadData(AccData);
   GyroReadAngRate(GyroData);
   sprintf(data,"%F",AccData[0]);
   sprintf(data+3,"%F",AccData[1]);
   sprintf(data+6,"%F",AccData[2]);
    UserToPMABufferCopy((uint8_t*)data,ENDP1_TXADDR,9);
      SetEPTxCount(ENDP1, 9);
      SetEPTxValid(ENDP1); 
   sprintf(data,"%F",GyroData[0]);
   sprintf(data+3,"%F",GyroData[1]);
   sprintf(data+6,"%F",GyroData[2]);
    UserToPMABufferCopy((uint8_t*)data,ENDP1_TXADDR,9);
      SetEPTxCount(ENDP1, 9);
      SetEPTxValid(ENDP1);
   
  // printf("%s\n",AccData);
  }
}
#ifdef USE_FULL_ASSERT
/*******************************************************************************
* Function Name  : assert_failed
* Description    : Reports the name of the source file and the source line number
*                  where the assert_param error has occurred.
* Input          : - file: pointer to the source file name
*                  - line: assert_param error line source number
* Output         : None
* Return         : None
*******************************************************************************/
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {}
}
#endif

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

mercredi 3 juillet 2013

Interfacing an MCP23017 a GPIO expander with a PIC16F877

Hello,
When we dealing with microcontrollers, the number of GPIO (General Purpose Input Output) pins is always limited and sometimes it is impossible to interface some components that desires many outputs from a microcontroller due to the unavailability of pins in the microcontroller and this may lead to change the used microcontroller to another one.
In some other cases, the microcontroller controls a very distant equipment that requires many pins to work, this will lead us to make one wear for each pin and so there is a big chance of loosing data plus there is the high price of the wires.

For this problems there are a simple solution that consists on a GPIO expander. The role of a GPIO expander is to add more GPIO pins to the microcontroller, the microcontroller then is interfacing with the expander using a serial protocols that requires few wires.

In this tutorial I used the MCP23017 which is a GPIO expander by MICROCHIP that talks with a PIC16F877 using I2C protocol.
I used mplab-x and hi tech C for code creation,and proteus ISIS for simulation:

If you want to know more about I2C visit this link.

The schematics:

The code:
I2C.C
#include "Includes.h"

void I2CInit(void){
        TRISC3 = 1;      /* SDA and SCL as input pin */
        TRISC4 = 1;      /* these pins can be configured either i/p or o/p */
        SSPSTAT |= 0x80; /* Slew rate disabled */
        SSPCON = 0x28;   /* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
        SSPADD = 0x28;    /* 100Khz @ 4Mhz Fosc */
}

/*
Function: I2CStart
Return:
Arguments:
Description: Send a start condition on I2C Bus
*/
void I2CStart(){
        SEN = 1;         /* Start condition enabled */
        while(SEN);      /* automatically cleared by hardware */
                     /* wait for start condition to finish */
}

/*
Function: I2CStop
Return:
Arguments:
Description: Send a stop condition on I2C Bus
*/
void I2CStop(){
        PEN = 1;         /* Stop condition enabled */
        while(PEN);      /* Wait for stop condition to finish */
                     /* PEN automatically cleared by hardware */
}

/*
Function: I2CRestart
Return:
Arguments:
Description: Sends a repeated start condition on I2C Bus
*/
void I2CRestart(){
        RSEN = 1;        /* Repeated start enabled */
        while(RSEN);     /* wait for condition to finish */
}

/*
Function: I2CAck
Return:
Arguments:
Description: Generates acknowledge for a transfer
*/
void I2CAck(){
        ACKDT = 0;       /* Acknowledge data bit, 0 = ACK */
        ACKEN = 1;       /* Ack data enabled */
        while(ACKEN);    /* wait for ack data to send on bus */
}

/*
Function: I2CNck
Return:
Arguments:
Description: Generates Not-acknowledge for a transfer
*/
void I2CNak(){
        ACKDT = 1;       /* Acknowledge data bit, 1 = NAK */
        ACKEN = 1;       /* Ack data enabled */
        while(ACKEN);    /* wait for ack data to send on bus */
}

/*
Function: I2CWait
Return:
Arguments:
Description: wait for transfer to finish
*/
void I2C_Wait(){
        while ( ( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );
    /* wait for any pending transfer */
}

/*
Function: I2CSend
Return:
Arguments: dat - 8-bit data to be sent on bus
           data can be either address/data byte
Description: Send 8-bit data on I2C bus
*/
void I2CSend(unsigned char dat){
        SSPBUF = dat;    /* Move data to SSPBUF */
        while(BF);       /* wait till complete data is sent from buffer */
        I2C_Wait();       /* wait for any pending transfer */
}

/*
Function: I2CRead
Return:    8-bit data read from I2C bus
Arguments:
Description: read 8-bit data from I2C bus
*/
unsigned char I2CRead(void){
        unsigned char temp;
/* Reception works if transfer is initiated in read mode */
        RCEN = 1;        /* Enable data reception */
        while(!BF);      /* wait for buffer full */
        temp = SSPBUF;   /* Read serial buffer and store in temp register */
        I2C_Wait();       /* wait to check any pending transfer */
        return temp;     /* Return the read data from bus */
}


MCP23017.C
#include "MCP23017.h"
#include "I2C.h"

void MCP23017_write(unsigned char reg, unsigned char data){
    I2CInit();
    I2CStart();
    I2CSend(DE_ADD_WRITE);
    I2CSend(reg);
    I2CSend(data);
    I2CStop();
}

unsigned char MCP23017_read(unsigned char reg){
    unsigned char Rxbyte;
    I2CStart();
    I2CSend(DE_ADD_WRITE);
    I2CSend(GP_PINS_A);
    I2CRestart();
    I2CSend(DE_ADD_READ);
    Rxbyte= I2CRead();
    I2CStop();
}

void MCP23017_IO(unsigned char PortA_IO, unsigned char PortB_IO){
    MCP23017_write(GPB_A,PortA_IO);
    MCP23017_write(GPB_B,PortB_IO);
}





dimanche 14 avril 2013

ADC with DMA

DMA stands for direct memory access, this can be used one data needed to be transferred from place to another as it is for example from RAM to FLASH memory, from I2C, SPI or ADC to memory.
The DMA controller replaces the CPU in data transfer operation so the CPU can be freed to do other tasks.
DMA can be useful when there is critical data to receive and the user wants to see all data, even using the interrupt I/O there still time wasted while context switching, this can be elure with DMA.
The STM32 microcontroller has 2 DMA Controllers (DMA1, DMA2) and there are connected to the peripheral and memory through channels.
In the following example, I will illustrate the use of DMA with ADC.


#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_adc.h"
#include "stm32f4xx_dma.h"


#define ADC3_DR_ADDRESS    ((uint32_t)0x4001224C)

/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
__IO uint32_t ADC3ConvertedValue = 0;
void config(){
 ADC_InitTypeDef       ADC_InitStructure;
   ADC_CommonInitTypeDef ADC_CommonInitStructure;
   DMA_InitTypeDef       DMA_InitStructure;
   GPIO_InitTypeDef      GPIO_InitStructure;

   /* Enable ADC3, DMA2 and GPIO clocks ****************************************/
   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOC, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);

   /* DMA2 Stream0 channel2 configuration **************************************/
   DMA_InitStructure.DMA_Channel = DMA_Channel_2;
   DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;
   DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADC3ConvertedValue;
   DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
   DMA_InitStructure.DMA_BufferSize = 1;
   DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
   DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
   DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
   DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
   DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
   DMA_InitStructure.DMA_Priority = DMA_Priority_High;
   DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
   DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
   DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
   DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
   DMA_Init(DMA2_Stream0, &DMA_InitStructure);
   DMA_Cmd(DMA2_Stream0, ENABLE);

   /* Configure ADC3 Channel7 pin as analog input ******************************/
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
   GPIO_Init(GPIOC, &GPIO_InitStructure);

   /* ADC Common Init **********************************************************/
   ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
   ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
   ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
   ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
   ADC_CommonInit(&ADC_CommonInitStructure);

   /* ADC3 Init ****************************************************************/
   ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
   ADC_InitStructure.ADC_ScanConvMode = DISABLE;
   ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
   ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
   ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
   ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
   ADC_InitStructure.ADC_NbrOfConversion = 1;
   ADC_Init(ADC3, &ADC_InitStructure);

   /* ADC3 regular channel7 configuration *************************************/
   ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);

  /* Enable DMA request after last transfer (Single-ADC mode) */
   ADC_DMARequestAfterLastTransferCmd(ADC3, ENABLE);

   /* Enable ADC3 DMA */
   ADC_DMACmd(ADC3, ENABLE);

   /* Enable ADC3 */
   ADC_Cmd(ADC3, ENABLE);

}
int main(void)
{
 config();
 ADC_SoftwareStartConv(ADC3);
    while(1)
    {
    }
}

samedi 6 avril 2013

ADC with STM32F4

In many embedded projects, we have to deal with signals directly from nature, like temperature, pressure, current, etc... Theses signals are analog by default and in most of cases we use sensors that converts these analog signals to analog electrical voltage to be injected in the microcontroller to do some work.
Unfortunately, microcontrollers are digital and just can't deal with analog signals so these signals must be converted again to digital signals that is comprehensible by the microcontroller.

For this purpose, microcontroller's manufacturers usually incorporate an ADC into the microcontroller. ADC is actually stands for Analog to Digital Converter. This module is omnipresent in most of microcontrollers.

I'm going to use the STM32F4 discovery board to interface an analog input provided by a potentiometer and visualize the received data with the watch feature while debugging the program.

#include "stm32f4xx_adc.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"

int ConvertedValue = 0; //Converted value readed from ADC


void adc_configure(){
 ADC_InitTypeDef ADC_init_structure; //Structure for adc confguration
 GPIO_InitTypeDef GPIO_initStructre; //Structure for analog input pin
 //Clock configuration
 RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,ENABLE);//The ADC1 is connected the APB2 peripheral bus thus we will use its clock source
 RCC_AHB1PeriphClockCmd(RCC_AHB1ENR_GPIOCEN,ENABLE);//Clock for the ADC port!! Do not forget about this one ;)
 //Analog pin configuration
 GPIO_initStructre.GPIO_Pin = GPIO_Pin_0;//The channel 10 is connected to PC0
 GPIO_initStructre.GPIO_Mode = GPIO_Mode_AN; //The PC0 pin is configured in analog mode
 GPIO_initStructre.GPIO_PuPd = GPIO_PuPd_NOPULL; //We don't need any pull up or pull down
 GPIO_Init(GPIOC,&GPIO_initStructre);//Affecting the port with the initialization structure configuration
 //ADC structure configuration
 ADC_DeInit();
 ADC_init_structure.ADC_DataAlign = ADC_DataAlign_Right;//data converted will be shifted to right
 ADC_init_structure.ADC_Resolution = ADC_Resolution_12b;//Input voltage is converted into a 12bit number giving a maximum value of 4096
 ADC_init_structure.ADC_ContinuousConvMode = ENABLE; //the conversion is continuous, the input data is converted more than once
 ADC_init_structure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;// conversion is synchronous with TIM1 and CC1 (actually I'm not sure about this one :/)
 ADC_init_structure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;//no trigger for conversion
 ADC_init_structure.ADC_NbrOfConversion = 1;//I think this one is clear :p
 ADC_init_structure.ADC_ScanConvMode = DISABLE;//The scan is configured in one channel
 ADC_Init(ADC1,&ADC_init_structure);//Initialize ADC with the previous configuration
 //Enable ADC conversion
 ADC_Cmd(ADC1,ENABLE);
 //Select the channel to be read from
 ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_144Cycles);
}
int adc_convert(){
 ADC_SoftwareStartConv(ADC1);//Start the conversion
 while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));//Processing the conversion
 return ADC_GetConversionValue(ADC1); //Return the converted data
}
int main(void){
 adc_configure();//Start configuration
    while(1){//loop while the board is working
     ConvertedValue = adc_convert();//Read the ADC converted value
    }
}


samedi 16 mars 2013

Blinky with STM32F4DISCOVERY board

In this tutorial I'm going to show you one of the most used IP in any ST microcontroller the GPIO. What you need to know witch could be obvious to some that we are actually going to program the microcontroller in the board and not the board!!

The microcontroller of the STM32F4DISCOVERY board is STM32F407VGT ==> Datasheet

I'm using coocox for developing and it's an eclipse based IDE very friendly and intuitive.

The GPIO IP:
As I said it stands for Gneral purpose Input Output,
Each of the GPIO pins can be configured by software as output (push-pull or open-drain,
with or without pull-up or pull-down), as input (floating, with or without pull-up or pull-down)
or as peripheral alternate function. Most of the GPIO pins are shared with digital or analog
alternate functions. All GPIOs are high-current-capable and have speed selection to better
manage internal noise, power consumption and electromagnetic emission.
The I/O configuration can be locked if needed by following a specific sequence in order to
avoid spurious writing to the I/Os registers.
Fast I/O handling allowing maximum I/O toggling up to 84 MHz.
(From datasheet)

There are 5 GPIOs in the STM32 microcontroller (GPIOA,GPIOB,GPIOC,GPIOD,GPIOE) every GPIO has 16 configurable pin and each has 7 registers:
Two are used to configure the sixteen port bits individually, (CRL,CRH)
two are used to read/write the sixteen port bits in parallel, (ODR,IDR)
two are used to set/reset the sixteen port bits individually, (BSRR,BRR)
and one is used to implement a “locking sequence” that is intended to prevent rogue code from accidentally modifying the port configuration (LCKR)

First start new project choose chip (ST-STM32F407VG) . Later on the repositry window will appear, we will do some blinking so we definitely need the GPIO, click on the GPIO check box, RCC, CMSIS boot and M4 CMSIS Core are automatically checked.



In the project tree double click on main.c

GPIO as output :

What are we going to do is to make the leds embedded on the board to blink together every 1sec but to do so we need to know to witch pin and witch GPIO these leds are connected in our STM32F4DISCOVERY board.

According to the board schematics in pag 6
The leds are connected to (PD12/PD13/PD14/PD15) the GPIO used is then GPIOD and the pins are (12, 13, 14, 15)

So what we need to do is explained in the following flowchart:

The program is :
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"

GPIO_InitTypeDef GPIO_InitStructure;

void Delay(__IO uint32_t nCount);
/**
* @brief GPIO pin toggle program
* @param None
* @retval None
*/
void main(void)
{
/* GPIOD Periph clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

/* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);

while (1)
{
/* LEDZ on */
GPIO_SetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
/* Insert delay */
Delay(0xFFFFF);
/* LEDZ off */
GPIO_ResetBits(GPIOD, GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15);
/* Insert delay */
Delay(0xFFFFF);
}
}

/**
* @brief Delay Function.
* @param nCount:specifies the Delay time length.
* @retval None
*/
void Delay(__IO uint32_t nCount)
{
while(nCount--)
{
}
}

GPIO as INPUT : 
Say that we need to read input from the outside world like buttons or switches we have to use the GPIO too.
In this case we are going to read the embedded button in the STM32F4DISCOVERY board.
 According to the board schematics this button is connected to the PA0 (GPIOA, pin 0).
What are we going to do is to set the leds on when the button is set and resetting them when the button is not set.

But we need to configure the GPIOA and the pin 0 as input before we can read data from it.

The program :


#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"

GPIO_InitTypeDef GPIO_InitStructure_Button;
GPIO_InitTypeDef GPIO_InitStructure;

void main(){
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//for buttons

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

/* Configure PD12, PD13, PD14 and PD15 in output pushpull mode */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13| GPIO_Pin_14| GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
GPIO_InitStructure_Button.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure_Button.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure_Button.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_Init(GPIOA,&GPIO_InitStructure_Button);
 int i;
        while(1){
                i = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0);
                GPIO_WriteBit(GPIOD,GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15,i);
        }
}







STM32F4DISCOVERY board

I got my STM32F4DISCOVERY board a few days ago and I'm so excited to try it.
This board is definitely one and unique board made by st for amateurs and professional to discover easily and with pleasure the strength of the STM32F4 series.

The board is really rich with features (copy past from the STM32F4DISCOVERY datasheet)
  1. STM32F407VGT6 microcontroller featuring 32-bit ARM Cortex-M4F core, 1 MB Flash, 192 KB RAM in an LQFP100 package
  2. On-board ST-LINK/V2 with selection mode switch to use the kit as a standalone ST-LINK/V2 (with SWD connector for programming and debugging)
  3. Board power supply: through USB bus or from an external 5 V supply voltage
  4. External application power supply: 3 V and 5 V
  5.  LIS302DL, ST MEMS motion sensor, 3-axis digital output accelerometer (Amazing !!!)
  6.   MP45DT02, ST MEMS audio sensor, omni-directional digital microphone
  7. CS43L22, audio DAC with integrated class D speaker driver
  8. Eight LEDs:LD1 (red/green) for USB communicationLD2 (red) for 3.3 V power onFour user LEDs, LD3 (orange), LD4 (green), LD5 (red) and LD6 (blue)2 USB OTG LEDs LD7 (green) VBus and LD8 (red) over-current
  9. Two push buttons (user and reset)
  10.  USB OTG FS with micro-AB connector (amazing for a microcontroller) 
  11. Extension header for all LQFP100 I/Os for quick connection to prototyping board and easy probing


This board can be used in many application with its DSP it can solve complex Digital signal functions used in filter computing plus it has the FPU (Floating point unit) that allows the STM32F4 to deal with floats up to 10exp-18 precision and that would be very useful in application that needs media processing or precision calculations.

I will post some tutorials talking about my experience with board.

Cheers ;)










dimanche 17 février 2013

Thoughts about my country

So what's wrong with Tunisia!! with such great talents spread all over the world with such an honorable history with such immense agriculture potential Tunisia falls in its greatness.
So many talents so many good minds so many charismatic people and so many diversity but it seems that all of this positive line qualities Tunisia doesn't seems to get use of it, but instead this diversity this democracy is just dividing us more and more.
About 12 million person are living now in Tunisia, but even with this relatively small number of population we have more than 200 categories of Tunisian people, salfi, nahthawi, cpr, pdp, joumhouri, masar, ili m3a te2sisii willi mouch m3ehom welli me3inouch bech itabe3,.....
It seems that our diversity is playing against us. It seems that our qualities is our enemies.
It seems that democracy is not the solution.

vendredi 8 février 2013

DC power supply


The need of static power supply

The need of power voltage supply is mandatory in any mechatronic application. For mobile mechatronic applications like robots, the power voltage supplier must be embedded with the application this can deliver many drawback like for example autonomy.
But when dealing with static mechatronic projects we can just get rid of the battery and use directly the domestic AC power supplier. because this supplier can deliver energy 24/7 with one drawback that this energy must be calibrated to be used in static mechatronic application witch are usually need a DC supply voltage.
In this article I'm going to show you how to create you own DC power supply.

Specifications 

INPUT : 220 V AC
OUTPUT: 5V DC / 1.5A

Principal functions:

 Our board change the 220V AC into 5V DC with a maximum operating current of 1.5A

Current protection : 


we need to protect the board from unpredictable current variation from the power supply or potential shunt that could be very dangerous and can harm our system. The obvious solution is to use a fuse.
The maximum needed current for mini mechatronic applications is 1A with a tolerance of 500mA so any current that exceeds 1.5A would be considered as dangerous to the board and the fuse must interfere. The choice is then a fuse with a normal operating current = 1.5A.


Galvanic isolation and Voltage decreasing

This part of the board is mainly responsible for decreasing the alternative voltage from 220V to 12V alternative current.
For this purpose we need a 220v 12V transformer that can assure both of the functions

Wave rectification


This part of the board is probably the most important, In fact in this part the alternative energy is transformed to a direct one. we need to eliminate the negative part of the wave or replace it with a positive wave.
For this purpose we need a full wave rectifier composed by 4 1N4001 Diodes:

Filtering and smoothing

The rectified wave still need to be more smoothed so I have to fill the gaps between the waves. To do so we need to add a capacitor that able to store voltage and release it in time to fill the gaps.
The specifications needed for our board are :
Vin :regulator input = 12V / Operating current = 1A
C = I * detlta(T)/delta(V) = 3333µF we take it as 4700µf or 2200µF

Voltage regulation

At this step we have a decent 12V DC but it's not really stable and we need to get the 5V DC To feed the electronics. For this purpose we have to add a 5V voltage regulator that can transform 12V to a stable 5v DC. The perfect choice is LM7805 witch is a 5V DC/DC regulator that is capable of supporting up to 1A witch is acceptable for the usual applications. It's recommended to add another filtering capacitor of 10mF in the output of the regulator to assure stabilization.


Integration of the hole design with Altium designer: