Welcome to this hands-on tutorial for getting started with ESP8266 using PlatformIO! We'll cover the basics of setting up your development environment and then dive into a series of challenges to learn about serial communication, GPIO, PWM, and servos. Finally, we'll introduce you to the basics of FreeRTOS.
- Install Visual Studio Code (VSCode) from https://code.visualstudio.com/
- Open VSCode and go to the Extensions view (Ctrl+Shift+X)
- Search for "PlatformIO" and install the PlatformIO IDE extension
- Restart VSCode after the installation
- Click on the PlatformIO icon in the left sidebar
- Choose "New Project"
- Name your project "ESP8266_Tutorial"
- Select "Espressif ESP8266 ESP-12E" as your board
- Choose "Arduino" as your framework
- Wait for the project to be created and initialized
Objective: Print "Hello, ESP8266!" to the serial monitor every second.
- Open
src/main.cpp - Replace the contents with the following code:
#include <Arduino.h>
void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println("Hello, ESP8266!");
delay(1000);
}- Build and upload the code to your ESP8266
- Open the Serial Monitor to see the output
Challenge: Modify the code to print the number of seconds since the ESP8266 started.
Objective: Make the built-in LED blink every 500ms.
- Modify
src/main.cpp:
#include <Arduino.h>
const int LED_PIN = 2; // Built-in LED on ESP-12E module
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
digitalWrite(LED_PIN, HIGH);
delay(500);
digitalWrite(LED_PIN, LOW);
delay(500);
}- Upload and observe the blinking LED
Challenge: Create a morse code function that blinks "SOS" (... --- ...) repeatedly.
Objective: Use PWM to gradually fade the LED in and out.
- Update
src/main.cpp:
#include <Arduino.h>
const int LED_PIN = 2;
void setup() {
pinMode(LED_PIN, OUTPUT);
}
void loop() {
for (int i = 0; i <= 255; i++) {
analogWrite(LED_PIN, i);
delay(10);
}
for (int i = 255; i >= 0; i--) {
analogWrite(LED_PIN, i);
delay(10);
}
}- Upload and observe the fading LED
Challenge: Implement a "breathing" effect by using a sine wave for smoother transitions.
Objective: Control a servo motor using the ESP8266.
- Connect a servo to your ESP8266 (signal wire to GPIO 4, power to 3.3V, ground to GND)
- Install the "ESP8266Servo" library from PlatformIO Library Manager
- Update
src/main.cpp:
#include <Arduino.h>
#include <ESP8266Servo.h>
Servo myservo;
const int SERVO_PIN = 4;
void setup() {
myservo.attach(SERVO_PIN);
}
void loop() {
myservo.write(0);
delay(1000);
myservo.write(90);
delay(1000);
myservo.write(180);
delay(1000);
}- Upload and watch the servo move
Challenge: Create a function that moves the servo to a random position every 2 seconds.
FreeRTOS is a real-time operating system that allows you to create tasks that run concurrently. Let's create a simple example using FreeRTOS and explore its key concepts.
- Update
src/main.cpp:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
Ticker blinker;
const int LED_PIN = 2;
bool ledState = false;
void blinkLED() {
ledState = !ledState;
digitalWrite(LED_PIN, ledState);
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
blinker.attach(0.5, blinkLED); // Blink LED every 500ms
xTaskCreate(
[](void * parameters) {
for(;;) {
Serial.println("Hello from FreeRTOS task!");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
},
"PrintTask",
1000,
NULL,
1,
NULL
);
}
void loop() {
// The loop function can be empty when using FreeRTOS
}- Upload and observe the LED blinking and serial output
This example demonstrates two concurrent operations:
- Blinking the LED using the Ticker library
- Printing a message every second using a FreeRTOS task
The xTaskCreate function is fundamental to FreeRTOS. It's used to create a new task. Let's break down its parameters:
BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode,
const char * const pcName,
uint16_t usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask
);In our example:
xTaskCreate(
[](void * parameters) {
for(;;) {
Serial.println("Hello from FreeRTOS task!");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
},
"PrintTask",
1000,
NULL,
1,
NULL
);Let's examine each parameter:
-
TaskFunction_t pvTaskCode: This is the actual function that will run as a task. We're using a lambda function that prints a message and then delays for 1 second. -
const char * const pcName: This is a name for the task, used for debugging. We've named it "PrintTask". -
uint16_t usStackDepth: This is the stack size in words. We've allocated 1000 words. -
void *pvParameters: These are parameters to pass to the task. We're not using any, so it's NULL. -
UBaseType_t uxPriority: This sets the priority of the task. We've set it to 1, which is a low priority. -
TaskHandle_t *pxCreatedTask: This is a handle to the created task. We're not storing the handle, so it's NULL.
The FreeRTOS scheduler is responsible for deciding which task should be running at any given time. It uses a priority-based preemptive scheduling algorithm. Here are some key points:
- Each task is given a priority (in our case, we set it to 1).
- The scheduler ensures that the highest priority task that is ready to run gets CPU time.
- Tasks with the same priority are scheduled round-robin (they take turns).
- Lower priority tasks only run when no higher priority tasks are ready.
vTaskDelay()is used to make a task "sleep" for a specified time, allowing other tasks to run.
In our example, we only have one task, so it will run repeatedly, printing the message and then delaying for 1 second.
The blinker.attach function is not part of FreeRTOS, but comes from the Ticker library, which is specific to ESP8266. Here's how it's used in our code:
Ticker blinker;
blinker.attach(0.5, blinkLED);The attach function sets up a function to be called repeatedly at a specified interval. It takes two parameters:
float seconds: The interval in seconds. In our case, it's 0.5 seconds.callback_t callback: The function to be called. In our case, it'sblinkLED.
This setup will cause the blinkLED function to be called every 0.5 seconds, toggling the LED state. This happens independently of the FreeRTOS task we created.
In this example, our program is doing two things concurrently:
- Blinking an LED every 0.5 seconds using the Ticker library.
- Printing a message every second using a FreeRTOS task.
This demonstrates how we can handle multiple operations on the ESP8266, some using FreeRTOS (like our printing task) and others using platform-specific libraries (like the LED blinking with Ticker).
Now that you understand the basics of FreeRTOS and task creation, try these challenges:
- Create a second task that increments a counter and prints its value every 5 seconds.
- Modify the LED blinking task to use FreeRTOS instead of the Ticker library.
- Implement a simple state machine using FreeRTOS tasks to control multiple LEDs.
Remember, FreeRTOS is a powerful tool for managing concurrent operations on your ESP8266. As you build more complex projects, you'll find it invaluable for organizing your code and managing multiple simultaneous tasks.