Paweł Szabaciuk, Autor w serwisie Paweł Szabaciuk

Paweł Szabaciuk

Software Developer

Author: Paweł Szabaciuk (page 1 of 3)

Monitoring środowiska w domu – schemat i płytka

Tak to wygląda jeśli chodzi o czujnik:

Monitoring środowiska w domu – podsumowanie po kilku miesiącach

Od uruchomienia monitoringu minęło już trochę czasu.
W międzyczasie przerobiłem szablon dla strony na trochę bardziej kolorowy.
Dodałem też filtrowanie danych po datach dla dni oraz miesięcy.
Same czujniki działają nadzwyczaj dobrze. Niestety kupiłem zestaw baterii słabej klasy, przez co czujniki potrafią się zawiesić przy wysyłce danych. Baterie po prostu nie podają odpowiedniego prądu, nie pomaga też jeden mały kondensator na linii zasilania. Powoduje to reset układu w czasie wysyłki danych.
Pierwsze baterie które miałem, pracują do dzisiaj. Dzisiaj przy nowych płytkach na pewno dodałbym więcej kondensatorów na zasilaniu, żeby podtrzymać ładunek niezbędny do wysyłki danych. Powinno to pomóc na problemy ze słabymi bateriami.
Zużycie prądu to ok. 3uA w spoczynku. W czasie nadawania 30mA zabiera układ RF, w czasie odbioru danych 15mA, 300uA pobiera czujnik w czasie pracy i reszta układu w granicach 3mA.
Jeśli chodzi o jednostkę centralną, to działa bez restartu od listopada (podmianka usług z poprawkami).
Projekt uważam więc za zadowalający.
Muszę dorobić w wolnej chwili czujniki dla reszty pomieszczeń oraz myślę ciągle nad czujnikiem jakości powietrza.

Poniżej kilka screenów z nowej szaty graficznej:

Monitoring środowiska w domu – wersja działająca

W końcu (w połowie sierpnia :p) udało mi się uruchomić system do monitoringu danych środowiskowych.
Koncepcja w stosunku do pierwotnej trochę się zmieniła, przez co centralką zbierającą i przechowującą dane jest Raspberry Pi.
Hosting zapewnia NodeJS wraz z ExpressJS. Dane zbierane są do bazy danych SQLite.
Całość chodzi stabilnie od prawie miesiąca.
Czujniki się nie zmieniły (chociaż kolejna wersja będzie poprawiona, antena wzdłuż baterii, czujnik od strony baterii a nie procesora).
Do RPi podpięty jest wygrzebany z otchłani śmieci na biurku wyświetlacz OLEDowy. Wyświetla bieżące dane.

Poniżej kilka screenów z hostingu:

WiringPi (like) obsługa przerwań

Dzisiaj zajmę się poprawną obsługą oczekiwania na przerwanie, jeśli przerwania oparte są na poll (czyli biblioteka WiringPi i klony).
W czym jest problem?
Otóż poll chodzi sobie w drugim wątku. Jest to metoda nie obciążająca procesora. Samo poll nie zużywa mocy obliczeniowej. Natomiast większość przykładów, które widziałem, oparte są na pętli nieskończonej, oczekującej na wystąpienie przerwania. Co powoduje, że ta pętla obciąża nam procesor w 100%.
Przykład takiego użycia:

 C++ | 
 
 copy code |
?

01
bool packetAvailable = false;         
02
 
03
void signalsInterrupt(void) 
04
{
05
	packetAvailable = true;
06
}
07
 
08
int main(int argc, char *argv[])
09
{
10
	wiringPiSetup();
11
 
12
	pinMode(GDO2, INPUT);
13
	pullUpDnControl(GDO2, PUD_UP);
14
 
15
	wiringPiISR(GDO2, INT_EDGE_FALLING, &signalsInterrupt);
16
 
17
	while (1)
18
	{
19
		if (packetAvailable) 
20
		{
21
			(...)
22
		}
23
	}
24
 
25
	return 0;
26
}

Mało eleganckie, nieprawdaż?
Z pomocą przychodzą nam mechanizmy do obsługi wątków, jak np. semafory.
A oto poprawny przykład, zużywający ~0% procesora:

 C++ | 
 
 copy code |
?

01
static sem_t interrupt;
02
 
03
void signalsInterrupt(void) 
04
{
05
	sem_post(&interrupt);
06
}
07
 
08
int main(int argc, char *argv[])
09
{
10
	wiringPiSetup();
11
 
12
	pinMode(GDO2, INPUT);
13
	pullUpDnControl(GDO2, PUD_UP);
14
 
15
	sem_init(&interrupt, 0, 0);
16
	wiringPiISR(GDO2, INT_EDGE_FALLING, &signalsInterrupt);
17
 
18
	while (1)
19
	{
20
		sem_wait(&interrupt);
21
 
22
		(...)
23
	}
24
 
25
	return 0;
26
}

Kod działa następująco. sem_init definiuje nam semafor obsługujący przerwanie. Callback signalsInterrupt wywoływany jest przez wątek obsługujący przerwanie (ten z poll). Tutaj ustawiany jest semafor. W pętli głównej while(1) oczekujemy na ustawienie semafora. Wszystko bez zużycia procesora.

Monitoring środowiska w domu

Jak pisałem wcześniej (tu i tu) pracuję nad prywatnym projektem. Projekt ten zakłada sieć czujników i układów wykonawczych.

Komunikacja odbywać się będzie przy użyciu fal radiowych na częstotliwości 433MHz.

Czujniki mają być zasilane z baterii CR2032 i działać minimum rok na nowej baterii.

Układów wykonawczych póki co nie mam, mam natomiast zestaw mini czujników opatych na SHT21. Co daje nam możliwość monitorowania temperatury i wilgotności na danym obszarze.

Cześć centralna oparta jest o ESP32. Udostępniać będzie stronę WWW z danymi zebranymi przez czujniki. Dane zapisywane będą na karcie SD. Dodatkowo na bieżąco wyświetlane dane będą na wyświetlaczu LCD.

Stan prac jest marny na dzień dzisiejszy. Czujniki są gotowe i oprogramowane, natomiast część centralna dopiero się kompletuje.

Visual GDB na platformie embedded linux segmentation fault przy starcie

Jeśli przy starcie sesji debugowej dostajemy komunikat:

To znaczy że musimy doinstalować symbole debugowe:

 Bash | 
 
 copy code |
?

1
apt install libc6-dbg

I to wszystko 🙂

NanoPi Air wyłaczenie monitora

Ponieważ i tak nie mamy złącza HDMI, warto zaoszczędzić te kilkaset miliamperów:

 Bash | 
 
 copy code |
?

1
nano /boot/boot.scr

 Bash | 
 
 copy code |
?

1
setenv video-mode "monitor=none"

 Bash | 
 
 copy code |
?

1
mkimage -C none -A arm -T script -d /boot/boot.cmd /boot/boot.scr

Kernel mainline i edycja dtb

NanoPI Neo Air to bardzo przyjemna płytka systemu embedded.
Pojawiła się potrzeba uruchomienia na tym maleństwie drivera do magistrali CAN.
O ile w dystrybucji ARMBIAN jest wszystko co potrzeba, czyli moduł w kernelu, o tyle problemem okazało się uruchomienie modułu.
Konfigurację (częstotliwość kwarcu dla MCP2515, IRQ) musiałem nadpisać dtb uwzględniając mój hardware.

Pierwszą rzeczą jaką zrobiłem, jest kopii zapasowa konfiguracji. Tak na wszelki wypadek.
Potem skopiowałem plik dtbo do katalogu użytkownika i zdekompilowałem go:

 Bash | 
 
 copy code |
?

1
dtc -I dtb -O dts sun8i-h3-spi0-mcp2515.dtbo > sun8i-h3-spi0-mcp2515.dts

Następnie wyedytowałem…

 Bash | 
 
 copy code |
?

1
nano sun8i-h3-spi0-mcp2515.dts

…do następującej postaci:

 Bash | 
 
 copy code |
?

01
/dts-v1/;
02
 
03
/ {
04
        compatible = "allwinner,sun8i-h3";
05
 
06
        fragment@0 {
07
                target-path = "/aliases";
08
 
09
                __overlay__ {
10
                        spi0 = "/soc/spi@01c68000";
11
                };
12
        };
13
 
14
        fragment@1 {
15
                target-path = "/clocks";
16
 
17
                __overlay__ {
18
                        #address-cells = <0x1>;
19
                        #size-cells = <0x1>;
20
 
21
                        can0_osc_fixed {
22
                                compatible = "fixed-clock";
23
                                #clock-cells = <0x0>;
24
                                #częstotliwość kwarcu:
25
                                clock-frequency = <16000000>;
26
                                linux,phandle = <0x2>;
27
                                phandle = <0x2>;
28
                        };
29
                };
30
        };
31
 
32
        fragment@2 {
33
                target = <0xffffffff>;
34
 
35
                __overlay__ {
36
 
37
                        can0_pin_irq@0 {
38
                                #pin z podpiętym IRQ
39
                                allwinner,pins = "PG11";
40
                                allwinner,function = "irq";
41
                                allwinner,drive = <0x0>;
42
                                allwinner,pull = <0x1>;
43
                                linux,phandle = <0x1>;
44
                                phandle = <0x1>;
45
                        };
46
                };
47
        };
48
 
49
        fragment@3 {
50
                target = <0xffffffff>;
51
 
52
                __overlay__ {
53
                        status = "okay";
54
                        #address-cells = <0x1>;
55
                        #size-cells = <0x0>;
56
 
57
                        mcp2515@0 {
58
                                reg = <0x0>;
59
                                compatible = "microchip,mcp2515";
60
                                pinctrl-names = "default";
61
                                pinctrl-0 = <0x1>;
62
                                spi-max-frequency = <0x989680>;
63
                                interrupt-parent = <0xffffffff>;
64
                                interrupts = <0 203 2>;
65
                                clocks = <0x2>;
66
                                status = "okay";
67
                                linux,phandle = <0x3>;
68
                                phandle = <0x3>;
69
                        };
70
                };
71
        };
72
 
73
        __symbols__ {
74
                can0_osc_fixed = "/fragment@1/__overlay__/can0_osc_fixed";
75
                can0_pin_irq = "/fragment@2/__overlay__/can0_pin_irq@0";
76
                can0 = "/fragment@3/__overlay__/mcp2515@0";
77
        };
78
 
79
        __fixups__ {
80
                pio = "/fragment@2:target:0", "/fragment@3/__overlay__/mcp2515@0:interrupt-parent:0";
81
                spi0 = "/fragment@3:target:0";
82
        };
83
 
84
        __local_fixups__ {
85
 
86
                fragment@3 {
87
 
88
                        __overlay__ {
89
 
90
                                mcp2515@0 {
91
                                        pinctrl-0 = <0x0>;
92
                                        clocks = <0x0>;
93
                                };
94
                        };
95
                };
96
        };
97
};

Na koniec ponowna kompilacja i skopiowanie do katalogu źródłowego:

 Bash | 
 
 copy code |
?

1
dtc -O dtb -o sun8i-h3-spi0-mcp2515.dtbo -b 0 sun8i-h3-spi0-mcp2515.dts && cp sun8i-h3-spi0-mcp2515.dtbo /boot/dtb/overlay/

Dodałem jeszcze obsługę do pliku armbianEnv:

 Bash | 
 
 copy code |
?

1
nano /boot/armbianEnv.txt

 Bash | 
 
 copy code |
?

1
verbosity=7
2
logo=disabled
3
console=both
4
disp_mode=1920x1080p60
5
overlay_prefix=sun8i-h3
6
rootdev=UUID=abdc65e6-2e32-4a5f-9a19-56c01c6bdb23
7
rootfstype=ext4
8
overlays=spi0-mcp2515

Konfiguracja samej magistrali CAN:

 Bash | 
 
 copy code |
?

1
nano /etc/modules

 Bash | 
 
 copy code |
?

1
can
2
can-dev
3
can-raw

 Bash | 
 
 copy code |
?

1
nano /etc/network/interfaces

 Bash | 
 
 copy code |
?

1
auto can0
2
iface can0 can static
3
        #taktowanie magistrali CAN
4
        bitrate 250000

I to wszystko. Po restarcie powinniśmy w dmsg zobaczyć następujące linie:

 Bash | 
 
 copy code |
?

1
[    6.824164] can: controller area network core (rev 20120528 abi 9)
2
[    6.829914] can: raw protocol (rev 20120528)
3
[    8.252856] mcp251x spi0.0 can0: MCP2515 successfully initialized.
4

ESP32 – zajawka cz.2

I czujniki. Mam pod ręką tylko miernik z marketu za 10zł, ale na pewno zawyża wynik patrząc na poprzednie pomiary. Wychodzi średnio 3-4uA. Czyli na baterii CR2032 ponad 5 lat pracy 🙂

ESP32 – mała zajawka

Pracuję ostatnio prywatnie nam małym projektem, który niedługo opiszę.

(jakość słaba bo zdjęcie robione pralką):

Older posts

© 2018 Paweł Szabaciuk

Theme by Anders NorenUp ↑