Introduction to MCU Lesson 2-Master Lighting

Introduction to MCU Lesson 2-Master Lighting

Officially enter the first lesson in controlling hardware

最后更新 10/21/2022 6:53 PM
陈显达
预计阅读 14 分钟
分类
share
标签
hardware-related

This article was submitted by a netizen, but the webmaster doesn't understand hardware at all.

Author: Chen Xianda

Original title: Introduction to MCU Lesson 2----Master Lighting

Original link: www.cnblogs.com/1996-Chinese-Chen/p/16814553.html

introduction

In the last blog, we officially started the learning path of single-chip computers. We talked about the concept of single-chip computers, the IO pins of the ESP32 series single-chip computers we use, and what GPUs are, as well as related bus communication concepts (UART,IIC,SPI), pulse modulation concepts (PWM), and signal digital conversion (ADC and DAC), and some of the functions that come with the board. In today's blog, I will take you officially into the first lesson of control hardware;

No matter what kind of MCU it is, the first lesson is to light up LED lights, commonly known as the "Master Lighting". Haha, our first lesson is also lighting up. So in the group, I didn't ask everyone to buy LEDs because we actually can use the code to control one of the LED tubes on the ESP board. When the power is connected, there will be a power lamp. The red lamp will light up and the power supply is normal. At the same time, there will be another lamp that is blue and will not be displayed by default. Next, we let another LED on the ESP32 development board flash.

lighting

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);
}         

Apply the code first, as shown above, and you can light up the other blue light on the board. Let me talk about the code first. The setup above means that a single chip microcomputer is powered on and will only run once, that is, every time it is powered on, it will run once. The loop below is a code for cycling. During the power-on period, it will always cycle, run setup first, and then run loop. The setup above is used to make some configurations for the single chip microcomputer. The above configuration is to set the second pin as output. That is, the MCU outputs to Pin 2, which outputs high and low levels to light up the LED light. In the ESP32, the pin of the blue light is 2, so here we set Pin 2 as the output mode.

In the second loop loop code, the first line calls a digitalWrite method. This method writes high and low levels to the pins we specified to power on and off a pin switch. The first parameter is the pin value of the pin to be written, that is, the pin value. The second parameter is the value to be written. HIGH and LOW are the high and low levels. HIGH is on and LOW is off. The second line of code is a delay function, and the value inside is the millisecond value, 1000. That means pause for one second

The gif below shows the results of one of our runs this time. You can see the blue light flashing constantly.

Code compilation and burning

After we finish writing the code, we need to compile it and then burn it into the MCU. After each time we write it, there is a checkmark button in the upper left corner of the editor. After we click this button, the ide will start compiling our code. After compiling, we need to burn the code into the MCU, click the right arrow button next to the checkmark, and the code will start burning. When Connecting appears below, we want the MCU to enter download mode. There are two buttons on the MCU, one button on the power lamp, and another button next to the horizontal level. When Connecting appears, you need to press and hold the button pointed by the arrow below without letting go, and the program will be written.

Arduino

Our development IDE is Arduino. I used vsc to use pure C language to develop ESP32 MCU. Later, I used Arduino because this is simpler than pure C and more suitable for getting started. However, for C development, the principle is the same, but it is nothing more than a pure difference in writing.

While the program is running, the code is constantly looped, but one of the methods is the main method, the other is loop. The other is the syntax difference. Arduino is encapsulated based on c and c++, and the encapsulation inside is closer to high-level languages. Here are some Arduino methods or constants, data types, etc.

C language

As for the C language, it is difficult for some people who have not had a good foundation or have not used the C language in depth. I will post here the code for an infrared control smart car I wrote before. The use here is an esp32 native C file for development, and its complexity is still slightly more complicated than that of 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);
}

The thing I like most about Arduino is that when we need to use some third-party libraries, the extensions here are easier to find than VSC. If you use C, you probably won't be able to find them in the plug-in market. You need to search on the Internet and find files written in C language, and then include them before using them. It's a bit difficult to find. For infrared, I searched for them online for a long time last time. In Arduino, I only need to search for the library or keywords I want in the management library interface and can find it. emmm, I think it's as simple as nuget, haha, so I prefer to use this one.

Here, we can search for the third-party libraries we want based on keywords and types, which is very convenient. At the same time, some third-party libraries also have examples that can be used directly. Overall, as a simple entry, Arduino is still a very good choice.

conclusion

Okay, that's the end of today's first lesson on lighting. If you don't understand anything, you can ask me anytime. You can join this group to learn about single-chip computers. There will be a stm32 series of courses later. If you want to use the IDE, you can watch a blog. The download address in the download address is the address of Baidu's online disk, and there are also group files. You can download if you need it. Our series of tutorials will be released until you can make your own smart car.

Keep Exploring

延伸阅读

更多文章