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
- 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.