ESP32 入门笔记06: WIFI时钟 + FreeRTOS+《两只老虎》 (ESP32 for Arduino IDE)

news2025/7/11 2:39:28

ESP32+FreeRTOS

Esp32 模块中已经提供了 FreeRTOS(实时操作系统)固件。

FreeRTOS有助于提高系统性能管理模块的资源。FreeRTOS允许用户处理多项任务,如测量传感器读数,发出网络请求,控制电机速度等,所有这些任务都可以同时独立运行。

FreeRTOS为不同的应用程序提供了多个API。这些 API 可用于创建任务并使其在不同内核上运行。您需要创建任务以将代码的特定部分分配给特定内核。您还可以确定代码将在哪个内核上运行的优先级。

硬件

在这里插入图片描述

软件

在这里插入图片描述

tone() 函数

Arduino 内置函数:Reference > Language > Functions > Advanced io > Tone

在引脚上生成指定频率(和 50% 占空比)的方波。可以指定持续时间,否则波形会一直持续到调用 noTone()。该引脚可以连接到压电蜂鸣器或其他扬声器以播放音调。 一次只能产生一种音调。如果一个音调已经在另一个引脚上播放,则对tone() 的调用将无效。如果音调在同一个引脚上播放,则呼叫将设置其频率。 使用tone() 函数会干扰引脚3 和11 上的PWM 输出(在Mega以外的板上)。 不可能产生低于 31Hz 的音调

语法

tone(pin, frequency) // 语法一
tone(pin, frequency, duration) // 语法二
tone(17, 1760, 1000, 0);  // 17:管脚  1760:频率 1000:延时 0:通道

在这里插入图片描述

入口参数:

  • pin: 生成音调的 Arduino 引脚。
  • frequency: 以赫兹为单位的音调频率。允许的数据类型: unsigned int 无符号整数。
  • duration: 以毫秒为单位的音调持续时间(可选)。允许的数据类型:unsigned long

noTone()函数

停止生成由tone() 触发的方波。如果没有生成音调,则无效。

语法

noTone(pin)

注意: 如果您想在多个引脚上播放不同的音高,您需要在一个引脚上调用 noTone(),然后再在下一个引脚上调用tone()。

示例程序P1

开发环境是VSCode + PlatformIO IDE

#include <Arduino.h>
#include <ESP32Tone.h>
#include <U8g2lib.h>
#include <Wire.h>

// buzzer pin
#define BUZZER 19
#define ADC_PIN 34
uint16_t adc = 0;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); // U8G2_R0:屏幕旋转0°度


/**
  * @brief  屏幕显示界面1
  * @param  无
  * @param  无
  * @retval adc:检测电池电量ADC34
  */
void page1(int adc) {
  u8g2.setFont(u8g2_font_helvR08_tf); //设置字体 字号 字形
  u8g2.setFontPosTop();  // 设置定位的位置以字符顶开始
  u8g2.setCursor(0,0);  // 设置屏幕坐标
  u8g2.print(String("ADC:") + String(adc));
  u8g2.nextPage();//刷新屏幕
}

/**
  * @brief  《两只老虎》简谱
  * @param  无
  * @param  无
  * @retval count:计数
  */
void two_tigers_music_play()
{
byte count = 0;                 // byte 占1个字节 1*8bit=8位 0~256 节省内存
// low 1-7 低音
unsigned int  LOW_1 = 262;      // unsigned int 占4个字节 4*8bit=32位  0~4294967295
unsigned short LOW_1_P_5 = 277; // unsigned short 等于 uint16_t
uint16_t LOW_2 = 294;           // uint16_t 占2个字节 2*8bit=16位  0~65535
uint16_t LOW_2_P_5 = 311;
uint16_t LOW_3 = 330;
uint16_t LOW_4 = 349;
uint16_t LOW_4_P_5 = 370;
uint16_t LOW_5 = 392;
uint16_t LOW_5_P_5 = 415;
uint16_t LOW_6 = 440;
uint16_t LOW_6_P_5 = 466;
uint16_t LOW_7 = 494;

for (count = 0; count < 2; count++) // 每句歌词唱两遍
{
  tone(BUZZER, LOW_1);
  delay(500);
  tone(BUZZER, LOW_2);
  delay(500);
  tone(BUZZER, LOW_3);
  delay(500);
  tone(BUZZER, LOW_1);
  delay(500);
  
  noTone(BUZZER);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER, LOW_3);
  delay(500);
  tone(BUZZER, LOW_4);
  delay(500);
  tone(BUZZER, LOW_5);
  delay(1000);

  noTone(BUZZER);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER, LOW_5);
  delay(350);
  tone(BUZZER, LOW_6);
  delay(150); 
  tone(BUZZER, LOW_5);
  delay(350);
  tone(BUZZER, LOW_4);
  delay(150); 
  tone(BUZZER, LOW_3);
  delay(500);
  tone(BUZZER, LOW_1);
  delay(500);

  noTone(BUZZER);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER, LOW_1_P_5);
  delay(500);
  tone(BUZZER, LOW_5_P_5);
  delay(500);
  tone(BUZZER, LOW_1_P_5);
  delay(1000);

  noTone(BUZZER);
  delay(500);
}

} 

/**
  * @brief  任务2函数
  * @param  无
  * @param  无
  * @retval pvParameters:
  */
void task_2( void * pvParameters ){
for(;;){
  adc = analogRead(ADC_PIN);
  page1(adc); // 显示电量
  vTaskDelay(1);
}
}
/**
  * @brief  任务3函数
  * @param  无
  * @param  无
  * @retval pvParameters:
  */
void task_3( void * pvParameters ){
for(;;){
  two_tigers_music_play();// 播放营业
  vTaskDelay(1);
}
}

/**
  * @brief  初始化setup()
  * @param  无
  * @param  无
  * @retval 
  */
void setup() {
  pinMode(BUZZER, OUTPUT);
  pinMode(ADC_PIN, INPUT);
  u8g2.enableUTF8Print();
  u8g2.setI2CAddress(0x3C*2);
  u8g2.begin();
  u8g2.firstPage();
  do
  {
    page1(adc);
  }while(u8g2.nextPage());


  xTaskCreatePinnedToCore(task_2, "task_2", 4096, NULL, 0, NULL, 1);
  xTaskCreatePinnedToCore(task_3, "task_3", 4096, NULL, 8, NULL, 1);
//xTaskCreatePinnedToCore 函数参数说明:
// task_2:实现任务的函数名称(task1)
// "task_2":任务的任何名称(“ task1”等)
// 4096:分配给任务的堆栈大小,以字为单位
// NULL:任务输入参数(可以为NULL)
// 2:任务的优先级(0是最低优先级)
// NULL:任务句柄(可以为NULL)
// 1:任务将运行的ESP32D的内核ID(0或1)
}

void loop() {
  vTaskDelay(1);
}



示例程序P2

开发环境是VSCode + PlatformIO IDE

/*
1.ESP32 NTP Client-Server: Get Date and Time (Arduino IDE) : https://randomnerdtutorials.com/esp32-date-time-ntp-client-server-arduino/
2.ESP32 Weather Station Interface PCB Shield (Temperature, Humidity, Pressure, Date and Time):https://randomnerdtutorials.com/esp32-weather-station-pcb/
3.esp32获取网络天气时钟--桌面旋转太空人天气预报站: https://blog.csdn.net/DWX_top/article/details/120650278
*/

#include <Arduino.h>
// #include <ESP32Tone.h> // tone库 ESP32 for Arduino IDE  
#include <U8g2lib.h>// 屏幕显示依赖库
#include <Wire.h>
#include <WiFi.h>
#include <time.h>
// buzzer pin
#define BUZZER 19
#define ADC_PIN 34
#define BUTTON 18
uint16_t adc = 0;
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); // U8G2_R0:屏幕旋转0°度
// Insert your network credentials
const char* ssid     = "CMCC-e47q";// wifi名称
const char* password = "23vc6uxj"; // wifi 密码

// NTP Server Details
const char* ntpServer = "pool.ntp.org"; //"ntp.ntsc.ac.cn";
const long  gmtOffset_sec = 28800;  // 北京时区
const int   daylightOffset_sec = 3600;

uint16_t alarm_clock_hour = 0;
uint16_t alarm_clock_minute = 0;
/**
  * @brief  屏幕界面1
  * @param  adc :读取电池的ADC
  * @retval alarm_clock_minute: 时钟的分钟数值
  */
uint16_t page1(uint16_t adc) {
  //DATE AND TIME
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    //Serial.println("Failed to obtain time");
  }
  //Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
  
  //GET DATE
  //Get full weekday name
  char weekDay[10];
  strftime(weekDay, sizeof(weekDay), "%a", &timeinfo);
  //Get day of month
  char dayMonth[4];
  strftime(dayMonth, sizeof(dayMonth), "%d", &timeinfo);
  //Get abbreviated month name
  char monthName[5];
  strftime(monthName, sizeof(monthName), "%b", &timeinfo);
  //Get year
  char year[6];
  strftime(year, sizeof(year), "%Y", &timeinfo);

  //GET TIME
  //Get hour (12 hour format)
  /*char hour[4];
  strftime(hour, sizeof(hour), "%I", &timeinfo);*/
  
  //Get hour (24 hour format)
  char hour[4];
  strftime(hour, sizeof(hour), "%H", &timeinfo);
  alarm_clock_hour = atoi(hour);  // c标准库函数-- atoi() 将字符串转换为整型
  
  //Get minute
  char minute[4];
  strftime(minute, sizeof(minute), "%M", &timeinfo);
  alarm_clock_minute = atoi(minute); // c标准库函数-- atoi() 将字符串转换为整型
  
  u8g2.firstPage();
  do{
	  u8g2.setFont(u8g2_font_timR08_tf); //设置字体 字号 字形
      u8g2.setFontPosTop();  // 设置定位的位置以字符顶开始
	  u8g2.setCursor(0,0);  // 设置屏幕坐标
	  u8g2.print(String("bat:") + String(adc));
  
	  u8g2.setFont(u8g2_font_timR18_tf); //设置字体 字号 字形
	  u8g2.setFontPosTop();  // 设置定位的位置以字符顶开始
	  u8g2.setCursor(30,10);  // 设置屏幕坐标
	  u8g2.print(String(hour) + String(":") + String(minute)); // 时 分

	  u8g2.setFont(u8g2_font_timR10_tf); //设置字体 字号 字形
	  u8g2.setFontPosTop();  // 设置定位的位置以字符顶开始
	  u8g2.setCursor(16,40);  // 设置屏幕坐标
	  u8g2.print(String(weekDay) + String(",") + String(dayMonth) + String(" ") + String(monthName) + String(" ")+String(year)); // 星期 , 日 月 年
  
  }
  while(u8g2.nextPage());//刷新屏幕
  vTaskDelay(100);
  return alarm_clock_minute;
}


/**
  * @brief  《两只老虎》简谱
  * @param  无
  * @param  无
  * @retval 无
  */
void two_tigers_music_play()
{
byte count = 0;                 // byte 占1个字节 1*8bit=8位 0~256 节省内存
// low 1-7 低音
unsigned int  LOW_1 = 262;      // unsigned int 占4个字节 4*8bit=32位  0~4294967295
unsigned short LOW_1_P_5 = 277; // unsigned short 等于 uint16_t
uint16_t LOW_2 = 294;           // uint16_t 占2个字节 2*8bit=16位  0~65535
uint16_t LOW_2_P_5 = 311;
uint16_t LOW_3 = 330;
uint16_t LOW_4 = 349;
uint16_t LOW_4_P_5 = 370;
uint16_t LOW_5 = 392;
uint16_t LOW_5_P_5 = 415;
uint16_t LOW_6 = 440;
uint16_t LOW_6_P_5 = 466;
uint16_t LOW_7 = 494;

for (count = 0; count < 2; count++) // 每句歌词唱两遍
{
  tone(BUZZER, LOW_1);
  delay(500);
  tone(BUZZER, LOW_2);
  delay(500);
  tone(BUZZER, LOW_3);
  delay(500);
  tone(BUZZER, LOW_1);
  delay(500);
  
  noTone(BUZZER);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER, LOW_3);
  delay(500);
  tone(BUZZER, LOW_4);
  delay(500);
  tone(BUZZER, LOW_5);
  delay(1000);

  noTone(BUZZER);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER, LOW_5);
  delay(350);
  tone(BUZZER, LOW_6);
  delay(150); 
  tone(BUZZER, LOW_5);
  delay(350);
  tone(BUZZER, LOW_4);
  delay(150); 
  tone(BUZZER, LOW_3);
  delay(500);
  tone(BUZZER, LOW_1);       
  delay(500);

  noTone(BUZZER);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER, LOW_1_P_5);
  delay(500);
  tone(BUZZER, LOW_5_P_5);
  delay(500);
  tone(BUZZER, LOW_1_P_5);
  delay(1000);

  noTone(BUZZER);
  delay(500);
}

} 

/**
  * @brief  任务2函数
  * @param  无
  * @param  无
  * @retval pvParameters:
  */
void task_2( void * pvParameters ){
for(;;){
  adc = analogRead(ADC_PIN);
  page1(adc); // 显示电量
  vTaskDelay(100);
}
}
/**
  * @brief  任务3函数
  * @param  无
  * @param  无
  * @retval pvParameters:
  */
void task_3( void * pvParameters ){
for(;;){
	if((alarm_clock_minute % 60) == 0 || digitalRead(BUTTON)== 0){
		two_tigers_music_play();// 整点播放 or 按键触发播放
	}
  vTaskDelay(1);
}
}

/**
  * @brief  初始化setup()
  * @param  无
  * @param  无
  * @retval 
  */
void setup() {
  Serial.begin(115200);
  pinMode(BUZZER, OUTPUT);
  pinMode(ADC_PIN, INPUT);
  pinMode(BUTTON,INPUT_PULLUP);
  
  u8g2.enableUTF8Print();
  u8g2.setI2CAddress(0x3C*2);
  u8g2.begin();
  u8g2.firstPage();
  do
  {
    page1(adc);
  }while(u8g2.nextPage());

  // Connect to Wi-Fi
  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.");
  
  // Init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

  xTaskCreatePinnedToCore(task_2, "task_2", 4096, NULL, 2, NULL, 1);
  xTaskCreatePinnedToCore(task_3, "task_3", 4096, NULL, 0, NULL, 1);
//xTaskCreatePinnedToCore 函数参数说明:
// task_2:实现任务的函数名称(task1)
// "task_2":任务的任何名称(“ task1”等)
// 4096:分配给任务的堆栈大小,以字为单位
// NULL:任务输入参数(可以为NULL)
// 2:任务的优先级(0是最低优先级)
// NULL:任务句柄(可以为NULL)
// 1:任务将运行的ESP32D的内核ID(0或1)
}

void loop() {
  vTaskDelay(1);
}

在这里插入图片描述


示例程序P3

ESP32的ADC 和DAC 使用要点总结:

  • 1.要用 dacWrite() 而非 analogWrite() 函数,前者 输出模拟信号,后者输出 PWM 信号;
  • 2.要使用analogReadMilliVolts() 直接读取电压,这个函数会结合衰减系数和特征曲线进行计算。
  • 3.要把esp32 库升级到2.0.5版本以上,否则 analogReadMilliVolts() 读数是错误的。
  • 4.使用电阻分压,使待测电压降低到2500mV以内。
  • 5.根据 ADC原始结果计算电压,可以使用公式:Vout = Dout * Vmax / Dmax
    - Vout :电压
    - Dout :ADC 原始数字读数。
    - Vmax :最大可测量输入模拟电压,请参阅 ADC 衰减。
    - Dmax:输出 ADC 原始数字读取结果的最大值,在 Single Read 模式下为 4095,在 Continuous Read 模式下为 4095。
/*
1.ESP32 NTP Client-Server: Get Date and Time (Arduino IDE) : https://randomnerdtutorials.com/esp32-date-time-ntp-client-server-arduino/
2.ESP32 Weather Station Interface PCB Shield (Temperature, Humidity, Pressure, Date and Time):https://randomnerdtutorials.com/esp32-weather-station-pcb/
3.esp32获取网络天气时钟--桌面旋转太空人天气预报站: https://blog.csdn.net/DWX_top/article/details/120650278
*/

#include <Arduino.h>
// #include <ESP32Tone.h> // tone库 ESP32 for Arduino IDE  
#include <U8g2lib.h>// 屏幕显示依赖库
#include <Wire.h>
#include <WiFi.h>
#include <time.h>
// BUZZER_PIN pin
#define BUZZER_PIN 19
#define ADC_PIN 34
#define BUTTON_PIN 18
// uint16_t adc = 0;
float volt = 0;

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); // U8G2_R0:屏幕旋转0°度
// Insert your network credentials
const char* ssid     = "CMCC-e47q";// wifi名称
const char* password = "23vc6uxj"; // wifi 密码

// NTP Server Details
const char* ntpServer = "pool.ntp.org"; //"ntp.ntsc.ac.cn";
const long  gmtOffset_sec = 28800;  // 北京时区
const int   daylightOffset_sec = 3600;

uint16_t alarm_clock_hour = 0;
uint16_t alarm_clock_minute = 0;
/**
  * @brief  屏幕界面1
  * @param  volt :读取电池的电压
  * @retval alarm_clock_minute: 时钟的分钟数值
  */
uint16_t page1(float volt) {
  //DATE AND TIME
  struct tm timeinfo;
  if(!getLocalTime(&timeinfo)){
    //Serial.println("Failed to obtain time");
  }
  //Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
  
  //GET DATE
  //Get full weekday name
  char weekDay[10];
  strftime(weekDay, sizeof(weekDay), "%a", &timeinfo);
  //Get day of month
  char dayMonth[4];
  strftime(dayMonth, sizeof(dayMonth), "%d", &timeinfo);
  //Get abbreviated month name
  char monthName[5];
  strftime(monthName, sizeof(monthName), "%b", &timeinfo);
  //Get year
  char year[6];
  strftime(year, sizeof(year), "%Y", &timeinfo);

  //GET TIME
  //Get hour (12 hour format)
  /*char hour[4];
  strftime(hour, sizeof(hour), "%I", &timeinfo);*/
  
  //Get hour (24 hour format)
  char hour[4];
  strftime(hour, sizeof(hour), "%H", &timeinfo);
  alarm_clock_hour = atoi(hour);  // c标准库函数-- atoi() 将字符串转换为整型
  
  //Get minute
  char minute[4];
  strftime(minute, sizeof(minute), "%M", &timeinfo);
  alarm_clock_minute = atoi(minute); // c标准库函数-- atoi() 将字符串转换为整型
  
  u8g2.firstPage();
  do{
	  u8g2.setFont(u8g2_font_timR08_tf); //设置字体 字号 字形
      u8g2.setFontPosTop();  // 设置定位的位置以字符顶开始
	  u8g2.setCursor(0,0);  // 设置屏幕坐标
	  u8g2.print(String("bat:") + String(volt));
  
	  u8g2.setFont(u8g2_font_timR18_tf); //设置字体 字号 字形
	  u8g2.setFontPosTop();  // 设置定位的位置以字符顶开始
	  u8g2.setCursor(30,10);  // 设置屏幕坐标
	  u8g2.print(String(hour) + String(":") + String(minute)); // 时 分

	  u8g2.setFont(u8g2_font_timR10_tf); //设置字体 字号 字形
	  u8g2.setFontPosTop();  // 设置定位的位置以字符顶开始
	  u8g2.setCursor(16,40);  // 设置屏幕坐标
	  u8g2.print(String(weekDay) + String(",") + String(dayMonth) + String(" ") + String(monthName) + String(" ")+String(year)); // 星期 , 日 月 年
  
  }
  while(u8g2.nextPage());//刷新屏幕
  vTaskDelay(100);
  return alarm_clock_minute;
}


/**
  * @brief  《两只老虎》简谱
  * @param  无
  * @param  无
  * @retval 无
  */
void two_tigers_music_play()
{
byte count = 0;                 // byte 占1个字节 1*8bit=8位 0~256 节省内存
// low 1-7 低音
unsigned int  LOW_1 = 262;      // unsigned int 占4个字节 4*8bit=32位  0~4294967295
unsigned short LOW_1_P_5 = 277; // unsigned short 等于 uint16_t
uint16_t LOW_2 = 294;           // uint16_t 占2个字节 2*8bit=16位  0~65535
uint16_t LOW_2_P_5 = 311;
uint16_t LOW_3 = 330;
uint16_t LOW_4 = 349;
uint16_t LOW_4_P_5 = 370;
uint16_t LOW_5 = 392;
uint16_t LOW_5_P_5 = 415;
uint16_t LOW_6 = 440;
uint16_t LOW_6_P_5 = 466;
uint16_t LOW_7 = 494;

for (count = 0; count < 2; count++) // 每句歌词唱两遍
{
  tone(BUZZER_PIN, LOW_1);
  delay(500);
  tone(BUZZER_PIN, LOW_2);
  delay(500);
  tone(BUZZER_PIN, LOW_3);
  delay(500);
  tone(BUZZER_PIN, LOW_1);
  delay(500);
  
  noTone(BUZZER_PIN);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER_PIN, LOW_3);
  delay(500);
  tone(BUZZER_PIN, LOW_4);
  delay(500);
  tone(BUZZER_PIN, LOW_5);
  delay(1000);

  noTone(BUZZER_PIN);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER_PIN, LOW_5);
  delay(350);
  tone(BUZZER_PIN, LOW_6);
  delay(150); 
  tone(BUZZER_PIN, LOW_5);
  delay(350);
  tone(BUZZER_PIN, LOW_4);
  delay(150); 
  tone(BUZZER_PIN, LOW_3);
  delay(500);
  tone(BUZZER_PIN, LOW_1);       
  delay(500);

  noTone(BUZZER_PIN);
  delay(500);
}

for (count = 0; count < 2; count++)
{
  tone(BUZZER_PIN, LOW_1_P_5);
  delay(500);
  tone(BUZZER_PIN, LOW_5_P_5);
  delay(500);
  tone(BUZZER_PIN, LOW_1_P_5);
  delay(1000);

  noTone(BUZZER_PIN);
  delay(500);
}

} 

/**
  * @brief  任务2函数
  * @param  无
  * @param  无
  * @retval pvParameters:
  */
void task_2( void * pvParameters ){

for(;;){
  // volt = analogRead(ADC_PIN) *4.2 / 4095;           //  ADC 原始结果计算电压公式:Vout = Dout * Vmax / Dmax
  volt = analogReadMilliVolts(ADC_PIN) * 11 / 1000.0;  // 10k + 1k 电阻串联分4.2V电压  1V = 1000mV
  page1(volt); // 显示电量
  vTaskDelay(100);
}
}
/**
  * @brief  任务3函数
  * @param  无
  * @param  无
  * @retval pvParameters:
  */
void task_3( void * pvParameters ){
for(;;){
	if((alarm_clock_minute % 60) == 0 || digitalRead(BUTTON_PIN)== 0){
		two_tigers_music_play();// 整点播放 or 按键触发播放
	}
  vTaskDelay(1);
}
}

/**
  * @brief  初始化setup()
  * @param  无
  * @param  无
  * @retval 
  */
void setup() {
  Serial.begin(115200);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(ADC_PIN, INPUT);
  pinMode(BUTTON_PIN,INPUT_PULLUP);
  
  u8g2.enableUTF8Print();
  u8g2.setI2CAddress(0x3C*2);
  u8g2.begin();
  u8g2.firstPage();
  do
  {
    page1(volt);
  }while(u8g2.nextPage());

  // Connect to Wi-Fi
  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.");
  
  // Init and get the time
  configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);

  xTaskCreatePinnedToCore(task_2, "task_2", 4096, NULL, 2, NULL, 1);
  xTaskCreatePinnedToCore(task_3, "task_3", 4096, NULL, 0, NULL, 1);
//xTaskCreatePinnedToCore 函数参数说明:
// task_2:实现任务的函数名称(task1)
// "task_2":任务的任何名称(“ task1”等)
// 4096:分配给任务的堆栈大小,以字为单位
// NULL:任务输入参数(可以为NULL)
// 2:任务的优先级(0是最低优先级)
// NULL:任务句柄(可以为NULL)
// 1:任务将运行的ESP32D的内核ID(0或1)
}

void loop() {
  vTaskDelay(1);
}
float adc;
adc = analogRead(ADC_PIN) * 4.2 / 4095;           //  ADC 原始结果计算电压公式:Vout = Dout * Vmax / Dmax
adc = analogReadMilliVolts(ADC_PIN) * 11 / 1000.0;  // 10k + 1k 电阻串联分4.2V电压  1V = 1000mV

参考资料

  • [1] 【CSDN】使用ARDUINO UNO和无源蜂鸣器实现音乐-《两只老虎》

  • [2] 【CSDN】Arduino之运用u8gbil库控制OLED

  • [3] Mixly2.0 中自带u8g2和freeRTOS积木模块
    在这里插入图片描述

  • [4] 【RNT】ESP32 NTP Client-Server: Get Date and Time (Arduino IDE)

  • [5] 【RNT】ESP32 Weather Station Interface PCB Shield (Temperature, Humidity, Pressure, Date and Time)

  • [6] 【CSDN】esp32获取网络天气时钟–桌面旋转太空人天气预报站

  • [7]【B站】ESP32-S2 正确调用 ADC DAC库函数(Arduino 环境)

  • [8]【ESPRESSIF】Analog to Digital Converter (ADC)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

靶向肿瘤代谢,助力攻克癌症

肿瘤代谢的简介 肿瘤代谢的起源在于奥托沃伯格 (Otto Warburg) 的假设&#xff0c;他也因发现线粒体呼吸链复合物 IV 而获得 1931 年诺贝尔生理学或医学奖。Warburg 观察到&#xff0c;与正常组织相比&#xff0c;体外癌组织切片使用大量葡萄糖生成乳酸 (即使在有氧的情况下也是…

SBT10100VDC-ASEMI低压降贴片肖特基二极管SBT10100VDC

编辑-Z SBT10100VDC在TO-263封装里采用的2个芯片&#xff0c;其尺寸都是62MIL&#xff0c;是一款低压降贴片肖特基二极管。SBT10100VDC的浪涌电流Ifsm为150A&#xff0c;漏电流(Ir)为4uA&#xff0c;其工作时耐温度范围为-65~150摄氏度。SBT10100VDC采用金属硅芯片材质&#x…

QScintilla代码跳转时indicator工作不正确的问题

首先看我这几个文章&#xff0c;知道一下indicator是什么&#xff0c;以及上下文&#xff1a; https://biao2488890051.blog.csdn.net/article/details/126798996?spm1001.2014.3001.5502 目标&#xff1a; 我现在要做按住 ctrl 鼠标左键点击释放 发生函数/变量的 定义/声明…

Pandas中你一定要掌握的时间序列相关高级功能

&#x1f4a1; 作者&#xff1a;韩信子ShowMeAI &#x1f4d8; 数据分析实战系列&#xff1a;https://www.showmeai.tech/tutorials/40 &#x1f4d8; 本文地址&#xff1a;https://www.showmeai.tech/article-detail/389 &#x1f4e2; 声明&#xff1a;版权所有&#xff0c;转…

ceph浅谈

总谈 ceph简介 用上ceph&#xff0c;多台机器的磁盘空间在一起了&#xff0c;在一台机器上就可以看到使用所有空间。 还可以保存多份安全备份 存储先ceph&#xff0c;自我管理修复&#xff0c;跨机房&#xff0c;节点越多&#xff0c;并行化&#xff0c;论上&#xff0c;节点越…

【虚幻引擎UE】UE5 实现相机录制视频并导出(C++调用外部exe)

说明: 该功能暂不支持导出声音。 由于OpenCV3和UE5不太兼容,因此考虑制作外部exe实现视频合成。 一、创建渲染目标 二、创建Actor加场景捕获组件2D 三、创建UE5内的C++代码 1、实现 SavePicToFile 导出图片蓝图函数 .cpp文件 // Fill out your copyright notice in the De…

数字集成电路设计(二、Verilog HDL基础知识)

文章目录1. 语言要素1.1 空白符1.2 注释符1.3 标识符1.3.1 转义标识符1.4 关键字1.5 数值1.5.1 整数及其表示方式1.5.2 实数及其表示方式1.5.3 字符串及其表示方式2. 数据类型2.1 物理数据类型2.1.1 连线型2.1.2 寄存器型2.2 连线型和寄存器型数据类型的声明2.2.1 连线型数据类…

深入了解海豚调度DolphinScheduler

深入了解海豚调度DolphinScheduler一、海豚调度介绍二、海豚调度特性三、建议配置四、名词解释五、模块介绍六、功能介绍1.项目首页2.工作流定义3.工作流实例4.任务实例5.任务定义七、任务类型1.SQL2.SPARK节点3.Apache Zeppelin八、集群部署1.前置准备工作2.准备 DolphinSched…

实现注册与登录模块

目录 1、加载依赖 2、实现jwt工具类jwtUtil类 3、实现config.filter.JwtAuthenticationTokenFilter类 4、配置config.SecurityConfig类 5、创建后端api之前对数据库进行修改 6、写API一共需要的三个地方 7、实现三个接口 8、验证用户登录用API调试 9、https://jwt.io/解…

MySQL表的增删查改(CRUD)

文章目录前言一、新增数据二、查询数据全列查询指定列查询表达式查询指定别名查询去重查询排序查询条件查询分页查询三、修改数据四、删除数据前言 CRUD代表: 增加(create) ,查询(retrieve) ,更新(update) ,删除(delete) 单词首字母。 一、新增数据 SQL使用insert关键字来表…

二叉搜索树、红黑树详解、红黑树高的应用、TreeMap的应用(图文详解)-Kotlin版本代码

二叉搜索树 何为二叉搜索树&#xff1f; 二叉搜索树是一种特殊的二叉树&#xff0c;它的左子节点总是小于或等于根节点&#xff0c;而右子节点 总是大于或等于根节点。 如下图&#xff0c;即是一颗二叉搜索树。 对于二叉搜索树来说&#xff0c;中序遍历可以遍历按照节点值…

【JavaSE】重载和重写

前言&#xff1a; 作者简介&#xff1a;爱吃大白菜1132 人生格言:纸上得来终觉浅&#xff0c;绝知此事要躬行 如果文章知识点有错误的地方不吝赐教&#xff0c;和大家一起学习&#xff0c;一起进步&#xff01; 如果觉得博主文章还不错的话&#xff0c;希望三连支持&#xff01…

python--敲击木鱼积累功德小项目(更新版(2))

前言&#xff1a;前几天上课闲着没事写了一个python敲击木鱼积累功德的小项目&#xff0c;当时纯粹就是写着玩&#xff0c;回顾一下鼠标事件的东西还记不记得&#xff0c;发现这个博客的点赞和收藏量还挺高的&#xff0c;我当时也没有把它当回事&#xff0c;后面也有很多人问怎…

11.11一些资源整理和总结

使用python读取tensorboard文件中的数据并写入到excel当中去能够代替Originlab的画图软件&#xff08;macos&#xff09;Mac款origin来了&#xff01;还不来看看&#xff01;ptflops&#xff1a;计算网络参数FLOPs的工具[github] 4 中方式计算 FLOPs&#xff08;知乎&#xff0…

栈和队列实现的思路和代码

栈和队列第一节----栈什么是栈实现栈的基本思路各个接口函数的实现初始化栈销毁栈压栈出栈返回栈顶元素栈的判空栈的大小第二节----队列什么是队列实现队列的基本思路各个接口函数的实现队列的初始化队列的销毁队列的插入队列的删除返回队头元素和队尾元素队列的判空队列的大小…

使用DESeq2进行转录组原始count标准化和差异分析

转录组测序完成后&#xff0c;一般我们会获得一个原始 read count表达矩阵&#xff0c;其中行是基因&#xff0c;列是样品。常用的差异分析工具包括limma、edgeR和DESeq2。DESeq2在测序领域使用最为广泛&#xff08;google scholar引用高达43284次&#xff0c;edgeR为28076次&a…

MYSQL索引查询问题质疑

前言 我们在写mysql查询语句的时候&#xff0c;尤其是经验不足的同学肯定会想要怎么使用索引加快查询&#xff0c;或是我这样写到底会不会命中索引。那么现在我就列举几个常见的索引查询问题进行简单说明一下。&#xff08;欢迎互怼&#xff01;&#xff09; 1.问&#xff1a…

小学生python游戏编程arcade----游戏界面按钮实现事件实现的三种方法

小学生python游戏编程arcade----游戏界面按钮实现事件实现的三种方法前言游戏界面按钮实现事件实现的三种方法1、按钮定义及事件3种方法1.1 按钮定义1.2三种事件引用方法1.2.1 类法1.2.2 事件方法2,自定义方法函数1.2.3 事件方法3,使用装饰器处理onclick事件1.3 效果图1.4 代码…

第十四届蓝桥杯校模拟赛详解+代码(一)

“须知少时凌云志&#xff0c;自许人间第一流” 鄙人11月八号有幸参加学校蓝桥杯校选拔赛&#xff0c;题型为5道填空题&#xff0c;5道编程题&#xff0c;总时间为4小时。奈何能力有限&#xff0c;只完成了5道填空和3道编程大题&#xff0c;现进行自省自纠&#xff0c;分享学习…

艾美捷细胞计数试剂盒-8(CCK-8),一步到位

艾美捷细胞计数试剂盒-8&#xff08;CCK-8&#xff09;&#xff1a;用于简单准确的细胞增殖和细胞毒性测定的比色试剂盒。 艾美捷细胞计数试剂盒-8&#xff08;CCK-8&#xff09;特点&#xff1a; 1、一步到位&#xff0c;不含放射性同位素的即用溶液 2、与[3H]-胸苷掺入试验…