Zacznij od wyniku, który można sprawdzić
Wyobraź sobie mały panel obok kierownicy lub drążka. Cztery kontrolki sygnalizują stany, a OLED pokazuje prędkość, obroty i paliwo. Na początku liczby celowo pochodzą z monitora portu szeregowego Arduino IDE. Nie potrzebujesz uruchomionego symulatora i możesz sam wywołać każdą reakcję.
Wymaganie: niezależne sterowanie czterema LED oraz czytelne wyświetlanie odebranych wartości. Zadanie programu: sprawdzać całe komunikaty, przyjmować wszystkie pola razem i oznaczać nieaktualne dane. Rezultatem jest zrozumiały element do dalszej rozbudowy, a nie automatyczna integracja z dowolnym symulatorem.
AI może objaśniać połączenia, przygotować kod i pomóc z błędami. Ty określasz, co ma się stać, kiedy i po czym poznasz sukces. Możesz to opisać, zanim nauczysz się pojęć zmiennej czy funkcji. Proś o wyjaśnienia nowych terminów na przykładzie aktualnie sprawdzanego fragmentu układu.
Dokładna lista części do tego przykładu
Przygotuj Arduino Uno R3, przewód USB do transmisji danych, płytkę stykową, przewody, cztery zwykłe czerwone LED oraz cztery osobne rezystory 1 kΩ o mocy co najmniej 0,125 W. Wyświetlacz to konkretnie Adafruit 4440: SSD1306, 128 × 32 piksele, I²C pod adresem 0x3C, automatyczny reset. Użyj przewodu przejściowego STEMMA QT albo prawidłowo przylutowanych pinów.
Producent dopuszcza logikę 5 V dla tego modelu. Nie oznacza to zgodności każdego podobnego OLED: sprawdź kontroler, kolejność pinów, zasilanie i poziomy sygnałów. SH1106 albo starsza płytka z osobnym resetem wymagają zmian. Najpierw ustal dokładną tożsamość części.
Uno R3 wystarczy do tego małego ekranu tekstowego. Ograniczona pamięć przemawia za prostym początkiem. W porównaniu mikrokontrolerów znajdziesz kryteria wyboru do większej grafiki, dodatkowych urządzeń i bardziej wymagających zadań.
Podłącz cztery LED i wyświetlacz
Odłącz USB przed montażem lub przepinaniem przewodów. Najpierw połącz wspólną masę, potem poszczególne funkcje. Każda LED potrzebuje własnego rezystora szeregowego; wspólny rezystor dla czterech diod jest niewłaściwy. Anoda zwykle ma dłuższą nóżkę, a płaska krawędź obudowy wskazuje stronę katody. Przy obciętych nóżkach sprawdź oznaczenia.
Przy spadku około 2 V na czerwonej LED, napięciu 5 V i rezystancji 1 kΩ prąd wynosi około 3 mA. To umiarkowane obciążenie do testu na biurku. Układ nie służy do taśm LED, mocnego oświetlenia ani obcych źródeł napięcia. Rozbudowę opisuje poradnik oświetlenia LED.
| Element / sygnał | Połączenie | Kontrola |
|---|---|---|
| LED 1 | D2 → 1 kΩ → anoda; katoda → GND | Osobny rezystor każdej LED |
| LED 2 | D3 → 1 kΩ → anoda; katoda → GND | Nie podłączaj LED bezpośrednio do D3 |
| LED 3 | D4 → 1 kΩ → anoda; katoda → GND | Sprawdź polaryzację |
| LED 4 | D5 → 1 kΩ → anoda; katoda → GND | Sprawdź polaryzację |
| OLED VIN | Uno 5V | Wyłącznie wskazany moduł |
| OLED GND | Uno GND | Wspólna masa |
| OLED SDA | Uno A4 / SDA | Ten sam sygnał |
| OLED SCL | Uno A5 / SCL | Ten sam sygnał |
| OLED RST | Nie podłączać | 4440 ma automatyczny reset |
Najpierw ustal znaczenie danych
Własny format ćwiczenia to V1,prędkość,obroty,paliwo,maska, zakończony LF, przy 115200 bodów. Akceptowane są wyłącznie nieujemne liczby całkowite: prędkość 0–999, obroty 0–20000, paliwo 0–100, maska 0–15. Bez spacji, jednostek i ułamków. Wysyłaj najwyżej pięć pełnych komunikatów na sekundę.
Maska jest sumą: LED 1 ma wartość 1, LED 2 wartość 2, LED 3 wartość 4, LED 4 wartość 8. Liczba 5 zapala LED 1 i 3, liczba 15 wszystkie, a 0 gasi wszystkie. Cyfry na OLED są uporządkowane od LED 1 do LED 4 od lewej strony; 1010 oznacza LED 1 i 3 włączone.
Po uruchomieniu widzisz WAIT. Poprawny komunikat daje OK przez port i DATA na ekranie. Niepoprawny daje ERR, bez częściowej zmiany poprzednich wartości. Po trzech sekundach bez poprawnych danych LED gasną i pojawia się STALE, a ostatnie liczby pozostają widoczne jako nieaktualne. Takie zachowanie należy określić od początku.
Tutaj S oznacza prędkość w km/h, R obroty na minutę, a F procent paliwa. Szkic wyświetla liczby bez przeliczeń; późniejsza konwersja jednostek należy do nadawcy. Bity LED są wskaźnikami testowymi bez ustalonej funkcji symulatora.
Przygotuj pełne polecenie dla AI
Dobry prompt Arduino obejmuje sprzęt, dane i obserwowalne zachowanie. Dodaj dokumentację producenta oraz potwierdzony model. Najpierw poproś o listę połączeń i pytania wymagające wyjaśnienia. Jeśli masz inne części, rozstrzygnij różnice przed użyciem wygenerowanego schematu. Przykładowe pełne polecenie:
Pomóż początkującemu zbudować edukacyjny moduł kokpitu. Wyjaśniaj kroki, nie wymyślaj pinów ani interfejsów symulatorów.
Sprzęt: Arduino Uno R3; cztery czerwone LED na D2,D3,D4,D5, każda przez 1 kOhm, katody do GND. OLED Adafruit 4440, SSD1306 128x32 I2C 0x3C; VIN=5V, GND=GND, SDA=A4, SCL=A5, automatyczny reset bez RST.
Zadanie: kompletny szkic z Wire, Adafruit GFX i Adafruit SSD1306. Odbiór moich testowych komunikatów USB-serial 115200 bodów, maksymalnie 5 linii/s: V1,speed,rpm,fuel,flags oraz LF; obsłuż CRLF. Zakresy: speed 0..999, rpm 0..20000, fuel 0..100, flags 0..15. Wartości 1,2,4,8 wybierają LED1..4.
Rezultat: cztery wiersze tekstu z wartościami i stanami. Start WAIT; poprawny komunikat DATA/OK; błędny ERR bez częściowych zmian. Po 3000 ms bez poprawnych danych zgaś LED, pokaż STALE i zachowaj ostatnie liczby.
Ograniczenia: stały bufor 64 bajty; zbyt długą linię odrzuć do LF; bez dynamicznych obiektów String i delay w loop; aktualizacja ekranu najwyżej co 200 ms. Uwzględnij SRAM, w tym 512 bajtów bufora OLED. Wyjaśnij błędy połączenia i pamięci.
Podaj połączenia, pełny kod, biblioteki i testy pojedynczych LED, wszystkich LED, błędnych wartości, przekroczenia długości i przerwania danych. Oddziel kompilację od testu fizycznego.
Przygotuj, wgraj i zrozum szkic
W Arduino IDE wybierz „Arduino Uno” i właściwy port. Menedżerem bibliotek zainstaluj Adafruit SSD1306 i Adafruit GFX Library wraz z Adafruit BusIO. Wire należy do pakietu AVR. Otwórz pobrany szkic w folderze uno-led-oled, najpierw go skompiluj, a potem wgraj na własną płytkę.
Cały kod można rozwinąć i pobrać poniżej. Logika odbiera dane etapami bez czekania przez delay(), a obraz odświeża najwyżej pięć razy na sekundę. Transmisja I²C nadal zajmuje czas: nie jest to gwarancja czasu rzeczywistego. Długie przewody lub dodatkowe urządzenia wymagają osobnych prób.
Bufor obrazu zajmuje 512 bajtów oprócz zmiennych, buforów bibliotek i stosu. Statyczny raport RAM nie pokazuje w pełni tej rezerwacji w czasie działania. F() trzyma stałe napisy we flash; szkic nie używa Arduino String. Poprawna kompilacja nie potwierdza sprawności połączeń ani ekranu.
Szkic skompilowano lokalnie dla arduino:avr:uno z AVR 1.8.7, Adafruit SSD1306 2.5.9, GFX 1.11.9 i BusIO 1.15.0: 15 168 bajtów flash i 614 bajtów statycznego RAM. Trzeba dodatkowo uwzględnić 512 bajtów bufora obrazu. Nie przeprowadzono tutaj próby fizycznego układu.
Pobierz kompletny szkic Arduino
Pokaż cały kod przykładu
// Cockpit Suite workshop learning example. This is not a simulator protocol.
// Board: Arduino Uno R3. OLED: Adafruit 4440, SSD1306 128x32, I2C 0x3C.
// OLED VIN=5V, GND=GND, SDA=A4, SCL=A5; auto-reset, no reset wire.
// LEDs: D2/D3/D4/D5 -> individual 1k resistor -> anode; cathodes -> GND.
// Send at most 5 lines/second: V1,speed,rpm,fuel,flags followed by LF.
// Example: V1,120,3500,65,5 (LED1 and LED3 on). CR before LF is accepted.
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <string.h>
const uint8_t LED_PINS[4] = {2, 3, 4, 5};
const uint8_t OLED_ADDRESS = 0x3C;
const uint32_t DATA_TIMEOUT_MS = 3000;
const uint32_t SCREEN_INTERVAL_MS = 200;
Adafruit_SSD1306 display(128, 32, &Wire, -1);
char lineBuffer[64];
uint8_t lineLength = 0;
bool discardLine = false;
bool haveData = false;
bool oledReady = false;
uint16_t speedValue = 0, rpmValue = 0, fuelValue = 0, flagValue = 0;
uint32_t lastDataMs = 0, lastScreenMs = 0;
bool parseNumber(const char *&cursor, uint16_t limit, char separator,
uint16_t &result) {
if (*cursor < '0' || *cursor > '9') return false;
uint16_t value = 0;
while (*cursor >= '0' && *cursor <= '9') {
uint8_t digit = *cursor++ - '0';
if (value > limit / 10 ||
(value == limit / 10 && digit > limit % 10)) return false;
value = value * 10 + digit;
}
if (*cursor != separator) return false;
if (separator != '\0') ++cursor;
result = value;
return true;
}
bool parseLine(const char *line) {
if (strncmp(line, "V1,", 3) != 0) return false;
const char *cursor = line + 3;
uint16_t speed, rpm, fuel, flags;
if (!parseNumber(cursor, 999, ',', speed) ||
!parseNumber(cursor, 20000, ',', rpm) ||
!parseNumber(cursor, 100, ',', fuel) ||
!parseNumber(cursor, 15, '\0', flags)) return false;
speedValue = speed;
rpmValue = rpm;
fuelValue = fuel;
flagValue = flags;
lastDataMs = millis();
haveData = true;
return true;
}
void readSerial() {
// Bound each pass so a continuous stream cannot starve the outputs.
for (uint8_t count = 0; count < 32 && Serial.available(); ++count) {
char character = (char)Serial.read();
if (character == '\r') continue;
if (character == '\n') {
lineBuffer[lineLength] = '\0';
if (!discardLine && parseLine(lineBuffer)) Serial.println(F("OK"));
else Serial.println(F("ERR"));
lineLength = 0;
discardLine = false;
} else if (!discardLine) {
// NUL and non-printable input are not part of this text protocol.
if (character < 32 || character > 126 ||
lineLength >= sizeof(lineBuffer) - 1) {
discardLine = true;
} else {
lineBuffer[lineLength++] = character;
}
}
}
}
void renderScreen(bool fresh) {
display.clearDisplay();
display.setCursor(0, 0);
display.print(F("S:")); display.print(speedValue);
display.print(F(" R:")); display.println(rpmValue);
display.print(F("F:")); display.print(fuelValue);
display.print(F("% LED:"));
for (uint8_t index = 0; index < 4; ++index)
display.print(fresh && (flagValue & (1U << index)) ? '1' : '0');
display.println();
display.println(!haveData ? F("WAIT") : (fresh ? F("DATA") : F("STALE")));
display.print(F("DEMO SERIAL"));
display.display();
}
void setup() {
for (uint8_t index = 0; index < 4; ++index) {
digitalWrite(LED_PINS[index], LOW);
pinMode(LED_PINS[index], OUTPUT);
}
Serial.begin(115200);
Wire.begin();
#if defined(WIRE_HAS_TIMEOUT)
Wire.setWireTimeout(25000, true);
#endif
Wire.beginTransmission(OLED_ADDRESS);
bool addressResponds = (Wire.endTransmission() == 0);
oledReady = addressResponds &&
display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDRESS, false, false);
if (oledReady) {
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setTextWrap(false);
renderScreen(false);
} else {
Serial.println(F("OLED ERROR: check model, wiring, address, RAM"));
}
Serial.println(F("READY: V1,speed,rpm,fuel,flags"));
}
void loop() {
readSerial();
uint32_t now = millis();
bool fresh = haveData && (uint32_t)(now - lastDataMs) < DATA_TIMEOUT_MS;
for (uint8_t index = 0; index < 4; ++index)
digitalWrite(LED_PINS[index],
fresh && (flagValue & (1U << index)) ? HIGH : LOW);
if (oledReady && (uint32_t)(now - lastScreenMs) >= SCREEN_INTERVAL_MS) {
lastScreenMs = now;
renderScreen(fresh);
}
}
Sprawdź zachowanie konkretnymi komunikatami
Ustaw monitor portu na 115200 bodów oraz nową linię albo „NL & CR”. Otwarcie portu może zresetować Uno: zaczekaj na READY. Po pierwszym uruchomieniu oczekuj WAIT i wszystkich LED wyłączonych.
Wyślij V1,120,3500,65,1: świecić ma tylko LED 1. Kolejno zamień ostatnią wartość na 2, 4 i 8. V1,120,3500,65,15 zapala wszystkie, a końcowe 0 je gasi. Porównaj wszystkie liczby na OLED z komunikatem. Sprawdź też granice: V1,999,20000,100,15 i V1,0,0,0,0.
Wyślij celowo V1,120,3500,101,5 albo pomiń pole. Oczekuj ERR bez częściowych zmian. Linia dłuższa niż 63 znaki ma zostać odrzucona do końca, a następna poprawna przyjęta. Po ponad trzech sekundach LED mają zgasnąć i pojawić się STALE. Kolejna poprawna linia ma przywrócić pracę. Oddzielnie zapisuj wynik oczekiwany i rzeczywisty.
Bezpośrednie porównanie: V1,120,3500,65,15 zapala wszystkie cztery LED, V1,120,3500,65,0 gasi wszystkie, a V1,120,3500,65,5 zapala tylko LED 1 i 3.
Zawęź problem przed zmianą układu
Przy ciemnej LED sprawdź polaryzację, jej rezystor i przypisany pin. Przy ciemnym OLED sprawdź model, zasilanie, masę, SDA/SCL i adres. OLED ERROR może oznaczać brak odpowiedzi magistrali lub nieudaną rezerwację pamięci. Sama odpowiedź adresu I²C nie potwierdza poprawnego obrazu.
Zapytaj AI konkretnie: „Uno R3, moduł 4440, szkic bez zmian. READY jest, V1,120,3500,65,1 daje OK, LED1 działa, ale OLED jest czarny. Jakie połączenia sprawdzić najpierw bez zasilania?” Dodaj wersje bibliotek i pełne błędy kompilatora. Proś o jedną uzasadnioną zmianę naraz.
Zachowaj działającą wersję przed rozbudową, poproś o objaśnienie zmian i powtórz testy. Poradnik wyszukiwania usterek porządkuje ten proces. Nie umieszczaj w pytaniu haseł, prywatnych konfiguracji ani niezwiązanych katalogów projektu. Mały zrozumiany krok daje lepszą podstawę niż wymiana całego programu bez diagnozy.
Przejdź od ćwiczenia do danych symulatora
Rzeczywiste dane wymagają udokumentowanej drogi po stronie komputera: odczytu źródła, przeliczenia jednostek, kontroli i wysłania wiadomości. V1 jest formatem tego ćwiczenia, nie deklarowanym interfejsem Cockpit Suite. Sprawdź obsługiwaną integrację urządzeń przed planowaniem automatycznego mostu. Monitor portu i drugi program zwykle nie mogą jednocześnie zajmować tego samego portu.
Ustal, czy LED pokazuje żądanie przełącznika, czy potwierdzony stan symulatora. Odróżnij brak danych od stanu wyłączenia. Pomogą przypisywanie danych oraz ekrany i instrumenty.
Jeśli potrzebujesz głównie przycisków i osi jako joysticka USB, FreeJoy proponuje inną drogę na odpowiednim sprzęcie. Ten szkic korzysta z USB-serial Uno i nie zmienia go w natywny joystick. Rozbuduj panel dopiero po potwierdzeniu całej pojedynczej drogi sygnału.
Kolejny krok wykonaj ze wsparciem społeczności
Cockpit Suite łączy obsługiwane symulatory i urządzenia we wspólnym środowisku. Projekt jest młody, lecz ma już dostępne oprogramowanie i rzeczywiste realizacje. Przygotowane kombinacje ułatwiają obsługiwane etapy; własny moduł Arduino nadal wymaga nauki i integracji. Twoje odtwarzalne doświadczenia pomagają je ulepszać.
Na forum Cockpit Suite pokaż cel, części i ostatni udany test. Chcemy pomóc w następnym kroku i staramy się odpowiadać tego samego dnia, jeśli to możliwe; późne pytania mogą otrzymać odpowiedź później. Pomagamy także przy druku 3D, frezarkach CNC i laserze z LightBurn. Aktywna społeczność w Europie i poza nią zamienia pojedyncze sukcesy w przydatną wiedzę.
Źródła i podstawy techniczne
Sprawdzone 18 października 2026. Procedura, protokół i szkic są własnym przykładem edukacyjnym. Dokumentacja nie zastępuje próby rzeczywistego układu.
- Arduino UNO R3Platforma Uno R3 i oficjalny opis pinów.
- Adafruit 4440: 128×32 I²C OLEDDokładny model: rozdzielczość, logika, automatyczny reset i adres I²C.
- Adafruit: Wiring 128×32 I²C DisplayOficjalne połączenia I²C; starsze wersje odróżnione od 4440.
- Adafruit SSD1306 library implementationImplementacja biblioteki: bufor, inicjalizacja i transmisja.