I2c bus for ds1307 For Basic PRO Compiler

Summary of I2c bus for ds1307 For Basic PRO Compiler


This article presents a PIC16F877-based automated water pump controller using Basic programming. It features real-time clock management via I2C, an LCD interface for displaying time and status, and five programmable time slots to automatically start and stop the pump based on sensor input. The system includes debouncing logic for buttons and handles standby modes when sensors are inactive.

Parts used in Automated Water Pump Controller:

  • PIC16F877 Microcontroller
  • LCD Display Module
  • I2C Real-Time Clock (RTC) Module
  • Input Buttons (S1 through S6)
  • Sensor Input (PORTC.0)
  • Relay/Control Output for Pump
  • 4MHz Oscillator
Include "modedefs.bas" 
@ Device PIC16F877,XT_OSC,WDT_off,PWRT_off,PROTECT_off ,BOD_Off
define  adc_bits 8
define  osc 4
DEFINE  LCD_DREG PORTD
DEFINE  LCD_DBIT 4
DEFINE  LCD_RSREG PORTD
DEFINE  LCD_RSBIT 1
DEFINE  LCD_EREG PORTD
DEFINE  LCD_EBIT 0

 S1      VAR PORTA.0 'set mode 
 S2      VAR PORTA.1 'set hour 0-23
 S3      VAR PORTA.2 'set minute 0-59
 S4      VAR PORTA.3 'set second 0-59
 s5      var portA.4 'set day 0-6
 s6      var portA.5 'set date 0-31
 sensor  var portc.0 'set month 0-12
 pump    var portc.1 'set year  0-99

  address con $00 
  cont    con $D0  
  sec     var byte
  minute  var byte 
  hour    var byte  
  d0      var byte 
  d1      var byte 
  hr      var byte 
  mn      var byte 
  ss      var byte 
  h_on    var byte[6] 
  m_on    var byte[6]
  h_off   var byte[6]
  m_off   var byte[6]
  comp    var byte[24]
  disp    var byte    
  sda     var portc.4 
  scl     var portc.3 
  low     portD.2 

TRISA = $FF  
TRISB = $00 
trisc = $01

 adcon1 = 7 
 hr = 0 
 mn = 0 
 ss = 0
 disp = 0

start:
   if sensor=0 and pump = 0 then 
        pause 6000 
         if sensor=0 and pump = 0then    
        pause 1000 
           gosub stand
       endif
    endif

    if (s1=0 and s2=0) then 
        pause 2000 
         if (s1=0 and s2=0) then            
           pause 1000 
           gosub setting
         endif
     endif

     if (s3=0 and s4=0) then 
        pause 2000 
         if (s3=0 and s4=0) then             
           pause 1000 
          gosub set_work
         endif
     endif

    gosub read_setpoint 
    gosub read_time 
    gosub display_time
    gosub comp_work 
goto start 
end 

  setting: 
     lcdout $fe,1,"Set Time" 
     pause 3000 
     lcdout $fe,1 
     hour   = 00 
     minute = 00 
     sec    = 00 

     gosub display_time
     gosub set_time      
  return 

set_work: 
     lcdout $fe,1,"Set_Point" 
     pause 3000 
     lcdout $fe,1 
     pause 10
     gosub set_point 
     pause 50    
  return 
set_point:
     if  s6=1  then
          IF  s1=0  Then  
            Pause 200
            if disp >= 4  then
               disp = 0               
            else   
            disp = disp + 1
            pause 150                          
            EndIF
          endif                                                                        
         gosub w_case          
         Pause 10 
         goto set_point
     endif 
    gosub start    
return

w_case:
 BRANCH disp,[t0,t1,t2,t3,t4]
 pause 100
return

t0:    
        if (s2=0) then         
        pause 50 
        comp[0] = comp[0]+1 
        if comp[0] > 23 then comp[0] = 0 
        d0 = comp[0] dig 0:d1 = comp[0] dig 1 
        d1 = d1<< 4 
        h_on[0] = d1|d0 
        pause 150
        endif

        if (s3=0) then         
        pause 50 
        comp[1] = comp[1]+1 
        if comp[1] > 59 then comp[1] = 0 
        d0 = comp[1] dig 0:d1 = comp[1] dig 1 
        d1 = d1<< 4 
        m_on[0] = d1|d0
        pause 150
        endif

        if(s4=0) then         
         pause 50 
         comp[2] = comp[2]+1 
         if comp[2] > 23 then comp[2] = 0 
         d0 = comp[2] dig 0:d1 = comp[2] dig 1 
         d1 = d1<< 4 
         h_off[0] = d1|d0
         pause 150
        endif

        if(s5=0) then         
         pause 50 
         comp[3] = comp[3]+1 
         if comp[3] > 59 then comp[3] = 0 
         d0 = comp[3] dig 0:d1 = comp[3] dig 1 
         d1 = d1<< 4 
         m_off[0] = d1|d0
         pause 150
        endif                           
       pause 20 
       gosub write_setpoint
       Lcdout $fe,1,"T0= ",hex2 h_on[0],":",hex2 m_on[0]," ",hex2 h_off[0],":",hex2 m_off[0]                   

return

t1:    
        if (s2=0) then         
        pause 50 
        comp[4] = comp[4]+1 
        if comp[4] > 23 then comp[4] = 0 
        d0 = comp[4] dig 0:d1 = comp[4] dig 1 
        d1 = d1<< 4 
        h_on[1] = d1|d0 
        pause 150
        endif

        if (s3=0) then         
        pause 50 
        comp[5] = comp[5]+1 
        if comp[5] > 59 then comp[5] = 0 
        d0 = comp[5] dig 0:d1 = comp[5] dig 1 
        d1 = d1<< 4 
        m_on[1] = d1|d0
        pause 150
        endif

        if(s4=0) then         
         pause 50 
         comp[6] = comp[6]+1 
         if comp[6] > 23 then comp[6] = 0 
         d0 = comp[6] dig 0:d1 = comp[6] dig 1 
         d1 = d1<< 4 
         h_off[1] = d1|d0
         pause 150
        endif

        if(s5=0) then         
         pause 50 
         comp[7] = comp[7]+1 
         if comp[7] > 59 then comp[7] = 0 
         d0 = comp[7] dig 0:d1 = comp[7] dig 1 
         d1 = d1<< 4 
         m_off[1] = d1|d0
         pause 150
        endif                           
       pause 20
       gosub write_setpoint             
  Lcdout $fe,1,"T1= ",hex2 h_on[1],":",hex2 m_on[1]," ",hex2 h_off[1],":",hex2 m_off[1]    

return 

t2:    
        if (s2=0) then         
        pause 50 
        comp[8] = comp[8]+1 
        if comp[8] > 23 then comp[8] = 0 
        d0 = comp[8] dig 0:d1 = comp[8] dig 1 
        d1 = d1<< 4 
        h_on[2] = d1|d0 
        pause 150
        endif

        if (s3=0) then         
        pause 50 
        comp[9] = comp[9]+1 
        if comp[9] > 59 then comp[9] = 0 
        d0 = comp[9] dig 0:d1 = comp[9] dig 1 
        d1 = d1<< 4 
        m_on[2] = d1|d0
        pause 150
        endif

        if(s4=0) then         
         pause 50 
         comp[10] = comp[10]+1 
         if comp[10] > 23 then comp[10] = 0 
         d0 = comp[10] dig 0:d1 = comp[10] dig 1 
         d1 = d1<< 4 
         h_off[2] = d1|d0
         pause 150
        endif

        if(s5=0) then         
         pause 50 
         comp[11] = comp[11]+1 
         if comp[11] > 59 then comp[11] = 0 
         d0 = comp[11] dig 0:d1 = comp[11] dig 1 
         d1 = d1<< 4 
         m_off[2] = d1|d0
         pause 150
        endif                           
       pause 20 
       gosub write_setpoint            
       Lcdout $fe,1,"T2= ",hex2 h_on[2],":",hex2 m_on[2]," ",hex2 h_off[2],":",hex2 m_off[2]        
return 

t3:    
        if (s2=0) then         
        pause 50 
        comp[12] = comp[12]+1 
        if comp[12] > 23 then comp[12] = 0 
        d0 = comp[12] dig 0:d1 = comp[12] dig 1 
        d1 = d1<< 4 
        h_on[3] = d1|d0 
        pause 150
        endif

        if (s3=0) then         
        pause 50 
        comp[13] = comp[13]+1 
        if comp[13] > 59 then comp[13] = 0 
        d0 = comp[13] dig 0:d1 = comp[13] dig 1 
        d1 = d1<< 4 
        m_on[3] = d1|d0
        pause 150
        endif

        if(s4=0) then         
         pause 50 
         comp[14] = comp[14]+1 
         if comp[14] > 23 then comp[14] = 0 
         d0 = comp[14] dig 0:d1 = comp[14] dig 1 
         d1 = d1<< 4 
         h_off[3] = d1|d0
         pause 150
        endif

        if(s5=0) then         
         pause 50 
         comp[15] = comp[15]+1 
         if comp[15] > 59 then comp[15] = 0 
         d0 = comp[15] dig 0:d1 = comp[15] dig 1 
         d1 = d1<< 4 
         m_off[3] = d1|d0
         pause 150
        endif                           
       pause 20 
       gosub write_setpoint            
Lcdout $fe,1,"T3= ",hex2 h_on[3],":",hex2 m_on[3]," ",hex2 h_off[3],":",hex2 m_off[3]       
return 

t4:    
        if (s2=0) then         
        pause 50 
        comp[16] = comp[16]+1 
        if comp[16] > 23 then comp[16] = 0 
        d0 = comp[16] dig 0:d1 = comp[16] dig 1 
        d1 = d1<< 4 
        h_on[4] = d1|d0 
        pause 150
        endif

        if (s3=0) then         
        pause 50 
        comp[17] = comp[17]+1 
        if comp[17] > 59 then comp[17] = 0 
        d0 = comp[17] dig 0:d1 = comp[17] dig 1 
        d1 = d1<< 4 
        m_on[4] = d1|d0
        pause 150
        endif

        if(s4=0) then         
         pause 50 
         comp[18] = comp[18]+1 
         if comp[18] > 23 then comp[18] = 0 
         d0 = comp[18] dig 0:d1 = comp[18] dig 1 
         d1 = d1<< 4 
         h_off[4] = d1|d0
         pause 150
        endif

        if(s5=0) then         
         pause 50 
         comp[19] = comp[19]+1 
         if comp[19] > 59 then comp[19] = 0 
         d0 = comp[19] dig 0:d1 = comp[19] dig 1 
         d1 = d1<< 4 
         m_off[4] = d1|d0
         pause 150
        endif                           
       pause 20 
       gosub write_setpoint            
Lcdout $fe,1,"T4= ",hex2 h_on[4],":",hex2 m_on[4]," ",hex2 h_off[4],":",hex2 m_off[4]       
return  

set_time: 
    pause 500 
loop2: 
  if (s1 = 1) then 
     pause 50               
     if (s2=0) then         
        pause 50 
        hr = hr+1 
        if hr > 23 then hr = 0 
        d0 = hr dig 0:d1 = hr dig 1 
        d1 = d1<< 4 
        hour = d1|d0 
         gosub display_time 
         pause 150
     endif     
   if (s3=0) then            
           pause 50 
           mn = mn+1 
          if mn > 59 then mn = 0 
          d0 = mn dig 0:d1 = mn dig 1 
          d1 = d1<< 4 
          minute = d1|d0 
          gosub display_time 
          pause 150 
   endif

       if (s4=0) then          
         pause 50 
         ss = ss+1 
         if ss > 59 then ss = 0 
         d0 = ss dig 0:d1 = ss dig 1 
         d1 = d1<< 4 
         sec = d1|d0 
         gosub display_time 
         pause 150
       endif          
    goto loop2
 endif 
  gosub write_time
return

 write_time: 
   i2cwrite sda,scl,cont,address,[sec,minute,hour]
 return  

 read_time: 
   i2cread sda,scl,cont,address,[sec,minute,hour] 
 return 

 display_time:
   lcdout $FE,1
   if pump = 0 then
   lcdout $fe,$80,"Time = ",hex2 hour,":",hex2 minute,":",hex2 sec  
   lcdout $FE,$C0,"Pump = <<Run>>"          
   pause 5
   else
   lcdout $fe,$80,"Time = ",hex2 hour,":",hex2 minute,":",hex2 sec  
   lcdout $FE,$C0,"Pump = <<Stop>>"          
   pause 5
   endif 
  return 

read_setpoint:
read 0,h_on[0]
read 1,h_on[1]
read 2,h_on[2]
read 3,h_on[3]
read 4,h_on[4]

'--------------
read 6, m_on[0]
read 7, m_on[1]
read 8, m_on[2]
read 9, m_on[3]
read 10,m_on[4]

'---------------
read 12,h_off[0]
read 13,h_off[1]
read 14,h_off[2]
read 15,h_off[3]
read 16,h_off[4]

'----------------
read 18,m_off[0]
read 19,m_off[1]
read 20,m_off[2]
read 21,m_off[3]
read 22,m_off[4]

return

write_setpoint:
write 0,h_on[0]
write 1,h_on[1]
write 2,h_on[2]
write 3,h_on[3]
write 4,h_on[4]

'-------------
write 6, m_on[0]
write 7, m_on[1]
write 8, m_on[2]
write 9, m_on[3]
write 10,m_on[4]

'--------------
write 12,h_off[0]
write 13,h_off[1]
write 14,h_off[2]
write 15,h_off[3]
write 16,h_off[4]

'-----------------
write 18,m_off[0]
write 19,m_off[1]
write 20,m_off[2]
write 21,m_off[3]
write 22,m_off[4]

return 

comp_work:
if (hour >= h_on[0] && minute >= m_on[0]) && (hour <= h_off[0] && minute <= m_off[0]-1)_
 ||(hour >= h_on[1] && minute >= m_on[1]) && (hour <= h_off[1] && minute <= m_off[1]-1)_
 ||(hour >= h_on[2] && minute >= m_on[2]) && (hour <= h_off[2] && minute <=  m_off[2]-1)_
 ||(hour >= h_on[3] && minute >= m_on[3]) && (hour <= h_off[3] && minute <=  m_off[3]-1)_
 ||(hour >= h_on[4] && minute >= m_on[4]) && (hour <= h_off[4] && minute <=  m_off[4]-1) then      
     pump = 0  
     pause 3
     else
     pump = 1  
     pause 3
 endif    
return    

stand:
repeat
 pause 200
 pump = 1
 lcdout $fe,$80,"....stand by...."
 lcdout $FE,$C0,"Pump = <<Stop>>"          
 pause 5 
until s4 = 0 and s5 = 0 
 gosub start
return

Quick Solutions to Questions related to Automated Water Pump Controller:

  • What microcontroller is used in this project?
    The project uses the PIC16F877 device.
  • How many programmable time slots does the system support?
    The system supports five distinct time slots labeled T0 through T4.
  • Does the code use an internal or external oscillator?
    The configuration specifies an XT_OSC setting with a 4MHz frequency.
  • Can the pump be controlled manually via buttons?
    Yes, buttons S1 through S5 allow users to set hours, minutes, seconds, days, and dates.
  • How is the real-time clock data stored and retrieved?
    Data is read and written using i2cread and i2cwrite commands on PORTC pins.
  • What happens if the sensor and pump inputs are both zero?
    The system enters a standby mode and waits for specific button presses to resume.
  • Which ports are assigned to the LCD control lines?
    The LCD registers and bits are defined using PORTD for data, register select, and enable lines.
  • How does the system determine when to turn the pump off?
    The pump turns off when the current time exceeds the configured off hour and minute for any active slot.

About The Author

Ibrar Ayyub

I am an experienced technical writer holding a Master's degree in computer science from BZU Multan, Pakistan University. With a background spanning various industries, particularly in home automation and engineering, I have honed my skills in crafting clear and concise content. Proficient in leveraging infographics and diagrams, I strive to simplify complex concepts for readers. My strength lies in thorough research and presenting information in a structured and logical format.

Follow Us:
LinkedinTwitter