ESP32环境下基于SD卡与FTP实现温湿度数据采集与存储

本篇文章将介绍如何利用ESP32开发板结合SD卡与FTP服务器功能,实现温湿度数据的实时采集、存储与远程访问。项目代码基于Arduino IDE平台编写,主要依赖于以下库:

  • SPI
  • DHT
  • WiFi
  • time.h
  • ESP-FTP-Server-Lib
  • SD
  • SPIFFS
  • FS

1. 硬件连接与配置

1.1 所需要的硬件

  1. ESP32开发板在这里插入图片描述

  2. DHT22传感器模块

  3. SD卡模块

1.2 SD卡接口

ESP32通过SPI总线与SD卡进行通信,各引脚连接如下:

  • CS:GPIO 23
  • MOSI:GPIO 17
  • MISO:GPIO 2
  • SCK:GPIO 16

1.3 DHT22温湿度传感器

DHT22传感器连接至ESP32的GPIO 13引脚。

1.4 Wi-Fi模块

ESP32内置Wi-Fi模块,用于接入无线网络。此处设定的Wi-Fi信息如下:

  • SSIDxxx
  • Passwordxxx

1.5 NTP服务器与时区设置

为了获取准确的本地时间,通过NTP协议从阿里云NTP服务器同步时间,并设定时区为中国标准时间(UTC+8):

  • NTP Serverntp1.aliyun.com
  • GMT Offset8 * 3600
  • Daylight Offset0

1.6 FTP服务器配置

创建一个FTP服务器,供远程设备访问存储在ESP32上的温湿度数据。FTP登录信息如下:

  • Usernameftp
  • Passwordftp

2. 代码详解

2.1 引入库与定义常量

#include <Arduino.h>
/*
  sd Card Interface code for ESP32
  SPI Pins of ESP32 sd card as follows:
  CS    = 23;
  MOSI  = 17;
  MISO  = 2;
  SCK   = 16;
*/

#include <SPI.h>
#include <DHT.h>
#include <WiFi.h>
#include <time.h>
#include <ESP-FTP-Server-Lib.h>
#include <SD.h>
#include <SPIFFS.h>
#include <FS.h>

#define DHTPIN 13
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);
static float h = 0;
static float t = 0;

File myFile;

FTPServer ftp;
// 设置SPI Pins
const int CS = 23;
const int MOSI_PIN = 17;
const int MISO_PIN = 2;
const int SCK_PIN = 16;

SPIClass CustomSPI;

// 设置wifi信息,更换为你的wifi设置
const char *ssid = "xxx";
const char *password = "xxx";

// NTP相关参数,设置NTP服务器为阿里NTP服务器
const char *ntpServer = "ntp1.aliyun.com";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;

char timeStr_bj[9];
char dateStr_bj[11];
char timeStr_gmt[9];

// FTP服务器配置
#define FTP_USER "ftp"
#define FTP_PASSWORD "ftp"

// 上一次执行的时间,初始化为0
unsigned long previousExecutionTime = 0;
// 执行间隔时间,单位为毫秒,这里设置为60000毫秒,即1分钟
const unsigned long INTERVAL_MS = 60000;

String printLocalTime()
{
  struct tm timeinfo;
  if (!getLocalTime(&timeinfo))
  {
    Serial.println("Failed to obtain time");
    return "";
  }

  char formattedTimeBuffer[30];                                                                // 为格式化的时间字符串分配足够的缓冲区
  strftime(formattedTimeBuffer, sizeof(formattedTimeBuffer), "%Y-%B-%d  %H:%M:%S", &timeinfo); // 使用 strftime 将 timeinfo 转换为格式化的字符串

  String formattedTime = formattedTimeBuffer; // 将格式化后的字符串复制到 String 对象中
  return formattedTime;
}

/**
 * 将温度和湿度数据写入指定路径的CSV文件中。
 * 
 * @param path 指定的CSV文件路径。
 * @param timeStr 记录的时间字符串。
 * @param humidity 湿度值。
 * @param temperature 温度值。
 * 
 * 函数首先尝试打开文件以追加模式写入。如果文件成功打开,将依次写入时间字符串、湿度和温度值,
 * 每个数据项之间用逗号分隔,并在温度值后换行。写入完成后,关闭文件并打印完成信息。
 * 如果打开文件时出现错误,将打印错误信息和文件路径。
 */
void WriteCSVRecord(const char *path, const char *timeStr, float humidity, float temperature)
{
  myFile = SD.open(path, FILE_APPEND);

  if (myFile)
  {
    Serial.printf("Writing to %s ", path);
    myFile.print(timeStr);
    myFile.print(",");
    myFile.print(humidity, 2);
    myFile.print(",");
    myFile.println(temperature, 2);
    myFile.close();
    Serial.println("completed.");
  }
  else
  {
    Serial.println("error opening file ");
    Serial.println(path);
  }
}

void ReadFile(const char *path)
{
  myFile = SD.open(path);

  if (myFile)
  {
    Serial.printf("Reading file from %s\n", path);
    while (myFile.available())
    {
      // Serial.write(myFile.read());
      Serial.println("Read succeded");
    }
    myFile.close();
  }
  else
  {
    char error_msg[64];
    sprintf(error_msg, "error opening %s", path);
    Serial.println(error_msg);
  }
}

void environment()
{
  h = dht.readHumidity();
  t = dht.readTemperature();
  Serial.printf("Humidity: %f \n", h);
  Serial.printf("Temperature: %f \n", t);
}
void setup()
{
  Serial.begin(9600);
  delay(500);
  dht.begin();
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP()); // 记下运行时生成的IP地址,后面会用到
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  SPIFFS.begin(true);
  CustomSPI.begin(SCK_PIN, MISO_PIN, MOSI_PIN, CS);

  while (!Serial)
  {
    ;
  }

  Serial.println("Initializing sd card...");

  if (!SD.begin(CS, CustomSPI, 1000000))
  {
    Serial.println("initialization failed!");
    return;
  }
  else
  {
    Serial.println("SD card initialization succeeded.");
  }

  // // 配置FTP

ftp.addUser(FTP_USER, FTP_PASSWORD); // 添加FTP用户

ftp.addFilesystem("SD", &SD); // 注册SD卡文件系统
ftp.addFilesystem("SPIFFS", &SPIFFS); // 注册SPIFFS文件系统

ftp.begin(); // 启动FTP服务

Serial.println("FTP server started"); // 打印启动信息}


void loop()
{
  unsigned long currentMillis = millis(); // 获取当前毫秒时间戳

  // 检查是否已过去一分钟
  if (currentMillis - previousExecutionTime >= INTERVAL_MS)
  {
    previousExecutionTime = currentMillis; // 更新上一次执行的时间戳

    environment(); // 执行环境相关操作
    String localTimeStr = printLocalTime(); // 获取本地时间字符串

    // 如果温度和湿度都不为零,则写入CSV文件
    if (h != 0 && t != 0)
    {
      WriteCSVRecord("/record.csv", localTimeStr.c_str(), h, t);
    }
  }
  // 处理FTP请求
  ftp.handle();
}

2.2 如果你是使用的PlatfromIO IDE可以把以下内容复制到你的platformio.ini里

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 9600
lib_deps = 
	adafruit/DHT sensor library@^1.4.6
	adafruit/Adafruit Unified Sensor@^1.1.14
	peterus/ESP-FTP-Server-Lib@^0.14.0

3. FTP命令行操作

3.1 步骤说明

  1. 打开命令提示符(Windows)或终端(macOS/Linux)。

  2. 输入以下命令连接到 FTP 服务器(请将 IP 地址替换为实际 FTP 服务器的 IP 地址):

  3. 输入用户名(默认为 “ftp”)和密码(默认为 “ftp”)。

  4. 输入 “ls” 或 “dir” 查看文件列表。

  5. 输入 “cd” 命令切换目录,例如 “cd /SD” 进入 “/SD” 目录。

  6. 输入 “lcd” 命令切换本地目录,例如 “lcd E:\temp” 进入 “E:\temp” 目录。

  7. 使用 “get” 或 “recv” 命令从 FTP 服务器下载文件,例如 “get record.csv” 下载 “record.csv” 文件。

  8. 使用 “put” 或 “send” 命令将文件上传到 FTP 服务器,例如 “put local_file.txt” 上传 “local_file.txt” 文件。

  9. 输入 “bye” 或 “quit” 命令退出 FTP 客户端。
    10.更多命令直接输入"help"来了解

3.2 我用如下步骤下载了SD卡中的record.csv到电脑上:

C:\Users\User>ftp 192.168.55.203
连接到 192.168.55.203。
220--- Welcome to FTP Server for ESP32 ---
220---        By Peter Buchegger       ---
220 --           Version 0.1           ---
200 Ok
用户(192.168.55.203:(none)): ftp
331 OK. Password required
密码:
230 OK.
ftp> cd SD
250 Ok. Current directory is /SD
ftp> lcd "E:\temp"
目前的本地目录 E:\temp。
ftp> dir
200 PORT command successful
150 Accepted data connection
drwxr-xr-x 1 owner group             0 Jan 01  1970 System Volume Information
-rw-r--r-- 1 owner group            16 Jan 01  1970 test.txt
-rw-r--r-- 1 owner group        113466 Jan 01  1970 record.csv
226 3 matches total
ftp: 收到 208 字节,用时 0.0120.80千字节/秒。
ftp> recv record.csv
200 PORT command successful
150 Accepted data connection
226 File successfully transferred
ftp: 收到 113466 字节,用时 1.1796.81千字节/秒。
ftp>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/569677.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Python | Leetcode Python题解之第46题全排列

题目&#xff1a; 题解&#xff1a; class Solution:def permute(self, nums):""":type nums: List[int]:rtype: List[List[int]]"""def backtrack(first 0):# 所有数都填完了if first n: res.append(nums[:])for i in range(first, n):# 动…

漫谈AI 时代的信息模型

模型化- 数字化转型的重要基石 在各行各业推行数字化转型过程中&#xff0c;构建信息化模型十分重要&#xff0c;它是数字化转型的基石。事实上&#xff0c;数字化转型的核心是“万物皆模型”&#xff0c;在工业领域&#xff0c;以德国为主导的工业4.0 发展进程中&#xff0c;…

超越5G:迈向6G网络传感前沿的革命性飞跃

6G推动的传感技术发展有望将人类感官拓展到目前的极限。从精确测绘到活动识别&#xff0c;联网传感揭示了看不见的事物&#xff0c;使我们能够理解和预测以前未知的周围环境。高精度定位、增强人类感官和手势/活动识别的无缝集成预示着未来机器将以前所未有的自主性运行... 在飞…

安全AI未来 | C3安全大会 · 2024,数据驱动 AI原生

数字为时代变革注入动力&#xff0c;AI为重塑社会文明带来原力。数智浪潮中&#xff0c;我们见证着时代跃迁的巨变&#xff0c;面临着适变、应变、驭变的挑战。 数字驱动、AI原生。数字的流动不仅承载着信息&#xff0c;更将激活未来的无限价值&#xff1b;AI&#xff0c;不…

为什么要写技术方案?

技术方案是为研究解决各类技术问题&#xff0c;有针对性&#xff0c;系统性的提出的方法、应对措施及相关对策。技术方案设计是一个技术开发者必备的能力&#xff0c;特别是对于高级、资深、架构师等角色。技术方案设计不仅能够帮助我们明确需求&#xff0c;规划架构&#xff0…

【数据库】三、数据库SQL语言命令(基础从入门到入土)

【全文两万多字&#xff0c;涵盖大部分常见情况&#xff0c;建议点赞收藏】 目录 文章目录 目录安装SQL语言1.使用2.DATABASE查看所有库新建数据库修改数据库删除数据库连接数据库 3.TABLE创建表查看库所有表删除表查看表信息重命名表修改表字段&#xff08;列&#xff09;表中…

自动批量将阿里云盘文件发布成WordPress文章脚本源码(以RiPro主题为例含付费信息下载地址SEO等自动设置)源码

背景 很多资源下载站&#xff0c;付费资源下载站&#xff0c;付费内容查看等都可以用WordPress站点发布内容&#xff0c;这些站点一般会基于一个主题&#xff0c;付费信息作为文章附属的信息发布&#xff0c;底层存储在WP表里&#xff0c;比如日主题&#xff0c;子比主题等。 …

js的算法-插入排序(直接插入排序)

插入排序 插入排序是一种简单直接的排序方法&#xff0c;其基本思想是每次将一个待排序的记录按其关键字大小插入到前面已经排好序的子序列&#xff0c;直到全部记录插入完成。由插入排序的思想可以引申出三个重要的排序算法&#xff1a; 直接插入排序、折半插入排序和希尔排序…

一份本金 能得两份利息?

构建完善的量化交易策略&#xff0c;需要了解多种交易标的。有的产品在特殊时间可以产生超额收益。 1天期的国债逆回购的手续费为万0.1。 看似较低&#xff0c;因为每笔最小手续费是0.1元&#xff0c;如果投资者买入的金额较小&#xff08;比如小于1w&#xff09;&#xff0c;…

bugku ezbypass

bugku ezbypass 1.代码审计 2.题目代码如下所示 <?php error_reporting(0); highlight_file(__FILE__);if (isset($_POST[code])) {$code $_POST[code];if (strlen($code) < 105){if (is_string($code)) {if (!preg_match("/[a-zA-Z0-9#%^&*:{}\-<\?>…

怎样用PHP语言实现远程控制三路开关

怎样用PHP语言实现远程控制三路开关呢&#xff1f; 本文描述了使用PHP语言调用HTTP接口&#xff0c;实现控制三路开关&#xff0c;三路开关可控制三路照明、排风扇等电器。 可选用产品&#xff1a;可根据实际场景需求&#xff0c;选择对应的规格 序号设备名称厂商1智能WiFi墙…

政企单位内外网数据交互,如何保障安全性和合规性?

政府内外网隔离是一种网络安全措施&#xff0c;旨在保护政府内部网络的安全性和保密性。根据国家法律要求&#xff0c;涉及国家秘密的计算机信息系统与公共网络之间必须实行物理隔离。这意味着这些系统应该被完全隔离开来&#xff0c;以防止任何未经授权的访问或数据泄露。其次…

Linux服务器安装谷歌浏览器

当我们使用自动化的时候&#xff0c;还想要将它部署到服务器上那么我们就需要安装谷歌或者其他浏览器&#xff0c;这里是以谷歌浏览器为例子 首先就是你的有安装包 我们到官网下载&#xff1a;https://www.google.cn/intl/zh-CN/chrome/&#xff0c;需要科学上网 进入官网之…

Python蜘蛛侠

目录 写在前面 蜘蛛侠 编写代码 代码分析 更多精彩 写在后面 写在前面 本期小编给大家推荐一个酷酷的Python蜘蛛侠&#xff0c;一起来看看叭~ 蜘蛛侠 蜘蛛侠&#xff08;Spider-Man&#xff09;是美国漫威漫画宇宙中的一位标志性人物&#xff0c;由传奇创作者斯坦李与艺…

工信部政策要求试点城市20%资金奖励中小企业用SaaS上云转型数字化

随着数字经济的不断发展&#xff0c;中小企业也迎来了前所未有的机遇和挑战。为了持续推动中小企业数字化转型&#xff0c;工信部出台了一项新政策&#xff0c;主要通过资金奖励的方式&#xff0c;鼓励中小企业采纳软件即服务&#xff08;SaaS&#xff09;模式&#xff0c;实现…

每日OJ题_BFS解决拓扑排序①_力扣207. 课程表

目录 拓扑排序和图的介绍 ①力扣207. 课程表 解析代码 拓扑排序和图的介绍 拓扑排序简单来说就是找到做事情的先后顺序&#xff08;拓扑排序的结果可能不是唯一的&#xff09;。 学习拓扑排序前先简单学习图的基本概念&#xff1a; 图是由顶点集合及顶点间的关系组成的一种…

Pytorch常用的函数(八)常见优化器SGD,Adagrad,RMSprop,Adam,AdamW总结

Pytorch常用的函数(八)常见优化器SGD,Adagrad,RMSprop,Adam,AdamW总结 在深度学习中&#xff0c;优化器的目标是通过调整模型的参数&#xff0c;最小化&#xff08;或最大化&#xff09;一个损失函数。 优化器使用梯度下降等迭代方法来更新模型的参数&#xff0c;以使损失函数…

windows系统实现postgresql数据库定时备份

在windows系统中&#xff0c;大家通常可能会遇到手动备份数据库、周期性的执行脚本等情况。如果每次手动去做的话不免有些麻烦&#xff0c;而且容易忘记。用过Linux的同学都知道用crontab就可以定时调用shell脚本来实现定时任务的执行&#xff0c;那么在windows系统怎么实现呢&…

IMU用于评估驾驶中颈部受伤风险

近日&#xff0c;一支由西班牙和意大利科研人员组成的联合团队成功研发了一种创新车载监控系统&#xff0c;该系统巧妙结合了IMU和红外激光传感器技术&#xff0c;旨在深入研究并有效评估驾驶员在紧急制动情境下颈部受伤的风险。 实验中&#xff0c;科研团队采用了一款低成本的…

最新国内敏捷调研报告:2023中国企业敏捷实践白皮书

在人工智能技术飞速发展&#xff0c;组织面临的复杂性和多变性不断加剧的背景下&#xff0c;《2023中国企业敏捷实践白皮书》通过广泛的调查&#xff0c;洞察剧变之下&#xff0c;谁在逆流而上&#xff0c;如何逆流而上。 敏捷作为适应市场变化的关键策略&#xff0c;已被越来越…
最新文章