Lendo sensores NTC com o Arduino – II


Dando continuidade à implementação do termômetro eletrônico utilizando um sensor termistor NTC e o Arduino, o próximo passo é a implementação das rotinas selecionaCmd e conversorAD. Observe que a medida que vamos implementando cada tarefa devemos verificar se a funcionalidade esperada da mesma está acontecendo. Isto deve ser realizado mesmo que tenhamos que “jogar fora” pequenos trechos do programa implementado visando unicamente o teste parcial.

A tarefa selecionaCmd possui o seguinte código:

.selecionaCmd
void selecionaCmd()
{
static char cTickAD;	
	
if (chModo == 1)   // operacao no modo autonomo	
	{
	if (cTickAD == 0)
		{
		cTickAD= cIntervalo;
		conversorAD();
		}
	else
		--cTickAD;
	}		
	
else               //operacao modo escravo  
	{
	if (cComando == '1')  //verifica se o comando atual e o cmd '1'
		{
		conversorAD();
		cComando= 0xFF; //informa que o comando foi executado
		}
	}	
} 

Esta tarefa é simples o suficiente para dispensar o fluxograma explicativo. Em primeiro lugar a tarefa testa a variável chModo. Se chModo estiver em um, isto indica que a operação está no modo autônomo. Como a tarefa é acordada a cada 100ms, ela espera decorrer o tempo dado por cIntervalo para chamar a tarefa conversorAD. Cada vez que chama ativa a conversorAD também recarrega o contador cTickAD, resultando num ciclo contínuo de chamadas espaçadas temporalmente com o intervalo de “cIntervalo” \* 100 ns.

Já no caso do modo for o modo escravo, a tarefa ao ser ativada verifica se o comando atual é “1”. O comando “1” corresponde ao pedido de leitura de temperatura da entidade remota. Se for “1” ativa a tarefa conversorAD e imediatamente informa a execução do programa.

A tarefa conversorAD possui o seguinte código:

.conversorAD
void conversorAD()
{

nUltimoValorLido=  analogRead(ENTRADA_TERMISTOR);
nFlagLido= 1;
 
sprintf(chBufferSaida,"$1,%d", nUltimoValorLido);
flagMsg=1;
}	 

Aqui temos o caso a que nos referimos antes de código apenas para teste. Observe que a tarefa faz a conversão AD do sinal disponível no pino AO (ENTRADA_TERMISTOR) e armazena este valor em nUltimoValorLido. Em seguida faz o flag nFlagLido==1, para habilitar a tarefa que vier a processar o nUltimoValorLido poder realiza a leitura. As linhas “sprintf(chBufferSaida,”$1,%d”, nUltimoValorLido); e flagMsg=1; ” são necessárias apenas nesta fase. Elas enviam o valor lido em A0 para a porta serial.

Uma maneira muito rápida de realizar teste é interligar o pino AO ao terra da placa (GND). O valor lido no terminal será zero. Conecte agora a 5 volts. O valor lido será 1023. Conecte em 3.3 volts. O valor lido será de 663.

Para facilitar copiamos aqui o software como está até o momento:

.tempNTC3.c
/*
 * tempNTC3.ino
 * Copyright 2017-07-31 tavares <tavares arroba  cadernodelaboratorio.com.br>
 * 0.1
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 * 
 */

 
#include  "Arduino.h"

//includes

 
//defines

#define LED_PLACA    13  // definimos aqui o pino de comando do led 
#define SEL_MODE     12  // pino que define o modo de operacao
#define ENTRADA_TERMISTOR  0


#define LIGA_LED_PLACA   digitalWrite (LED_PLACA, HIGH);
#define DESLIGA_LED_PLACA    digitalWrite (LED_PLACA, LOW); 



//variaveis globais
char cDuracao;     // numero de centenas de milisegundos que deve durar cada piscada
char cPiscadas;  // 2 * numero de vezes que deve piscar

char chBufferSaida[32];   //buffer de mensagens de saída
char flagMsg;             // em zero, buffer vazio, em 1 tem mensagem

char chModo;  // modo de operacao  1-> autonomo   0-> escravo

char cIntervalo;  //x 100mS intervalo aquisicao AD

char cComando; // contem o comando recebido da serial

int nUltimoValorLido;
char nFlagLido;


 
void setup()
{
// inicializacao de tempNTC
pinMode ( LED_PLACA,OUTPUT); // pino led como saida

pinMode(SEL_MODE,INPUT_PULLUP);

//inicializacao da interface serial
Serial.begin(9600, SERIAL_8N1); //serial iniciada em 9600,8,n,1

// 3 piscadas de 500ms informando a inicializacao
cDuracao= 10;    
cPiscadas= 6; 

//mensagem inicial

strcpy(chBufferSaida,"$0,tempNTC v 1.0");
flagMsg=1;

// intervalo inicial de aquisicao = 1s
cIntervalo= 10;

// indica nenhum comando esperando
cComando= 0xFF;

}
 
void  loop()
{
checkTimer();
}


/*
 tarefa CheckTimer
 gera o loop loop100 a cada 100 ms
 chamada atraves do loop principal do programa
*/
 
void checkTimer()
{
unsigned long tempoAtual;  
static  unsigned long tempoAnterior100ms;
 
tempoAtual= millis();   //obtem o tempo atual
 
if((tempoAtual - tempoAnterior100ms) >= 100L)
    {
    tempoAnterior100ms= tempoAtual;
    loop100();
    }

}
 


void loop100(void)
{
acionaLed();	
enviaMsg();	
leModo();	
selecionaCmd();
}	



void acionaLed()
{
static char cEstadoLed;
static char cIntervaloAtual;

if (cPiscadas >= 0 )
	{
	if (cIntervaloAtual <= 0)
		{
		cIntervaloAtual = 	cDuracao;
		-- cPiscadas;
		cEstadoLed= !cEstadoLed;
		}
	
	if (cEstadoLed == 0)
		{
		LIGA_LED_PLACA
		}
	else
		{
		DESLIGA_LED_PLACA
		}
		
	-- cIntervaloAtual;		
			
	}
	
}	
	

void enviaMsg()
{
if (flagMsg==1)
	{
	LIGA_LED_PLACA
	Serial.println(chBufferSaida);
	flagMsg=0;
	DESLIGA_LED_PLACA
	}
}	
	


void leModo()
{
chModo= (char) digitalRead(SEL_MODE);
}
 
 
void selecionaCmd()
{
static char cTickAD;	
	
if (chModo == 1)   // operacao no modo autonomo	
	{
	if (cTickAD == 0)
		{
		cTickAD= cIntervalo;
		conversorAD();
		}
	else
		--cTickAD;
	}		
	
else               //operacao modo escravo  
	{
	if (cComando == '1')  //verifica se o comando atual e o cmd '1'
		{
		conversorAD();
		cComando= 0xFF; //informa que o comando foi executado
		}
	}	
} 



void conversorAD()
{

nUltimoValorLido=  analogRead(ENTRADA_TERMISTOR);
nFlagLido= 1;
 
sprintf(chBufferSaida,"$1,%d", nUltimoValorLido);
flagMsg=1;
 
	
}	


Agora passamos a tarefa converteGraus. O modelo matemático implementado por esta tarefa foi já deduzido no capítulo anterior. O código se torna o seguinte:

.converteGraus

void converteGraus()
{
double fValue;	
double fTemp;
char strSaida[8];

//  dtostrf(floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, charBuf);	
if (nFlagLido == 1)
	{
	nFlagLido = 0;
	// convertemos o valor para volts
	fValue= (float)nUltimoValorLido * 0.00488;
	// convertemos em graus centigrados
    fTemp= fValue * 27.776 - 38.247;	
    //preparamos para envio a serial
    dostrf(fTemp, 3, 2, strSaida);
    strcpy(chBufferSaida,"$1,");
    strcat(chBufferSaida,strSaida);
    strcat(chBufferSaida,"\n");
    flagMsg=1;
	}
	
}	

É uma implementação direta das equações levantadas anteriormente. O que podemos destacar neste código é o uso da função dtostr, ao invés da mais convencional sprintf, na conversão do valor em ponto flutuante para uma string ascii. A função sprintf implementada no software Arduino NÃO possui a parte de processamento em ponto flutuante. É uma implementação incompleta em relação ao padrão da linguagem “C”. Felizmente o uso da dtostr atende plenamente os nossos objetivos.

O código parcial se torna então:

.tempNTC4.c
/*
 * tempNTC4.ino
 * Copyright 2017-07-31 tavares <tavares arroba cadernodelaboratorio.com.br>
 * 0.1
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 * 
 */

 
#include  "Arduino.h"

//includes

 
//defines

#define LED_PLACA    13  // definimos aqui o pino de comando do led 
#define SEL_MODE     12  // pino que define o modo de operacao
#define ENTRADA_TERMISTOR  0


#define LIGA_LED_PLACA   digitalWrite (LED_PLACA, HIGH);
#define DESLIGA_LED_PLACA    digitalWrite (LED_PLACA, LOW); 



//variaveis globais
char cDuracao;     // numero de centenas de milisegundos que deve durar cada piscada
char cPiscadas;  // 2 * numero de vezes que deve piscar

char chBufferSaida[32];   //buffer de mensagens de saída
char flagMsg;             // em zero, buffer vazio, em 1 tem mensagem

char chModo;  // modo de operacao  1-> autonomo   0-> escravo

char cIntervalo;  //x 100mS intervalo aquisicao AD

char cComando; // contem o comando recebido da serial

int nUltimoValorLido;
char nFlagLido;


 
void setup()
{
// inicializacao de tempNTC
pinMode ( LED_PLACA,OUTPUT); // pino led como saida

pinMode(SEL_MODE,INPUT_PULLUP);

//inicializacao da interface serial
Serial.begin(9600, SERIAL_8N1); //serial iniciada em 9600,8,n,1

// 3 piscadas de 500ms informando a inicializacao
cDuracao= 10;    
cPiscadas= 6; 

//mensagem inicial

strcpy(chBufferSaida,"$0,tempNTC v 1.0");
flagMsg=1;

// intervalo inicial de aquisicao = 1s
cIntervalo= 10;

// indica nenhum comando esperando
cComando= 0xFF;

}
 
void  loop()
{
checkTimer();
}


/*
 tarefa CheckTimer
 gera o loop loop100 a cada 100 ms
 chamada atraves do loop principal do programa
*/
 
void checkTimer()
{
unsigned long tempoAtual;  
static  unsigned long tempoAnterior100ms;
 
tempoAtual= millis();   //obtem o tempo atual
 
if((tempoAtual - tempoAnterior100ms) >= 100L)
    {
    tempoAnterior100ms= tempoAtual;
    loop100();
    }

}
 


void loop100(void)
{
acionaLed();	
enviaMsg();	
leModo();	
selecionaCmd();
converteGraus();
}	



void acionaLed()
{
static char cEstadoLed;
static char cIntervaloAtual;

if (cPiscadas >= 0 )
	{
	if (cIntervaloAtual <= 0)
		{
		cIntervaloAtual = 	cDuracao;
		-- cPiscadas;
		cEstadoLed= !cEstadoLed;
		}
	
	if (cEstadoLed == 0)
		{
		LIGA_LED_PLACA
		}
	else
		{
		DESLIGA_LED_PLACA
		}
		
	-- cIntervaloAtual;		
			
	}
	
}	
	

void enviaMsg()
{
if (flagMsg==1)
	{
	LIGA_LED_PLACA
	Serial.println(chBufferSaida);
	flagMsg=0;
	DESLIGA_LED_PLACA
	}
}	
	


void leModo()
{
chModo= (char) digitalRead(SEL_MODE);
}
 
 
void selecionaCmd()
{
static char cTickAD;	
	
if (chModo == 1)   // operacao no modo autonomo	
	{
	if (cTickAD == 0)
		{
		cTickAD= cIntervalo;
		conversorAD();
		}
	else
		--cTickAD;
	}		
	
else               //operacao modo escravo  
	{
	if (cComando == '1')  //verifica se o comando atual e o cmd "1"
		{
		conversorAD();
		cComando= 0xFF; //informa que o comando foi executado
		}
	}	
} 



void conversorAD()
{

nUltimoValorLido=  analogRead(ENTRADA_TERMISTOR);
nFlagLido= 1;

}	


void converteGraus()
{
double fValue;	
double fTemp;
char strSaida[8];

//  dtostrf(floatVar, minStringWidthIncDecimalPoint, numVarsAfterDecimal, charBuf);	
if (nFlagLido == 1)
	{
	nFlagLido = 0;
	// convertemos o valor para volts
	fValue= (float)nUltimoValorLido * 0.00488;
	// convertemos em graus centigrados
    fTemp= fValue * 27.776 - 38.247;	
    //preparamos para envio a serial
	dtostrf(fTemp, 3, 2, strSaida);
	strcpy(chBufferSaida,"$1,");
	strcat(chBufferSaida,strSaida);
	strcat(chBufferSaida,"\n");
	
    flagMsg=1;
	}
	
}	

As próximas ( e últimas ) tarefas a serem implementadas são a decodificaCmd e processaCmd. Estas tarefas recebem os comandos advindos da interface serial e os processam de acordo com o valor dos mesmos.

Entre as novas variáveis globais, a maioria é auto explicativa. Mas uma delas merece um estudo mais detalhado. Identifique no código as linhas:

 //vetor de funcoes que implementam os comandos
 void (*func[NUMEROMAXIMOFUNCOES])();

O que significa esta linha? Em primeiro lugar, identificamos um um vetor , informado pelos caracteres [ e ]. Este vetor tem a dimensão de NUMEROMAXIMOFUNCOES. O vetor contem ponteiros para funções, dado pelos caracteres (/ e ). Ou seja, neste vetor iremos armazenar os endereços das tarefas que serão ativadas em função dos comandos recebidos. Para executar uma tarefa cujo endereço está armazenado na posição “nIndex” usamos o código (\func[nIndex])(); Observe que pegamos o conteúdo da posição nIndex do vetor e chamamos a função () cujo endereço está associado a este conteúdo. É uma forma muito elegante e concisa de ativar tarefas (ou chamar funções) a partir do seu endereço, usando um mínimo de código e com grande flexibilidade, pois os elementos do vetor podem ser alterados dinamicamente.


A tarefa decodificaCmd pode ser implementada com o seguinte código. Verifique que a string do comando vai sendo montada no buffer chPDU , e logo ao ser detectado um caractere delimitador de fim de mensagem (0x0A) , é chamada a tarefa que decodifica este comando e chama as funções que implementam cada comando.

.decodificaCmd
chLido= Serial.read();
 
if(chLido != -1)
  {
  if(chLido != 0x0d)  //joga fora os 0x0d caso existam
    { 
    chPDU[cIndexEscrita]= chLido;
    
    if(chLido == 0x0A)  // delimitador de final de comando detectdo
      {
      chPDU[cIndexEscrita]=0;  
      processaCmd();  //ao final do comando chama a decodificacao
      cIndexEscrita=0;  //prepara para um novo comando
      }
    else
      {  
      ++cIndexEscrita;
      cIndexEscrita &= (MAX_LEN_ENTRADA -1);
      }
    }
  }
 
}

As funções propriamente ditas são as seguintes:

.retorna identificação
void reID()
{
strcpy(chBufferSaida,"$0,tempNTC v 1.0");
flagMsg=1;
}

Esta função salva a string relacionada a identificação do firmware e faz o flagMasg == 1. Com isto, na próxima varredura de 100ms a mensagem será enviada.

.le valor temperatura
void leValorTemperatura()
{
cComando= '1';	
	
}

Faz o flag cComando == 1. Com isto, na pŕoxima varredura de 100 ms o valor da temperatura será enviado à porta serial.

.Configura o intervalo
void configuraIntervalo()
{
cIntervalo= (char) atoi (chParam);
}

Converte em char o parâmetro passado no comando e atualiza a variável cIntervalo com este valor.

O programa completo do medidor de temperatura fica sendo:

.tempNTC5.ino
/*
 * tempNTC5.ino
 * Copyright 2017-07-31 tavares <tavares arroba cadernodelaboratorio.com.br>
 * 0.1
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301, USA.
 * 
 * 
 */

 
#include  "Arduino.h"

//includes

 
//defines

#define LED_PLACA    13  // definimos aqui o pino de comando do led 
#define SEL_MODE     12  // pino que define o modo de operacao
#define ENTRADA_TERMISTOR  0


#define LIGA_LED_PLACA   digitalWrite (LED_PLACA, HIGH);
#define DESLIGA_LED_PLACA    digitalWrite (LED_PLACA, LOW); 

#define MAX_LEN_ENTRADA     32  //tamanho do buffer de entrada
#define MAX_LEN_SAIDA       32  // tamnho do buffer de saida
#define NUMERO_MAXIMO_FUNCOES    4

//variaveis globais
char cDuracao;     // numero de centenas de milisegundos que deve durar cada piscada
char cPiscadas;  // 2 * numero de vezes que deve piscar

char chBufferSaida[MAX_LEN_SAIDA];   //buffer de mensagens de saída
char flagMsg;             // em zero, buffer vazio, em 1 tem mensagem

char chModo;  // modo de operacao  1-> autonomo   0-> escravo

char cIntervalo;  //x 100mS intervalo aquisicao AD

char cComando; // contem o comando recebido da serial

int nUltimoValorLido;  //ultimo valor do AD
char nFlagLido; // informa que temos um valor AD valido


char chLido;  // contem o caracter lido na serial
char chParam[4]; // buffer para armazenamento do primeiro parametro
char chCmd[4];    // buffer para o armazenamento do comando completo
char chPDU[MAX_LEN_ENTRADA];  //buffer parmontagem da string recebida 
int cIndexEscrita;  // indice para montagem da string recebida na serial

//vetor de funcoes que implementam os comandos
void (*func[NUMERO_MAXIMO_FUNCOES])();


 
void setup()
{
// inicializacao de tempNTC
pinMode ( LED_PLACA,OUTPUT); // pino led como saida

pinMode(SEL_MODE,INPUT_PULLUP);

//inicializacao da interface serial
Serial.begin(9600, SERIAL_8N1); //serial iniciada em 9600,8,n,1

// 3 piscadas de 500ms informando a inicializacao
cDuracao= 10;    
cPiscadas= 6; 

//mensagem inicial

strcpy(chBufferSaida,"$0,tempNTC v 1.0");
flagMsg=1;

// intervalo inicial de aquisicao = 1s
cIntervalo= 10;

// indica nenhum comando esperando
cComando= 0xFF;

//inicializacao do vetor de chamada de funcoes
func[0]= reID;
func[1]= leValorTemperatura;
func[2]= configuraIntervalo;


}
 
void  loop()
{
checkTimer();
decodificaCmd();
}


/*
 tarefa CheckTimer
 gera o loop loop100 a cada 100 ms
 chamada atraves do loop principal do programa
*/
 
void checkTimer()
{
unsigned long tempoAtual;  
static  unsigned long tempoAnterior100ms;
 
tempoAtual= millis();   //obtem o tempo atual
 
if((tempoAtual - tempoAnterior100ms) >= 100L)
    {
    tempoAnterior100ms= tempoAtual;
    loop100();
    }

}
 


void loop100(void)
{
acionaLed();	
enviaMsg();	
leModo();	
selecionaCmd();
converteGraus();
}	



void acionaLed()
{
static char cEstadoLed;
static char cIntervaloAtual;

if (cPiscadas >= 0 )
	{
	if (cIntervaloAtual <= 0) 
            { cIntervaloAtual = cDuracao; 
            -- cPiscadas; 
            cEstadoLed= !cEstadoLed; 
             }
        if (cEstadoLed == 0) 
             { 
             LIGA_LED_PLACA 
             } 
         else 
             { 
             DESLIGA_LED_PLACA 
             } 
         -- cIntervaloAtual; 
         } 
} 

void enviaMsg() 
    { 
    if (flagMsg==1) 
         { 
         LIGA_LED_PLACA 
         Serial.println(chBufferSaida); 
         flagMsg=0; 
         DESLIGA_LED_PLACA 
          } 
     } 

void leModo() 
{ 
chModo= (char) digitalRead(SEL_MODE); 
} 

void selecionaCmd() 
{ 
static char cTickAD; 
if (chModo == 1) // operacao no modo autonomo 
    { if (cTickAD == 0) 
        { 
        cTickAD= cIntervalo; 
        conversorAD(); 
        } 
     else --cTickAD; 
     } else //operacao modo escravo 
        { if (cComando == '1') //verifica se o comando atual e o cmd "1" 
             { 
             conversorAD(); 
             cComando= 0xFF; //informa que o comando foi executado 
             } 
         } 
} 

void conversorAD() 
{ 
nUltimoValorLido= analogRead(ENTRADA_TERMISTOR); 
nFlagLido= 1; 
} 

void converteGraus() 
{ 
double fValue; 
double fTemp; 

if (nFlagLido == 1) 
    { 
    nFlagLido = 0; // convertemos o valor para volts 
    fValue= (float)nUltimoValorLido * 0.00488; // convertemos em graus centigrados 
    fTemp= fValue * 27.776 - 38.247; //preparamos para envio a serial 
    dtostrf(fTemp, 3, 2, strSaida);
    strcpy(chBufferSaida,"$1,");
    strcat(chBufferSaida,strSaida);
    strcat(chBufferSaida,"\n");
    
    flagMsg=1; 
    } 
} 

void decodificaCmd() 
{ 
chLido= Serial.read(); 
if(chLido != -1) 
    { 
    if(chLido != 0x0d) //joga fora os 0x0d caso existam 
        { 
        chPDU[cIndexEscrita]= chLido; 
        if(chLido == 0x0A) // delimitador de final de comando detectdo 
            { 
            chPDU[cIndexEscrita]=0; 
            processaCmd(); //ao final do comando chama a decodificacao 
            cIndexEscrita=0; //prepara para um novo comando 
            } 
        else 
            { 
             ++cIndexEscrita; 
            cIndexEscrita &= (MAX_LEN_ENTRADA -1); 
            } 
        } 
    } 
} 

void processaCmd()  
{ 
int nCmd; //obtem o comando 
strcpy(chCmd,strtok(chPDU,",")); 
nCmd= atoi(chCmd); //obtem o paraemtro 
strcpy(chParam,strtok(NULL,","));  
if(nCmd > (NUMERO_MAXIMO_FUNCOES-1) ||  nCmd < 0)
  {
  strcpy(chBufferSaida,"$255,Comando inexistente");
+  flagMsg=1;
  }	  
else 
//chama a rotina correspondente
  (*func[nCmd])(); 
  
}	
	
	
void reID()
{
strcpy(chBufferSaida,"$0,tempNTC v 1.0");
flagMsg=1;
}
	


void leValorTemperatura()
{
cComando= '1';	
	
}



void configuraIntervalo()
{
cIntervalo= (char) atoi (chParam);
}
	

void configuraModo()
{
chModo= (char) atoi (chParam);	
	
}

Para testar completamente, curte circuite a entrada D12 para terra. O Arduino irá parar de enviar os valores de temperatura para o terminal. Digite o comando 0. Deverá vir a identificação do firmware. Digite 1 . Deverá receber o valor da temperatura. Deixe a entrada digital D12 em nível lógico 1. Os dados de temperatura deverão ser enviados periodicamente para a serial. Agora digite o comando 2,20. O intervalo entre cada envio deverá se alterar para 2 segundos entre cada envio.

Parabéns, o seu termômetro está respondendo exatamente como as especificações! E, se você seguiu desde o início esta série, deverá estar apto a compreender cada linha do código e adaptá-lo ao seu problema específico.

Até agora temos utilizado um emulador de terminais para interagir com o firmware do Arduino. Não seria interessante utilizarmos uma interface própria para isto!? Assunto para nosso próximo encontro!

 

Deixe um comentário