 ATTINY85 dispone di sensore di temperatura interna Sto lavorando su uno dei miei progetti da video blog RTFMs (check out http://rtfms.com ) che richiede di rilevamento della temperatura in un packaging molto piccolo. Naturalmente la mia scelta è ATTINY85 - un chip impressionante poco da AVR che, oltre a altri beni (come 6 canali PWM, interfaccia seriale, ecc) ha sensore di temperatura interna. Così ho deciso di utilizzare uno. Non è stato facile, ma dopo poche ore di forum e schede tecniche di scavo mi si avvicinò con una classe che fa il lavoro di affidabilità abbastanza impressionante e precisione.
Prima di tutto per eseguire questo codice è necessario un Arduino-Tiny ( http://code.google.com/p/arduino-tiny/ ) core e un qualche tipo di ISP. Sto utilizzando Arduino Duemilanove come ISP. Vedere la mia RTFMs blog per maggiori dettagli su come farlo funzionare in questo modo, come caricare nucleo corretta ecc AFAIK tutti i core popolari funzionano bene con questo codice. Ho solo recomment Arduino-Tiny a causa della sua ricca gamma di funzionalità che può essere usato per diffondere una maggiore potenza di ATTINY85. La soluzione si compone di due file che è possibile copiare nel progetto. Basta CopyPaste da questa pagina: 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 -32.767 / * * Basato su campioni: * - Il sensore di temperatura interno ha deviazione orribile. La sua uscita varia parecchio (+ / -10 gradi / sec), quindi richiede * Alcuni "smoothing". Sto eliminando i valori estremi ed in esecuzione di rotolamento avg sul resto. Questa operazione riporta ok * I risultati su 20 campioni e altro ancora. È possibile ridurre il numero di campioni per ridurre il tempo di risposta, ma questo * Diminuirà precisione. * - La linearità è ok e circa 1.0 come promesso la scheda tecnica * - La necessità di spostamento che deve essere calcolato per ogni chip fornito separatamente e in c'tor * * Per calaculate il gancio valere come terminale al pin 2 (Serial TX) 9600 8N1 e utilizzare * Temperature.print () chiamata al metodo. Questo stamperà letture di temperatura. Partita contro la vostra * Calibrato termometro attaccato al chip. Regolare Tos in c'tor se necessario. * Si veda il capitolo 17,12 del foglio dati ATTINY85 per i dettagli un po 'più * / class {InternalTemperatureSensor int offset; Coefficiente di galleggiare; letture int [TEMPERATURE_SAMPLES]; int pos; pubblico: InternalTemperatureSensor (float k, int o): offset (o), coefficiente di (k), pos (0) {} / / È chiamata ogni volta che è necessario preparare il chip per leggere sensore (cioè nel setup) / / Se si sta utilizzando altre ADC oltre la temperatura si chiama prima di ogni lettura della temperatura void init (); / / Restituisce la temperatura attuale mediato in LSB int in_lsb (); / / Restituisce la temperatura attuale mediato in gradi Celsius int in_c (); / / Restituisce la temperatura attuale mediato in gradi Fahrenheit int in_f (); / / Restituisce la temperatura attuale mediato in gradi Kelvin int in_k (); / / Restituisce la temperatura attuale prima lettura dal sensore int raw (); / / Stampa le letture di temperatura e corrente in vari formati annullare print (); }; # Endif / / _INTERNAL_TEMPERATURE_SENSOR_H_ InternalTemperatureSensor.pde # Include "InternalTemperatureSensor.h" vuoto InternalTemperatureSensor :: init () { / / AnalogReference (INTERNAL1V1); / / ATTINY85 datasheet p140 (17.13.2), P137 (17.12) / / Configura ADMUX ADMUX = B1111; / / Seleziona Sensore di temperatura ADMUX & = ~ _BV (Adlar); / / Right-regolazione risultato ADMUX | = _BV (REFS1), la tensione Ref / / Set ADMUX & = ~ (_BV (REFS0) | _BV (REFS2)); / / a 1.1V / / Configura ADCSRA ADCSRA & = ~ (_BV (aDate) | _BV (ADIE)); / / Disattiva AutoTrigger, Disabilita interrupt ADCSRA | = _BV (ADEN); / / Abilita ADC ADCSRA | = _BV (ADSC); / / Start prima conversione / / Seed campioni int raw_temp; while (((raw_temp = raw ()) <0)); for (int i = 0; i <TEMPERATURE_SAMPLES; i + +) { letture di [i] = raw_temp; } } int InternalTemperatureSensor :: in_lsb () { int readings_dup [TEMPERATURE_SAMPLES]; int raw_temp; / / Ricordo del campione if ((raw_temp = raw ())> 0) { letture [pos] = raw_temp; pos + +; pos% = TEMPERATURE_SAMPLES; } / / Copiare i campioni for (int i = 0; i <TEMPERATURE_SAMPLES; i + +) { readings_dup [i] = letture [i]; } / / Estremi bolla alla estremità della matrice int extremes_count = TEMPERATURE_SAMPLES / EXTREMES_RATIO; int swap; for (int i = 0; i <extremes_count; + + i) {/ / per cento di iterazioni di sorta bolla sulle piccole N agisce più velocemente del Q-sort for (int j = 0; j <TEMPERATURE_SAMPLES - 1; j + +) { if (readings_dup [i]> readings_dup [i +1]) {/ / potrebbe essere fatto con 3 XOR e non di swap, se volete fantasia swap = readings_dup [i]; readings_dup [i] = readings_dup [i +1]; readings_dup [i +1] = swap; } } } / / Media mezzo della matrice sum_temp int = 0; for (int i = extremes_count; i <TEMPERATURE_SAMPLES - extremes_count; i + +) { sum_temp + = readings_dup [i]; } ritorno sum_temp / (TEMPERATURE_SAMPLES - extremes_count * 2); } int InternalTemperatureSensor :: in_c () { ritorno in_k () - 273; } int InternalTemperatureSensor :: in_f () { ritorno in_c () * 9/5 + 32; } int InternalTemperatureSensor :: in_k () { ritorno in_lsb () + offset;! / / per SEMPLICITÀ sto usando k = 1, utilizzare la riga successiva se si vuole K = 1,0 / / Return (int) (in_lsb () * coefficiente) + offset; } int InternalTemperatureSensor :: raw () { if (ADCSRA & _BV (ADSC)) { return -1; Else {} int ret = ADCL | (ADCH << 8); / / Prendi il risultato precedente di conversione ADCSRA | = _BV (ADSC); / / Inizia nuova conversione ritorno ret; } } vuoto InternalTemperatureSensor :: print () { Serial.print ("> R:"); Serial.print (raw (), 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); / / L'argomento viene ignorato 1,0 per impostazione predefinita, si vedano i commenti c'tor vuoto setup () { temperature.init (); / / Chiama init () in configurazione o ogni volta che dopo aver modificato ADCSRA o ADMUX } void loop () { / / Temperature.print (); / / scommentare questa riga per eseguire il debug di uscita del sensore tramite collegamento seriale int war_sensor_data = temperature.raw (); / / Questo restituisce un output del sensore poco sfruttabili int temperature_in_celsius = temperature.in_c (); temperatura / / Questa operazione riporta più utilizzabile in gradi Celsius } Spiegazione ATtinyX5 utilizza ADC4 per leggere dati dal sensore interno. Nel metodo Init () tutto magico con la necessaria registri viene fatto per preparare il sistema di lettura di questi dati. È necessario chiamare questo metodo ogni volta che si desidera configurare ADMUX e ADCSRA per il recupero dei dati di temperatura del sensore. Se l'unico canale ADC che utilizzate nel vostro programma è ADC4 il sensore di temperatura di allora si dovrebbe chiamare solo nel setup (), vale a dire una volta. Questo riduce il tempo a leggere la temperatura procedura almeno di un fattore due. Metodo InternalTemperatureSensor :: raw () restituisce i dati grezzi provenienti dal sensore. Purtroppo questi dati sono poco sfruttabili. Per illustrare il problema di dare un'occhiata in uscita dal InternalTemperatureSensor :: print () metodo di debug. La prima colonna è ciò che il sensore ritorna. La velocità d'uscita è di circa 5 righe al secondo, quindi entro 2 secondi il sensore valori restituiti con 18 gradi di differenza.
 ATTINY85 della temperatura interna del sensore Indicatori Al fine di renderlo più fruibile InternalTemperatureSensor metodo di dati :: in_lsb fa media mobile e rimuove gli estremi dall'ingresso. Il risultato si può vedere dalla foto sopra: l'uscita in_lsb contrassegnato come L: è il modo più usabile. E 'più accurata troppo. È possibile regolare i parametri di media mobile, ma nel complesso non mi consiglia di effettuare TEMPERATURE_SAMPLES inferiore a 20 e superiore a 50. Se è inferiore a 20 allora deviazione cresce in modo significativo. Fare TEMPERATURE_SAMPLES superiore a 50 non migliora la precisione ma la memoria rifiuti e rallenta i calcoli. Anche EXTREMES_RATIO definisce la quantità di valori estremi sarà tagliato, non rendono meno di 2 (che eliminerà tutti i valori). Rendere più efficace TEMPERATURE_SAMPLES si impedisce la rimozione estremi dai campioni. Oltre a questi metodi fondamentali 3 alcuni in_c utilità metodi (), in_k (), in_f () sono forniti. Tornano temperatura in gradi Celsius, Fahrenheit e Kelvin. Un altro problema con il sensore interno che non è calibrato, quindi per ogni chip è necessario utilizzare il metodo print () per produrre la lettura e regolare il secondo parametro del costruttore per abbinare questi valori con il termometro calibrato. Il valore di -13 nel codice sorgente funziona solo per uno dei miei ATtinies, non vi è alcuna garanzia che funzionerà per gli altri. Nel complesso il sensore interno è utilizzabile, ma non aspettatevi molto da essa. I sensori esterni sono ancora molto meglio. Questo post è pubblicato in Hardware , Robotics . |