Menu

all about electronic and microcontrollers
Showing posts with label Push Button. Show all posts
Showing posts with label Push Button. Show all posts

Tuesday, November 11, 2014

DS1307 [ RTC with Set Functions] & DS18B20 & MAX7219 [8 Digits]

Today I will show you how to display the values of RTC DS1307 and DS18B20 on six digits with seven segments driven by MAX7219. Obviously I designed a sort of menu (helped by three buttons) to be able to change the values on IC DS1307.
We have already explained, in previous projects, how works and communicate the IC DS1307 and MAX7219, so we will proceed further by developing electronic schematic and the software model.

Hardware setup:
I intend to display the clock and room temperature, on six digits with seven segment. The time will be displayed on digits for 5 seconds then for another 5 second it will be displayed the temperature and so on.
In my case, the clock and max7219 circuit are mounted separately on pcb.
Clock circuit is designed separately by me, but max7219 circuit is acquired from Mikroelektronika.
Electrical schematic is designed to include the complete circuit.
Physical realization is carried out on the breadboard with 2420 dots.




Video:

Circuit Diagram:
This schematic has a low difficulty level. Microcontroller used is PIC16F876A.
S1 is the master reset button, R1 is the resistor of pull-up button.
Crystal quartz used has 8Mhz.
ICSP connector is used to program the microcontroller (I use PICKIT2).
R1, R3, R5, R10 are pull-up resistors.
Diode D1 has a protective role.
All three buttons are part of: incrementing hour, incrementing minute and enter.
Communication between DS1307 and circuit board "breadboard" is established by five pins as follow (GND, SQW, SCL, SDA, 5VDC). SQW pin is not used in this project.
We used a battery of 3vcc to ensure the functioning of the internal clock of DS1307 IC's, even if it is disconnected from 5 VDC.
Communication between max7219 circuit and microcontroller is set by pins RC0 (CS), RC1 (CLK) and RC2 (MOSI) used for software SPI protocol.
IF you are planning to use the "Serial 7-Seg 8-Digit Board" from mikroelektronika, it is necessary to set the appropriate switches on the DIP switch SW1 to the ON position:
  • Switch 1- MOSI 
  • Switch 4 - SCK 
  • Switch 7 - CS 
Port RC7 ensure communication with DS18B20 sensor.
The capacitors C8-C11 serve as power filtering. Preferably is that the capacitors filters to be as near by ICs.


Electronic schematic is built in Eagle Cad, free version.

Software:
The program is written in mikroC Pro for PIC (version v6.4.0).
Below is my software version:
/*
'*******************************************************************************
'  Project name: Real Time Clock [DS1307 with Set Functions] & DS18B20 & max7219
'  Description:
'          With this experiment we wish to succed the next task:
'          Display on 6 digits with 7 segment leds, the clock and the room 
'          temperature (in Celsius Degree).
'          Setting the time helped by three buttons: hours, minutes and enter.
'
'          The sign "-" to the negative temperature and the hundreds for the
'          temperature value are displayed just if are used.
'          The time is displayed 5 second then he display the temperature value 
'          in Celsius Degrees for other 5 seconds and the loop goes to infinite.
'          Our clock, displays as shown below(but just in display time,
'          not in set mode).
'          Ex. of viewing in 7 segment display,6 digits :
'          Display time, mode:             Display temperature mode:
'               __________                         _________
'              |__24.59.59|     ~5 sec delay      |____23.6C|
'
'          Hardware configuration is:
'             IC ds1307 is connected with our microcontroller trough RC3=SCL,
'             RC4=SDA (I2C Connections), 
'             max7219 as follow:(CS at RC0, CLK at RC1 and MOSI(SDO) at RC2)
'             DS18B20 is assigned to RC7,
'             RB0,RB1 and RB3 are assigned to the buttons
'             Buttons Menu: RB0= Enter,  (It goes to set functions or exit from set functions)
'                           RB1= Minutes,
'                           RB2= Hours,
'
'  Written by:
'          Aureliu Raducu Macovei, 2014.
'  Test configuration:
'    MCU:                        PIC16F876A;
'    Test.Board:                 WB-106 Breadboard 2420 dots;
'    SW:                         MikroC PRO for PIC 2013 (version v6.4.0);
'  Configuration Word:
'    Oscillator:                 HS (8Mhz)on pins 9 and 10;
'    Watchdog Timer:             OFF;
'    Power up Timer:             OFF;
'    Browun Out Detect:          ON;
'    Low Voltage Program:        Disabled;
'    Data EE Read Protect:       OFF;
'    Flash Program Write:        Write Protection OFF;
'    Background Debug:           Disabled;
'    Code Protect:               OFF
'*******************************************************************************
*/

// Software SPI module connections for max7219
sbit SoftSpi_SDI at RC6_bit;
sbit SoftSpi_SDO at RC2_bit;                   // MOSI
sbit SoftSpi_CLK at RC1_bit;
sbit Chip_Select at RC0_bit;

sbit SoftSpi_SDI_Direction at TRISC6_bit;
sbit SoftSpi_SDO_Direction at TRISC2_bit;
sbit SoftSpi_CLK_Direction at TRISC1_bit;
sbit Chip_Select_Direction at TrisC0_bit;
// End Software SPI module connections for max7219

const unsigned short TEMP_RESOLUTION = 12;     //This is resolution for ds18b20
unsigned temp;

unsigned sec, min1, hr, week_day, day, mn, year;
unsigned short mask(unsigned short num)
{
 switch (num)               // Define switch cases
 {
  case  0 : return 0x7E;    // 0 for those values please study the datasheet max7219
  case  1 : return 0x30;    // 1
  case  2 : return 0x6D;    // 2
  case  3 : return 0x79;    // 3
  case  4 : return 0x33;    // 4
  case  5 : return 0x5B;    // 5
  case  6 : return 0x5F;    // 6
  case  7 : return 0x70;    // 7
  case  8 : return 0x7F;    // 8
  case  9 : return 0x7B;    // 9
  case 10 : return 0x01;    // Symbol '-'
  case 11 : return 0x00;    // Blank
  case 12 : return 0x80;    // Comma "," symbol
  case 13 : return 0x43;    // C
  } //case end
}

void max7219_init()
{
 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x09);      // Decode-Mode Register
 Soft_Spi_write(0x00);      // No decode for digits 7–0
 Chip_Select = 1;           // DESELECT MAX
 
 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x0A);      // Intensity Register Format
 Soft_Spi_write(0x01);      // Segment luminosity intensity set to 3/32
 Chip_Select = 1;           // DESELECT MAX

 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x0B);      // Scan-Limit Register Format
 Soft_Spi_write(0x05);      // Display digits 0 1 2 3 4 5
 Chip_Select = 1;           // DESELECT MAX

 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x0C);      // Shutdown Register Format
 Soft_Spi_write(0x01);      // Normal Operation
 Chip_Select = 1;           // DESELECT MAX

 Chip_Select = 0;           // SELECT MAX
 Soft_Spi_write(0x00);      // No-Op
 Soft_Spi_write(0xFF);      // No test
 Chip_Select = 1;           // DESELECT MAX
}

char minute2,hour2;
void max7219_display_set_mode(unsigned minute2, unsigned hour2)
{
 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(6);                              // digit 6
 Soft_Spi_write(mask((hour2/10)%10));            // assign tens of hours
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(5);                              // digit 5
 Soft_Spi_write ((mask(hour2%10))+ mask(12));    // assign units of hours
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(4);                              // digit 4
 Soft_Spi_write(mask((minute2/10)%10));          // assign tens of minutes
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(3);                              // digit 3
 Soft_Spi_write((mask(minute2%10))+mask(12));    // assign units of minutes
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;           // select max7219
 Soft_Spi_write(2);         // digit 2
 Soft_Spi_write (0);        // set as blank
 Chip_Select = 1;           // deselect max7219

 Chip_Select = 0;           // select max7219
 Soft_Spi_write(1);         // digit 1
 Soft_Spi_write (0);        // set as blank
 Chip_Select = 1;           // deselect max7219
}

void max7219_display (unsigned sec, unsigned min, unsigned hr)
{
 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(6);                              // digit 6
 Soft_Spi_write(mask((hr/10)%10));               // assign tens of hours
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(5);                              // digit 5
 Soft_Spi_write ((mask(hr%10))+ mask(12));       // assign units of hours
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(4);                              // digit 4
 Soft_Spi_write(mask((min/10)%10));              // assign tens of minutes
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(3);                              // digit 3
 Soft_Spi_write((mask(min%10))+mask(12));        // assign units of minutes
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(2);                              // digit 2
 Soft_Spi_write (mask((sec/10)%10));             // assign tens of seconds
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(1);                              // digit 1
 Soft_Spi_write (mask(sec%10));                  // assign units of seconds
 Chip_Select = 1;                                // deselect max7219
}

//-----Reads time and date information from RTC (DS1307)
void Read_Time(unsigned *sec, unsigned *min, unsigned *hr, unsigned *week_day, 
               unsigned *day, unsigned *mn, unsigned *year)
{
 I2C1_Start();
 I2C1_Wr(0xD0);
 I2C1_Wr(0);
 I2C1_Repeated_Start();
 I2C1_Wr(0xD1);
 *sec =I2C1_Rd(1);
 *min =I2C1_Rd(1);
 *hr =I2C1_Rd(1);
 *week_day =I2C1_Rd(1);
 *day =I2C1_Rd(1);
 *mn =I2C1_Rd(1);
 *year =I2C1_Rd(0);
 I2C1_Stop();
}//~

//-----------------start write time routine------------------
void Write_Time(unsigned minute, unsigned hour)
{
 unsigned tmp1, tmp2;
 
 tmp1 = minute / 10;           // assign values from variables
 tmp2 = minute % 10;           // assign values from variables
 minute = tmp1 * 16 + tmp2;    // assign values from variables

 tmp1 = hour / 10;             // assign values from variables
 tmp2 = hour % 10;             // assign values from variables
 hour = tmp1 * 16 + tmp2;      // assign values from variables

 I2C1_Start();          // issue start signal
 I2C1_Wr(0xD0);         // address DS1307
 I2C1_Wr(0);            // start from word at address (REG0)
 I2C1_Wr(0x80);         // write $80 to REG0. (pause counter + 0 sec)
 I2C1_Wr(minute);       // write minutes word to (REG1)
 I2C1_Wr(hour);         // write hours word (24-hours mode)(REG2)
 I2C1_Wr(0x00);         // write 6 - Saturday (REG3)
 I2C1_Wr(0x00);         // write 14 to date word (REG4)
 I2C1_Wr(0x00);         // write 5 (May) to month word (REG5)
 I2C1_Wr(0x00);         // write 01 to year word (REG6)
 I2C1_Wr(0x80);         // write SQW/Out value (REG7)
 I2C1_Stop();           // issue stop signal

 I2C1_Start();          // issue start signal
 I2C1_Wr(0xD0);         // address DS1307
 I2C1_Wr(0);            // start from word at address 0
 I2C1_Wr(0);            // write 0 to REG0 (enable counting + 0 sec)
 I2C1_Stop();           // issue stop signal
}
//-----------------end write time routine------------------

//-------------------- Formats date and time
void Transform_Time(unsigned *sec, unsigned *min, unsigned *hr, 
                    unsigned *week_day, unsigned *day, unsigned *mn, unsigned *year)
{
 *sec  =  ((*sec & 0x70) >> 4)*10 + (*sec & 0x0F);
 *min  =  ((*min & 0xF0) >> 4)*10 + (*min & 0x0F);
 *hr   =  ((*hr & 0x30) >> 4)*10 + (*hr & 0x0F);
 *week_day =(*week_day & 0x07);
 *day  =  ((*day & 0xF0) >> 4)*10 + (*day & 0x0F);
 *mn   =  ((*mn & 0x10) >> 4)*10 + (*mn & 0x0F);
 *year =  ((*year & 0xF0)>>4)*10+(*year & 0x0F);
}//~

void blink_min()
{
 Chip_Select = 0;               // select max7219
 Soft_Spi_write(4);             // digit 4
 Soft_Spi_write(0);             // set as blank
 Chip_Select = 1;               // deselect max7219

 Chip_Select = 0;               // select max7219
 Soft_Spi_write(3);             // digit 3
 Soft_Spi_write(0);             // set as blank
 Chip_Select = 1;

 delay_ms(50);                               // 50ms delay
 max7219_display_set_mode(minute2,hour2);    // display those values
 delay_ms(50);                               // 50ms delay
}
void blink_hr()
{
 Chip_Select = 0;               // select max7219
 Soft_Spi_write(6);             // digit 6
 Soft_Spi_write(0);             // set as blank
 Chip_Select = 1;               // deselect max7219

 Chip_Select = 0;               // select max7219
 Soft_Spi_write(5);             // digit 5
 Soft_Spi_write(0);             // set as blank
 Chip_Select = 1;               // deselect max7219

 delay_ms(50);                               // 50ms delay
 max7219_display_set_mode(minute2,hour2);    // display those values
 delay_ms(50);                               // 50ms delay
}

char setuptime=0;
unsigned count=0;
void Press_Switch()
{
 if(button(&portb,0,1,0))        // check if button RB0 is pressed
 {
  Delay_ms(200);
  setuptime = !setuptime;        // switch that value;

  if(setuptime)
  {
  hour2=hr;
  minute2=min1;
  max7219_display_set_mode(minute2,hour2);   // display those values
  }
  else
  {
   hr=hour2;
   min1=minute2;
   Write_Time(min1,hr);
   max7219_display_set_mode(minute2,hour2);
  }
 }
 
 if(Setuptime)
 {
  if(button(&portb,1,1,0))
  {
   Delay_ms(150);
   minute2++;
   if(minute2 > 59)
   minute2=0;
   blink_min();
   }
  if(button(&portb,2,1,0))
  {
   Delay_ms(150);
   hour2++;
   if(hour2 > 23)
   hour2=0;
   blink_hr();
   }
  }
}

// Starts ds18b20 declarations
void ds18b20(unsigned int temp2write)
{
 const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
 unsigned temp_whole;
 unsigned int temp_fraction;
 unsigned short isNegative = 0x00;
 // Check if temperature is negative
 if (temp2write & 0x8000)
 {
  temp2write = ~temp2write + 1;
  isNegative = 1;
  }
 // Extract temp_whole
 temp_whole = temp2write >> RES_SHIFT ;

 // Extract temp_fraction and convert it to unsigned int
 temp_fraction  = temp2write << (4-RES_SHIFT);
 temp_fraction &= 0x000F;
 temp_fraction *= 625;          // 625 for ds18b20 and 5000 for ds1820;

 Chip_Select = 0;               // select max7219
 Soft_Spi_write(1);             // digit 1
 Soft_Spi_write(mask(13));      // write C symbol
 Chip_Select = 1;               // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(2);                              // Set digit number 3
 Soft_Spi_write(mask(temp_fraction /1000));      // assigne as fraction
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(3);                              // Set digit number 3
 Soft_Spi_write((mask(temp_whole%10))+mask(12)); // Assigne as ones
 Chip_Select = 1;                                // deselect max7219

 Chip_Select = 0;                                // select max7219
 Soft_Spi_write(4);                              // Set digit number 4
 Soft_Spi_write (mask((temp_whole/10)%10));      // Assigne as tens
 Chip_Select = 1;                                // deselect max7219
  
 if (isNegative == 1)
 {
  Chip_Select = 0;               // select max7219
  Soft_Spi_write(5);             // Set digit number 5
  Soft_Spi_write(mask(10));      // Assigne as symbol "-"
  Chip_Select = 1;               // deselect max7219
  }
 else
 {
  if(isNegative ==0 && temp_whole/100==0)
  {
   Chip_Select = 0;               // select max7219
   Soft_Spi_write(5);             // Set digit number 5
   Soft_Spi_write(mask(11));      // Assign as blank
   Chip_Select = 1;               // deselect max7219
   }
  else
  {
   Chip_Select = 0;                         // select max7219
   Soft_Spi_write(5);                       // Set digit number 5
   Soft_Spi_write(mask(temp_whole/100));    // Assign the hundreds
   Chip_Select = 1;                         // deselect max7219
   }
  }
  
 Chip_Select = 0;                 // select max7219
 Soft_Spi_write(6);               // Set digit number 6
 Soft_Spi_write(0);               // Assign value 0
 Chip_Select = 1;                 // deselect max7219
}// End ds18b20 declarations

void interrupt()
{
 if(setuptime)
 count=0;
 else
 count++;                  // Interrupt causes count to be incremented by 1
 TMR0 = 0;                 // Timer TMR0 is returned its initial value
 INTCON = 0x20;            // Bit T0IE is set, bit T0IF is cleared
}

void main() 
{
 CMCON  |= 7;                  // Disable Comparators
 OPTION_REG = 0x84;            // Prescaler Rate Selected at 1:32;
 TMR0 = 0;                     // Reset timer;
 INTCON = 0xA0;                // Disable interrupt PEIE,INTE,RBIE,T0IE

 Chip_Select_Direction = 0;    // Set RC0 pin as output
 Soft_Spi_init();              // Initialize software SPI module
 max7219_init();               // initialize  max7219
 I2C1_Init(100000);            // initialize I2C

 while (1)                     // and here, our while loope
 {
  Press_Switch();
     
  if(!setuptime)
  {
   if(count<=1400)                    // ~ 5 seconds
   {
    Read_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year);      // read time from RTC(DS1307)
    Transform_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // format date and time
    max7219_display(sec,min1, hr);
    }
   else
   {
    if(count>1400)                     // ~ 5 seconds
    {
     //Perform temperature reading
     Ow_Reset(&PORTC, 7);          // Onewire reset signal
     Ow_Write(&PORTC, 7, 0xCC);    // Issue command SKIP_ROM
     Ow_Write(&PORTC, 7, 0x44);    // Issue command CONVERT_T
     
     Ow_Reset(&PORTC, 7);
     Ow_Write(&PORTC, 7, 0xCC);    // Issue command SKIP_ROM
     Ow_Write(&PORTC, 7, 0xBE);    // Issue command READ_SCRATCHPAD

     temp =  Ow_Read(&PORTC, 7);   // Next Read Temperature and Read Byte 0 from Scratchpad
     // Then read Byte 1 from Scratchpad and shift 8 bit left and add the Byte 0
     temp = (Ow_Read(&PORTC, 7) << 8) + temp;
     ds18b20(temp);                  //Format and display result on digits.
     }
    }
   if(count>2800)
   count = 0;
   }
  }
}

Saturday, March 29, 2014

Real Time Clock [DS1307 with Set Functions] & DS18B20

Hello dear fellows, today I will share with you this amazing project which will highlights what can be done with DS1307.
The Real Time Clock (RTC) chip produced by Maxim is a popular and relatively low cost solution for creating a room clock.

Features:
  1. Real-Time Clock (RTC) Counts Seconds, Minutes, Hours, Date of the Month, Month, Day of the week, and Year with Leap-Year Compensation Valid Up to 2100.
  2. 56-Byte, Battery-Backed, General-Purpose RAM with Unlimited Writes.
  3.  I2C Serial Interface.
  4. Programmable Square-Wave Output Signal.
  5.  Automatic Power-Fail Detect and Switch Circuitry.
  6. Consumes Less than 500nA in Battery-Backup Mode with Oscillator Running.
  7.  Operating temperature range for commercial use only: 0°C to +70°C.
  8. Optional Industrial Temperature Range: -40°C to +85°C.
  9. Available in 8-Pin Plastic DIP or SO.
As can be seen from it's datasheet, the communications are achieved via I2C (designed by Philips) protocol.

Hardware setup:
In the current article I intend to display the clock information and room temperature, on the LCD with 2x16 characters. Also trough four buttons, I will try to be able to set all the times variable, stored, in DS1307 chip.
Physical realization is carried out on the breadboard with 2420 dots.





Trough this video I would like to let you know precisely, how are things going.


Below I present the timing diagram for I2C signal transmitted on pins 5-6 of the DS1307.

Data Transfer on I2C Serial Bus.

Pin Configurations.
The diagram block.


For more details, please study the DS1307 datasheet.

Circuit Diagram:
Difficulty level of the electronic scheme, is low. The microcontroller used is PIC16F876A.
S1 is the master reset button, R1 is the resistor of pull-up button.
Cristal quartz by 8 MHz, is used.
ICSP connector is used to program the microcontroller.
Trough R7 we can adjust the contrast for LCD with 2x16 characters.
R6 adjusts the current through the LED LCD (light intensity of it).
R2-R5, R8-R10 are resistors for pull-up.

I personally designed the physical pcb circuit for DS1307, through the five pins,  pcb communicate with the breadboard in this way (GND, SQW, SCL, SDA, 5VDC). In this project i didn't use SQW pin.


The electronic scheme is built in Eagle Cad , free version.

Software:
The program is written in mikroC Pro for PIC 2013 (version v6.0.0).
Below is my software version:
/*
'*******************************************************************************
'  Project name: Real Time Clock [DS1307 with Set Functions] & DS18B20
'  Description:
'          Trough the current experiment we wish to succed the next task:
'          Display on LCD 2x16 character the clock and room temperature.
'          Setting trough four buttons: the minutes, hours, date of the month,
'          month, day of the week, and year.
'
'          Our clock displays as shown below(but just in display time,
'          not in set mode).
'          Ex. of viewing on 2x16 LCD characters:
'          Display time, mode:             Set time, mode (cursor on):
'          ------------------              ------------------
'          |Sat, 03 Dec 2011|              |Sat, 03 12  2011|
'          |21:32:03 +26,1*C|              |21:32:03        |
'          ------------------              ------------------
'
'          Hardware configuration is:
'             IC ds1307 is connected with our microcontroller trough RC3=SCL,
'             RC4=SDA (I2C Connections), RB0,RB1,RB4-RB7 are assigned to LCD (2x16)
'             DS18B20 is assigned to RC7,
'             Buttons Menu: RC0= Increment value,
'                           RC1= Decrement value,
'                           RC2= Change cursor position,
'                           RC5= Enter.(It goes to set functions or exit from set
'                                functions)
'  Written by:
'          Aureliu Raducu Macovei, 2014.
'  Test configuration:
'    MCU:                        PIC16F876A;
'    Test.Board:                 WB-106 Breadboard 2420 dots;
'    SW:                         MikroC PRO for PIC 2013 (version v6.0.0);
'  Configuration Word:
'    Oscillator:                 HS (8Mhz)on pins 9 and 10;
'    Watchdog Timer:             OFF;
'    Power up Timer:             OFF;
'    Browun Out Detect:          ON;
'    Low Voltage Program:        Disabled;
'    Data EE Read Protect:       OFF;
'    Flash Program Write:        Write Protection OFF;
'    Background Debug:           Disabled;
'    Code Protect:               OFF
'*******************************************************************************
*/

// LCD module connections
sbit LCD_RS at RB0_bit;                 // LCD_RS assigned to PORT RB0;
sbit LCD_EN at RB1_bit;                 // LCD_EN assigned to PORT RB1;
sbit LCD_D4 at RB4_bit;                 // LCD_D4 assigned to PORT RB4;
sbit LCD_D5 at RB5_bit;                 // LCD_D5 assigned to PORT RB5;
sbit LCD_D6 at RB6_bit;                 // LCD_D6 assigned to PORT RB6;
sbit LCD_D7 at RB7_bit;                 // LCD_D7 assigned to PORT RB7;

sbit LCD_RS_Direction at TRISB0_bit;    // LCD_RS assigned to TRIS B0;
sbit LCD_EN_Direction at TRISB1_bit;    // LCD_EN assigned to TRIS B1;
sbit LCD_D4_Direction at TRISB4_bit;    // LCD_D4 assigned to TRIS B4;
sbit LCD_D5_Direction at TRISB5_bit;    // LCD_D5 assigned to TRIS B5;
sbit LCD_D6_Direction at TRISB6_bit;    // LCD_D6 assigned to TRIS B6;
sbit LCD_D7_Direction at TRISB7_bit;    // LCD_D7 assigned to TRIS B7;
// End LCD module connections

unsigned char sec,min1,hr,week_day,day,mn,year;
//--------------------- Reads time and date information from RTC (DS1307)
void Read_Time(char *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year)
{
 I2C1_Start();                    // Issue start signal
 I2C1_Wr(0xD0);                   // Address DS1307, see DS1307 datasheet
 I2C1_Wr(0);                      // Start from address 0
 I2C1_Repeated_Start();           // Issue repeated start signal
 I2C1_Wr(0xD1);                   // Address DS1307 for reading R/W=1
 *sec =I2C1_Rd(1);                // Read seconds byte
 *min =I2C1_Rd(1);                // Read minutes byte
 *hr =I2C1_Rd(1);                 // Read hours byte
 *week_day =I2C1_Rd(1);           // Read week day byte
 *day =I2C1_Rd(1);                // Read day byte
 *mn =I2C1_Rd(1);                 // Read mn byte
 *year =I2C1_Rd(0);               // Read Year byte
 I2C1_Stop();                     // Issue stop signal
}
//-----------------write time routine------------------
void Write_Time(char minute, char hour ,char weekday,char day,char month,char year)
{
 char tmp1, tmp2;

 tmp1 = minute / 10;               //Write tens of minute
 tmp2 = minute % 10;               //Write unit of minute
 minute = tmp1 * 16 + tmp2;        //Includes all value

 tmp1 = hour / 10;                 //Write tens of hour
 tmp2 = hour % 10;                 //Write unit of hour
 hour = tmp1 * 16 + tmp2;          //Includes all value

 tmp1 = weekday / 10;              //Write tens of weekday
 tmp2 =  weekday % 10;             //Write unit of weekday
 weekday = tmp1 *16 +tmp2;         //Includes all value

 tmp1 = day / 10;                  //Write tens of day
 tmp2 =  day % 10;                 //Write unit of day
 day = tmp1 *16 +tmp2;             //Includes all value

 tmp1 = month / 10;                //Write tens of month
 tmp2 =  month % 10;               //Write unit of month
 month = tmp1 *16 +tmp2;           //Includes all value

 tmp1 = year / 10;                 //Write tens of year
 tmp2 =  year % 10;                //Write unit of year
 year = tmp1 *16 +tmp2;            //Includes all value

 I2C1_Start();          // issue start signal
 I2C1_Wr(0xD0);         // address DS1307
 I2C1_Wr(0);            // start from word at address (REG0)
 I2C1_Wr(0x80);         // write $80 to REG0. (pause counter + 0 sec)
 I2C1_Wr(minute);       // write minutes word to (REG1)
 I2C1_Wr(hour);         // write hours word (24-hours mode)(REG2)
 I2C1_Wr(weekday);      // write 6 - Saturday (REG3)
 I2C1_Wr(day);          // write 14 to date word (REG4)
 I2C1_Wr(month);        // write 5 (May) to month word (REG5)
 I2C1_Wr(year);         // write 01 to year word (REG6)
 I2C1_Wr(0x80);         // write SQW/Out value (REG7)
 I2C1_Stop();           // issue stop signal

 I2C1_Start();          // issue start signal
 I2C1_Wr(0xD0);         // address DS1307
 I2C1_Wr(0);            // start from word at address 0
 I2C1_Wr(0);            // write 0 to REG0 (enable counting + 0 sec)
 I2C1_Stop();           // issue stop signal
}
//-------------------- Formats date and time---------------------
void Transform_Time(char  *sec, char *min, char *hr, char *week_day, char *day, char *mn, char *year)
{
  *sec  =  ((*sec & 0x70) >> 4)*10 + (*sec & 0x0F);
  *min  =  ((*min & 0xF0) >> 4)*10 + (*min & 0x0F);
  *hr   =  ((*hr & 0x30) >> 4)*10 + (*hr & 0x0F);
  *week_day =(*week_day & 0x07);
  *day  =  ((*day & 0xF0) >> 4)*10 + (*day & 0x0F);
  *mn   =  ((*mn & 0x10) >> 4)*10 + (*mn & 0x0F);
  *year =  ((*year & 0xF0)>>4)*10+(*year & 0x0F);
 }
//------------------------Display time---------------------------
char *txt,*mny;
void Display_Time(char sec, char min, char hr, char week_day, char day, char mn, char year)
{
 switch(week_day)
 {
  case 1: txt="Mon"; break;       // Monday;
  case 2: txt="Tue"; break;       // Tuesday;
  case 3: txt="Wed"; break;       // Wednesday;
  case 4: txt="Thu"; break;       // Thursday;
  case 5: txt="Fri"; break;       // Friday;
  case 6: txt="Sat"; break;       // Saturday;
  case 7: txt="Sun"; break;       // Sunday;
  }

 LCD_Out(1, 1,txt);
 LCD_chr(1, 4,',');

 switch(mn)
 {
  case  1: mny="Jan"; break;
  case  2: mny="Feb"; break;
  case  3: mny="Mar"; break;
  case  4: mny="Apr"; break;
  case  5: mny="May"; break;
  case  6: mny="Jun"; break;
  case  7: mny="Jul"; break;
  case  8: mny="Aug"; break;
  case  9: mny="Sep"; break;
  case 10: mny="Oct"; break;
  case 11: mny="Nov"; break;
  case 12: mny="Dec"; break;
  }

 Lcd_Chr(1, 6, (day / 10) + 48);    // Print tens digit of day variable
 Lcd_Chr(1, 7, (day % 10) + 48);    // Print oness digit of day variable
 Lcd_Out(1, 9,mny);
 Lcd_out(1,13,"20");
 Lcd_Chr(1,15, (year / 10)  + 48);  // we can set year 00-99 [tens]
 Lcd_Chr(1,16, (year % 10)  + 48);  // we can set year 00-99 [ones]
 Lcd_Chr(2, 1, (hr / 10)  + 48);
 Lcd_Chr(2, 2, (hr % 10)  + 48);
 Lcd_Chr(2, 3,':');
 Lcd_Chr(2, 4, (min / 10) + 48);
 Lcd_Chr(2, 5, (min % 10) + 48);
 Lcd_Chr(2, 6,':');
 Lcd_Chr(2, 7, (sec / 10) + 48);
 Lcd_Chr(2, 8, (sec % 10) + 48);
 }
//-------------------Display Time in Set mode--------------------
char minute1,hour1,weekday1,month1;
char minute,hour,weekday,day1,month,year1;
void Display_Time_SetMode()
{
 switch(weekday1)
 {
  case 1: txt="Mon"; break;       // Monday;
  case 2: txt="Tue"; break;       // Tuesday;
  case 3: txt="Wed"; break;       // Wednesday;
  case 4: txt="Thu"; break;       // Thursday;
  case 5: txt="Fri"; break;       // Friday;
  case 6: txt="Sat"; break;       // Saturday;
  case 7: txt="Sun"; break;       // Sunday;
  }

 LCD_Out(1, 1,txt);
 LCD_chr(1, 4,',');

 Lcd_Chr(1, 6, (day1 / 10)   + 48);    // Print tens digit of day variable
 Lcd_Chr(1, 7, (day1 % 10)   + 48);    // Print oness digit of day variable
 Lcd_chr(1,10, (month1 / 10) + 48);    // Print tens digit of month variable
 Lcd_chr(1,11, (month1 % 10) + 48);    // Print oness digit of month variable
 Lcd_out(1,13,"20");
 Lcd_Chr(1,15, (year1 / 10)  + 48);    // Print tens digit of year variable
 Lcd_Chr(1,16, (year1 % 10)  + 48);    // Print oness digit of year variable
 Lcd_Chr(2, 1, (hour1 / 10)  + 48);    // Print tens digit of hour variable
 Lcd_Chr(2, 2, (hour1 % 10)  + 48);    // Print oness digit of hour variable
 Lcd_Chr(2, 3,':');
 Lcd_Chr(2, 4, (minute1 / 10) + 48);   // Print tens digit of minute variable
 Lcd_Chr(2, 5, (minute1 % 10) + 48);   // Print oness digit of minute variable
 Lcd_Chr(2, 6,':');
 Lcd_Chr(2, 7, (0 / 10) + 48);
 Lcd_Chr(2, 8, (0 % 10) + 48);
}

char SPos;
//----------------------Move cursor routine----------------------
char index;
void movecursor()
{
 char i,moveto;
 if(SPos==0)
 lcd_cmd(_lcd_first_row);  // set weekday;
 if(SPos==1)
 lcd_cmd(_lcd_first_row);  // set day;
 if(SPos==2)
 lcd_cmd(_lcd_first_row);  // set month;
 if(SPos==3)
 lcd_cmd(_lcd_first_row);  // set year;
 if(SPos==4)
 lcd_cmd(_lcd_second_row); // set hours;
 if(SPos==5)
 lcd_cmd(_lcd_second_row); // set minutes;

 moveto = 2;
 switch(index)
 {
  case 0: moveto = 2;break;
  case 1: moveto = 6;break;
  case 2: moveto =10;break;
  case 3: moveto =15;break;
  case 4: moveto = 1;break;
  case 5: moveto = 4;break;
  }
  for(i=1; i<= moveto; i++)
  lcd_cmd(_lcd_move_cursor_right);
}
//------------Start Buttons routine--------------;
char setuptime=0;
void Press_Switch()
{
 if(setuptime)
 {
  if(Button(&portc,2,1,0))         // If buttons at port c2 is pressed
  {
   delay_ms(200);
   SPos++;
   if(SPos>5)
   SPos=0;
   index++;
   if(index > 5)
   index=0;
   movecursor();
   }
  //-----------------------------case mode to set all values---------------------
  switch(SPos)
  {
   case 0: if(button(&portc,0,1,0))       // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            weekday1++;
            if(weekday1 > 7)
            weekday1=1;
            Display_Time_SetMode();
            index=0;
            movecursor();
            }

           if(button(&portc,1,1,0))       // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            weekday1--;
            if(weekday1 < 1)
            weekday1=7;
            Display_Time_SetMode();
            index=0;
            movecursor();
            }
           break;
   case 1: if(button(&portc,0,1,0))       // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            day1++;
            if(day1 > 31)
            day1 = 1;
            Display_Time_SetMode();
            index=1;
            movecursor();
            }

           if(button(&portc,1,1,0))        // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            day1--;
            if(day1 < 1)
            day1 = 31;
            Display_Time_SetMode();
            index=1;
            movecursor();
            }
           break;
   case 2: if(button(&portc,0,1,0))         // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            month1++;
            if(month1 > 12)
            month1 = 1;
            Display_Time_SetMode();
            index=2;
            movecursor();
            }

           if(button(&portc,1,1,0))          // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            month1--;
            if(month1 < 1)
            month1 = 12;
            Display_Time_SetMode();
            index=2;
            movecursor();
            }
           break;
   case 3: if(button(&portc,0,1,0))           // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            year1++;
            if(year1 > 99)
            year1 = 1;
            Display_Time_SetMode();
            index=3;
            movecursor();
            }

           if(button(&portc,1,1,0))           // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            year1--;
            if(year1 < 1)
            year1 = 99;
            Display_Time_SetMode();
            index=3;
            movecursor();
            }
           break;
   case 4: if(button(&portc,0,1,0))            // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            hour1++;
            if(hour1 > 23)
            hour1 = 0;
            Display_Time_SetMode();
            index=4;
            movecursor();
            }

           if(button(&portc,1,1,0))            // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            hour1--;
            if(hour1 > 23)
            hour1 = 0;
            Display_Time_SetMode();
            index=4;
            movecursor();
            }
           break;
   case 5: if(button(&portc,0,1,0))            // If buttons at port c0 is pressed
           {
            Delay_ms(200);
            minute1++;
            if(minute1 > 59)
            minute1 = 0;
            Display_Time_SetMode();
            index=5;
            movecursor();
            }

           if(button(&portc,1,1,0))             // If buttons at port c1 is pressed
           {
            Delay_ms(200);
            minute1--;
            if(minute1 > 59)
            minute1 = 0;
            Display_Time_SetMode();
            index=5;
            movecursor();
            }
           break;
   }                            // end "if is in switch mode"
  }                             // end "if is in setup"

 if(button(&portc,5,1,0))                      // If buttons at port c5 is pressed
 {
  Delay_ms(200);
  setuptime = !setuptime;
  if(SetupTime)
  {
   lcd_cmd(_lcd_clear);
   lcd_cmd(_lcd_blink_cursor_on);
   weekday1=week_day;
   hour1=hr;
   minute1=min1;
   day1=day;
   month1=mn;
   year1=year;
   Display_Time_SetMode();
   SPos=0;
   index=0;
   movecursor();
   }
   else
   {
   Lcd_Cmd(_Lcd_clear);
   lcd_cmd(_lcd_cursor_off);
   weekday=weekday1;
   hour=hour1;
   minute=minute1;
   day=day1;
   month=month1;
   year=year1;
   Write_time(minute,hour,weekday,day,month,year);
   }
  }
 }
//----------------------End Buttons Routine-------------------
//------------------Temperature sensor routines---------------
const unsigned short TEMP_RESOLUTION = 12;     // 9 for DS1820 and 12 for DS18B20
char *text = "000,0";
unsigned temp;
void Display_Temperature(unsigned int temp2write)
{
 const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
 char temp_whole;
 unsigned int temp_fraction;
 unsigned short isNegative = 0x00;

 // Check if temperature is negative
 if (temp2write & 0x8000)
 {
  text[0] = '-';
  temp2write = ~temp2write + 1;
  isNegative = 1;
  }
  // Extract temp_whole
  temp_whole = temp2write >> RES_SHIFT ;
  // Convert temp_whole to characters
  if (!isNegative){
  if (temp_whole/100)
  text[0] = temp_whole/100  + 48;                // Extract hundreds digit
  else
  text[0] = '+';
  }
  text[1] = (temp_whole/10)%10 + 48;             // Extract tens digit
  text[2] =  temp_whole%10     + 48;             // Extract ones digit
  // Extract temp_fraction and convert it to unsigned int
  temp_fraction  = temp2write << (4-RES_SHIFT);
  temp_fraction &= 0x000F;
  temp_fraction *= 625;
  // Convert temp_fraction to characters
  text[4] =  temp_fraction/1000 + 48;         // Extract thousands digit
  // Print temperature on LCD
  Lcd_Out(2, 10,text);
  lcd_chr(2, 15,0xB2);                        // Ascii code for degrees symbol;
  Lcd_chr(2, 16,'C');                         // Show symbol "C" from Celsius
}
//----------------Read and display Temperature from DS18B20--------------
void Read18b20()
{
 //--- Perform temperature reading
 Ow_Reset(&PORTC, 7);                           // Onewire reset signal;
 Ow_Write(&PORTC, 7, 0xCC);                     // 0xCC Issue command SKIP_ROM;
 Ow_Write(&PORTC, 7, 0x44);                     // Issue command CONVERT_T;
 Delay_us(700);                                 // delay 0,7s (required for signal
                                                // processing);
 Ow_Reset(&PORTC, 7);                           // Onewire reset signal;
 Ow_Write(&PORTC, 7, 0xCC);                     // Issue command SKIP_ROM;
 Ow_Write(&PORTC, 7, 0xBE);                     // Issue command READ_SCRATCHPAD;

 temp = Ow_Read(&PORTC, 7);                     // Next Read Temperature, read Byte
                                                // 0 from Scratchpad;
 temp = (Ow_Read(&PORTC, 7) << 8) + temp;       // Then read Byte 1 from Scratchpad
                                                // and shift 8 bit left and add the Byte 0;
 //--- Format and display result on Lcd
 Display_Temperature(temp);                     // Call Display_Temperature;
 }
//------------------Temperature sensor routines---------------
void Init_Main()
{
 CMCON |=7;             //TURN OFF ANALOGUE COMPARATOR AND MAKE PORTA TO DIGITAL I/O;

 I2C1_Init(100000);         // initialize I2C
 Lcd_Init();                // Initialize LCD
 Lcd_Cmd(_LCD_CLEAR);       // Clear LCD display
 Lcd_Cmd(_LCD_CURSOR_OFF);  // Turn cursor off

 Display_Time(sec, min1, hr, week_day, day, mn, year);

 !setuptime=1;
 index=0;
 SPos=0;
 }
//-----------------Here we have the Main Routine----------------
void main()
{
 Init_Main();
 while (1)                                                 // While loop
 {
  Read_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year);      // read time from RTC(DS1307)
  Transform_Time(&sec,&min1,&hr,&week_day,&day,&mn,&year); // Transform time
  Press_Switch();                                          // Check buttons;
  if(!setuptime)
  {
   Display_Time(sec, min1, hr, week_day, day, mn, year);
   Read18b20();
   }
  }
}

Tuesday, December 14, 2010

Lesson nr.20-Sound generation

Hardware setup:


Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:


Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.20:
'          Sound generation.
'  Done by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          In this experiment we will work with sounds.
'          I'll show how to generate and make sound helped by microcontroller 
'          and some buttons.
'          Communication with the buzzer will be performed  at PORT RB3 ( as PWM mode).
'          The Push buttons are connected to PORT RA4 (generates Tone1), RA6
'          (generates Tone2) and RA7(generates melody2). 
'          Of course we need pull-up resistors (4k7 is required).
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  Configuration Word
'    Oscillator:                 INTOSC:I/O on RA.6, I/O on RA.7
'    Watchdog Timer:             OFF
'    Power up Timer:             Disabled
'    Master Clear Enable:        Enabled
'    Browun Out Detect:          Enabled
'    Low Voltage Program:        Disabled
'    Data EE Read Protect:       Disabled
'    Code Protect:               OFF
'*******************************************************************************
*/
void Tone1()
{
 Sound_Play(5000, 1000);         // Frequency = 659Hz, duration = 250ms
}

void Tone2() 
{
 Sound_Play(4000, 1000);         // Frequency = 698Hz, duration = 250ms
 }

void Tone3() 
{
 Sound_Play(3000, 1000);         // Frequency = 784Hz, duration = 250ms
 }

void Melody1()                  // Make funny melody 1;
{
 Tone1(); Tone2(); Tone3();
 Tone3(); Tone2(); Tone1();
 Tone1(); Tone3(); Tone2();
 Tone3(); Tone2(); Tone1(); Tone3();
 Tone1(); Tone2(); Tone3();
 Tone3(); Tone1(); Tone2(); Tone2(); Tone1();
 }

void ToneA()                    // Tone A;
{
 Sound_Play(1618, 50);          // (frequency, duration)
}

void ToneB()                    // Tone B;
{
 Sound_Play(1918, 50);          // (frequency, duration)
}

void ToneC()                    // Tone C;
{
 Sound_Play(2212, 50);          // (frequency, duration)
}

void Melody2()                  // Make funny melody 2;
{
 unsigned short i;
 for (i = 12; i > 0; i--)
 {
  ToneA(); ToneB(); ToneC();
  }
 }

void main() 
{
 CMCON |=7;                     // Disable comparator
 TRISB = 0xF0;                  // Pins RB7-RB4 are configured as inputs,
                                // RB3 is configured as an output
 Sound_Init(&PORTB, 3);
 Sound_Play(5000,100);          // Start with this song (frequency, duration)

 while (1)                      // infinite loop
 {
  if (Button(&PORTA,4,1,0))     // RB4 generates Tone1
  Tone1();
  
  if (Button(&PORTA,6,1,0))     // RB6 generates Tone2
  Tone2();

  if (Button(&PORTA,7,1,0))     // RA7 generates melody 2
  {
   Melody2();
   Delay_ms(1500);              // Delay 1,5s
   Melody2();
   Delay_ms(1500);              // Delay 1,5s
   Melody2();
   }
  }
}

Lesson nr.19-Using Internal EEPROM Memory

Hardware setup:



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:


Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.19:
'          Using Internal EEPROM Memory.
'  Done by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          In this experiment we will work with internal EEPROM Memory
'          and I'll show how to write and read information on it helped by a little
'          menu displayed on the LCD.
'          Communication with LCD will be performed through 4-bits and connections
'          is made as follows: D4 with RB0, D5 with RB1, D6 with RB2, D7 with RB3;
'                              RS with RB4 and EN with RB5.
'          The Push buttons are connected to PORT RA4 (for read), RA6(for write) and RA7
'          (for delete). Of course we need pull-up resistors (4k7 is required).
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  Configuration Word
'    Oscillator:                 INTOSC:I/O on RA.6, I/O on RA.7
'    Watchdog Timer:             OFF
'    Power up Timer:             Disabled
'    Master Clear Enable:        Enabled
'    Browun Out Detect:          Enabled
'    Low Voltage Program:        Disabled
'    Data EE Read Protect:       Disabled
'    Code Protect:               OFF
'*******************************************************************************
*/
// LCD module connections
sbit LCD_RS at RB4_bit;                 // LCD_RS assigned to PORT RB4;
sbit LCD_EN at RB5_bit;                 // LCD_EN assigned to PORT RB5;
sbit LCD_D4 at RB0_bit;                 // LCD_D4 assigned to PORT RB0;
sbit LCD_D5 at RB1_bit;                 // LCD_D5 assigned to PORT RB1;
sbit LCD_D6 at RB2_bit;                 // LCD_D6 assigned to PORT RB2;
sbit LCD_D7 at RB3_bit;                 // LCD_D7 assigned to PORT RB3;

sbit LCD_RS_Direction at TRISB4_bit;    // LCD_RS assigned to TRIS B4;
sbit LCD_EN_Direction at TRISB5_bit;    // LCD_EN assigned to TRIS B5;
sbit LCD_D4_Direction at TRISB0_bit;    // LCD_D4 assigned to TRIS B0;
sbit LCD_D5_Direction at TRISB1_bit;    // LCD_D5 assigned to TRIS B1;
sbit LCD_D6_Direction at TRISB2_bit;    // LCD_D6 assigned to TRIS B2;
sbit LCD_D7_Direction at TRISB3_bit;    // LCD_D7 assigned to TRIS B3;
// End LCD module connections

// Define Messages
char message1[] = "Switch1: Read";
char message2[] = "Switch2: Write";
char message3[] = "Switch3: Erase";
char message4[] = "EEPROM_Write";
char message5[] = "EEPROM_Read ";
char message6[] = "EEPROM ERASED";
char message7[] = "Internal";
char message8[] = "EEPROM";
char message9[] = "*";
char message10[] = "**";
char message11[] = "***";

char digit[] = "00000000000000";
unsigned short  ii, All ;

void read_eeprom()
{
 if (Button(&PORTA, 4, 1, 0))           // Detect logical one to zero;
 {    
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,3,message5);
  Lcd_Out(2,7,message9);
  delay_ms(1000);                       // Delay 1s
  Lcd_Out(2,7,message10);
  delay_ms(1000);                       // Delay 1s
  Lcd_Out(2,7,message11);
  delay_ms(1000);                       // Delay 1s
  for (ii=0; ii<=13; ii++)
  {
   All = EEPROM_Read(0x00+ii);          // Start EEPROM Location,
   digit[ii] = All+65;                  // Look at ascii table
   }
  Lcd_Out(2,2,digit);
  delay_ms(5000);                       // Delay 5s
  }
 }

void write_eeprom()
{
 if (Button(&PORTA, 6, 1, 0))           // Detect logical one to zero
 {
  for (ii=0; ii<14; ii++)
  EEPROM_Write(0x00+ii,ii);
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,3,message4);
  Lcd_Out(2,7,message9);
  delay_ms(1000);
  Lcd_Out(2,7,message10);
  delay_ms(1000);
  Lcd_Out(2,7,message11);
  delay_ms(1000);
  }
 }

void delete_eeprom()
{
 if (Button(&PORTA, 7, 1, 0))           // Detect logical one to zero
 {     
  Lcd_Cmd(_LCD_CLEAR);
  Lcd_Out(1,3,message6);
  Lcd_Out(2,7,message9);
  delay_ms(1000);
  Lcd_Out(2,7,message10);
  delay_ms(1000);
  Lcd_Out(2,7,message11);
  delay_ms(1000);
  for (ii=0; ii<=13; ii++)
  EEPROM_Write(0x00+ii,0x0e);
  }
 }

void main() {
CMCON  |= 7;                            // Disable Comparators
TRISA4_bit = 1;
TRISA6_bit = 1;
TRISA7_bit = 1;
TRISB = 0;
PORTB = 0;
Lcd_Init();
Lcd_Cmd(_LCD_CLEAR);                    // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF);               // Cursor off
Lcd_Out(1,5,message7);
Lcd_Out(2,6,message8);
delay_ms(3000);                         // Delay 3s
do {
    Lcd_cmd(_LCD_Clear);
    Lcd_Out(1,2,message1);              // Write message1 in 1st row
    delay_ms(1000);
    read_eeprom();
    write_eeprom();
    delete_eeprom();
    Lcd_cmd(_LCD_Clear);
    Lcd_Out(1,2,message2);
    delay_ms(1000);
    read_eeprom();
    write_eeprom();
    delete_eeprom();
    Lcd_cmd(_LCD_Clear);
    Lcd_Out(1,2,message3);
    delay_ms(1000);
    read_eeprom();
    write_eeprom();
    delete_eeprom();
    } while(1);
}

Tuesday, November 30, 2010

Lesson nr.17-Alphanumeric LCD and Push Button

Hardware setup:
In this experiment we will work with alphanumeric LCD and push button.
Communication with LCD will be performed through 4-bits and connections is made as follows: D4 with RB0, D5 with RB1, D6 with RB2, D7 with RB3, RS with RB4 and EN with RB5. The Push button is connected to PORT RA4 (for increment) and PORT RA6 (for decrement). Of course both button have pull-up resistors (4k7).
To make this project more interesting , you can reach from 0000 to 9999 by pressing the button.



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:


Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.17:
'          Alphanumeric LCD and Push Button.
'  Done by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          In this experiment we will work with alphanumeric LCD and push button.
'          Communication with LCD will be performed through 4-bits and connections
'          is made as follows: D4 with RB0, D5 with RB1, D6 with RB2, D7 with RB3;
'                              RS with RB4 and EN with RB5.
'          The Push button is connected to PORT RA4 (for increment) and PORT RA6
'          (for decrement). Of course both button have pull-up resistors (4k7).
'          To make this project more interesting , you can reach from 0000 to 9999 
'          by pressing the button.
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  Configuration Word
'    Oscillator:                 INTOSC:I/O on RA.6, I/O on RA.7
'    Watchdog Timer:             OFF
'    Power up Timer:             Disabled
'    Master Clear Enable:        Enabled
'    Browun Out Detect:          Enabled
'    Low Voltage Program:        Disabled
'    Data EE Read Protect:       Disabled
'    Code Protect:               OFF
'*******************************************************************************
*/
// LCD module connections
sbit LCD_RS at RB4_bit;                 // LCD_RS assigned to PORT RB4;
sbit LCD_EN at RB5_bit;                 // LCD_EN assigned to PORT RB5;
sbit LCD_D4 at RB0_bit;                 // LCD_D4 assigned to PORT RB0;
sbit LCD_D5 at RB1_bit;                 // LCD_D5 assigned to PORT RB1;
sbit LCD_D6 at RB2_bit;                 // LCD_D6 assigned to PORT RB2;
sbit LCD_D7 at RB3_bit;                 // LCD_D7 assigned to PORT RB3;

sbit LCD_RS_Direction at TRISB4_bit;    // LCD_RS assigned to TRIS B4;
sbit LCD_EN_Direction at TRISB5_bit;    // LCD_EN assigned to TRIS B5;
sbit LCD_D4_Direction at TRISB0_bit;    // LCD_D4 assigned to TRIS B0;
sbit LCD_D5_Direction at TRISB1_bit;    // LCD_D5 assigned to TRIS B1;
sbit LCD_D6_Direction at TRISB2_bit;    // LCD_D6 assigned to TRIS B2;
sbit LCD_D7_Direction at TRISB3_bit;    // LCD_D7 assigned to TRIS B3;
// End LCD module connections

char Message1[]="LCD and Button";       // Message for line1;
unsigned int number = 0;

char *digit = "0000";

void Display_init()   // define display_init;
{                    
 digit[0] = number/1000 + 48;           // thousands digit;
 digit[1] = (number/100)%10 +48;        // hundreds digit;
 digit[2] = (number/10)%10 + 48;        // tens digit;
 digit[3] = number%10 +48;              // unit digit;
 Lcd_Out(2,7,digit);                    // display on LCD from column 2, character 7;
}

void main()                             // main;
{
 CMCON |= 7;                            // turn off analogue comparator and make PORTA to digital I/O;
 TRISA6_bit = 1;                        // make PORT RA6 as input for button;
 TRISA7_bit = 1;                        // make PORT RA7 as input for button;
 PORTA = 0;                             // Turn ON PORTA;
 TRISB = 0;                             // Set PORTB direction to be output;
 PORTB = 0;                             // Turn ON PORTB;

 Lcd_init();                            // LCD Initialization;
 Lcd_cmd(_LCD_CLEAR);                   // Clear LCD;
 Lcd_cmd(_LCD_CURSOR_OFF);              // Cursor mode, off;
 Lcd_out(1,2,Message1);                 // display message1 from column 1, character 3;

 do{
    if(Button(&PORTA,4,1,0)){
                             Delay_ms(200);    // If button is pressed, delay 0,2s and increment "number" with 1;
                             number = number +1;
                             }
    if(Button(&PORTA,6,1,0)){
                             Delay_ms(200);    // If button is pressed, delay 0,2s and decrement "number" with 1;
                             number = number -1;
                             }
    if (number > 9999u)                 // if it's more than 9999 go to 0;
    number = 0;
    display_init();                     // call display_init();
    } while(1);                         // infinite loop;
 }                                      // end.

Sunday, October 17, 2010

Lesson nr.13-7Segment and Push Button

Hardware setup:
Today Lesson is different from the last one, by the presence of two buttons and manually increment .
All 7-segment displays are connected to PORTB (RB0..RB7, segment A to RB0, segment B to RB1, etc.) with refresh via pins RA0..RA3 on PORTA.
If button on RA6 is presed the current number will be incremented by "1" and if button on RA7 is pressed the current number will be decremented by "1". Minimum number is 0000 and maximum number is 9999.



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:



Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.13:
'          Push Button & 7 Segment Display
'  Done by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          This code demonstrates  displaying number on four 7-segment display (common
'          cathode), in multiplex mode. All 7-segment displays are connected to PORTB
'          (RB0..RB7, segment A to RB0, segment B to RB1, etc.) with refresh via pins
'          RA0..RA3 on PORTA. If button on RA6 is presed the current number will be
'          incremented by "1" and if button on RA7 is pressed the current number will
'          be decremented by "1".
'
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         mikroC PRO for PIC
'  Configuration Word
'    Oscillator:                 INTOSC:I/O on RA.6, I/O on RA.7
'    Watchdog Timer:             OFF
'    Power up Timer:             Disabled
'    Master Clear Enable:        Enabled
'    Browun Out Detect:          Enabled
'    Low Voltage Program:        Disabled
'    Data EE Read Protect:       Disabled
'    Code Protect:               OFF
'*******************************************************************************
*/
//***********Header*************/
unsigned short mask(unsigned short num)
{
 switch (num) 
 {
  case 0 : return 0x3F;
  case 1 : return 0x06;
  case 2 : return 0x5B;
  case 3 : return 0x4F;
  case 4 : return 0x66;
  case 5 : return 0x6D;
  case 6 : return 0x7D;
  case 7 : return 0x07;
  case 8 : return 0x7F;
  case 9 : return 0x6F;
  }
}
/*******Endless mask***********/
unsigned short shifter, portb_index;
unsigned int digit, number;
unsigned short portb_array[4];

void interrupt()
{
 PORTA = 0;                           // Turn off all 7seg. displays;
 PORTB = portb_array[portb_index];    // Bring appropriate value to PORTB;
 PORTA = shifter;                     // Turn on appropriate 7seg. display;

 //move shifter to next digit;
 shifter <<= 1;
 if(shifter > 15u)
 shifter = 1;

 //increment portb_index;
 portb_index ++ ;
 if (portb_index > 3u)
 portb_index = 0;                     //turn on 1st, turn off 2nd 7 seg.;
 TMR0 = 0;                            //reset TIMER0 value;
 INTCON = 0x20;                       //clear T0IF, Bit T0IF=0, T0IE=1;
 }

void main()
{
 CMCON |= 7;                          // Set AN pins to Digital I/O;
 OPTION_REG = 0x80;                   // Set timer TMR0;
 digit = 0;
 portb_index = 0;
 shifter = 1;
 TMR0 = 0;
 INTCON = 0xA0;                       // Disable interrupt PEIE,INTE,RBIE,T0IE
 TRISA = 0;
 TRISA6_bit = 1;
 TRISA7_bit = 1;                      // All port A pins are configured as outputs
 PORTA = 0;                           // Turn off displays
 TRISB = 0;                           // All port D pins are configured as outputs
 PORTB = 0;                           // Turn off all display segments
 
 number = 0;                          //initial value;
 
 do {
     if(Button(&PORTA,6,1,0)){
                              Delay_ms(200);
                              digit++ ;
                              number = number +1;
                              PORTB = number;
                              }
     if(Button(&PORTA,7,1,0)){
                              Delay_ms(200);
                              digit = digit -1;
                              number = number -1;
                              PORTB = number;
                              }
     if (number > 9999u)
     number = 0;

     digit = number % 10u;            //extract ones digit;
     portb_array[0] = mask(digit);    //and store it to PORTB array;
     digit = (number / 10u) % 10u;    //extract tens digit;
     portb_array[1] = mask(digit);    //and store it to PORTB array;
     digit = (number / 100u) % 10u;   //extract hundreds digit;
     portb_array[2] = mask(digit);    //and store it to PORTB array;
     digit = number / 1000u;          //extract thousands digit;
     portb_array[3] = mask(digit);    //and store it to PORTB array;
     } while(1);                      //Endless loop;
}                                     //End.

Lesson nr.07-PWM & Push Button

Hardware setup:
In this experiment we will use the CCP1 as a PWM to control the power to a L.E.D. PWM stands for the Pulse Width Modulation where the width of a digital waveform is varied to control the power delivered to a load (in this case an L.E.D). The underlying principle in the whole process is that the average power delivered is directly proportional to the modulation duty cycle. The term duty cycle describes the proportion of on time to the regular interval or period of time; a low duty cycle corresponds to low power, because the power is off for most of the time. Duty cycle is expressed in percent, 100% being fully on and 0% means off.


Trough  hardware configuration of the microcontroller we will deduct to use the PORT RB3 as PWM output.
Button S1 and (pull-up) resistance with value of 4.7 K will provide the manual reset mode to the microcontroller.
Buttons S2 and S3 will vary the width form of our signal.
ICSP connector provides the connection between the programmer (PicKit 2) and microcontroller (PIC16F628A).



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:


Software:
Here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.07:
'          PWM & Push Button
'  Written by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          In this experiment we will show how to work with module CCP1 as PWM mode.
'          The PORT RB3 is used for this experiment (as output, for a led)
'          and RA6-RA7 (as imput, for buttons).
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  Configuration Word
'    Oscillator:                 INTOSC:I/O on RA.6, I/O on RA.7
'    Watchdog Timer:             OFF
'    Power up Timer:             Disabled
'    Master Clear Enable:        Enabled
'    Browun Out Detect:          Enabled
'    Low Voltage Program:        Disabled
'    Data EE Read Protect:       Disabled
'    Code Protect:               OFF
'*******************************************************************************
*/
unsigned short last_duty, current_duty;
void main()                 // main;
{
 CMCON |= 7;                // turn off analogue comparator and make PORTA to digital I/O;
 trisb3_bit = 0;            // make rb3 as output;
 portb = 0;                 // turn off LEDs on PORTB;
 current_duty = 0;          // Initial value of variable current_duty;
 last_duty = 0;             // Reset variable last_duty;
 pwm1_init(5000);           // PWM module initialization (5KHz);
 pwm1_start();              // Start PWM1 module;
 pwm1_set_duty(last_duty);
 do {
     while(last_duty>0<255){
                            if (Button(&PORTA, 6,1,0))
                            last_duty = last_duty +2;       // If the button connected to 
                                                            // RA0 is pressed
                            Pwm1_Set_Duty(last_duty);
                            delay_ms(100);

                            if (Button(&PORTA, 7,1,0))
                            last_duty = last_duty -2;       // If the pressed button is 
                                                            // connected to RA1
                            Pwm1_Set_Duty(last_duty);
                            delay_ms(100);
                            }
     delay_ms(200);                       // 200mS delay
     } while(1);                          // Do forever;
}                                         // End.

Lesson nr.06-Push Button

Hardware setup:
In this experiment we will make a demonstration with button library. The PORTB is used for this experiment (as output, for a leds) and RA6 (as imput, for button S2).
As usualy, button S1 and (pull-up) resistance with value of 4.7 K will provide the manual reset mode to the microcontroller. This arangement provides a standard schematic when we whant to include a button as input, current mode is with pull-up resistance, but also exist and with pull-down resistance which will not be used in our experiments, at least for the moment.
ICSP connector provides the connection between the programmer (PicKit 2) and microcontroller (PIC16F628A).



Circuit Diagram:
For those who want to build it on their own breadboard or other platform, here is the electronic scheme built in Eagle Cad, free version:


Software:
Here's a page from Button Library that specify buttons routines:


And as usualy, here is the C program written for MikroC PRO for PIC 2010 (version v4.15).
/*
'*******************************************************************************
'  Lesson nr.06:
'          Push Button
'  Written by:
'          Aureliu Raducu Macovei, 2010.
'  Description:
'          In this experiment we will make a demonstration with button library
'          The PORTB is used for this experiment (as output, for a leds)
'          and RA6 (as imput, for button).
'  Test configuration:
'    MCU:                        PIC16F628A
'    Test.Board:                 WB-106 Breadboard 2420 dots
'    SW:                         MikroC PRO for PIC 2010 (version v4.15)
'  Configuration Word
'    Oscillator:                 INTOSC:I/O on RA.6, I/O on RA.7
'    Watchdog Timer:             OFF
'    Power up Timer:             Disabled
'    Master Clear Enable:        Enabled
'    Browun Out Detect:          Enabled
'    Low Voltage Program:        Disabled
'    Data EE Read Protect:       Disabled
'    Code Protect:               OFF
'*******************************************************************************
*/
unsigned short oldstate;
void main()
{                                     // Main;
 TRISB = 0;                           // Set PORTB direction to be output;
 PORTB = 0xFF;                        // Turn OFF LEDs on PORTA;

 TRISA6_bit = 1;                      // Set PORT RB1 input for button;
 oldstate = 0;                        // Define value of oldstate;

do {
    if (Button(&PORTA,6,1,1)) oldstate = 1;
    Delay_ms(100);                                              //delay for prevent crash
    if (oldstate &&Button(&PORTA,6,1,0)) {
                                          PORTB = ~PORTB;       //invert state of PORTB
                                          oldstate = 0;
                                          }
    } while(1);                                                 //Infinite loop.
}