FastBond2阶段2——基于ESP32C3开发的简易IO调试设备

news2024/11/27 8:23:32

  • 1. 项目介绍

之前买了许多国产单片机esp32c3一直在吃灰,没有发挥它的真实价值。非常感谢硬禾组织的Fastbond2活动,刚好两者经过微妙的碰撞。恰可以用于FastBond2活动主题4 - 测量仪器(单片机开发测试领域),或者用于国产ESP32C3单片机简单应用开发教育等领域。回顾立项过程,且听我娓娓道来!

1.1 立项目标

设计用户操作界面,该设备具备简单易用的操作界面,外加显示屏SSD1306和旋转编码器进行显示和控制,用户后期可进行二次开发WiFi或蓝牙连接电脑或手机监控。

1.2 立项指标

  1. 多种数字和模拟信号的输入输出:用户可以选择不同的输入输出模式,并通过设备的操作界面进行设置。例如,用户可以选择某个GPIO口作为模拟输入引脚,然后通过设备的操作界面设置输入的电压值,以模拟外部信号的输入,达到调试简易传感器读取和执行器输出功能。
  2. 支持PWM输出、舵机控制特性:用户可以选择某个GPIO口作为PWM输出引脚,并通过设备的操作界面设置PWM输出的频率和占空比。用户还可以选择某个GPIO口作为舵机控制引脚,并通过设备的操作界面设置舵机的角度。
  3. 因此系统具有一定的电流输出能力、信号辨识能力和显示交互功能。 
  • 2. 市场应用介绍

《FastBond2阶段2——基于ESP32C3开发的简易IO调试设备》是一种基于ESP32C3芯片开发的简易IO调试设备。它具有小巧、便携、功能强大等特点,可广泛应用于各个领域的电子设备调试和开发过程中。

市场应用介绍如下:

  1. 电子产品调试:该设备可以作为一种便携式的IO调试工具,用于电子产品的调试和测试。它支持多种接口,如GPIO、I2C、SPI、UART等,可以方便地与各种电子设备进行连接和通信,帮助工程师快速调试和验证电路功能。

  2. 物联网设备开发:随着物联网技术的发展,越来越多的设备需要与互联网进行连接和通信。该设备可以作为物联网设备开发过程中的工具,帮助开发者快速连接和通信,实现设备与云平台的数据传输和控制。

  3. 教育培训:该设备具有简单易用的特点,适合在教育培训领域使用。学生可以通过该设备学习和实践各种电子接口和通信协议的使用,提高他们的电子技术能力和创新能力。

  4. 嵌入式系统开发:对于嵌入式系统开发者来说,该设备可以作为一种基础工具,用于快速原型设计和验证。通过该设备,开发者可以快速连接和测试各种外设,并进行相关的软硬件开发工作。

  5. DIY爱好者:该设备适合DIY爱好者使用,他们可以利用该设备进行各种创意项目的开发。无论是控制LED灯的亮灭,还是与其他传感器进行数据交互,都可以通过该设备实现,并为DIY爱好者们带来更多的乐趣和创造力。

综上所述,《FastBond2阶段2——基于ESP32C3开发的简易IO调试设备》具有广泛的市场应用前景。它可以满足不同领域的需求,为电子产品调试、物联网设备开发、教育培训、嵌入式系统开发和DIY爱好者等提供了简单、便捷、高效的解决方案。

  • 3. 项目设计思路

项目地址:Scheme-it | 嵌入式快速调试设备 | DigiKey

得捷电子的Scheme-it工具融合了原理图、框图和流程图绘制等功能,支持多种格式导出。并且,得捷电子提供原理图kicad格式导出的功能,同步导出对应器件的封装,减少查找封装的麻烦。Scheme-it无需专门下载安装,在浏览器在线运行,上手速度很快。这里我非常迅速画了系统的方案框图:

这里面的外设驱动详细内容见:【Arduino环境下驱动合宙esp32c3单片机基本外设】

  • 4. 项目方案框图和原理图解释

4.1 系统设计流程图

接下来就是一步一个脚印把模块调通,最后进行解耦实验,有机会就用3D打印机打印一个外壳。如系统设计流程图所示

系统设计流程图是一个用于描述系统设计过程的流程图。在这个流程中,首先进行的是项目立项,然后进入系统设计阶段,包括结构设计和硬件模块设计。在硬件模块设计中,又包括硬件模块设计和软件模块设计。然后进行联合调试,如果调试成功,就进行系统设计修改,如果调试失败,就回到硬件模块设计进行更改,直到调试成功。最后,进行是总结并记录归档。

4.2 电路原理图

这里采用kicad绘制的原理图,这里面的蜂鸣器电路设计有缺陷,因此我加250Ω电阻直接飞线绕过三极管驱动蜂鸣器,我之前画过电路图(设计有诸多不合理,欢迎大家批评指正),但从来都没有打板子,这是我第一次打板子验证项目,非常感谢硬禾给机会,太感动了!

设计用户操作界面,该设备具备简单易用的操作界面,外加显示屏SSD1306和旋转编码器进行显示和控制,用户后期可进行二次开发WiFi或蓝牙连接电脑或手机监控。
多种数字和模拟信号的输入输出:用户可以选择不同的输入输出模式,并通过设备的操作界面进行设置。 引出了开发板全部可用端口,其中包括GPIO、ADC、UART、IIC、SPI端口。

这里面的外设驱动详细内容见:【Arduino环境下驱动合宙esp32c3单片机基本外设】

  • 5. 设计中用到规定厂商的元器件介绍

这里采用了 乐鑫科技(Espressif)的ESP32-C3-MINI-1-N4,由于之前合宙esp32c3可以等效替代,对此采用这款合宙esp32c3开发板代替,是采用ESP32-C3-MINI-1-N4模组设计的。

ESP32­C3­MINI­1技术规格书

ESP32-C3 系列芯片

由于项目需要达到300元包邮,所以我选购了Pi400键盘系统

期待后期有发光发热的地方叫上鹏鹏哦!

  • 6. PCB绘制打板介绍及遇到的问题和解决方法

 6.1 PCB板图

工程整体采用两层板结构;

底层覆铜设计,右边是覆铜效果,左边没有覆铜效果;

采用esp32c3单片机放在中间,底部板载USB供电,靠上设计SSD1306屏幕显示,基本外设左右排开,左边有SPI、舵机端口、ADC和WS2812。右边设计有蜂鸣器和旋转编码器,中间开发板的端口全部引出。

设计的尺寸非常小宽7.37*长8.64,四周设计了立柱。

6.2 3D封装效果图

所选封装比较杂乱,偏向传统与现代工业融合

第一次下单 嘉立创返回说我没有阻焊层,修改ganber文件导出后,第二次下单工艺信息,大约5天左右就到啦!国产雄起

6.3 实物图

打板图

实物图

 6.4 遇到的问题

1. 蜂鸣器驱动设计错误,解决办法:直接连接IO口,不过pwm控制效果区别不明显

2. WS2812封装对应错误,解决办法:选择引出的GPIO驱动,完美!

  • 7. 关键代码及说明

总共迭代了四个版本

7.1 版本1.0

是通过ChatGPT生成的,然后结合自己开发的外设调试,搭建了基本框架,可以屏幕显示,有舵机、ws2812和ADC交互控制显示,需要安装以下5个库

  1. #include <U8g2lib.h>
  2. #include <Encoder.h>
  3. #include <ESP32Servo.h>
  4. #include <FastLED.h>
  5. #include <WS2812FX.h>
// #define ENCODER_DO_NOT_USE_INTERRUPTS
#include <U8g2lib.h>
#include <Encoder.h>
#include <ESP32Servo.h>
#include <FastLED.h>
#include <WS2812FX.h>
#define OLED_CLOCK 5
#define OLED_DATA 4
#define OLED_RESET U8X8_PIN_NONE
#define ENCODER_CLK 7
#define ENCODER_DT 6
#define ENCODER_SW 8
#define SERVO_PIN 19
#define LED_PIN 18
#define NUM_LEDS 4
#define SENSOR_PIN 0



U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/OLED_CLOCK, /* data=*/OLED_DATA, /* reset=*/OLED_RESET);  // ESP32 Thing, pure SW emulated I2C
Encoder encoder(ENCODER_CLK, ENCODER_DT);
// ESP32PWM pwm;
Servo myservo;  // create servo object to control a servo
CRGB leds[NUM_LEDS];
int currentMenu = 0;
int servoAngle = 0;
int ledColorIndex = 0;
int sensorValue = 0;
int encoderButtonState = 0;
long position = 0;
long newPos = 0;

void setup() {
  ESP32PWM::allocateTimer(0);
  ESP32PWM::allocateTimer(1);
  ESP32PWM::allocateTimer(2);
  ESP32PWM::allocateTimer(3);
  myservo.setPeriodHertz(50);             // standard 50 hz servo
  myservo.attach(SERVO_PIN, 1000, 2000);  // attaches the servo on pin 18 to the servo object
  Serial.begin(9600);
  u8g2.begin();
  u8g2.setFont(u8g2_font_ncenB14_tr);
  pinMode(ENCODER_SW, INPUT_PULLUP);
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  // pwm.setPeriodHertz(50);
  // pwm.attachServo(SERVO_PIN);
}

void loop() {
  u8g2.clearBuffer();

  switch (currentMenu) {
    case 0:  // Main menu
      u8g2.setCursor(0, 20);
      u8g2.print("1. Servo");
      u8g2.setCursor(0, 40);
      u8g2.print("2. WS2812");
      u8g2.setCursor(0, 60);
      u8g2.print("3. Sensor");
      break;

    case 1:  // Servo menu
      // int servoencoderValue = 0;
      u8g2.setCursor(0, 20);
      u8g2.print("Servo Angle: ");
      u8g2.setCursor(30, 40);
      u8g2.print(servoAngle);

      // Handle servo control
      servoAngle = servoAngle + checkencoder();
      if (servoAngle > 180) {
        servoAngle = 180;
      } else if (servoAngle < 0) {
        servoAngle = 0;
      }
      myservo.write(servoAngle);
      break;

    case 2:  // WS2812 menu
      // int LEDencoderValue = 0;
      u8g2.setCursor(0, 20);
      u8g2.print("LED Color: ");
      u8g2.setCursor(30, 40);
      u8g2.print(ledColorIndex);

      // Handle LED color control
      ledColorIndex = ledColorIndex + checkencoder();
      if (ledColorIndex < 0) {
        ledColorIndex = 0;
      } else if (ledColorIndex > 2) {
        ledColorIndex = 2;
      }
      setLedColor();
      break;

    case 3:  // Sensor menu
      u8g2.setCursor(0, 20);
      u8g2.print("Sensor Value: ");
      u8g2.setCursor(30, 40);
      u8g2.print(sensorValue);

      // Read sensor value
      sensorValue = analogRead(SENSOR_PIN);
      break;
  }

  u8g2.sendBuffer();
  // Handle menu navigation
  encoderButtonState = digitalRead(ENCODER_SW);
  if (encoderButtonState == LOW) {
    delay(50);  // Debounce delay
    encoderButtonState = digitalRead(ENCODER_SW);
    if (encoderButtonState == LOW) {
      currentMenu++;
      if (currentMenu > 3) {
        currentMenu = 0;
      }
      delay(200);  // Debounce delay
    }
  }
}
int checkencoder() {
  newPos = encoder.read();
  Serial.println("newPos:" + String(newPos) + "position:" + String(position));
  delay(1);
  if (newPos > position) {
    position = newPos;
    return 1;
  } else if (newPos < position) {
    position = newPos;
    return -1;
  }

  return 0;
}
void setLedColor() {
  switch (ledColorIndex) {
    case 0:
      leds[0] = CRGB::Red;
      leds[1] = CRGB::Red;
      leds[2] = CRGB::Red;
      leds[3] = CRGB::Red;
      break;

    case 1:
      leds[0] = CRGB::Green;
      leds[1] = CRGB::Green;
      leds[2] = CRGB::Green;
      leds[3] = CRGB::Green;
      break;

    case 2:
      leds[0] = CRGB::Blue;
      leds[1] = CRGB::Blue;
      leds[2] = CRGB::Blue;
      leds[3] = CRGB::Blue;
      break;
  }
  FastLED.show();
}

 7.2 版本1.1

增加了蜂鸣器控制,设计四级菜单,WS2812由三种颜色怎加到10种,解决旋转编码器无法减法控制,添加按键返回功能

// #define ENCODER_DO_NOT_USE_INTERRUPTS
#include <U8g2lib.h>
#include <Encoder.h>
#include <ESP32Servo.h>
#include <FastLED.h>
#include <WS2812FX.h>
#define OLED_CLOCK 5
#define OLED_DATA 4
#define OLED_RESET U8X8_PIN_NONE
#define ENCODER_CLK 7
#define ENCODER_DT 6
#define ENCODER_SW 8
#define SERVO_PIN 19
#define LED_PIN 18
#define NUM_LEDS 4
#define SENSOR_PIN 0
#define SENSOR_PIN2 1
#define BUZZER 13


U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/OLED_CLOCK, /* data=*/OLED_DATA, /* reset=*/OLED_RESET);  // ESP32 Thing, pure SW emulated I2C
// 创建Encoder对象
Encoder myEncoder(ENCODER_CLK, ENCODER_DT);
// ESP32PWM pwm;
Servo myservo;  // create servo object to control a servo
CRGB leds[NUM_LEDS];
int currentMenu = 0;
int servoAngle = 0;
int ledColorIndex = 0;
int sensorValue = 0;
int sensorValue2 = 0;
int BuzzerValue = 128;
int encoderButtonState = 0;
long position = 0;
long newPos = 0;
long oldPosition = 0;
int increment = 0;
int ws = 0;
void setup() {
  myservo.setPeriodHertz(50);             // standard 50 hz servo
  myservo.attach(SERVO_PIN, 1000, 2000);  // attaches the servo on pin 18 to the servo object
  Serial.begin(9600);
  u8g2.begin();
  u8g2.setFont(u8g2_font_ncenB14_tr);
  pinMode(ENCODER_SW, INPUT_PULLUP);
  pinMode(ENCODER_CLK, INPUT_PULLUP);
  pinMode(ENCODER_DT, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = getColor(-1);
  }
  FastLED.show();
  // pwm.setPeriodHertz(50);
  // pwm.attachServo(SERVO_PIN);
}

void loop() {
  u8g2.clearBuffer();
  switch (currentMenu) {
    case 0:  // Main menu
      u8g2.setCursor(30, 20);
      u8g2.print("Main menu");
      u8g2.setFont(u8g2_font_ncenB08_tr);
      u8g2.setCursor(0, 40);
      u8g2.print("1. Servo");
      u8g2.setCursor(0, 60);
      u8g2.print("2. WS2812");
      u8g2.setCursor(64, 40);
      u8g2.print("3. Sensor");
      u8g2.setCursor(64, 60);
      u8g2.print("4. Buzzer");
      break;

    case 1:  // Servo menu
      // int servoencoderValue = 0;
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("Servo Angle: ");
      u8g2.setCursor(30, 40);
      u8g2.print(servoAngle);
      u8g2.sendBuffer();
      while (1) {
        if (checkencoder() == true) {
          setservo();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    case 2:  // WS2812 menu
      // int LEDencoderValue = 0;
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("LED Color: ");
      u8g2.setCursor(30, 40);
      u8g2.print(ledColorIndex);
      u8g2.sendBuffer();
      // Handle LED color control
      while (1) {
        if (checkencoder() == true) {
          setLedColor();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    case 3:  // Sensor menu
      u8g2.setFont(u8g2_font_ncenB08_tr);
      u8g2.setCursor(10, 30);
      u8g2.print("Sensor1: ");
      u8g2.setCursor(64, 30);
      u8g2.print(sensorValue);
      u8g2.setCursor(10, 60);
      u8g2.print("Sensor2: ");
      u8g2.setCursor(64, 60);
      u8g2.print(sensorValue2);

      // Read sensor value
      sensorValue = analogRead(SENSOR_PIN);
      sensorValue2 = analogRead(SENSOR_PIN2);
      break;

    case 4:  // Buzzer menu
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("Buzzer Value: ");
      u8g2.setCursor(30, 40);
      u8g2.print(BuzzerValue);
      // Handle Buzzer control
      while (1) {
        if (checkencoder() == true) {
          setbuzzer();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;
  }
  increment = 0;
  u8g2.sendBuffer();
  // Handle menu navigation
  if (checkswitch() == true) {
    currentMenu++;
    if (currentMenu > 4) {
      currentMenu = 0;
    }
    delay(200);  // Debounce delay
  }
}
bool checkencoder() {
  long newPosition = myEncoder.read();
  if (newPosition != oldPosition) {
    // Serial.println(newPosition + String(";") + oldPosition);
    increment = newPosition - oldPosition;
    oldPosition = newPosition;
    return true;
  }
  return false;
}
bool checkswitch() {
  encoderButtonState = digitalRead(ENCODER_SW);
  if (encoderButtonState == LOW) {
    delay(50);  // Debounce delay
    encoderButtonState = digitalRead(ENCODER_SW);
    if (encoderButtonState == LOW) {
      return true;
    } else {
      return false;
    }
  } else {
    return false;
  }
}
void setLedColor() {
  ledColorIndex = ledColorIndex + increment;
  if (ledColorIndex < 0) {
    ledColorIndex = 0;
  } else if (ledColorIndex > 10) {
    ledColorIndex = 10;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(ledColorIndex);
  u8g2.sendBuffer();
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = getColor(ledColorIndex);
  }
  FastLED.show();
  delay(1);
}
void setservo() {
  servoAngle = servoAngle + increment*3;
  if (servoAngle > 180) {
    servoAngle = 180;
  } else if (servoAngle < 0) {
    servoAngle = 0;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(servoAngle);
  u8g2.sendBuffer();
  myservo.write(servoAngle);
}

void setbuzzer() {
  BuzzerValue = BuzzerValue + increment*8;
  if (BuzzerValue > 255) {
    BuzzerValue = 255;
  } else if (BuzzerValue < 0) {
    BuzzerValue = 0;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(BuzzerValue);
  u8g2.sendBuffer();
  analogWrite(BUZZER, BuzzerValue);
}

CRGB getColor(int index) {
  switch (index) {
    case 0:
      return CRGB::Red;
    case 1:
      return CRGB::Green;
    case 2:
      return CRGB::Blue;
    case 3:
      return CRGB::Yellow;
    case 4:
      return CRGB::Magenta;
    case 5:
      return CRGB::Cyan;
    case 6:
      return CRGB::White;
    case 7:
      return CRGB::Purple;
    case 8:
      return CRGB::Orange;
    case 9:
      return CRGB::Pink;
    default:
      return CRGB::Black;
  }
}

 7.3 版本1.2

增加了蓝牙交互,设计五级菜单,通过蓝牙上传设备状态信息,并且可接收手机端数据,但未完成控制设备。值得注意这个版本最稳定

// #define ENCODER_DO_NOT_USE_INTERRUPTS
#include <U8g2lib.h>
#include <Encoder.h>
#include <ESP32Servo.h>
#include <FastLED.h>
#include <WS2812FX.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#define OLED_CLOCK 5
#define OLED_DATA 4
#define OLED_RESET U8X8_PIN_NONE
#define ENCODER_CLK 7
#define ENCODER_DT 6
#define ENCODER_SW 8
#define SERVO_PIN 19
#define LED_PIN 18
#define NUM_LEDS 4
#define SENSOR_PIN 0
#define SENSOR_PIN2 1
#define BUZZER 13
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"  // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
//创建Bluetooth对象
BLECharacteristic *pCharacteristic;
//创建SSD1306屏幕对象
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/OLED_CLOCK, /* data=*/OLED_DATA, /* reset=*/OLED_RESET);  // ESP32 Thing, pure SW emulated I2C
// 创建Encoder对象
Encoder myEncoder(ENCODER_CLK, ENCODER_DT);
// ESP32PWM pwm;
Servo myservo;  // create servo object to control a servo
CRGB leds[NUM_LEDS];
int currentMenu = 0;
int servoAngle = 0;
int ledColorIndex = 0;
int sensorValue = 0;
int sensorValue2 = 0;
int BuzzerValue = 128;
int encoderButtonState = 0;
long position = 0;
long newPos = 0;
long oldPosition = 0;
int increment = 0;
bool deviceConnected = false;
char BLEbuf[256] = { 0 };
uint32_t cnt = 0;
String message_c;
char *message;
// const char *message1;
class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer) {
    deviceConnected = true;
  };

  void onDisconnect(BLEServer *pServer) {
    deviceConnected = false;
  }
};

class MyCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    std::string rxValue = pCharacteristic->getValue();

    if (rxValue.length() > 0) {
      Serial.print("------>Received Value: ");

      for (int i = 0; i < rxValue.length(); i++) {
        Serial.print(rxValue[i]);
      }
      Serial.println();
    }
  }
};


void setup() {
  myservo.setPeriodHertz(50);             // standard 50 hz servo
  myservo.attach(SERVO_PIN, 1000, 2000);  // attaches the servo on pin 18 to the servo object
  Serial.begin(115200);
  u8g2.begin();
  u8g2.clearDisplay();
  pinMode(ENCODER_SW, INPUT_PULLUP);
  pinMode(ENCODER_CLK, INPUT_PULLUP);
  pinMode(ENCODER_DT, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = getColor(-1);
  }
  FastLED.show();
  // Create the BLE Device
  BLEDevice::init("ESP32 BLE vor");
  // 创建蓝牙服务器
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  // // 创建广播服务的UUID
  BLEService *pService = pServer->createService(SERVICE_UUID);
  // 创建广播服务的UUID
  pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
  pCharacteristic->addDescriptor(new BLE2902());
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
  pCharacteristic->setCallbacks(new MyCallbacks());
  // 开始蓝牙服务
  pService->start();
  // 开始广播
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

void loop() {
  u8g2.clearBuffer();
  switch (currentMenu) {
    case 0:  // Main menu
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(7, 22);
      u8g2.print("Main menu");
      u8g2.setFont(u8g2_font_ncenB08_tr);
      u8g2.setCursor(0, 40);
      u8g2.print("1. Servo");
      u8g2.setCursor(0, 60);
      u8g2.print("2. WS2812");
      u8g2.setCursor(64, 40);
      u8g2.print("3. Sensor");
      u8g2.setCursor(64, 60);
      u8g2.print("4. Buzzer");
      break;

    case 1:  // Servo menu
      // int servoencoderValue = 0;
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("Servo Angle: ");
      u8g2.setCursor(30, 40);
      u8g2.print(servoAngle);
      u8g2.sendBuffer();
      while (1) {
        if (checkencoder() == true) {
          setservo();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    case 2:  // WS2812 menu
      // int LEDencoderValue = 0;
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("LED Color: ");
      u8g2.setCursor(30, 40);
      u8g2.print(ledColorIndex);
      u8g2.sendBuffer();
      // Handle LED color control
      while (1) {
        if (checkencoder() == true) {
          setLedColor();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    case 3:  // Sensor menu
      u8g2.setFont(u8g2_font_ncenB08_tr);
      u8g2.setCursor(10, 30);
      u8g2.print("Sensor1: ");
      u8g2.setCursor(64, 30);
      u8g2.print(sensorValue);
      u8g2.setCursor(10, 60);
      u8g2.print("Sensor2: ");
      u8g2.setCursor(64, 60);
      u8g2.print(sensorValue2);

      // Read sensor value
      sensorValue = analogRead(SENSOR_PIN);
      sensorValue2 = analogRead(SENSOR_PIN2);
      break;

    case 4:  // Buzzer menu
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("Buzzer Value: ");
      u8g2.setCursor(30, 40);
      u8g2.print(BuzzerValue);
      // Handle Buzzer control
      while (1) {
        if (checkencoder() == true) {
          setbuzzer();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    case 5:  // Blue uart
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("Blue uart : ");
      u8g2.setFont(u8g2_font_ncenB08_tr);
      u8g2.setCursor(0, 40);
      u8g2.print(BuzzerValue);
      // Handle Buzzer control
      while (1) {
        setbluetooth();
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    default:
      break;
  }
  increment = 0;
  u8g2.sendBuffer();
  // Handle menu navigation
  if (checkswitch() == true) {
    currentMenu++;
    if (currentMenu > 5) {
      currentMenu = 0;
    }
    delay(200);  // Debounce delay
  }
}
bool checkencoder() {
  long newPosition = myEncoder.read();
  if (newPosition != oldPosition) {
    // Serial.println(newPosition + String(";") + oldPosition);
    increment = newPosition - oldPosition;
    oldPosition = newPosition;
    return true;
  }
  return false;
}
bool checkswitch() {
  encoderButtonState = digitalRead(ENCODER_SW);
  if (encoderButtonState == LOW) {
    delay(50);  // Debounce delay
    encoderButtonState = digitalRead(ENCODER_SW);
    if (encoderButtonState == LOW) {
      return true;
    } else {
      return false;
    }
  } else {
    return false;
  }
}
void setLedColor() {
  ledColorIndex = ledColorIndex + increment;
  if (ledColorIndex < 0) {
    ledColorIndex = 0;
  } else if (ledColorIndex > 10) {
    ledColorIndex = 10;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(ledColorIndex);
  u8g2.sendBuffer();
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = getColor(ledColorIndex);
  }
  FastLED.show();
  delay(1);
}
void setservo() {
  servoAngle = servoAngle + increment * 3;
  if (servoAngle > 180) {
    servoAngle = 180;
  } else if (servoAngle < 0) {
    servoAngle = 0;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(servoAngle);
  u8g2.sendBuffer();
  myservo.write(servoAngle);
}

void setbuzzer() {
  BuzzerValue = BuzzerValue + increment * 8;
  if (BuzzerValue > 255) {
    BuzzerValue = 255;
  } else if (BuzzerValue < 0) {
    BuzzerValue = 0;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(BuzzerValue);
  u8g2.sendBuffer();
  analogWrite(BUZZER, BuzzerValue);
}

void setbluetooth() {
  if (deviceConnected) {  //设备连接后,每秒钟发送txValue。
    memset(BLEbuf, 0, 32);
    message_c = "s "+String(servoAngle)+" w"+String(ledColorIndex)+" s"+String(analogRead(SENSOR_PIN))+"s"+String(analogRead(SENSOR_PIN2))+"b"+String(BuzzerValue)+"\n";
    char* p = const_cast<char*>(message_c.c_str());
    memcpy(BLEbuf, p, 32);
    pCharacteristic->setValue(BLEbuf);

    pCharacteristic->notify();  // Send the value to the app!
    Serial.print("*** Sent Value: ");
    Serial.print(BLEbuf);
    Serial.println(" ***");
    // sensorValue = analogRead(SENSOR_PIN);
    // sensorValue2 = analogRead(SENSOR_PIN2);
    // memset(BLEbuf, 0, 256);
    // // sprintf(message, "S%dW%dS%dS%dB%d", servoAngle, ledColorIndex, sensorValue, sensorValue2, BuzzerValue);
    // sprintf(message, "S%dW%d", servoAngle, ledColorIndex);
    // // message_c = message;
    // // char* p = const_cast<char*>(message.c_str());
    // // message1 = message;
    // memcpy(BLEbuf, message, 256);
    // // memcpy(BLEbuf, message_c, 32);
    // pCharacteristic->setValue(BLEbuf);
    // pCharacteristic->notify();  // Send the value to the app!
    // delay(10);
    u8g2.setCursor(0, 40);
    u8g2.print(BLEbuf);
    // // u8g2.setCursor(0, 60);
    // // u8g2.print(message_c.substring(15, 32));
    u8g2.sendBuffer();
    // Serial.println("Sent Value:" + String(BLEbuf));
    delay(100);
  }
}

CRGB getColor(int index) {
  switch (index) {
    case 0:
      return CRGB::Red;
    case 1:
      return CRGB::Green;
    case 2:
      return CRGB::Blue;
    case 3:
      return CRGB::Yellow;
    case 4:
      return CRGB::Magenta;
    case 5:
      return CRGB::Cyan;
    case 6:
      return CRGB::White;
    case 7:
      return CRGB::Purple;
    case 8:
      return CRGB::Orange;
    case 9:
      return CRGB::Pink;
    default:
      return CRGB::Black;
  }
}

 7.4 版本1.3

设计了两个线程,完成了实时的蓝牙交互,不过ws2812控制不稳定。推荐版本1.2

// #define ENCODER_DO_NOT_USE_INTERRUPTS
#include <U8g2lib.h>
#include <Encoder.h>
#include <ESP32Servo.h>
#include <FastLED.h>
#include <WS2812FX.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#define OLED_CLOCK 5
#define OLED_DATA 4
#define OLED_RESET U8X8_PIN_NONE
#define ENCODER_CLK 7
#define ENCODER_DT 6
#define ENCODER_SW 8
#define SERVO_PIN 19
#define LED_PIN 18
#define NUM_LEDS 4
#define SENSOR_PIN 0
#define SENSOR_PIN2 1
#define BUZZER 13
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E"  // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
//创建Bluetooth对象
BLECharacteristic *pCharacteristic;
//创建SSD1306屏幕对象
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2(U8G2_R0, /* clock=*/OLED_CLOCK, /* data=*/OLED_DATA, /* reset=*/OLED_RESET);  // ESP32 Thing, pure SW emulated I2C
// 创建Encoder对象
Encoder myEncoder(ENCODER_CLK, ENCODER_DT);
// ESP32PWM pwm;
Servo myservo;  // create servo object to control a servo
CRGB leds[NUM_LEDS];
int currentMenu = 0;
int servoAngle = 0;
int ledColorIndex = 0;
int sensorValue = 0;
int sensorValue2 = 0;
int BuzzerValue = 128;
int encoderButtonState = 0;
long position = 0;
long newPos = 0;
long oldPosition = 0;
int increment = 0;
bool deviceConnected = false;
char BLEbuf[256] = { 0 };
uint32_t cnt = 0;
String message_c;
char *message;
// const char *message1;
class MyServerCallbacks : public BLEServerCallbacks {
  void onConnect(BLEServer *pServer) {
    deviceConnected = true;
  };

  void onDisconnect(BLEServer *pServer) {
    deviceConnected = false;
  }
};

class MyCallbacks : public BLECharacteristicCallbacks {
  void onWrite(BLECharacteristic *pCharacteristic) {
    std::string rxValue = pCharacteristic->getValue();

    if (rxValue.length() > 0) {
      Serial.print("------>Received Value: ");

      for (int i = 0; i < rxValue.length(); i++) {
        Serial.print(rxValue[i]);
      }
      Serial.println();
    }
  }
};


void appCpuLoop(void *pvParameters) {
  while (true) {
    if (currentMenu != 5) {
      memset(BLEbuf, 0, 32);
      message_c = "s " + String(servoAngle) + "w" + String(ledColorIndex) + " s" + String(analogRead(SENSOR_PIN)) + "s" + String(analogRead(SENSOR_PIN2)) + "b" + String(BuzzerValue) + "\r\n";
      char *p = const_cast<char *>(message_c.c_str());
      memcpy(BLEbuf, p, 32);
      pCharacteristic->setValue(BLEbuf);

      pCharacteristic->notify();  // Send the value to the app!
      Serial.print("*** Sent Value: ");
      Serial.print(BLEbuf);
      Serial.println(" ***");
      delay(700);
    }
    delay(300);
  }

  vTaskDelete(NULL);
}

void setup() {
  myservo.setPeriodHertz(50);             // standard 50 hz servo
  myservo.attach(SERVO_PIN, 1000, 2000);  // attaches the servo on pin 18 to the servo object
  Serial.begin(115200);
  u8g2.begin();
  u8g2.clearDisplay();
  pinMode(ENCODER_SW, INPUT_PULLUP);
  pinMode(ENCODER_CLK, INPUT_PULLUP);
  pinMode(ENCODER_DT, INPUT_PULLUP);
  pinMode(BUZZER, OUTPUT);
  FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = getColor(-1);
  }
  FastLED.show();
  // Create the BLE Device
  BLEDevice::init("ESP32 BLE vor");
  // 创建蓝牙服务器
  BLEServer *pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  // // 创建广播服务的UUID
  BLEService *pService = pServer->createService(SERVICE_UUID);
  // 创建广播服务的UUID
  pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
  pCharacteristic->addDescriptor(new BLE2902());
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
  pCharacteristic->setCallbacks(new MyCallbacks());
  // 开始蓝牙服务
  pService->start();
  // 开始广播
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
  xTaskCreatePinnedToCore(appCpuLoop,      //具体实现的函数
                          "APP_CPU_LOOP",  //任务名称
                          8192,            //堆栈大小
                          NULL,            //输入参数
                          1,               //任务优先级
                          NULL,            //
                          1                //核心  0\1
  );
}

void loop() {
  u8g2.clearBuffer();
  switch (currentMenu) {
    case 0:  // Main menu
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(7, 22);
      u8g2.print("Main menu");
      u8g2.setFont(u8g2_font_ncenB08_tr);
      u8g2.setCursor(0, 40);
      u8g2.print("1. Servo");
      u8g2.setCursor(0, 60);
      u8g2.print("2. WS2812");
      u8g2.setCursor(64, 40);
      u8g2.print("3. Sensor");
      u8g2.setCursor(64, 60);
      u8g2.print("4. Buzzer");
      break;

    case 1:  // Servo menu
      // int servoencoderValue = 0;
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("Servo Angle: ");
      u8g2.setCursor(30, 40);
      u8g2.print(servoAngle);
      u8g2.sendBuffer();
      while (1) {
        if (checkencoder() == true) {
          setservo();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    case 2:  // WS2812 menu
      // int LEDencoderValue = 0;
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("LED Color: ");
      u8g2.setCursor(30, 40);
      u8g2.print(ledColorIndex);
      u8g2.sendBuffer();
      // Handle LED color control
      while (1) {
        if (checkencoder() == true) {
          setLedColor();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    case 3:  // Sensor menu
      u8g2.setFont(u8g2_font_ncenB08_tr);
      u8g2.setCursor(10, 30);
      u8g2.print("Sensor1: ");
      u8g2.setCursor(64, 30);
      u8g2.print(sensorValue);
      u8g2.setCursor(10, 60);
      u8g2.print("Sensor2: ");
      u8g2.setCursor(64, 60);
      u8g2.print(sensorValue2);

      // Read sensor value
      sensorValue = analogRead(SENSOR_PIN);
      sensorValue2 = analogRead(SENSOR_PIN2);
      break;

    case 4:  // Buzzer menu
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("Buzzer Value: ");
      u8g2.setCursor(30, 40);
      u8g2.print(BuzzerValue);
      // Handle Buzzer control
      while (1) {
        if (checkencoder() == true) {
          setbuzzer();
          increment = 0;
        }
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    case 5:  // Blue uart
      u8g2.setFont(u8g2_font_ncenB14_tr);
      u8g2.setCursor(0, 20);
      u8g2.print("Blue uart : ");
      u8g2.setFont(u8g2_font_ncenB08_tr);
      u8g2.setCursor(0, 40);
      u8g2.print(BuzzerValue);
      // Handle Buzzer control
      while (1) {
        setbluetooth();
        if (checkswitch() == true) {
          break;
        }
      }
      break;

    default:
      break;
  }
  increment = 0;
  u8g2.sendBuffer();
  // Handle menu navigation
  if (checkswitch() == true) {
    currentMenu++;
    if (currentMenu > 5) {
      currentMenu = 0;
    }
    delay(200);  // Debounce delay
  }
}
bool checkencoder() {
  long newPosition = myEncoder.read();
  if (newPosition != oldPosition) {
    // Serial.println(newPosition + String(";") + oldPosition);
    increment = newPosition - oldPosition;
    oldPosition = newPosition;
    return true;
  }
  return false;
}
bool checkswitch() {
  encoderButtonState = digitalRead(ENCODER_SW);
  if (encoderButtonState == LOW) {
    delay(50);  // Debounce delay
    encoderButtonState = digitalRead(ENCODER_SW);
    if (encoderButtonState == LOW) {
      return true;
    } else {
      return false;
    }
  } else {
    return false;
  }
}
void setLedColor() {
  ledColorIndex = ledColorIndex + increment;
  if (ledColorIndex < 0) {
    ledColorIndex = 0;
  } else if (ledColorIndex > 10) {
    ledColorIndex = 10;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(ledColorIndex);
  u8g2.sendBuffer();
  for (int i = 0; i < NUM_LEDS; i++) {
    leds[i] = getColor(ledColorIndex);
  }
  FastLED.show();
  delay(1);
}
void setservo() {
  servoAngle = servoAngle + increment * 3;
  if (servoAngle > 180) {
    servoAngle = 180;
  } else if (servoAngle < 0) {
    servoAngle = 0;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(servoAngle);
  u8g2.sendBuffer();
  myservo.write(servoAngle);
}

void setbuzzer() {
  BuzzerValue = BuzzerValue + increment * 8;
  if (BuzzerValue > 255) {
    BuzzerValue = 255;
  } else if (BuzzerValue < 0) {
    BuzzerValue = 0;
  }
  u8g2.setCursor(30, 40);
  u8g2.print(BuzzerValue);
  u8g2.sendBuffer();
  analogWrite(BUZZER, BuzzerValue);
}

void setbluetooth() {
  if (deviceConnected) {  //设备连接后,每秒钟发送txValue。
    memset(BLEbuf, 0, 32);
    message_c = "s " + String(servoAngle) + "w" + String(ledColorIndex) + " s" + String(analogRead(SENSOR_PIN)) + "s" + String(analogRead(SENSOR_PIN2)) + "b" + String(BuzzerValue) + "\r\n";
    char *p = const_cast<char *>(message_c.c_str());
    memcpy(BLEbuf, p, 32);
    pCharacteristic->setValue(BLEbuf);

    pCharacteristic->notify();  // Send the value to the app!
    Serial.print("*** Sent Value: ");
    Serial.print(BLEbuf);
    Serial.println(" ***");
    // sensorValue = analogRead(SENSOR_PIN);
    // sensorValue2 = analogRead(SENSOR_PIN2);
    // memset(BLEbuf, 0, 256);
    // // sprintf(message, "S%dW%dS%dS%dB%d", servoAngle, ledColorIndex, sensorValue, sensorValue2, BuzzerValue);
    // sprintf(message, "S%dW%d", servoAngle, ledColorIndex);
    // // message_c = message;
    // // char* p = const_cast<char*>(message.c_str());
    // // message1 = message;
    // memcpy(BLEbuf, message, 256);
    // // memcpy(BLEbuf, message_c, 32);
    // pCharacteristic->setValue(BLEbuf);
    // pCharacteristic->notify();  // Send the value to the app!
    // delay(10);
    u8g2.setCursor(0, 40);
    u8g2.print(BLEbuf);
    // // u8g2.setCursor(0, 60);
    // // u8g2.print(message_c.substring(15, 32));
    u8g2.sendBuffer();
    // Serial.println("Sent Value:" + String(BLEbuf));
    delay(100);
  }
}

CRGB getColor(int index) {
  switch (index) {
    case 0:
      return CRGB::Red;
    case 1:
      return CRGB::Green;
    case 2:
      return CRGB::Blue;
    case 3:
      return CRGB::Yellow;
    case 4:
      return CRGB::Magenta;
    case 5:
      return CRGB::Cyan;
    case 6:
      return CRGB::White;
    case 7:
      return CRGB::Purple;
    case 8:
      return CRGB::Orange;
    case 9:
      return CRGB::Pink;
    default:
      return CRGB::Black;
  }
}
  • 8. 功能展示及说明

8.1 主菜单显示

主菜单显示,所有设备初始化,舵机归位,灯灭,蜂鸣器静音

8.2 舵机控制

舵机显示60度位置,屏幕同步数值

8.3 WS2812控制

WS2812显示蓝色灯,屏幕同步数值

8.4 ADC读取

实时读取光敏ADC,屏幕同步数值

8.5 蜂鸣器PWM

蜂鸣器输出PWM,屏幕同步数值

8.6 蓝牙交互

手机连接ESP32 BLE vor蓝牙,发送数据

 屏幕读取状态

 手机实时接收设备信息

 电脑串口显示设备状态和接收手机数据

  • 9总结

这是我第四次参加嵌入式相关的网上比赛活动

  • 第一次是RT-Thread的【基于RT-Thread+RA6M4的智能鱼缸系统设计之鱼我所欲也】活动,作品是2022年暑假做的获得第六名,还是比较开心!
  • 第二次2023年寒假做的是【基于MAX7800羽毛板语音控制ESP8266小车】,成绩还没有出来,第七名。
  • 第三次2023年春做的【基于腾讯云的CH32V307开发板远程机械臂小车】,由于图床引用CSDN导致最后评审没有显示出来,最后获得安慰奖

这次最大的收获是第一次实现了PCB板设计、制作和调试全流程,加深了对手机蓝牙双向通信,对esp32国产单片机更有信心!
这次最大的遗憾是没有加入蓝牙控制程序,相信大家自己解决哒。

建议:

  1. 希望得捷电子优化国内访问网站浏览和提高scheme-it工具设计水平;
  2. 期待硬禾联合各大平台推出更多有质量有意义持续性的创客活动!

非常感谢硬禾联合得捷电子官方组织的FastBond2活动,大家都为这个国内嵌入式生态出一份力,只要努力认真做了都会有所收获,期盼这些作品在将来某一天为构建美好未来贡献一份微博之力!
我后期会持续更新我测评的一系列国内开发板测评,并且作为宣传大使努力鼓励大家有所获参加有质量的硬禾活动🛹🛹🛹每天都一点点结合实际需求联动丰富生活,从而实现对外部世界进行充分的感知,尽最大努力认识这个有机与无机的环境,科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣
🥳🥳🥳再次非常感谢硬禾的Lucia支持等等🥳🥳🥳期待这一次的成绩哟!
参考文献:

FastBond2阶段1——基于ESP32C3开发的简易IO调试设备 - 电子森林 (eetree.cn)

【esp32c3配置arduino IDE教程】-CSDN博客

【Arduino环境下驱动合宙esp32c3单片机基本外设】-CSDN博客

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

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

相关文章

虚拟机项目部署与发布

目录 一.单机项目 1.1. 本机测试 1.2.部署 二.前后端 3.1.准备 3.2.部署 今天就到这里了哦&#xff0c;希望能帮到你哦&#xff01;&#xff01;&#xff01; 一.单机项目 当我们拿到已开发完的项目后&#xff0c;首先需要在我们自己的主机上进行测试&#xff0c;开发完的…

【Shell脚本4】Shell 传递参数

Shell 传递参数 我们可以在执行 Shell 脚本时&#xff0c;向脚本传递参数&#xff0c;脚本内获取参数的格式为&#xff1a;$n。n 代表一个数字&#xff0c;1 为执行脚本的第一个参数&#xff0c;2 为执行脚本的第二个参数&#xff0c;以此类推…… 以下实例我们向脚本传递三个…

持续集成交付CICD:安装Jenkins Slave(从节点)

目录 一、实验 1.安装Jenkins Slave 二、问题 1.salve节点启动jenkins报错 2.终止命令行jenkins节点状态丢失 一、实验 1.安装Jenkins Slave&#xff08;从节点&#xff09; &#xff08;1&#xff09;查看jenkins版本 Version 2.414.2 (2) 添加节点 系统设置&#xf…

c++ 信息学奥赛 2047:【例5.16】过滤空格

#include<cstdio> using namespace std; char st[200]; int main() { while (scanf("%s",&st)1)printf("%s ",st); //%s 后要有一个空格&#xff0c;不能省略return 0; } 解析&#xff1a;本题中使用一个技巧&#xff0c;那就是scanf函数…

Redis原理到常用语法基础图文讲解

在初期&#xff0c;已经讲述了Redis安装问题。现在正式进入Redis的入门阶段 系统架构的演进 传统单机架构 一台机器运行应用程序、数据库服务器 现在大部分公司的产品都是这种单机架构。因为现在计算机硬件发展速度很快&#xff0c;哪怕只有一台主机&#xff0c;性能也很高…

多种循环法打印乘法表

1 问题 使用多种循环法打印乘法表&#xff0c;有助于巩固夯实循环的语法及用法。 使用for-for、for-while、while-for方法实现乘法表。 2 方法 &#xff08;1&#xff09;for-for:使用两个for.. in..来实现乘法表。 &#xff08;2&#xff09;for-while:使用一个for语句再一个w…

C++前缀和算法的应用:最大化城市的最小供电站数目

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 二分法 题目 给你一个下标从 0 开始长度为 n 的整数数组 stations &#xff0c;其中 stations[i] 表示第 i 座城市的供电站数目。 每个供电站可以在一定 范围 内给所…

强化学习中策略的迭代

一、策略迭代 一旦使用vπ改善了策略π&#xff0c;产生了更好的策略π0&#xff0c;我们就可以计算vπ0并再次对其进行改进&#xff0c;产生更好的π00。因此&#xff0c;我们可以获得一系列单调改善的策略和值函数&#xff1a; 其中E−→表示策略评估&#xff0c;I−→表示策…

[云原生1. ] Docker 的安全及日志管理

文章目录 1. Docker自身存在的安全问题1.1 Docker 自身漏洞1.2 Docker 源码问题 2. Docker 架构缺陷与安全机制2.1 容器之间的局域网攻击2.2 DDoS 攻击耗尽资源2.3 有漏洞的系统调用2.4 共享root用户权限 3. Docker 安全基线标准3.1 docker容器使用安全注意点&#xff1a;3.1.1…

【Spring Boot 源码学习】JedisConnectionConfiguration 详解

Spring Boot 源码学习系列 JedisConnectionConfiguration 详解 引言往期内容主要内容1. RedisConnectionFactory1.1 单机连接1.2 集群连接1.3 哨兵连接 2. JedisConnectionConfiguration2.1 RedisConnectionConfiguration2.2 导入自动配置2.3 相关注解介绍2.4 redisConnectionF…

3.26每日一题(线性非齐次的特解如何设)

1、非齐次方程有e的2x次幂&#xff1a;特解也有e的2x次幂 2、e的2x次幂前面有特殊的一元方程&#xff1a;特解要设为一般的特征方程&#xff08;axb&#xff09; 3、求线性齐次特征方程的特征根&#xff1b; 4、判断e的 rx 次幂中的 r 和特征根有没有重合的个数&#xff1a;…

vue3的自定义指令

除了 Vue 内置的一系列指令 (比如 v-model 或 v-show) 之外&#xff0c;Vue 还允许你注册自定义的指令 (CustomDirectives)。 1.自定义指令的目的和简单介绍 自定义指令主要是为了重用涉及普通元素的底层 DOM 访问的逻辑。 一个自定义指令由一个包含类似组件生命周期钩子的对象…

创建日期时间类型对象 pendulum.datetime()

【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 创建日期时间类型对象 pendulum.datetime() 选择题 请问pdl.datetime(2023,10,1,12,0,0)的结果是&#xff1a; import pendulum as pdl print("【执行】pdl.datetime(2023,10,1)") …

【数智化案例展】领克汽车——火山引擎助力领克汽车数字化营销实践

‍ 火山引擎案例 本项目案例由火山引擎投递并参与数据猿与上海大数据联盟联合推出的《2023中国数智化转型升级创新服务企业》榜单/奖项”评选。 大数据产业创新服务媒体 ——聚焦数据 改变商业 领克汽车是由吉利汽车、沃尔沃汽车和吉利控股集团合资成立的全球新高端品牌。据吉…

inno setup 运行时进行文件复制和替换

问题描述&#xff1a; 当我们采用 inno setup进行打包时&#xff0c;需要实现将安装包中的某个文件进行替换&#xff0c;而且我们知道在Winodws系统可以有xcopy和copy两个命令可以提供该功能&#xff1b;而xcopy命令进行文件复制时会有如下提示&#xff1a; 此时需要手动输入字…

【算法】单调栈 每日温度 接雨水

文章目录 例题739. 每日温度42. 接雨水 相关练习1475. 商品折扣后的最终价格901. 股票价格跨度1019. 链表中的下一个更大节点84. 柱状图中最大的矩形 单调栈【基础算法精讲 26】 例题 739. 每日温度 https://leetcode.cn/problems/daily-temperatures/description/ 提示&a…

麒麟V4搭建本地源

1.创建本地源目录 mkdir -p /package/pack 2.修改目录权限为_apt属组 chown _apt /package/pack 3.将软件包复制到/package/pack cp -av 软件包 /package/pack 4.修改目录权限为755 chmod -R 755 /package/ 5.创建本地源的index文件 dpkg-scanpackages . | gzip -9c &…

算法通关村第六村-白银挑战树的层序遍历

大家好我是苏麟 , 今天说说数的层序遍历 . 层次遍历简介 广度优先在面试里出现的频率非常高&#xff0c;整体属于简单题&#xff0c;但是很多人面试遇到时就直接放弃了&#xff0c;实在可惜。我们本章就集中研究一下到底难在哪里。 广度优先又叫层次遍历&#xff0c;基本过程…

Oracle-Ogg经典模式升级为集成模式步骤

​前言: Oracle Ogg集成模式比起经典模式功能更加的强大&#xff0c;支持更多的数据类型&#xff0c;压缩表同步&#xff0c;XA事务&#xff0c;多线程模式&#xff0c;PDB模式同步&#xff0c;RAC环境下抽取配置简单等新功能&#xff0c;所以可以选择将经典模式升级转化为集成…

The service already exists! 安装mysql数据库错误!

当你输入mysql install命令时报The service already exists! 报错的原因是服务已经存在&#xff01; 说明你之前可能已经装过了。 解决方法&#xff1a; 输入sc delete mysql 提示DeleteService 成功,则表示删除成功&#xff0c;你就可以重新输入mysqld install了。 最后显…