
1. Main Functions
(1) Automatically collect light and sound data;
(2) Automatically control the street light switch based on sound decibel values and light intensity;
(3) The street light turns on and automatically turns off 3 seconds after a person leaves.
2. Usage Method
After the system is running, the LCD1602 displays the collected light intensity and sound decibel values. When the sound decibel exceeds 45, it indicates that someone has passed. At this time, the system determines whether to turn on the street light based on the light intensity value. If the light intensity value is less than 1000, it indicates that the light is dim, and the street light will turn on; otherwise, it will turn off. If the street light is on and the sound decibel drops below 45, indicating that the person has left, the street light will automatically turn off after 3 seconds.
If the light value is less than 1000, indicating that the light is dim, and the sound decibel value is less than 45, indicating that no one is present, the street light will remain off.
3. Hardware Resources
51 Microcontroller Core Module, PCF8591 ADC/DAC Module, LCD1602 Module, Street Light Control Switch Module, Light Sensor, and Sound Sensor Module.
4. Software Design
Main Code (Part)
The code is as follows:
#include<reg52.h>
typedef unsigned char uint8;
typedef unsigned int uint16;
sbit rs=P2^6; // Data command selection
sbit rw=P2^5; // Read/write selection
sbit e=P2^7; // Enable
sbit scl=P2^1; // PCF8591 clock
sbit sda=P2^0; // Data line
sbit relay=P3^6; // Street light control switch
uint8 num[]="0123456789";
uint8 d1[7]="Light: ";
uint8 d2[7]="Sound: ";
uint16 ad[5];
uint8 dsok;
uint8 miao;
void delay(uint16 i) // Delay function, approximately 10us
{
while(i--);
}
void wrc(uint8 c) // LCD write command function
{
delay(1000);
rs=0;
rw=0;
e=0;
P0=c;
e=1;
delay(10);
e=0;
}
void wrd(uint8 dat) // LCD write data function
{
delay(1000);
rs=1;
rw=0;
e=0;
P0=dat;
e=1;
delay(10);
e=0;
rs=0;
}
void init() // LCD initialization function
{
delay(1000);
wrc(0x38);
wrc(0x38);
wrc(0x38);
wrc(0x06);
wrc(0x0c);
wrc(0x01);
}
void time0init() // Timer 0 initialization
{
TMOD=0X01;
TH0=0XFC;
TL0=0X18; //1ms
// TR0=1;
ET0=1;
EA=1;
}
void iicinit() // IIC initialization function
{
sda=1;
scl=1;
}
void iicstart() // Start signal
{
sda=1;
scl=1;
delay(10);
sda=0;
delay(10);
scl=0;
delay(10);
}
void iicstop() // Stop signal
{
sda=0;
scl=1;
delay(10);
sda=1;
delay(10);
sda=0;
delay(10);
}
void ack() // Acknowledge signal
{
sda=1;
scl=0;
delay(2);
sda=0;
delay(2);
scl=1;
delay(10);
scl=0;
delay(2);
sda=1;
delay(5);
}
void noack() // No acknowledge signal
{
sda=0;
scl=0;
delay(2);
sda=1;
delay(2);
scl=1;
delay(10);
scl=0;
delay(2);
sda=0;
delay(5);
}
void iicwrbyte(uint8 dat) // IIC write byte function
{
uint8 i;
scl=0;
for(i=0;i<8;i++) {
if(dat&0x80) {
sda=1;
}
else {
sda=0;
}
dat<<=1;
scl=1;
delay(10);
scl=0;
delay(10);
}
sda=1;
delay(10);
}
uint8 iicread() // IIC read data function
{
uint8 i,dat;
scl=0;
sda=1;
for(i=0;i<8;i++) {
dat<<=1;
if(sda==1) {
dat|=0x01;
}
scl=1;
delay(10);
scl=0;
delay(10);
}
return dat;
}
void pcf8591wrbyte(uint8 channel) // Write data to corresponding channel in IIC
{
iicinit();
iicstart();
iicwrbyte(0x90); // pcf8591 write data 1001 A2A1A0 R/W
ack();
iicwrbyte(channel|0x40); // Enable output by opening channel channelX
noack();
iicstop();
}
uint8 pcf8591read() // Read data from the channel
{
uint8 dat;
iicinit();
iicstart();
iicwrbyte(0x90);
ack();
iicstart();
iicwrbyte(0x91); // pcf8591 read data 1001 A2A1A0 R/W
ack();
dat=iicread();
noack();
iicstop();
return dat;
}
void pcf8591dac(uint8 value) // DA conversion
{
iicinit();
iicstart();
iicwrbyte(0x90);
ack();
iicwrbyte(0x40); // No need to open channel channelX, enable output
ack();
iicwrbyte(value);
noack();
iicstop();
}
void display() // Display function
{
float v,v1;
uint8 i;
pcf8591wrbyte(0); // Potentiometer conversion
ad[0]=pcf8591read(); // Read the previous data
delay(10);
pcf8591wrbyte(1); // Potentiometer conversion
ad[0]=pcf8591read(); // Read the previous data
delay(10);
pcf8591wrbyte(2); // Potentiometer conversion
ad[1]=pcf8591read(); // Read the previous data
delay(10);
v=ad[0]*0.01953; // Convert potentiometer data to voltage value 0.01953
v=v*1000; // Get 3 significant digits
ad[0]=v;
v1=ad[1]*0.01953; // Convert potentiometer data to voltage value 0.01953
v1=v1*1000; // Get 3 significant digits
ad[1]=v1/100;
wrc(0x00+0x80);
for(i=0;i<7;i++) {
wrd(d1[i]);
}
wrd(num[ad[0]/1000]);
wrd(num[ad[0]%1000/100]);
wrd(num[ad[0]%1000%100/10]);
wrd(num[ad[0]%1000%100%10]);
wrc(0x40+0x80);
for(i=0;i<7;i++) {
wrd(d2[i]);
}
wrd(num[ad[1]/10]);
wrd(num[ad[1]%10]);
wrd('d');
wrd('b');
ad[4]=ad[0];
pcf8591dac(ad[4]/2); // Convert digital quantity to analog quantity output by pcf8591's AOUT
}
void data_change() // Data comparison function
{
if(ad[0]<1000&&ad[1]>45&&dsok==0) // When light intensity is below 1000 and sound is greater than 45 decibels, turn on the light
{
relay=0;
TR0=1; // Turn on timer 0
}
if(dsok==1)
{
relay=1;
dsok=0;
}
}
void main() // Main function
{
init(); // LCD initialization
time0init(); // Timer 0 initialization
while(1)
{
display(); // Display function
data_change(); // Data comparison function
}
}
void tim0() interrupt 1
{
static uint16 n;
TH0=0XFC;
TL0=0X18;//1ms
n++;
if(n==1000) // Timer 1 second
{
n=0;
miao++;
if(miao==3)
{
miao=0;
dsok=1;
TR0=0;
}
}
}
5. Experimental Phenomena


