智慧鱼缸,检测土壤湿度,检测室内温湿度和光照,检测鱼缸水位,检测鱼缸温度,各种蜂鸣器报警(水温超20-24)和控制舵机(步进电机),控制两个水泵,一个需要是从植物里面抽水到鱼缸,另外一个是供养氧作用,数据上传onenet,显示在oled,ESP32做主MCU,下行控制氧气水泵
1、项目简介
2、实现逻辑
3、应用场景
#智慧鱼缸
4、核心代码梳理
const char *ssid = "ziroom602";//WIFI
const char *password = "4001111";//WIFI密码
const char* serverIP = "183.230.40.33"; //欲访问的地址
uint16_t serverPort = 80; //服务器端口号
String url = "http://api.heclouds.com/devices/7xxxxxxxxx7/datapoints?type=3";//网址 设备ID
String api="h8txxxxxxxxxxxxxxxxxxxYFNsgW4=";//api-key
String post;//http请求
int Content_Length;
WiFiClient client; //声明一个客户端对象,用于与服务器进行连接
OneWire ds(0); // on pin 10 (a 4.7K resistor is necessary)
BH1750FVI myBH1750(BH1750_DEFAULT_I2CADDR, BH1750_CONTINUOUS_HIGH_RES_MODE_2, BH1750_SENSITIVITY_DEFAULT, BH1750_ACCURACY_DEFAULT);
U8G2_SSD1306_128X64_NONAME_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 18, /* data=*/ 19, /* cs=*/ 5, /* dc=*/ 16, /* reset=*/ 17);
Servo myservo; // create servo object to control a servo
#define DHTTYPE DHT11 //选择的类型
int servoPin = 14; // GPIO pin used to connect the servo control (digital out)
#define LED_BUILTIN 02
#define WATER 15
#define GROUND_H 4
#define WATER_MOTOR 12 //
#define O2_MOTOR 13
#define BEEP 33
#define DHTPIN 27 //DHT11 DATA 数据引脚
DHT dht(DHTPIN, DHTTYPE);
long ground_h = 0, water = 0, pwm_value = 0;
float tank_temp = 0, house_h = 0, house_t = 0, light_value = 0;
int8_t rx_data = 0, beep_flag = 0, water_ok_flag = 0, water_in_flag = 0, O2_in_flag = 0;
static unsigned long time_=0;//定义初始发送时间为0
static unsigned long time_out=0;//定义超时发送时间为0
void setup(void)
{
//DHT11
dht.begin();
//OLED
u8g2.begin();
u8g2.enableUTF8Print(); // enable UTF8 support for the Arduino print() function
//USART
Serial.begin(9600);
//PIN CFG
pinMode(LED_BUILTIN, OUTPUT);
pinMode(WATER_MOTOR, OUTPUT);
pinMode(O2_MOTOR, OUTPUT);
pinMode(BEEP, OUTPUT);
digitalWrite(BEEP, 1); //low - beep
pinMode(GROUND_H, INPUT);
pinMode(GROUND_H, INPUT_PULLUP);
pinMode(WATER, INPUT);
pinMode(WATER, INPUT_PULLUP);
//WIFI
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);//连接到网络
while (WiFi.status() != WL_CONNECTED) {//等待网络连接成功
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());//打印模块IP
//BH1750
while (myBH1750.begin() != true)
{
Serial.println(F("ROHM BH1750FVI is not present")); //(F()) saves string to flash & keeps dynamic memory free
delay(5000);
}
Serial.println(F("ROHM BH1750FVI is present"));
//PWM & MOTOR
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
myservo.setPeriodHertz(50);// Standard 50hz servo
myservo.attach(servoPin, 500, 2400);
}
void loop(void)
{
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;
//DS18B20
if ( !ds.search(addr)) {
ds.reset_search();
delay(250);
return;
}
if (OneWire::crc8(addr, 7) != addr[7]) {
Serial.println("CRC is not valid!");
return;
}
switch (addr[0]) {
case 0x10:
//Serial.println(" Chip = DS18S20"); // or old DS1820
type_s = 1;
break;
case 0x28:
//Serial.println(" Chip = DS18B20");
type_s = 0;
break;
case 0x22:
// Serial.println(" Chip = DS1822");
type_s = 0;
break;
default:
Serial.println("Device is not a DS18x20 family device.");
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1); // start conversion, with parasite power on at the end
delay(1000); // maybe 750ms is enough, maybe not
present = ds.reset();
ds.select(addr);
ds.write(0xBE); // Read Scratchpad
for ( i = 0; i < 9; i++) { // we need 9 bytes
data[i] = ds.read();
}
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
tank_temp = celsius;
//DHT11
house_h = dht.readHumidity();
house_t = dht.readTemperature();
if (isnan(house_h) || isnan(house_t))
{
Serial.println("Failed to read from DHT sensor!");
return;
}
//BH1750
light_value = myBH1750.readLightLevel();
//logic
ground_h = 1-digitalRead(GROUND_H);
water = 1-digitalRead(WATER);
Serial.printf("GROUND-WATER: %d,%d",ground_h,water);
Serial.println("//");
digitalWrite(WATER_MOTOR, 1-ground_h); //HIGH-OPEN ground h low open water motor
digitalWrite(O2_MOTOR, water);//no use
if(light_value >= 50)
pwm_value = 180;
else if(light_value <= 20)
pwm_value = 0;
if((tank_temp>30) || (tank_temp<20))
{
digitalWrite(BEEP, 0); //low - beep
}
else digitalWrite(BEEP, 1);
//MOTOR
myservo.write(pwm_value); // set the servo position according to the scaled value (value between 0 and 180)
//LED
digitalWrite(LED_BUILTIN, HIGH);
delay(1000);
digitalWrite(LED_BUILTIN, LOW);
delay(1000);
//OLED
u8g2.setFont(u8g2_font_unifont_t_chinese2);
u8g2.clearBuffer(); //清除模组的缓存
u8g2.setFont(u8g2_font_ncenB08_tr); // 设置字体
u8g2.setCursor(0, 15);
u8g2.printf("TEMP-WATER: %.2fC", tank_temp);
u8g2.setCursor(0, 30);
u8g2.printf("GOUND:%d WATER:%d",ground_h, water);
u8g2.setCursor(0, 45);
u8g2.printf("HOUSE-TH: %.1fC,%.1f%",house_t,house_h);
u8g2.setCursor(0, 60);
u8g2.printf("LIGHT-LUX: %.2fLux",light_value);
u8g2.sendBuffer(); // 将缓存输出到屏幕
}
5、部分参考资料
#硬件原理图资料见资料包(下)
6、注意事项
#代码暂不包含nodemcu代码
完整可运行项目地址
或 点击下方”大饼匠人“卡片,关注并回复"6"免费下载开发资料