Pesquisar

Currículo e bio do autor Casal de artigos relacionados com o meu hobby - robótica
Minhas impressões sobre a imigração para a Austrália. Em russo apenas. Receitas para resolver problemas cotidianos
Linux lugares ligados Windows lugares ligados
Software lugares ligados Um monte de informações sobre hardware
Diferentes ferramentas podem ser úteis Mensagens sobre tecnologias web vários
Tudo o que não se encaixa no resto do menu RSS feed para este blog

Tag Cloud

Arquivo

Links

Blog do Andrey Mikhalchuk

English flagItalian flagKorean flagChinese (Simplified) flagPortuguese flagGerman flagFrench flagSpanish flagJapanese flagRussian flagDanish flagFinnish flagHebrew flag

Technoblog sobre a vida

20 de junho de 2011 Leitura ATtiny85/45/25 sensor interno de temperatura

ATtiny85 has internal temperature sensor

ATTINY85 tem sensor de temperatura interna

Eu estou trabalhando em um dos meus projetos de RTFMs video blog (confira http://rtfms.com ) que requer sensor de temperatura em uma embalagem muito pequena. Naturalmente a minha escolha é ATTINY85 - um chip impressionante pouco de AVR que, além de outros bens (como 6ch PWM, etc interface serial) tem sensor de temperatura interna. Então eu decidi usar um. Isso não foi fácil, mas depois de algumas horas de escavação e de fóruns de folhas de dados eu vim com uma classe que faz o trabalho com confiabilidade bastante impressionante e precisão.


Primeiro de tudo para executar esse código você precisa de um Arduino-Tiny ( http://code.google.com/p/arduino-tiny/ core) e algum tipo de ISP. Estou usando o Arduino Duemilanove como ISP. Veja meus RTFMs blog para mais detalhes sobre como fazê-lo trabalhar desta maneira, como carregar núcleo correta etc AFAIK todos os núcleos populares vai funcionar bem com este código. Só recomment Arduino-Tiny por causa da sua funcionalidade rico que pode ser usado para desencadear mais potência de ATTINY85.
A solução consiste em dois arquivos que você pode copiar para o seu projeto. Apenas CopyPaste-los a partir desta página:

InternalTemperatureSensor.h

# Ifndef _INTERNAL_TEMPERATURE_SENSOR_H_
# Define _INTERNAL_TEMPERATURE_SENSOR_H_

# Define TEMPERATURE_SAMPLES 30
# Define TEMPERATURE_ADJUSTMENT -13
# Define EXTREMES_RATIO 5

# Define MAXINT 32767
# Define MININT -32767

/ *
* Com base em amostras:
* - O sensor de temperatura interno tem desvio horrível. É um monte de saída varia (+ / -10 graus / seg), assim o exigir
* Alguns "suavização". Eu estou removendo valores extremos e execução de rolamento avg sobre o resto. Isso retorna ok
* Os resultados sobre amostras de 20 e mais. Pode-se reduzir o número de amostras para reduzir o tempo de resposta, mas esta
* Diminuirá precisão.
* - A linearidade é ok e cerca de 1,0 como a folha de dados prometeu
* - A necessidade de compensação a ser calculado para cada chip separadamente e fornecidos em c'tor
*
* Para calaculate o gancho deslocamento para cima do terminal para o pino 2 (TX Serial) 9600 8N1 e usar
* Temperature.print () chamada de método. Isto irá imprimir leituras de temperatura. Combine-o contra o seu
* Calibrado termómetro ligado ao chip. Ajustar Tos em c'tor se necessário.
* Veja o capítulo 17,12 do datasheet ATTINY85 para detalhes um pouco mais
* /

InternalTemperatureSensor classe {
int offset;
flutuar coeficiente;
int leituras [TEMPERATURE_SAMPLES];
int pos;

público:
InternalTemperatureSensor (float k, int o): deslocamento (o), o coeficiente (k), pos (0) {}
/ / Chame-o cada vez que você precisa para preparar o chip para ler sensor (ou seja, na configuração)
/ / Se você estiver usando ADCs outros além temperatura chamá-lo antes de cada leitura de temperatura
void init ();
/ / Retorna a temperatura média atual em LSB
int in_lsb ();
/ / Retorna a temperatura atual média em graus Celsius
int in_c ();
/ / Retorna a temperatura atual média em graus Fahrenheit
int in_f ();
/ / Retorna a temperatura atual média em Kelvins
int in_k ();
/ / Retorna a temperatura atual cru leitura do sensor
int-prima ();
/ / Imprime as leituras de temperatura atuais em vários formatos
anular print ();
};
# Endif / / _INTERNAL_TEMPERATURE_SENSOR_H_

InternalTemperatureSensor.pde

# Include "InternalTemperatureSensor.h"

vazio InternalTemperatureSensor :: init () {
/ AnalogReference / (INTERNAL1V1);
/ / ATTINY85 datasheet P140 (17.13.2), P137 (17,12)
/ / Configurar ADMUX
ADMUX = B1111, sensor de temperatura / / Selecione
ADMUX & = ~ _BV (ADLAR) / / resultado direito do ajuste
ADMUX | = _BV (REFS1); tensão Ref / Set /
ADMUX & = ~ (_BV (REFS0) | _BV (REFS2)) / / para 1.1V
/ / Configurar ADCSRA
ADCSRA & = ~ (_BV (ADATE) | _BV (ADIE)) / / Desativar autotrigger, Desativar interrupção
ADCSRA | = _BV (ADEN) / / Ativar ADC
ADCSRA | = _BV (ADSC); / / Inicia primeira conversão
/ Seed / amostras
int raw_temp;
enquanto (((raw_temp = raw ()) <0));
for (int i = 0; i <TEMPERATURE_SAMPLES; i + +) {
leituras [i] = raw_temp;
}
}

InternalTemperatureSensor int :: in_lsb () {
int readings_dup [TEMPERATURE_SAMPLES];
int raw_temp;
/ / Lembre-se a amostra
if ((raw_temp = raw ())> 0) {
leituras [pos] = raw_temp;
pos + +;
pos% = TEMPERATURE_SAMPLES;
}
/ / Copiar as amostras
for (int i = 0; i <TEMPERATURE_SAMPLES; i + +) {
readings_dup [i] = leituras [i];
}
/ / Extremos bolha para as extremidades da matriz
int extremes_count = TEMPERATURE_SAMPLES / EXTREMES_RATIO;
int swap;
for (int i = 0; i <extremes_count; + + i) {/ / por cento de iterações do bubble sort em pequena N funciona mais rápido do tipo Q-
for (int j = 0; j <TEMPERATURE_SAMPLES - 1; j + +) {
if (readings_dup [i]> readings_dup [i +1]) {/ / poderia ser feito com 3 XORs e não de swap se você gosta de fantasia
trocar = readings_dup [i];
readings_dup [i] = readings_dup [i +1];
readings_dup [i +1] = trocar;
}
}
}
/ Média / meio da matriz
int sum_temp = 0;
for (int i = extremes_count; i <TEMPERATURE_SAMPLES - extremes_count; i + +) {
sum_temp + = readings_dup [i];
}
voltar sum_temp / (TEMPERATURE_SAMPLES - extremes_count * 2);
}

int InternalTemperatureSensor :: in_c () {
voltar in_k () - 273;
}

InternalTemperatureSensor int :: in_f () {
voltar in_c () * 9/5 + 32;
}

InternalTemperatureSensor int :: in_k () {
voltar in_lsb () + offset;! / / para simplicty estou usando k = 1, use a próxima linha se você quiser K = 1,0
/ / Return (int) (in_lsb () * coeficiente) + offset;
}

int InternalTemperatureSensor :: cru () {
if (ADCSRA e _BV (ADSC)) {
retornar -1;
Else {}
int ret = ADCL | (ADCH << 8); / / Pega o resultado da conversão anterior
ADCSRA | = _BV (ADSC); / / Começa nova conversão
voltar ret;
}
}

InternalTemperatureSensor vazio :: print () {
Serial.print ("> R:");
Serial.print (matéria-prima (), DEC);
Serial.print ("L:");
Serial.print (in_lsb (), DEC);
Serial.print ("K:");
Serial.print (in_k (), DEC);
Serial.print ("C:");
Serial.print (in_c (), DEC);
Serial.print ("F:");
Serial.print (in_f (), DEC);
Serial.println ("#");
}

Uso

Temperatura InternalTemperatureSensor (1,0, TEMPERATURE_ADJUSTMENT) / / O argumento 1,0 é ignorado por padrão, consulte os comentários c'tor
void setup () {
temperature.init () / / Chame init () na configuração ou de cada vez depois de modificar ou ADCSRA ADMUX
}

void loop () {
/ Temperature.print / () / descomente / para depurar a saída do sensor através de conexão serial
int war_sensor_data = temperature.raw () / / Isso retorna a saída do sensor pouco utilizável
int temperature_in_celsius = temperature.in_c (); temperatura / / Isso retorna mais utilizável em graus Celsius
}

Explicação

ATtinyX5 utiliza ADC4 para leitura de dados a partir do sensor interno. No método init () toda a magia necessária com os registros é feito para preparar o sistema para ler esses dados. Você precisa chamar esse método cada vez que você deseja configurar e ADMUX ADCSRA para recuperar os dados do sensor de temperatura. Se o canal de ADC só você usar no seu programa é ADC4 o sensor de temperatura, então, você só deve chamá-lo no setup (), ou seja, uma vez. Isto reduz a temperatura, tempo de procedimento de leitura, pelo menos, por dois fatores.

Método InternalTemperatureSensor :: cru () retorna os dados brutos do sensor. Infelizmente esse dado é pouco utilizável. Para ilustrar o problema dê uma olhada na saída de InternalTemperatureSensor :: print () método de depuração. A primeira coluna é o que o sensor retorna. O débito é de aproximadamente 5 linhas por segundo, portanto, dentro de 2 segundos o sensor valores retornados com 18 graus de diferença.

ATtiny85 Internal Temperature Sensor Readouts

ATTINY85 Leituras sensor interno de temperatura


A fim de tornar este dados InternalTemperatureSensor método mais utilizável :: in_lsb não circulante média e remove os extremos da entrada. O resultado você pode ver na foto acima: a saída in_lsb marcado como L: é a forma mais utilizável. É mais preciso muito. Você pode ajustar os parâmetros de média móvel, mas no geral eu não recomendo fazer TEMPERATURE_SAMPLES menos de 20 e maior que 50. Se é menos do que 20, então o desvio cresce significativamente. Fazendo TEMPERATURE_SAMPLES superior a 50 não melhorar a precisão, mas a memória de resíduos e diminui cálculos. Também EXTREMES_RATIO define quanto de valores extremos serão cortadas, não torná-lo menos do que 2 (que vai eliminar todos os valores). Tornando-o mais do que TEMPERATURE_SAMPLES será eficaz impedir a remoção extremos das amostras.
Para além destes 3 métodos núcleo alguns utilidade in_c métodos (), in_k (), in_f () são fornecidos. Eles retornam a temperatura em graus Celsius, Fahrenheit e Kelvin.

Mais um problema com o sensor interno é que ele não está calibrado, assim, para cada chip que você precisa para usar o método print () para emitir a leitura e ajuste o segundo parâmetro do construtor para combinar esses valores com o seu termômetro calibrado. O valor -13 no código fonte só funciona para um dos meus ATtinies, não há garantia de que vai trabalhar para os outros.
Em geral, o sensor interno é utilizável, mas não espere muito dele. Sensores externos são ainda muito melhor.

Este post foi publicado em Hardware , Robótica .

Sem comentários

Nenhum comentário até o momento

Deixe uma resposta

Mapa do Site (C) Andrey Mikhalchuk, 2005-2008