Como fazer com que a função tone respeite a duração específicada?

Fala pessoal, tudo bem?

Ainda no projeto inicial de um altímetro digital baseado no TTGO(ESP32) e BMP280, estou tentando implementar alguns alertas sonoros. Pra isso estou usando um buzzer no pin 2; 

Para gerar os tons, tentei seguir este exemplo:

https://www.pschatzmann.ch/home/2021/01/07/esp32-tone/

porém após implementado ao meu codigo inicial do altímetro, a função não está respeitando a duração específicada do ultimo tom.

 p. exemplo, quando ligado a ideia era que seguisse essa sequencia:

tone(1020, 200);
tone(8120, 200);
tone(4020, 400);

e então após o ultimo tom, voltasse ao silencio. Porém, em todo o codigo onde coloquei esses sons a saída trava no ultimo tom e não desliga mais.

Tentei usar a função noTone() porém também ficou com erro como "not declared in this scope" mesmo colocando como global noTone(2).

Alguem conseguiria me ajudar nessa?

Muito obrigado!

Exibições: 329

Anexos

Responder esta

Respostas a este tópico

olá Guilherme.

      Certamente o RV (Minerin)  irá resolver isso.  Mas me adiantei um pouco e aproveitei para organizar seu código, além de documentá-lo um pouco.

      Claro, também resolvi o problema que vc relatou sobre o Buzzer  não estar parando,  e inclusive testei o funcionamento no ESP32.

      Segue o código documentado e com o problema resolvido:  "alti_1_V08t_02.zip"

      Mas há um ponto importante que vc precisa verificar, que é sobre o tipo do Buzzer que vc está usando no seu Hardware.

      Vc precisa checar se seu Buzzer é acionado por "HIGH" ou por "LOW",  e setar isso no código, conforme vc pode ver na figura a seguir:

(clique na figura para "zoom")

      Neste caso, eu deixei setado como "HIGH" (onde está marcado em roxo na figura).  Mas se seu Buzzer for acionado por "LOW", então vc deve setar isso naquela linha do código mostrada na figura anterior.  Isso é muito importante (depois explico porque).

      Se vc não tiver certeza sobre isso,  post aqui uma foto do seu Buzzer, para que possamos ajudar nesta identificação.

      Observe também na figura anterior, que o pino onde o Buzzer está conectado já está setado para "2" (onde está marcado em verde na figura), que é o que vc disse estar usando.

      Caso tenha alguma dúvida, fique à vontade para perguntar.

      Espero ter ajudado.

      Abrçs,

      Elcids

olá novamente Guilherme.

      Quando eu ouvi o som do Buzzer  gerado no seu código original, achei um pouco estranho, pois as frequências dos tons gerados pareciam ser diferentes daquelas que vc estava setando.  Mas no código que postei, não me atentei muito a isso,  e reproduzi a mesma função original que setava a frequência do Buzzer.

      Mas como fiquei com isso na cabeça,  resolvi me atentar ao setting da frequência no código,  e para minha surpresa vi que estava incorreta.  O método usado pelo autor original (o "pschatzmann" do link que vc postou),  usa uma Interrupção gerada por um Timer de Hardware,  para inverter o sinal no pino de ON/OFF do Buzzer,  e por isso essas Interrupções tem que ocorrer na metade do período da frequência desejada.  Mas da forma que estava no código,  estava gerando Interrupções numa taxa exatamente igual ao período da frequência desejada,  e como resultado,  os tons audíveis no Buzzer tinham sempre a metade da frequência esperada, confirmando minha suspeita dos tons parecerem estranhos.  A figura a seguir mostra como isto estava sendo feito, onde salientei em amarelo:

(clique na figura para "zoom")

      Assim, modifiquei a função para que gerasse os tons nas frequências corretas.  Isto consistiu em apenas dividir por 2  o valor setado para o período do Timer.  Claro, testei novamente e dessa vez percebi que os tons estavam "normais". Também medi os períodos gerados no Buzzer e constatei que agora estavam corretos.  A figura a seguir mostra a alteração, salientada na cor verde:

(clique na figura para "zoom")

      O  "if"  na parte salientada em azul,  apenas impede o setting do Timer quando a frequência é zero (o que corresponde a um sinal "DC").

      Aproveitei, e também fiz algumas pequenas melhorias no código.  Algumas são um tanto sutis e de pouco significado.  Mas duas dessas melhorias eu acredito que vale a pena mencionar:

      1)  melhoria do controle ON/OFF do Driver do Buzzer.  A ISR da Interrupção do Timer, agora também desliga o Driver do Buzzer quando ele não está habilitado. Isso garante que o Driver fique "OFF", caso alguma Interrupção ocorra depois que o controle lógico "mandou" desligar o Buzzer.  Essa medida pode ser considerada um exagero, uma vez que mesmo para frequências muito baixas, é improvável que uma Interrupção ocorra depois que o controle lógico desligou o Buzzer (mas como não é impossível de ocorrer, já que as as Interrupções são "pseudo-assíncronas" ao controle, achei melhor deixar implementado esse desligamento "extra").

      2)  acrescentei a execução de um comando enviado via Terminal do Arduino,  para testar os tons gerados no Buzzer.  Para isso basta digitar no Terminal, um comando simples especificando a frequência (em Hz) e a duração (em mili-segundos),  para o tom a ser gerado.  Por exemplo:  caso deseje gerar 1430 Hz durante 50 mili-segundos,  basta digitar e enviar pelo Terminal o seguinte comando:

                     1430:50

            Ao invés do ":",  vc pode usar qualquer caracter de separação. Mas aconselho usar o ":", pois parece mais lógico.  No Terminal vc também pode digitar vários comandos seguidos separados por um "espaço", e enviar todos de uma vez só, como no exemplo a seguir:

                     2100:20  1000:80  500:200

            Mas claro, devido ao "delay(150)"  que existe no final do "loop" do Arduino, entre cada som gerado haverá justamente um intervalo mínimo de 150ms.  Mas observe que se vc quiser apenas inserir um intervalo adicional, basta colocar um comando com frequência zero, como por exemplo  0:50  para 50 mili-segundos adicionais,  e isto vc pode acrescentar a seu critério entre cada comando que vc digitou na linha do Terminal.

            A figura a seguir mostra a execução do comando no "loop" do Arduino,  que como se pode ver é muito simples:

(clique na figura para "zoom")

      Aproveito também para algumas observações importantes:

      -  sobre a questão do ON/OFF do Driver do Buzzzer no Hardware, que eu me referi no post anterior,  explico agora por que é importante.  Como se está gerando tons no Buzzer,  obrigatoriamente este Buzzer deve ser do tipo "passivo",  e a maioria deles possui uma impedância de carga relativamente baixa,  normalmente menor que 50 Ohms.  Assim se o sinal de controle do Buzzer for deixado "ON" por longos períodos, poderá sobre-aquecer o Transistor Driver  que existe na plaquinha do Buzzer, podendo inclusive "queimar" o mesmo.  Assim,  é importante deixar o Driver (o Transistor) desligado quando não estiver gerando sinais no Buzzzer.  Por isso é importante saber se o Buzzer utilizado é ligado com "HIGH" ou "LOW".  Além disso,  isso evita consumo exagerado da alimentação, principalmente se vc está usando o "sleep" do ESP32.

            Inclusive seria de bom senso, evitar usar o pino "2" para controle do Buzzer, pois este pino tem influência no "boot" do ESP32,  e dependendo do Buzzer usado,  este poderá "enganar" o "boot" após um reset.

      -  a placa ESP32 "TTGO",  tem um "Pullup" externo (normalmente 100k) conectado ao pino "35"  do ESP32.  Isto porque este pino é "Input only",  e não possui "Pullup" interno.   Assim para aqueles que queiram usar  outras placas  ESP32,  o pino "35"  não é  uma boa opção para a conexão de um Botão,  já que a maioria das outras placas não possui um "Pullup" externo naquele pino.  Mas diversos outros pinos podem ser usados,  e deve ser um pino de "RTC_IO" caso o "wakeup"  do ESP32 seja efetivamente usado (não esquecer de setar o número do pino  na função "esp_sleep_enable_ext0_wakeup").

      -  ao invés de usar o método via Timer  para gerar tons no Buzzer,  seria mais interessante usar um sinal PWM  com ciclo de 50%,  usando o Hardware do "LEDC" do ESP32.  Isso garantiria uma geração mais precisa das frequências dos tons,  uma vez que os períodos não teriam influência da execução do código (especificamente devido às IRQs  e aos chaveamentos de Processos  existentes no ESP32).

      Segue o código com as alterações:   "alti_1_V08t_03.zip"

      Abrçs,

      Elcids

Mas rapaaazzz, muito obrigado por toda ajuda! Principalmente em documentar melhor. To tentando melhorar essas coisas também.

Humm no caso pra usar o PWM eu poderia migrar o buzzer pra outro canal que não o 2, mantendo do duty-cicle em 50%, é isso?

Quanto a ligação do buzzer ele funciona em high; então acho que a implementação é essa mesma.

Mais uma vez, muito obrigado!

Olá novamente Guilherme.

      Sobre a documentação, é também um exercício.  É algo que temos que fazer constantemente, praticamente impor uma rotina.  Mas claro, nem sempre é fácil, e infelizmente 99% dos programadores não fazem isso da forma que deveriam (a verdade é que a maioria detesta fazer isso, e não se incomodam em admitir isso).

      Mas se vc fizer a documentação desde o início,  já será um passo grande pra facilitar o gerenciamento do próprio código.  E não precisa seguir completamente as regras técnicas (que são bem rigorosas em relação à documentação).  Para códigos do dia a dia,  tente seguir a "receita" de como fiz no seu caso,  pois irá te ajudar muito conforme vc desenvolve estes códigos.

      Sobre a questão do Nível Lógico de acionamento do Buzzer,  o importante é que vc tenha entendido o motivo de especificar isso no código.  Procure sempre fazer isso.  Note inclusive que isso deveria ser feito também em relação ao Nível Lógico presente no pino de um Botão  quando este é acionado (e embora isso seja muito simples,  eu preferi não fazer no seu código pra não parecer rigoroso e chato).

      Sobre a questão de usar o "PWM via LEDC",  também o importante é que vc tenha entendido o motivo:  garantir que a geração da frequência dos tons não tenha influência da execução do código (especificamente Interrupções  e chaveamento de Tasks/Processos  no ESP32).

      Assim,  alterei o último código que postei,  para que a geração dos tons no Buzzer seja com "PWM via LEDC" do ESP32.  Inclusive essa alteração simplificou um pouco o código.  Mas não há nada realmente significativo para falar sobre isso,  pois todo o código está funcionalmente comentado,  além da alteração ser bem simples.  Eu inclusive testei na prática e funcionou como esperado,  gerando os tons com grande fidelidade.

      O código com "PWM /LEDC", é este:  "alti_1_V08t_PWM_01.zip"

      Sobre a questão de usar o pino "2"  para controle do Buzzer,  recomendo usar um outro pino,  pois caso em algum momento futuro vc precise trocar o Buzzer por um outro que tenha uma impedância perceptível,  evitará problemas com o "boot"  do ESP32.  Claro, se trocar o pino,  não esqueça de alterar o número dele no código, assim como setar o Nível Lógico ("HIGH" ou "LOW") adequadamente. Estes settings são mostrados na figura a seguir:

(clique na figura para "zoom")

      Ah,  vc não comentou se testou o código do post anterior.  Caso tenha testado,  espero que  tenha apreciado o "feature" de enviar comandos  via Terminal do Arduino  para testar a geração de tons ou sequências de tons no Buzzer  (no post anterior eu mostrei exemplos de como usar isso).

      Abrçs,

      Elcids

Opa, peço desculpas pela demora em responder!!

Eu tentei mas não consegui resposta quando uso o terminal.

Já quanto ao restante do código, funcionou sem problema algum. A única outra coisa que coloquei foi uma nova função para que o altímetro não dispare o alarme de altitude crítica na subida, só na descida. 

Inclusive to tentando fazer o exercicio comentado e descrever melhor o que está sendo implementado.

Nesse caso fiz isso

//***********************************************************************

// Variaveis para comparação de valores de altitude e definicao se delta positivo (subida) ou negativo (queda)
float alti1;
float alti2;

//***********************************************************************

if ( ( int( alti_Pressao ) < 6000 ) && ( int( alti_Pressao ) > 5000 ) && ((alti1 - alti2) < 0) ) // se a pressao esta' entre 5000 e 6000 e em queda (delta negativo)
{
Display_TFT.fillScreen( TFT_RED ); // sinaliza via tela vermelha.
Display_TFT.print( int( alti_Pressao ) ); // exibe no Display, a Pressao atual.

**********************************************************************************

Acabei de baixar aqui o novo codigo modificado. Vou botar pra rodar e volto com as novidades ahahahah

Abraço!

olá Guilherme.

      Sobre o envio do comando para testar tons  via Terminal do Arduino,  não se esqueça de configurar a velocidade  no seu terminal (neste caso 115200),  do contrário o ESP32  não receberá o comando corretamente.  Veja a figura a seguir,  onde mostro o exemplo para enviar 3 comandos, gerando 3 tons um em seguida do outro:

(clique na figura para "zoom")

      Observe no Terminal,  que na opção do "final de linha",  vc pode selecionar qualquer das 4 opções disponíveis,  pois o código irá funcionar em todos os casos (mas a opção mais comum é "Ambos NL e CR", que é também considerada "padrão").

      E em uma única linha,  vc pode enviar apenas um comando ou quantos desejar.  Eles serão executados sequencialmente.

      Ah, como vc pode ver na figura anterior, no meu caso o Terminal está em Português (o padrão no meu computador),  mas em inglês não será muito diferente.

      Sobre a documentação,  vou deixar uma dica valiosa.

      Veja:  "alti1" e "alti2"  são nomes não muito representativos,  e não clarificam para o que estas variáveis são usadas.  Observe que daqui a algum tempo, nem mesmo vc saberá o que estas variáveis significam,  e seria bom saber isso sem precisar analisar o código (e sim apenas olhando o nome das variáveis).

      Por isso,  procure usar nomes que possam aludir ao significado do uso das Variáveis (o mesmo vale para funções  ou quaisquer outros nomes no código, incluindo os definidos via "#define").

      Não sei o que "alti1" e "alti2"  significam exatamente,  mas vou chutar dois nomes que acredito serem mais representativos (de acordo com o que vc descreveu),  como mostro a seguir:

      float  alti_Delta_subida;

      float  alti_Delta_queda;

      Faz uma diferença, não é?

      E não fique receoso (ou com preguiça)  de colocar nomes um pouco mais longos,  mas também não exagere no comprimento (apenas o suficiente para ser entendido,  senão começa a "poluir" e dificultar o entendimento do código).

      Qualquer dúvida ou dificuldade, e que esteja ao meu alcance para ajudar, fique à vontade para perguntar.

      E sucesso no seu Projeto !!!

      Abrçs,

      Elcids

boa tarde Elcids vc esta sem Skype, se tiver passa pra mim, presizo falar com vc um abrço

RSS

© 2022   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço