W tej części postaram się opisać czujniki meteorologiczne a dokładniej czujnik opadu, czujnik kierunku oraz czujnik prędkości wiatru są to czujniki składowe anemometrów sygnalizujących. Stacja meteo nie musi tylko mierzyć oraz zapisywać warunków atmosferycznych, może również sterować zewnętrznymi urządzeniami ale o tym w innej części.
Zajmijmy się czujnikiem opadu. Czujnik ten mierzy opad metodą korytkową. Opad zbierany na lejku czyli górnej obudowie czujnika spływa po ściankach poprzez sitko do jego wnętrza gdzie na korytku zbiera się opad. Każde przechylenie korytka powoduje chwilowe zwarcie kontaktronu co jest równe 0,2794 mm / metr kwadratowy opadu. Impulsy opadu zliczam do czasu zapisu do bazy danych. Po zapisie ilości opadu w bazie mysql zeruję licznik opadu. Sumowaniem dobowego opadu zajmuje się funkcja w php po stronie serwera www.
Czujnik składa się z górnej obudowy, podstawy, korytka służącego do pomiaru ilości opadu, posiada małą płytkę pcb z kontaktronem.
Na ostatniej fotografii widzimy w jaki sposób złożony jest czujnik opadu, jego płytka PCB onieśmiela, oznacza to iż gdy czujnik ulegnie uszkodzeniu to mogą uszkodzić się tylko trzy rzeczy:
1. Połączenie płytki z przewodami.
2. Kontaktron.
3. Ścieżki.
Na płytce znajdują się dwie ścieżki i kontaktron oraz dodatkowe dwie sztuki gąbek przyklejonych do płytki aby usztywnić ją w obudowie. Magnes zwiera kontaktron, który położony jest w centralnej części korytka aby każdy przechył zwierał kontaktron.
Dla czujnika opadu w pliku meteo_sensors.h zadeklarowałem następujące zmienne oraz funkcje, jest to podstawowa wersja która umożliwi wam bezproblemowy odczyt z czujników zawierająca fragment opadu. W dalszej części biblioteka będzie kompletowana:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/* * meteo_sensors.h * * Created on: 14 paź 2016 * Author: avrtech * Strona www: http://avrtech.pl * * Obsługa czujników dla użytku prywatnego wymaga pozostawienia stopki. * Aby wykorzystać bibliotekę do celów komercyjnych proszę o kontakt poprzez stronę www. */ #ifndef CZUJNIKI_METEO_SENSORS_H_ #define CZUJNIKI_METEO_SENSORS_H_ // zmienne - opad uint32_t rainfall_mm, rainfall_mm_j, rainfall_mm_d; extern volatile uint32_t tmp_imp_rainfall; //licznik impulsów z czujnika opadu void init_wind_rainfall (void); // inicjalizacja timerów na potrzeby czujników void pomiar_opadu (void); // funkcja mierząca i przeliczająca ilość opadu w mm #endif /* CZUJNIKI_METEO_SENSORS_H_ */ |
Natomiast w pliku meteo_sensors.c inicjujemy timer oraz prostą funkcję służącą do zliczania impulsów z czujnika opadu:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
/* * meteo_sensors.c * * Created on: 14 paź 2016 * Author: avrtech * Strona www: http://avrtech.pl * * Obsługa czujników dla użytku prywatnego wymaga pozostawienia stopki. * Aby wykorzystać bibliotekę do celów komercyjnych proszę o kontakt poprzez stronę www. */ #include <avr/interrupt.h> // dołączenie wewnętrznej biblioteki przerwań #include "wind_rainfall.h" // dołączenie deklaracji // zmienne - opad (1 impuls na 1 sek = 0,2794mm) volatile uint32_t tmp_imp_rainfall; //licznik impulsów z czujnika opadów extern uint32_t rainfall_mm; //zmienna wyniku opadu deszczu void pomiar_opadu (void) { rainfall_mm = tmp_imp_rainfall * 27; // przelicz ilosc impulsow na mm bez przecinka rainfall_mm_j = rainfall_mm / 100; // przesun przecinek o 1 w prawo pozbywajac sie dziesietnych rainfall_mm_d = rainfall_mm - (rainfall_mm_j * 100); // oblicz dziesietne predkosci wiatru } // inicjalizacja timerów na potrzeby czujników void init_wind_rainfall (void) { rainfall_mm = 0; //konfiguracja Timer2 licznik przybliżonej sekundy do pomiarów kwarc 11.059.200 Hz TCCR2 |= (1<<WGM21); // tryb CTC TCCR2 |= (1<<CS22)|(1<<CS21)|(1<<CS20); // prescaler = 1024 OCR2 = 107; // 100Hz tick TIMSK |= (1<<OCIE2); // przerwanie Compare // inicjalizacja przerwania INT1 na potrzeby zliczania impulsów z czujnika opadów PORTD |= (1<<PD3); // podciągnięcie pinu INT1 do VCC MCUCR |= (1<<ISC11); // wyzwalanie zboczem opadającym GICR |= (1<<INT1); // odblokowanie przerwania } // Obsługa przerwania INT 1 ISR( INT1_vect ) { tmp_imp_rainfall++; // przy każdym zboczu opadającym zlicz impuls } |
Czujnik prędkości wiatru zbudowany jest z podstawy oraz trzech łopatek. Wiejący wiatr napiera na łopatki obracając nimi. Każdy wygenerowany impuls w ciągu 1 sekundy to 1.492 mph po przeliczeniu 2.4006279999999998 km/h prędkość ta została zaokrąglona do 2.4 km/h. Możemy również obliczyć prędkość w m/s która równa jest 0.6669527583. Analogicznie jak km/h wynik przeliczenia prędkości zaokrąglony został do 0.66 m/s. Do bazy msql na serwerze www zapisuję prędkość wiatru odczytaną w trakcie zapisu oraz prędkość maksymalną która została odczytana pomiędzy zapisami. Pokusić się można o podanie średniej prędkości wiatru jaka była pomiędzy zapisami. Wystarczy zsumować odczytane prędkości wiatru i podzielić tę wartość przez ilość odczytów.
Zastanawiacie się pewnie jak zdjąć łopatki? Otóż jest to dość proste, chwyćcie podstawę w jedną rękę, łopatki w drugą i delikatnie ciągnijcie. Łopatki zsuną się z łożyska. Jest to ważny element serwisowy, gdyż ona łożysku jest smar. Łożysko powinno się smarować przynajmniej raz do roku aby chronić przed wilgocią. W ten sam sposób zdejmiemy wskaźnik kierunku wiatru.
Zasada działania czujnika prędkości wiatru jest identyczna jak w przypadku opadu deszczu, jednakże funkcja jest trochę inaczej realizowana. Plik nagłówkowy w przypadku obsługi samego czujnika prędkości wiatru wyglądał będzie następująco:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* * meteo_sensors.h * * Created on: 14 paź 2016 * Author: avrtech * Strona www: http://avrtech.pl * * Obsługa czujników dla użytku prywatnego wymaga pozostawienia stopki. * Aby wykorzystać bibliotekę do celów komercyjnych proszę o kontakt poprzez stronę www. */ #ifndef CZUJNIKI_METEO_SENSORS_H_ #define CZUJNIKI_METEO_SENSORS_H_ // zmienne - wiatr uint32_t spd_wind_kmh, spd_wind_kmh_max, spd_wind_kmh_j, spd_wind_kmh_d, spd_windm_kmh_j, spd_windm_kmh_d; void init_wind_rainfall (void); // inicjalizacja timerów na potrzeby czujników void pomiar_wiatru (void); // funkcja mierząca i przeliczająca prędkość wiatru w km/h #endif /* CZUJNIKI_METEO_SENSORS_H_ */ |
Oczywiście ilu programistów tyle pomysłów ja pokazuję wam drogę wraz z działającą funkcją. Plik programu będzie następujący:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
/* * meteo_sensors.c * * Created on: 14 paź 2016 * Author: avrtech * Strona www: http://avrtech.pl * * Obsługa czujników dla użytku prywatnego wymaga pozostawienia stopki. * Aby wykorzystać bibliotekę do celów komercyjnych proszę o kontakt poprzez stronę www. */ #include <avr/interrupt.h> // dołączenie wewnętrznej biblioteki przerwań #include "wind_rainfall.h" // dołączenie deklaracji // zmienne - wiatr (1 impuls na 1 sek = 2,4km/h) volatile uint32_t tmp_spd_wind; //licznik impulsów z czujnika prędkości wiatru extern uint32_t spd_wind_kmh, spd_wind_kmh_max; //zmienne wyniku prędkości wiatru void pomiar_wiatru (void) { spd_wind_kmh = tmp_spd_wind * 24; // przelicz ilosc impulsow na km/h bez przecinka if(spd_wind_kmh >= spd_wind_kmh_max){ // jezeli predkosc wiatru jest wieksza lub równa prędkości max spd_wind_kmh_max = spd_wind_kmh; // przypisz wartość prędkości wiatru do prędkości max } spd_wind_kmh_j = spd_wind_kmh / 10; // przesun przecinek o 1 w prawo pozbywajac sie dziesietnych spd_wind_kmh_d = spd_wind_kmh - (spd_wind_kmh_j * 10); // oblicz dziesietne predkosci wiatru spd_windm_kmh_j = spd_wind_kmh_max / 10; // przesun przecinek o 1 w prawo pozbywajac sie dziesietnych spd_windm_kmh_d = spd_wind_kmh_max - (spd_windm_kmh_j * 10); // oblicz dziesietne predkosci wiatru tmp_spd_wind = 0; // wyzeruj licznik impulsów } // inicjalizacja timerów na potrzeby czujników void init_wind_rainfall (void) { spd_wind_kmh_max = 0; //konfiguracja Timer2 licznik przybliżonej sekundy do pomiarów kwarc 11.059.200 Hz TCCR2 |= (1<<WGM21); // tryb CTC TCCR2 |= (1<<CS22)|(1<<CS21)|(1<<CS20); // prescaler = 1024 OCR2 = 107; // 100Hz tick TIMSK |= (1<<OCIE2); // przerwanie Compare // inicjalizacja przerwania INT0 na potrzeby zliczania impulsów z czujnika wiatru PORTD |= (1<<PD2); // podciągnięcie pinu INT0 do VCC MCUCR |= (1<<ISC01); // wyzwalanie zboczem opadającym GICR |= (1<<INT0); // odblokowanie przerwania } // Obsługa przerwania INT 0 ISR( INT0_vect ) { tmp_spd_wind++; // przy każdym zboczu opadającym zlicz impuls } |
Z powyższych kodów jesteście wstanie skleić jedną bibliotekę do obsługi czujnika opadu oraz prędkości wiatru.
Czujnik kierunku wiatru działa na innej zasadzie niż czujnik opadu oraz prędkości wiatru, mimo iż ich konstrukcja jest bardzo zbliżona. Czujnik ten złożony został z 8 kontaktronów oraz rezystorów użytych jako dzielnik napięcia. Wyposażony jest on dodatkowo w gniazdo RJ-11 aby można było podłączyć czujnik prędkości wiatru i jednym przewodem sprowadzić oba czujniki do płytki głównej stacji meteo.
Zwróćcie uwagę na ostatnią fotografię w której to widać gdzie założony jest magnes zwierający kontaktrony. Został on wysunięty na sam rant po to aby nie zwierać zbyt dużej ilości kontaktronów.
Czujnik ten podłączamy trochę inaczej do mikrokontrolera gdyż nie będzie on podłączony do wejścia INT0 czy też INT1. Zostanie on podłączony do pinu ADC mikrokontrolera, w moim przypadku jest to ATmega32.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
/* * main.c * * Created on: 14 paź 2016 * Author: avrtech * Strona www: http://avrtech.pl * * Obsługa czujników dla użytku prywatnego wymaga pozostawienia stopki. * Aby wykorzystać bibliotekę do celów komercyjnych proszę o kontakt poprzez stronę www. */ // DOŁĄCZENIE STANDARDOWYCH BIBLIOTEK #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <inttypes.h> #include <stdlib.h> #include <stdio.h> #include <string.h> uint16_t pm, adc; // zmienne na potrzeby kierunku wiatru - pomiar ADC uint8_t av_cz_d, av_cz_u; uint32_t av; char buffer_out[32]; // bufor wyjsciowy nRF char buffer_data[15]; // bufor wyjsciowy nRF char buffer_KW[5]; // bufor kierunku wiatru char buffer_KW_AV[5]; // bufor kierunku wiatru char buffer_KW_DE[5]; // bufor kierunku wiatru char buffer_KW_ST[5]; // bufor kierunku wiatru char direction_string[5]; // bufor kierunku wiatru char direction_degree[6]; // zmienna stopni kierunku wiatru uint16_t wartosc_ADC(uint8_t pin); //deklaracja funkcji pomiaru ADC void kierunek_wiatru( void ); // sprawdzenie kierunku wiatru int main(void){ ADMUX |= (1<<REFS0); // wybór wewnętrznego źródła napięcia odniesienia = 5V ADCSRA |= (1<<ADEN)|(1<<ADPS1)|(1<<ADPS0); // Włączenie modułu ADC oraz ustawienie preskalera na 64 sei(); // zezwolenie na przerwania while(1){ // tutaj należy dopisać funkcję wykonującą się co 1 sekundę i umieścić w niej odczyty z czujników } } // odczyt wartości ADC uint16_t wartosc_ADC(uint8_t pin){ ADMUX |= (ADMUX & 0xF8) | pin; // ustawienie wybranego pinu ADC ADCSRA |= (1<<ADSC); // start pomiaru while( ADCSRA & (1<<ADSC) ); // oczekiwanie na koniec pomiaru return ADCW; } // sprawdzenie kierunku wiatru void kierunek_wiatru( void ){ pm = wartosc_ADC(7); adc = pm; av = adc * 49; av_cz_d = av/10000; av_cz_u = (av/100) % 100; sprintf(buffer_KW, "%i", pm); sprintf(buffer_KW_AV, "%i.%i", av_cz_d, av_cz_u); if ((adc > 760) && (adc < 799)) {strcpy(direction_degree, "0"); strcpy(direction_string, "N");}; if ((adc > 380) && (adc < 430)) {strcpy(direction_degree, "22.5"); strcpy(direction_string, "NNE");}; if ((adc > 450) && (adc< 470)) {strcpy(direction_degree, "45"); strcpy(direction_string, "NE");}; if ((adc > 70) && (adc< 85)) {strcpy(direction_degree, "67.5"); strcpy(direction_string, "ENE");}; if ((adc > 85) && (adc < 100)) {strcpy(direction_degree, "90"); strcpy(direction_string, "E");}; if ((adc > 60) && (adc < 69)) {strcpy(direction_degree, "112.5"); strcpy(direction_string, "ESE");}; if ((adc > 170) && (adc < 199)) {strcpy(direction_degree, "135"); strcpy(direction_string, "SE");}; if ((adc > 110) && (adc < 137)) {strcpy(direction_degree, "157.5"); strcpy(direction_string, "SSE");}; if ((adc > 270) && (adc < 299)) {strcpy(direction_degree, "180"); strcpy(direction_string, "S");}; if ((adc > 230) && (adc < 260)) {strcpy(direction_degree, "202.5"); strcpy(direction_string, "SSW");}; if ((adc > 610) && (adc < 640)) {strcpy(direction_degree, "225"); strcpy(direction_string, "SW");}; if ((adc > 590) && (adc < 605)) {strcpy(direction_degree, "247.5"); strcpy(direction_string, "WSW");}; if ((adc > 930) && (adc < 960)) {strcpy(direction_degree, "270"); strcpy(direction_string, "W");}; if ((adc > 810) && (adc < 830)) {strcpy(direction_degree, "292.5"); strcpy(direction_string, "WNW");}; if ((adc > 870) && (adc < 899)) {strcpy(direction_degree, "315"); strcpy(direction_string, "NW");}; if ((adc > 690) && (adc < 715)) {strcpy(direction_degree, "337.5"); strcpy(direction_string, "NNW");}; sprintf(buffer_KW_ST, "%s", direction_degree); sprintf(buffer_KW_DE, "%s", direction_string); } |
Oczywiście jest to najprostszy przykład, który do własnej prywatnej stacji można wykorzystać z zachowaniem informacji z kąd pochodzi oraz autora jako avrtech.pl jak i linku do mojego bloga. Zaznaczam również, że wartości ADC mogą się różnić np z powodu zastosowanych innych rezystorów lub inaczej ułożonej płytce PCB w obudowie czujnika kierunku wiatru.
Witam,potrzebuję porady mam stację WS 1080 i działa wszystko ok.Mam natomiast okazję kupić bazę ws 1600.Niby częstotliwość pracy podobna ale czy zaloguje się do istniejących czujników?.Czy ktoś z Państwa ma jakies doświadczenie w tej materii.Pozdrawiam
Witam
Jako iż nie bawiłem się stacjami WS1080 ani WS1600 nie jestem w stanie pomóc. Baza może i pracuje na tych samych częstotliwościach lub podobnych (a jak podobnych to na pewno się nie da ich połączyć) ale to nie oznacza że czujniki dogadają się z bazą o wyższych możliwościach.
Może być tak, że czujniki od WS1080 dogadają się ze stacją WS1600 ale nie podadzą wszystkich parametrów, może również być tak, że nie dogadają się i nic nie będzie działało a wszystko to zależy głównie od ramek jakie wysyłają czujniki a jakie w stanie jest odebrać baza.
Wnioskując po tym, że WS1080 oraz WS1600 jest tego samego producenta to czujniki od WS1080 powinny się dogadać z WS1600 ale powtarzam „powinny” jak już wcześniej wspomniałem wszystko zależy od tego jakie ramki wysyłają czujniki a jakie może odebrać baza.
Nie mniej sądzę, że około połowy ekranu w WS1600 będzie pusta.
Polecam napisać maila do sprzedawcy, ewentualnie do producenta, gdyż nie jestem w stanie odpowiedzieć jednoznacznie za producenta tym bardziej, że nie miałem okazji bawić się tymi stacjami.
Pozdrawiam
Drogi Autorze gdzie można kupić takie czujniki? Najbardziej interesuje mnie ten od prędkości wiatru. Znalazłem na stronie maplina ale nie ma wysyłki do Polski. Da się to dostać u nas?
Witaj no niestety mimo iż Maplin sprzedaje czujniki które mimo wszystko mają napis MADE IN CHINA to tam się ich nie da zakupić. Pozostaje ktoś znajomy w UK, który dokona zakupu i wyśle czujnik do Ciebie.
Zapraszam na forum nettemp.pl albo na stronę forum atnel. Dałem tam ogłoszenia o sprzedaży czujników prędkości i kierunku wiatru. Wysyłka z pl bo czujniki mam w warsztacie.
Witaj :) Jestem na obu forach :) pozdrawiam :)
witam nie mogę znaleźć na w/w forach ogłoszenia o sprzedaży czujnika prędkości wiatru.
Przeczytaj pozostałe komentarze. Np w tym z 2017-01-27 o 17:57 podałem linka gdzie można je zakupić w chinach.
Oficjalnie mogę stwierdzić, że od krótkiego czasu czujniki dostępne są również na aliexpress :)
Cena nie jest mała ale jeżeli komuś chce się czekać to lepsze to niż brak wysyłki w Maplinie do PL
https://pl.aliexpress.com/
Jak długo będą dostępne i czy na stałe nie mam pojęcia.
Pozdrawiam
Super robota… BRAWO!
Mam takie małe pytanie odnośnie sensora opadów deszczu.
Z tego co piszesz to „kołyska” przechyli się jak wpadnie do niej 279,4 mililitrów wody-tak, dobrze myślę?
Cieszę się, że komuś się podobają moje wpisy. Aktualnie przygotowuję kolejny lecz na jego potrzeby piszę program od 0 aby pozbyć się wszystkich ewentualnych błędów programowych i pozostałości w kodzie, także mam nadzieję, że wiedza którą staram się przekazać będzie pomocna.
Co do ilości mililitrów to nigdy nie sprawdzałem tej wartości strzykawką ale dokładnie tak to powinno wyglądać.
Witam.
Czy podczas korzystania z czujnika prędkości wiatru, oraz ilości opadu nie miałeś problemu z tzw. drganiami styków? Akurat jak ja się bawiłem z tymi czujnikami to właśnie miałem problem taki, że niepoprawnie zliczały impulsy, szczególnie przy małych częstotliwościach przełączeń (zamiast jeden to kilka impulsów).
Czy zabezpieczyłeś program przed takim zjawiskiem, jak drgania styków?
Jak często pomiary wykonujesz? Tylko przed wysłaniem danych na serwer, czy częściej i potem na serwer wysyłasz dane uśrednione?
Cześć Danielos
Generalnie nie miałem problemów z drganiami styków gdyż czujniki podłączam do pinów INT0 oraz INT1 po stronie sprzętowej mam dołożone 100nF do GND i piny wewnętrznie podciągnięte do VCC.
Czujniki są sprawdzane co 1s. Wyniki do domu wysyłane są również co 1 sek (wszystkie) natomiast na stronę www dane wysyłam co 10 minut.
Dzięki za odpowiedź!
Po Twojej informacji, że nie miałeś problemów z drganiami, sprawdziłem połączenia i program. Okazało się, że skonfigurowałem nie ten pin do którego miałem podpięty czujnik i dlatego działy mi się cuda z odczytem. Po poprawieniu, odczyt się udał.
Pozdrawiam!
Cieszę się, że mój wpis był pomocny. Dzięki za informacje.