【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

单片机,应用层,大师,软件 · 浏览次数 : 593

小编点评

**标题:介绍Arduino中的红外线控制** **引言:** 红外线控制是Arduino中一个非常重要的技术。通过使用红外线传感器,我们可以控制LED灯,创建各种自动设备。 **红外线传感器:** 红外线传感器是用于接收红外线信息的设备。红外线传感器使用红外线传感器接收红外线,并通过电路转换为电信号。 **红外线控制电路:** 红外线控制电路用于接收红外线信号,并控制LED灯。电路包含红外线传感器、LED灯、电路板和控制软件。 **代码示例:** ```c #include #include RedSensor redSensor; RedLED redLED; void setup() { Serial.begin(9600); redSensor.begin(); redLED.begin(); } void loop() { int sensorValue = redSensor.read(); if (sensorValue == RED_SENSOR_VALUE) { redLED.show(); } else { redLED.hide(); } Serial.print(sensorValue); delay(1000); } ``` **扩展:** * 使用红外线传感器控制LED灯创建自动设备。 * 使用红外线传感器接收红外线信号并创建自动设备。 * 红外线传感器用于控制红外线灯创建自动设备。 **第三方库:** * RedSensor:红外线传感器库 * RedLED:红外线 LED库 * Arduino.h:Arduino库 **其他:** * 使用红外线传感器控制LED灯创建自动设备。 * 使用红外线传感器接收红外线信号并创建自动设备。 * 红外线传感器用于控制红外线灯创建自动设备。

正文

引言

在上一博客中,我们正式开始了单片机的学习之路,讲了单片机的概念,以及我们使用的ESP32系列的单片机的IO引脚,讲了什么是GPIO,以及相关的总线通讯概念(UART,IIC,SPI),脉冲调制概念(PWM),以及信号数字互转的(ADC和DAC),板子自带的一些功能,在今天的博客中,我会带你们正式进入控制硬件的第一课;

不管是什么单片机,入门第一课都是点亮LED灯,俗称“点灯大师”,哈哈,我们的第一课也是点灯,那我在群里,没有让大家去购买LED,是因为我们实际上可以使用代码去控制ESP板子上面的其中一个LED灯管,当电源接通后会有一个电源灯,红色的灯亮起,电源正常,同时还有一个灯为蓝色的,默认为不显示的,接下来我们便让ESP32开发板的另外一个LED灯进行闪烁。

点灯

void setup() {

  // put your setup code here, to run once:
 pinMode(2,OUTPUT);
}

void loop() {
  digitalWrite(2, HIGH);   // sets the LED on
  delay(1000);                  // waits for a second
  digitalWrite(2, LOW);    // sets the LED off
  delay(1000);       
}         

先上代码,如上所示,即可点亮板子的另一个蓝色的灯,先讲一下代码,上面的setup,一个单片机通电,只会运行一次,即每通电一次,运行一次,下面的loop是循环的一个代码,通电期间,一直循环,先运行setup,在运行loop,上面的setup顾名思义,是用来对单片机做一些配置,上面的配置就是将第二个引脚设置为输出,即单片机向引脚2输出,输出高低电平,用来点亮LED灯,在ESP32中,蓝色灯的引脚为2,所以在此处我们设置引脚2为输出模式,

第二个loop循环代码,第一行调用了一个digitalWrite的方法,这个方法是给我们指定的引脚写入高低电平,以此来给某个引脚开关通电,断电,第一个参数为要写入的引脚的pin值,即引脚值,第二个参数为需要写入的值,HIGH,LOW这两个为高低电平,HIGH通电,LOW断电,第二行代码,则是一个延迟函数,里面的值是毫秒值,1000,即代表暂停一秒

下面的gif展示了我们这次的一个运行结果,可以看到蓝色灯在不停的进行闪烁。

代码编译和烧录

在我们代码写完成之后,我们需要编译,然后在烧写到单片机里面去,那每次写完之后呢,在编辑器左上角有一个对号的按钮,我们点击这个按钮之后,ide会开始编译我们的代码,在编译之后,我们需要将代码烧录到单片机内部,点击对号旁边的右箭头按钮,代码开始烧录,等待下方出现Connecting的时候,我们要让单片机进入下载模式,单片机上面有两个按钮,电源灯上面有一个按钮,同横着水平旁边还有一个按钮,当出现了Connecting的时候需要去按住下方箭头所指的那个按钮不松手,则会写入程序。

Arduino

我们的开发IDE为Arduino,我之前配过vsc使用纯c语言去进行开发ESP32单片机,后面使用了Arduino,因为这个相比于纯c来说更简单一些,更适合入门,但是对于C开发,原理也是一样的,无非就是写法上纯在差异。

在程序运行都是不停的在进行循环代码,但是方法上一个是main方法,一个是loop其他的就是语法的区别了,Arduino是基于c和c++进行封装的,里面的封装更趋近于高级语言,这里展示一下Arduino的一些方法或者常量,数据类型等。

C语言

而对于c语言来说,有的基础不好,或者没有深入使用过c语言的来讲是有一些难度的,我在这里贴一下我之前写的一个红外线控制智能小车的代码,此处使用的是esp32原生的c文件来进行开发,其复杂程度和Arduino相比还是略现复杂。

/* brushed dc motor control example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

/*
 * This example will show you how to use MCPWM module to control brushed dc motor.
 * This code is tested with L298 motor driver.
 * User may need to make changes according to the motor driver they use.
 */

#include <stdio.h>
#include "sdkconfig.h"
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_attr.h"
#include "driver/rmt.h"
#include "driver/mcpwm.h"
#include "soc/mcpwm_periph.h"
#include "IR_Rev.h"
// const static char *TAG = "IR_Rre Demo";

#define RECV_PIN 23  // 一体化红外接收头GPIO
uint8_t command = 0; // 接收到的ENC红外指令
int direction = 0;
float currentspeed = 0;
int currentcolor = 2;
#define GPIO_PWM0A_OUT 15 // Set GPIO 15 as PWM0A
#define GPIO_PWM0B_OUT 16 // Set GPIO 16 as PWM0B
#define GPIO_PWM1A_OUT 17
#define GPIO_PWM1B_OUT 18
#define GPIO_PWM2A_OUT 12 // Set GPIO 15 as PWM0A
#define GPIO_PWM2B_OUT 14 // Set GPIO 16 as PWM0B
#define GPIO_PWM3A_OUT 25
#define GPIO_PWM3B_OUT 26
#define RED 2
#define GREEN 4
#define BLUE 5
#define INFARE 21
static void mcpwm_example_gpio_initialize(void)
{
    printf("initializing mcpwm gpio...\n");
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0A, GPIO_PWM0A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM0B, GPIO_PWM0B_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1A, GPIO_PWM1A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_0, MCPWM1B, GPIO_PWM1B_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM0A, GPIO_PWM2A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM0B, GPIO_PWM2B_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM1A, GPIO_PWM3A_OUT);
    mcpwm_gpio_init(MCPWM_UNIT_1, MCPWM1B, GPIO_PWM3B_OUT);
}
// forwards he forward 替换实现顺时针吹风和逆时针吹风
/**
 * @brief motor moves in forward direction, with duty cycle = duty %
 */
static void brushed_motor_forward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle)
{
    mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A);
    mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_B, duty_cycle);
    mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_DUTY_MODE_0); // call this each time, if operator was previously in low/high state
}
static void brushed_motor_forwards(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle)
{
    ESP_ERROR_CHECK(mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B));
    ESP_ERROR_CHECK(mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_A, duty_cycle));
    ESP_ERROR_CHECK(mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_DUTY_MODE_0)); // call this each time, if operator was previously in low/high state
}
// forwards he forward 替换实现顺时针吹风和逆时针吹风
/**
 * @brief motor moves in forward direction, with duty cycle = duty %
 */
static void brushed_motor_backward(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle)
{
    mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B);
    mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_A, duty_cycle);
    mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_A, MCPWM_DUTY_MODE_0); // call this each time, if operator was previously in low/high state
}
static void brushed_motor_backwards(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num, float duty_cycle)
{
    ESP_ERROR_CHECK(mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A));
    ESP_ERROR_CHECK(mcpwm_set_duty(mcpwm_num, timer_num, MCPWM_OPR_B, duty_cycle));
    ESP_ERROR_CHECK(mcpwm_set_duty_type(mcpwm_num, timer_num, MCPWM_OPR_B, MCPWM_DUTY_MODE_0)); // call this each time, if operator was previously in low/high state
}

/**
 * @brief motor stop
 */
static void brushed_motor_stop(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num)
{
    mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_A);
    mcpwm_set_signal_low(mcpwm_num, timer_num, MCPWM_OPR_B);
}

static void setspeed(uint8_t command)
{
    if ((uint8_t)command == 22)
    {
        printf("%d\n", 22);
        currentspeed = 10;
    }
    else if ((uint8_t)command == 12)
    {
        printf("%d\n", 12);
        currentspeed = 20;
    }
    else if ((uint8_t)command == 24)
    {
        printf("%d\n", 24);
        currentspeed = 30;
    }
    else if ((uint8_t)command == 94)
    {
        printf("%d\n", 94);
        currentspeed = 40;
    }
    else if ((uint8_t)command == 8)
    {
        printf("%d\n", 8);
        currentspeed = 50;
    }
    else if ((uint8_t)command == 28)
    {
        printf("%d\n", 28);
        currentspeed = 60;
    }
    else if ((uint8_t)command == 90)
    {
        printf("%d\n", 90);
        currentspeed = 70;
    }
    else if ((uint8_t)command == 66)
    {
        printf("%d\n", 66);
        currentspeed = 80;
    }
    else if ((uint8_t)command == 82)
    {
        printf("%d\n", 82);
        currentspeed = 90;
    }
    else if ((uint8_t)command == 74)
    {
        printf("%d\n", 74);
        currentspeed = 100;
    }
}
static void head(float speed)
{
    brushed_motor_forward(MCPWM_UNIT_0, MCPWM_TIMER_0, speed);
    brushed_motor_forwards(MCPWM_UNIT_0, MCPWM_TIMER_1, speed);
    brushed_motor_forward(MCPWM_UNIT_1, MCPWM_TIMER_0, speed);
    brushed_motor_forwards(MCPWM_UNIT_1, MCPWM_TIMER_1, speed);
}
static void last(float speed)
{
    brushed_motor_backward(MCPWM_UNIT_0, MCPWM_TIMER_0, speed);
    brushed_motor_backwards(MCPWM_UNIT_0, MCPWM_TIMER_1, speed);
    brushed_motor_backward(MCPWM_UNIT_1, MCPWM_TIMER_0, speed);
    brushed_motor_backwards(MCPWM_UNIT_1, MCPWM_TIMER_1, speed);
}
static void left(float speed)
{
    mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_1, MCPWM_OPR_A);
    mcpwm_set_signal_low(MCPWM_UNIT_1, MCPWM_TIMER_0, MCPWM_OPR_B);
}
static void right(float speed)
{
    mcpwm_set_signal_low(MCPWM_UNIT_0, MCPWM_TIMER_0, MCPWM_OPR_B);
    mcpwm_set_signal_low(MCPWM_UNIT_1, MCPWM_TIMER_1, MCPWM_OPR_A);
}
/**
 * @brief Configure MCPWM module for brushed dc motor
 */
static void mcpwm_example_brushed_motor_control(void *arg)
{
    // 1. mcpwm gpio initialization
    mcpwm_example_gpio_initialize();

    // 2. initial mcpwm configuration
    printf("Configuring Initial Parameters of mcpwm...\n");
    mcpwm_config_t pwm_config;
    pwm_config.frequency = 1000; // frequency = 500Hz,
    pwm_config.cmpr_a = 0;       // duty cycle of PWMxA = 0
    pwm_config.cmpr_b = 0;       // duty cycle of PWMxb = 0
    pwm_config.counter_mode = MCPWM_UP_COUNTER;
    pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_0, &pwm_config)); // Configure PWM0A & PWM0B with above settings
    mcpwm_config_t pwm_configs;
    pwm_configs.frequency = 1000; // frequency = 500Hz,
    pwm_configs.cmpr_a = 0;       // duty cycle of PWMxA = 0
    pwm_configs.cmpr_b = 0;       // duty cycle of PWMxb = 0
    pwm_configs.counter_mode = MCPWM_UP_COUNTER;
    pwm_configs.duty_mode = MCPWM_DUTY_MODE_0;
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_0, MCPWM_TIMER_1, &pwm_configs)); // Configure PWM0A & PWM0B with above settings

    mcpwm_config_t pwm_configA;
    pwm_configA.frequency = 1000; // frequency = 500Hz,
    pwm_configA.cmpr_a = 0;       // duty cycle of PWMxA = 0
    pwm_configA.cmpr_b = 0;       // duty cycle of PWMxb = 0
    pwm_configA.counter_mode = MCPWM_UP_COUNTER;
    pwm_configA.duty_mode = MCPWM_DUTY_MODE_0;
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_1, MCPWM_TIMER_0, &pwm_configA)); // Configure PWM0A & PWM0B with above settings
    mcpwm_config_t pwm_configAs;
    pwm_configAs.frequency = 1000; // frequency = 500Hz,
    pwm_configAs.cmpr_a = 0;       // duty cycle of PWMxA = 0
    pwm_configAs.cmpr_b = 0;       // duty cycle of PWMxb = 0
    pwm_configAs.counter_mode = MCPWM_UP_COUNTER;
    pwm_configAs.duty_mode = MCPWM_DUTY_MODE_0;
    ESP_ERROR_CHECK(mcpwm_init(MCPWM_UNIT_1, MCPWM_TIMER_0, &pwm_configAs)); // Configure PWM0A & PWM0B with above settings */ */
    while (1)
    {
        command = IRrecvReadIR();


        printf("IR Command is %02X\n", command);
        printf("IR 111 is %d\n", (uint8_t)command);
        if ((uint8_t)command == 69)
        {
            brushed_motor_stop(MCPWM_UNIT_0, MCPWM_TIMER_0);
            brushed_motor_stop(MCPWM_UNIT_0, MCPWM_TIMER_1);
            brushed_motor_stop(MCPWM_UNIT_1, MCPWM_TIMER_0);
            brushed_motor_stop(MCPWM_UNIT_1, MCPWM_TIMER_1);
        }
        else if ((uint8_t)command == 64)
        {
            direction = 64;
            head(currentspeed);
        }
        else if ((uint8_t)command == 25)
        {
            direction = 25;
            last(currentspeed);
        }
        else if ((uint8_t)command == 7)
        {
            printf("IR 32 is %d\n", (uint8_t)command);
            left(currentspeed);
        }
        else if ((uint8_t)command == 9)
        {
            printf("IR 23 is %d\n", (uint8_t)command);
            right(currentspeed);
        }
        else
        {
            printf(" %d\n", direction);
            setspeed(command);
            if (direction == 64)
            {
                head(currentspeed);
            }
            else if (direction == 25)
            {
                last(currentspeed);
            }
        }
    }
}
static void openlight(void *arg)
{
    gpio_set_level(INFARE, 1);
    while (1)
    {

        gpio_set_level(currentcolor, 1);
        vTaskDelay(200 / portTICK_PERIOD_MS);
        gpio_set_level(currentcolor, 0);
        if(currentcolor==2)
        {
            currentcolor=4;
        }
        else if (currentcolor==4)
        {
            currentcolor=5;
        }
        else if (currentcolor==5)
        {
            currentcolor=2;
        }
    }

}
void app_main(void)
{
    IRrecvInit(RECV_PIN, 3);
    gpio_set_direction(INFARE, GPIO_MODE_OUTPUT);
    gpio_set_direction(RED, GPIO_MODE_OUTPUT);
    gpio_set_direction(GREEN, GPIO_MODE_OUTPUT);
    gpio_set_direction(BLUE, GPIO_MODE_OUTPUT);
    xTaskCreate(mcpwm_example_brushed_motor_control, "mcpwm_examlpe_brushed_motor_control", 4096, NULL, 5, NULL);
    xTaskCreate(openlight, "openlight", 4096, NULL, 5, NULL);
}

而令我最喜欢Arduino的一点是,我们需要使用一些第三方库的时候,这里的扩展相比VSC更容易找一些,C的话在插件市场极大可能找不到,需要在网上自己搜索,找到c语言写好的文件,然后include进来再去使用,找的话有点难度,对于红外线来讲,上次我在网上找就找了挺久的一段时间。而在Arduino我只需在管理库界面搜索我想要的库或者关键字都可以找到,emmm,我觉得就像nuget一样简单,哈哈,所以我更喜欢用这个一点。

在这里,我们就可以根据关键字,类型去搜索我们想要的第三方库,很方便,同时有的第三方库也是有例子可以直接使用,总体来说,作为简单入门,Arduino还是很不错的一个选择。

结语

好啦,今天的点灯第一课就到这里啦,如果又不懂的可以随时问我,可以加这个群一起来学习单片机,后面还会开stm32系列的课程,IDE的话可以看上一篇博客中的下载地址是有百度网盘的地址,同时群文件也有,有需要的可以下载啦,我们系列教程会出到可以自己做一个智能小车为止。

与【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师相似的内容:

【单片机入门】(二)应用层软件开发的单片机学习之路-----点灯大师

引言 在上一博客中,我们正式开始了单片机的学习之路,讲了单片机的概念,以及我们使用的ESP32系列的单片机的IO引脚,讲了什么是GPIO,以及相关的总线通讯概念(UART,IIC,SPI),脉冲调制概念(PWM),以及信号数字互转的(ADC和DAC),板子自带的一些功能,在今天的博客中,我会带你们正

【单片机入门】(三)应用层软件开发的单片机学习之路-----UART串口通讯和c#交互

引言 在第一章博客中,我们讲了Arduino对Esp32的一个环境配置,以及了解到了常用的一个总线通讯协议,其中有SPI,IIC,UART等,今天我为大家带来UART串口通讯和c#串口进行通讯的一个案例,以及什么是中断,中断的作用和实践,话不多说,让我们正式开始。 UART 在第一篇博客中,我们讲了

【单片机入门】(四)应用层软件开发的单片机学习之路-----ESP32开发板PWM控制电机以及中断的使用

引言 各位大佬,晚上好啊,在上一篇博客中,我们讲了什么是UART串口通讯,以及使用USB转TTL使得单片机可以和c#上位机做一个串口通讯,接下来,为大家带来PWM的概念原理,以及实际案例,使用PWM对电机进行速度调制,因为本课程的最后是做一个红外遥控的智能小车,所以是需要电机四个,驱动四个,轮胎四个

【Flink入门修炼】2-3 Flink Checkpoint 原理机制

如果让你来做一个有状态流式应用的故障恢复,你会如何来做呢? 单机和多机会遇到什么不同的问题? Flink Checkpoint 是做什么用的?原理是什么?

《最新出炉》系列入门篇-Python+Playwright自动化测试-44-鼠标操作-上篇

1.简介 前边文章中已经讲解过鼠标的拖拽操作,今天宏哥在这里对其的其他操作进行一个详细地介绍和讲解,然后对其中的一些比较常见的、重要的操作单独拿出来进行详细的介绍和讲解。 2.鼠标操作语法 鼠标操作介绍官方API的文档地址:https://playwright.dev/docs/api/class-

《最新出炉》系列入门篇-Python+Playwright自动化测试-8-上下文(Context)

1.简介 其实前边的文章中也提到过Context,只不过是 一笔带过,但是宏哥觉得在playwright中挺重要的,所以宏哥今天单独将其拎出来讲解和分享一下,希望对您有所帮助或者参考。 2.前言 Playwright为每个测试创建一个浏览器上下文,即BrowserContext,浏览器上下文相当于一

《最新出炉》系列入门篇-Python+Playwright自动化测试-10-标签页操作(tab)

1.简介 标签操作其实也是基于浏览器上下文(BrowserContext)进行操作的,而且宏哥在之前的BrowserContext也有提到过,但是有的童鞋或者小伙伴还是不清楚怎么操作,或者思路有点模糊,因此今天单独来对其进行讲解和分享一下,希望您有所帮助。 2.单标签页 单个标签操作这个是最简单的,

限流器设计思路(浅入门)

目录令牌桶算法(Token Bucket)漏桶算法(Leaky Bucket)滑动窗口(Sliding Window)总结 限流器(Rate Limiter)是一种用于控制系统资源利用率和质量的重要机制。它通过限制单位时间内可以执行的操作数量,从而防止系统过载和保护服务的可靠性。在Java中,可以使

《最新出炉》系列入门篇-Python+Playwright自动化测试-9-页面(page)

1.简介 通过前边的讲解和学习,细心认真地小伙伴或者童鞋们可能发现在Playwright中,没有Element这个概念,只有Page的概念,Page不仅仅指的是某个页面,例如页面间的跳转等,还包含了所有元素、事件的概念,所以我们包括定位元素、页面转向,都是基于Page操作的。页面提供了与浏览器中的单

[转帖]Eclipse-MAT的插件介绍使用

学习 尚硅谷 宋红康 JVM从入门到精通 的学习笔记 概述 MAT (Memory Analyzer Tool ) 工具是一款功能强大的Java堆内存分析器.可以用于查找内存泄露以及查看内存消耗情况. MAT是基于Eclipse开发的,不仅仅可以单独使用,还可以作为插件的形式内嵌在Eclipse中使