First I find the device with SDHC card mounted:
pi@raspberrypi ~ $ sudo fdisk -l Disk /dev/mmcblk0: 7969 MB, 7969177600 bytes 4 heads, 16 sectors/track, 243200 cylinders, total 15564800 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x000108cb Device Boot Start End Blocks Id System /dev/mmcblk0p1 8192 122879 57344 c W95 FAT32 (LBA) /dev/mmcblk0p2 122880 15564799 7720960 83 Linux
Now I mount a USB stick for storing a copy of the system:
pi@raspberrypi ~ $ mkdir /media/sda1 ## Assume USB stick is /dev/sda1 pi@raspberrypi ~ $ mount /dev/sda1 /media/sda1
Raw copy with dd
pi@raspberrypi ~ $ sudo dd if=/dev/mmcblk0 | gzip -1 > /media/sda1/sd_backup.img.gz ## w/o compression: pi@raspberrypi ~ $ sudo dd if=/dev/mmcblk0 of=/media/sda1/sd_backup.img ## over ssh in case there is no USB stick at hand: user@othercomputer ~ $ sudo ssh root@raspberrystar dd if=/dev/mmcblk0 | gzip -1 | dd of=sd_backup.img.gz
Note: raspberrystar
is the name of my
system---change it to appropriate IP address or name.
Restoring system image:
pi@raspberrypi ~ $ zcat sd_backup.img.gz > /dev/sdX
Where /dev/sdX
denotes the device with blank SDHC card mounted.
More details can be found here.
Copying over sshfs
:
pi@raspberrypi ~ $ sudo apt-get install sshfs fuse-utils pi@raspberrypi ~ $ mkdir -p ~/Dist/jupiter ## mounting (as user tomek) remote directory /public/raspberry at jupiter; ## mounting point is: ~/Dist/jupiter pi@raspberrypi ~ $ sshfs tomek@jupiter:/public/raspberry/ ~/Dist/jupiter failed to open /dev/fuse: Permission denied
On first try failure (as usual). Only fuse group members can read/write from/to /dev/fuse
.
User pi should be added to group "fuse":
pi@raspberrypi ~ $ sudo usermod -a -G fuse pi
To activate the modifications made in /etc/group
one should log out/log in now.
pi@raspberrypi ~ $ sshfs tomek@jupiter:/public/raspberry/ ~/Dist/jupiter pi@raspberrypi ~ $ ls -l /home/pi/Dist/jupiter total 0 ## Raw copy with dd (with compression): sudo dd if=/dev/mmcblk0 | gzip -1 > /home/pi/Dist/jupiter/raspberrystar.iso
Added 3 Oct 2012:
15564800+0 przeczytanych recordów 15564800+0 zapisanych recordów skopiowane 7969177600 bajtów (8,0 GB), 3504,04 s, 2,3 MB/s
Raw copying of 8Gb SDHC card with compression over sshfs took about 1 hr. The resulting image size is about 1,6 Gb.
It is said to overclock Raspberry Pi one has to upgrade the system:
sudo apt-get update && sudo apt-get install raspberrypi* raspi-config
Then configure it with raspi-config
utility:
sudo raspi-config
It is good anyhow to check the system version first:
uname -a Linux raspberrystar.pinkaccordions.org 3.2.27+ #174 PREEMPT Wed Sep 26 14:09:47 BST 2012 armv6l GNU/Linux
The kernel is up to date. Inspecting raspi-config
I have discovered
it is not updated, but I prefer to configure the system via CLI (command line or console) interface
rather than GUI one (no need to connect the RPi to a TV set which is in another room:-).
So I decided not to upgrade the system but rather manually configure it.
To achieve overclocking one has to add the following lines to
/boot/config.txt
file:
pi@raspberrystar ~ $ sudo vim /boot/config.txt ## add the following: temp_limit=80 arm_freq=900 sdram_freq=500
Now reboot:
pi@raspberrystar ~ $ sudo reboot
Check the dmesg
:
pi@raspberrystar ~ $ dmesg | grep 7000 [ 1.956412] bcm2835-cpufreq: min=700000 max=900000 cur=700000
CPU frequency is still 700Mhz. To increase it one has to
edit scaling_governor
file:
pi@raspberrystar ~ $ sudo bash root@raspberrystar:/home/pi# echo "performance" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor ## check if the above works:-) pi@raspberrystar ~ $ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor performance # display available options: pi@raspberrystar ~ $ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors conservative ondemand userspace powersave performance
The ondemand
option
allows for adjusting CPU frequency depending
on CPU utilization.
Without any further reboot the new settings work:
# check current CPU frequency pi@raspberrystar ~ $ cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq 900000
There is even a temperature sensor available so one can check if the CPU is not overheated:
# check processor temperature: pi@raspberrystar ~ $ /opt/vc/bin/vcgencmd measure_temp temp=46.5'C
To boot the system with scaling_governor
set to appropriate
value one has to edit /etc/rc.local
:
pi@raspberrystar ~ $ sudo vim /etc/rc.local # Add the following line # echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
I have performed a simple test:
#!/bin/bash # N=5 START=$(date +%s) for ((i=1;i<=$N;i++ )) ; do echo "**** Iteration $i ****" STARTI=$(date +%s) perl -e 'for ($i=0;$i<=10000000;$i++) { $s .= "xx"; }' ENDI=$(date +%s) ; TOTALI=$(( $ENDI - $STARTI )) echo "*** $TOTALI s." done END=$(date +%s) TOTAL=$(( $END - $START )) MEAN=`awk -v m=$TOTAL -v n=$N 'BEGIN { print m/n }'` echo "total: " $TOTAL "mean: " $MEAN ##
The test uses the following perl program:
perl -e 'for ($i=0;$i<=10000000;$i++) { $s .= "xx"; }'
Because computing time can vary, the program has to be run N
times
and the mean time is reported.
My Rpi runs 28--29s at 700 Mhz, 25,8s at 800 Mhz and 21s at 900 Mhz.
So running at 900 Mhz results in almost 30% reduction of computing time.
Do wykonania instalacji potrzebne są:
Czujnik DHT-22 temperatury/wilgotności (ok. 30 zł za sztukę). Droga sprawa...
REZYSTOR 0,25W 10K OHM węglowy (1,00 zł za 100 sztuk na Allegro).
Do tego: przewody połączeniowe żeńskie, przewód telefoniczny czterożyłowy lub inny podobny, kostka elektryczna oraz rurka termokurczliwa do izolacji i wzmocnienia połączeń. (Por. Raspberry Pi: magistrala 1-Wire i rejestracja temperatury.)
UWAGA: tańszą wersja DHT-22 jest DHT-11 (aka SHT-11). Połasiłem się nawet na takowy, bo taniej ale nie polecam. Przede wszystkim mierzy temperaturę w przedziale od 0C do 50C (z kiepską dokładnością +/- 2C) więc nie nadaje się do pomiaru temperatury zewnętrznej. Do tego odczyt wilgotności jest zaniżony i nie działa podłączony do niektórych pinów GPIO (być może jest to problem oprogramowania, którego używam). Dla porównania DHT-22 mierzy temperaturę w przedziale od -40C do +80C z dokładnością +/- 0,5C.
Na stronie learn.adafruit.com znajduje się tutorial, z którego korzystałem...
Sensor DHT-22 ma cztery piny (por. rys #1). Podłączyłem linie danych (DQ) do pinów P22, P24 i P25 (każdy sensor musi mieć oddzielną linię danych). Vdd każdego sensora do pina P1 (zasilanie 3,3V). GND (masa) każdego czujnika do pina P6. Ponadto każde DQ należało połączyć za pomocą rezystora z linią zasilania Vdd.
Pin Null nie jest wykorzystywany.
Lutowanie i łączenie wszystkiego do kupy wykonałem w sposób identyczny (kostka elektryczna, rurka termokurczliwa itp.) z opisanym bardziej szczegółowo we wpisie Raspberry Pi: magistrala 1-Wire i rejestracja temperatury.
Pobieram, kompiluję i instaluję niezbędną bibliotekę:
pi@raspberrystar $ wget http://www.open.com.au/mikem/bcm2835/bcm2835-1.8.tar.gz pi@raspberrystar $ tar -zxvf bcm2835-1.8.tar.gz pi@raspberrystar $ cd bcm2835-1.8 pi@raspberrystar $ ./configure && make && sudo make install
Pobieram program do obsługi czujników:
pi@raspberrystar $ git clone https://github.com/adafruit/Adafruit-Raspberry-Pi-Python-Code.git pi@raspberrystar $ cd Adafruit-Raspberry-Pi-Python-Code pi@raspberrystar $ cd Adafruit_DHT_Driver
W pliku Makefile należy dopisać -l rt
na końcu wiersza
zaczynającego się od CFLAGS
:
CFLAGS = -std=c99 -I. -lbcm2835 -l rt
teraz:
## w katalogu Adafruit_DHT_Driver pi@raspberrystar $ make
Jeżeli wszystko działa, to:
# Uruchomienie ./Adafruit_DHT typ-czujnika nr-pina-DQ pi@raspberrystar $ sudo ./Adafruit_DHT 22 25 Using pin #25 Data (40): 0x3 0xe7 0x0 0x17 0x1 Temp = 2.3 *C, Hum = 99.9 %
W katalogu Adafruit_DHT_Driver znajduje się też skrypt Pythona
pn. Adafruit_DHT_googledocs.ex.py
służący do wysyłania odczytanych danych do arkusza
google.docs. Skrypt Adafruit_DHT_googledocs.ex.py
do działania potrzebuje modułu gspread
:
pi@raspberrystar $ wget http://pypi.python.org/packages/source/g/gspread/gspread-0.0.13.tar.gz pi@raspberrystar $ tar -zxvf gspread-0.0.13.tar.gz pi@raspberrystar $ cd gspread pi@raspberrystar $ sudo python setup.py install
Skrypt Pythona Adafruit_DHT_googledocs.ex.py
:
1) w nieskończonej pętli uruchamia co 30 sekund program
Adafruit_DHT
,
2) wyłuskuje z wydruku wartości temperatury/wilgotności, 3) wysyła co trzeba
na google.docs. Fragment skryptu wygląda następująco:
while(True): output = subprocess.check_output(["./Adafruit_DHT", "2302", "4"]); print output # search for humidity printout matches = re.search("Hum =\s+([0-9.]+)", output) if (not matches): time.sleep(3) continue humidity = float(matches.group(1)) ## pominięty kod ... time.sleep(30)
Ponieważ ja chcę oprócz wysłania na google.docs coś tam jeszcze zrobić z danymi,
to miałem do wyboru albo rozbudować Adafruit_DHT_googledocs.ex.py
o dodatkową
funkcjonalność albo go uprościć. Wybrałem to drugie:
moja wersja Adafruit_DHT_googledocs.ex.py
ogranicza się wyłącznie do wysłania
na google.docs wartości przekazanych jako argumenty wywołania:
temp = float(sys.argv[1]) humidity = float(sys.argv[2]) ## pominięty kod ...
Resztą zajmie się poniższy skrypt basha:
#!/bin/bash # LOG_DIR=/home/pi/Logs/DHT BIN_DIR=/home/pi/bin SENSTYPE=22 SLEEP_TIME=5 function ReadSensor() { local sensorType="$1" local sensorId="$2" local WYNIK="" local SUCCESS="" ## zwiększyłem powtórzenia do 5 (sleep zmniejszony do 5s/było 10) for i in 1 2 3 4 5; do WYNIK=`sudo $BIN_DIR/Adafruit_DHT $sensorType $sensorId | tr '\n' ' '` SUCCESS=`echo $WYNIK | awk ' { if (NF > 10) {print "YES"} else { print "NO"}}'` if [ "$SUCCESS" = "YES" ] ; then echo "$sensorId=$i $WYNIK" >> $LOG_DIR/DHT22.log DHT_CURR_TEMP=`echo $WYNIK | awk '{print $13}'` DHT_CURR_HUM=`echo $WYNIK | awk '{print $17}'` break fi sleep $SLEEP_TIME; done ## Wszystkie próby okazały się nieudane if [ $SUCCESS = "NO" ] ; then echo "$sensorId=? $WYNIK" >> $LOG_DIR/DHT22.log DHT_CURR_TEMP="999.9" DHT_CURR_HUM="999.9" fi } echo "@`date "+%Y%m%d%H%M%S"`" >> $LOG_DIR/DHT22.log ## Czujnik w pokoju: ReadSensor $SENSTYPE "24" READINGS="$DHT_CURR_TEMP $DHT_CURR_HUM" sleep 12 ## Czujnik na zewnątrz: ReadSensor $SENSTYPE "25" READINGS="$READINGS $DHT_CURR_TEMP $DHT_CURR_HUM" sleep 12 ## Czujnik weranda: ReadSensor $SENSTYPE "22" READINGS="$READINGS $DHT_CURR_TEMP $DHT_CURR_HUM" ## zamiana na HTML + wykres /usr/bin/perl /home/pi/bin/dht2ht.pl > /var/www/stats/DHT22.html # Wyslanie na google /home/pi/bin/DHT_googledocs.ex.py $READINGS
Podobnie jak w przypadku magistrali 1-Wire zdarzają się problemy
z odczytaniem wartości czujnika. Na tą okoliczność funkcja ReadSensor
próbuje
odczytu kilkukrotnie. Maksymalna nieudana liczba prób, którą zaobserwowałem
w ciągu kilkudniowej eksploatacji to 3.
Skrypt jest uruchamiany co 30 min przez crona:
1,31 * * * * /home/pi/bin/dht2ht.sh
Plik LOG
wygląda jakoś tak:
@20121113230101 24=1 Using pin #24 Data (40): 0x2 0x22 0x0 0xc9 0xed Temp = 20.1 *C, Hum = 54.6 % 25=1 Using pin #25 Data (40): 0x3 0xe7 0x0 0x1c 0x6 Temp = 2.8 *C, Hum = 99.9 % 22=4 Using pin #22 Data (40): 0x2 0x73 0x0 0xb0 0x25 Temp = 17.6 *C, Hum = 62.7 %
Wiersz zaczynający się od @
zawiera datę i czas
odczytu. Wiersze zaczynające się od nn=m zawierają odczytane
dane (nn to numer czujnika, m numer próby w której
odczytano wartości lub ?
jeżeli wszystkie próby były
nieudane)
Uwaga: zauważyłem, że przy intensywnych operacjach I/O są duże problemy z odczytaniem wskazań czujników.
Perlowy skrypt dht2ht.pl
tworzy tabelę oraz wykresy prezentujące odczytane
wartości plus obliczoną na ich podstawie
temperaturę punktu rosy.
Rezultat działania można
oglądać tutaj.
Omawiane w tym wpisie skrypty są
zaś tutaj.
Arkusz google.docs zawierający odczyty z moich trzech czujników jest
dostępny tutaj.
(Uwaga: z jakiś ważnych powodów skrypt Adafruit_DHT_googledocs.ex.py
zaczął dopisywanie
danych od 162 wiersza arkusza.)
W temacie kopii zapasowej na stronach poświęconych Raspberry Pi znaleźć można wyłącznie(?)
opisy jak to zrobić za pomocą dd
. Ten sposób nie podoba mi się
na dłużą metę z uwagi na czas -- kopiowanie karty 8Gb z kompresją przez sshfs zajęło
około 1 godziny. Tworzenie kopii przyrostowych (za pomocą rsync
) wydaje się lepszym pomysłem...
Załóżmy, że do /etc/fstab
wpisano:
/dev/disk/by-id/usb-WD_5000AAV_External_57442D574341535535303634313031-0:0-part1 \ /mnt/external-disk ext4 noauto,user,rw 0 0
Utworzenie kopii systemu sprowadza się wykonania:
rsync -av --exclude=/proc/ --exclude=/sys/ --exclude=/tmp/ \ --exclude=/mnt/ --exclude=/home/pi/Dist/ --delete / /mnt/external-disk/backup/rpi
Opcja --exclude
pomija wymienione pliki/katalogi. W szczególności należy
koniecznie umieścić tam katalogi, w których są/mogą być montowane inne systemy plików,
np. /mnt/
(uniknięcie pętli, bo przecież /mnt/
zawiera zamontowany dysk USB)
oraz /home/pi/Dist/
(moje zwyczajowe miejsce montowania systemów plików przez sshfs
)
Kopia systemu z raspberry będzie tworzona na innym komputerze dostępnym poprzez sieć.
Konfigurowanie rsynca
należy rozpocząć od jego zainstalowania na obu
komputerach (źródłowym i odbiorcy):
apt-get install rsync
Zawartość pliku /etc/rsyncd.conf
po stronie źródła (czyli raspberry):
uid = 0 gid = 0 hosts allow = 192.168.1.*** transfer logging = no read only = yes [wholefs] path = / comment whole root fs
W pliku /etc/default/rsync
(także po stronie źródła,
tj. raspberry) należy wpisać lub ,,odhaszować'':
RSYNC_ENABLE=true
Teraz trzeba wystartować rsync
(po ustawnieniu RSYNC_ENABLE
, rsync
będzie już uruchamiany
w momencie startu systemu -- nie potrzeba
do tego żadnych dodatkowych zabiegów w konfiguracji)
# /etc/init.d/rsync restart
Można sprawdzić czy działa
podając polecenie (moje raspberry nazywa się raspberrystar)
na komputerze odbiorcy (jako root
):
rsync raspberrystar::wholefs/
Jeżeli wszystko jest OK to wyświetlona zostanie zawartość katalogu /
na raspberrystar (czyli źródle).
Utworzenie kopii systemu sprowadza się wykonania:
rsync -av --exclude=/proc/ --exclude=/sys/ --exclude=/tmp/ \ --exclude=/mnt/ --exclude=/home/pi/Dist/ --delete \ raspberrystar::wholefs/ /public/sheeva/backup/raspberrystar/rootfs
W razie potrzeby kopia może być szybko przeniesiona na inną kartę SDHC.
# uwaga: nazwy katalogów odpowiadają wariantowi #2 tworzenia kopii: rsync -av --log-file=rsync_`date +%Y%m%d%H`.log --delete \ /public/sheeva/backup/raspberrystar/rootfs/ /public/sdX
Gdzie /public/sdX
oznacza miejsce zamontowania karty SDHC.
Karta musi być wcześniej sklonowana z ,,pierwszej'' kopii systemu wykonanej za pomocą dd
, tj.:
zcat sd_backup.img.gz > /dev/sdX
Teraz można gdybać czy użycie samego dd
nie będzie prostsze. Być może -- ja wolę korzystać
na co dzień z rsynca
.
Zauważyłem, że przy intensywnych operacjach I/O są problemy z odczytem
danych przez GPIO (temperatura/wilgotność).
Problem nie jest duży, ponieważ tworzenie pierwszej kopii systemu zajęło mi jakieś 20 min
(można się spodziewać, że kolejne będą tworzone w ciągu kilku minut),
ale dla większej pewności dodałem ionice
i --bwlimit
(specjalnie tego nie testując, oprócz sprawdzenia, że działa)
ionice -c3 rsync -av --bwlimit=500 --exclude=/proc/ --exclude=/sys/ --exclude=/tmp/ \ --exclude=/mnt/ --exclude=/home/pi/Dist/ --delete \ raspberrystar::wholefs/ /public/sheeva/backup/raspberrystar/rootfs
Jeżeli powyższe zapisane zostanie do skryptu, np. o nazwie backup_raspberry.sh
,
to teraz aby ten skrypt był uruchamiany raz na tydzień, np. w niedzielę o 4:00
należy wpisac do pliku crontab (na komputerze odbiorcy) coś takiego:
0 4 * * 7 /root/bin/backup_raspberry.sh >> /root/logs/RSync/RSync.log 2>&1