ÍNDICE DE CONTEÚDO
Introdução
Atualmente, a maior parte dos sistemas embarcados e placas de desenvolvimento suportam a programação através de linguagens estruturadas, como C ou Python, ou mesmo linguagens simbólicas, como Assembly (os mais experientes vão se recordar ainda do BASIC Stamp ou do Pascal em alguns microcontroladores).
No entanto, aplicações corporativas, de bancos de dados, ou interfaces gráficas em sistemas operacionais e smartphones geralmente são escritas usando paradigmas de mais alto nível de abstração, como a Programação Orientada a Objetos (POO), através de linguagens como Java, Kotlin, Swift, C# ou C++, dentre outras.
Este artigo tem por objetivo descrever a aplicação da Programação Orientada a Objetos (POO) no desenvolvimento de projetos de dispositivos embarcados, através de programação com linguagem C++, além de comparar as vantagens e desvantagens da abordagem em relação à programação estruturada clássica com linguagem C. Ainda, é apresentado um projeto exemplo para a Espressif ESP32, usando o kit de desenvolvimento ESP-IDF.
Paradigma da Programação Orientada a Objetos
As linguagens de programação podem ser classificadas segundo seu paradigma, ou seja, sua base de conceito.
Seminário Linux Embarcado 2024: Evento Presencial em São Paulo
Participe do Seminário Linux Embarcado 2024 em São Paulo. Conhecimento técnico, palestras, workshops e oportunidade de networking com profissionais experientes.
Dois dos mais populares paradigmas de programação são: procedural, que se baseia em blocos funcionais de código, reutilizáveis, de responsabilidades definidas, das quais se espera um processamento de parâmetros (ou variáveis), e possivelmente a obtenção de um retorno desse processamento (resultado); e orientada a objetos, baseada na interação entre elementos distintos, que encapsulam seus próprios dados (atributos ou propriedades) e comportamentos (métodos).
A maioria das linguagens de programação orientadas a objetos (POO) são baseadas no conceito de instâncias de classe. Classes são formas de definir quais as propriedades e seus tipos, e quais comportamentos (métodos) estarão presentes em todos os objetos instanciados dessa mesma classe.
No paradigma procedural, cada procedimento (função) recebe dados como parâmetros, processa e pode retornar dados ao procedimento chamador. É responsabilidade do chamador (e da rotina global) gerenciar a guarda dos dados entre as chamadas de procedimento, usando variáveis (locais e globais).
Ao invés disso, na POO, cada classe delimita a responsabilidade de seus objetos instanciados, e cada objeto possui seu próprio conjunto de dados num espaço de memória particular. A interação planejada entre objetos, com a troca definida de dados entre eles é o que compõe o sistema completo.
A programação orientada a objetos surgiu como uma evolução na forma de organizar e estruturar o código, facilitando a modelagem de sistemas complexos. Alguns dos principais conceitos da POO incluem:
- Encapsulamento: Este princípio se refere à capacidade de esconder os detalhes internos de um objeto e expor apenas o que é necessário para o uso desse objeto. Isso é alcançado através de modificadores de acesso (como público, privado e protegido), que controlam a visibilidade dos dados e métodos de um objeto.
- Abstração: Este conceito envolve a simplificação de objetos complexos, expondo apenas os detalhes essenciais e ocultando a complexidade desnecessária. A abstração facilita a compreensão e a manutenção do código, permitindo que os desenvolvedores se concentrem nos aspectos mais importantes do problema a ser resolvido.
- Herança: Permite que uma classe (subclasse) herde propriedades e métodos de outra classe (superclasse). Isso promove a reutilização de código e estabelece uma hierarquia entre classes. A herança facilita a criação de novas funcionalidades com base em implementações existentes.
- Polimorfismo: Refere-se à capacidade de diferentes classes serem tratadas como instâncias de uma mesma classe através de interfaces ou classes base comuns. O polimorfismo permite que métodos sobrecarregados sejam chamados de forma genérica, melhorando a flexibilidade e a extensibilidade do código.
Linguagens populares que suportam POO incluem Java, Kotlin, C++, Python, e C#, por exemplo. Cada uma dessas linguagens implementa os princípios da POO de maneira ligeiramente diferente, mas todas compartilham os conceitos fundamentais descritos acima.
A adoção da POO trouxe diversos benefícios, como a modularidade, que permite o desenvolvimento de componentes independentes e reutilizáveis; a facilidade de manutenção e evolução do software, pois alterações em uma classe não afetam diretamente outras partes do sistema; e a possibilidade de trabalhar com abstrações mais próximas do mundo real, facilitando a comunicação entre desenvolvedores e stakeholders.
Programação Procedural versus Orientada a Objetos
Muitos autores consideram o paradigma de programação orientada a objetos vantajoso em relação à programação procedural, pelos seguintes motivos:
- O encapsulamento torna o software mais confiável (ao alterar uma parte nenhuma outra é afetada);
- O desenvolvimento é oportuno (ou não-sequencial), já que ao dividir o todo em partes, várias delas podem ser desenvolvidas em paralelo;
- O software é manutenível, pois há menos código repetido, e a modificação em uma parte pode beneficiar todas as partes que a utilizam;
- O software é extensível (é possível crescer para continuar útil, sem ser estático, e sem afetar o código existente);
- Os pedaços, subsistemas ou todo o sistema são reutilizáveis;
- O software é natural, pois é projetado com base na funcionalidade, e menos com os detalhes de implementação.
No entanto, as principais desvantagens apontadas são:
- Baixo desempenho, se comparado a um sistema programado completamente em paradigma procedural, ou mesmo diretamente em Assembly. Isso acontece devido à complexidade do modelo, que traz representações na forma de classes, e possui mais desvios do que um código procedural. Porém, no momento em que estamos tecnologicamente (dispositivos com alta integração, com elevado poder de processamento e boa quantidade de memória), essa suposta execução mais lenta não seria percebida pelo desenvolvedor e nem pelo usuário do dispositivo – a menos que estejamos falando de microcontroladores com pequenas quantidades de memória RAM, processamento lento e/ou em sistemas de missão crítica – onde até o Assembly se torna mais interessante.
- Maior uso de memória, se comparado a um sistema programado completamente em paradigma procedural, ou mesmo diretamente em Assembly. A representação de dados e procedimentos através de classes e suas instâncias implica em uma separação de responsabilidades, e consequentemente, de áreas de memória. Um sistema escrito em paradigma procedural (ou Assembly) terá um aspecto mais sequencial e centralizador, onde regiões de memória para diferentes finalidades acabam se juntando. Da mesma maneira que descrito no item anterior, nos dispositivos mais modernos, onde a quantidade de memória não é tão crítica assim, essa diferença não é percebida, e é compensada pelas demais vantagens de se utilizar POO no desenvolvimento (reuso, manutenibilidade, encapsulamento, etc.).
Apesar das desvantagens apresentadas, a programação orientada a objetos traz outros pontos que acabam sendo mais interessantes no contexto de aplicações modernas. Como o desempenho dos sistemas não é mais uma das grandes preocupações críticas na maioria das aplicações (devido ao poder de processamento e às boas quantidades de memória dos dispositivos atualmente disponíveis), a programação orientada a objetos se tornou muito difundida.
Além disso, deve-se observar que a comparação entre os dois paradigmas é possível – e significativamente mais justa – apenas entre duas linguagens compiladas nativas de alto desempenho (como C e C++, por exemplo). Linguagens interpretadas como Python ou JavaScript terão desempenho muito inferior, tanto em velocidade de execução, como em uso de memória (independente do paradigma escolhido). Já linguagens compiladas para execução em máquina virtual (como o caso do Java, Kotlin ou C#) terão desempenho intermediário apenas, com bastante uso de memória ao executar (pois é necessário subir a máquina virtual para interpretação, por exemplo a JVM no caso de Java/Kotlin).
Principais diferenças entre C e C++
As linguagens C e C++ são duas das linguagens de programação mais influentes e amplamente utilizadas no desenvolvimento de software. Embora C++ tenha sido inicialmente derivada de C, ela incorpora uma série de melhorias e funcionalidades adicionais que a diferenciam significativamente de sua predecessora. Esta seção analisa as principais diferenças entre C e C++.
Paradigma de Programação
C é uma linguagem de programação procedural, o que significa que se baseia em chamadas de funções e estruturas de controle para o fluxo do programa. O código é organizado em procedimentos ou funções que operam em dados.
C++ é uma linguagem de programação multiparadigma, mas é mais conhecida por seu suporte à programação orientada a objetos (POO). Isso permite a modelagem de problemas como coleções de objetos interativos, facilitando a gestão de sistemas complexos e a reutilização de código.
Tipagem e Segurança de Tipos
C oferece uma tipagem mais flexível e menos rígida, mas isso pode levar a problemas de segurança de tipos, como erros de conversão implícita de tipos.
C++ introduz um sistema de tipos mais robusto e seguro, incluindo templates e a capacidade de sobrecarga de operadores e funções, permitindo uma maior flexibilidade e segurança no uso de tipos.
Gestão de Memória
C utiliza funções como malloc() e free() para alocação e desalocação dinâmica de memória. A gestão de memória é manual e pode ser propensa a erros como vazamentos de memória e ponteiros pendentes.
C++ introduz operadores new e delete para alocação e desalocação de memória, além de suporte a construtores e destrutores que facilitam a gestão de recursos e melhoram a segurança e eficiência da memória.
Bibliotecas Padrão
A biblioteca padrão de C (C Standard Library) é limitada e oferece funcionalidades básicas para manipulação de strings, entrada/saída, e gestão de memória.
A biblioteca padrão de C++ (Standard Template Library, STL) é muito mais rica e inclui suporte a coleções genéricas, algoritmos, iteradores e outras utilidades que facilitam a programação genérica e orientada a objetos.
Suporte a Classes e Objetos
C não possui suporte nativo a POO. Qualquer tentativa de simular POO em C geralmente resulta em um código mais complexo e menos legível (uso de structs e ponteiros, por exemplo).
C++ introduz o conceito de classes e objetos, permitindo o encapsulamento de dados e funções, herança e polimorfismo. Isso facilita a modelagem de sistemas complexos e a reutilização de código.
Controle de Fluxo e Estruturas de Dados
C oferece estruturas de controle básicas, como if, for, while, e estruturas de dados como arrays e structs, mas sem suporte a encapsulamento e herança.
Além das estruturas de controle herdadas de C, o C++ oferece suporte a classes e objetos, que permitem a criação de estruturas de dados complexas com comportamentos associados. Além disso, C++ também oferece suporte a tratamento de exceções com try-catch, o que pode simplificar a manipulação de situações de erro.
Afinal, C ou C++?
Embora C e C++ compartilhem muitas semelhanças sintáticas e conceituais, as diferenças em seus paradigmas de programação, tipagem, gestão de memória, bibliotecas padrão, e suporte a classes e objetos tornam C++ uma linguagem mais poderosa e flexível para o desenvolvimento de sistemas complexos. Por outro lado, a linguagem C ainda continua a ser amplamente utilizada em aplicações de baixo nível e sistemas com pouca memória e baixa capacidade de processamento, devido a sua simplicidade e eficiência.
Programação Orientada a Objetos (C++) em Sistemas Embarcados
A programação orientada a objetos (POO) em C++ tem se mostrado uma abordagem poderosa e eficiente para o desenvolvimento de sistemas embarcados. Sistemas embarcados são dispositivos que combinam hardware e software para realizar funções específicas dentro de um sistema maior. Esses sistemas variam desde pequenos dispositivos de controle, como microcontroladores em eletrodomésticos, até sistemas mais complexos encontrados em automóveis e equipamentos médicos.
Benefícios da POO em C++ para Sistemas Embarcados
A utilização de POO (em específico com linguagem C++) pode trazer benefícios ao programar sistemas embarcados. A seguir estão descritos alguns deles.
- Modularidade e reutilização de código: A POO permite que o código seja organizado em classes e objetos, promovendo a modularidade. Isso facilita a reutilização de componentes de software em diferentes partes do sistema ou em outros projetos, reduzindo o tempo de desenvolvimento e os custos.
- Encapsulamento: Em sistemas embarcados, onde a segurança e a confiabilidade são cruciais, o encapsulamento ajuda a proteger os dados internos dos objetos. Isso reduz o risco de erros causados por acesso indevido ou modificações não autorizadas.
- Manutenção e evolução: A capacidade de herança e polimorfismo permite que novos recursos sejam adicionados a um sistema existente sem a necessidade de alterar significativamente o código existente. Isso é especialmente útil em sistemas embarcados que precisam evoluir com o tempo, adicionando novas funcionalidades ou melhorando as existentes.
- Abstração de hardware: C++ permite a criação de classes que abstraem diretamente os componentes de hardware, como sensores, atuadores e interfaces de comunicação. Isso resulta em um código mais limpo e compreensível, facilitando o desenvolvimento e a depuração.
- Disponibilidade de frameworks ou bibliotecas C++: Algumas bibliotecas especializadas escritas em C++ (como o framework gráfico Qt), são disponibilizadas em determinadas plataformas de hardware (por exemplo, em alguns módulos Single Board Computer), o que facilita a criação de funcionalidades avançadas, como interfaces gráficas de usuário em displays LCD, por exemplo.
Desafios da POO em C++ para Sistemas Embarcados
Apesar dos benefícios, programar sistemas embarcados utilizando POO pode ser desafiador em alguns aspectos. A seguir são enumerados alguns desses principais desafios.
- Uso de recursos: Sistemas embarcados muitas vezes operam com recursos limitados, como memória e poder de processamento. A sobrecarga associada à POO, como a alocação dinâmica de memória e o uso de bibliotecas padrão, pode ser um problema. Desenvolvedores precisam ser cuidadosos ao utilizar POO para não comprometer a performance e eficiência do sistema.
- Tempo de execução: Em aplicações de tempo real, como controle de motores ou sistemas de navegação, a previsibilidade e a baixa latência são essenciais. O uso de POO pode introduzir alguma incerteza no tempo de execução devido a chamadas de métodos virtuais e outras funcionalidades dinâmicas.
- Complexidade: A abstração e a modularidade oferecidas pela POO podem, às vezes, levar a uma complexidade adicional no design e na depuração do sistema. É necessário um balanço cuidadoso entre a abstração e a simplicidade.
Estratégias para Implementação
A seguir são sugeridas algumas estratégias para auxiliar na programação de sistemas embarcados utilizando POO (em linguagem C++).
- Uso restrito de funcionalidades dinâmicas: Minimizar o uso de alocação dinâmica de memória (new e delete) e preferir a alocação estática ou em pilha, que são mais previsíveis e eficientes.
- Programação em tempo de compilação: Aproveitar templates e outras funcionalidades de metaprogramação de C++ para realizar operações em tempo de compilação, reduzindo a sobrecarga em tempo de execução.
- Bibliotecas otimizadas: Utilizar bibliotecas específicas para sistemas embarcados que são otimizadas para uso em ambientes com recursos limitados, como a STL reduzida para sistemas embarcados.
- Design orientado a objetos eficiente: Adotar práticas de design eficientes, como o uso de classes base e interfaces bem definidas, e evitar a herança múltipla complexa.
Exemplos de Aplicações
A seguir são listadas algumas das possíveis aplicações para sistemas embarcados programados com o uso de POO/C++.
- Automóveis: Sistemas de controle de motores, sistemas de infotainment (informação e entretenimento conjugados) e unidades de controle eletrônicas (ECUs) frequentemente utilizam C++ para gerenciar a complexidade e a interação entre diversos subsistemas.
- Dispositivos médicos: Equipamentos como monitores cardíacos e bombas de insulina se beneficiam da modularidade e da segurança oferecidas pela POO, permitindo atualizações de software seguras e eficientes.
- Eletrônicos de consumo: Dispositivos como smart TVs, consoles de jogos e sistemas de áudio utilizam C++ para implementar interfaces de usuário e funcionalidades avançadas de controle.
- Indústria aeroespacial: Sistemas de controle de voo, navegação e monitoramento, que requerem alta confiabilidade e tempo de resposta rápido, utilizam POO em C++ para gerenciar a complexidade e a interação entre diferentes módulos de software.
- Automação industrial: Máquinas e sistemas de controle em linhas de produção se beneficiam da POO em C++ para desenvolver software modular e flexível, que pode ser facilmente atualizado e mantido.
Considerações sobre uso de POO/C++ em Sistemas Embarcados
A adoção da programação orientada a objetos em C++ para sistemas embarcados oferece uma série de benefícios significativos, incluindo modularidade, encapsulamento, facilidade de manutenção e abstração de hardware. No entanto, é essencial abordar os desafios inerentes, como o uso de recursos limitados e a complexidade adicional, para garantir que o sistema final seja eficiente e confiável.
Implementação Prática de Sistema Embarcado usando C++
Nesta seção será abordado um exemplo de implementação prática de sistema embarcado, utilizando POO e linguagem C++, aplicável para os módulos ESP32 da Espressif.
O que é o ESP32
O ESP32 é uma plataforma versátil e poderosa para desenvolvimento de sistemas embarcados, oferecendo conectividade Wi-Fi e Bluetooth em um único chip, desenvolvido pela empresa Espressif Systems. Com suporte para diversas linguagens de programação e frameworks, como ESP-IDF para C e C++, e NuttX para RTOS, o ESP32 é ideal para uma ampla gama de aplicações IoT. O suporte da Espressif e a comunidade ativa de desenvolvedores tornam o ESP32 uma excelente escolha para projetos embarcados, devido a sua versatilidade, conectividade, poder de processamento e baixo custo.
A Espressif Systems é uma empresa de semicondutores sediada em Xangai, China, conhecida por seus chips de comunicação sem fio. Além do ESP32, a empresa também ficou conhecida pelo ESP8266, um predecessor muito popular do ESP32.
Os módulos ESP32 são pacotes que contêm o chip ESP32, memória flash e outros componentes necessários para a operação, o que facilita o trabalho de desenvolvimento. Exemplos populares de módulos incluem o ESP-WROOM-32, ESP32-S2-WROOM, dentre outros. Esses módulos são também usados em uma ampla gama de dispositivos IoT, desde sistemas de automação residencial até dispositivos portáteis.
O coração dos módulos ESP32 é um chip da série ESP32, que inclui várias versões, como ESP32-D0, ESP32-D2, ESP32-S0, ESP32-S2, ESP32-C3, ESP32-C6 e assim por diante. Estes chips são baseados em um ou dois núcleos Tensilica Xtensa LX6 (alguns modelos são baseados em RISC-V), com frequências de operação na casa dos 240MHz (há modelos mais rápidos, outros mais econômicos). O ESP32 inclui uma variedade de periféricos, como ADCs, DACs, interfaces SPI, I2C, I2S, UARTs, PWM, temporizadores e sensores touch capacitivos, além das funcionalidades de Wi-Fi e Bluetooth, naturalmente.
O ESP32 é amplamente utilizado em projetos de Internet das Coisas (IoT) devido à sua capacidade de conectar-se a redes Wi-Fi e Bluetooth. Exemplos de aplicações incluem:
- Automação Residencial: Controle de iluminação, termostatos, câmeras de segurança, etc.
- Dispositivos Portáteis: Relógios inteligentes, rastreadores de fitness, etc.
- Sistemas Industriais: Monitoramento e controle de processos industriais.
- Wearables: Dispositivos vestíveis que monitoram atividades físicas e saúde.
Como Programar o ESP32
O ESP32 pode ser programado utilizando diversas ferramentas e linguagens de programação. Duas das opções mais comuns são a Arduino IDE (que utiliza a linguagem baseada em Wiring e os sketches Arduino) e o ESP-IDF.
ESP-IDF
O ESP-IDF (Espressif IoT Development Framework) é o framework oficial de desenvolvimento da Espressif para o ESP32. Ele oferece uma série de APIs e ferramentas para desenvolver aplicativos robustos para o ESP32. O ESP-IDF é escrito em C e oferece suporte extensivo para recursos do chip, incluindo Wi-Fi, Bluetooth e periféricos.
Para começar com o ESP-IDF:
- Instalação: O ESP-IDF é multiplataforma e pode ser instalado no Windows, macOS e Linux. A Espressif fornece um instalador que inclui todas as dependências necessárias.
- Configuração do Ambiente: Após a instalação, é necessário configurar o ambiente de desenvolvimento e o caminho do ESP-IDF.
- Exemplo de Código: O ESP-IDF vem com vários exemplos que ajudam a iniciar rapidamente, como projetos de conectividade Wi-Fi e controle de GPIO.
O ESP32 pode ser programado em C usando o ESP-IDF, que oferece uma API completa para acessar todos os recursos do microcontrolador. A linguagem C é ideal para desenvolvimento de baixo nível e permite um controle preciso sobre o hardware.
Além de C, o ESP32 pode ser programado em C++. O uso de C++ permite a aplicação de conceitos de programação orientada a objetos, que podem tornar o código mais modular e reutilizável. O ESP-IDF suporta C++ nativamente, permitindo que os desenvolvedores utilizem classes e outras funcionalidades avançadas da linguagem.
Programação com NuttX
NuttX é um sistema operacional de tempo real (RTOS) leve e altamente configurável que também pode ser usado com o ESP32. Ele é conhecido por sua compatibilidade com POSIX, o que facilita a portabilidade de aplicativos.
Com o NuttX, é possível programar o ESP32 em qualquer linguagem que suporte POSIX e tenha compilador para a plataforma alvo. Dentre as linguagens suportadas, é possível programar com C++ no NuttX.
Para usar C++ com NuttX no ESP32:
- Configuração do NuttX: Configurar NuttX para o ESP32 envolve a seleção dos drivers e módulos necessários.
- Desenvolvimento: Desenvolver aplicações em C++ no NuttX permite aproveitar as funcionalidades do RTOS, como threads, semáforos e filas, junto com a programação orientada a objetos.
- Compilação e Flashing: Compilar e carregar o firmware no ESP32 usando ferramentas como esptool.py.
Para maiores informações, é recomendável visitar a documentação do projeto NuttX.
Desenvolvimento de um Projeto em C++
Nesta seção será apresentado um exemplo de projeto em C++ usando o ESP32, com o ESP-IDF.
Como pré-requisito, é necessário configurar o ambiente de desenvolvimento do ESP-IDF, conforme a documentação oficial do ESP-IDF.
- Criar um novo projeto
Crie um novo diretório para o projeto e navegue até ele. Execute o comando abaixo para criar uma nova estrutura de projeto:
1 |
idf.py create-project <project-name> |
A estrutura básica do projeto ESP-IDF em C++ ficará assim:
1 2 3 4 5 6 7 8 |
my_project/ ├── CMakeLists.txt ├── components/ ├── main/ │ ├── CMakeLists.txt │ ├── main.cpp ├── Makefile └── sdkconfig |
- Editar os arquivos-fonte do projeto
No diretório main/, o arquivo CMakeLists.txt deve ter esta linha:
1 2 3 |
# CMakeLists.txt idf_component_register(SRCS "main.cpp" INCLUDE_DIRS ".") |
Edite o arquivo main.cpp, conforme código demonstrado abaixo, para criar um exemplo simples que inicializa o Wi-Fi em modo estação e se conecta a uma rede Wi-Fi:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
// main.cpp #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "esp_wifi.h" #include "nvs_flash.h" #include "esp_event.h" static const char *TAG = "wifi_station"; extern "C" void app_main(); class WiFi { public: WiFi(const char* ssid, const char* password) : ssid_(ssid), password_(password) {} void init() { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); wifi_config_t wifi_config = {}; strcpy((char *)wifi_config.sta.ssid, ssid_); strcpy((char *)wifi_config.sta.password, password_); ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); ESP_LOGI(TAG, "wifi_init_sta finished."); } void connect() { ESP_ERROR_CHECK(esp_wifi_connect()); ESP_LOGI(TAG, "Connecting to %s...", ssid_); } private: const char* ssid_; const char* password_; }; extern "C" void app_main() { ESP_LOGI(TAG, "ESP32 WiFi Station Example"); WiFi wifi("your_ssid", "your_password"); wifi.init(); wifi.connect(); while (true) { vTaskDelay(1000 / portTICK_PERIOD_MS); } } |
- Compilar o projeto e fazer o flash para o dispositivo
Para compilar e carregar o firmware no ESP32, execute os seguintes comandos no terminal:
1 2 3 |
idf.py build idf.py flash idf.py monitor |
Esses comandos irão compilar o código, carregar o firmware no ESP32 e abrir o monitor serial para observar os logs.
Este exemplo básico demonstra como usar C++ com o ESP-IDF para inicializar e conectar o Wi-Fi em um ESP32. Apesar de bastante simples (aqui foi criada apenas uma classe chamada WiFi que faz a conexão à rede), outras classes podem ser criadas para gerenciar funcionalidades específicas do sistema, implementar as regras de negócio e abstrair as partes de baixo nível de hardware, e ser instanciadas e reutilizadas conforme necessário. Desta forma, a modularidade e o reaproveitamento de código oferecidos pela programação orientada a objetos tornam o desenvolvimento mais gerenciável e escalável para projetos complexos.
Conclusão
A aplicação da programação orientada a objetos (POO) em sistemas embarcados, especialmente utilizando C++ se apresenta como uma abordagem vantajosa para o desenvolvimento de software embarcado moderno. Através da POO, é possível criar sistemas mais modulares, reutilizáveis e manuteníveis, características cruciais para projetos complexos e de longa duração.
O uso de POO permite a modelagem de sistemas através de classes e objetos, facilitando o encapsulamento de dados, a abstração e a implementação de funcionalidades específicas de maneira organizada. A adoção de POO para sistemas embarcados não só promove a reutilização de código através de herança e polimorfismo, mas também melhora a segurança e a robustez do software com o uso de templates, programação genérica e tratamento de exceções. Além disso, frameworks e bibliotecas consagradas que suportam POO fornecem uma base sólida para o desenvolvimento de sistemas embarcados com funcionalidades avançadas.
Embora existam desafios, como o perigo de aumentar o consumo de recursos em comparação com a programação procedural, os benefícios da POO como a clareza na modelagem de problemas e a facilidade de manutenção, superam as desvantagens em muitos cenários. Dessa forma, a POO, especialmente com o uso da linguagem C++, se estabelece como uma ferramenta poderosa para o desenvolvimento de software embarcado eficiente e escalável.
Referências
Booch, G. Object-Oriented Analysis and Design with Applications (3rd Edition). 2007. Addison-Wesley.
Bloch, J. Effective Java (3rd Edition). 2018. Addison-Wesley.
Embedded. Nuts to OOP!. 1999. Disponível em: https://www.embedded.com/nuts-to-oop.
Espressif Systems. ESP32 Series Datasheets. 2016. Disponível em: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf.
Espressif Systems. ESP-IDF Programming Guide. 2016. Disponível em: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/index.html.
Gamma, E., Helm, R., Johnson, R., & Vlissides, J. Design Patterns: Elements of Reusable Object-Oriented Software. 1994. Addison-Wesley.
Hunt, A., & Thomas, D. The Pragmatic Programmer: Your Journey to Mastery (20th Anniversary Edition). 2019. Addison-Wesley.
International Organization for Standardization. ISO/IEC 9899:2018: Information technology – Programming languages – C. Geneva, Switzerland. 2018. Disponível em: https://www.iso.org/standard/74528.html.
International Organization for Standardization. ISO/IEC 14882:2020: Programming languages – C++. Geneva, Switzerland. 2020. Disponível em: https://www.iso.org/standard/79358.html.
Josuttis, N. M. The C++ Standard Library: A Tutorial and Reference (2nd Edition). 2012. Addison-Wesley.
Kernighan, B. W., & Ritchie, D. M. The C Programming Language (2nd Edition). 1988. Prentice Hall.
Lippman, S. B., Lajoie, J., & Moo, B. E. C++ Primer (5th Edition). 2012. Addison-Wesley.
Martin, R. C. Clean Code: A Handbook of Agile Software Craftsmanship. 2008. Prentice Hall.
Meyers, S. Effective C++: 55 Specific Ways to Improve Your Programs and Designs (3rd Edition). 2005. Addison-Wesley.
NuttX Project. NuttX Documentation. 2020. Disponível em: https://nuttx.apache.org/docs/latest/.
Python Software Foundation. Python Official Site. 2001. Disponível em: https://www.python.org/.
Qt Group. Qt Framework. 1995. Disponível em: https://www.qt.io/product/framework.
Stackoverflow. Is object orientation bad for embedded systems, and why? [closed]. 2010. Disponível em: https://stackoverflow.com/questions/3274445/is-object-orientation-bad-for-embedded-systems-and-why.
Stroustrup, B. The C++ Programming Language (4th Edition). 2013. Addison-Wesley.
Toradex. Single Board Computers (SBC). 2003. Disponível em: https://www.toradex.com.
Vaughan-Nichols, S. J. IoT Development with the ESP32 (1st Edition). 2020. Apress.Imagem de Destaque: Gerada por IA.