Conhecendo o co-processador ULP (Ultra Low Power) do ESP32

O ESP32, SoC da Espressif, além de todo potencial já conhecido, conta com um terceiro processador, desconhecido do público. Conheça este terceiro processador, chamado de ULP (Ultra Low Power), feito especificamente para operação em Low Power, já que o consumo é de aproximadamente 150 uA.
Este post faz parte da série Co-processador Ultra Low Power do ESP32. Leia também os outros posts da série:

O ESP32, SoC da Espressif, além de todo potencial que é mostrado pelos mais diversos autores, conta com um terceiro processador, que ainda não foi dito aqui e em muitos lugares. Este terceiro processador é chamado de ULP (Ultra Low Power), feito especificamente para operação em Low Power, já que o consumo é de aproximadamente 150 uA, ou onde precisamos de co-processador para efetuar algum processamento paralelo ao sistema principal, como ler estados de pinos (digitais e analógicos), efetuar operações aritméticas/lógicas e até comunicações com outros sistemas embarcados enquanto o sistema principal faz algum processamento pesado ou de tempo crítico. O ULP é programado no ambiente de desenvolvimento chamado ESP-IDF, que é o local padrão de desenvolvimento do ESP32 e conta com todas ferramentas e features disponíveis para esse microcontrolador.

Por que e quando devo utilizar o ULP?

O ULP é indicado para operações e projetos Low Power ou ajudar o sistema principal em alguma tarefa (co-processamento). Vamos justificar estes 2 usos básicos:

  • Low Power: Normalmente em dispositivos portáteis, o poder de processamento é baixo ou depende de algum evento externo para que ocorra alguma ação, por exemplo um sensor chegar em um valor específico. Por conta disso, não é indicado o uso de todo o potencial do microcontrolador, aí entramos com os métodos de economia do microcontrolador (Sleeps).

O ULP entraria em ação neste caso para, por exemplo, fazer Polling do sensor, já que seu consumo (150 uA) é extremamente mais baixo que o sistema principal (30-50 mA). Quando o ULP verificar que o sensor gerou um evento necessário para a ação do sistema, acordará o sistema principal para que seja feito o serviço pesado, como envio de dados ao banco de dados.

  • Co-processamento: Imagine que seu microcontrolador está trabalhando quase no seu limite. Por exemplo, fazendo leitura de dezenas de sensores e controlando diversos atuadores; isso tudo sem que haja perda de sincronismo por conta de um passo longo a ser realizado para tomada de decisão, como uma operação matemática complexa ou tratamento dos sensores e atuadores. Com esse cenário, é comum adicionar outros microcontroladores para ajudar a efetuar algumas tarefas específicas e livrar o sistema principal para focar na tarefa crítica.

O ULP entraria nesse cenário justamente efetuando alguma dessas 3 ações. Podemos atribuí-lo tanto a leitura dos sensores quanto o controle dos atuadores e até as contas matemáticas para tomada de decisões. Ele seria visto como um outro microcontrolador do sistema, mas este “mora“ dentro do próprio ESP32, o que ajuda extremamente na velocidade de processamento e evita comunicações lentas entre sistemas separados. Poderíamos deixar o controle dos atuadores por conta total do ULP, assim livramos o sistema principal dessa tarefa e deixariamos a leitura dos sensores melhores, podendo-se adicionar um Polling mais profundo.

Faremos esses 2 projetos de forma simples, separadamente, para mostrar os conceitos de aplicação do incrível ULP:

  • Low Power: Deixaremos o microcontrolador em Deep Sleep para economia de energia, enquanto o ULP ficará lendo um sensor analógico. Quando for detectado o nível de tensão definido, efetuará alguma ação como acordar o microcontrolador para uma tarefa pesada ou algo do tipo;
  • Co-processamento: Faremos alguma tarefa pesada de tempo crítico com o sistema principal em que qualquer desvio de processamento prejudicará essa tarefa designada. O ULP ficará lendo sensores para detectar se há alguma mudança que precise ser feita na tarefa do sistema principal e, assim, livramos o sistema principal de fazer a checagem de sensores, visto que iria interferir no tempo de processamento e atrapalhar o Flow code.

Não será ensinado aqui como instalar a ESP-IDF + ULP, entretanto nos links abaixo há todas as instruções para instalação da ESP-IDF e do ULP na IDF.

Instalação da ESP-IDF

http://esp-idf.readthedocs.io/en/latest/get-started/index.html

Instalação do ULP na IDF

http://esp-idf.readthedocs.io/en/latest/api-guides/ulp.html

Características do ULP

O ULP pode ser pensado como um microcontrolador dentro de outro. Há algumas restrições de acesso às memórias e periféricos, mas vamos adotá-lo como um microcontrolador independente dentro do ESP32 para facilitar a didática. Ele é focado em Low Power e, por causa disso, seu consumo é extremamente baixo. Mesmo sabendo desse foco, podemos utilizar para o que bem entendermos, como no co-processamento.

  • Consumo máximo (100% duty cycle): 150 uA;
  • Clock: 8,5 MHz +- 7%;
  • Memória (RTC_SLOW_MEM): 8 KB;
  • 4 Registradores de 16 bits para uso geral (R0-R3);
  • 1 Registrador de 8 bits para contagens e loops (STAGE_CNT);
  • 26 Mnemônicos.

Aqui me cabe fazer algumas observações importantes para que não haja confusões na hora de você testar na prática.

  • O consumo máximo é obtido quando o ULP fica 100% do tempo ligado, entretanto, é comum de utilizá-lo como se fosse um LED piscando com PWM, por isso foi dito com 100% duty cycle. O método utilizado para baixar ainda mais seu consumo é criar paradigmas para que seja feito algum processamento como ler um sensor, voltar a dormir e acordar algum tempo predefinido depois para ler novamente o sensor ou efetuar sua tarefa.
  • O clock ainda é uma variável para muitos, já que foi dito nos datasheets que seu clock é de 8 MHz, entretanto isso não é uma verdade absoluta. O clock do ULP está numa grande faixa de variação de chip para chip, que varia inclusive pela temperatura em que o microcontrolador se encontra. A faixa de variação do Clock é de 7,905 MHz até 9,095 MHz.

Por conta dessa grande variação de chip para chip e ainda a diferença pela temperatura, para nossa sorte, os desenvolvedores do ESP32 criaram uma função na IDF que retorna o clock aproximado e, com isso, conseguimos utilizar esse clock calculado para efetuar tarefas de tempo crítico ou comunicações seriais de alta frequência, onde o tempo é crucial. Ainda sim, essa função nem sempre retorna o mesmo valor, fazendo com que tenhamos que fazer alguma espécie de benchmark para cálculo real do clock, como algum PWM e osciloscópio, analisador lógico ou frequencímetro.

  • A memória dedicada do ULP é de 8 KB (RTC_SLOW_MEM), onde fica seu código e variáveis, entretanto, é óbvio que podemos comunicar-se com o sistema principal, já que essa memória é compartilhada entre os 3 processadores. Podemos fazer envio de variáveis para lá e também a obtenção delas, onde há uma imensa quantidade de memória disponível e, com isso, criar métodos para expandir a memória do ULP através da memória principal.

Podemos tanto acessar variáveis criadas no sistema principal (Main Core programado em C/C++) como também acessar as variáveis criadas no ULP (programado em Assembly) pelo sistema principal. Essa capacidade de comunicação entre os 2 sistemas permite uma incrível e gigantesca gama de aplicações.

  • Os Mnemônicos, ou Instruction set disponíveis para uso no ULP, estão disponíveis tanto no Datasheet quanto nesta página web.

Entendendo o funcionamento do ULP

Vamos começar com um fluxograma de como é o funcionamento do sistema inteiro até que o ULP entre em execução. O sistema principal deve definir (reservar) a memória de uso e também seu Entry Point antes que o ULP entre em execução, ou seja, ele é dependente do sistema principal para ser iniciado.

Fluxograma de boot do ULP.
Figura 1 – Fluxograma de boot do ULP.

Ainda podemos utilizá-lo (para uma economia de energia maior) similarmente a um LED com PWM. Isso ocorre com a junção de 3 itens:

  1. Timer do ULP: Responsável por acordá-lo com o tempo pré-definido. O período deste pode ser definido e alterado a qualquer momento, tanto pelo sistema principal quanto pelo próprio ULP. Após otTimer acordar o ULP, o periférico entra em uma espécie de “espera” e fica inativo até que o comando HALT seja executado pelo ULP, onde todo o processo é reiniciado e o timer volta a contar para acordar o ULP novamente.
  2. Execução do código: Após ser acordado, começará a execução normal de seu código.
  3. Mnemônico HALT: Responsável por fazê-lo dormir.

Vejamos um gráfico do funcionamento do método citado acima, que é bastante utilizado para operações e projetos de Low Power:

Ciclos de Sleep Wakeup do ULP
Figura 2 – Ciclos de Sleep <-> Wakeup do ULP.
  1. Timer habilitado. Como pode ser visto, o Sleep cycles é de 500, logo, após 500 ciclos do Timer, o ULP acordará automaticamente;
  2. 500 ciclos expirado e ULP entra em execução do seu código;
  3. Ao fim de seu código, o comando HALT é executado, colocando o ULP para dormir novamente. O Timer também é reativado e retorna a contagem dos ciclos;
  4. Sleep cycles mudado para 1100, a frequência de execução do código será menor que antes;
  5. Timer desabilitado. Caso você execute o HALT após o Timer estar desabilitado, o ULP não acordará novamente.

Já para projetos onde é usado para ajudar no processamento principal, normalmente, não é utilizado essa técnica para baixar o consumo. Então nós iremos apenas ativar o ULP e mantê-lo funcionando o tempo todo ou desejado.

No próximo post desta série sobre ULP vamos começar a programá-lo focando em operações e projetos de Low Power, deixaremos o sistema principal em Deep Sleep enquanto o ULP lê um sensor analógico para efetuar alguma ação, como acordar o ESP32 do Deep Sleep. Os projetos feitos serão simples apenas para demonstração básica do funcionamento e não dificultar o entendimento geral.

Saiba mais sobre o ESP32 e economia de energia

ESP32: o sucessor do ESP8266

Estratégias de programação para portáteis

Aplicando conceitos de economia em microcontroladores

Outros artigos da série

Usando o ULP do ESP32 em projetos Low Power >>

Engenheiro da Computação pela USC, pretende sempre se aprimorar e fazer a diferença nesta imensa área da tecnologia. Apaixonado por sistemas embarcados IoT, processamento de imagem, linux, astronomia e integração da computação nos mais diversos fins práticos e didáticos.

Notificações
Notificar
guest
0 Comentários
Inline Feedbacks
View all comments

WEBINAR

Imagens de Ultrassom: Princípios e Aplicações

DATA: 26/10 ÀS 19:30 H