Arquivo de tag esp32

Ricardo Jorge porRicardo Jorge

PROGMEM e os microcontroladores AVR

Neste artigo sobre PROGMEM e os microcontroladores AVR, será abordado o uso de PROGMEM, que é um grande aliado quando necessitamos melhor utilizar a memória RAM de nossos microcontroladores usados em diversos projetos recreativos, IoT, Indústria 4.0 e muito mais.

É importante lembrar que arduino é uma das mais conhecidas e utilizadas plataformas de desenvolvimento / prototipagem de hardware, fazendo dele um excelente representante dos microcontroladores AVR.

Existem outros artigos em nosso Blog falando sobre arduino e alguns de seus usos :

O que é PROGMEN?

A palavra-chave PROGMEM é um modificador de variável, que informa ao compilador para “manter esta variável na memória flash”, ao invés de carregá-la na SRAM.

O PROGMEM é útil para placas arduino que têm SRAM limitada, mas muitos usuários do arduino e até mesmo alguns desenvolvedores de bibliotecas não o usam.

Com certeza, se você estiver desenvolvendo algum sistema IoT ou sensores mais complexos com display LCD, mais cedo ou mais tarde, notará o uso da SRAM em seu projeto.

E logo fará a seguinte pergunta: Porque um sketch de 100 linhas usou grande parte dos preciosos 2.048 bytes de SRAM do arduino Uno?

Arquitetura Harvard versus Von Neumann

Antes de falarmos sobre o que é PROGMEM e o que ele faz, precisamos entender duas arquiteturas básicas no projeto de microprocessadores.

Primeiro precisamos entender que para um programa ser executado em seu computador pessoal (Mac, Windows ou Linux), ele precisará estar armazenado em algum tipo de mídia, como o disco rígido por exemplo.

E que antes que este programa entre em execução, ele será copiado do disco rígido para a memória RAM.

Após o programa ser carregado na memória RAM e entrar em execução, poderá declarar variáveis ​​e estruturas de dados que usarão ainda mais RAM.

Quando você termina de usar o programa, alguns dos dados talvez sejam salvos no disco rígido, mas toda a cópia do programa e de suas variáveis que estavam na RAM, serão liberadas e assim a memória ficará livre para o próximo programa a ser usado.

Considerando a arquitetura de um microprocessador de computador, essa abordagem é denominada de arquitetura de Von Neumann, onde o código e os dados existem no mesmo espaço de endereços na RAM.

A maioria das placas Arduíno usa microcontroladores baseados na arquitetura AVR.

Muitos AVRs têm quantidade limitada de RAM estática (SRAM), mas podem ter mais espaço disponível na memória Flash.

Por exemplo, o arduino Uno tem SRAM de apenas 2.048 bytes e 32.728 bytes de memória Flash.

O AVR é ​​um processador de arquitetura Harvard, amplamente utilizado para projetos de microcontroladores (MCU), em que a memória do programa é separada da memória de dados.

Para MCUs com arquitetura Hardvard, o programa é executado diretamente da memória de programa (memória Flash), mas todas as variáveis ​​e dados são carregados na SRAM.

Muitas das variáveis, como as mensagens a serem exibidas, não precisam ser carregadas na SRAM porque embora sejam definidas como uma variável do tipo string, o conteúdo desta string nunca mudará.

O problema é agravado pelo fato de que a maioria das linguagens de programação, C e C++, não foram projetadas para arquiteturas Harvard, mas sim, para arquitetura Von Neumann como seu computador pessoal, onde código e dados existem no mesmo espaço de endereço.

Através do PROGMEM você pode otimizar o uso da memória RAM em seus projetos.

Arquitetura Harvard pode significar coisas diferentes

O termo “arquitetura Harvard” pode significar coisas diferentes para diferentes processadores ou MCUs: tome os chips ARM como exemplo, eles têm arquitetura de “barramento” Harvard, o que significa que os acessos de código e dados podem acontecer ao mesmo tempo.

No entanto, o espaço de memória é unificado, o que significa que tanto a instrução quanto os dados compartilham o mesmo espaço de memória.

Isso é diferente da arquitetura de memória Harvard usada em MCU baseado em AVR ou outros MCUs de 8 bits, como 8051, Pic, etc, que têm espaços de memória separados para código e dados.

A arquitetura Harvard também pode ser usada para especificar designs de cache.

O cache de nível 1 em processadores ARM são normalmente Harvard, ou seja, cache de código e dados estão separados.

Armazenando dados na área de código

Isso significa que qualquer compilador para um processador de arquitetura Harvard, como o AVR, deve usar outros meios para operar com espaços de endereço separados.

O arduino usa uma variação do compilador GCC para compilar o código em códigos AVR.

O atributo PROGMEM que você vê no arduino veio do avr-libc, que faz parte do conjunto de ferramentas AVR.

A biblioteca avr-libc fornece uma macro simples denominada PROGMEM que é definida como um atributo para dizer ao compilador GCC para fazer algo especial sobre as variáveis ​​que têm o atributo PROGMEM.

A macro PROGMEM é definida no arquivo de cabeçalho do sistema e foi compilada junto com o arduino Core e, portanto, disponível para ser usada por todos os usuários do arduino.

Resumo

Em resumo, as macros e funções usadas para recuperar dados da Área de Código “consomem” código adicional para carregar os dados que estão nesta área.

Isso aumenta um pouco o tamanho do código na memória Flash e usa ciclos adicionais que aumentam um pouco o tempo de execução do programa.

De forma geral, considerando o pouco espaço de SRAM existente no Arduíno Uno (2kB SRAM) ou ATtiny85 (512 bytes SRAM), o benefício de usar PROGMEM freqüentemente supera o aumento no tempo de execução e o uso adicional da memória Flash.


Este artigo foi baseado nesta excelente postagem.


Image by Tiki Shabudin from Pixabay
Ricardo Jorge porRicardo Jorge

Função switch e a máquina de estado – state machine

A função switch, associada a máquina de estado ( state machine ), simplifica o código e facilita a manutenção, substituindo os vários “IF” aninhados, também conhecido como cascata de “IF”.

Não raro durante o desenvolvimento de um código, é necessário tomar decisões sobre vários eventos para que o fluxo prossiga na direção correta.

A máquina de estado também é conhecida como :

  • finite-state machine (FSM)
  • finite-state automaton (FSA)
  • autômato finito

Porque utilizar a máquina de estado?

Implementar código usando uma máquina de estado é uma técnica de design extremamente útil para resolver problemas complexos de engenharia.

As máquinas de estado dividem o projeto em uma série de etapas, ou o que é chamado de estados no jargão da máquina de estado.

Cada estado executa alguma tarefa estritamente definida.

Os eventos, por outro lado, são os estímulos que fazem com que a máquina de estado se mova, ou transite, entre estados.

Como a máquina de estado opera?

Cada máquina de estado tem o conceito de “estado atual”.

Este é o estado que a máquina de estado ocupa naquele momento.

Em qualquer momento, a máquina de estado pode estar em apenas um único estado.

Cada instância de um estado particular da máquina de estado, pode redefinir o estado inicial, ou o próximo estado.

Entretanto, o estado inicial não é executado imediatamente pela máquina de estado, quando o programa for iniciado.

Somente após receber um evento, a máquina de estado executa uma função que estava associada ao evento.

Desta forma, as várias etapas, ou estados, são executados quando cada evento é recebido e avaliado pela máquina de estado.

Devido a forma de operar da função switch, ela é perfeita para navegação entre os estados de uma máquina de estado.

Imagine criar uma máquina de estado, utilizando “IF” !

Em relação ao uso de “IF”, as principais vantagens da função switch são :

  • Código legível
  • Facilidade de manutenção
  • Facilidade de alteração : inclusão / remoção de opções ( estados )
  • Rapidez na seleção do trecho de código a ser executado

Função switch e a máquina de estado

Abaixo temos um exemplo real da aplicação da função switch usada para determinar a frequência da rede AC.

Posteriormente este código será comentado com mais detalhes, no artigo referente ao Monitor AC.

//
// Calculate frequency
//

  if(freqEnabled)
  {
    freqSampleVAC = sampleVAC - 512;
    switch(freqSM) {
      case 1:
        if(freqSampleVAC < 0) {              // wait for zero to start counting cycles
          freqSM = 2;
        }
      break;
      case 2:
        if(freqSampleVAC >= 0)               // wait for positive cycle
        {
          freqStartTime = micros(); 
          freqSM = 3;
        }
      break;
      case 3:
        if(freqSampleVAC < 0 )               // wait for zero crossing
        {
          freqSM = 4;
        }  
      break;
      case 4:
        if(freqSampleVAC >=0 )                // one cycle is completed
        {
          freqSample++;                   // count number of cycles and wait for another one
          freqSM = 3;
        }
      break;
    }
  
        if(freqSample == ACFreq)          
        {
            acFrequency = 1000000 / ((float)(micros() - freqStartTime) / freqSample);
            freqSample = 0;
            freqSM = 1;
            freqEnabled = false;           // now frequency info can be used
            freq_activity = !freq_activity;
        }
    }


Referência :

Finite-state machine

State Machine Design in C

Artigos relacionados :

arduino – como melhorar a precisão da entrada analógica

Linguagem C dicas sobre programação

IoT – protocolo MQTT – introdução



Image by Arek Socha from Pixabay