Instabilidade no ADC do Mega.

Boa Tarde Amigos.

Estou com problemas de estabilidade na leitura de sinais analógicos no Arduino Mega.

Tenho que ler algumas portas consecutivas, já lí bastante à respeito e tomei diversas precauções, mas mesmo assim as leituras não são estáveis.

A variação é pequena, mas acho que isto não deveria ser normal.

A rotina abaixo faz a leitura das portas A1, A3, A5, A7 e A9, eu conectei todas elas a uma fonte de alimentação de boa capacidade. Todas as portas estão ligadas juntas.

E estabilizei uma tensão de 3.30V, esta tensão é acompanhada por um multimetro RMS, e está realmente estável.

Devido a alguns problemas de estabilização do ADC que já lí por aí, utilizei um delay para esperar que o ADC realmente estabilize. (inclusive já utilizei delays muito mais longos para teste)

Também estou efetuando 10 leituras e tirando a média, mesmo assim os valores ainda variam.

static void LerPortas2() { // Rotina para leitura das portas analógias... atualizar valores...
	float vpino;
	uint32_t Somatorio;
	int TempRead;
	int TempoEstabiliza = 100; // ms

	
	
	analogRead(A1); // forçando o Setup do ADC, para ler a porta, descartando esta leitura
	delay(TempoEstabiliza); // delay para que o ADC estabilize
	Somatorio = 0;
	for (int i=0; i<10; i++) {
		Somatorio += ADCW; // lendo direto do registrador ADCW, mesmo que ler pelo analogread, mas economizando a etapa de setup do adc que foi feito anteriormente.
		delay(TempoEstabiliza);
		}
	TempRead = Somatorio / 10;
	vpino = (TempRead * 5.0 / 1024);
	Serial.print(ADMUX, BIN);
	Serial.print("=Channel - Analogs Values A1=");
	Serial.print(TempRead);
	Serial.print(" - Tensao Pino=");
	Serial.println(vpino);

	
	// preparar para a leitura de A3
	analogRead(A3);
	delay(TempoEstabiliza);
	Somatorio = 0;
	for (int i=0; i<10; i++) {Somatorio += ADCW;delay(TempoEstabiliza);}
	TempRead = Somatorio / 10;
	vpino = (TempRead * 5.0 / 1024);
	Serial.print(ADMUX, BIN);
	Serial.print("=Channel - Analogs Values A3=");
	Serial.print(TempRead);
	Serial.print(" - Tensao Pino=");
	Serial.println(vpino);

	
	// preparar para a leitura de A5
	analogRead(A5);
	delay(TempoEstabiliza);
	Somatorio = 0;
	for (int i=0; i<10; i++) {Somatorio += ADCW;delay(TempoEstabiliza);}
	TempRead = Somatorio / 10;
	vpino = (TempRead * 5.0 / 1024);
	Serial.print(ADMUX, BIN);
	Serial.print("=Channel - Analogs Values A5=");
	Serial.print(TempRead);
	Serial.print(" - Tensao Pino=");
	Serial.println(vpino);

	
	// preparar para a leitura de A7
	analogRead(A7);
	delay(TempoEstabiliza);
	Somatorio = 0;
	for (int i=0; i<10; i++) {Somatorio += ADCW;delay(TempoEstabiliza);}
	TempRead = Somatorio / 10;
	vpino = (TempRead * 5.0 / 1024);
	Serial.print(ADMUX, BIN);
	Serial.print("=Channel - Analogs Values A7=");
	Serial.print(TempRead);
	Serial.print(" - Tensao Pino=");
	Serial.println(vpino);
	
	
	// preparar para a leitura de A9
	analogRead(A9);
	delay(TempoEstabiliza);
	Somatorio = 0;
	for (int i=0; i<10; i++) {Somatorio += ADCW;delay(TempoEstabiliza);}
	TempRead = Somatorio / 10;
	vpino = (TempRead * 5.0 / 1024);
	Serial.print(ADMUX, BIN);
	Serial.print("=Channel - Analogs Values A9=");
	Serial.print(TempRead);
	Serial.print(" - Tensao Pino=");
	Serial.println(vpino);
}



void setup() {
	// put your setup code here, to run once:
	Serial.begin(115200);
	while (!Serial) {
		; // wait for serial port to connect. Needed for native USB port only
	}
	Serial.println(F("\n[Inicializando Sistema...]"));
	
	analogReference(DEFAULT);

}

void loop() {
	// put your main code here, to run repeatedly:
	LerPortas2();

	delay(4000);
}

Veja abaixo o resultado na saída…

1000001=Channel - Analogs Values A1=676 - Tensao Pino=3.30
1000011=Channel - Analogs Values A3=686 - Tensao Pino=3.35
1000101=Channel - Analogs Values A5=683 - Tensao Pino=3.33
1000111=Channel - Analogs Values A7=683 - Tensao Pino=3.33
1000001=Channel - Analogs Values A9=682 - Tensao Pino=3.33

1000001=Channel - Analogs Values A1=682 - Tensao Pino=3.33
1000011=Channel - Analogs Values A3=680 - Tensao Pino=3.32
1000101=Channel - Analogs Values A5=685 - Tensao Pino=3.34
1000111=Channel - Analogs Values A7=678 - Tensao Pino=3.31
1000001=Channel - Analogs Values A9=684 - Tensao Pino=3.34

1000001=Channel - Analogs Values A1=681 - Tensao Pino=3.33
1000011=Channel - Analogs Values A3=681 - Tensao Pino=3.33
1000101=Channel - Analogs Values A5=685 - Tensao Pino=3.34
1000111=Channel - Analogs Values A7=680 - Tensao Pino=3.32
1000001=Channel - Analogs Values A9=684 - Tensao Pino=3.34

Como disse a diferença é pequena, mas pelo fato da fonte ser estável e de todas as portas estarem conectadas ao mesmo ponto, deveriam todos apresentar sempre o mesmo valor.

E obviamente este valor de tensão serão resultados de alguns sensores que estarei utilizando, portanto uma pequena diferença aqui significa uma boa diferença no resultado final.

Alguém já teve este problema, tem idéia de como resolver?

Valeu!!

Que medidas é que tomaste para garantir que não tinhas ruído no sinal do Arduino?

Já pensaste que ao colocares todas essas entradas no mesmo ponto podes estar a causar esse ruído?

Já viste qual é a precisão do AD para ver se o efeito é realmente anormal?

Já agora, o ATmega tem apenas um AD e uma mux. Ou seja, ao leres todos os canais não os estás a ler ao mesmo tempo, mas sequencialmente. Existe no manual do Arduino algo acerca de quando se muda de canal, fazer uma ou algumas medições (já foi há algum tempo que li isso) sem usar o valor para garantir que o AD está no melhor estado para realizar a medição.

Se quiseres pensar noutras coisas, podes deixar de parte a analogRead() e programar por ti o uso do AD. Existe um método em que desligas toda a parte digital do chip para fazer a leitura analógica.

A minha opinião pessoal é que a medição que estás a ver é normal. Eu já vi bastante pior... e a solução, regra geral passa por uma média de leituras... tipo 10 ou até mesmo 5 no teu caso para obteres valores muito próximos uns dos outros.

Olá…

Obrigado pela resposta bubulindo.

Sim, no teste que postei já estava efetuando uma média de 10 valores, e também estava mantendo um delay para que ao mudar de canal o ADC estabilizasse.

Para efetuar o teste e variar a tensão eu utilizei uma fonte fixa de 5V e um POT de 10voltas para variar o valor nas portas analógicas.

Tudo isto ligado a um proto-board.

Passei a noite encafifado com isto, e hoje resolvi colocar o osciloscópio para ver se existia a presença e ruído…

Enfim… na Imagem “sem_capacitor”, é possível ver um pequeno ruído na linha amarela que é a saída do meu POT, e a linha azul que é a saída da fonte muito menos ruído.

Então coloquei um capacitor entre o GND e a saída do POT, e o resultado pode ser observado na imagem “com_capacitor”.

O ruído foi praticamente eliminado, e as leituras passaram a ser muito melhores.

Conclusão, todo o conjunto Potenciômetro, Fios, Proto-Board estavam contribuindo para gerar um ruído que o multímetro não identificava (certamente o multímetro faz muito mais integrações antes de mostrar um valor).

Bom, meu projeto original contém outros dispositivos, inclusive um shield Ethernet, e ao colocar o Ethernet para trabalhar, percebi novamente um pequeno ingresso de ruído ao plugar o cabo de rede, não chegou a atrapalhar as medições, mas no projeto final certamente vou colocar mais um capacitor alí entre o VCC e o GND do Shield Ethernet.

Abs.

O multímetro faz uma média da tensão, funcionando como um filtro. É também bastante difícil encontrar um multímetro com a precisão necessária para apanhar esse tipo de ruído.