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

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

https://portal.vidadesilicio.com.br/instalando-esp-idf-no-windows-esp32/

 

Instalação do ULP na IDF

 

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

https://portal.vidadesilicio.com.br/ultra-low-power-coprocessor-ulp-esp32/

 

 

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 >>
Este post faz da série Co-processador Ultra Low Power do ESP32. Leia também os outros posts da série:

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

José Morais
Estudante de Engenharia da Computação pela USC, pretende se aprimorar e fazer a diferença nesta imensa área da tecnologia. Apaixonado por IoT, sistemas embarcados, microcontroladores e integração da computação nos mais diversos fins práticos e didáticos.

Deixe um comentário

Seja o Primeiro a Comentar!

avatar
 
  Notificações  
Notificar