具体要求,当传感器检测实际液位低于最低最低液位是开始工作,具体可以询问
或者结合这两个也行
https://www.bilibili.com/video/BV1Zk4y1z7fg?share_source=copy_web
#include <reg51.h>
#include <intrins.h>
#include "main.h"
uchar code TabNumASCII[10] = {'0','1','2','3','4','5','6','7','8','9'};
bool g_flag = isNo;
bool g_flag05s = isNo;
uchar ucCount = 0;
uint uiH = 80;
uint uiL = 30;
uint uiD = 100;
bool g_flagSwitch = isNo;
bool g_flagBeepTimer = isNo;
void delay10us(void)
{
unsigned char i;
_nop_();
i = 2;
while (--i);
}
void delay100us(void)
{
uchar i;
_nop_();
i = 47;
while (--i);
}
void delay125us(void)
{
unsigned char i;
i = 60;
while (--i);
}
void delay5ms(void)
{
unsigned char i, j;
i = 10;
j = 183;
do
{
while (--j);
} while (--i);
}
void delay500ms(void)
{
unsigned char i, j, k;
_nop_();
i = 4;
j = 205;
k = 187;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void initIO(void)
{
P0 = 0xff;
P1 = 0xff;
P2 = 0xff;
P3 = 0xff;
}
void initTimer0(void)
{
TMOD &= 0xF0;
TMOD |= 0x01;
TL0 = 0;
TH0 = 0;
//TR0 = 1;
ET0 = 1;
EA = 1;
}
void initTimer1(void)
{
TMOD &= 0x0F;
TMOD |= 0x10;
TL1 = 0xB0;
TH1 = 0x3C;
TR1 = 1;
ET1 = 1;
}
void zd0(void) interrupt 1
{
g_flag = isYes;
if(++ucCount >= 8)
{
ucCount = 0;
g_flag05s = isYes;
}
TL0 = 0;
TH0 = 0;
}
void tm1_isr() interrupt 3 using 1
{
static uchar count = DATA_switchTime;
static uchar uiCount = 1200;
static uint uiCount_BeepTimer = DATA_BeepTimer;
TL1 = 0xB0;
TH1 = 0x3C;
if (g_flagSwitch == isNo)
{
if (count-- == 0)
{
count = DATA_switchTime;
g_flagSwitch = isYes;
// TR1 = 0;
}
}
if(g_flagBeepTimer == isNo)
{
if (uiCount-- == 0)
{
uiCount = 1200;
if(uiCount_BeepTimer-- == 0)
{
uiCount_BeepTimer = DATA_BeepTimer;
g_flagBeepTimer = isYes;
// TR1 = 0;
}
}
}
}
void exint1() interrupt 2
{
EX1 = 0;
TR0 = 0;
}
void LCD_waitNotBusy(void)
{
uchar sta;
IO_LCD_Data = 0xFF;
io_LCD_RS = 0;
io_LCD_RW = 1;
do
{
io_LCD_E = 1;
_nop_();
_nop_();
sta = P0;
io_LCD_E = 0;
}while(sta & 0x80);
}
void LCDWriteCommand(uchar command,bool ifReadBusy)
{
if (ifReadBusy == isReadBusy) LCD_waitNotBusy();
io_LCD_RS = 0;
io_LCD_RW = 0;
IO_LCD_Data = command;
io_LCD_E = 1;
_nop_();
_nop_();
io_LCD_E = 0;
}
void LCDWriteData(uchar dat)
{
LCD_waitNotBusy();
io_LCD_RS = 1;
io_LCD_RW = 0;
IO_LCD_Data = dat;
io_LCD_E = 1;
_nop_();
_nop_();
io_LCD_E = 0;
}
void initLCD1602(void)
{
uchar i;
IO_LCD_Data = 0;
for(i = 0; i < 3; i++)
{
LCDWriteCommand(0x38,isNotReadBusy);
delay5ms();
}
LCDWriteCommand(0x38,isReadBusy);
LCDWriteCommand(0x08,isReadBusy);
LCDWriteCommand(0x01,isReadBusy);
LCDWriteCommand(0x06,isReadBusy);
LCDWriteCommand(0x0F,isReadBusy);
}
void putOneCharToLCD1602(uchar line, uchar position, uchar ucData)
{
line &= DATA_LineMax;
position &= DATA_PositionMax;
if (line == DATA_LineTow) position |= 0x40;
position |= 0x80;
LCDWriteCommand(position, isReadBusy);
LCDWriteData(ucData);
}
void putLineCharsToLCD1602(uchar line, uchar position, uchar count, uchar code *ucData)
{
uchar i;
for(i = 0; i < count; i++)
{
putOneCharToLCD1602(line, position + i, ucData[i]);
}
}
void putThreeCharToLCD1602(uchar line, uchar position, uint uiNumber)
{
uiNumber %= 1000;
putOneCharToLCD1602(line, position, TabNumASCII[uiNumber / 100]);
putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 / 10]);
putOneCharToLCD1602(line, ++position, TabNumASCII[uiNumber % 100 % 10]);
}
uchar GetKey(void)
{
uchar KeyTemp = (IO_KEY | DATA_KEY_ORL);
if( KeyTemp != DATA_KEY_Null )
{
uchar CountTemp = 0;
do
{
delay125us();
if(KeyTemp != (IO_KEY | DATA_KEY_ORL)) return 0;
} while(++CountTemp > Data_Key20msCountMax);
while((IO_KEY | DATA_KEY_ORL) != DATA_KEY_Null);
return KeyTemp;
}
return 0;
}
uchar INC_Number(uchar Number, uchar Min, uchar Max)
{
if(Number >= Max) return Min; else return (++ Number);
}
uchar DEC_Number(uchar Number, uchar Min, uchar Max)
{
if(Number <= Min) return Max; else return (-- Number);
}
void execute_key_task(uchar ucKeyValue)
{
uchar state = 0;
uchar keyValue = 0;
if(ucKeyValue != DATA_KEY_Set) return;
putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");
putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
while(1)
{
keyValue = GetKey();
if(keyValue == 0) continue;
switch(keyValue)
{
case DATA_KEY_Set:
{
switch(state)
{
case 0:
{
state = 1;
putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
}
break;
case 1:
{
uchar tempMax = uiD - DATA_uiD_Min;
if(tempMax < 2 + 2) tempMax = 2 + 2;
if(uiH > tempMax)
{
uiH = tempMax;
putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
}
else if(uiH < 2 + 2)
{
uiH = 2 + 2;
putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
}
state = 2;
putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
}
break;
case 2:
{
if(uiL > uiH - 2)
{
uiL = uiH - 2;
putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
}
return;
}
break;
}
}
break;
case DATA_KEY_INC:
{
switch(state)
{
case 0:
{
uiD = INC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);
putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
}
break;
case 1:
{
uchar tempMax = uiD - DATA_uiD_Min;
if(tempMax < 2 + 2) tempMax = 2 + 2;
uiH = INC_Number(uiH, 2, tempMax);
putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
}
break;
case 2:
{
uiL = INC_Number(uiL, 0, uiH - 2);
putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
}
break;
}
}
break;
case DATA_KEY_DEC:
{
switch(state)
{
case 0:
{
uiD = DEC_Number(uiD, DATA_uiD_Min, DATA_uiD_Max);
putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
}
break;
case 1:
{
uchar tempMax = uiD - DATA_uiD_Min;
if(tempMax < 2 + 2) tempMax = 2 + 2;
uiH = DEC_Number(uiH, 2, tempMax);
putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
}
break;
case 2:
{
uiL = DEC_Number(uiL, 0, uiH - 2);
putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
}
break;
}
}
break;
}
}
}
void buzzerCall(void)
{
uchar i;
for(i = 0; i < 90; i++)
{
io_Buzzer = 0;
delay100us();
io_Buzzer = 1;
delay100us();
delay100us();
}
delay100us();
delay100us();
}
bool CalculatedWaterLevel(void)
{
uchar i = 8 + 2;
uint uiTime;
ulong ulDis;
uiTime = TH0 << 8 | TL0;
ulDis = (uiTime * 3.40) / 200;
TH0 = 0;
TL0 = 0;
if((ulDis > uiD) || (g_flag == isYes ))
ioLed_Red = ! ioLed_Red;
ioLed_Green = ! ioLed_Green;
ioLed_Yellow = ! ioLed_Yellow;
if(buzzerCallFlag == isCall)
{
buzzerCall();
}
return isNo;
}
else
{
ulDis = uiD - ulDis;
if(ulDis > uiH)
{
io_Control_Inlet = isio_Control_Inlet_OFF;
io_Control_Outlet = isio_Control_Outlet_ON;
g_flagSwitch = isNo;
ioLed_Red = ! ioLed_Red;
ioLed_Green = isLedOFF;
ioLed_Yellow = isLedOFF;
if(ulDis - uiH > (uiD - uiH) / DATA_alarmCoefficient)
{
buzzerCall();
}
}
else if(ulDis < uiL)
if(g_flagSwitch == isYes)
{
io_Control_Outlet = isio_Control_Outlet_OFF;
io_Control_Inlet = isio_Control_Inlet_ON;
g_flagSwitch = isNo;
}
ioLed_Red = isLedOFF;
ioLed_Green = isLedOFF;
ioLed_Yellow = ! ioLed_Yellow;
if( uiL - ulDis > uiL / DATA_alarmCoefficient)/
{
buzzerCall();
}
}
else
{
ioLed_Red = isLedOFF;
ioLed_Green = ! ioLed_Green;
ioLed_Yellow = isLedOFF;
}
putThreeCharToLCD1602(lineTow, i, ulDis);
return isYes;
}
}
void main(void)
{
initIO();
delay500ms();
initLCD1602(); »¯
putLineCharsToLCD1602(lineOne, 8, 8, "D:000cm "); putThreeCharToLCD1602(lineOne, 8 + 2, uiD);
putLineCharsToLCD1602(lineOne, 0, 8, "H:000cm ");
putThreeCharToLCD1602(lineOne, 0 + 2, uiH);
putLineCharsToLCD1602(lineTow, 0, 8, "L:000cm ");
putThreeCharToLCD1602(lineTow, 0 + 2, uiL);
putLineCharsToLCD1602(lineTow, 8, 8, "C:000cm ");
initTimer0();
initTimer1();
io_Control_Inlet = isio_Control_Inlet_OFF;
io_Control_Outlet = isio_Control_Outlet_ON;
g_flagSwitch = isNo;
while(1)
{
io_US_TX = 1;
delay10us();
io_US_TX = 0;
while(io_US_RX == 0);
TR0 = 1;
IT1 = 1;
EX1 = 1;
while(EX1 == 1 && g_flag == isNo)
{
uchar ucKeyValue = GetKey();
if(ucKeyValue) execute_key_task(ucKeyValue);
}
if(CalculatedWaterLevel() == isNo) continue;
TR0 = 0;
TL0 = 0;
TH0 = 0;
g_flag = isNo;
ucCount = 0;
g_flag05s = isNo;
TR0 = 1;
while(g_flag05s == isNo)
{
uchar ucKeyValue = GetKey();
if(ucKeyValue)
{
if(ucKeyValue == DATA_KEY_DEC)
{
g_flagBeepTimer = isNo;
}
execute_key_task(ucKeyValue);
}
}
TR0 = 0;
TL0 = 0;
TH0 = 0;
g_flag = isNo;
if(g_flagBeepTimer == isYes)
{
buzzerCall();
}
}
}
import RPi.GPIO as GPIO
import time
# 设置舵机引脚
servo_pin = 18
# 设置传感器引脚
sensor_pin = 17
# 设置最低液位值
lowest_level = 10 # 这里的值需要根据实际情况进行设置
# 初始化GPIO设置
GPIO.setmode(GPIO.BCM)
GPIO.setup(servo_pin, GPIO.OUT)
GPIO.setup(sensor_pin, GPIO.IN)
# 定义舵机控制函数
def control_servo(angle):
pwm = GPIO.PWM(servo_pin, 50)
pwm.start(0)
duty_cycle = angle / 18.0 + 2.5
pwm.ChangeDutyCycle(duty_cycle)
time.sleep(1)
pwm.stop()
# 主程序
try:
while True:
# 读取传感器状态
sensor_status = GPIO.input(sensor_pin)
if sensor_status == GPIO.LOW:
print("实际液位低于最低液位,启动舵机工作")
control_servo(90) # 设置舵机角度,这里是90度,根据实际情况进行设置
time.sleep(1) # 控制舵机工作的持续时间
control_servo(0) # 舵机回到初始位置
else:
print("实际液位正常")
time.sleep(1) # 每隔1秒检测一次传感器状态
except KeyboardInterrupt:
GPIO.cleanup()
使用了RPi.GPIO库来控制树莓派上的GPIO引脚。程序会不断检测传感器引脚的状态,当检测到实际液位低于最低液位时,舵机会开始工作,持续一定时间后回到初始位置。可以根据实际情况修改舵机引脚、传感器引脚、最低液位值和舵机角度等参数。
你好,代码有什么问题么,我看函数都蛮好的
/*****************************************************************************
** 文件 : main.c
** 作者 : Zheng23
** 日期 :
** 功能 :
/*****************************************************************************/
//#include <STC15.h>
//#include"STC89C5xRC.H"
//一定要用12M的晶振
//一定要用12M的晶振
//一定要用12M的晶振
//一定要用12M的晶振
//一定要用12M的晶振
//一定要用12M的晶振
#include "reg51.h"
#define uint8 unsigned char
#define uint16 unsigned short int
#define uint32 unsigned long
sbit SERVO0=P1^4; //控制舵机的PWM输出口
uint16 Servo0PwmDuty=1500; //PWM脉冲宽度
/***********************************************************
* 名 称: DelayMs(uint16 ms)
* 功 能: 延时ms毫秒
* 入口参数: ms 毫秒
* 出口参数: 无
* 说 明:
/**********************************************************/
void DelayMs(uint16 ms)
{
uint16 i,j;
for(i=0;i<85;i++) //89单片机用85,12系列单片机用800
for(j=0;j<ms;j++);
}
/***********************************************************
* 名 称:InitTimer0()
* 功 能:时钟0初始化
* 入口参数:无
* 出口参数:无
* 说 明:12M晶振,12分频,所以计数器每递增一个数就是1微秒,完全满足舵机控制的精度要求
因为定时器是TH0,TL0都要全部计数到0xFF后在计1个数就会产生中断,所以要想产生
x毫秒的中断,那么TH0,TL0就应该赋值(0xFFFF-x) 从这个值开始计数产生定时中断
/**********************************************************/
void InitTimer0(void)
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x00; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0 = 1; //开定时器0中断
}
/***********************************************************
* 名 称:Timer0Value(uint16 pwm)
* 功 能:给定时器0计数器赋值产生定时中断
* 入口参数:pwm 控制舵机的PWM脉冲宽度值(范围:500~2500)
* 出口参数:无
* 说 明:12M晶振,12分频,所以计数器每递增一个数就是1微秒,完全满足舵机控制的精度要求
因为定时器是TH0,TL0都要全部计数到0xFF后在计1个数就会产生中断,所以要想产生
pwm毫秒的中断,那么TH0,TL0就应该赋值(0xFFFF-pwm) 从这个值开始计数产生定时中断
/**********************************************************/
void Timer0Value(uint16 pwm)
{
uint16 value;
value=0xffff-pwm;
TR0 = 0;
TL0=value; //16位数据给8位数据赋值默认将16位数据的低八位直接赋给八位数据
TH0=value>>8; //将16位数据右移8位,也就是将高8位移到低八位,再赋值给8位数据
TR0 = 1;
}
/***********************************************************
* 名 称: main()
* 功 能: 入口函数
* 入口参数: 无
* 出口参数: 无
* 说 明:
/**********************************************************/
void main(void)
{
InitTimer0(); //定时器0初始化
EA = 1; //开总中断
while(1) //大循环
{
Servo0PwmDuty = 500; //脉冲宽度在500微秒,对应-90°
DelayMs(1000); //延时1秒
Servo0PwmDuty = 1000; //脉冲宽度在1000微秒,对应-45°
DelayMs(1000);
Servo0PwmDuty = 1500;
DelayMs(1000);
Servo0PwmDuty = 2000;
DelayMs(1000);
Servo0PwmDuty = 2500;
DelayMs(1000);
Servo0PwmDuty = 2000;
DelayMs(1000);
Servo0PwmDuty = 1500;
DelayMs(1000);
Servo0PwmDuty = 1000;
DelayMs(1000);
}
}
/***********************************************************
* 名 称: Timer0_isr() interrupt 1 using 1
* 功 能: 时钟0中断处理
* 入口参数: 无
* 出口参数: 无
* 说 明:
/**********************************************************/
void Timer0_isr(void) interrupt 1 using 1
{
static uint16 i = 1; //静态变量:每次调用函数时保持上一次所赋的值,
//跟全局变量类似,不同是它只能用于此函数内部
switch(i)
{
case 1:
SERVO0 = 1; //PWM控制脚高电平
//给定时器0赋值,计数Pwm0Duty个脉冲后产生中断,下次中断会进入下一个case语句
Timer0Value(Servo0PwmDuty);
break;
case 2:
SERVO0 = 0; //PWM控制脚低电平
//高脉冲结束后剩下的时间(20000-Pwm0Duty)全是低电平了,Pwm0Duty + (20000-Pwm0Duty) = 20000个脉冲正好为一个周期20毫秒
Timer0Value(20000-Servo0PwmDuty);
i = 0;
break;
}
i++;
}
以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:
你好,以下是一个简单的单个舵机控制程序的C语言代码示例,使用了51单片机和proteus仿真环境:
#include <reg51.h>
#define Servo P1 // 定义舵机控制引脚P1
#define Sensor P2 // 定义液位传感器引脚P2
void delay(unsigned int n) // 延时函数
{
unsigned int i, j;
for(i=0; i<n; i++)
for(j=0; j<125; j++);
}
void main()
{
while(1)
{
if(Sensor < 100) // 当实际液位低于最低液位时
{
Servo = 0x00; // 舵机转到最低位置
delay(50000); // 延时等待舵机到位
Servo = 0xFF; // 舵机转到最高位置
delay(50000); // 延时等待舵机到位
}
else
{
Servo = 0x00; // 舵机转到最低位置
delay(50000); // 延时等待舵机到位
}
}
}
该程序中使用P1口控制舵机的转动,P2口接液位传感器检测实际液位高低,当实际液位低于最低液位时,舵机会先转到最低位置,然后再转到最高位置,等待一段时间后再转回最低位置;当实际液位高于最低液位时,舵机只会转到最低位置。程序中的delay函数用于延时等待舵机到位。这只是一个简单的示例程序,具体实现还需根据具体的硬件和需求进行调整。
以下答案由GPT-3.5大模型与博主波罗歌共同编写:
以下是单个舵机控制程序的 Python 代码:
import RPi.GPIO as GPIO
import time
# 设置GPIO模式为BCM编码方式
GPIO.setmode(GPIO.BCM)
# 设置GPIO21为输出信号口
GPIO.setup(21, GPIO.OUT)
# 设置脉宽为50Hz
servo = GPIO.PWM(21, 50)
# 启动脉冲,设置角度为0,初始化位置
servo.start(0)
# 指定位置函数
def setPosition(degrees):
duty = degrees / 18 + 2.5
servo.ChangeDutyCycle(duty)
time.sleep(1)
servo.ChangeDutyCycle(0)
# 角度从0到180依次打印
for i in range(0, 180, 10):
print(i)
setPosition(i)
# 角度从180到0依次打印
for i in range(180, 0, -10):
print(i)
setPosition(i)
# 停止脉冲
servo.stop()
# 清除GPIO口
GPIO.cleanup()
需要注意的是,这里使用的是树莓派GPIO控制舵机的方式,如果使用其他硬件,请使用相应的代码进行控制。同时,代码只是一个简单的示例,具体实现需要根据具体的舵机和控制方式进行调整。
如果我的回答解决了您的问题,请采纳!
以下答案由GPT-4.5Plus大模型(语音)与博主A努力中.......共同编写:
一个简单的单个舵机控制程序可以设计如下:
python
class Servo:
def __init__(self, min_width, max_width, center_width):
self.min_width = min_width # 舵机最小脉冲宽度
self.max_width = max_width # 舵机最大脉冲宽度
self.center_width = center_width # 舵机中心脉冲宽度
self.curr_width = center_width # 当前脉冲宽度
python
def rotate(self, width):
self.curr_width = width
# 发送舵机转动信号,可调用外部库
python
def angle_to_width(self, angle):
range = self.max_width - self.min_width
ratio = (angle + 90) / 180 # 角度范围转化到0-1之间
return self.min_width + range * ratio
python
servo = Servo(1000, 2000, 1500) # 初始化舵机对象
# 转动舵机到90度
servo.rotate(servo.angle_to_width(90))
# 中心位置
servo.rotate(servo.center_width)
# 转动舵机到-45度
servo.rotate(servo.angle_to_width(-45))
以上是一个简单的单舵机控制程序,通过定义舵机对象存储参数,设置转动函数和角度转换函数,可以方便地根据给定角度控制舵机转动。