Zgodnie z propozycją @p.kaczmarek2 postaram się podzielić tutaj kilkoma pomysłami na rozszerzenia i funkcje firmware OpenBeken IoT, zaczynając "zgodnie z życzeniem"
Kod znajduje się w PR #1627 .
Zacznę od kilku informacji i zrzutów ekranu, ale chętnie poznam opinie na bardziej podstawowe pytania w dalszej części tego postu.
Tak więc "tylko" uruchomienie już obecnego sterownika (/src/driver/ds18b20.c) nie było takie trudne, najważniejsza część (synchronizacja protokołu OneWire) została wykonana i ulepszona przy wsparciu wielu innych osób dla "prostego" sterownika. Tak więc brakowało tylko warstwy sterownika, protokół działał już całkiem dobrze.
Tak więc pierwsze podejście było następujące:
Przeniesienie wszystkich podstawowych funkcji do osobnego pliku, tak aby wszystkie podstawowe funkcje "one_wire" lub "ds18b2" (aż do odczytu/zapisu bajtu) mogły być współdzielone między dwoma sterownikami.
Nieco większym wyzwaniem były pewne ogólne decyzje: Jak obsługiwać czujniki?
Krótka wycieczka:
Wszystkie czujniki mają unikalny adres, który pozwala na adresowanie ich na magistrali, dzięki czemu możliwe jest rozróżnienie wielu urządzeń na tej magistrali. Prosty sterownik wybiera łatwą drogę
Aby odczytać temperaturę, procedura jest następująca: "Wszystkie urządzenia: Przygotuj do odczytu temperatury", a następnie "Wszystkie urządzenia: Zapisz temperaturę" - a "wszystkie urządzenia" odnoszą się do jednego czujnika na tym pinie.
To podejście nie działa w przypadku wielu czujników, przynajmniej jeśli chodzi o odczyt: Jeśli kilka czujników zgłosi swoją temperaturę jednocześnie, to nie będzie działać.
Dlatego adresy czujników muszą być odpytywane indywidualnie: "Wszystkie urządzenia: Prepare for temperature reading", a następnie "Sensor A: Write temperature", "Sensor B: Write temperature" itd.
Sterownik musi najpierw znać adresy urządzeń (czujników). Aby to osiągnąć, sterownik ma możliwość określenia wszystkich adresów czujników za pomocą sprytnego algorytmu (dla zainteresowanych można sprawdzić https://www.analog.com/en/resources/app-notes/1wire-search-algorithm.html ).
Użyłem następującej struktury danych:
typedef uint8_t DeviceAddress[8]; // wir müssen die Sensoren anhand ihrer Adresse unterscheiden
typedef struct {
DeviceAddress array[DS18B20MAX]; // unique address of the sensor
uint8_t index; // an index ;-)
char name[DS18B20MAX][DS18B20namel]; // a description/name for this sensor
float lasttemp[DS18B20MAX]; // the last temperature read by this sensor
unsigned short last_read[DS18B20MAX]; // keep track of when the sensor was last read successfully
short channel[DS18B20MAX]; // possibly set channel to this temperature value
short GPIO[DS18B20MAX]; // on which pin is the sensor?
} DS1820devices;
To również wyjaśnia, jakie funkcje powinien mieć sterownik, moim zdaniem:
- W przypadku pojedynczego czujnika nie ma to znaczenia, ale w przypadku wielu czujników warto to rozważyć: Czujniki powinny mieć przypisaną "nazwę", ponieważ nam, ludziom, łatwiej jest skojarzyć "Kuchnia" lub "Sypialnia" niż "28-FF-3C-01-12-34-56-78" lub "28-7B-9C-01-23-45-67-89".
- Wszystkie informacje, które wcześniej miałem tylko dla całego systemu, są teraz potrzebne dla każdego czujnika:
- Na którym pinie należy go szukać?
- Kiedy ten czujnik ostatnio odpowiadał?
- Który kanał powinien być używany do pomiaru temperatury?
Jak to wygląda?
Tak wygląda strona główna po uruchomieniu sterownika z 10 (nieskonfigurowanymi) klonami DS18B20:
Może chcesz zobaczyć jak wygląda moja konfiguracja? Zrobiłem małą "testową płytkę prototypową", która zapewni dwie "magistrale" z 7 i 3 czujnikami oraz jeden "pojedynczy" czujnik. Czujniki 7 i pojedynczy są przeznaczone do wyłącznego użytku; dzielą rezystor 4,7kΩ (dzięki użytkownikowi git "rpv-tomsk" - patrz PR PR #1579 - przy użyciu "HAL_PIN_Setup_Input_Pullup" może również działać bez zewnętrznego podciągania)..
Teraz, aby skonfigurować czujniki, można użyć poleceń sterownika:
Oczywiście zaczynamy od
startDriver DS1820 [sekundy między odczytami temperatury]
uruchomienie sterownika, opcjonalne ustawienie interwału odczytu czujników, domyślnie 15 sekund
(obecne również w "trybie prostym")
Sterownik przeskanuje wszystkie piny skonfigurowane jako "DS1820_IO", aby znaleźć adresy wszystkich czujników.
Następnie można skonfigurować czujniki za pomocą następujących poleceń:
DS18B20_setsensor <address> <GPIO> <name> [channel]
Konfiguracja adresu czujnika, nazwy czujnika i (opcjonalnie) kanału
Przykłady:
DS18B20_setsensor "0x28 0x01 0x02 0x03 0x04 0x05 0x06 0x07" "5" "kitchen"
DS18B20_setsensor "0x28 0x02 0x03 0x04 0x05 0x06 0x07 0x08" 5 "bedroom" 3
DS18B20_setsensor "0x28 0x03 0x04 0x05 0x06 0x07 0x08 0x09" PB21 "my room" 3
Jeśli adres czujnika jest "znany" (czujnik został znaleziony podczas (początkowego) skanowania), pin, nazwa i kanał są ustawiane/aktualizowane.
Jeśli czujnik nie znajduje się jeszcze na liście, zostanie dodany wraz z pinem, nazwą i kanałem.
Oznacza to, że możemy używać sterownika nawet bez (złożonego) skanowania magistrali - jest to dość duża funkcja i w najlepszym przypadku potrzebna tylko raz: do identyfikacji czujników przy pierwszym uruchomieniu.
Później adresy są znane i można je ustawić bezpośrednio.
DS1820_SetResolution <bits> [<sensor address>]
ustawia rozdzielczość temperatury jednego / wszystkich czujników (jeśli opcjonalny adres nie jest obecny)
(obecna również w "trybie prostym" - tam jedynym argumentem jest rozdzielczość)
przykłady:
DS1820_SetResolution 9 "0x28 0x01 0x02 0x03 0x04 0x05 0x06 0x07"
DS1820_SetResolution 9
Ważna uwaga: dla większości moich (klonów) DS18B20 ustawienie rozdzielczości nie działa, zawsze będą używać rozdzielczości 12-bitowej!
DS18B20_scansensors
Czyści wszystkie dane i skanuje wszystkie magistrale w poszukiwaniu podłączonych czujników.
Jeśli dodano czujnik lub nie wszystkie czujniki zostały wykryte, można rozpocząć skanowanie od nowa.
Wada: utracisz wszystkie skonfigurowane dane - ale dzięki funkcji "setsensor" możesz je później łatwo dodać ponownie.
Ponieważ lubię prostotę, dodałem również prostą stronę konfiguracji, aby dokonać wszystkich ustawień:
Pozwala to również na wygenerowanie "backlog command" całej konfiguracji. W ten sposób można je łatwo skopiować i wkleić do autoexec lub jako polecenie startowe i zachować ustawienia po ponownym uruchomieniu. W moim przypadku wynikowa komenda to:
backlog startDriver DS1820 ; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xD5 0xB0 0x35 0x82" 10 "Kitchen door" 10; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xD5 0xB1 0xB1 0xAB" 10 "Kitchen window" 11; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xD5 0xC3 0xB2 0x6E" 10 "Master Bedroom" 12; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xFB 0xD1 0x06 0x20" 10 "Livingroom " 13; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xFB 0xBD 0x67 0x0C" 10 "Adams room" 14; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xFB 0xAF 0x75 0x50" 10 "Eves room" 15; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xFB 0xBF 0x27 0xDB" 10 "Garage" 16; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xD4 0x7D 0xC4 0x3E" 37 "Pool" 17; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xD4 0x1F 0x6D 0xC6" 37 "Cellar" 18; DS18B20_setsensor "0x28 0x61 0x64 0x35 0xD5 0xEF 0x00 0x6C" 37 "Garden" 19
Strona główna będzie odzwierciedlać zmiany:
można zobaczyć opis każdego czujnika, a kanały zostały zaktualizowane.
Mam nadzieję, że daje to pierwsze wyobrażenie o tym, co zrobiłem i jak korzystać ze sterownika.
Być może zauważyłeś, że sterownik nazywa się "DS1820", a polecenia "DS18B20_XXX" - wynika to z faktu, że zacząłem od alternatywnego "pełnego" sterownika oprócz prostego sterownika (przenosząc część kodu prostego sterownika do współdzielonego pliku kodu).
rpv-tomsk zaproponował użycie tylko jednego pliku, więc zintegrowałem wszystko w jednym pliku, gdzie "#define DS1820full 1" wybierze pełny kod.
Oto moje pierwsze pytanie do innych deweloperów i zwolenników: Co według was jest "lepsze":
Posiadanie tylko jednego pliku kodu z "#defines" do wyboru funkcji?
+ wprowadzone zmiany są zawsze wprowadzane dla obu wersji
+ nie ma potrzeby tworzenia oddzielnego pliku "ds1820 protocol" dla współdzielonego kodu
- wiele "#defines" czasami utrudnia czytanie kodu, może prowadzić do błędów
Pozostawienie/powrót do trzech plików: prostego, pełnego i współdzielonego kodu?
+ znacznie łatwiejszy do odczytania, nie ma potrzeby posiadania kilku "#definicji" wewnątrz funkcji
- jeśli wprowadzane są zmiany, musimy dotknąć dwóch plików (jeśli jest to w jakimś wspólnym kodzie)
(jest +/-, jeśli musimy również zmienić to w dwóch miejscach w jednym pliku, jeśli znajduje się wewnątrz "#defines")
Na koniec najważniejsze pytanie - czy w ogóle tego potrzebujemy?
Czy jest wielu użytkowników "czekających" na dołączenie wielu czujników?
Tak, pozwoliłem sobie na to, ale może być też małe rozwiązanie: Wiele czujników, ale z wieloma GPIO, jeden czujnik na pin. Nie trzeba walczyć z adresami, wystarczy zapętlić wszystkie piny z rolą "DS1820_IO". Kanał jest już ustawiony (wraz z pinem) i wiem, że czujnik na pinie 18 znajduje się w kuchni, a ten na pinie 21 w salonie.
Więc proszę o komentarze w każdym kierunku
Dodano po 14 [minutach]: .
Dla W800 dodatkowy rozmiar (prosty do pełnego) to około 6k - mamy skomplikowane skanowanie, ale przede wszystkim "ładne" GUI konfiguracyjne rozwali obraz.
Fajne? Ranking DIY