Spisu treści:

Sine-ese Dragon: 10 kroków (ze zdjęciami)
Sine-ese Dragon: 10 kroków (ze zdjęciami)

Wideo: Sine-ese Dragon: 10 kroków (ze zdjęciami)

Wideo: Sine-ese Dragon: 10 kroków (ze zdjęciami)
Wideo: 🐉💚ДРАКОНЧИК ИЗ ПЛЮШЕВОЙ ПРЯЖИ ВЯЗАНЫЙ КРЮЧКОМ💛crochet dragon🐉gehäkelter Drache 2024, Listopad
Anonim
Sine-ese smok
Sine-ese smok

Sine-ese Dragon to nastrojowy element wystroju domu, który wykorzystuje mechaniczne ruchy i światła, aby przekazać prognozę pogody na następne trzy godziny. Z definicji otoczenie opisuje bezpośrednie otoczenie czegoś; dlatego zdecydowano, że właściwe będzie włączenie danych pogodowych do wyświetlacza otoczenia. Pogoda to aspekt, który nieumyślnie zmienia ludzkie dni i jest informacją, która zmienia się co minutę, a nawet co sekundę.

Chiński Smok jest „symbolem władzy, siły i szczęścia” i często ma wysoką kulturową i tradycyjną wartość na subkontynencie azjatyckim. Oprócz przynoszenia szczęścia, chiński smok ma również potężne moce, które kontrolują „wodę, opady deszczu, tajfuny i powodzie”. Ostatecznie chiński smok został uznany za odpowiedni do reprezentowania danych pogodowych.

Wyobrażanie sobie

Sine-ese Dragon jest manipulowany w sześciu głównych punktach w trzech oddzielnych sekcjach reprezentujących prognozę pogody w trzech 3-godzinnych odstępach. Dla każdego 3-godzinnego interwału zostaną uwzględnione następujące informacje:

  • Opis pogody - określa kolor aktualnych informacji o pogodzie.
  • Temperatura - określa wysokość ciała
  • Wilgotność - miganie segmentów LED
  • Prędkość wiatru - kontroluje prędkość poruszającego się ciała w lewo iw prawo.

Wymagane materiały

  1. 3 mm sklejka/karton
  2. Drewniane kołki lub pałeczki 5 mm
  3. 2 fotony cząstek
  4. 3 zabawki Slinky
  5. 6 serwosilników
  6. Lampy NeoPixel (zszyte ze sobą pasmo lub pojedyncze światła)
  7. Dużo super kleju
  8. Gwint przewodzący
  9. Farba akrylowa
  10. Tkanina dekoracyjna
  11. Wycinarka laserowa
  12. drukarka 3d

Krok 1: W górę iw dół

W górę i w dół!
W górę i w dół!
W górę i w dół!
W górę i w dół!
W górę i w dół!
W górę i w dół!

Twoim pierwszym krokiem do zbudowania Sine-ese Dragona jest skonstruowanie elementu, który kontroluje ruch ciała w górę iw dół. Jak ekscytujące!

  1. Pobierz pliki Adobe Illustrator (.ai) i wydrukuj je za pomocą wycinarki laserowej.

    upDownBoxWithPlatform.ai należy wydrukować na kartonie

  2. Pobierz pliki do drukowania 3D (.stl) i użyj swojej ulubionej drukarki 3D, aby je wydrukować.

    Kolor nie ma znaczenia dla dysku ani tokarki. Na drugim zdjęciu obracacz tarczy został włożony w otwór tarczy

  3. Złóż pierwsze dwa elementy i sklej je razem, jak pokazano na rysunkach 3 do 5.

    1. Platforma
    2. Rowki na dysk
  4. Teraz ułóż pudełko zgodnie z poniższymi wskazówkami.

    1. Przewody serwomechanizmu powinny przejść przez prostokątny otwór z boku puszki.
    2. Najkrótszy koniec tokarki zostaje przymocowany do głowicy serwomechanizmu, a dłuższy przechodzi przez otwór po drugiej stronie pudełka z okrągłym otworem. Pokazuje to rysunek 6.
  5. Teraz potrzebujemy czegoś, co zapewni, że platforma pozostanie wypoziomowana, gdy dysk zostanie obrócony. Pokrój pałeczki na patyczki o długości 75 mm (rysunek 7) i przyklej je przez górną część pudełka do górnej części platformy za pomocą gorącego kleju. Upewnij się, że patyki są wypoziomowane pod kątem 90 stopni do platformy.
  6. Włóż patyczek o długości 212 mm do środkowego otworu na górze pudełka na platformie.

Słodki! Teraz masz kompletne pudełko (rysunek 8) do poruszania się smoka w górę iw dół. Teraz powtórz powyższe kroki jeszcze dwa razy!

Krok 2: A co z lewą i prawą stroną?

A co z lewą i prawą stroną?!
A co z lewą i prawą stroną?!
A co z lewą i prawą stroną?!
A co z lewą i prawą stroną?!
A co z lewą i prawą stroną?!
A co z lewą i prawą stroną?!
A co z lewą i prawą stroną?!
A co z lewą i prawą stroną?!

Teraz nie możemy zapominać o ruchu lewego i prawego smoka Sine-ese, prawda? Przejdźmy do drugiego kroku!

  1. Pobierz pliki Adobe Illustrator (.ai) i wydrukuj je za pomocą wycinarki laserowej.

    1. leftRightBoxWithPlatforms.ai należy wydrukować na kartonie.
    2. Plik armTurner.ai należy wydrukować na materiale o grubości 3 mm.
  2. Pobierz pliki do drukowania 3D (.stl) i użyj swojej ulubionej drukarki 3D, aby je wydrukować.

    Upewnij się, że wydrukujesz dwa ramiona! Kolor nie ma tu znaczenia

  3. Połącz ze sobą dwie platformy, jak pokazano na rysunku 3, używając gorącego kleju.
  4. Złóż pudełko. Chociaż może to być trudne, łatwiej jest to osiągnąć poprzez:

    1. Włożenie dwóch platform między dwie duże szczeliny po obu stronach pudełka.
    2. Umieszczenie pierwszego ramienia na górze górnej platformy.
    3. Przewlekanie ramienia obracającego przez ramię, a następnie przez górną platformę.
    4. Umieszczenie drugiego ramienia na górze dolnej platformy.
    5. Przewlekanie ramienia obracającego przez drugie ramię, a następnie dolną platformę.
    6. Wkładanie ramienia obracającego przez prostokątny otwór drukowanego w 3D ramienia obracającego.
    7. Drugi koniec tokarki idzie na górę serwomotoru.
    8. Dodaj górną, dolną i tylną część do pudełka.

Twoje ostateczne zmontowane pudełko powinno wyglądać jak szóste zdjęcie. Teraz możesz powtórzyć to jeszcze dwa razy!

Pod koniec tego kroku powinieneś mieć sześć pudełek z trzema systemami ruchu w górę/dół i lewo/prawo.

Krok 3: Podnoszenie ciała… JAK?

Podnoszenie ciała… JAK?
Podnoszenie ciała… JAK?

Dobre pytanie! Wtedy pojawiają się te wydrukowane w 3D, cienkie uchwyty. Pobierz dołączony plik.stl i wydrukuj go za pomocą drukarki 3D. Pamiętaj, aby wydrukować łącznie 6 uchwytów na 6 różnych pudełek.

Jeśli widzieliście powyżej zdjęcie slinky posiadacza, niespodzianka została zrujnowana - taki jest kolor naszego Sine-ese Dragona!

Krok 4: Ale te pudełka nie są takie ładne…

I zgadzam się! Dlatego użyjemy wycinarki laserowej, aby wyciąć o wiele bardziej atrakcyjne pudełko, aby pomieścić wszystkie te pudełka i je ukryć.

Pobierz te pliki Adobe Illustrator i wytnij je za pomocą wycinarki laserowej. Projekt chmur został narysowany ręcznie przez jednego z kontrybutorów. Możesz je modyfikować, usuwając je w pliku programu Illustrator i dodając własny projekt według własnego uznania! Poniżej znajdują się sugerowane kroki, aby wszystko połączyć.

  1. Złóż i sklej wszystkie trzy elementy z pierwszego pliku (outerBoxFinal_1) razem.
  2. Nie dodawaj jeszcze kawałka z drugiego pliku (outerBoxFinal_2).
  3. Umieść kawałek z trzeciego pliku (outerBoxFinal_3) na dole pudełka i powinien zamknąć się u góry. Klej TYLKO na spodzie pudełka.
  4. Dwukrotnie wydrukuj innerBoxesPlatform. Sklej ze sobą dwa kawałki, które mają duże prostokątne otwory. Następnie sklej ze sobą trzy pozostałe kawałki. Na koniec przyklej go do drugiego klejonego zestawu z otworami.
  5. Umieść platformę na dole dużego pudełka.
  6. Włóż wszystkie 6 mniejszych pudełek w odpowiednie miejsca na platformie.
  7. Teraz umieść kawałek z drugiego pliku (outerBoxFinal_2) na górze pudełka i przyklej wokół krawędzi. Otwory w górnej części powinny być wyrównane z otworami w mniejszych pudełkach. Jeśli nie, przestaw swoje mniejsze pudełka. W ogóle nie dodawaj kleju do mniejszych pudełek.
  8. Jeśli używasz płytki stykowej, która ma lepki kawałek na dole, umieść go w pobliżu środka dolnego kawałka w miejscu, w którym po zamknięciu pudełka płytka prototypowa wraz z fotonami powinna zniknąć. W dolnej części znajdują się małe szczeliny ułatwiające podłączenie do Photonów z zewnątrz.

Krok 5: Slinky Zabawki? O mój

Slinky Zabawki? O mój!
Slinky Zabawki? O mój!
Slinky Zabawki? O mój!
Slinky Zabawki? O mój!

Ciało smoka:

1. Połącz ze sobą trzy slinky za pomocą gorącego kleju lub taśmy.

2. Zmierz długość i średnicę slinków i wytnij kawałek tkaniny dekoracyjnej.

3. Przynieś dwa końce materiału i zszyj je razem.

4. Po zakończeniu szycia wsuń slinki jak skarpetę.

5. Przyszyj końce slinky do szytej tkaniny.

Krok 6: Wydrukuj swojego smoka

Wydrukowane w 3D części smoka:

1. Części zostały zaczerpnięte z

2. Wykorzystaliśmy tylko głowę, nogi i oczy.

3. Po wydrukowaniu części wygładź ją papierem ściernym i acetonem.

4. Pomaluj części tak, jak chcesz je ozdobić.

Krok 7: Czas wzmocnić smoka za pomocą NeoPixels

Czas wzmocnić smoka dzięki NeoPixels!
Czas wzmocnić smoka dzięki NeoPixels!
Czas wzmocnić smoka dzięki NeoPixels!
Czas wzmocnić smoka dzięki NeoPixels!

Segment lekki:

1. Możesz po prostu użyć nici neopixel do stworzenia świateł, jeśli chcesz. (Skończyły się nici).

2. Użyliśmy 20 lamp neopikselowych i połączyliśmy je przewodami. Przewody te zostały do nich przylutowane i połączone z fotonem za pomocą czerwonych przewodów, aby pasowały do motywu smoka.

3. Możesz również przyszyć swoje neopikselowe światła na długim kawałku materiału, ale nie użyliśmy ich, ponieważ mieliśmy slinky wykonane z metalu.

Montaż części: Zabezpiecz segment świetlny wewnątrz korpusu smoka za pomocą nici lub drutów. Upewnij się, że jesteś w stanie podłączyć światła do fotonu wewnątrz skrzynki bazowej. Przymocuj głowę, nogi i ogon do ciała za pomocą kleju. Gdy są na miejscu, przymocuj ciało do slinky uchwytów, które wydrukowaliśmy wcześniej. Teraz ciało jest gotowe do zaprogramowania.

Krok 8: Czas programowania

Ponieważ będziemy używać dwóch fotonów cząstek do pracy z sześcioma oddzielnymi serwomotorami (jeden foton może działać tylko z czterema), napiszemy dwa oddzielne, ale podobne kody, które będą migać na mikrokontrolerach.

Teraz dla pierwszego mikrokontrolera…

W pliku Arduino (.ino) dołącz następujące biblioteki i definiuje:

#include "neopixel.h"

#include "ArduinoJson.h"

#define PIXEL_PIN D4

#define PIXEL_COUNT 18

Następnie zadeklaruj następujące zmienne:

Pasek Adafruit_NeoPixel = Adafruit_NeoPixel(LICZBA_PIKSELÓW,PIN_PIKSELÓW);

Serwo serwoLeftRight_1; Serwo serwoUpDown_1; Serwo serwoLeftRight_2; Serwo serwoUpDown_2; int pozycjaLeftPrawy_1 = 0; int pozycjaGóraDół_1 = 0; int lewyPrawy_1 = 1; int góraDół_1 = 1; int pozycjaLeftPrawy_2 = 100; // musi mieścić się w zakresie od 0 do 180 (w stopniach) int positionUpDown_2 = 180; // musi mieścić się w zakresie od 0 do 180 (w stopniach) int leftRight_2 = 1; //0=w lewo, 1=w prawo int upDown_2 = 1; //0=w górę, 1=w dół const size_t bufferSizeCurrent = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + JSON_OBJECT_SIZE(12) 390; const size_t bufferSizeForecast = 38*JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(38) + 2*JSON_OBJECT_SIZE(0) + 112*JSON_OBJECT_SIZE(1) + 39*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 38*JSON_OBJECT_SIZE(4) + 38*JSON_OBJECT_SIZE(4) (5) + 76*JSON_OBJECT_SIZE(8) + 12490; String weatherArray[3]; float temperatureArray[3]; pływak wilgotnościArray[3]; pływająca tablica prędkości wiatru[3]; String timestampArray[3]; int upDownMaxDegree[3]; int leftRightSpeed[3]; Ciąg allData5DaysPrognoza;

Kliknij tutaj, aby dowiedzieć się, jak skonfigurować webhooki. Kiedy skończysz, dodaj następujące deklaracje i funkcje i wprowadź odpowiednie zmiany, jeśli to konieczne:

void getWeather5DayForecast() { Particle.publish("get_weather5DayForecast"); allData5DaysForecast = ""; } Timer timerWeatherForecast(60000, getWeather5DayForecast); void pobierzCurrentWeather() { Particle.publish("get_currentWeather"); } Timer timerWeatherCurrent(60000, getCurrentWeather);

Następujące funkcje sterują ruchami smoka w górę/dół i lewo/prawo:

void zmieńLeftRight1() { if (leftRight_1) { positionLeftRight_1 = positionLeftRight_1 + leftRightSpeed[0]; if (pozycjaLeftRight_1 > 100) { leftRight_1 = 0; } } else { pozycjaLeftPrawo_1 = pozycjaLeftPrawo_1 - leftRightSpeed[0]; if (pozycjaLeftRight_1 < 0) { leftRight_1 = 1; } } servoLeftRight_1.write(positionLeftRight_1); }

nieważna zmiana w lewo w prawo2 () {

if (leftRight_2) { pozycjaLeftRight_2 = pozycjaLeftRight_2 + LeftRightSpeed[1]; if (pozycjaLeftRight_2 > 100) { leftRight_2 = 0; } } else { pozycjaLeftPrawo_2 = pozycjaLeftPrawo_2 - leftRightSpeed[1]; if (pozycjaLeftRight_2 < 0) { leftRight_2 = 1; } } servoLeftRight_2.write(positionLeftRight_2); }

nieważna zmianaW górę1() {

if (upDown_1) { positionUpDown_1++; if (positionUpDown_1 > upDownMaxDegree[0]) { upDown_1 = 0; } } else { positionUpDown_1--; if (pozycjaUpDown_1 < 1) { upDown_1 = 1; } } servoUpDown_1.write(positionUpDown_1); }

nieważna zmianaW górę2() {

if (upDown_2) { positionUpDown_2++; if (positionUpDown_2 > upDownMaxDegree[1]) { upDown_2 = 0; } } else { positionUpDown_2--; if (pozycjaUpDown_2 < 1) { upDown_2 = 1; } } servoUpDown_2.write(positionUpDown_2); }

Aby móc zmieniać ruchy w interwale, tworzone są timery.

Licznik czasowyLeftRight1(100, zmieńLeftRight1);

Licznik czasowyLeftRight2(100, zmieńLeftRight2); Timer timerUpDown1(10, zmianaUpDown1); Timer timerUpDown2(10, zmianaUpDown2);

Na koniec dodawana jest funkcja konfiguracji. Pamiętaj, aby wprowadzić odpowiednie zmiany w wierszach kodu, które dotyczą webhooków.

void setup() { // uruchomienie liczników pogody timerWeatherForecast.start(); timerWeatherCurrent.start(); //Neopiksele strip.begin(); // Umieść inicjalizację jak pinMode i rozpocznij funkcje tutaj. // Ustaw serwo Micro ServoLeftRight_1.attach(D1); servoUpDown_1.attach(D0); serwoLeftPrawo_2.attach(D3); servoUpDown_2.attach(D2); servoLeftRight_1.write(positionLeftRight_1); //zainicjuj pozycję serwa servoUpDown_1.write(positionUpDown_1); //zainicjuj pozycję serwa servoLeftRight_2.write(positionLeftRight_2); //zainicjuj pozycję serwa servoUpDown_2.write(positionUpDown_2); //zainicjuj timer pozycji serwaLeftRight1.start(); timerLewoPrawo2.start(); timerUpDown1.start(); timerUpDown2.start(); // Otwórz konsolę Serial.begin(9600); opóźnienie (2000); Serial.println("Cześć!"); // Zapisz się do get_weather5DayForecast i get_currentWeather webhooków Particle.subscribe("hook-response/get_weather5DayForecast", gotWeather5DayForecast, MY_DEVICES); Particle.subscribe("hook-response/get_currentWeather/0", gotCurrentWeatherData, MOJE_URZĄDZENIA); pobierzAktualnąPogodę(); getWeather5DayForecast(); }

W tym projekcie nie jest używana funkcja pętli. Nie możemy zapomnieć o funkcjach do obsługi danych otrzymanych z webhooków!

void gotWeather5DayForecast(const char *event, const char *data){ allData5DaysForecast += dane; // zapisuje wszystkie dane w jednym ciągu. int allData5DaysForecastLen = allData5DaysForecast.length(); bufor znaków[allData5DaysForecastLen + 1]; allData5DaysForecast.toCharArray(bufor, allData5DaysForecastLen + 1); // utwórz bufor dla łańcucha int bufferLength = sizeof(buffer); DynamicJsonBuffer jsonBufferWeather(bufferLength); JsonObject& root = jsonBufferWeather.parseObject(bufor); // Sprawdź, czy parsowanie się powiodło. if (!root.success()) { //Serial.println("Parsowanie prognozy pogody na 5 dni…BŁĄD!"); powrót; } int i = 1; JsonArray& lista = root["lista"]; for (JsonObject& currentObject: lista){ if (i < 3){ JsonObject& main = currentObject["main"]; temperatura pływaka = main["temp"]; int wilgotność = main["wilgotność"]; JsonObject& pogoda = obecnyObiekt["pogoda"][0]; const char* weatherInfo = pogoda["główna"]; pływająca prędkość wiatru = bieżącyObiekt["wiatr"]["prędkość"]; const char* znacznik czasu = bieżącyObiekt["dt_txt"]; int tempFah = przelicz naFahrenheita(temperatura); int servoMaxDegree = updateUpDown(tempFah); upDownMaxDegree = servoMaxDegree; int servoIncrement = updateleftRight(windSpeed); leftRightSpeed = servoIncrement; setColor(informacje o pogodzie, ja); temperatureArray = tempFah; wilgotnośćArray = wilgotność; weatherArray = weatherInfo; windSpeedArray = windSpeed; tablica znaczników czasu = znacznik czasu; i++; } jeszcze{ przerwa; } } }

void gotCurrentWeatherData(const char *event, const char *data){ DynamicJsonBuffer jsonBufferWeather(bufferSizeCurrent); JsonObject& root = jsonBufferWeather.parseObject(dane); // Sprawdź, czy parsowanie się powiodło. if (!root.success()) { //Serial.println("Parsing dla aktualnej pogody…BŁĄD!"); powrót; } JsonObject& pogoda = root["pogoda"][0]; const char* weather_main = pogoda["główna"]; JsonObject& main = root["główny"]; float main_temp = main["temp"]; int główna_wilgotność = główna["wilgotność"]; float prędkość_wietrza = root["wiatr"]["prędkość"]; const char* znacznik czasu = root["dt_txt"]; int tempFah = konwertuj naFahrenheita(main_temp); int servoMaxDegree = updateUpDown(tempFah); upDownMaxDegree[0] = servoMaxDegree; int servoIncrement = updateleftRight(wind_speed); leftRightSpeed[0] = servoIncrement; setColor(weather_main, 0); weatherArray[0] = pogoda_główna; temperatureArray[0] = tempFah; wilgotnośćArray[0]= główna_wilgotność; windSpeedArray[0] = wind_speed; timestampArray[0] = znacznik czasu; }

Poniżej znajdują się dodatkowe funkcje sterujące aktualizacją pozycji serwonapędów, konwersją temperatury z Kelvina na Fahrenheita oraz ustawianiem kolorów diod LED.

int updateUpDown(float temp){ //Odwzoruj stopień na zakres [0, 180] float servoMaxDegree = temp * 45 / 31 + (990 / 31); Serial.print("nowy stopień serwo: "); Serial.println(servoMaxDegree); powrót servoMaxDegree; }

int updateleftRight(pływająca prędkość wiatru){

//Przypisz prędkość wiatru do zakresu [1, 100] float servoIncrement = windSpeed * 99 / 26 + 1; Serial.print("nowa wartość przyrostu serwa: "); Serial.println(servoPrzyrost); zwróć servoInkrement; }

int konwertuj na stopnie Fahrenheita(zmienna tempKel){

int tempFah = tempKel * 9,0 / 5,0 - 459,67; powrót tempFah; }

void setColor(String weatherDesc, int index){

int ledIndex = 0; if (indeks == 0){ ledIndex = 0; } else if (indeks == 1){ ledIndex = 6; } else if (indeks == 2){ ledIndex = 12; } else{ powrót; } if(weatherDesc == "Clear") { //żółty for (int j = ledIndex; j < ledIndex+6; j++){ strip.setPixelColor(j, strip. Color(253, 219, 62));// żółty pasek.pokaż(); opóźnienie(20); } } else if(weatherDesc == "Chmury"){ //grey for (int j = ledIndex; j < ledIndex+6; j++){ strip.setPixelColor(j, strip. Color(223, 229, 237)); //szary pasek.show(); opóźnienie(20); } } else if (weatherDesc == "Snow"){ //biały for (int j = ledIndex; j < ledIndex+6; j++){ strip.setPixelColor(j, strip. Color(255, 225, 225)); //biały pasek.show(); opóźnienie(20); } } else if (weatherDesc == "Deszcz"){//blue for (int j = ledIndex; j < ledIndex+6; j++){ strip.setPixelColor(j, strip. Color(119, 191, 246)); //niebieski pasek.show(); opóźnienie(20); } } else{ //red for (int j = ledIndex; j < ledIndex+6; j++){ strip.setPixelColor(j, strip. Color(254, 11, 5));//red strip.show(); opóźnienie(20); } } }

Po dodaniu wszystkiego do pliku Arduino skompiluj go. Jeśli nie ma błędów, śmiało prześlij kod do pierwszego Photona. W następnym kroku otrzymasz podobny kod do flashowania na drugim Photonie.

Krok 9: Kontynuacja programowania

Ponieważ kod drugiego Photona jest prawie identyczny z kodem pierwszego, cały kod jest kopiowany i wklejany poniżej:

#include "ArduinoJson.h"

Serwo serwoLeftRight_3;

Serwo serwoUpDown_3;

int pozycjaLewaPrawa_3 = 45;

int pozycjaGóraDół_3 = 0; int lewyPrawy_3 = 1; int w górę w dół_3 = 1;

const size_t bufferSizeCurrent = JSON_ARRAY_SIZE(1) + JSON_OBJECT_SIZE(1) + 2*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(4) + JSON_OBJECT_SIZE(5) + JSON_OBJECT_SIZE(6) + JSON_OBJECT_SIZE(12) + 390;

const size_t bufferSizeForecast = 38*JSON_ARRAY_SIZE(1) + JSON_ARRAY_SIZE(38) + 2*JSON_OBJECT_SIZE(0) + 112*JSON_OBJECT_SIZE(1) + 39*JSON_OBJECT_SIZE(2) + JSON_OBJECT_SIZE(3) + 38*JSON_OBJECT_SIZE(4) + 38*JSON_OBJECT_SIZE(4) (5) + 76*JSON_OBJECT_SIZE(8) + 12490;

String weatherArray[3];

float temperatureArray[3]; pływak wilgotnościArray[3]; pływająca tablica prędkości wiatru[3]; String timestampArray[3]; int upDownMaxDegree[3]; int leftRightSpeed[3];

Ciąg allData5DaysPrognoza;

void pobierzWeather5DayForecast()

{ Cząstka.publish("get_weather5DayForecast2"); allData5DaysForecast = ""; }

Licznik czasuWeatherForecast(60000, getWeather5DayForecast); //10, 800 000 ms = 3 dni

void pobierzAktualnąPogodę()

{ Cząstka.publish("get_currentWeather2"); }

Timer timerWeatherCurrent(60000, getCurrentWeather);

nieważna zmiana w lewo w prawo3() {

if (leftRight_3) { pozycjaLeftRight_3 = pozycjaLeftRight_3 + LeftRightSpeed[2]; if (pozycjaLeftRight_3 > 100) { leftRight_3 = 0; } } else { pozycjaLeftPrawo_3 = pozycjaLeftPrawo_3 - leftRightSpeed[2]; if (pozycjaLeftRight_3 < 0) { leftRight_3 = 1; } } servoLeftRight_3.write(positionLeftRight_3); }

nieważna zmianaW górę3() {

if (upDown_3) { positionUpDown_3++; if (positionUpDown_3 > upDownMaxDegree[2]) { upDown_3 = 0; } } else { positionUpDown_3--; if (positionUpDown_3 < 1) { upDown_3 = 1; } } servoUpDown_3.write(positionUpDown_3); }

Licznik czasowyLeftRight3(100, zmieńLeftRight3);

Timer timerUpDown3(10, zmianaUpDown3);

pusta konfiguracja () {

// uruchom liczniki pogody timerWeatherForecast.start(); timerWeatherCurrent.start(); // Umieść inicjalizację jak pinMode i rozpocznij funkcje tutaj. // Ustaw serwomechanizm Micro ServoLeftRight_3.attach(D1); servoUpDown_3.attach(D0);

servoLeftRight_3.write(pozycjaLeftRight_3); //zainicjuj pozycję serwa

servoUpDown_3.write(positionUpDown_3); //zainicjuj pozycję serwa

timerLewoPrawo3.start();

timerUpDown3.start(); // Otwórz konsolę Serial.begin(9600); opóźnienie (2000); Serial.println("Cześć!"); // Zasubskrybuj webhooki get_weather5DayForecast i get_currentWeather Particle.subscribe("hook-response/get_weather5DayForecast2", gotWeather5DayForecast, MY_DEVICES); Particle.subscribe("hook-response/get_currentWeather2/0", gotCurrentWeatherData, MOJE_URZĄDZENIA); pobierzAktualnąPogodę(); getWeather5DayForecast(); }

void gotWeather5DayForecast(const char *event, const char *data)

{ allData5DaysPrognoza += dane; // zapisuje wszystkie dane w jednym ciągu. int allData5DaysForecastLen = allData5DaysForecast.length(); bufor znaków[allData5DaysForecastLen + 1]; allData5DaysForecast.toCharArray(bufor, allData5DaysForecastLen + 1); // utwórz bufor dla łańcucha int bufferLength = sizeof(buffer); DynamicJsonBuffer jsonBufferWeather(bufferLength); JsonObject& root = jsonBufferWeather.parseObject(bufor); //Serial.println(allData5DaysForecast); // Sprawdź, czy parsowanie się powiodło. if (!root.success()) { //Serial.println("Parsowanie prognozy pogody na 5 dni…BŁĄD!"); powrót; } int i = 1; JsonArray& lista = root["lista"]; for (JsonObject& currentObject: lista){ if (i < 3){ JsonObject& main = currentObject["main"]; temperatura pływaka = main["temp"]; int wilgotność = main["wilgotność"]; JsonObject& pogoda = obecnyObiekt["pogoda"][0]; const char* weatherInfo = pogoda["główna"]; pływająca prędkość wiatru = bieżącyObiekt["wiatr"]["prędkość"]; const char* znacznik czasu = bieżącyObiekt["dt_txt"]; int tempFah = przelicz naFahrenheita(temperatura); int servoMaxDegree = updateUpDown(tempFah); upDownMaxDegree = servoMaxDegree; int servoIncrement = updateleftRight(windSpeed); leftRightSpeed = servoIncrement; temperatureArray = tempFah; wilgotnośćArray = wilgotność; weatherArray = weatherInfo; windSpeedArray = windSpeed; tablica znaczników czasu = znacznik czasu; i++; } jeszcze{ przerwa; } } }

void gotCurrentWeatherData(const char *event, const char *data)

{ DynamicJsonBuffer jsonBufferWeather(bufferSizeCurrent); JsonObject& root = jsonBufferWeather.parseObject(dane); //Serial.println(dane); // Sprawdź, czy parsowanie się powiodło. if (!root.success()) { //Serial.println("Parsing dla aktualnej pogody…BŁĄD!"); powrót; } JsonObject& pogoda = root["pogoda"][0]; const char* weather_main = pogoda["główna"]; JsonObject& main = root["główny"]; float main_temp = main["temp"]; int główna_wilgotność = główna["wilgotność"]; float prędkość_wietrza = root["wiatr"]["prędkość"]; const char* znacznik czasu = root["dt_txt"]; int tempFah = konwertuj naFahrenheita(main_temp); int servoMaxDegree = updateUpDown(tempFah); upDownMaxDegree[0] = servoMaxDegree; int servoIncrement = updateleftRight(wind_speed); leftRightSpeed[0] = servoIncrement; weatherArray[0] = pogoda_główna; temperatureArray[0] = tempFah; wilgotnośćArray[0]= główna_wilgotność; windSpeedArray[0] = wind_speed; timestampArray[0] = znacznik czasu; }

int updateUpDown (wartość zmiennoprzecinkowa){

//Odwzoruj stopień na zakres [0, 180] float servoMaxDegree = temp * 45 / 31 + (990 / 31); Serial.print("nowy stopień serwo: "); Serial.println(servoMaxDegree); powrót servoMaxDegree; }

int updateleftRight(pływająca prędkość wiatru){

//Przypisz prędkość wiatru do zakresu [1, 100] float servoIncrement = windSpeed * 99 / 26 + 1; Serial.print("nowa wartość przyrostu serwa: "); Serial.println(servoPrzyrost); zwróć servoInkrement; }

int konwertuj na stopnie Fahrenheita(zmienna tempKel){

int tempFah = tempKel * 9,0 / 5,0 - 459,67; powrót tempFah; }

Zrobiłeś to! Udało Ci się przejść przez dział programowania projektu! Teraz upewnij się, że wykonałeś całe okablowanie i połączenia od serwomotorów i neopikseli do płytki stykowej i mikrokontrolerów. UWAGA: włóż dodatkowe kołki/pałeczki przez pionowe szczeliny w pudełkach, aby umożliwić ruchy ciała w lewo i w prawo. Drugi koniec powinien być połączony z ciałem smoka.

Krok 10: Ciesz się swoim smokiem

Gratulacje! Zbudowałeś od podstaw smoka Sine-ese! Teraz wszystko, co musisz zrobić, to usiąść wygodnie i cieszyć się nastrojowym wyświetlaczem!

UWAGA: Ten projekt został zbudowany jako część zajęć przez Joan Bemponga i Soundaryę Muthuvel. Stronę kursu można znaleźć tutaj.

Zalecana: