esp32 camera_ESP32操作L298N以及示例程序说明

本教程介绍了如何使用ESP32和L298N电机驱动器来控制DC电机的方向和速度。首先,我们将快速了解L298N电机驱动器的工作原理。然后,我们将向您展示一个示例,说明如何使用带有Arduino IDE的ESP32和L298N电机驱动器来控制DC电机的速度和方向。

注意:有很多方法可以控制直流电动机。我们将使用L298N电机驱动器。本教程还与类似的电机驱动器模块兼容。

所需部件

要完成本教程,您需要以下部分:

17109ebbf406afea8f49e408af613e4c.png
ESP32 DOIT DEVKIT V1直流马达L298N电机驱动器电源: 4节1.5节AA电池 或 开关电源2个100nF陶瓷电容器 (可选)1个SPDT滑动开关 (可选)跳线

L298N电机驱动器介绍

有许多方法可以控制直流电动机。我们将在这里使用的方法适用于大多数需要6V或12V操作的业余爱好者电机。

我们将使用L298N电动机驱动器,该驱动器在35V电压下可处理高达3A的电流。此外,它还允许我们同时驱动两个直流电动机,这非常适合构建机器人。

L298N电机驱动器如下图所示:

e8b9d4dd3833af5910c9c2d041fa4099.png

L298N电机驱动器引脚排列

让我们看一下L298N电机驱动器的引脚排列,看看它是如何工作的。

c1c9f06be0c1b9759436c9223cb4fedd.png

电机驱动器在每个电机的每侧都有两个接线端子。OUT1和OUT2在左侧,OUT3和OUT4在右侧。

OUT1:直流电机A +端子 OUT2:直流电动机A –端子 OUT3:直流电机B +端子 OUT4:直流电动机B –端子

在底部,有一个带+ 12V,GND和+ 5V的三个接线端子。+ 12V端子用于马达电源。+ 5V端子用于L298N芯片。但是,如果安装了跳线,则芯片将使用电动机的电源供电,并且您无需通过+ 5V端子提供5V 电压。

注意:如果您提供的电压超过12V,则需要卸下跳线,并向+ 5V端子提供5V的电压。

重要的是要注意,尽管端子名称为+ 12V,但在这里我们将使用设置(在有跳线的情况下)可以提供6V至12V之间的任何电压。在本教程中,将使用4节AA 1.5V电池,这些电池的总输出约为6V,但是您可以使用任何其他合适的电源。例如,您可以使用开关电源来测试本教程。

综上所述:

+ 12V:+ 12V端子是您应该连接电源的地方 GND:电源GND + 5V:如果移除了跳线,则提供5V。如果有跳线,则充当5V输出 跳线:默认的跳线–使用电动机电源为芯片加电。跳线已移除:您需要为+ 5V端子提供5V电压。如果您提供的电压超过12V,则应卸下跳线

在右下角,您有四个输入引脚和两个启用端子。输入引脚用于控制直流电动机的方向,而使能引脚用于控制每个电动机的速度。

IN1: 电动机A的输入1 IN2:电动机A的输入2 IN3:电机B的输入1 IN4:电机B的输入2 EN1:电机A的使能引脚 EN2:电机B的使能引脚

默认情况下,使能引脚上有跳线帽。您需要卸下那些跳线帽以控制电动机的速度。

使用L298N控制直流电动机

现在您已经熟悉了L298N电动机驱动器,让我们看看如何使用它来控制直流电动机。

使能引脚

使能引脚就像电动机的ON和OFF开关。例如:

如果将 HIGH信号发送到使能1引脚,则电动机A准备好以最大速度进行控制;如果将 低电平信号发送到使能1引脚,则电动机A关闭;否则,电动机A启用。如果发送 PWM信号,则可以控制电动机的速度。电机速度与占空比成正比。但是,请注意,在较小的占空比下,电动机可能不会旋转,并且会发出持续的嗡嗡声。

输入脚

输入引脚控制电动机旋转的方向。输入1和输入2控制马达A,输入3和4控制马达B.

如果将LOW应用于输入1,将HIGH应用于输入2,则电动机将正转;如果以相反的方式加电:输入1为高,输入2为低,电动机将向后旋转。可以使用相同的方法来控制电动机B,但是将HIGH或LOW应用于输入3和输入4。

控制2台直流电动机–是构建机器人的理想选择

如果要使用2个直流电动机建造机器人汽车,则这些电动机应沿特定方向旋转,以使机器人向左,向右,向前或向后移动。

例如,如果您希望机器人向前移动,则两个电动机都应向前旋转。为了使其向后移动,两者都应向后旋转。

为了使机器人朝一个方向旋转,您需要更快地旋转相反的电机。例如,要使机器人向右转,请在左侧启用电动机,然后在右侧禁用电动机。

使用ESP32控制直流电机–速度和方向

现在,您知道如何使用L298N电动机驱动器控制直流电动机,让我们建立一个简单的示例来控制一个直流电动机的速度和方向。

原理图

我们将控制的电机连接到电机A的输出引脚,因此我们需要将电机驱动器的ENABLEA,INPUT1和INPUT2引脚连接到ESP32。将直流电动机和L298N电动机驱动器连接到ESP32。

DC电动机需要较大的电流跳跃才能启动,因此应使用ESP32的外部电源为电动机供电。例如,我们使用4AA电池,但是您可以使用任何其他合适的电源。在此配置中,您可以使用6V至12V的电源。

电池座和电机驱动器之间的开关是可选的,但切断和接通电源非常方便。这样,您就不需要不断地连接然后断开电线以节省功率。

我们建议将0.1uF陶瓷电容器焊接到直流电动机的正负极,以帮助消除任何电压尖峰。(注意:电动机也可以在没有电容器的情况下工作。)

准备Arduino IDE

Arduino IDE有一个附加组件,可让您使用Arduino IDE及其编程语言对ESP32进行编程。确保已安装ESP32插件后,可以继续本教程。

上传代码

以下代码控制直流电动机的速度和方向。该代码在现实世界中没有用,这只是一个简单的示例,可以更好地了解如何使用ESP32控制DC电动机的速度和方向。

/*********

Rui Santos

Complete project details at https://randomnerdtutorials.com

*********/

// Motor A

int motor1Pin1 = 27;

int motor1Pin2 = 26;

int enable1Pin = 14;

// Setting PWM properties

const int freq = 30000;

const int pwmChannel = 0;

const int resolution = 8;

int dutyCycle = 200;

void setup() {

// sets the pins as outputs:

pinMode(motor1Pin1, OUTPUT);

pinMode(motor1Pin2, OUTPUT);

pinMode(enable1Pin, OUTPUT);

// configure LED PWM functionalitites

ledcSetup(pwmChannel, freq, resolution);

// attach the channel to the GPIO to be controlled

ledcAttachPin(enable1Pin, pwmChannel);

Serial.begin(115200);

// testing

Serial.print("Testing DC Motor...");

}

void loop() {

// Move the DC motor forward at maximum speed

Serial.println("Moving Forward");

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, HIGH);

delay(2000);

// Stop the DC motor

Serial.println("Motor stopped");

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, LOW);

delay(1000);

// Move DC motor backwards at maximum speed

Serial.println("Moving Backwards");

digitalWrite(motor1Pin1, HIGH);

digitalWrite(motor1Pin2, LOW);

delay(2000);

// Stop the DC motor

Serial.println("Motor stopped");

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, LOW);

delay(1000);

// Move DC motor forward with increasing speed

digitalWrite(motor1Pin1, HIGH);

digitalWrite(motor1Pin2, LOW);

while (dutyCycle <= 255){

ledcWrite(pwmChannel, dutyCycle);

Serial.print("Forward with duty cycle: ");

Serial.println(dutyCycle);

dutyCycle = dutyCycle + 5;

delay(500);

}

dutyCycle = 200;

}

将代码上传到ESP32。确保选择了正确的板和COM端口。让我们看一下代码是如何工作的。

声明电机引脚

首先,定义电机引脚连接的GPIO。在这种情况下,电机A的输入1连接到GPIO 27,输入2连接到GPIO 26,使能引脚连接到GPIO 14。

int motor1Pin1 = 27;

int motor1Pin2 = 26;

int enable1Pin = 14;

设置PWM属性以控制速度

如前所述,您可以通过向L298N电机驱动器的使能引脚施加PWM信号来控制直流电机的速度。速度将与占空比成正比。要将PWM与ESP32一起使用,您需要首先设置PWM信号属性。

const int freq = 30000;

const int pwmChannel = 0;

const int resolution = 8;

int dutyCycle = 200;

在这种情况下,我们将在通道0上以8位分辨率生成30000 Hz的信号。我们从200的占空比开始(您可以将占空比值设置为0到255)。

对于我们使用的频率,当您应用小于200的占空比时,电机将不会移动,并且会发出奇怪的蜂鸣声。因此,这就是为什么我们一开始将占空比设置为200的原因。

注意:我们在此处定义的PWM属性只是一个示例。电机可以在其他频率下正常工作。

设定()

在setup()中,首先将电动机引脚设置为输出。

pinMode(motor1Pin1, OUTPUT);

pinMode(motor1Pin2, OUTPUT);

pinMode(enable1Pin, OUTPUT);

您需要通过使用ledcSetup()函数来配置具有先前定义的属性的PWM信号,该函数接受pwmChannel,frequency和resolution作为参数,如下所示:

ledcSetup(pwmChannel, freq, resolution);

接下来,您需要选择将从其获取信号的GPIO。为此,请使用 ledcAttachPin()函数,该函数接受要获取信号的GPIO以及生成信号的通道作为参数。在此示例中,我们将在enable1Pin GPIO中获取信号,该GPIO与GPIO 14相对应。生成信号的通道为pwmChannel,与通道0相对应。

ledcAttachPin(enable1Pin, pwmChannel);

向前移动直流电动机

在loop()中是电动机运动的地方。该代码很好地说明了代码各部分的功能。要使电动机向前移动,请将输入1引脚设置为LOW,将输入2引脚设置为HIGH。在此示例中,电动机向前旋转2秒钟(2000毫秒)。

// Move the DC motor forward at maximum speed

Serial.println("Moving Forward");

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, HIGH);

delay(2000);

向后移动直流电动机

要向后移动直流电动机,请反方向向电动机输入引脚供电。高输入1,低输入2。

// Move DC motor backwards at maximum speed

Serial.println("Moving Backwards");

digitalWrite(motor1Pin1, HIGH);

digitalWrite(motor1Pin2, LOW);

delay(2000);

停止直流电机

要使直流电动机停止,您可以将使能引脚设置为LOW,或者将输入1和输入2引脚都设置为LOW。在此示例中,我们将两个输入引脚都设置为LOW。

// Stop the DC motor

Serial.println("Motor stopped");

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, LOW);

delay(1000);

控制直流电动机速度

要控制直流电动机的速度,我们需要更改PWM信号占空比。为此,您可以使用ledcWrite()函数,该函数接受生成信号的PWM通道(而不是输出GPIO)和占空比的参数,如下所示。

ledcWrite(pwmChannel, dutyCycle);

在我们的示例中,我们有一个while循环,可以在每个循环中将占空比增加5。

// Move DC motor forward with increasing speed

digitalWrite(motor1Pin1, HIGH);

digitalWrite(motor1Pin2, LOW);

while (dutyCycle <= 255){

ledcWrite(pwmChannel, dutyCycle);

Serial.print("Forward with duty cycle: ");

Serial.println(dutyCycle);

dutyCycle = dutyCycle + 5;

delay(500);

}

当while条件不再成立时,我们将占空比再次设置为200。

dutyCycle = 200;

写在最后

在本教程中,我们向您展示了如何使用ESP32和L298N电机驱动器来控制DC电机的方向和速度。综上所述:

要控制直流电动机旋转的方向,请使用输入1和输入2引脚;将LOW应用于输入1,将HIGH应用于输入2,以使电动机向前旋转。用另一种方法加电以使其向后旋转。要控制直流电动机的速度,请在使能引脚上使用PWM信号。直流电动机的速度与占空比成正比。
  • 7
    点赞
  • 86
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个ESP32将摄像头拍摄的图片存储到SD卡中的示例程序,它将图片转换为JPG格式并保存到SD卡中: ``` #include "esp_camera.h" #include "esp_timer.h" #include "img_converters.h" #include "sdmmc_cmd.h" #include "driver/sdmmc_host.h" #include "driver/sdspi_host.h" #include "driver/gpio.h" #include "esp_vfs_fat.h" #include "esp_log.h" #define PIN_NUM_MISO 19 #define PIN_NUM_MOSI 23 #define PIN_NUM_CLK 18 #define PIN_NUM_CS 4 static const char* TAG = "example"; // 初始化 SD 卡 static void sd_card_init() { ESP_LOGI(TAG, "Initializing SD card"); sdmmc_host_t host = SDSPI_HOST_DEFAULT(); sdspi_slot_config_t slot_config = SDSPI_SLOT_CONFIG_DEFAULT(); slot_config.gpio_miso = PIN_NUM_MISO; slot_config.gpio_mosi = PIN_NUM_MOSI; slot_config.gpio_sck = PIN_NUM_CLK; slot_config.gpio_cs = PIN_NUM_CS; esp_vfs_fat_sdmmc_mount_config_t mount_config = { .format_if_mount_failed = true, .max_files = 5, .allocation_unit_size = 16 * 1024 }; sdmmc_card_t* card; esp_err_t ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); if (ret != ESP_OK) { if (ret == ESP_FAIL) { ESP_LOGE(TAG, "Failed to mount filesystem. If you want the card to be formatted, set format_if_mount_failed = true."); } else { ESP_LOGE(TAG, "Failed to initialize the card (%s). Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret)); } return; } sdmmc_card_print_info(stdout, card); } // 将图片转换为 JPG 格式并保存到 SD 卡中 void save_jpeg_to_sdcard(camera_fb_t * fb) { char *filename = "/sdcard/picture.jpg"; // 以二进制写方式打开文件 FILE *file = fopen(filename, "wb"); if (file == NULL) { ESP_LOGE(TAG, "Failed to open file for writing"); return; } esp_jpeg_encoder_t *encoder = malloc(sizeof(esp_jpeg_encoder_t)); if (!encoder) { ESP_LOGE(TAG, "JPEG encoder init error"); fclose(file); return; } ESP_LOGI(TAG, "Encoding JPEG image"); // 初始化 JPEG 编码器 esp_err_t err = esp_jpeg_encoder_init(encoder); if (err != ESP_OK) { ESP_LOGE(TAG, "JPEG encoder init error"); fclose(file); free(encoder); return; } // 将图片转换为 RGB888 格式 uint8_t *rgb_buf = malloc(fb->width * fb->height * 3); if (!rgb_buf) { ESP_LOGE(TAG, "RGB buffer allocation failed"); fclose(file); free(encoder); esp_jpeg_encoder_deinit(encoder); return; } size_t out_len; err = fmt2rgb888(fb->buf, fb->len, fb->format, rgb_buf); if (err != ESP_OK) { ESP_LOGE(TAG, "RGB conversion error"); fclose(file); free(encoder); esp_jpeg_encoder_deinit(encoder); free(rgb_buf); return; } // 将 RGB888 格式的图片编码为 JPEG 格式 err = esp_jpeg_encode(encoder, rgb_buf, fb->width, fb->height, PIXFORMAT_RGB888, 95, file, &out_len); if (err != ESP_OK) { ESP_LOGE(TAG, "JPEG encoding error"); fclose(file); free(encoder); esp_jpeg_encoder_deinit(encoder); free(rgb_buf); return; } ESP_LOGI(TAG, "JPEG image saved to SD card"); fclose(file); free(encoder); esp_jpeg_encoder_deinit(encoder); free(rgb_buf); } void app_main() { // 初始化摄像头 camera_config_t config = { .pin_pwdn = -1, .pin_reset = -1, .pin_xclk = 32, .pin_sscb_sda = 26, .pin_sscb_scl = 27, .pin_d7 = 35, .pin_d6 = 34, .pin_d5 = 39, .pin_d4 = 36, .pin_d3 = 21, .pin_d2 = 19, .pin_d1 = 18, .pin_d0 = 5, .pin_vsync = 25, .pin_href = 23, .pin_pclk = 22, .xclk_freq_hz = 10000000, .ledc_timer = LEDC_TIMER_0, .ledc_channel = LEDC_CHANNEL_0, .pixel_format = PIXFORMAT_JPEG, .frame_size = FRAMESIZE_SVGA, .jpeg_quality = 12, .fb_count = 2 }; esp_err_t err = esp_camera_init(&config); if (err != ESP_OK) { ESP_LOGE(TAG, "Camera init failed with error 0x%x", err); return; } // 初始化 SD 卡 sd_card_init(); // 拍摄图片 camera_fb_t * fb = esp_camera_fb_get(); if (!fb) { ESP_LOGE(TAG, "Camera capture failed"); return; } // 将图片保存到 SD 卡中 save_jpeg_to_sdcard(fb); // 释放摄像头缓冲区 esp_camera_fb_return(fb); ESP_LOGI(TAG, "Done"); } ``` 这个示例代码需要使用开发板上的 SD 卡槽和一个 SD 卡。在这个示例中,我们首先初始化 SD 卡,然后拍摄一张图片,将其转换为 RGB888 格式,然后编码为 JPEG 格式并保存到 SD 卡中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值