Monitorizarea temperaturii în sala serverelor
Urmărirea condițiilor de bună funcționare într-o incintă destinată serverelor sau oricăror sisteme de calcul cu funcționare continuă reprezintă o funcționalitate importantă. În cadrul proiectului de față vom prezenta un sistem de monitorizare a temperaturii într-o astfel de incintă.
Sistemul de măsurare va fi construit pe baza unei plăci de dezvoltare A-Star 32U4 Micro dar se poate folosi orice altă placă bazată pe microcontrolerul ATmega 32U4 (precum Arduino Leonardo). În plus se va utiliza un senzor de temperatură analogic brick și un afișaj LCD 16×2 cu conectare I2C. Sistemul va funcționa ca termometru de perete (va afișa temperatura ambientală pe afișajul LCD propriu) și ca senzor USB de temperatură pentru un server. Soluția propusă este mult mai ieftină decât soluțiile comerciale prezente pe piață (a se vedea produsele LinkUSB – 1-Wire USB Interface, LinkUSBi – 1-Wire USB Interface, GO-TEMP). Schema de interconectare între componentele sistemului este următoarea:
Atât senzorul de temperatură cât și afișajul LCD se vor alimenta la 5V. Senzorul de temperatură va avea ieșirea (pinul OUT) conectat la pinul A0 al plăcii de dezvoltare. Afișajul LCD (modulul I2C al afișajului) va avea pinul SCL conectat la pinul 3 al plăcii de dezvoltare și pinul SDA la pinul 2.
Programul a fost dezvoltat utilizând Arduino IDE 1.8.5 și biblioteca LiquidTWI 1.5.1.
#include <Wire.h>
#include <LiquidTWI.h>
LiquidTWI lcd(0);
Variabila globală aprins va memora starea luminii de fundal pentru afișajul LCD. Funcția readTempInCelsius va efectua citirea senzorului de temperatură (citirea constă într-un număr de achiziții analogice returnându-se media eșantionărilor efectuate).
boolean aprins;
float readTempInCelsius(int count, int pin) {
float temperaturaMediata = 0;
float sumaTemperatura = 0;
if (aprins) lcd.setBacklight(LOW);
for (int i =0; i < count; i++) {
int reading = analogRead(pin);
float voltage = reading * 5.0;
voltage /= 1024.0;
float temperatureCelsius = (voltage – 0.5) * 100 ;
sumaTemperatura = sumaTemperatura +
temperatureCelsius;
}
if (aprins) lcd.setBacklight(HIGH);
return sumaTemperatura / (float)count;
}
Secțiunea setup() inițializează conexiunea serială și comunicația I2C cu afișajul LCD. Inițial lumina de fundal a afișajului va fi oprită.
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
aprins = false;
lcd.setBacklight(LOW);
lcd.setCursor(0,0);
lcd.print(„Temperatura:”);
}
În secțiunea loop() se citește temperatura și se afișează pe ecranul LCD la un interval de o secundă. În cazul primirii caracterului t pe serială se va trimite înapoi valoarea temperaturii în acel moment. Tot pe serială se vor putea recepționa comenzi de aprindere sau stingere a iluminatului de fundal pentru ecranul LCD (caracterele h și l).
void loop() {
int t;
t = Serial.read();
float temperatura = readTempInCelsius(10,0);
if (t==’t’) Serial.println(temperatura);
if (t==’h’) { lcd.setBacklight(HIGH); aprins = true; }
if (t==’l’) { lcd.setBacklight(LOW); aprins = false; }
lcd.setCursor(0,1);
lcd.print(temperatura); lcd.print(” C”);
delay(1000);
}
Sistemul se va conecta la un server Linux care va citi periodic temperatura ambientală și o va transmite spre înregistrare către serviciul Robofun IoT. Testele au fost realizate pe un server Linux rulând distribuția CentOS 5.11. Pentru citirea și înregistrarea temperaturii s-a utilizat următorul script bash:
#! /bin/bash
t1=$(sensors | grep „Core 0” | sed ‘s/.*:\s*+\(.*\) .*(.*/\1/’)
t1=${t1:0:2}
curl -X GET ‘http://iot.robofun.ro/api/v1/senzor/…/input?value=’$t1 > /dev/null 2>&1
modprobe cdc_acm
echo „0x1ffb 0x2300” > /sys/bus/usb/drivers/cdc_acm/new_id
stty -F /dev/ttyACM0 9600
echo „t” >/dev/ttyACM0
read -r t2 < /dev/ttyACM0
curl -X GET ‘http://iot.robofun.ro/api/v1/senzor/…/input?value=’$t2 > /dev/null 2>&1
t1=$(($t1+0))
if [ $t1 -gt 45 ]
then
echo „h” >/dev/ttyACM0
else
echo „l” >/dev/ttyACM0
fi
În cadrul scriptului trebuie personalizate cheile de autentificare pentru cele două valori înregistrate pe serviciul Robofun IoT. Acestea se obțin prin înregistrare gratuită. Pentru a fi rulat în mod automat scriptul va fi trecut în fișierul de configurare /etc/crontab (scriptul va fi rulat la intervale de o oră, se presupune că scriptul a fost salvat sub numele temperature.sh în directorul /root):
# cpu temperature
05 * * * * root /root/temperature.sh
Scriptul va realiza două citiri:
- În variabila t1 se va salva temperatura nucleului 0 (testele au fost realizate pe o arhitectură multinucleu). Pentru a citi temperatura nucleului s-a utilizat utilitarul sensors. După extragerea temperaturii din informațiile oferite de utilitar aceasta va fi postată pe platforma Robofun IoT.
- În variabila t2 se va salva temperatura temperatura ambientală primită de la senzorul extern USB. Pentru instalarea software a senzorului trebuie să avem în vedere două aspecte:
- Placa A-Star 32U4 Micro este posibil să fie identificată greșit de sistemul de operare Linux. Este nevoie să aplicăm patch-ul oferit de producătorul plăcii de dezvoltare.
- Distribuția CentOS 5.11 (pe care s-au realizat testele) este destul de veche. Din acest motiv placa de dezvoltare nu este recunoscută și nu este încărcat în mod automat modulul de nucleu necesar. Din acest motiv vom încărca în mod forțat modulul CDC_ACM (modprobe cdc_acm) și vom forța identificarea plăcii de baza identificatorului USB – VID PID (echo „0x1ffb 0x2300” > …). Pe o distribuție Linux mai nouă este foarte probabil să nu fie necesare aceste comenzi.
Scriptul configurează conexiunea serială (viteză de comunicație 9600bauds), trimite comanda t, citește valoarea temperaturii și o trimite spre înregistrare către platforma Robofun IoT.
În final scriptul folosește posibilitatea de comandă serială a iluminatului de fundal a LCD-ului senzorului de temperatură extern USB pentru a semnaliza o temperatură mai mare de 45 de grade pentru nucleul 0. Bineînțeles, sistemul poate fi îmbunătățit pentru a afișa temperatura procesorului serverului – să devină afișaj extern pentru monitorizarea temperaturii procesorului.