tak jsem se konečně dostal k odzkoušení a vytvoření jednoduchého návodu na kontrolu teploty v domácnosti za použití 1wire sběrnice DS2482S-100 a teplotních čidel DS18B20. Pro ukládání dat jsem použil DB MySQL a ukládání je řešeno za pomocí PHP skriptu. Pro zobrazení na webu jsem použil doménu raspberry-pi.eu, kterou hostuji doma na svém Pi (mám veřejnou IP), php a java script. Další možností kontroly teplot doma, je přes chytré zařízení běžící pod systémem android (bez veřejné IP to bude fungovat pouze doma na stejné síti)
![zapojení do nepájivého p]()
zapojení do nepájivého p
1. Součástky a zapojení
- DS18B20 teplotní čidlo
- DS2482S-100 I2C na 1wire
- MS-DIP na SO-8 redukce
- 4.7 kOhm odpor
- kabely a nepájivé pole
- telefonní kabel na zavedení čidel do místností
![velikost DS2482S-100]()
velikost DS2482S-100
základním a nejtěžším úkolem je napájení sběrnice DS2482S-100 na plošňák SO-8, kterým pak můžeme vkládat do nepájivého pole
![DS2482S-100 na SO-8]()
DS2482S-100 na SO-8
dále je potřeba vše dát dohromady. V mém případě mám jedno teplotní čidlo zapojeno přímo v nepájivém poli a připraven pro napojení dalších teplotních čidel (viz. druhý obrázek níže v pravém rohu)
![zapojení do nepájivého pole]()
zapojení do nepájivého pole
![schéma zapojení]()
schéma zapojení
![zapojení do nepájivého p]()
zapojení do nepájivého p
zde je vidět, jak tam jsou navíc zapojené kabely (pro přenos dat jsem použil telefonní kabel - 4linku a jeden není použit) od ostatních čidel rozmístěných po bytě. Výhodou tohoto zapojení je, že se na jeden kabel dají napojit veškerá čidla (pokud to je jedním směrem), protože jsou zapojené do sběrnice
![zapojení]()
zapojení
2. Nainstalování a nastavení Pi
- nejprve odstraňte I2C moduly z jádra černé listiny.
Notice
sudo nano /etc/modprobe.d/raspi-blacklist.conf
zakomentujte řádek přidání „#“ na začátku řádku
Notice
#blacklist i2c-bcm2708
uzavřít a uložit soubor (CTRL+x a pak „y“ a enter)
- pro nastavení nahrání modulů při startu je potřeba upravit tento soubor
Notice
sudo nano /etc/modules
přidat tyto dva řádky
Notice
i2c-bcm2708
i2c-dev
uzavřít a uložit soubor (CTRL+x a pak „y“ a enter)
- instalace některých nástrojů pro práci s I2C
Notice
suddo apt-get install i2c-tools python-smbus
- teplotní čidlo již komunikuje a pro získání teploty je potřeba nainstalovat owfs a ow-shell balíček
Notice
apt-get install owfs ow-shell
- vytvoření adresáře, kde se potom budou ve složkách objevovat připojené teplotní čidla
Notice
sudo mkdir /mnt/1wire
- nyní je potřeba upravit soubor ows.conf
přidání „#“ na začátek řádku
Notice
#server: FAKE = DS18S20,DS2405
přidání těchto řádků na konec souboru
Notice
device = /dev/i2c-1
mountpoint = /mnt/1wire
Celsius
allow_other
error_print = 0
error_level = 0
uzavřít a uložit soubor (CTRL+x a pak „y“ a enter)
- poslední soubor, který je třeba také upravit je fuse.conf
odstranění „#“ na začátku řádku u
uzavřít a uložit soubor (CTRL+x a pak „y“ a enter)
- po těchto změnách je dobré pro jistotu udělat restart Pi
- po naběhnutí Pi se musí spustit „owfs“
- pak už stačí spustit midnight commander a doklikat se do složky /mnt/1wire/
zde jsou vidět tři adresy teplotních senzorů
![MC_mmt_1wire]()
MC_mmt_1wire
jeden si vybereme a najedeme na soubor temperature a dáme F3
![MC_mmn_1wire]()
MC_mmn_1wire
a zde je aktuální teplota na daném senzoru
![MC_mmn_1wire]()
MC_mmn_1wire
ještě je potřeba udělat jednu důležitou věc a to nastavení automatického spuštění „owfs“ po startu
na konec přidáme tento řádek
Notice
@reboot sudo -u root owfs
uzavřít a uložit soubor (CTRL+x a pak „y“ a enter)
3. Nastavení automatického ukládání dat z jednotlivých čidel do databáze MySQL pomocí PHP skriptu
nejprve se musí nainstalovat appace, mysql a php do Raspberry Pi (pokud již není nainstalováno)
Notice
sudo apt-get install apache2 php5 php5-mysql mysql-server
po instalaci a zadání hesla pro uživatele „root“ pro MySQL vytvoříme databazi „develop“
Notice
CREATE DATABASE develop;
pro ukládání dat do DB jsem zvolil dvě tabulky a jeden pohled
Notice
CREATE TABLE `teplomery` (
`rid` INT(11) NOT NULL AUTO_INCREMENT,
`nazev` VARCHAR(25) COLLATE utf8_czech_ci NOT NULL,
`adresa` VARCHAR(255) COLLATE utf8_czech_ci NOT NULL,
`stav` TINYINT(4) NOT NULL DEFAULT ’1′,
PRIMARY KEY (`rid`)
);
do této tabulky je potřeba vložit názvy a adresy teploměru
Notice
INSERT INTO teplomery (nazev,adresa) VALUES (‚obyvak_pc_stul’, ’28.869481050000′);
INSERT INTO teplomery (nazev,adresa) VALUES (‚chodba’, ’28.909581050000′);
INSERT INTO teplomery (nazev,adresa) VALUES (‚loznice’, ’28.93BB81050000′);
tabulka pro ukládání teplot
Notice
CREATE TABLE `teploty` (
`rid` INT(11) NOT NULL AUTO_INCREMENT,
`teplomer` INT(11) NOT NULL,
`teplota` DECIMAL(10,4) NOT NULL,
`InsDT` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`rid`),
KEY `FK_teplomer` (`teplomer`),
CONSTRAINT `teploty_ibfk_1` FOREIGN KEY (`teplomer`) REFERENCES `teplomery` (`rid`) ON UPDATE CASCADE
);
a pohled pro výběr dat (stav je označení pro aktivní teploměr -> 1 aktivní, 0 neaktivní)
Notice
CREATE VIEW `teploCsv` AS
SELECT
DATE_FORMAT(`a`.`InsDT`,’%Y-%m-%d %H:%i’) AS `dt`,
`b`.`rid` AS `ID`,
`b`.`nazev` AS `nazev`,
`a`.`teplota` AS `teplota`
FROM (`teploty` `a`
JOIN `teplomery` `b`
ON (((`a`.`teplomer` = `b`.`rid`)
AND (`b`.`stav` > 0))));
defaultní umístění adresáře pro www je /var/www/ kde je potřeba vytvořit PHP skript, který se napojí do DB a pak nastavení v CRONu pro automatické volání tohoto PHP skriptu, který se bude pravidelně spouštět a ukládat teploty
Notice
sudo nano temperaturesensor.php
vložíme tento skript, kde je potřeba změnit heslo pro root uživatele
Notice
<?php
/*
* Writes temperature Data to DB
*
*/
$mysqlhost=“localhost“;
$mysqluser=“root“;
$mysqlpwd=“pwd“;
$mysqldb=“develop“;
$temperatureSensorPath1 = „/mnt/1wire/28.869481050000/temperature“;
$temperatureSensorPath2 = „/mnt/1wire/28.909581050000/temperature“;
$temperatureSensorPath3 = „/mnt/1wire/28.93BB81050000/temperature“;
// — Read sensor data —
$tempSensorRawData1 = implode(“, file($temperatureSensorPath1));
$temperature1 = $tempSensorRawData1;
$tempSensorRawData2 = implode(“, file($temperatureSensorPath2));
$temperature2 = $tempSensorRawData2;
$tempSensorRawData3 = implode(“, file($temperatureSensorPath3));
$temperature3 = $tempSensorRawData3;
// — Write Data to DB —
$connection=mysql_connect($mysqlhost, $mysqluser, $mysqlpwd) or die („Could not$
mysql_select_db($mysqldb, $connection) or die(„Could not select DB!“);
$sql_query_1 = „INSERT INTO teploty (teplomer,teplota) VALUES (’1′, $temperatur$
mysql_query($sql_query_1);
$sql_query_2 = „INSERT INTO teploty (teplomer,teplota) VALUES (’2′, $temperatur$
mysql_query($sql_query_2);
$sql_query_3 = „INSERT INTO teploty (teplomer,teplota) VALUES (’3′, $temperatur$
mysql_query($sql_query_3);
?>
nastavení CRONu
vložíme tento řádek, kde je nastaveno, že skript bude do DB ukládat data každých 5 minut
Notice
*/5 * * * * php -f /var/www/temperaturesensor.php
4. Vytvoření skriptů pro zobrazení dat na webu
najedeme do adresáře pro www a zde se musejí vytvořit tři skripty. dallas.php je skript, který se bude spouštět a volat skript pro získání dat z DB dallas.csv.php a pro graf dygraph-combined.js.
první skript dallas.php
Notice
sudo nano dallas.php
vložíme tento skript a je nutné upravit na local host. (ja mám veřejnou IP a běží mi to na doméně raspberry-pi.eu)
Notice
<?php if(is_int($_GET['period'])) {
$params = “;
}
?> <html> <head>
<script type=“text/javascript“ src=“dygraph-combined.js“></script>
<style>
div {font: calibri}
</style>
<!–link rel=“stylesheet“ href=“bootstrap.min.css“>
<link rel=“stylesheet“ href=“site.css“–> </head> <body>
<div id=“graphdiv“ style=“width:1000px; height:600px; float:left“></div>
<div id=“labelsdiv“ style=““></div>
<script type=“text/javascript“>
g2 = new Dygraph(
document.getElementById(„graphdiv“),
„http://www.raspberry-pi.eu/dallas.csv.php<?php echo $params; ?>“, // p$
{// options
hideOverlayOnMouseOut: 0,
rollPeriod: 5,
showRoller: true,
labelsDiv: labelsdiv,
labelsSeparateLines: true,
legend: „always“
}
);
</script> </body>
</html>
druhý skript dallas.csv.php
Notice
sudo nano dallas.csv.php
zde je opět nutné změnit heslo
Notice
<?php
header („Content-Type:text/csv“);
isset($_GET['dtMin']) ? $dtMin = date(„Y-m-d H:i:s“, intval($_GET['dtMi$
date("Y-m-d H:i:s", time() - 86400); //den = 86400
isset($_GET['dtMax']) ? $dtMax = date(„Y-m-d H:i:s“, intval($_GET['dtMa$
date("Y-m-d H:i:s", time());
isset($_GET['T']) ? $tmer = “ AND nazev=’{$_GET['T']}‘ “ : $tmer = „“;
$db = mysqli_connect(„localhost“, „root“, „pwd“, „develop“);
mysqli_query($db, „SET NAMES UTF8″) or die(„chyba set names“);
$data = mysqli_query($db, „SELECT * FROM teploCsv WHERE dt BETWEEN ‚$dt$
‚$dtMax‘ ORDER BY nazev, dt“);
while($row = mysqli_fetch_array($data))
{
$teplomery[$row['nazev']]['nazev'] = $row['nazev'];
$teploty[$row['dt']][$row['nazev']] = $row['teplota'];
}
$nazvy = array_keys($teplomery);
$casy = array_keys($teploty);
echo ‚ďż˝as’;
foreach($nazvy as $nazev)
{
echo ‚,‘ . $nazev;
}
echo „\n“;
foreach($casy as $cas)
{
echo $cas;
foreach($nazvy as $nazev)
{
echo ‚,‘ . $teploty[$cas][$nazev];
}
echo „\n“;
}
?>
ještě poslední skript, který je potřeba vytvořit je pro zobrazení grafu
Notice
sudo nano dygraph-combined.js
a vložit tyto data dygraph-combined.js
pak už stačí jenom spustit prohlížeč */dallas.php
![www_zobrazení]()
www_zobrazení
5. Vytvoření aplikace pro Android zařízení, extrakce dat z MySQL DB za použití PHP, JSON (toto je možné za předpokladu veřejné IP na Raspberry PI, jinak bude funguvat pouze doma po připjení na domací síť)
vytvoření aplikace pomocí vývojového prostředí Eclipse. Zde v tomto skriptu je nutné změnit na vaši IP (HttpPost httppost = new HttpPost(„http://localhost/android.php“);) na Pi popřípadě na localhost - jedná se o volaný PHP skript, který vrací data ve formátu JSON (nebudu zde rozvádět krok po kroku vývoj aplikací pro android zařízení) – do tohoto skriptu byl použit font led_real, který se musí přidat do assets do projektu v eclipse
Notice
package cz.androidapk.teplota;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONObject;
import cz.androidapk.teplota.R.id;
import android.os.Bundle;
import android.os.StrictMode;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.graphics.Typeface;
import android.util.Log;
import android.view.Menu;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView resultView;
TextView resultViewTeplomer1;
TextView resultViewTeplota1;
TextView resultViewTeplomer2;
TextView resultViewTeplota2;
TextView resultViewTeplomer3;
TextView resultViewTeplota3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
//StrictMode.enableDefaults();
// Font path
String fontPath = „led_real.ttf“;
// text view label
resultView = (TextView) findViewById(id.resultView);
resultViewTeplomer1 = (TextView) findViewById(id.textViewTemplomer1);
resultViewTeplota1 = (TextView) findViewById(id.textViewTeplota1);
resultViewTeplomer2 = (TextView) findViewById(id.textViewTeplomer2);
resultViewTeplota2 = (TextView) findViewById(id.textViewTeplota2);
resultViewTeplomer3 = (TextView) findViewById(id.textViewTeplomer3);
resultViewTeplota3 = (TextView) findViewById(id.textViewTeplota3);
// Loading Font Face
Typeface tf = Typeface.createFromAsset(getAssets(), fontPath);
// Applying font
// resultViewTeplota1.setTypeface(tf, Typeface.BOLD);
resultViewTeplota1.setTypeface(tf);
resultViewTeplota2.setTypeface(tf);
resultViewTeplota3.setTypeface(tf);
StrictMode.enableDefaults();
//StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy);
getData();
}
public void getData(){
String result = „“;
InputStream isr = null;
//get data from HTTP
try{
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost(„http://localhost/android.php“);
HttpResponse response = httpclient.execute(httppost);
HttpEntity entity = response.getEntity();
isr = entity.getContent();
}catch(Exception e) {
Log.e(„log_tag“,“Error on HTTP connection “ + e.toString());
resultView.setText(„Couldnt connect to DB“);
}
//convert response string
try{
BufferedReader reader = new BufferedReader(new InputStreamReader(isr,“iso-8859-1″), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null){
sb.append(line + „\n“);
}
isr.close();
result = sb.toString();
}catch(Exception e){
Log.e(„log_tag“,“Error converting result „+ e.toString());
}
//parse json data
try{
//String s = „“;
String cas = „“;
String teplomer1 = „“;
String teplota1 = „“;
String teplomer2 = „“;
String teplota2 = „“;
String teplomer3 = „“;
String teplota3 = „“;
JSONArray jArray = new JSONArray(result);
for(int i=0; i<jArray.length(); i++){
JSONObject json = jArray.getJSONObject(i);
if (i==0){
cas = json.getString(„dt“);
teplomer1 = json.getString(„nazev“);
teplota1 = json.getString(„teplota“);
}
if (i==1){
teplomer2 = json.getString(„nazev“);
teplota2 = json.getString(„teplota“);
}
if (i==2){
teplomer3 = json.getString(„nazev“);
teplota3 = json.getString(„teplota“);
}
//s = s +
//“dt : “ + json.getString(„dt“) + „\n“ +
//“ID : “ + json.getString(„ID“) + „\n“ +
//“nazev : “ + json.getString(„nazev“) + „\n“ +
//“teplota : „+ json.getString(„teplota“)+ „\n\n“;
}
resultView.setText(cas);
resultViewTeplomer1.setText(teplomer1);
resultViewTeplota1.setText(teplota1);
resultViewTeplota1.setTextSize(80);
resultViewTeplota1.setTextColor(Color.parseColor(„#00ccff“));
resultViewTeplomer2.setText(teplomer2);
resultViewTeplota2.setText(teplota2);
resultViewTeplota2.setTextSize(80);
resultViewTeplota2.setTextColor(Color.parseColor(„#66FF00″));
resultViewTeplomer3.setText(teplomer3);
resultViewTeplota3.setText(teplota3);
resultViewTeplota3.setTextSize(80);
resultViewTeplota3.setTextColor(Color.parseColor(„#FF0033″));
}catch (Exception e){
Log.e(„log_tag“, „Error Parsing data „+ e.toString());
}
}
}
najedeme do adresáře na Raspberry Pi pro www a zde je potřeba vytvořit skript – android.php.
první skript android.php
Notice
sudo nano android.php
vložíme tento skript a je nutné upravit na localhost (já mám veřejnou IP a běží mi to na doméně raspberry-pi.eu)
Notice
<?php
$connect=mysql_connect(„localhost“,“jméno“,“heslo“) or die(„Unable $
mysql_select_db(„develop“) or die(„Could not open the db“);
$query = „SELECT * FROM teploCsv order by Dt desc, ID asc limit$
$result = mysql_query($query, $connect);
while ($row = mysql_fetch_assoc($result)) {
$output[]=$row;
}
print(json_encode($output));
mysql_close($connect);
?>
pak už stačí být připojen s telefonem k internetu a při každém spuštění aplikace se načte poslední datum aktualizace DB spolu s teplotami
![android]()
android