Skocz do zawartości

Tablica liderów


Popularna zawartość

Pokazuje zawartość z najwyższą reputacją 18.01.2019 we wszystkich miejscach

  1. 2 punkty
    Hej koledzy i koleżanki;-) Ci którzy są dłużej obecni na Forbocie mnie już trochę znają, ale dla nowych użytkowników których sporo ostatnio, krótki rys historyczny. Moje zainteresownie elektroniką zaczęło się w październiku 2017 roku od jakiejś nudy przy kompie kiedy to przeglądając neta natknąłem się na kursy Forbota. Długo sie nie namyślając zamówiłem najpierw kurs elektroniki podstawowy i od strzału dodatkowy, no i oczywiście zestaw tablic. Jako, że mnie to strasznie wciągnęło, dalej poszło za ciosem: technika cyfrowa i oczywiście kurs arduino poziom pierwszy i drugi . Wciągnęło niesamowicie, chyba głównie dzięki temu, że autorzy kursu potrafili swoją wiedzę przekazać jasno, klarownie i przede wszystkim ciekawie. Dobra koniec tej łzawej historyjki pora na opis projektu. Mój system zbudowany jest z: Arduino MEGA, nodeMCU z esp8266, czujnik zanieczyszczeń powietrza PMS5003; ethernet Shield do wyżej wymienionego, czterech czujników temperaturyDS18B20, dwa czujniki temperatury i wilgotności typu DHT11, jeden DHT22, czujnik ciśnienia i temperatury BMP280 I2C, moduł zegarowy RTC1307 I2C, enkoder z przyciskiem, wyświetlacz LCD 20×4 I2C, dwie listwy diod programowalnych po 4 szt, czujnik deszczu, buzzer bez generatora, moduł 8 przekaźników; kilka dodakowych przekaźników, radiolinia PIN4 Proxima 2szt, przekaźnik czasowy PCM-04 Zamel; kilka krańcówek, bramki logiczne OR; żaróweczka neonka, fotorezystor, kupa przewodów, rezystorów, diod itp., tablet, telefon. Działanie: Układ mierzy temperaturę w dwóch miejscach w domu, na zewnątrz temperaturę w słońcu, przy gruncie i 1m nad gruntem w cieniu. Dodatkowo mierzy ciśnienie atmosferyczne, wilgotność zewnętrzną i wewnętrzną oraz temperaturę wody w CO. Od niedawna także poziom zanieczyszczenia powietrza (budowę urządzonka pomiarowego przedstawię w kolejnym artykule). Zapamiętuje również, najwyższe i najniższe wartości każdego z czujników wraz z datą zdarzenia. Funkcją dodatkową jest alarm wywoływany przy pierwszych opadach deszczu, a także (na wyraźne życzenie żony) alarm informujący kiedy pralka w piwnicy skończyła pracę. Jeśli kogoś interesuje ta ostatnia funkcja odsyłam do mojego tematu na Forbocie. Główną funkcją układu jest sterowanie pracą 8 przekaźników obsługujących min. bramę, furtkę, oświetlenie. Każdy z przekaźników jest sterowany niezależnie: -sygnałem z arduino idącym przez bramki OR do których dochodzą także -sygnały z zewnętrznych włączników naściennych -radiolini sterowanych pilotem, - no i oczywiscie aplikacją BLYNK z telefonu, tabletu... Dopiero sygnał za bramką OR idzie do przekaźnika oraz dodatkowo jako potwierdzenie wraca do arduino. Dioda led na obudowie tabletu informuje o włączeniu przekaźnika także, kiedy tenże jest włączony „poza arduino” przez włącznik naścienny bądź radiolinię. Informacja o tym fakcie wraca do arduino powodując odpowiednie zmiany zmiennych i na bieżąco aktualizując diody led i informacje wyświetlane na LCD 20×4 oraz wyświetlaczu telefonu i tabletu w kuchni na ścianie będącego "centrum sterowania" całością. Wszystkie dane z czujników są na bieżąco wyświetlane i przewijane na LCD 20×4 który to wyswietlacz stał się dodatkowym(po tablecie) i zainstalowałem go w obudowie szafki zawierającej najważniejsze elementy układu. Po wciśnięciu przycisku enkodera wchodzimy w menu opcje gdzie możemy na LCD20x4 sprawdzić najwyższy i najniższy odczyt każdego z czujników, datę tego odczytu oraz zresetować pamięć dla każdego odczytu i czujnika z osobna. Możemy również tym enkoderem sprawdzić w menu stan przekaźników i nimi sterować. Wciśnięcie enkodera jest sygnalizowane przez buzzer. Osobną sprawą jest BLYNK który miał służyć początkowo tylko do kontroli przez telefon nad przekaźnikami, ale po poznaniu jego możliwości, całkowicie zmieniłem założenia i teraz to tablet z zainstalowanym Blynkiem jest głównym wyświetlaczem i sterownikiem całego układu. Trochę bliżej na temat aplikacji BLYNK w moim systemie możecie przeczytać tu. Na tablecie mam podmenu: przekaźniki, czujniki, max i min, historia, alarmy. W menu przekaźniki sterujemy z tableta i telefonu, w dowolnym miejscu na świecie, przekaźnikami, otrzymując z powrotem informację o faktycznym włączeniu przekaźnika(zmiana koloru widgeta oraz wyświetlonego na nim napisu).Ta informacja pojawia się także kiedy przekaźnik zostanie włączony przez kogoś innego(przez włącznik ścienny, radiolinia lub drugie urządzenie:tablet lub telefon). Choć poprzez udostępnienie tokena do naszego projektu takich urządzeń może być więcej. Drugie menu w BLYNK-uto wyświetlanie danych z wszystkich czujników odświeżane co 1 min, oraz małe „diody led” migające i informujące o prawidłowej komunikacji apka-arduino MEGA i apka-ESP(czujnik jakości powietrza). Kolejne menu to ekran z rozwijanym podmenu na którym wyświetlone są nazwy wszystkich czujników i poprzez wybór któregoś z nich możemy sprawdzić(podobnie jak to było na LCD20x4), najniższą i najwyższą wartość datę tego zdarzenia i zresetować pamięć dla każdego czujnika osobno. Następne menu to historia, czyli wykresy. Ja mam ustawione wyświetlanie na wykresach historii odczytów ciśnienia atmosferycznego, wigotności, temperatury CO, temperatury zewnętrznej, oraz osobny wykres dla czujnika jakości powietrza. Ostatnie menu w BLYNK-uto alarmy. Po pojawieniu się na odpowiednim pinie arduino sygnału z czujnika deszczu lub sygnału o końcu pracy pralki, na wyświetlaczu LCD20x4 przestaje się przewijać informacja o dacie, godzinie i odczytach z czujników, a wyświetla się info o alarmie z odpowiednią treścią, albo o pralce albo o deszczu. Dodatkowo listwy diod led migają na niebiesko(pralka) lub na czerwono(deszcz). Po wciśnięciu enkodera, wyłączeniu na tablecie lub telefonie albo upływie ustawionego czasu alarm wyłącza się. Informacja o alarmie pojawia się jako notyfikacja także na tablecie i telefonie, w sposób wizualny i dźwiękowy, poprzez wybraną melodię z pamięci talefonu/tableta. Ostatnio dołożyłem dodatkowo obsługę przekaźników głosowo poprzez Google Assistant. Jeśli kogoś bliżej interesuje ta kwestia to zapraszam tutaj. Kolejną miłą opcją jest podpięty do tabletu poprzez bluetooth wzmacniacz klasy D z pilotem spięty z głośnikami zainstalowanymi w kuchni. Google assistant pozwala na bezdotykowe, głosowe włączanie ulubionego przeboju z YT, radia itp. Co do przekażnika czasowego i krańcówek i przeakźników to mają one zastosowanie przy sterowaniu bramą garażową i oświetleniem garażu. Bramą garażową steruję z przycisku naściennego, pilotów radiowych, telefonu, tabletu. Jednak dodatkowo jest założony przekaźnik czasowy który po uplywie zadanego czasu zamyka otwartą bramę niezależnie od systemu. Również włącznik naścienny jest niezależny, więc nawet jak by sytem padł(co się nie zdażyło za ostatnie12 miesięcy) mogę sterować bramą. Krańcowki zainstalowane przy bramie podają informację do Aruduino, a te wysyła info do Blynka który informuje mnie notyfikacją, gdziekolwiek bym nie był, że właśnie została otwarta lub zamknięta brama garażowa. Kolejną sprawą jest automatyka oświetlenia garażu. Zrobiona "analogowo" tzn. jesli świeci się lampa z czujnikiem ruchu przed garażem, a brama jest calkowicie otwarta, zapala się całe oświetlenie garażu. Co znakomicie ułatwia nocne parkowanie. Chyba tyle. Aktualnie pracuję nad stroną internetową(dziękuję wszystkim cierpliwym webmasterom z Forbota za pomoc) postawioną na RPi, która będzie pokazywać światu jakie to fajne powietrze mamy w Kryrach;-). W planach też pomiar siły i kierunku wiatru. Gdyby ktoś chciał poczytać o początkach tego projektu to tutaj, a cały worklog jest tu. Cały sketch sterujący arduino i Blynkiem tutaj. Teraz kilka zdjęć i filmów. Wnętrze szafki z Arduino i całym osprzętem, płytka główna przed i po tuningu: "Centrum": Kilka slajdów z BLYNK-a: Wzmacniacz i głośniki w kuchni: Jeden film mówi więcej niż tysiąc słów więc: Prototyp: Aktualny: LCD dodatkowy: Jeszcze LCD z dołożoną obsługą PMS5003: Działanie BLYNK-a i przekaźników: BLYNK, "centrum", google assistant: Google Assistant w praktyce: Dziękuję za poświęcony czas i pozdrawiam wszystkich. Lajkujcie, subskrybujcie bądzcie moimi followersami i co się tam jeszcze robi
  2. 2 punkty
    Nie robiłem przeglądu całego kodu, tylko szybko "rzuciłem okiem". A że zabolało to napisałem... Pierwsza sprawa to formatowanie pliku nagłówkowego. Niby nie jest to wymagane, ale miło jeśli czytając ten plik można się domyślić, co robi dana klasa. Natomiast deklarowanie metod bez nazw parametrów tego nie ułatwia: size_t addTask(unsigned int, unsigned int, unsigned int, void (*makeT)()); void removeTask(size_t); To jednak nie jest jeszcze błąd. Pierwszy błąd to brak konstruktora - jakiegokolwiek. Drugi błąd to założenie, że właściwości w klasie będą miały jakieś sensowne wartości początkowe... Ponieważ nic z tym nie zrobiłeś, C++ utworzył domyślny konstruktor oraz konstruktory kopiujące. Więc jeśli ktoś ich użyje to kaboom i kod wyleci przy zwalnianiu pamięci, albo i wcześniej. W metodzie addTask używasz radośnie zmiennej tasks: size_t RZTimer::addTask(unsigned int _wait, unsigned int _iterations, unsigned int _interval, void (*makeT)()) { »·······tasks++; A skąd pomysł, że na początku jej wartość wyniesie zero? Podpowiem - to przypadek, że działa. Następna rzecz to realloc(). Ogółnie w C++ należy unikać zarządzania pamiecią rodem z C. Czyli lepiej używać new[] oraz delete[]. Ale dalej jest jeszcze gorzej. Kod wygląda tak: size_t RZTimer::addTask(unsigned int _wait, unsigned int _iterations, unsigned int _interval, void (*makeT)()) { »·······tasks++; »·······parameters = (parameter*) realloc(parameters, tasks * sizeof(parameter)); Masz więc zmienną parameters, której nie zainicjalizowałeś... I jeszcze przy każdym nowym tasku zwalniasz całą tablicę zadań i tworzysz nową. To jest złe, straszne i niedobre. Poczytaj o listach, można je zaimplementować w moment, a wtedy wystarczy przydzielać pamięć tylko dla nowego zadania. Nie mówiąc już o tym, że skoro piszesz w C++ to może lepiej utworzyć klasę dla zadania i nie trzeba będzie nic alokować dynamicznie. Wbrew pozorom używanie sterty w embedded bywa problematyczne - pojawia się np. fragmentacja pamięci, bez MMU ciężko sobie z nią poradzić. Pewnie błędów jest więcej, ale nie miałem odwagi czytać. Proponuję schować ten kod głęboko i nie pokazywać, bo wstyd. Lepiej najpierw opanować podstawy programowania, a później pisać biblioteki i się nimi chwalić.
  3. 1 punkt
    Krótki opis mojego projektu, zamieszczony również na zaprzyjaźnionym forum, a za pomoc i zaangażowanie, teraz i w przyszłości, dziękuję wszystkim pomocnym z forum FORBOTa : Do zbudowania układu posłużyły mi: klon Arduino MEGA, ethernet Shield do wyżej wymienionego, kilka(podłączony na razie jeden) czujników temperaturyDS18B20, dwa czujniki typu DHT11, ale zamienię je chyba na DHT22, czujnik ciśnienia i temperatury BMP280 I2C, moduł zegarowy RTC1307 I2C, enkoder z przyciskiem, wyświetlacz LCD 20×4 I2C, listwa diod programowalnych 8szt (będzie zamieniona na dwie po 4 szt), czujnik deszczu, buzzer bez generatora, tablet. Układ mierzy temperaturę w dwóch miejscach w domu, na zewnątrz temperaturę w słońcu, przy gruncie i 1m nad gruntem w cieniu. Dodatkowo mierzy ciśnienie atmosferyczne, wilgotność zewnętrzną i wewnętrzną oraz temperaturę wody w CO. Funkcją dodatkową jest alarm wywoływany przy pierwszych opadach deszczu, a także (na wyraźne życzenie żony) alarm informujący kiedy pralka w piwnicy skończyła pracę. Kolejną funkcją układu jest sterowanie pracą 8 przekaźników obsługujących min. bramę, furtkę, oświetlenie. O stanie pracy przekaźników informują programowalne diody LED. Enkoder służy do poruszania się po menu na LCD20x4(prawo, lewo, przycisk), każdy obrót i wciśnięcie jest sygnalizowane przez buzzer. Docelowo planuję dołożyć czujnik zanieczyszczenia powietrza, mierzący pył PM2,5, PM10. Wszystkie dane z czujników są na bieżąco wyświetlane i przewijane na LCD 20×4, po wciśnięciu przycisku enkodera wchodzimy w menu opcje gdzie możemy na LCD20x4 sprawdzić najwyższy i najniższy odczyt każdego z czujników, datę tego odczytu oraz zresetować pamięć dla każdego odczytu i czujnika z osobna. Pierwszą pozycją w menu opcje jest kolejne podmenu Włączniki, w którym możemy sterować poprzez enkoder wszystkimi ośmioma przekaźnikami. Każdy z przekaźników jest sterowany sygnałem z arduino idącym przez bramki OR do których dochodzą także sygnały z zewnętrznych włączników naściennych. Dopiero sygnał za bramką OR idzie do przekaźnika oraz dodatkowo jako potwierdzenie wraca do arduino. Dioda led informuje o włączeniu przekaźnika także, kiedy tenże jest włączony „poza arduino” przez włącznik naścienny. Informacja o tym fakcie wraca do arduino powodując odpowiednie zmiany zmiennych i na bieżąco aktualizując diody led i informacje wyświetlane na LCD 20×4. Osobną sprawą jest BLYNK który miał służyć początkowo tylko do kontroli przez telefon nad przekaźnikami, ale po poznaniu jego możliwości, całkowicie zmieniłem założenia i teraz to tablet z zainstalowanym Blynkiem jest głównym wyświetlaczem i sterownikiem całego układu. Na tablecie mam podmenu: przekaźniki, czujniki, max i min, historia, alarmy. W menu przekaźniki sterujemy z tableta i telefonu, w dowolnym miejscu na świecie, przekaźnikami, otrzymując z powrotem informację o faktycznym włączeniu przekaźnika(zmiana koloru widgeta oraz wyświetlonego na nim napisu) , także przez kogoś innego(przez włącznik ścienny, lub drugie urządzenie:tablet lub telefon). Choć poprzez udostępnienie tokena do naszego projektu takich urządzeń może być więcej. Drugie menu to wyświetlanie danych z wszystkich czujników odświeżane co 1 min, oraz mała „dioda led” migająca i informująca o prawidłowej komunikacji apka-arduino. Kolejne menu to ekran z rozwijanym podmenu na którym wyświetlone są nazwy wszystkich czujników i poprzez wybór któregoś z nich możemy sprawdzić(podobnie jak to było na LCD20x4), najniższą i najwyższą wartość i zresetować pamięć dla każdego czujnika osobno. Następne menu to historia, ja mam ustawione wyświetlanie na wykresach historii odczytów ciśnienia atmosferycznego i wigotności. Ostatnie menu to alarmy. Po pojawieniu się na odpowiednim pinie arduino sygnału z czujnika deszczu lub sygnału o końcu pracy pralki, na wyświetlaczu LCD20x4 przestaje się przewijać informacja o dacie, godzinie i odczytach z czujników, a wyświetla się info o alarmie z odpowiednią treścią, albo o pralce albo o deszczu. Dodatkowo listwa diod led miga jak szalona wszystkimi kolorami i sposobami. Po wciśnięciu enkodera lub upływie ustawionego czasu alarm wyłącza się. Informacja o alarmie pojawia się też na tablecie i telefonie, w sposób wizualny i dźwiękowy, poprzez wybraną melodię z pamięci talefonu/tableta. Dodam jeszcze, że do tabletu dam dorobić fajną ramkę, w której tenże tablet umocuję, dodatkowo w ramce umoieszczę listwy led informujące o stanie przekaźników, niezależnie od tabletu i wyświetlanego na nim menu, a ramka przy okazji będzie też kryć kabel zasilający tablet:-) To chyba tyle, jakby coś to pytajcie i doradzajcie:-)
  4. 1 punkt
    Służba czasu ma istotne znaczenie przy różnego rodzaju obserwacjach astronomicznych. M.in do rejestracji jasności gwiazd zmiennych (szczególnie krótkookresowe zmienne zaćmieniowe wymagają dokładnego zanotowania momentu obserwacji), czasu wystąpienia zjawisk zakryciowych czy też w oczekiwaniu na tranzyt np ISS na tle Słońca czy Księżyca. Zainspirowany projektem opisanym w niedawnym artykule przedstawiam swój stary pomysł, o nieco innych założeniach i chyba bardziej przydatny do faktycznych obserwacji nieba. Do budowy możemy wykorzystać moduł oparty na mikrokontrolerze ATmega328P, np Arduino UNO, Nano czy nawet Pro Mini (co zapewni nam energooszczędność i dłuższy czas pracy na baterii). Bardzo istotne, by wybrać moduł GPS z wyprowadzonym sygnałem PPS. Zrealizowałem go w dwóch wersjach: z wyraźnym wyświetlaczem siedmiosegmentowym LED z kontrolerem MAX7219 i alarmem oraz mniej wyraźnym OLED, za to z opcją zapamiętywania momentów ostatnich naciśnięć przycisku. /* DIN - 12 CLK - 11 LOAD - 10 */ #include "LedControl.h" //http://github.com/wayoda/LedControl #include <Time.h> // http://www.pjrc.com/teensy/td_libs_Time.html #include <TinyGPS++.h> // http://arduiniana.org/libraries/tinygpsplus/ #include <SoftwareSerial.h> #define UsePPS 1 #define PPSPin 2 #define UTCcorrection -2 #define TimeZone 0 #define BuzzerPin 13 static const int RXPin = 3, TXPin = 4; unsigned long syncTime = 0, cycle = 0; bool sync = 0; tmElements_t tmbegin; unsigned long beginTime = 0; TinyGPSPlus gps; LedControl lc = LedControl(12, 11, 10, 1); SoftwareSerial ss(RXPin, TXPin); void setup() { Serial.begin(9600); tmbegin.Hour = 20; tmbegin.Minute = 42; tmbegin.Second = 36; tmbegin.Day = 17; tmbegin.Month = 1; tmbegin.Year = 2019 - 1970; beginTime = makeTime(tmbegin); Serial.println("Begin time: " + String(beginTime)); ss.begin(9600); if (UsePPS) { pinMode(PPSPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(PPSPin), PPS, RISING); } pinMode(BuzzerPin, OUTPUT); digitalWrite(BuzzerPin, LOW); /* The MAX72XX is in power-saving mode on startup, we have to do a wakeup call */ lc.shutdown(0, false); /* Set the brightness to a medium values */ lc.setIntensity(0, 1); /* and clear the display */ lc.clearDisplay(0); } void loop() { while (!sync && ss.available() > 0) { gps.encode(ss.read()); } if (millis() - syncTime - cycle * 1000 >= 1000) { String digit = String(second()); if (digit.length() == 1) { lc.setChar(0, 0, digit[0], false); lc.setChar(0, 1, '0', false); } else { lc.setChar(0, 0, digit[1], false); lc.setChar(0, 1, digit[0], false); } digit = String(minute()); if (digit.length() == 1) { lc.setChar(0, 2, digit[0], true); lc.setChar(0, 3, '0', false); } else { lc.setChar(0, 2, digit[1], true); lc.setChar(0, 3, digit[0], false); } digit = String(hour()); if (digit.length() == 1) { lc.setChar(0, 4, digit[0], true); lc.setChar(0, 5, '0', false); } else { lc.setChar(0, 4, digit[1], true); lc.setChar(0, 5, digit[0], false); } if (now() - (TimeZone * 60 * 60) >= beginTime) { digitalWrite(BuzzerPin, HIGH); } cycle++; Serial.println(String(year()) + "." + String(month()) + "." + String(day()) + " " + String(hour()) + ":" + String(minute()) + ":" + String(second()) + " UNIX time: " + String(now())); } } void PPS() { if (gps.time.isUpdated() && gps.date.year() > 2015 && !timeStatus()) { setTime(gps.time.hour(), gps.time.minute(), gps.time.second(), gps.date.day(), gps.date.month(), gps.date.year()); adjustTime(UTCcorrection + (TimeZone * 60 * 60) + 1); syncTime = millis(); cycle = 0; detachInterrupt(digitalPinToInterrupt(PPSPin)); sync = 1; } Serial.println("PPS"); } Arduino "czyta" UART ze strony modułu GPS dopóki zegar nie jest zsynchronizowany. while (!sync && ss.available() > 0) { gps.encode(ss.read()); } Jeżeli GPS odczyta aktualny czas, Arduino czeka do najbliższego przerwania dokonanego przez wzrastające zbocze sygnału PPS. Wtedy ustawiany jest "zegarek" w bibliotece Time. Po tym deaktywowane jest przerwanie pinu PPS. Po uruchomieniu urządzenia sprawdźmy, czy działa ono poprawnie. Porównajmy wskazania np ze stroną https://time.is. Być może konieczna będzie korekcja sekund przestępnych, gdyż GPS prezentuje czas nieskoordynowany. Zrobimy to poprawiając #define UTCcorrection -2 Alarm możemy ustawić edytując tmbegin.Hour = 20; itd. Brzęczek podłączony do pinu 13 ostrzeże nas, że za chwilę nastąpi przejście Międzynarodowej Stacji Kosmicznej na tle Słońca lub Księżyca, a my musimy szczególnie się skupić. Możemy nawet podłączyć w to miejsce transoptor, który "podkablowany" do lustrzanki cyfrowej automatycznie zacznie wykonywać serię zdjęć (wcześniej ustawmy aparat w "continuous shooting mode")! Takie zjawisko trwa około sekundy i szczególnie w przypadku Słońca jest zupełnie niespodziewane (wizualnie dla obserwatora, wcześniej możemy jednak wyliczyć stosowny moment) i łatwo je przegapić. Tranzyt ISS na tle Słońca sfotografowany automatycznie 8 kwietnia 2017. Zjawisko wystąpiło bardzo nisko nad horyzontem. Stąd... komin sąsiada (czarny pasek) widoczny po lewej. Po prawej plama słoneczna. ISS to ta prostokątna plamka na środku wysokości, po prawej. Wersja ze stoperem wykorzystuje wyświetlacz OLED z kontrolerem SPI SH1106. W pierwszej linijce prezentowany jest aktualny czas. W kolejnych - historia zatrzymań stopera. /* OLED Arduino D0-----------10 D1-----------9 RST----------13 DC-----------11 VCC----------5V GND----------GND*/ #include <Time.h> // http://www.pjrc.com/teensy/td_libs_Time.html #include <TinyGPS++.h> // http://arduiniana.org/libraries/tinygpsplus/ #include <SPI.h> #include <Adafruit_GFX.h> // http://github.com/adafruit/Adafruit-GFX-Library #include <Adafruit_SSD1306.h> // http://github.com/adafruit/Adafruit_SSD1306 #include <SoftwareSerial.h> #define PPSPin 2 #define ButtonPin 3 #define UTCcorrection -1 // difference between time received from TinyGPS++ library and UTC (leap seconds!) http://time.is/UTC #define remeberValues 3 #define OLED_MOSI 9 #define OLED_CLK 10 #define OLED_DC 11 #define OLED_CS 12 #define OLED_RESET 13 #define NUMFLAKES 10 #define XPOS 0 #define YPOS 1 #define DELTAY 2 unsigned long pushsFIFO[remeberValues]; unsigned long lastButtonchange = 0, syncUNIXtime = 0, syncMillis = 0, pushTime = 0, pushTimeUNIX = 0; unsigned char LCDrefreshSecond = 0; static const int RXPin = 4, TXPin = 5; static const uint32_t GPSBaud = 9600; unsigned long cutnumber(); String timeString(); String millisToTimeString(); void addToFIFO(); TinyGPSPlus gps; tmElements_t tm; SoftwareSerial ss(RXPin, TXPin); Adafruit_SSD1306 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS); /* Uncomment this block to use hardware SPI #define OLED_DC 6 #define OLED_CS 7 #define OLED_RESET 8 Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS); */ void setup() { Serial.begin(9600); ss.begin(GPSBaud); pinMode(PPSPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(PPSPin), PPS, RISING); pinMode(ButtonPin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(ButtonPin), button, FALLING); display.begin(SSD1306_SWITCHCAPVCC); display.clearDisplay(); for (int i = 0; i < remeberValues; i++) { pushsFIFO[remeberValues] = 0; } } void loop() { while (ss.available() > 0) { gps.encode(ss.read()); } if (pushTime) { Serial.print("Button push time: "); Serial.print(pushTime); Serial.print(" sync time: "); Serial.print(syncMillis); Serial.print(" sync UNIX time: "); Serial.println(syncUNIXtime); Serial.println(millisToTimeString(pushTime)); Serial.println(second()); pushTime = 0; } if (LCDrefreshSecond != cutnumber(millis() - syncMillis, 4, 3)) { breakTime(now(), tm); display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 0); display.print(tm.Month); display.print("/"); display.print(tm.Day); display.print("/"); display.print((tm.Year > 0) ? tm.Year - 30 : 0); display.print(" "); display.print(tm.Hour); display.print(":"); display.print(tm.Minute); display.print(":"); display.print(tm.Second); display.println("UTC"); for (int i = 0; i < remeberValues; i++) { if (pushsFIFO[i] == 0) { break; } display.print(i + 1); display.print(": "); display.println(millisToTimeString(pushsFIFO[i])); } display.display(); LCDrefreshSecond = cutnumber(millis() - syncMillis, 4, 3); } } void PPS() { if (gps.time.isUpdated() && gps.date.year() > 2015 && !timeStatus()) { syncMillis = millis(); setTime(gps.time.hour(), gps.time.minute(), gps.time.second(), gps.date.day(), gps.date.month(), gps.date.year()); adjustTime(UTCcorrection + 1); detachInterrupt(digitalPinToInterrupt(PPSPin)); syncUNIXtime = now(); } Serial.println("PPS"); } void button() { if (millis() - lastButtonchange > 500) { pushTime = millis(); addToFIFO(pushTime); LCDrefreshSecond = LCDrefreshSecond + 5; } lastButtonchange = millis(); } unsigned long cutnumber(unsigned long number, unsigned int cutbeg, unsigned int cutend) { number = number - pow(10, cutbeg) * (unsigned long) (number / pow(10, cutbeg)); if (cutend != 0) { number = (unsigned long) (number / pow(10, cutend)); } return number; } String timeString(unsigned long timeUNIX) { breakTime(timeUNIX, tm); String timeWord = String(tm.Hour) + ":" + String(tm.Minute) + ":" + String(tm.Second); return timeWord; } String millisToTimeString(unsigned long inputMillis) { pushTimeUNIX = syncUNIXtime + (inputMillis - syncMillis) / 1000; String timeWord = timeString(pushTimeUNIX) + "." + cutnumber(inputMillis - syncMillis, 3, 0); return timeWord; } void addToFIFO(unsigned long value) { for (int i = remeberValues - 1; i > 0; i--) { pushsFIFO[i] = pushsFIFO[i - 1]; } pushsFIFO[0] = value; } Stoper dedykowany jest obserwatorom zjawisk zakryciowych. Tuż przed zakryciem gwiazdy 4 Sgr przez Księżyc. Do fotografowania dłuższych zjawisk astronomicznych (np zaćmień Słońca czy Księżyca) możemy wykorzystać szkic GPS_DSLR_timer.ino. Ustawimy tam moment początku i końca oraz interwał czasu, z jakim chcemy automatycznie fotografować zjawisko. Możemy też wykonać mniej dokładny zegarek synchronizowany serwerem NTP. Użyjemy w tym celu ESP8266 oraz wyświetlacza LCD 2x16 z konwerterem I2C LCM1602. Jeżeli napotkamy problem z uruchomieniem tego "monitora", pamiętajmy że występuje on pod różnymi adresami I2C (pierwsza zmienna przy wywołaniu konstruktora biblioteki LCD LiquidCrystal_I2C lcd(0x27, 16, 2);). Czasem też konieczna jest regulacja kontrastu kręcąc potencjometrem znajdującym się pod spodem. Co ciekawe niewielka zmiana napięcia zasilającego powoduje zmianę prezentowanego kontrastu. /* I2C D4 - SCL D3 - SDA */ #include <ESP8266HTTPClient.h> #include <ESP8266WiFi.h> #include <WiFiClientSecure.h> #include <WiFiUdp.h> #include <Wire.h> #include <LiquidCrystal_I2C.h> //https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library #include <Time.h> // http://www.pjrc.com/teensy/td_libs_Time.html IPAddress timeServerIP; // time.nist.gov NTP server address const char* ntpServerName = "time.google.com"; const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message byte packetBuffer[ NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets unsigned long last_time_sync = 0, last_NTP_check = 0, last_time_LCD = 0; unsigned int localPort = 2390; // local port to listen for UDP packets // A UDP instance to let us send and receive packets over UDP WiFiUDP udp; LiquidCrystal_I2C lcd(0x27, 16, 2); tmElements_t tm; time_t getNtpTime(); void setup() { Serial.begin(9600); //Serial connection Wire.begin(D3, D4); Wire.setClock(100000); lcd.begin(); lcd.backlight(); WiFi.softAPdisconnect(); WiFi.disconnect(); WiFi.mode(WIFI_STA); WiFi.begin("Siec WiFi", "i haslo do niej"); //WiFi connection while (WiFi.status() != WL_CONNECTED) { //Wait for the WiFI connection completion delay(500); Serial.println("Waiting for connection"); } udp.begin(localPort); } void loop() { if (millis() - last_time_sync > 10 * 24 * 60 * 60 * 1000 || last_time_sync == 0) { unsigned long unixt = unix_time(); Serial.println(unixt); if (unixt > 1512876158) { Serial.println("SYNC OK"); setTime(unixt); last_time_sync = millis(); } } unsigned long nowTime = now(); if (nowTime > last_time_LCD) { last_time_LCD = nowTime; lcd.clear(); lcd.setCursor(0, 0); lcd.print(String(year()-2000) + "." + String(month()) + "." + String(day()) + " " + String(hour()) + ":" + String(minute()) + ":" + String(second())); lcd.setCursor(0, 1); lcd.print("UNIX " + String(now())); Serial.println(String(year()) + "." + String(month()) + "." + String(day()) + " " + String(hour()) + ":" + String(minute()) + ":" + String(second()) + " UNIX time: " + String(now())); } } // send an NTP request to the time server at the given address //https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/NTPClient/NTPClient.ino unsigned long sendNTPpacket(IPAddress& address) { //Serial.println("sending NTP packet..."); // set all bytes in the buffer to 0 memset(packetBuffer, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request // (see URL above for details on the packets) packetBuffer[0] = 0b11100011; // LI, Version, Mode packetBuffer[1] = 0; // Stratum, or type of clock packetBuffer[2] = 6; // Polling Interval packetBuffer[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBuffer[12] = 49; packetBuffer[13] = 0x4E; packetBuffer[14] = 49; packetBuffer[15] = 52; // all NTP fields have been given values, now // you can send a packet requesting a timestamp: udp.beginPacket(address, 123); //NTP requests are to port 123 udp.write(packetBuffer, NTP_PACKET_SIZE); udp.endPacket(); } time_t unix_time() { if (WiFi.status() == WL_CONNECTED && ((unsigned long)(millis() - last_NTP_check) > 15000 || last_time_sync == 0)) { last_NTP_check = millis(); //get a random server from the pool WiFi.hostByName(ntpServerName, timeServerIP); sendNTPpacket(timeServerIP); // send an NTP packet to a time server // wait to see if a reply is available delay(1000); int cb = udp.parsePacket(); if (!cb) { Serial.println("no packet yet"); } else { //Serial.print("packet received, length="); //Serial.println(cb); // We've received a packet, read the data from it udp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer //the timestamp starts at byte 40 of the received packet and is four bytes, // or two words, long. First, esxtract the two words: unsigned long highWord = word(packetBuffer[40], packetBuffer[41]); unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]); // combine the four bytes (two words) into a long integer // this is NTP time (seconds since Jan 1 1900): unsigned long secsSince1900 = highWord << 16 | lowWord; Serial.print("Seconds since Jan 1 1900 = " ); Serial.println(secsSince1900); // now convert NTP time into everyday time: Serial.println("Unix time sync "); // Unix time starts on Jan 1 1970. In seconds, that's 2208988800: const unsigned long seventyYears = 2208988800UL; // subtract seventy years: unsigned long epoch = secsSince1900 - seventyYears; // print Unix time: if (epoch > 1512876158) { return epoch + 2; } else { return 0; } } } } Do komunikacji z serwerem NTP wykorzystałem poradnik Arduino Time Sync from NTP Server using ESP8266 WiFi module.
  5. 1 punkt
    Nie czepiałbym się tego kodu tak bardzo, gdyby to był zwykły program. Każdy się kiedyś uczył, a kto nie robi błędów niech pierwszy rzuci kamień... Ale tutaj mamy "bibliotekę", którą co najgorsze może użyć ktoś w swoim programie i przeszczepi wszystkie koszmarki. Więc jeśli zmienimy nazwę "biblioteka" na własny program i nie będziemy tego sprzedawać innym jako dobre i działające, wtedy ok, fajnie że Autor chce się czegoś nauczyć. Tylko niech od razu napisze, że to wadliwy prototyp, a nie biblioteka do wykorzystania.
  6. 1 punkt
    Osobiście ciężko mi się z tym zgodzić. Próba autora to takie "nieskończone DIY" tylko wśród tworzenia kodu. Być może zła kategoria na forum, być może niepotrzebne przekonanie o sensowność rozwiązania, ale wpis jak najbardziej sensowny, bo gdzie jak nie w komentarzach autor ma się czegoś nauczyć? Zaprezentował kod, dostał wskazówki na poprawę i chyba o to właśnie chodzi, co nie?
  7. 1 punkt
    I bardzo dobrze - po prostu nigdy. HTML renderowany jest po stronie przeglądarki, a PHP działa po stronie serwera i dopiero może stworzyć kod HTML (w zasadzie może stworzyć cokolwiek, ale na początek przyjmijmy że będziemy tworzyć HTML). W dodatku wszystko, co nie jest ujęte w znaczniki języka <?php ... ?> jest bezpośrednio i bez żadnych zmian kopiowane na wyjście skryptu. Stwórz sobie taki pliczek i zapisz go w swoim katalogu domowym pod nazwą test.php: <!DOCTYPE html> <head> <title>Test PHP</title> </head> <body> <?php $a = 5; $b = $a * $a; echo "<span>5<sup>2</sup>=$b</span>"; ?> </body> </html> Teraz wykonaj polecenie: php test.php Powinieneś zobaczyć, co interpreter PHP zrobił z tym plikiem. Jeśli Ci się udało i zobaczyłeś kod w HTML - skopiuj ten plik na swój serwer i przeglądarką wejdż na adres: http://twój_ip/.../test.php (zamieniając oczywiście te trzy kropki w ścieżkę do pliku). Powinieneś zobaczyć efekt działania interpretera - mianowicie taki, że umie pomnożyć 5 x 5 Czy to mniej więcej wyjaśnia, o co w tym wszystkim chodzi?
  8. 1 punkt
    Sortowanie zadań wg najbliższego wydarzenia na pewno poprawiłoby wydajność biblioteki. Może zamiast cierpkich (choć ZASŁUŻONYCH) słów mógłbyś choć troche pomóc i powiedzieć, jak efektywniej alokować pamięć bez użycia realloc i nie mając dostępu do STL C++? Bez zewnętrznych bibliotek nie mam STL w Arduino.
  9. 1 punkt
    Proponuję zamiast pisania bibliotek mały kurs C++. I to nie napisać, ale przeczytać. Na początek temat: konstruktory. Kolejny to alokacja pamięci, bo użycie realloc to marny pomysł. Przy okazji może jakieś podstawy struktur danych, np. listy? Ogólnie napisanie biblioteki jest trudniejsze niż napisanie zwykłego programu. I lepiej jeśli za takie wyzwania zabierają się osoby z pewnym doświadczeniem oraz umiejętnościami. Niestety w Arduino pisać każdy może... a później pojawiają się opinie o marnej jakości kodu bibliotek dla Arduino - i nawet ciężko się z tym nie zgodzić.
  10. 1 punkt
    Na szczęście wszystko działa. Wystarczylo zmienić port com. Tak używam orginalnego arduino. Dziękuje wszystkim za rady i poświęcony czas
  11. 1 punkt
    Sterowanie silnikiem DC za pomocą mostka L293D zostało również omówione w naszym kursie Arduino. Wystarczy dostosować odpowiednio wyprowadzenia do Twojej płytki: Kurs Arduino – #8 – Sterowanie silnikami DC, pętla for
  12. 1 punkt
    @beszt, witam na forum Widzę, że to Twoje pierwsze kroki na Forbocie, oto najważniejsze informacje na start: Chcesz przywitać się z innymi członkami naszej społeczności? Skorzystaj z tematu powitania użytkowników. Opis najciekawszych funkcji, które ułatwiają korzystanie z forum znajdziesz w temacie instrukcja korzystania z forum - co warto wiedzieć? Poszczególne posty możesz oceniać (pozytywnie i negatywnie) za pomocą reakcji - ikona serca w prawym dolnym rogu każdej wiadomości. Adres/identyfikator urządzenia ustawia się za pomocą wejść opisany jako A0 oraz A1. Adres zależy również od tego czy zapisujemy, czy odczytujemy dane - jest to opisane w dokumentacji: Jest tam podana informacja na temat sposobu '"obliczenia" identyfikatora: dla odczytu mamy binarnie 01000001, co daje 0x41 dla zapisu mamy binarnie 010000000, co daje 0,40 Gdzie pogrubione 00 to wartości ustawione za pomocą pinów A0 oraz A1
  13. 1 punkt
    Kolega odkrył koło na nowo Oficjalna biblioteka SimpleTimer Arduino Poza tym można natrafić na identyczną funkcjonalność w postaci Timera Blynk - podstawa wysyłania danych do chmury.
  14. 1 punkt
    Szybkie pytanie do osób zajmujących się programowaniem Qt. Mianowicie czy istnieje jakaś prosta metoda na uzyskanie animacji tekstu wprowadzanego znak po znaku, w obiekcie QTextBrowser? Zależy mi szczególnie na tym, żeby tekst dało się sformatować tagami HTML.
  15. 1 punkt
    Czynników może być wiele. Sprawdź zasilacz do Rasberry - na pewno nie powinien to być zasilacz od telefonu, bo to będzie loteria. Powinien dostarczać minimum 1A. Jak masz krótszy kabel HDMI to może pomóc - może wkradła się jakaś niewydajność. Z kwestii programowych to możesz zajrzeć co jest w config.txt - plik ten zobaczysz na partycji boot po włożeniu karty z RPi do komputera. Możesz dopisać w tym pliku taki fragment. Powinno to "wymusić" używacie HDMI. hdmi_force_hotplug=1 "Setting hdmi_force_hotplug to 1 pretends that the HDMI hotplug signal is asserted, so it appears that a HDMI display is attached. In other words, HDMI output mode will be used, even if no HDMI monitor is detected." Innym pomysłem jest podkręcenie tego parametru. Pewnie masz tam 5, więc daj np 7. config_hdmi_boost=5 Możesz przejrzeć dokumentację, jest tam kilka innych parametrów z opisem użycia.
  16. 1 punkt
    Mam wrażenie, że w Minisumo był jakiś przestój, gdy starsi zawodnicy przestali już jeździć na zawody, a młodych brakowało. Na szczęście coraz częściej widać nowe konstrukcje i jest szansa na to, że powoli ilość i jakość robotów w tej kategorii wzrośnie.
  17. 1 punkt
  18. 1 punkt
    Masz kilka opcji: - Postawienie serwera w jakimś hostingu, jak wspomniano wyżej. - Postawienie sobie jakiegoś proxy czy VPN na własnym VPS (AWS daje free tier gdzie mamy małego VPSa na rok bez opłat). Ale bez jakieś wiedzy z zakresu security i administracji nie polecam stawiać swojego VPSa. - Hole punching (np: pwnat) tylko to wydłuży kilkukrotnie czas nawiązania połączenia. - Może jeszcze UPnP
  19. 1 punkt
    Był. Trzeba go było wyeliminować przez chwilowe wygaszanie jednej lampy przed zapaleniem następnej.
  20. 1 punkt
    @pesimist oczywiście masz rację. Była to literówka, już poprawiłem Post wydzielony z:
  21. 1 punkt
    Precyzyjne, mechaniczne dzieło sztuki:
  22. 1 punkt
    Czy bylibyście zainteresowani programami komputerowymi oraz mobilnymi do sterowania Arduino poprzez port szeregowy lub Bluetooth? - konsolowa aplikacja C++ - graficzna aplikacja Qt C++ Obydwa programy sterują zasilaniem w amatorskim obserwatorium astronomicznym. "Odcinają prąd" po skończonej sesji obserwacyjnej. - aplikacja mobilna Apache Cordova do łączenia się z Arduino poprzez Bluetooth Program ten steruje wyzwalaczem do lustrzanki cyfrowej z interwałometrem.
  23. 1 punkt
    OOO Miło zobaczyć Nixie na forbocie Też bawię się w budowę i już popełniłem parę zegarków... można zobaczyć na https://www.nixietime.pl/ Obecnie jestem na etapie robienia bardziej kompaktowej wersji, oraz uniwersalnego sterownika do różnych lamp. Swoje zegary opierałem o tranzystory MMBTA... Ty użyłeś widzę Transoptor'ow oraz jednego układu 74141.... pytanie... jak Ci to działa?:) czy nie ma problemu duszków? Szukam jakiegoś dobrego sterowania do tych lampek które nie będzie wymagało "miliona" elementów.
  24. 1 punkt
    Tym razem prezentuję jeden z moich starszych projektów. Powstał on w 2013 roku, będąc pierwszą poważniejszą próbą umiejętności zdobytych podczas nauki programowania mikrokontrolerów AVR. Wszystko zaczęło się jakiś czas wcześniej, gdy do moich rąk trafił stary, polski telefon z tarczą numerową, wyprodukowany przez przedsiębiorstwo RWT w latach sześćdziesiątych. Któryś z poprzednich właścicieli tego urządzenia potraktował je jako źródło części - wewnątrz brakowało większości elementów potrzebnych do normalnej pracy. Na szczęście obudowa zachowała się w idealnym stanie. Przywrócenie telefonu do stanu oryginalnego mijało się z celem, więc w najlepszym razie mógłby on służyć za stylową dekorację. W pewnym momencie wpadłem na inny pomysł co do zastosowania tego zabytku. Mniej więcej w tym samym czasie udało mi się bowiem zdobyć kilka modułów GSM Motorola D15, wymontowanych ze złomowanych centralek alarmowych. Rozwiązanie nasuwało się samo - zrobić z tego "komórkę". Urządzenie działa w oparciu o mikrokontroler Atmega328, którego głównym zadaniem jest sterowanie modułem GSM za pomocą komend AT. Układ zajmuje się także zliczaniem impulsów wysyłanych przez tarczę numerową podczas wybierania numeru, a także generuje sygnał PWM udający sygnały wybierania i zajętości, Najbardziej problematycznym elementem był dzwonek, wymagający do działania cyklicznych zmian przepływu prądu. Zadanie to jest realizowane prze prosty półmostek H. Ponieważ dzwonek wymaga do pracy napięcia co najmniej kilkudziesięciu V, w grę wchodziły dwa rozwiązania: zbudowanie przetwornicy albo przewinięcie uzwojeń. Zdecydowałem się na drugie z nich. Urządzenie wyposażone jest we wbudowany akumulator litowo-polimerowy oraz scalony kontroler ładowania MCP73831T. Podczas budowy telefonu popełniłem kilka błedów oraz poszedłem na kilka kompromisów, na które dzisiaj w żadnym razie bym się nie zgodził. Najważniejsze problemy tej konstrukcji to: Pojawiające się okazjonalnie zakłócenia, będące wynikiem zastosowania modułu GSM bez różnicowego toru audio. Dziś zastosowałbym któryś z tanich i ogólnodostępnych modułów GSM. Brak stabilnego zasilania. Cała elektronika jest zasilana bezpośrednio napięciem akumulatora. Nie stanowi to problemu, ponieważ wartości mieszczą się w dopuszczalnych warunkach pracy wszystkich elementów, a wraz z rozładowywaniem akumulatora zmienia się wspólny punk odniesienia, wyznaczany przez VCC. Dzisiaj jednak zastosowałbym przetwornicę S7V8F3. Program został napisany w sposób blokujący, w oparciu o "delay'e" oraz pętle oczekujące na wykonanie określonego zadania. Z uwagi na powyższe projekt w końcu doczeka się zapewne uwspółcześnionej rewizji.
  25. 1 punkt
    Obudowa do głównego wyświetlacza, gotowa.
Tablica liderów jest ustawiona na Warszawa/GMT+02:00
×