Está frio no chalé e você deseja ligar o aquecedor algumas horas antes da sua chegada ou está preocupado com a possibilidade de um desligamento de emergência do sistema de aquecimento de uma casa de campo na sua ausência. Todos esses problemas podem ser resolvidos usando o módulo GSM, que pode enviar e receber mensagens SMS e responder a elas, ativando e desativando a carga necessária. Em teoria, tudo é simples, na prática, no caminho para implementar esse dispositivo, existem muitas armadilhas.

Meu plano era criar um dispositivo simples e barato, equipado com dois sensores de temperatura, um sensor de umidade, um módulo GSM, além de um relé de estado sólido e um soquete para conectar a carga. O que aconteceu no final pode ser visto na foto. O sensor climático BME280 foi escolhido como sensor de temperatura e umidade; seu canal de pressão não é utilizado. Na foto, você pode vê-lo sob a tampa transparente à esquerda do módulo principal. Esse arranjo reduz o efeito da geração de calor dentro do alojamento nas leituras do sensor. Como tampa, é utilizado um tubo de ensaio de plástico chinês com dois orifícios de ventilação. O segundo sensor de temperatura é remoto, feito no DS18B20. Ele está localizado dentro de uma sonda de metal, conectada à caixa com um cabo através de uma tomada de áudio comum para fones de ouvido. A sonda foi projetada para medir diretamente a temperatura do sistema de aquecimento. O volume do corpo principal é ocupado por um relé de estado sólido (eu escolhi um mais potente) e um conversor de 220V a 5V para alimentar o circuito. O soquete para conectar a carga está montado na parte traseira do gabinete, na foto não é visível. Um display OLED baseado no controlador SH1106 exibe as leituras do sensor e também mostra se a carga está ligada. Para controlar todo o sistema, o módulo Arduino Pro Mini é usado na versão 3.3V 8MHz. Eu não sou um grande fã desta plataforma, mas a abundância de bibliotecas, incluindo cuidadosamente embriagada pela autora, faz dela a melhor escolha quando você precisa fazer rapidamente algo simples.
O módulo SIM800L GSM está alojado em uma caixa de metal separada para reduzir a interferência que ele cria no restante do circuito. Como a prática demonstrou, a interferência disso não é muito reduzida. E, radicalmente, são reduzidos por uma antena externa conectada por um cabo blindado ao conector coaxial, na foto acima, em primeiro plano. Mas falaremos sobre isso com mais detalhes posteriormente.

Muitos artigos foram escritos sobre o uso de módulos GSM, inclusive no hub, por isso evitarei repetições e falarei sobre o que não vi em publicações sobre esse tópico, como criar um dispositivo confiável com base nesse módulo.
Nas garagens, onde costumo visitar, coloquei recentemente uma barreira na entrada, que se abre quando você liga para um determinado número. Aparentemente, é feito em um módulo GSM semelhante. Fiquei surpreso com o quão difícil é passar por esse número para abri-lo. Agora eu sei muitas razões para isso. Esse conhecimento me custou vários meses de experimentos e uma quantidade impressionante de dinheiro gasto com eles. Espero que agora esse conhecimento sirva a outra pessoa. Considere o que é importante prestar atenção, passando de problemas óbvios de hardware para problemas menos óbvios de software.
A primeira coisa que é importante fazer corretamente é inserir um cartão SIM.
Pareceu-me óbvio que o cartão SIM é inserido com um canto chanfrado para a frente. Durante uma semana, tenho tentado entender por que o módulo não deseja se registrar na rede, dominando simultaneamente os comandos no terminal. Como resultado, em algum fórum em inglês, encontrei uma menção de que você precisa inseri-lo com um canto chanfrado atrás. É estranho que geralmente seja inserido dessa maneira e daquilo.
Para funcionar bem, você precisa comer bem.
Os requisitos de energia para o módulo GSM são bastante específicos. É fabricado com base em um microchip projetado para telefones celulares com botão de pressão e é projetado para ser alimentado diretamente a partir de uma bateria de lítio. Portanto, 5V é muito para ele, e 3,3V não é suficiente. Além disso, no modo de transmissão com potência máxima, é capaz de consumir corrente de até 2A. Se a fonte de alimentação não for capaz de fornecer a corrente necessária, o módulo GSM poderá reiniciar ao tentar se registrar na rede e continuar a reinicializar em um ciclo sem fim. Os períodos de pico de consumo geralmente duram menos de um segundo, por isso é tentador usar um estabilizador de baixa corrente com armazenamento de energia por períodos de pico de carga. Como uma unidade, você pode usar uma bateria de lítio. Ao mesmo tempo, é importante garantir a possibilidade de desconectá-lo e é importante não esquecer de usá-lo; caso contrário, desconectar o dispositivo da rede resultará em uma descarga profunda da bateria e em danos irreversíveis. Outra opção é substituir a bateria por um ionistor (supercapacitor). Ele não tem medo de descarga profunda. Mas ele também tem problemas com a confiabilidade. Uma célula do ionistor é geralmente classificada para tensão de 2,5 a 3V. Os ionistores projetados para alta voltagem consistem em várias células (geralmente 2). Nesse caso, no entanto, o desequilíbrio de tensão nas células pode resultar em quebra das células. Esse desequilíbrio é facilmente obtido devido à diferença na capacitância da célula ou à diferença na corrente de fuga. O parâmetro de resistência interna do ionistor também deve ser considerado. Ionistores com alta resistência interna a altas correntes são inúteis, e ionistores com baixa resistência não são mais baratos que a bateria. Depois que meu ionistor morreu repentinamente devido a um desequilíbrio de células, eu apenas apliquei um conversor de 220V a 5V de potência suficiente. Para diminuir a tensão no módulo GSM desejado, coloquei um diodo de silício regular entre o conversor e o módulo. Nesse diodo, 0,7V geralmente cai, de modo que o módulo obtém os 4,3V necessários. Após o diodo, é útil colocar um capacitor eletrolítico de grande capacidade. Isso diminui a tensão quando o transmissor é ligado de repente.
Mantenha-se afastado da antena de transmissão.
Mesmo depois de fornecer ao módulo GSM a energia necessária, o sintoma de reinicialização aparecia periodicamente, mas desta vez o Arduino foi reiniciado. Observar seu poder usando um osciloscópio mostrou que o poder não é necessário aqui. Aparentemente, o transmissor criou o módulo, uma vez que o problema surgia com mais frequência, piores as condições de recepção do sinal da estação base. Tal efeito radical de interferência da antena transmissora é bastante explicável se lembrarmos que o transmissor do módulo é capaz de fornecer 2 watts à antena. Esse poder pode ferver um mililitro de água em 5 minutos ou aquecer seu ouvido alguns graus. Para combater esse problema, vários métodos foram tentados. Primeiro, conectei uma antena externa, localizada fora do gabinete e conectada ao módulo com um cabo coaxial curto. No entanto, isso não deu o efeito esperado. Em seguida, coloquei o módulo em uma caixa de metal separada, à qual a antena estava conectada por fora. Melhorou, mas não muito. Melhorou radicalmente a situação apenas com a remoção da antena a uma certa distância do dispositivo devido à sua conexão com um cabo coaxial de comprimento suficiente.
Por que isso acontece é fácil entender por considerações físicas. Uma antena típica é um pino de quarto de onda, ou seja, metade da antena dipolo. Mas, para criar um campo elétrico, metade do dipolo não é suficiente, você precisa da segunda metade e, em seguida, um campo elétrico aparecerá entre os elementos carregados negativa e positivamente da antena. Para uma antena chicote comum, a outra metade é a superfície da Terra, o corpo do instrumento ou 'balanços' condutivos especiais. Mas para os profissionais de marketing, tudo isso é muito complicado, por isso geralmente vendemos apenas metade da antena normal. Como ela trabalha? Muito simples - a outra metade é o cabo ao qual a antena está conectada. O fato de ser blindado não muda nada. A superfície externa de sua trança desempenha o papel da segunda metade da antena dipolo. Nesse caso, a interferência é facilmente induzida aos fios que passam na vizinhança, apesar de o cabo parecer estar blindado. Bem, se não houver cabo, por exemplo, ocultamos o módulo em uma tela de metal, da qual a antena se destaca? Se a tela for grande (comparada com o comprimento de onda), funcionará como a segunda metade do emissor e, se for pequena, os outros fios conectados a este módulo emitem, não importa qual. A figura a seguir ilustra o acima (os prós e os contras são mostrados para maior clareza, na realidade, a carga dos elementos da antena muda de sinal com a frequência da portadora).

A antena 'direita' é mostrada à esquerda; seu cabo de entrada não emite interferências. A imagem do meio mostra a antena que você costuma comprar. Aqui, o cabo de entrada faz parte do emissor e interfere nos fios que passam nas proximidades. A situação à direita mostra quando a fonte de sinal está oculta em um gabinete blindado compacto. Aqui, todos os fios trazidos para esse invólucro fazem parte do emissor.
A moral é que a única maneira confiável de se proteger das interferências causadas pela antena transmissora é retirá-la do restante dos eletrônicos, conectando-a a um cabo coaxial de comprimento suficiente. Quanto tempo é suficiente? É natural medir a distância com o comprimento de onda, neste caso, é um máximo de 30 cm, distância mínima pela qual a antena deve ser atribuída, mas quanto mais longe, melhor.
Nem todas as portas seriais são igualmente úteis.
Nos microcontroladores AVR simples, que todo mundo costuma usar, existe apenas uma porta serial de hardware e é usada para baixar o programa. Portanto, a implementação de software da porta serial é uma solução muito popular. Vou provar uma afirmação que muitos achariam inesperada - para gerenciar o módulo GSM, a implementação de software da porta serial é inadequada.
A essência do problema é que a implementação de software da porta serial proíbe interrupções durante todo o tempo em que o próximo caractere for transmitido ou recebido. Parece que isso é ruim, como muitos fazem. Por exemplo, a implementação do protocolo 1-Wire para leitura de termômetros da Dallas Semiconductor também proíbe interrupções durante a transmissão de um bit, ou seja, 65 microssegundos. Isso, é claro, também não é bom. Se o sistema tiver outros manipuladores de interrupção, eles não poderão fornecer um tempo de resposta à interrupção menor que esses 65 microssegundos. Se uma solicitação de interrupção chegar quando for negada, ela só será processada depois que a interrupção for resolvida novamente. Por exemplo, uma porta serial de hardware usa interrupções para colocar o próximo caractere recebido no buffer do receptor. Se o próximo caractere chegar até que a interrupção do anterior seja processada, ele será perdido. Isso significa que a porta serial do hardware não poderá operar a uma velocidade superior a 115200 bits por segundo. No caso de implementação de software da porta serial, tudo é pior. Para sua operação, é necessário que o tempo de resposta a uma interrupção seja menor que o tempo de transmissão de um bit. Isso nos limita a uma velocidade de 9600 bits por segundo.
Um problema mais sério é que o próprio software da porta serial proíbe interrupções. Além disso, o tempo em que os proíbe (o tempo de transmissão ou recepção de um caractere) é sempre cerca de 10 vezes maior que o tempo máximo de processamento de interrupção necessário para a operação correta do receptor da mesma porta serial do software. Ou seja, sempre interfere consigo mesmo a tal ponto que, ao mesmo tempo, não pode receber e enviar dados. Obviamente, na maioria dos casos, isso não é necessário. Na maioria, mas não no nosso caso, com o módulo GSM. Ele pode, inesperadamente para nós, por sua própria iniciativa, começar a transferir dados (por exemplo, ao receber uma mensagem SMS). E no caso de usar uma implementação de software da porta serial, isso pode facilmente levar a uma falha do protocolo de comunicação com o módulo. Portanto, apliquei a mesma porta serial de hardware na programação do Arduino e na comunicação com o módulo GSM. Inconveniente, é claro, mas esta é a única maneira de criar um dispositivo confiável.
Protocolo assíncrono - manipulador assíncrono
Um protocolo assíncrono é um protocolo no qual um lado da troca pode começar a transmitir informações inesperadamente para o outro lado, ou seja, sem nenhuma sincronização com suas mensagens. Este é exatamente o protocolo de comunicação com o módulo GSM. Ele responde regularmente a solicitações do Arduino, mas também pode começar a transmitir algo próprio, por exemplo, para informar sobre a mensagem SMS recebida. E isso cria um problema real, já que nenhuma das bibliotecas que conheço por trabalhar com o módulo do Arduino leva em consideração a assincronia de protocolo. Imagine que o Arduino enviou um comando para o módulo e, ao mesmo tempo, transmitiu informações sobre a mensagem SMS recebida. Esta informação será aceita em vez de responder ao comando. Como resultado, a biblioteca retornará um erro em resposta ao comando (na melhor das hipóteses, tudo ficará travado na pior das hipóteses) e a mensagem sobre o SMS recebido será perdida.
Isso é fácil de corrigir - você só precisa escrever seu próprio manipulador de protocolo assíncrono. Um manipulador assíncrono cria apenas os requisitos mínimos necessários para respostas do módulo a seus comandos. Como resultado, o módulo responde OK ou ERROR para cada comando. E isso é o suficiente para corrigir a resposta. Todas as outras linhas que vêm do módulo são processadas, independentemente de terem sido fornecidas em resposta a um comando ou por conta própria. O significado dessas linhas sempre pode ser determinado pelo início. Se a linha começar com + CSQ, ela conterá informações sobre a qualidade do sinal. Se iniciar + CMT, essas são as informações sobre o SMS recebido e o endereço do remetente. A primeira linha é enviada como parte da resposta ao comando AT + CSQ e o segundo módulo é enviado por iniciativa própria, mas para nós essa diferença é absolutamente insignificante. O módulo envia mensagens SMS recebidas diretamente para a porta serial. Isso evita a leitura da memória e a exclusão subsequente. Para reconhecermos as mensagens SMS no fluxo geral de mensagens do módulo, elas devem começar com o símbolo #, caso contrário, a mensagem será ignorada.
Uma biblioteca criada pelo autor que implementa a abordagem acima está localizada
aqui .
Para receber linhas começando com uma certa sequência de caracteres, o cliente cria um objeto especial - uma armadilha. Ele pode criar qualquer número dessas armadilhas. As linhas recebidas do módulo, exceto OK, ERROR, que não caíram em nenhuma das traps, são simplesmente ignoradas. Como essa arquitetura não requer uma análise completa das respostas do módulo a muitos tipos diferentes de comandos, o código da biblioteca é muitas vezes mais compacto do que qualquer uma das bibliotecas que conheço.
Qual é o resultado?
O resultado é um dispositivo que funciona de maneira confiável em uma área com pouca cobertura, ainda melhor do que o telefone comum. Abaixo está um resumo completo.

Para os interessados, há um link para o github, onde você encontrará o código-fonte do projeto e uma descrição dos comandos que podem ser enviados ao dispositivo em mensagens SMS.
github.com/olegv142/GsmMon