Serial-Studio/examples/LorenzAttractor/LorenzAttractor_ESP32.ino
2024-12-03 02:55:58 -05:00

131 lines
4.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Lorenz Attractor Data Generator (Fixed-Point Arithmetic)
//
// Author: Alex Spataru
//
// This program is specifically designed for the ESP32 microcontroller and simulates
// the Lorenz system using fixed-point arithmetic. The Lorenz system is a set of
// three chaotic differential equations, and the program transmits the generated
// data (x, y, z) over the serial port. The output is ideal for visualizing the
// Lorenz attractor in real-time using tools like Serial Studio.
//
// Lorenz System Parameters:
// - σ (sigma): 10.0 (controls the rate of rotation in the attractor)
// - ρ (rho): 28.0 (sets the "height" of the attractor)
// - β (beta): 8.0 / 3.0 (controls the damping)
//
// How It Works:
// - The program calculates the Lorenz attractor using the Euler method, updating
// the x, y, and z values at each step based on the Lorenz equations.
// - It uses fixed-point arithmetic for precise calculations, which is necessary
// due to the ESP32's 32-bit floating-point limitations.
// - The ESP32's FreeRTOS capabilities are leveraged to separate simulation and
// serial transmission tasks for optimal performance.
// - The data is transmitted asynchronously at regular intervals for visualization.
//
// Required Tools:
// - ESP32 microcontroller (e.g., ESP32 DevKit, NodeMCU ESP32, etc.)
// - Serial Studio or any serial plotting tool to visualize the data.
//
// Baud Rates:
// - Serial Studio: 115200 baud
//
// Notes:
// - This program is optimized for the ESP32 and may require modifications to work
// on other platforms due to its use of FreeRTOS and ESP32-specific features.
// - Ensure your ESP32 board is correctly connected and configured for the Arduino IDE.
//
// How to Run:
// - Load this program onto an ESP32 using the Arduino IDE or similar tool.
// - Connect to the ESP32 via Serial Studio or another serial plotting tool.
// - Observe the real-time Lorenz attractor visualization.
//
#include <Arduino.h>
// Queue for asynchronous data transmission
QueueHandle_t DATA_QUEUE;
///
/// Task to calculate the Lorenz system state
///
void simulationTask(void *param) {
// Parameters for the Lorenz system (scaled by 1000 for fixed-point arithmetic)
const int32_t sigma = 10000; // σ: 10.0 scaled by 1000
const int32_t rho = 28000; // ρ: 28.0 scaled by 1000
const int32_t beta = 2666; // β: 8/3 scaled by 1000
// Initial conditions (scaled by 1000)
int32_t x = 100;
int32_t y = 0;
int32_t z = 0;
// Initialize derivatives
int32_t dx = 0;
int32_t dy = 0;
int32_t dz = 0;
// Time step (scaled by 1000)
const int32_t dt = 10;
// Task loop
while (true) {
// Calculate the derivatives (scaled by 1000)
dx = ((sigma * (y - x)) / 1000) * dt / 1000;
dy = (((x * (rho - z)) / 1000 - y) * dt) / 1000;
dz = (((x * y) / 1000 - (beta * z) / 1000) * dt) / 1000;
// Integrate the derivatives to update the system's state
x += dx;
y += dy;
z += dz;
// Send data to the queue
int32_t data[3] = { x, y, z };
xQueueSend(DATA_QUEUE, &data, portMAX_DELAY);
// Maintain consistent time step
vTaskDelay(pdMS_TO_TICKS(dt));
}
}
///
/// Task to transmit Lorenz system data over Serial
///
void serialTask(void *param) {
while (true) {
int32_t data[3];
if (xQueueReceive(DATA_QUEUE, &data, portMAX_DELAY)) {
Serial.print(data[0] / 1000.0, 6);
Serial.print(",");
Serial.print(data[1] / 1000.0, 6);
Serial.print(",");
Serial.println(data[2] / 1000.0, 6);
}
}
}
///
/// Configures the ESP32, initializes the serial port, and creates tasks
///
void setup() {
// Initialize Serial communication
Serial.begin(115200);
while (!Serial)
;
// Create a queue to hold Lorenz system data
DATA_QUEUE = xQueueCreate(10, sizeof(int32_t[3]));
// Create tasks for simulation and data transmission
xTaskCreate(simulationTask, "SimulationTask", 4096, NULL, 1, NULL);
xTaskCreate(serialTask, "SerialTask", 2048, NULL, 1, NULL);
}
///
/// The main loop is empty; tasks handle simulation and data transmission
///
void loop() {
// Do nothing
}