{ "cells": [ { "cell_type": "markdown", "id": "2ce0d28d", "metadata": {}, "source": [ "# Programar" ] }, { "cell_type": "markdown", "id": "68ad5ac7", "metadata": {}, "source": [ "\n", "## Arquitetura Modular\n", "\n", "Um sistema como o do **aeropêndulo** envolve vários componentes (sensor, atuador, driver, controlador, interface). \n", "Se o código for escrito de forma monolítica, rapidamente se torna **difícil de entender, testar e manter**. \n", "\n", "Uma **arquitetura modular baseada em máquinas de estado** permite: \n", "- Que terceiros compreendam facilmente a lógica do programa e das suas partes. \n", "- Testar cada módulo de forma independente. \n", "- Garantir que diferentes tarefas (ex.: leitura de sensores, comando do motor, interface com utilizador) não se bloqueiam mutuamente. \n", "- Evitar o uso de `delay()`, que pode ser fatal num sistema de controlo em tempo real. \n", "- Usar de forma eficiente os recursos de hardware do Arduino, como o **gerador PWM** ou as **interrupções**, libertando o processador de tarefas críticas temporizadas.\n", "\n", "---\n", "\n", "## Introdução a Máquinas de Estado\n", "\n", "Uma **máquina de estados finitos (FSM – Finite State Machine)** é um modelo que organiza o comportamento de um sistema em **estados**, com **transições** entre eles, desencadeadas por **eventos**. \n", "\n", "Elementos principais:\n", "- **Estados:** configurações em que o sistema pode estar (ex.: “verde”, “amarelo”, “vermelho”). \n", "- **Estado inicial:** ponto de partida. \n", "- **Transições:** regras de mudança de estado. \n", "- **Eventos:** condições que causam a transição. \n", "- **Estado final:** opcional, marca o fim da execução. \n", "\n", "**Exemplo genérico:** um semáforo alterna entre verde, amarelo e vermelho, com tempos definidos.\n", "\n", "---\n", "\n", "## Exemplo 1 — Dois LEDs a Piscar em Concorrência\n", "\n", "Um primeiro exercício útil é piscar **dois LEDs com frequências diferentes**.\n", "Cada LED é controlado por uma **máquina de estado independente**, mas ambas executam em concorrência dentro do `loop()`.\n", "\n", "```cpp\n", "#define LED1 2\n", "#define LED2 3\n", "\n", "float f1 = 1.0; // Frequência LED1 [Hz]\n", "float f2 = 2.0; // Frequência LED2 [Hz]\n", "int duty = 50; // Duty cycle (%)\n", "\n", "void setup() {\n", " pinMode(LED1, OUTPUT);\n", " pinMode(LED2, OUTPUT);\n", " Serial.begin(115200);\n", "}\n", "\n", "void loop() {\n", " autoBlink(LED1, f1, duty);\n", " autoBlink(LED2, f2, duty);\n", "}\n", "\n", "void autoBlink(int pin, float f, int duty) {\n", " const int APAGADO = 0, ACESO = 1;\n", " static int state = APAGADO;\n", " static unsigned long t0 = millis();\n", "\n", " int T = 1000 / f; \n", " int TH = T * duty / 100;\n", " int TL = T - TH;\n", "\n", " switch (state) {\n", " case APAGADO:\n", " if (millis() - t0 > TL) {\n", " digitalWrite(pin, HIGH);\n", " t0 = millis();\n", " state = ACESO;\n", " }\n", " break;\n", " case ACESO:\n", " if (millis() - t0 > TH) {\n", " digitalWrite(pin, LOW);\n", " t0 = millis();\n", " state = APAGADO;\n", " }\n", " break;\n", " }\n", "}\n", "```\n", "\n", "---\n", "\n", "## Exemplo 2 — Máquina de Estado Temporal (Protocolo)\n", "\n", "Além de FSMs que descrevem **sequências de estados físicos**, também podemos ter máquinas de estado que implementam **protocolos temporais**.\n", "\n", "**Exemplo:** criar uma **rampa de valores PWM** para gerar uma forma de onda triangular (útil em ensaios de calibração de motores).\n", "\n", "```cpp\n", "#define MOTOR_PIN 5\n", "int pwmValue = 0;\n", "int step = 5;\n", "\n", "void loop() {\n", " static unsigned long t0 = millis();\n", " unsigned long T = 50; // passo de 50 ms\n", "\n", " if (millis() - t0 > T) {\n", " pwmValue += step;\n", " if (pwmValue >= 255 || pwmValue <= 0) step = -step; \n", " analogWrite(MOTOR_PIN, pwmValue);\n", " t0 = millis();\n", " }\n", "}\n", "```\n", "\n", "Este tipo de FSM é útil para **ensaios automáticos** (ex.: rampa ou senoide) sem intervenção do utilizador.\n", "\n", "---\n", "\n", "## Exemplo 3 — FSM baseada em Interação do Utilizador\n", "\n", "Outra FSM típica responde a **eventos externos**, como o pressionar de um botão.\n", "\n", "```cpp\n", "#define BUTTON_PIN 7\n", "#define LED_PIN 8\n", "\n", "void setup() {\n", " pinMode(BUTTON_PIN, INPUT_PULLUP);\n", " pinMode(LED_PIN, OUTPUT);\n", "}\n", "\n", "void loop() {\n", " static int state = 0;\n", " static int lastButton = HIGH;\n", " int button = digitalRead(BUTTON_PIN);\n", "\n", " if (lastButton == HIGH && button == LOW) { // deteta transição\n", " state = !state;\n", " digitalWrite(LED_PIN, state);\n", " }\n", " lastButton = button;\n", "}\n", "```\n", "\n", " Esta FSM mostra a diferença entre um **protocolo temporal** (exemplo anterior) e um **protocolo baseado em eventos externos**.\n", "\n", "---\n", "\n", "## Esqueleto para o Aeropêndulo\n", "\n", "Segue uma estrutura modular que poderá ser usada como ponto de partida:\n", "\n", "```cpp\n", "void setup() {\n", " initSensor();\n", " initMotor();\n", " initControl();\n", "}\n", "\n", "void loop() {\n", " readSensor();\n", " computeControl();\n", " commandMotor();\n", " logData();\n", "}\n", "```\n", "\n", "Cada função pode ser implementada como uma **máquina de estado própria**, permitindo testar e substituir módulos sem afetar os restantes.\n", "\n", "---\n", "\n", "## Interrupções no Arduino\n", "\n", "O Arduino permite associar funções a **interrupções de hardware**, que são executadas automaticamente quando ocorre um evento (ex.: transição num pino digital, overflow de um timer).\n", "\n", "### Exemplo: Contagem de Pulsos (Encoder Simples)\n", "\n", "```cpp\n", "#define ENCODER_PIN 2\n", "volatile long counter = 0;\n", "\n", "void ISR_encoder() {\n", " counter++;\n", "}\n", "\n", "void setup() {\n", " attachInterrupt(digitalPinToInterrupt(ENCODER_PIN), ISR_encoder, RISING);\n", " Serial.begin(115200);\n", "}\n", "\n", "void loop() {\n", " Serial.println(counter);\n", " delay(500);\n", "}\n", "```\n", "\n", " Para **encoders em quadratura**, usam-se duas interrupções (canais A e B), permitindo detetar também o sentido de rotação.\n", "\n", "---\n", "\n" ] } ], "metadata": { "language_info": { "name": "python" } }, "nbformat": 4, "nbformat_minor": 5 }