Paweł Szabaciuk, Autor w serwisie Paweł Szabaciuk

Paweł Szabaciuk

Software Developer

Author: Paweł Szabaciuk (page 1 of 3)

SystemAIR Modbus RTU

W pracy trafił się temat gadania po protokole Modbus. Przy użyciu standardowego Modbusa RTU. W dość znacznej prędkości 9600 🙂 A co najlepsze, to wyjście z urządzenia jest RS232, do tego przejście na RS485 i w takiej postaci mam się podłączyć 🙂

Poczytałem, poszukałem i co nieco się dowiedziałem od strony praktycznej.

Na początek mamy zdefiniowanych kilka bytów, określających rodzaje danych.
Rodzaje rejestrów zdefiniowanych przez protokół Modbus:

  • Coil – jest to 1 bitowy rejestr, wykorzystywany do kontroli wyjścia. Może być do odczytu i/lub do zapisu
  • Discrete Input – jest to 1 bitowy rejestr, używany jako wejście. Może być tylko do odczytu
  • Input Register – 16 bitowy rejestry, używany jako wejście. Może być tylko do odczytu
  • Holding registers – najbardziej uniwersalne 16 bitowe rejestry. Mogą być do odczytu i do zapisu. Może być używany np. do wejść, wyjść, danych konfiguracyjnych lub dowolnych danych wymagających przechowania

Jak widać, wielkiej filozofii nie ma, o ile mamy dokumentację techniczną producenta co gdzie pod jakim adresem siedzi.

Ponieważ nie mogę nic mówić o projekcie z pracy, postanowiłem podłączyć się do centrali wentylacyjnej, która to gada sobie po RS485 i Modbus z dowolnym urządzeniem master.
Ogólno dostępna dokumentacja do central wentylacyjnych firmy SystemAir.

Mamy tutaj rozpisane dokładnie jakie są rejestry, pod jakimi adresami, czy można je zapisywać czy odczytywać i jakiego są rodzaju.
Drugą istotną informacją jest adres i prędkość transmisji. Każde urządzenie slave w Modbus musi mieć swój unikalny adres. I tak na przykładzie centrali, mamy domyślnie adres 1. Pod taki adres się dobijamy, żeby np. odczytać informację o prędkości wentylacji, która to jest dostępna pod adresem 101 (czyli 101 – 1, zgodnie z dokumentacją).

W dokumentacji widzimy też, że rejestr ten może być zapisany nową wartością, i tak możemy odczytać i zmienić szybkość działania wentylatorów w centrali.

Na tej podstawie powstał prosty sterownik, oparty na starej płytce, pół-uniwersalnej na ESP8266.

Płytka jest identyczna z postem: Sterowanie pompą obiegową od cyrkulacji. Wlutowany został tylko transceiver MAX3485 do komunikacji po RS485 z centralą.

W wyniku pół dnia siedzenia nad kodem, mamy prostą aplikację do monitorowania danych i konfiguracji centrali przez stronę www.

W planach połączenie centrali z czujnikami środowiskowymi i sterowanie bardziej automatyczne siłą wentylacji z automatu.

Honda Hornet zmiana przedniej zębatki.

Dzisiaj nadszedł czas zmiany zębatki przedniej w Hondzie Hornet PC36 2004 rok.
Moto po jednym sezonie wymagało napięcia łańcucha. Dokładnie o 0.5 podziałki na wachaczu. Ponieważ pierwsza zużywa się przednia zębatka i to zużycie odpowiada głównie za niszczenie zestawu napędowego, najprościej po prostu ją zmieniać jak się zużyje.
Zmiana ta jest banalanie prosta.
Zaczynamy od ściągnięcia osłony zębatki. Następnie luzujemy śrubę na zębatce. Powinno pójść prosto, w końcu moment dokręcenia to tylko 54 N-m. Najprościej to zapiąć bieg, postawić kogoś na hamulcu tylnim ( albo samemu jak mamy za długie ręce ) i odkręcamy śrubę.
Po tej opracji, stawiamy tył na stojaku, luzujemy naciąg łańcucha, luzujemy nakrętkę tylnej osi. Wyciągamy łańcuch przez przednią zębatkę i ściągamy ją wałka.

Tak wygląda stara zębatka:

Tak wygląda nowa:

Stara i nowa:

I z bliska:

Wszystko widać, tłumaczenia są zbędne.
Zakładamy zębatkę na wałek, czyścimy podkładkę i śrubę, wkręcamy śrubę w wałek.
Następnie wstępnie napinamy łańcuch i dokręcamy śrubę. Dla mojego moto właściwy moment to 54 N-m. Robimy to odwrotnie do odkręcania, więc najprościej przy użyciu tylnego hamulca.
Na koniec regulujemy napięcie łańcucha – dla mojego moto właściwy luz to 30-40mm, więc ustawiam go w połowie. Póki moto jest na stojaku, smarujemy łańcuch. Na koniec zestawiamy ze stojaka i dokręcamy tylną oś. U mnie – 88 N-m.

Sterowanie pompą obiegową od cyrkulacji

Dzisiaj temat dość prozaiczny. Recyrkulacja wody w instalacji domowej, żeby po odkręceniu kranu leciał z niego Johny Walk… wróć! ciepła woda. I żeby nie trzeba było na tę ciepłą wodę czekać. Tylko żeby od razu była ciepła.

Problem jest w tym, że zimą woda jest ogrzewana przez piec, a piec ma możliwość sterowania pompą. Nawet potrafi ją włączać cyklicznie, co by ciepło w zasobniku oszczędzać. Tylko trzeba było sobie instrukcję doczytać. Bo pan serwisant, który uruchamiał instalację o takiej rzeczy nie wiedział. Albo nie pomyślał.

Inaczej jest latem, kiedy to woda ciepła jest pozyskiwana z innych źródeł. Na przykład kolektory słoneczne, pompa ciepła etc. Wtedy nie za bardzo ma co sterować pompką.

Samo sterowanie jest banalnie proste, raz na jakiś czas, mieszamy wodę w instalacji przez załączenie napięcia na pompie. W piecu można ustawić to mieszanie od 1x na godzine na 5 minut do 6x na godzinę na 5 minut. Lektura elektrody zaś głosi, że trzeba to robić raz na 5 minut przez minutę. Zimą miałem 5×5, latem mam 10×1 i nie widzę różnicy.

Do tej pory miałem prosty układ na ATMega328. Nie posiadał on jednak RTC, wobec czego, całość działała całą dobę.
Całą dobę ciepłej wody jednak nie używamy. W nocy zazwyczaj śpimy, więc żeby oszczędzić trochę ciepła w zasobniku, nie ma sensu odpalać pompki w godzinach nocnych.

Powstał więc układ na ESP8266. Pilnuje on sobie czasu na liczniku, natomiast aktualny czas pozyskuje sobie z internetu. Przez NTP. Jak zabraknie prądu i nie będzie internetu, to do czasu pozyskania aktualnego czasu i tak będzie mieszać wodę, tyle, że całą dobę.

Używam WebSocketów do prezentacji real-time czy pompka aktualnie jest włączona, czy też nie. No i można sobie skonfigurować godziny pracy oraz zakresy czasowe dla stanów ON i OFF.

Schemat jest banalny. Typowa implementacja ESP12E z automatycznym programowaniem przy użyciu RTS i DTR. Pamiętajcie tylko o wyprowadzeniu masy do konwertera USB< ->UART. Ja zapomniałem (schemat już poprawiony). Przez co straciłem trochę czasu na walkę z komunikacją.
Brakuje przekaźnika, ponieważ mam już płytkę z przekaźnikiem, do której jest podłączona pompa obiegowa, potrzebuję tylko podać sygnał z zakresu 3 – 5V żeby przekaźnik załączył pompę.

Sterownik wygląda tak:

Płytka jest „uniwersalna”, to znaczy ma obsłużyć jeszcze dwie inne sytuacje, dlatego ma dodatkowe elementy, i miejsce na kolejne. Może kiedyś to też opiszę 🙂

Tradycyjnie też, kilka screenów z aplikacji:

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 leży problem?
Otóż poll chodzi sobie w drugim wątku. Jest to metoda nieobciążająca procesor. Samo poll nie zużywa mocy obliczeniowej. Natomiast większość przykładów, które widziałem, opartych jest 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. Aplikacja działa teraz bez obciążania procesora.

Specjalne podziękowania dla anonimowego darczyńcy za zredagowanie tekstu 🙂

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

Older posts

© 2018 Paweł Szabaciuk

Theme by Anders NorenUp ↑