Microcontroller Programming Self-Learning Tutorial

Click to follow “Stephen“,

Set as “pinned or starred”, to receive valuable content immediately

Microcontroller Programming Self-Learning Tutorial

Table of Contents

  1. Microcontroller Basics
  2. Development Environment Setup
  3. Basic C Language
  4. GPIO Programming
  5. Timer Applications
  6. Interrupt System
  7. Serial Communication
  8. ADC Applications
  9. PWM Control
  10. Sensor Interfaces
  11. Comprehensive Projects
  12. Advanced Technologies

Microcontroller Basics

What is a Microcontroller?

A microcontroller (Microcontroller Unit, MCU) is a compact integrated circuit designed to govern a specific operation in an embedded system. It integrates a CPU, memory, and input/output peripherals, characterized by its small size, low power consumption, low cost, and high reliability, making it widely used in embedded systems.

Basic Components of a Microcontroller

  • CPU: Central Processing Unit, executes instructions
  • Memory: Program memory (Flash), data memory (RAM)
  • Input/Output Interfaces: GPIO, UART, SPI, I2C, etc.
  • Timer: Used for timing and counting
  • Interrupt System: Handles external events
  • ADC/DAC: Analog-to-Digital/Digital-to-Analog Conversion

Common Microcontroller Series

  1. 51 Microcontroller Series

  • Features: Easy to start, abundant resources
  • Representatives: AT89C51, STC89C52
  • Suitable for: Basic learning
  • AVR Series

    • Features: Good performance, moderate price
    • Representatives: ATmega328P, ATmega2560
    • Suitable for: Medium complexity projects
  • ARM Cortex-M Series

    • Features: Powerful performance, rich functionality
    • Representatives: STM32F103, STM32F407
    • Suitable for: Complex projects
  • ESP32 Series

    • Features: Integrated WiFi/Bluetooth
    • Representatives: ESP32-WROOM-32
    • Suitable for: IoT projects

    Development Environment Setup

    Hardware Preparation

    1. Development Board Selection

    • Beginner Recommendation: Arduino Uno or STM32F103C8T6
    • Advanced Recommendation: STM32F407 or ESP32
    • Professional Recommendation: STM32H7 Series
  • Essential Tools

    • USB Data Cable
    • Breadboard and Dupont Wires
    • Common Electronic Components (LEDs, Resistors, Buttons, etc.)
    • Multimeter and Oscilloscope (optional)

    Software Environment

    1. Arduino IDE (Recommended for beginners)

    • Download Link: https://www.arduino.cc/
    • Features: Simple and easy to use, suitable for beginners
    • Supports: Arduino, ESP32, etc.
  • Keil MDK (For STM32 development)

    • Download Link: https://www.keil.com/
    • Features: Powerful, professional-level development
    • Supports: ARM Cortex-M series
  • STM32CubeIDE (Free STM32 development)

    • Download Link: https://www.st.com/
    • Features: Free, fully functional
    • Supports: All STM32 series
  • IAR Embedded Workbench

    • Features: Professional-level development environment
    • Supports: Various MCUs
    • Price: Commercial software

    Environment Configuration Steps

    1. Install Development Software

    • Download and install the selected IDE
    • Configure compiler path
    • Install necessary library files
  • Connect Hardware

    • Connect the development board to the computer via USB
    • Install drivers
    • Confirm device recognition is normal
  • Test Environment

    • Compile a simple program
    • Download to the development board
    • Verify the program runs correctly

    Basic C Language

    Basic Syntax

    // Include header file
    #include <stdio.h>
    
    // Main function
    int main() {
        // Variable declaration
        int a = 10;
        float b = 3.14;
        char c = 'A';
        
        // Output statement
        printf("Hello World!\n");
        
        return 0;
    }

    Data Types

    1. Integer

    • <span>char</span>: 8 bits, -128 to 127
    • <span>int</span>: 16 bits or 32 bits
    • <span>long</span>: 32 bits or 64 bits
    • <span>unsigned</span>: Unsigned type
  • Floating Point

    • <span>float</span>: 32-bit floating point
    • <span>double</span>: 64-bit floating point
  • Pointer Types

    • <span>int *p</span>: Integer pointer
    • <span>void *ptr</span>: Generic pointer

    Control Structures

    // if statement
    if (condition) {
        // Execute code
    } else {
        // Other code
    }
    
    // for loop
    for (int i = 0; i < 10; i++) {
        // Loop code
    }
    
    // while loop
    while (condition) {
        // Loop code
    }

    Function Definition

    // Function declaration
    int add(int a, int b);
    
    // Function definition
    int add(int a, int b) {
        return a + b;
    }

    Arrays and Pointers

    // Array definition
    int array[10];
    
    // Pointer operation
    int *ptr = &array[0];
    *ptr = 100;  // Assignment

    GPIO Programming

    Basic Concepts of GPIO

    GPIO (General Purpose Input/Output) is a general-purpose input/output interface that can be configured as input or output mode.

    Basic Operations

    // Arduino example
    void setup() {
        pinMode(13, OUTPUT);    // Set pin as output
        pinMode(2, INPUT);      // Set pin as input
    }
    
    void loop() {
        digitalWrite(13, HIGH); // Output high level
        delay(1000);
        digitalWrite(13, LOW);  // Output low level
        delay(1000);
    }

    STM32 GPIO Example

    // STM32 GPIO configuration
    void GPIO_Init(void) {
        // Enable GPIOA clock
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        
        // Configure GPIO structure
        GPIO_InitTypeDef GPIO_InitStructure;
        
        // Configure PA0 as output
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
    }
    
    // GPIO operations
    void LED_On(void) {
        GPIO_SetBits(GPIOA, GPIO_Pin_0);
    }
    
    void LED_Off(void) {
        GPIO_ResetBits(GPIOA, GPIO_Pin_0);
    }

    Button Input

    // Button detection
    int buttonPressed(void) {
        if (digitalRead(2) == LOW) {
            delay(20);  // Debounce
            if (digitalRead(2) == LOW) {
                return 1;
            }
        }
        return 0;
    }

    Project Practice: LED Control

    // LED blinking program
    void setup() {
        pinMode(13, OUTPUT);
        pinMode(2, INPUT_PULLUP);
    }
    
    void loop() {
        if (buttonPressed()) {
            digitalWrite(13, !digitalRead(13));  // Toggle LED state
        }
        delay(100);
    }

    Timer Applications

    Timer Basics

    Timers are important peripherals in microcontrollers used for timing, counting, and PWM generation.

    Timer Configuration

    // STM32 timer configuration
    void Timer_Init(void) {
        // Enable timer clock
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        
        // Configure timer
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        TIM_TimeBaseStructure.TIM_Period = 999;  // Auto-reload value
        TIM_TimeBaseStructure.TIM_Prescaler = 7199;  // Prescaler value
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
        
        // Enable timer
        TIM_Cmd(TIM2, ENABLE);
    }

    Timer Interrupts

    // Timer interrupt configuration
    void Timer_Interrupt_Init(void) {
        NVIC_InitTypeDef NVIC_InitStructure;
        
        // Configure NVIC
        NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
        
        // Enable timer interrupt
        TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    }
    
    // Timer interrupt service function
    void TIM2_IRQHandler(void) {
        if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) {
            TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
            
            // Interrupt handling code
            LED_Toggle();
        }
    }

    Arduino Timer

    // Arduino timer example
    unsigned long previousMillis = 0;
    const long interval = 1000;  // 1 second
    
    void loop() {
        unsigned long currentMillis = millis();
        
        if (currentMillis - previousMillis >= interval) {
            previousMillis = currentMillis;
            
            // Code to execute at intervals
            digitalWrite(13, !digitalRead(13));
        }
    }

    Interrupt System

    Interrupt Basics

    Interrupts are an important mechanism for microcontrollers to respond to external events, allowing timely handling of urgent events.

    External Interrupt Configuration

    // STM32 external interrupt configuration
    void EXTI_Init(void) {
        // Enable AFIO clock
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        
        // Configure GPIO as input
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        // Configure external interrupt
        GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
        
        EXTI_InitTypeDef EXTI_InitStructure;
        EXTI_InitStructure.EXTI_Line = EXTI_Line0;
        EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
        EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
        EXTI_InitStructure.EXTI_LineCmd = ENABLE;
        EXTI_Init(&EXTI_InitStructure);
        
        // Configure NVIC
        NVIC_InitTypeDef NVIC_InitStructure;
        NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
    }
    
    // External interrupt service function
    void EXTI0_IRQHandler(void) {
        if (EXTI_GetITStatus(EXTI_Line0) != RESET) {
            EXTI_ClearITPendingBit(EXTI_Line0);
            
            // Interrupt handling code
            LED_Toggle();
        }
    }

    Arduino Interrupt

    // Arduino interrupt example
    void setup() {
        pinMode(13, OUTPUT);
        pinMode(2, INPUT_PULLUP);
        
        // Configure external interrupt
        attachInterrupt(digitalPinToInterrupt(2), buttonISR, FALLING);
    }
    
    void loop() {
        // Main loop code
    }
    
    // Interrupt service function
    void buttonISR() {
        digitalWrite(13, !digitalRead(13));
    }

    Serial Communication

    Serial Basics

    Serial communication (UART) is an important interface for microcontrollers to communicate with external devices.

    Serial Configuration

    // STM32 serial configuration
    void UART_Init(void) {
        // Enable GPIO and UART clock
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
        
        // Configure GPIO
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  // TX
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;  // RX
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        // Configure UART
        USART_InitTypeDef USART_InitStructure;
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_Init(USART2, &USART_InitStructure);
        
        USART_Cmd(USART2, ENABLE);
    }
    
    // Send data
    void UART_SendByte(uint8_t data) {
        while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
        USART_SendData(USART2, data);
    }
    
    // Receive data
    uint8_t UART_ReceiveByte(void) {
        while (USART_GetFlagStatus(USART2, USART_FLAG_RXNE) == RESET);
        return USART_ReceiveData(USART2);
    }

    Arduino Serial

    // Arduino serial example
    void setup() {
        Serial.begin(115200);
        Serial.println("Hello World!");
    }
    
    void loop() {
        if (Serial.available()) {
            char c = Serial.read();
            Serial.print("Received: ");
            Serial.println(c);
        }
        delay(100);
    }

    Serial Communication Project

    // Serial control LED
    void setup() {
        Serial.begin(115200);
        pinMode(13, OUTPUT);
    }
    
    void loop() {
        if (Serial.available()) {
            char command = Serial.read();
            
            switch (command) {
                case '1':
                    digitalWrite(13, HIGH);
                    Serial.println("LED ON");
                    break;
                case '0':
                    digitalWrite(13, LOW);
                    Serial.println("LED OFF");
                    break;
            }
        }
    }

    ADC Applications

    ADC Basics

    ADC (Analog-to-Digital Converter) converts analog signals into digital signals.

    ADC Configuration

    // STM32 ADC configuration
    void ADC_Init(void) {
        // Enable ADC clock
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
        
        // Configure GPIO
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        // Configure ADC
        ADC_InitTypeDef ADC_InitStructure;
        ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
        ADC_InitStructure.ADC_ScanConvMode = DISABLE;
        ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
        ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
        ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
        ADC_InitStructure.ADC_NbrOfChannel = 1;
        ADC_Init(ADC1, &ADC_InitStructure);
        
        // Configure ADC channel
        ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5);
        
        // Enable ADC
        ADC_Cmd(ADC1, ENABLE);
        
        // ADC calibration
        ADC_StartCalibration(ADC1);
        while (ADC_GetCalibrationStatus(ADC1));
    }
    
    // ADC read
    uint16_t ADC_Read(void) {
        ADC_SoftwareStartConvCmd(ADC1, ENABLE);
        while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
        return ADC_GetConversionValue(ADC1);
    }

    Arduino ADC

    // Arduino ADC example
    void setup() {
        Serial.begin(115200);
    }
    
    void loop() {
        int sensorValue = analogRead(A0);
        float voltage = sensorValue * (5.0 / 1023.0);
        
        Serial.print("ADC Value: ");
        Serial.print(sensorValue);
        Serial.print(", Voltage: ");
        Serial.println(voltage);
        
        delay(1000);
    }

    Temperature Sensor Project

    // LM35 temperature sensor
    void setup() {
        Serial.begin(115200);
    }
    
    void loop() {
        int sensorValue = analogRead(A0);
        float voltage = sensorValue * (5.0 / 1023.0);
        float temperature = voltage * 100;  // LM35: 10mV/°C
        
        Serial.print("Temperature: ");
        Serial.print(temperature);
        Serial.println(" °C");
        
        delay(1000);
    }

    PWM Control

    PWM Basics

    PWM (Pulse Width Modulation) is used to control motors, LED brightness, etc.

    PWM Configuration

    // STM32 PWM configuration
    void PWM_Init(void) {
        // Enable clock
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
        
        // Configure GPIO
        GPIO_InitTypeDef GPIO_InitStructure;
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(GPIOA, &GPIO_InitStructure);
        
        // Configure timer
        TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
        TIM_TimeBaseStructure.TIM_Period = 999;
        TIM_TimeBaseStructure.TIM_Prescaler = 71;
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
        TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
        
        // Configure PWM
        TIM_OCInitTypeDef TIM_OCInitStructure;
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_Pulse = 500;  // 50% duty cycle
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
        TIM_OC1Init(TIM2, &TIM_OCInitStructure);
        
        TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);
        TIM_Cmd(TIM2, ENABLE);
    }
    
    // Set PWM duty cycle
    void PWM_SetDuty(uint16_t duty) {
        TIM_SetCompare1(TIM2, duty);
    }

    Arduino PWM

    // Arduino PWM example
    void setup() {
        pinMode(9, OUTPUT);
    }
    
    void loop() {
        // Fade in
        for (int i = 0; i <= 255; i++) {
            analogWrite(9, i);
            delay(10);
        }
        
        // Fade out
        for (int i = 255; i >= 0; i--) {
            analogWrite(9, i);
            delay(10);
        }
    }

    Servo Control

    // Servo control example
    #include <Servo.h>
    
    Servo myservo;
    
    void setup() {
        myservo.attach(9);
    }
    
    void loop() {
        myservo.write(0);    // 0 degrees
        delay(1000);
        myservo.write(90);   // 90 degrees
        delay(1000);
        myservo.write(180);  // 180 degrees
        delay(1000);
    }

    Sensor Interfaces

    Common Sensors

    1. Temperature Sensors: DS18B20, LM35, DHT11
    2. Humidity Sensors: DHT11, DHT22
    3. Distance Sensors: HC-SR04 Ultrasonic
    4. Accelerometer Sensors: MPU6050
    5. Light Sensors: Photoresistor

    DS18B20 Temperature Sensor

    #include <OneWire.h>
    #include <DallasTemperature.h>
    
    OneWire oneWire(2);
    DallasTemperature sensors(&oneWire);
    
    void setup() {
        Serial.begin(115200);
        sensors.begin();
    }
    
    void loop() {
        sensors.requestTemperatures();
        float temperature = sensors.getTempCByIndex(0);
        
        Serial.print("Temperature: ");
        Serial.print(temperature);
        Serial.println(" °C");
        
        delay(1000);
    }

    HC-SR04 Ultrasonic Sensor

    const int trigPin = 9;
    const int echoPin = 10;
    
    void setup() {
        Serial.begin(115200);
        pinMode(trigPin, OUTPUT);
        pinMode(echoPin, INPUT);
    }
    
    void loop() {
        // Send ultrasonic wave
        digitalWrite(trigPin, LOW);
        delayMicroseconds(2);
        digitalWrite(trigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);
        
        // Read echo time
        long duration = pulseIn(echoPin, HIGH);
        
        // Calculate distance
        float distance = duration * 0.034 / 2;
        
        Serial.print("Distance: ");
        Serial.print(distance);
        Serial.println(" cm");
        
        delay(1000);
    }

    MPU6050 Accelerometer Sensor

    #include <Wire.h>
    
    const int MPU_ADDR = 0x68;
    
    void setup() {
        Wire.begin();
        Serial.begin(115200);
        
        // Initialize MPU6050
        Wire.beginTransmission(MPU_ADDR);
        Wire.write(0x6B);
        Wire.write(0);
        Wire.endTransmission(true);
    }
    
    void loop() {
        Wire.beginTransmission(MPU_ADDR);
        Wire.write(0x3B);
        Wire.endTransmission(false);
        Wire.requestFrom(MPU_ADDR, 6, true);
        
        int16_t AcX = Wire.read() << 8 | Wire.read();
        int16_t AcY = Wire.read() << 8 | Wire.read();
        int16_t AcZ = Wire.read() << 8 | Wire.read();
        
        Serial.print("AcX: "); Serial.print(AcX);
        Serial.print(" | AcY: "); Serial.print(AcY);
        Serial.print(" | AcZ: "); Serial.println(AcZ);
        
        delay(1000);
    }

    Comprehensive Projects

    Project 1: Smart Temperature Monitoring System

    #include <DallasTemperature.h>
    #include <LiquidCrystal.h>
    
    OneWire oneWire(2);
    DallasTemperature sensors(&oneWire);
    LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
    
    const int ledPin = 13;
    const int buzzerPin = 8;
    const float tempThreshold = 30.0;
    
    void setup() {
        Serial.begin(115200);
        sensors.begin();
        lcd.begin(16, 2);
        pinMode(ledPin, OUTPUT);
        pinMode(buzzerPin, OUTPUT);
    }
    
    void loop() {
        sensors.requestTemperatures();
        float temperature = sensors.getTempCByIndex(0);
        
        // Display temperature
        lcd.setCursor(0, 0);
        lcd.print("Temp: ");
        lcd.print(temperature);
        lcd.print("C");
        
        // Temperature alarm
        if (temperature > tempThreshold) {
            digitalWrite(ledPin, HIGH);
            tone(buzzerPin, 1000);
            lcd.setCursor(0, 1);
            lcd.print("ALARM!");
        } else {
            digitalWrite(ledPin, LOW);
            noTone(buzzerPin);
            lcd.setCursor(0, 1);
            lcd.print("Normal");
        }
        
        Serial.print("Temperature: ");
        Serial.println(temperature);
        
        delay(1000);
    }

    Project 2: Smart Car

    // Motor control pins
    const int leftMotor1 = 5;
    const int leftMotor2 = 6;
    const int rightMotor1 = 9;
    const int rightMotor2 = 10;
    
    // Ultrasonic sensor
    const int trigPin = 7;
    const int echoPin = 8;
    
    void setup() {
        pinMode(leftMotor1, OUTPUT);
        pinMode(leftMotor2, OUTPUT);
        pinMode(rightMotor1, OUTPUT);
        pinMode(rightMotor2, OUTPUT);
        pinMode(trigPin, OUTPUT);
        pinMode(echoPin, INPUT);
        Serial.begin(115200);
    }
    
    void loop() {
        float distance = getDistance();
        
        if (distance < 20) {
            // Obstacle detected, stop and turn
            stop();
            turnRight();
            delay(500);
        } else {
            // Move forward
            forward();
        }
        
        delay(100);
    }
    
    void forward() {
        analogWrite(leftMotor1, 200);
        analogWrite(leftMotor2, 0);
        analogWrite(rightMotor1, 200);
        analogWrite(rightMotor2, 0);
    }
    
    void backward() {
        analogWrite(leftMotor1, 0);
        analogWrite(leftMotor2, 200);
        analogWrite(rightMotor1, 0);
        analogWrite(rightMotor2, 200);
    }
    
    void turnLeft() {
        analogWrite(leftMotor1, 0);
        analogWrite(leftMotor2, 200);
        analogWrite(rightMotor1, 200);
        analogWrite(rightMotor2, 0);
    }
    
    void turnRight() {
        analogWrite(leftMotor1, 200);
        analogWrite(leftMotor2, 0);
        analogWrite(rightMotor1, 0);
        analogWrite(rightMotor2, 200);
    }
    
    void stop() {
        analogWrite(leftMotor1, 0);
        analogWrite(leftMotor2, 0);
        analogWrite(rightMotor1, 0);
        analogWrite(rightMotor2, 0);
    }
    
    float getDistance() {
        digitalWrite(trigPin, LOW);
        delayMicroseconds(2);
        digitalWrite(trigPin, HIGH);
        delayMicroseconds(10);
        digitalWrite(trigPin, LOW);
        
        long duration = pulseIn(echoPin, HIGH);
        return duration * 0.034 / 2;
    }

    Project 3: IoT Data Collection

    #include <WiFi.h>
    #include <HTTPClient.h>
    #include <DHT.h>
    
    const char* ssid = "YourWiFi";
    const char* password = "YourPassword";
    const char* serverUrl = "http://your-server.com/api/data";
    
    #define DHTPIN 4
    #define DHTTYPE DHT11
    DHT dht(DHTPIN, DHTTYPE);
    
    void setup() {
        Serial.begin(115200);
        dht.begin();
        
        // Connect to WiFi
        WiFi.begin(ssid, password);
        while (WiFi.status() != WL_CONNECTED) {
            delay(1000);
            Serial.println("Connecting to WiFi...");
        }
        Serial.println("WiFi connected");
    }
    
    void loop() {
        float temperature = dht.readTemperature();
        float humidity = dht.readHumidity();
        
        if (WiFi.status() == WL_CONNECTED) {
            HTTPClient http;
            http.begin(serverUrl);
            http.addHeader("Content-Type", "application/json");
            
            String jsonData = "{\"temperature\":" + String(temperature) + ",\"humidity\":" + String(humidity) + "}";
            
            int httpResponseCode = http.POST(jsonData);
            
            if (httpResponseCode > 0) {
                Serial.println("Data sent successfully");
            } else {
                Serial.println("Error sending data");
            }
            
            http.end();
        }
        
        Serial.print("Temperature: ");
        Serial.print(temperature);
        Serial.print("°C, Humidity: ");
        Serial.print(humidity);
        Serial.println("%\n");
        
        delay(5000);  // Send data every 5 seconds
    }

    Advanced Technologies

    RTOS Applications

    #include <FreeRTOS.h>
    #include <task.h>
    
    // Task 1: LED control
    void LEDTask(void *pvParameters) {
        while (1) {
            digitalWrite(13, HIGH);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
            digitalWrite(13, LOW);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
    }
    
    // Task 2: Sensor reading
    void SensorTask(void *pvParameters) {
        while (1) {
            float temperature = dht.readTemperature();
            Serial.print("Temperature: ");
            Serial.println(temperature);
            vTaskDelay(2000 / portTICK_PERIOD_MS);
        }
    }
    
    void setup() {
        Serial.begin(115200);
        pinMode(13, OUTPUT);
        dht.begin();
        
        // Create tasks
        xTaskCreate(LEDTask, "LED", 1000, NULL, 1, NULL);
        xTaskCreate(SensorTask, "Sensor", 1000, NULL, 1, NULL);
    }
    
    void loop() {
        // Empty loop, tasks are scheduled by RTOS
    }

    Low Power Design

    #include <avr/sleep.h>
    #include <avr/power.h>
    
    void setup() {
        Serial.begin(115200);
        pinMode(2, INPUT_PULLUP);
        
        // Configure external interrupt
        attachInterrupt(digitalPinToInterrupt(2), wakeUp, FALLING);
    }
    
    void loop() {
        Serial.println("Going to sleep...");
        delay(1000);
        
        // Enter sleep mode
        set_sleep_mode(SLEEP_MODE_PWR_DOWN);
        sleep_enable();
        sleep_mode();
        
        // Continue execution after waking up
        sleep_disable();
        Serial.println("Woke up!");
    }
    
    void wakeUp() {
        // Interrupt wake-up handling
    }

    Firmware Upgrade

    #include <Update.h>
    
    void setup() {
        Serial.begin(115200);
        
        // Check for firmware updates
        if (checkForUpdate()) {
            performUpdate();
        }
    }
    
    bool checkForUpdate() {
        // Check if there is new firmware on the server
        HTTPClient http;
        http.begin("http://your-server.com/firmware");
        int httpCode = http.GET();
        
        if (httpCode == HTTP_CODE_OK) {
            return true;
        }
        return false;
    }
    
    void performUpdate() {
        HTTPClient http;
        http.begin("http://your-server.com/firmware");
        int httpCode = http.GET();
        
        if (httpCode == HTTP_CODE_OK) {
            int contentLength = http.getSize();
            
            if (Update.begin(contentLength)) {
                size_t written = Update.writeStream(http.getStream());
                
                if (written == contentLength) {
                    if (Update.end()) {
                        Serial.println("Update successful");
                        ESP.restart();
                    }
                }
            }
        }
    }

    Learning Suggestions

    Learning Path

    1. Basic Stage: Master basic C language, familiarize with GPIO operations
    2. Intermediate Stage: Learn about timers, interrupts, and serial communication
    3. Application Stage: Master ADC, PWM, and sensor interfaces
    4. Project Stage: Complete comprehensive projects, accumulate practical experience
    5. Professional Stage: Learn about RTOS, low power design, and firmware upgrades

    Practical Suggestions

    1. Hands-On Practice: Timely practice after theoretical learning
    2. Project-Driven: Learn relevant skills through projects
    3. Problem-Oriented: Look for solutions promptly when encountering problems
    4. Continuous Learning: Stay updated with new technologies and trends

    Recommended Resources

    1. Official Documentation: Technical documents provided by manufacturers
    2. Online Tutorials: Official tutorials for Arduino, STM32, etc.
    3. Technical Forums: Electronics enthusiasts, 21ic, etc.
    4. Open Source Projects: Open source projects on GitHub

    END

    Follow Stephen, learn together, and grow together.

    Click “” to support.

    Leave a Comment