Urządzenie wskazujące położenie Międzynarodowej Stacji Kosmicznej

Urządzenie wskazujące położenie Międzynarodowej Stacji Kosmicznej
Pobierz PDF Download icon

Międzynarodowa Stacja Kosmiczna (ISS) znajduje się na orbicie ok. 400 km nad Ziemią. Okrąża ją w około 1,5 h i czasami widoczna jest na niebie (dzięki ogniwom fotowoltaicznym odbija sporo światła – jej jasność przekracza Wenus i może być widoczna gołym okiem nawet za dnia. Tylko jak ją odnaleźć na wielkim niebie? Opisane urządzenie będzie śledzić w czasie rzeczywistym położenie ISS i będzie stale wskazywało na nią, gdy orbituje wokół Ziemi.

System jest zasilany z ogniw litowo-jonowych, dzięki czemu można go z łatwością używać poza domem. Jego pracą steruje moduł z mikrokontrolerem ESP32, który łączy się z Wi-Fi w celu pobrania aktualnych współrzędnych ISS. Następnie wykonuje obliczenia, aby wyznaczyć kąty między obserwatorem na Ziemi a ISS na niebie, tak, aby mógł skierować wskaźnik w jego stronę. Lokalizacja ISS jest aktualizowana, co 5 sekund, więc urządzenie będzie ją dokładnie śledziło, gdy porusza się po niebie.

Potrzebne elementy

Na rysunku 1 pokazano schemat konstrukcyjny.

Rysunek 1. Schemat konstrukcyjny

Do budowy urządzenia potrzebne będą następujące elementy:

  • mikrokontroler ESP32 zintegrowany w module,
  • wyświetlacz OLED o przekątnej 0,91" i rozdzielczości 128×32 pikseli,
  • moduł ładowarki akumulatorów litowo-jonowych (2S – 7,4 V),
  • zasilacz oparty na układzie MP1584EN,
  • płytka uniwersalna (25×13 otworów),
  • goldpiny i złącza o rastrze 2,54 mm,
  • dwa ogniwa litowo-jonowe 18650 oraz koszyczek na nie,
  • dwa silniki krokowe 28BYJ-48,
  • dwie płytki sterowników silnika krokowego ULN2003,
  • łożysko 60002RS (10x26x8 mm),
  • pierścień ślizgowy z sześcioma torami,
  • przełącznik kołyskowy KCD1-104,
  • gniazdo zasilacza 2,1 mm,
  • przewody połączeniowe do łączenia obwodów,
  • zestaw różnych śrub i nakrętek,
  • elementy wydrukowane w technice 3D (pliki do druku 3D znaleźć można na portalu Thingverse https://bit.ly/3a96XsJ).

Moduł sterujący

Głównym elementem urządzenia jest mikrokontroler ESP32, który wykonuje wszystkie obliczenia i steruje silnikami krokowymi, aby ustawić wskaźnik względem ISS. Zastosowany moduł z ESP32 ma postać małej płytki rozwojowej, dzięki czemu posiada złącze micro USB, ułatwiające programowanie z komputera. Zostanie umieszczony na płytce uniwersalnej, pokazanej na fotografii 1a, która ułatwi jego integrację z pozostałymi elementami wskaźnika.

Fotografia 1. Sposób montażu modułu z ESP32 na płytce uniwersalnej

Montaż rozpoczynamy od kawałka płytki uniwersalnej z otworami o rastrze 2,54 mm i ułożeniu 24×13. Po przylutowaniu złącz i goldpinów, tak jak na fotografii 1b, należy przeciąć miedziane paski, aby każda strona ESP32 była elektrycznie oddzielona. Autor projektu robi to lekko rozwiercając otwory wiertłem 3 mm. Można to zrobić też ostrym nożem lub skalpelem.

Zamiast wlutować moduł bezpośrednio na płytkę uniwersalną, lepiej jest wlutować złącza żeńskie, aby można było łatwo zamontować oraz wyjąć.

W celu wykonania połączeń z płytką dodano dodatkowy rząd kątowych goldpinów. Połączenia można wykonać przewodami, które mają na końcach typowe złącza do łączenia z goldpinami. Dzięki temu łatwo można łączyć i odłączać różne komponenty od płytki, co ułatwia testowanie i uruchamianie modułu. Złącze USB powinno wystawać poza krawędź płytki uniwersalnej (fotografia 1c), dzięki czemu w obudowie będzie trochę więcej miejsca.

Schemat połączeń

Schemat elektryczny został pokazany na rysunku 2. Pokazuje, jak podłączyć wszystkie komponenty elektryczne ze sobą. Każdy składnik należy dołączyć, a następnie przetestować przed przejściem do następnej sekcji układu. Dzięki temu układ zostanie zbudowany poprawnie i da się łatwo uruchomić. Połączenia zostały wykonane za pomocą typowych dla zestawów uruchomieniowych kabelków ze złączami do goldpinów. Dzięki temu można je łatwo zmieniać bez konieczności ich wylutowywania.

Montaż obudowy urządzenia

Cały układ wykonany jest z elementów wydrukowanych w technice 3D. W pierwszej kolejności należy wydrukować zewnętrzną obudowę sekcji podstawy ze wspornikami, ponieważ posiada ona otwory na przełączniki. Autor wewnętrzną płytkę wydrukował w kolorze czerwonym, aby lepiej było widać je na zdjęciach. Na tym etapie można sprawdzić dopasowanie komponentów, które będą osadzane w obudowie, w tym gniazdo zasilania, włącznik, buzzer, przełącznik dotykowy i wyświetlacz OLED.

Wszystkie otwory w płycie wewnętrznej można rozwiercić do średnicy 2,5 mm, a następnie gwintować gwintownikiem M3 (takim, jak do metalu). Będą one używane, jako punkty mocowania obudowy akumulatora i sterownika silnika krokowego. Należy pamiętać, aby wkręcić śruby mocujące baterię od spodu (płaska powierzchnia), a otwory silnika krokowego od góry (z wgłębieniem na płytkę uniwersalna z modułem ESP32). Wewnętrzna płyta powinna wsuwać się w główny korpus osłony zewnętrznej i będzie spoczywać na dwóch podporach.

Fotografia 2. Montaż bazy układu wraz z modułami elektronicznymi

Aby utrzymać ją na miejscu, można dodać kilka kropli kleju typu superglue (fotografia 2).

Opisując ruch urządzenia astronomicznego, obrót podstawy od lewej do prawej nazywany jest azymutem. W tej sekcji znajduje się również azymutalny sterownik silnika krokowego.

Gotowe płytki z driverem ULN2003 są często pozostawiane z długimi wyprowadzeniami komponentów od strony lutowania. Dobrym pomysłem jest przycięcie ich równo przed montażem.

Płytkę sterownika silnika krokowego można teraz zamocować na miejscu za pomocą przygotowanych śrub maszynowych.

Rysunek 2. Schemat elektryczny opisywanego urządzenia

Teraz należy podłączyć moduł z ESP32 do zasilacza bateryjnego, azymutalnego sterownika silnika krokowego, wyświetlacza OLED i włącznika dotykowego zgodnie ze schematem elektrycznym, pokazanym na rysunku 2.

Zasilanie

Urządzenie może być zasilane z zasilacza sieciowego 5 V przez złącze zasilania, gdy jest uruchomione w pomieszczeniu. Po podłączeniu system będzie ładował ogniwa litowo-jonowe za pomocą specjalnego modułu ładowania, zabezpieczającego je, aby nie ulegały przeładowaniu (ponieważ może to być niebezpieczne). Jeśli kabel ładujący zostanie odłączony, przełącznik z przodu może zasilać urządzenie z wbudowanych ogniw.

Ogniwa litowo-jonowe zostały pozyskane ze starego laptopa. Autor konstrukcji nałożył jedynie na nie nowe, czerwone osłony z rurki termokurczliwej. Ogniwa są umocowane w specjalnym koszyku, który łączy je ze sobą. Sam koszyk przymocowany jest do wewnętrznej płyty urządzenia za pomocą śrub z łbem stożkowym (fotografia 3).

Fotografia 3. Sposób zamontowania koszyków na akumulatorki

Gniazdo zasilania jest podłączone do obwodu ładowarki, a napięcie wyjściowe z ogniw jest podawane do przetwornicy, która stabilizuje napięcie zasilania 5 V.

Obrotnica oraz kopuła

Niezbędne elementy składowe wydrukowane w technice 3D to (angielskie nazwy korespondują z plikami do pobrania z portali Thingverse):

  • 003 Spindle Plate,
  • 003 Centre Spindle,
  • 003 Spacer for Rotating Platform,
  • 003 Involute Azimuth Gear.

Montaż jest bardzo prosty. Należy zamocować silnik krokowy na miejscu za pomocą śrub do metalu, podkładek i nakrętek, tak, aby dobrze trzymał się na miejscu. Gwint osi obrotu można oczyścić za pomocą gwintownika M8, a wydrążony środek należy rozwiercić wiertłem o średnicy 5 mm, aby żadne pozostałości z druku 3D nie zaczepiły o przewody podczas ich przewlekania. Oś jest umieszczana w płycie za pomocą klucza, który zapobiega jej obracaniu się. Kropla kleju zapewnia, że nie zostanie on wypchnięty z swojego miejsca podczas montażu.

Rysunek 3. Projekt zmontowanej podstawy obrotnicy

Na rysunku 3 pokazano projekt zmontowanej podstawy obrotnicy.

Kolejne elementy składowe wydrukowane w technice 3D to:

  • 004 Rotating Platform,
  • 004 Long Collar,
  • 004 Slip Ring Holder,
  • 004 Elevation Motor Housing,
  • 004 Elevation Driver Mount.

Obrotowa platforma posiada łożysko 60002RS umieszczone w środku. Jest ono ciasno wpasowane, więc pistolet na gorące powietrze może zostać użyty do podgrzania metalowego korpusu łożyska i środka obrotowej platformy. Delikatny ruch wirowy opalarki zapewnia, że obszar nie zostanie przegrzany, ponieważ może szybko się odkształcić, jeśli zastosuje się zbyt dużo ciepła. Łożysko można następnie umieścić na górze wnęki i wcisnąć na miejsce płaskim przedmiotem. Gdy PLA wydruku ostygnie, będzie pewnie trzymać ten element na miejscu.

W tym momencie można umieścić przekładnię azymutalną od wewnątrz obrotowej platformy, aby upewnić się, że zęby koła zębatego zazębiają się swobodnie i nie zaczepiają o żadne niedoskonałości wydruku.

Uchwyt 004 Elevation Driver Mount można przymocować do obrotowej platformy za pomocą wkrętów z łbem stożkowym M3×12 mm i nakrętek uwięzionych wewnątrz uchwytu sterownika. Płytka drukowana jest mocowana za pomocą wkrętów M3×10 mm wkręcanych w gwintowane otwory w drukowanej podstawie sterownika.

Obudowa silnika elewacji jest również mocowana za pomocą śrub i nakrętek uwięzionych w plastiku, a silnik powinien dobrze pasować do obudowy. Pomocne może być użycie pęsety do precyzyjnego umieszczenia nakrętek we właściwym miejscu. Wiązkę przewodów silnika krokowego można podłączyć do sterownika. Należy uważać, aby przewody nie dotykały środkowej osi, ponieważ będzie się ona obracać w czasie pracy urządzenia.

Następnie należy wsunąć pierścień dystansowy na oś, a następnie na zespół platformy obrotowej. Drugi kołnierz można umieścić za nim na osi. Sześć połączeń pierścienia ślizgowego należy przeprowadzić przez uchwyt pierścienia ślizgowego, a następnie przewlec przez wydrążone wrzeciono – może to być nieco trudne, najłatwiej jest wykonać to pojedynczo. Teraz można przykręcić uchwyt pierścienia ślizgowego do osi obrotnicy. Wystarczy ją dokręcić mocno palcami, sprawdzając, czy obrotnica może swobodnie poruszać się na łożysku. Obrotnica nie obraca się szybko, ale komponenty zamontowane na niej zostały umieszczone po przeciwnych stronach, aby była maksymalnie wyważona. Gdy wszystkie części są na miejscu, można przymocować pierścień ślizgowy do uchwytu za pomocą trzech wkrętów samogwintujących. Przy wykonywaniu tej części konstrukcji pomocna będzie fotografia 4.

Fotografia 4. Obrotnica i jej oś podczas montażu

Ostatnia partia elementów do druku 3D składa się na kopułę. Należy wydrukować następujące elementy:

  • 005 Geodesic Dome,
  • 006 Pointer Body Bottom Half,
  • 006 Pointer Body Top Half,
  • 006 Pointer Front Cone,
  • 006 Pointer Locking Ring,
  • Geodesic Locking Ring Jig,
  • 000 Base Plate.

Konstrukcja powinna wyglądać jak na rysunku 4. Nadszedł czas, aby dokończyć montaż, instalując kopułę. Geodesic Locking Ring Jig należy umieścić na szczycie obrotowej platformy, a następnie użyć go do ustawienia śrub blokujących na odpowiedniej wysokości, aby dobrze zablokować kopułę na mocujących ją elementach. Kopułę zabezpiecza się, po prostu upuszczając ją na śruby i przekręcając, aby zablokować ją na miejscu. Podczas montażu należy upewnić się, że boczny otwór znajduje się w jednej linii z wałem silnika krokowego do podnoszenia wskaźnika.

Rysunek 4. Wygląd konstrukcji przed zamontowaniem kopuły

Wskaźnik składa się z dwóch połówek, stożkowej strzałki z przodu i pierścienia blokującego z tyłu. Gdy kopuła jest na miejscu, wystarczy nasunąć wskazówkę na silnik krokowy elewacji, przykręcić podstawę i system jest gotowy do programowania i testowania.

Obliczenia pozycji ISS i oprogramowanie

Na stronie projektu umieszczono obliczenia matematyczne, które posłużyły do ustalenia lokalizacji ISS. Można pominąć tę sekcję, jeśli używa się gotowego programu, ale autor udostępnia go dla osób chętnych, aby zrozumieć, w jaki sposób system działa. Główny program sterujący trackerem ISS został pokazany na listingu 1. Ze strony z projektem można pobrać plik .ino, lub po prostu skopiować kod i wkleić go do Arduino IDE.

Listing 1. Firmware programu do wskazywania pozycji ISS

// ISS Tracker - David Hunt
// Wersja 1.4
// Licencja - Attribution Non-Commercial Share Alike (by-nc-sa)
// pobierz wszystkie niezbędne biblioteki za pomocą menedżera bibliotek
#include < AccelStepper . h >
// do sterowania silnikami krokowymi
#include < ezTime . h >
#include < WiFi . h >
#include < HTTPClient . h >
// aby pobrać dane z API
#include < ArduinoJson . h >
// aby wyodrębnić informacje o lokalizacji ISS
#include < U8g2lib . h >
// wyszukaj U8g2 w menedżerze bibliotek
#include < Wire . h >

time_t next_pass_timestamp = 1572652800 ; // 2 listopada 2019 jako punkt odniesienia
const char ssid [ ] = "Twoja sieć tutaj" ; // SSID sieci (nazwa)
const char pass [ ] = "Hasło routera" ; // twoje hasło sieciowe
const int touch_threshold = 40 ; // wejście touchpin (T0) jest GPIO4
const pływak steps_per_degree = XXL Standard 4096 / 360 ; // 4096 kroków na obrót w trybie pół kroku
double my_latitude = 51,89970 ; // zmień tutaj swoją lokalizację
double my_longitude = - 2.12084 ; // znajdź swoje współrzędne za pomocą google maString next_pass_JSON; // dane o lokalizacji są pobierane w formacie JSON
int next_risetime ;
int next_duration ;

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2 ( U8G2_R0 ) ;
// Definicje pinów silnika w numerach GPIO
#define motor_pin_az1 13 // IN1 w sterowniku ULN2003
#define motor_pin_az2 12 // IN2 w sterowniku ULN2003
#define motor_pin_az3 14 // IN3 w sterowniku ULN2003
#define motor_pin_az4 27 // IN4 na Sterownik ULN2003

# zdefiniować motor_pin_el1 26 // IN1 na sterowniku ULN2003
# zdefiniować motor_pin_el2 25 // IN2 na sterowniku ULN2003
# zdefiniować motor_pin_el3 33 // IN3 na sterowniku ULN2003
# zdefiniować motor_pin_el4 32 // IN4 na sterowniku ULN2003

#define MotorInterfaceType 8 // 8 = tryb pół kroku, 4 = tryb pełnego kroku
// Inicjalizacja za pomocą sekwencji pinów IN1-IN3-IN2-IN4 do korzystania z biblioteki AccelStepper z silnikiem krokowym 28BYJ-48:
AccelStepper azimuth_motor = AccelStepper ( MotorInterfaceType , motor_pin_az1 , motor_pin_az3 , motor_pin_az2 , motor_pin_az4 ) ;
AccelStepper elevation_motor = AccelStepper ( MotorInterfaceType , motor_pin_el1 , motor_pin_el3 , motor_pin_el2 , motor_pin_el4 ) ;

Strefa czasowa my_timezone ;

// użyj internetu, aby sprawdzić czas następnego przelotu
void get_next_pass ( double lat , double lon , int & p_risetime , int & p_duration ) {
HTTPClient http ;
const char * api_host = "http://api.open-notify.org/iss-pass.json?lat=" ;
char my_lat_position [ 10 ] ;
char my_lon_position [ 10 ] ;
char api_address [ 255] ;
//
zamień współrzędne zapisane jako podwójne na łańcuchy z dokładnością do 4 dp dtostrf ( lat , 7 , 4 , my_lat_position ) ;
dtostrf ( lon , 7 , 4 , my_lon_position ) ;
// utwórz adres URL za pomocą polecenia get
strcpy ( api_address , api_host ) ;
strcat ( api_address , my_lat_position ) ;
strcat ( api_address , "& lon =") ;
strcat ( api_address , my_lon_position ) ;
// pobierz tylko czas i datę następnego przebiegu
strcat ( api_address , "& n = 1" ) ;

http . begin ( api_address ) ;
int httpCode = http . GET ( ) ;
if ( httpCode > 0 ) {
String payload = http . getString ( ) ;
// Serial.println (httpCode);
// Serial.println (ładunek);
const size_t capacity = JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 3 ) + 200;
DynamicJsonDocument doc ( pojemność ) ;
DeserializationError error = deserializeJson ( doc , payload ) ;
p_duration = doc [ "odpowiedź" ] [ 0 ] [ "czas trwania" ] ; // zapisz tę wartość do next_duration
p_risetime = doc [ "response" ] [ 0 ] [ "risetime" ] ; // zapisz tę wartość do next_risetime
}
else {
Serial . println ( "Błąd żądania HTTP" ) ;
}
http . koniec ( ) ; // Zwolnij zasoby
}
// przekonwertuj to do postaci czytelnej dla człowieka w dniach, godzinach, minutach i sekundach
String time_to_next_flyby ( int next_observation ) {
int time_remaining ;
int next_rise_days ;
int next_rise_hours ;
int next_rise_minutes ;
int next_rise_seconds ;
Strunowy countdown_time ;
time_remaining = next_observation - teraz ( ) ;
next_rise_days = time_remaining / ( 3600 * 24 ) ;
time_remaining % = ( 3600 * 24 ) ;
next_rise_hours = time_remaining / 3600 ;
time_remaining % = 3600 ;
next_rise_minutes = time_remaining / 60 ;
next_rise_seconds = time_remaining 60 % ;
countdown_time + = next_rise_days ;
countdown_time + = "dni" ;
countdown_time + = next_rise_hours ;

if ( next_rise_minutes < 10 ) {
countdown_time + = ": 0" ; } // dodaj wiodące zero dla pojedynczej cyfry
else {
countdown_time + = ":" ;
}
countdown_time + = next_rise_minutes ;
if ( next_rise_seconds < 10 ) {
countdown_time + = ": 0" ; } // dodaj wiodące zero dla pojedynczej cyfry
else {
countdown_time + = ":" ;
}
countdown_time + = next_rise_seconds ;
return countdown_time ;
}

// znajdź aktualne położenie ISS nad Ziemią
// i oblicz kąty, aby wskazać na nią z naszej lokalizacji
void point_to_ISS ( ) {
HTTPClient http ;
podwójna szerokość geograficzna ;
podwójna długość geograficzna ;
if ( http . begin ( "http://api.open-notify.org/iss-now.json" ) ) {
int httpCode = http . GET ( ) ;
// httpCode będzie ujemny, jeśli wystąpi błąd,
jeśli ( httpCode > 0 ) {
String ISS_Location_Data = http . getString ( ) ;
//Serial.println(httpCode); // to będzie 200 dla pomyślnego pobrania
//Serial.println(ISS_Location_Data); // dane Json
const size_t capacity = JSON_OBJECT_SIZE ( 2 ) + JSON_OBJECT_SIZE ( 3 ) + 200 ;
DynamicJsonDocument doc ( pojemność ) ;
DeserializationError error = deserializeJson ( doc, ISS_Location_Data ) ;
// const char * message = doc ["wiadomość"];
long timestamp = doc [ "timestamp" ] ;
latitude = doc [ "iss_position" ] [ "latitude" ] ;
longitude = doc [ "iss_position" ] [ "longitude" ] ;

// Wydrukuj wartości przydatne do debugowania, aby sprawdzić, czy działa
//Serial.println(timestamp);
//Serial.println(latitude, 4);
//Serial.println(longitude, 4);
}
else {
Serial . print ( "Błąd HTTP:" ) ;
Szeregowy . println ( http . errorToString ( httpCode ) . c_str ( ) ) ;
}
http . koniec ( ) ; // Zwolnij zasoby
}
else {
Serial . wydrukować( „Błąd HTTP: nie można się połączyć” ) ;
}

// ESP32 oblicza kąty w radianach (nie w stopniach)
double latitude_in_radians = latitude * PI / 180 ;
double longitude_in_radians = longitude * PI / 180 ;
double my_latitude_in_radians = my_latitude * PI / 180 ;
double my_longitude_in_radians = my_longitude * PI / 180 ;
// oblicz kierunek azymutu na ISS
double x = cos (latitude_in_radians ) * sin ( longitude_in_radians - my_longitude_in_radians ) ;
double y = cos ( my_latitude_in_radians ) * sin ( latitude_in_radians ) - sin ( my_latitude_in_radians ) * cos ( latitude_in_radians ) * cos ( longitude_in_radians - my_longitude_in_radians ) ;
podwójne b = atan2 ( x, y ) ;
//Serial.print("Bearing to ISS: ");
b = b * 180 / PI ; // konwersja na stopnie
//Serial.println(b);

// obliczyć namiar na wysokość do ISS
double earth_radius = 6371 ; // średnia wartość w km
double orbit = 412 ; // średnia wartość w km - może sprawdź też tę wartość?
double x1 = earth_radius * cos ( my_latitude_in_radians ) * cos ( my_longitude_in_radians ) ;
double y1 = earth_radius * cos ( my_latitude_in_radians ) * sin ( my_longitude_in_radians );
double z1 = earth_radius * sin ( my_latitude_in_radians ) ;
double x2 = earth_radius * cos ( latitude_in_radians ) * cos ( longitude_in_radians ) ;
double y2 = earth_radius * cos ( latitude_in_radians ) * sin ( longitude_in_radians ) ;
double z2 = earth_radius * sin (latitude_in_radians ) ;

double dist_to_nadir = sqrt ( sq ( x2 - x1 ) + sq ( y2 - y1 ) + sq ( z2 - z1 ) ) ;
//Serial.print("Distance to nadir: ");
//Serial.println(dist_to_nadir);
podwójne geocentric_angle_in_radians = 2 * asin ( dist_to_nadir / ( 2 * earth_radius ) ) ;
//Serial.print("Geocentric angle w stopniach: ");
//Serial.println(geocentric_angle_in_radians * 180 / PI);
podwójna odległość_do_ISS = sqrt ( sq ( orbita + promień_ziemia ) + sq ( promień_ziemi ) - 2 * ( orbita + promień_ziemi ) * promień_ziemi * cos ( geocentric_ang_in_radians ) ) ;
//Serial.print("Distance to ISS: ");
//Serial.println(distance_to_ISS);
double ISS_angle = ( 180 / PI ) * asin ( ( orbit + earth_radius ) * ( sin ( geocentric_angle_in_radians ) / distance_to_ISS ) ) ;

// azymutalny silnik krokowy ma 4096 pół kroków na obrót i przełożenie 113/22
azymut_motor . moveTo ( XXL Standard 4096 / 360 * 113 / 22 * b ) ;
// silnik elewacji ma 4096 pół kroków na obrót
Elevation_motor . moveTo ( XXL Standard 4096 / 360 * ISS_angle ) ;

// uruchom silnik, czekając na aktualizację współrzędnych co 5 sekund
double holding_time = now ( ) ;
while ( now ( ) - holding_time < 5 ) {
azymuth_motor . run ( ) ;
Elevation_motor . run ( ) ;
wydajność ( ) ;
}
}

// wydrukuj wiadomości na OLED używając dwóch wierszy tekstu
void display_message ( String line_one , String line_two ) {
u8g2 . setFont ( u8g2_font_8x13_tr ) ;
//u8g2.setFont(u8g2_font_fur14_tr);
u8g2 . firstPage ( ) ;
u8g2 . setCursor ( 0 , 15 ) ;
u8g2 . print ( line_one ) ;
u8g2 . setCursor ( 0 ; 31 ) ;
u8g2 . print ( line_two ) ;
u8g2 . nextPage ( ) ;
}

void setup ( ) {
Serial . rozpocząć ( 115200 ) ;
opóźnienie ( 3000 ) ; // spróbuj tego, aby umożliwić OLED nawiązanie komunikacji?
u8g2 . begin ( ) ; // dla OLED
u8g2 . enableUTF8Print ( ) ; //
// Ustaw maksymalne kroki silnika na sekundę:
azymuth_motor . setMaxSpeed ( 800 ) ; // duże przełożenie, więc przyspiesz to
azymuth_motor . setAcceleration( 100,0 ) ;
Elevation_motor . setMaxSpeed ( 400 ) ;
Elevation_motor . setAcceleration ( 100,0 ) ;

// ######################### sekcja kalibracji ##################### ##########
display_message ( "Strzałka zatrzymaj, gdy" , "skierowana w dół" ) ;
while ( touchRead ( T0 ) > touch_threshold ) {
elevation_motor . ruch ( 400 ) ;
Elevation_motor . run ( ) ;
}
// przycisk został naciśnięty, gdy wskaźnik elewacji jest skierowany w dół
display_message ( "Silnik podniesienia" , "ustaw na zero" ) ;
Elevation_motor . setCurrentPosition ( 0 ) ;
opóźnienie ( 1000 ) ;
display_message ( "Stop strzałka na" , "lewa strona" ) ;
while ( touchRead ( T0 ) > touch_threshold ) {
azymut_motor . ruch ( 400 ) ;
azimuth_motor . run ( ) ;
}
// przycisk jest naciśnięty, gdy wskaźnik azymutu jest skierowany do przodu
display_message („Silnik azymutu” , „ustawiony na zero” ) ;
opóźnienie ( 2000 ) ; // pauza, aby poinformować, że został naciśnięty przycisk
azimuth_motor . setCurrentPosition ( 0 ) ;
// przesuń elewację, aby wskazywała na Polaris
// ten kąt jest taki sam jak szerokość geograficzna obserwatora, punkt odniesienia w dół, więc +90
elevation_motor . moveTo ( steps_per_degree * ( my_latitude + 90 ) ) ;
Elevation_motor . runToPosition ( ) ;
display_message ( "Wskaż Polaris" , "Następnie naciśnij przycisk" ) ;
while ( touchRead ( T0 ) > touch_threshold ) { } // czekaj na naciśnięcie przycisku
display_message ( "Teraz skalibrowano" , "" ) ;
opóźnienie ( 2000 ) ; // pauza, aby powiadomić cię o naciśnięciu przycisku
// ######################## koniec sekcji kalibracji ######## ####################

// ######################### Połącz się z WiFi #################### ###################
Serial . println ( "Śledzenie ISS" ) ;
display_message ( "Wyszukiwanie" , ssid ) ;
Szeregowy . println ( ssid ) ;
WiFi . begin ( ssid , pass ) ;
while ( WiFi . status ( ) ! = WL_CONNECTED ) {
opóźnienie ( 500 ) ;
Szeregowy . print ( „.” ) ;
}
Seryjny . println ( "Połączono z Wi-Fi" ) ;
display_message ( "Połączono z" , ssid ) ;

// ######################### Synchronizuj czas z UTC ################### ############
// Odkomentuj poniższy wiersz, aby zobaczyć, co robi za kulisami
setDebug ( INFO ) ;
waitForSync ( ) ; // nie rób nic, dopóki nie nadejdzie właściwy czas

Szeregowy . println ( "Bieżący czas UTC:" + UTC . dateTime ( ) ) ;
my_timezone . setLocation ( F ( "GB" ) ) ; // <a href="/ https://en.wikipedia.org/wiki/List_of_tz_database_time_zones "> https://en.wikipedia.org/wiki/List_of_tz_database ...>
opóźnienie ( 3000 ) ;
Szeregowy . print ( F ( "Czas lokalny:" ) ) ;
Szeregowy .println ( my_timezone . dateTime ( ) ) ;
}
void loop ( ) {
events ( ) ; // dzięki temu silniki będą się poruszać
//Serial.println("COOKIE: "+ UTC.dateTime (COOKIE));
// Serial.println (dateTime (next_pass_timestamp, "D dM H: i: s"));
if ( now ( ) + next_duration > next_risetime ) { // następny przelot tylko wtedy, gdy obecny
minie get_next_pass ( my_latitude , my_longitude, next_risetime , next_duration ) ;
}
Seryjny . print ( "Następny przelot:" ) ;
//Serial.print(dateTime(next_risetime, "D dM H: i: s"));
Szeregowy . println ( time_to_next_flyby ( next_risetime ) ) ;
point_to_ISS ( ) ;
opóźnienie ( 1000 ) ;
//display_message(UTC.dateTime("H:i:s T "), my_timezone.dateTime (" H: i: s "));
display_message ( UTC . dateTime ( "H: i: s T") , time_to_next_flyby ( next_risetime ) ) ;
}

Program działa w dosyć prosty sposób. Sekwencja działania systemu po uruchomieniu wygląda następująco:

  1. Połącz z Internetem;
  2. Uzyskaj aktualny czas;
  3. Uzyskaj czas następnego przejścia ISS przez niebo w danej lokalizacji;
  4. Oblicz czas do następnego przejazdu;
  5. Nieskończona pętla:
    • uzyskaj aktualną lokalizację ISS,
    • oblicz kąty,
    • wskaż strzałką na ISS.

Kalibracja

Kiedy urządzenie jest włączane po raz pierwszy, musi wiedzieć, gdzie wskazuje wskaźnik. W tej chwili proces ten zależy od operatora. Poniżej znajduje się procedura kalibracji układu mechanicznego:

  1. Wyrównaj zerowy punkt odniesienia dla elewacji (w kierunku Ziemi wynosi zero);
  2. Wyrównaj zerowy punkt odniesienia dla azymutu (po lewej stronie urządzenia);
  3. Podnieś ramie elewacji do gwiazdy polarnej;
  4. Po precyzyjnym ręcznym ustawieniu urządzenia jest ono wyrównane północą.

Pierwotnie kopuła urządzenia miała posiadać wbudowany kompas, ułatwiający jego ustawienie w terenie, jednakże igła magnetyczna znajduje się zbyt blisko silników, aby precyzyjnie wskazywać północ. Dlatego też autor zdecydował się polegać na nawigacji za pomocą gwiazdy polarnej. Jeśli Gwiazda Polarna nie jest widoczna na niebie z powodu zachmurzenia, prawdopodobnie i tak nie jest to dobra noc, aby zobaczyć przelatującą ISS.

Nikodem Czechowski, EP

Źródło: http://bit.ly/3ck527a

Artykuł ukazał się w
Elektronika Praktyczna
luty 2021
DO POBRANIA
Pobierz PDF Download icon
Materiały dodatkowe

Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik kwiecień 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Automatyka, Podzespoły, Aplikacje kwiecień 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna kwiecień 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich maj 2024

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów