Wednesday, November 12, 2014

Interfacing DHT11 humidity and temperature sensor with PIC16F877A

After interfacing the DHT11 with Arduino uno board at the following post:
ARDUINO Humidity & Temperature Measurement Using DHT11 Sensor
Now we are going to see how to interface this sensor with microchip pic16f877a.
There are some descriptions of how this sensor work  in the above link.
The circuit:
The below picture shows the schematic diagram of our circuit, the LCD is 16x2 and crystal is 12MHz.



A brief description of the code:
The code is written using MikroC compiler.
 First we must send a start signal to the sensor, we do that by configuring the pic pin connected to the sensor as output, the mcu sends 0 for 18ms then sends 1 for 30us.
After sending start signal to the sensor, the sensor will send a response signal to the mcu. To detect this signal mcu pin must be configured as input.
When the sensor finishes the response signal, it begins sending humidity and temperature data serially.
If there is a problem with the sensor or there is no sensor connected to the circuit, the LCD displays "there is no response from the sensor". And if there is a problem in the sensor which means the values are incorrect the LCD displays "Check sum error".


This video shows temperature and humidity in my home at: 18:33 11/13/2014 :
 




// LCD module connections
 sbit LCD_RS at RB5_bit;
 sbit LCD_EN at RB4_bit;
 sbit LCD_D4 at RB3_bit;
 sbit LCD_D5 at RB2_bit;
 sbit LCD_D6 at RB1_bit;
 sbit LCD_D7 at RB0_bit;
 sbit LCD_RS_Direction at TRISB5_bit;
 sbit LCD_EN_Direction at TRISB4_bit;
 sbit LCD_D4_Direction at TRISB3_bit;
 sbit LCD_D5_Direction at TRISB2_bit;
 sbit LCD_D6_Direction at TRISB1_bit; 
 sbit LCD_D7_Direction at TRISB0_bit;
 // End LCD module connections
 char *text,mytext[4];
 unsigned char  a = 0, b = 0,i = 0,t1 = 0,t2 = 0,
               rh1 = 0,rh2 = 0,sum = 0;
 void StartSignal(){
 TRISD.F2 = 0;    //Configure RD2 as output
 PORTD.F2 = 0;    //RD2 sends 0 to the sensor
 delay_ms(18);
 PORTD.F2 = 1;    //RD2 sends 1 to the sensor
 delay_us(30);
 TRISD.F2 = 1;    //Configure RD2 as input
  }
 void CheckResponse(){
 a = 0;
 delay_us(40);
 if (PORTD.F2 == 0){
 delay_us(80);
 if (PORTD.F2 == 1)   a = 1;   delay_us(40);}
 }
 void ReadData(){
 for(b=0;b<8;b++){
 while(!PORTD.F2); //Wait until PORTD.F2 goes HIGH
 delay_us(30);
 if(PORTD.F2 == 0)    i&=~(1<<(7-b));  //Clear bit (7-b)
 else{i|= (1<<(7-b));               //Set bit (7-b)
 while(PORTD.F2);}  //Wait until PORTD.F2 goes LOW
 }
 }
 void main() {
 TRISB = 0;        //Configure PORTB as output
 PORTB = 0;        //Initial value of PORTB
 Lcd_Init();
 while(1){
 Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
 Lcd_Cmd(_LCD_CLEAR);             // clear LCD
  StartSignal();
  CheckResponse();
  if(a == 1){
  ReadData();
  rh1 =i;
  ReadData();
  rh2 =i;
  ReadData();
  t1 =i;
  ReadData();
  t2 =i;
  ReadData();
  sum = i;
  if(sum == rh1+rh2+t1+t2){
  text = "Temp:  .0C";
  Lcd_Out(1,6,text);
  text = "Humidity:  .0%";
  Lcd_Out(2,2,text);
  ByteToStr(t1,mytext);
  Lcd_Out(1,11,Ltrim(mytext));
  ByteToStr(rh1,mytext);
  Lcd_Out(2,11,Ltrim(mytext));}
  else{
  Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
  Lcd_Cmd(_LCD_CLEAR);             // clear LCD
  text = "Check sum error";
  Lcd_Out(1,1,text);}
  }
  else { 
  text="No response";
  Lcd_Out(1,3,text);
  text = "from the sensor";
  Lcd_Out(2,1,text);
  }
  delay_ms(2000);
  }
  }

Saturday, November 8, 2014

PIC16F877A LCD Example

This is just an example to show how to interface 16x2 lcd with pic16f877a. The lcd is going to display "PIC16F877A" in the the first line and "LCD Example" in the second line. The code is written using MikroC compiler.
The  circuit diagram and MikroC code are below:





// LCD module connections
sbit LCD_RS at RB5_bit;
sbit LCD_EN at RB4_bit;
sbit LCD_D4 at RB3_bit;
sbit LCD_D5 at RB2_bit;
sbit LCD_D6 at RB1_bit;
sbit LCD_D7 at RB0_bit;
sbit LCD_RS_Direction at TRISB5_bit;
sbit LCD_EN_Direction at TRISB4_bit;
sbit LCD_D4_Direction at TRISB3_bit;
sbit LCD_D5_Direction at TRISB2_bit;
sbit LCD_D6_Direction at TRISB1_bit;
sbit LCD_D7_Direction at TRISB0_bit;
// End LCD module connections
char *text;
void main() {
TRISB = 0;
PORTB = 0;
Lcd_Init();
Lcd_Cmd(_LCD_CURSOR_OFF);        // cursor off
Lcd_Cmd(_LCD_CLEAR);             // clear LCD
text = "PIC16F877A" ;
Lcd_Out(1,4,text);
text = "LCD Example";
Lcd_Out(2,4,text);
while(1);                     //infinite loop
}

Tuesday, November 4, 2014

Real Time Clock

Now, I'm going to work with real time clocks, for that I will use the integrated circuit DS1307serial real time clock. I will use this ic with Arduino uno board and also I have to return to the pic microcontroller chip PIC16F877A. For the pic mcu I will use Microc and the full codes and schematics will be available on the next posts.
The DS1307 provides clock and calender. The clock shows seconds, minutes and hours and the calender shows day, month and year. The ds1307 uses I2C serial interface to transfer information with the microcontroller. More information in its datasheet.


Sunday, November 2, 2014

Cd-Rom 3 phase Sensored BLDC Motor Arduino Controller

BLDC (brushless dc) motors are three phase dc motors, unlike the simple dc motors the bldc motors are more difficult to control. These motors are used in many applications for examples rc airplans and rc cars.






In this post we will see how to control cd-rom sensored BLDC motor using Arduino uno board. But first there are some things we should know in order to control the motor in easy way.
The bldc motor that we are going to use is sensored via hall effect sensors (position sensors) attached with the motor(3 sensors). Each sensor outputs digital high for 180 electrical degrees and low for the other 180 electrical degrees.these sensors are used to tell us where is the position of the motor, then when we know the position of the motor we will energize just tow windings (of three). The below figure shows how sensors outputs and the corresponding voltage applied to the motor:



The motor is driven by a 3 phase bridge which contains 6 mosfets like the figure below:



And for the bridge I used to run the motor visit this post below:
Three Phase BLDC Motor Bridge
We can run the bldc motor in the cw or ccw rotaion but the sensor of the cw rotaion is different from the sensor of the ccw direction. The tow tables below show the sensor and the coils that activated at each phase:


Also for more information for the hall effect sensors and how to test it visit this link:
The complete circuit is shown below:


The Arduino code is below:
I used timer 2 interrupt every about 30ms to read the analog value and generate the corresponding pwm signal. For the pwm I used PWM.h library to generate 20KHz easily. Also in the code there are tow functions one for forward rotation and the other for the backward rotation.

#include <PWM.h>
int32_t frequency = 20000; //pwm frequency in Hz
unsigned int n = 0, timer2_initial_value, s = 0;
void setup(){
  InitTimersSafe();
  bool success = SetPinFrequencySafe(9, frequency);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(13, OUTPUT);
  pinMode(0, INPUT);
  pinMode(1, INPUT);
  pinMode(2, INPUT);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, INPUT_PULLUP);
  // initialize timer2 interrupt for adc reading 
  noInterrupts();           // disable all interrupts
  TCCR2A = 0;
  TCCR2B = 0;
  timer2_initial_value = 0;  
  TCNT2 = timer2_initial_value;   // preload timer
  TCCR2B |= (1 << CS22) |(1 << CS21) | (1 << CS20); // 1024 prescaler 
  TIMSK2 |= (1 << TOIE2);   // enable timer overflow interrupt
  interrupts();             // enable all interrupts
}
 ISR(TIMER2_OVF_vect)        // interrupt service routine 
 {
  TCNT2 = timer2_initial_value;   // preload timer
  n++;
  if (n>20){
    n = 0;
   if (s != analogRead(A0)){
   s = analogRead(A0); 
  pwmWrite(9,s/4);}}
 }
int fwd(){
   while(1){
if (digitalRead(2)==1){
    if (digitalRead(1)==0){
      if (digitalRead(0)==1){
        digitalWrite(8,0);digitalWrite(7,0);digitalWrite(6,0);
        digitalWrite(5,1);digitalWrite(4,1);digitalWrite(3,0);}
      else {
        digitalWrite(8,1);digitalWrite(7,0);digitalWrite(6,0);
        digitalWrite(5,1);digitalWrite(4,0);digitalWrite(3,0);}}
        
     if (digitalRead(1)==1){
      if (digitalRead(0)==0){
        digitalWrite(8,1);digitalWrite(7,0);digitalWrite(6,0);
        digitalWrite(5,0);digitalWrite(4,0);digitalWrite(3,1);}}}
        
   
 if (digitalRead(2)==0){
    if (digitalRead(1)==1){
      if (digitalRead(0)==0){
        digitalWrite(8,0);digitalWrite(7,0);digitalWrite(6,1);
        digitalWrite(5,0);digitalWrite(4,0);digitalWrite(3,1);}
      else {
        digitalWrite(8,0);digitalWrite(7,1);digitalWrite(6,1);
        digitalWrite(5,0);digitalWrite(4,0);digitalWrite(3,0);}}
        
     if (digitalRead(1)==0){
      if (digitalRead(0)==1){
        digitalWrite(8,0);digitalWrite(7,1);digitalWrite(6,0);
        digitalWrite(5,0);digitalWrite(4,1);digitalWrite(3,0);}}}
   if (digitalRead(12)==0) break;}
}
 int bwd(){
   while(1){
if (digitalRead(2)==1){
    if (digitalRead(1)==0){
      if (digitalRead(0)==1){
        digitalWrite(8,0);digitalWrite(7,0);digitalWrite(6,1);
        digitalWrite(5,0);digitalWrite(4,0);digitalWrite(3,1);}
      else {
        digitalWrite(8,0);digitalWrite(7,1);digitalWrite(6,1);
        digitalWrite(5,0);digitalWrite(4,0);digitalWrite(3,0);}}
        
     if (digitalRead(1)==1){
      if (digitalRead(0)==0){
        digitalWrite(8,0);digitalWrite(7,1);digitalWrite(6,0);
        digitalWrite(5,0);digitalWrite(4,1);digitalWrite(3,0);}}}
        
   
 if (digitalRead(2)==0){
    if (digitalRead(1)==1){
      if (digitalRead(0)==0){
        digitalWrite(8,0);digitalWrite(7,0);digitalWrite(6,0);
        digitalWrite(5,1);digitalWrite(4,1);digitalWrite(3,0);}
      else {
        digitalWrite(8,1);digitalWrite(7,0);digitalWrite(6,0);
        digitalWrite(5,1);digitalWrite(4,0);digitalWrite(3,0);}}
        
     if (digitalRead(1)==0){
      if (digitalRead(0)==1){
        digitalWrite(8,1);digitalWrite(7,0);digitalWrite(6,0);
        digitalWrite(5,0);digitalWrite(4,0);digitalWrite(3,1);}}}
   if (digitalRead(12)==0) break;}
}
     
void loop(){
  digitalWrite(13, LOW);
  pwmWrite(9,s);
  digitalWrite(8,0);digitalWrite(7,0);digitalWrite(6,0);
  digitalWrite(5,0);digitalWrite(4,0);digitalWrite(3,0);
  if (digitalRead(10)==0) {digitalWrite(13, HIGH);bwd();}
  if (digitalRead(11)==0) {digitalWrite(13, HIGH);fwd();}
}


This videos shows my work:


Saturday, November 1, 2014

Sensored Cd-Rom BLDC Motor Hall Effect Sensors

In this post I will show how to test the hall effect sensors attached with the sensored bldc motor.
The hall effect sensors are necessary to know the position of the motor in order to energize just tow windings.
The hall effect sensor is a small IC has 4 pins in the cd-rom drive motor, vcc, gnd and the tow others are data pins.
This schematic diagram shows how to test the hall effect sensors:





This video shows how should it work: