يحتوي هذا المستودع على التعليمات البرمجية والوثائق والأشياء الأخرى المتعلقة بمشروع السيارة اللعبة الصفراء الذي قمت بإنشائه.
لقد قمت أيضًا بإنشاء تطبيق Flutter للهاتف المحمول للتحكم في السيارة اللعبة، راجع مستودع YellowToyCarApp.
تتكون الأجهزة من:
تتكون البرامج من:
/
أو /index
أو /index.html
→ موقع ويب مُقدم للمستخدم للتحكم في السيارة.
/status
→ الحالة الأساسية، بما في ذلك الوقت وحالة الأضواء والمحركات والبيانات التشخيصية الأخرى.
{
"uptime" : 123456 , // Microseconds passed from device boot.
"time" : "2023-01-12T23:49:03.348+0100" , // Device time, synced using SNTP.
"rssi" : - 67 , // Signal strength of AP the device is connected to, or 0 if not connected.
/* With `?details=1` querystring parameter, extended response is provided. */
"stations" : [ "a1:b2:c3:d4:e5:f6" ] , // list of stations currently connected to our AP
}
/config
→ نقطة النهاية لطلبات ضبط التكوين (JSON GET/POST API)
{
/* Control & config for motors and lights */
"control" : {
/* Other */
"timeout" : 2000 , // Time in milliseconds counted from last control request/packet, after which movement should stop for safety reason
/* Input values */
"mainLight" : 1 ,
"otherLight" : 1 ,
"left" : 12.3 , // The motors duty cycle are floats as percents,
"right" : 12.3 , // i.e. 12.3 means 12.3% duty cycle.
/* Calibration */
"calibrate" : {
"left" : 0.95 , // Inputs will be multiplied by calibration values before outputting PWM signal.
"right" : 1.05 ,
"frequency" : 100 , // Frequency to be used by PWMs
}
} ,
/* Networking related. Some things are not implemented, including: DNS and DHCP leases */
"network" : {
"mode" : "ap" , // for Access Point or "sta" for station mode, or "nat" (to make it work like router)
"fallback" : 10000 , // duration after should fallback to hosting AP if cannot connect as station
"dns1" : "1.1.1.1" ,
"dns2" : "1.0.0.1" ,
"sta" : {
"ssid" : "YellowToyCar" ,
"psk" : "AAaa11!!" ,
"static" : 0 , // 1 if static IP is to be used in STA mode
"ip" : "192.168.4.1" ,
"mask" : 24 , // as number or IP
"gateway" : "192.168.4.1"
} ,
"ap" : {
"ssid" : "YellowToyCar" ,
"psk" : "AAaa11!!" ,
"channel" : 0 , // channel to use for AP, 0 for automatic
"hidden" : 0 ,
"ip" : "192.168.4.1" ,
"mask" : 24 , // as number or IP
"gateway" : "192.168.4.1" ,
"dhcp" : {
"enabled" : 1 ,
"lease" : [ "192.168.4.1" , "192.168.4.20" ] ,
}
} ,
"sntp" : {
"pool" : "pl.pool.ntp.org" ,
"tz" : "CET-1CEST,M3.5.0,M10.5.0/3" ,
"interval" : 3600000
}
} ,
/* Camera settings. See this project or `esp32_camera` library sources for details. */
"camera" : {
"framesize" : 13 ,
"pixformat" : 4 ,
"quality" : 12 ,
"bpc" : 0 ,
"wpc" : 1 ,
"hmirror" : 0 ,
"vflip" : 0 ,
"contrast" : 0 ,
"brightness" : 0 ,
"sharpness" : 0 ,
"denoise" : 0 ,
"gain_ceiling" : 0 ,
"agc" : 1 ,
"agc_gain" : 0 ,
"aec" : 1 ,
"aec2" : 0 ,
"ae_level" : 0 ,
"aec_value" : 168 ,
"awb" : 1 ,
"awb_gain" : 1 ,
"wb_mode" : 0 ,
"dcw" : 1 ,
"raw_gma" : 1 ,
"lenc" : 1 ,
"special" : 0
}
}
يُرجع JSON بالتكوين الحالي، إذا لم يغير أي شيء.
192.168.4.1
في الوقت الحالي، نظرًا لأن إعدادات DHCP مشفرة ببعض القيم الافتراضية. /capture
→ التقاط الإطار من كاميرا السيارة.
:81/stream
→ تتدفق الإطارات المستمرة من كاميرا السيارة باستخدام MJPEG الذي يستغل نوع المحتوى الخاص: multipart/x-mixed-replace
الذي يُعلم العميل باستبدال الصورة إذا لزم الأمر. يتم استخدام خادم HTTP منفصل (وبالتالي المنفذ غير القياسي 81)، حيث إنها أسهل طريقة لإرسال الأجزاء بشكل مستمر (الإطارات التالية) في هذا الطلب الفردي الذي لا نهاية له.
ينتظر التطبيق حزم UDP على المنفذ 83.
ثماني | 0 | 1 | 2 | 3 | |
---|---|---|---|---|---|
ثماني | أجزاء | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 | 16 17 18 19 20 21 22 23 | 24 25 26 27 28 29 30 31 |
0 | 0 | (UDP) منفذ المصدر | (UDP) منفذ الوجهة | ||
4 | 32 | (UDP) الطول | (UDP) المجموع الاختباري | ||
8 | 64 | نوع الحزمة (دائمًا 1) | الأعلام (انظر الجدول أدناه) | واجب المحرك الأيسر | واجب المحرك الصحيح |
قليل | قناع | وصف |
---|---|---|
0 | 0b00000001 | الضوء الرئيسي (LED خارجي أبيض ساطع) |
1 | 0b00000010 | ضوء آخر (LED أحمر صغير داخلي) |
2 | 0b00000100 | محجوز |
3 | 0b00001000 | محجوز |
4 | 0b00010000 | محجوز |
5 | 0b00100000 | محجوز |
6 | 0b01000000 | اتجاه المحرك الأيسر |
7 | 0b10000000 | الاتجاه الصحيح للمحرك |
0
) تعني للأمام، والبتة المحددة ( 1
) تعني للخلف. ثماني | 0 | 1 | 2 | 3 | |
---|---|---|---|---|---|
ثماني | أجزاء | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15 | 16 17 18 19 20 21 22 23 | 24 25 26 27 28 29 30 31 |
0 | 0 | (UDP) منفذ المصدر | (UDP) منفذ الوجهة | ||
4 | 32 | (UDP) الطول | (UDP) المجموع الاختباري | ||
8 | 64 | نوع الحزمة: 2 | الأعلام (انظر أدناه) | الوقت (بالمللي ثانية) للمزج السلس نحو القيم الحركية المستهدفة | |
12 | 96 | واجب المحرك الأيسر، النسبة المئوية كتعويم (أي 63.8f تساوي 63.3% من دورة التشغيل) | |||
16 | 128 | واجب المحرك الأيمن، النسبة المئوية للتعويم (أي 63.8f تساوي 63.3% من دورة العمل) |
تم تطوير بعض البرامج النصية لتسهيل التطوير والاستخدام.
$ python . s cripts c onfig.py --help
usage: config.py [-h] [--status] [--status-only] [--config-file PATH] [--wifi-mode {ap,sta,apsta,nat,null}] [--ip IP] [--read-only] [--restart [RESTART]]
This script allows to send & retrieve config from the car.
optional arguments:
-h, --help show this help message and exit
--status Request status before sending/requesting config.
--status-only Only request status.
--config-file PATH JSON file to be send as config.
--wifi-mode {ap,sta,apsta,nat,null}
Overwrite WiFi mode from config.
--ip IP, --address IP
IP of the device. Defaults to the one used for AP mode from new config or 192.168.4.1.
--read-only If set, only reads the request (GET request instead POST).
--restart [TIMEOUT] Requests for restart after updating config/retrieving the config.
$ python . s cripts c ontrol.py --help
usage: control.py [-h] [--ip IP] [--port PORT] [--interval INTERVAL] [--dry-run] [--show-packets] [--short-packet-type] [--no-blink] [--max-speed VALUE] [--min-speed VALUE] [--acceleration VALUE]
This script allows to control the car by continuously reading keyboard inputs and sending packets.
optional arguments:
-h, --help show this help message and exit
--ip IP, --address IP
IP of the device. Default: 192.168.4.1
--port PORT Port of UDP control server. Default: 83
--interval INTERVAL Interval between control packets in milliseconds. Default: 100
--dry-run Performs dry-run for testing.
--show-packets Show sent packets (like in dry run).
--short-packet-type Uses short packet type instead long.
--no-blink Prevents default behaviour of constant status led blinking.
Driving model:
--max-speed VALUE Initial maximal speed. From 0.0 for still to 1.0 for full.
--min-speed VALUE Minimal speed to drive motor. Used to avoid motor noises and damage.
--acceleration VALUE Initial acceleration per second.
Note: The 'keyboard' library were used (requires sudo under Linux), and it hooks work also out of focus, which is benefit and issue at the same time, so please care.
Controls:
WASD (or arrows) keys to move; QE to rotate;
F to toggle main light; R to toggle the other light;
Space to stop (immediately, uses both UDP and HTTP);
V to toggle between vectorized (smoothed) and raw mode;
+/- to modify acceleration; [/] to modify max speed;
Shift to temporary uncap speed; ESC to exit.
اسم ودود | اسم | تقارب | أولوية | ملف المصدر | وصف |
---|---|---|---|---|---|
مهام IPC | ipcx * | الجميع* | 0 | (داخلي) | تُستخدم مهام IPC لتنفيذ ميزة الاتصال بين المعالجات. |
رئيسي | main | وحدة المعالجة المركزية0 | 1 | main.cpp | يقوم بتهيئة كل شيء، وبدء مهام أخرى، ثم يحمل منطق الخلفية. |
تيار الكاميرا | httpd | وحدة المعالجة المركزية0 | 5 | camera.cpp | |
LwIP | ؟ | ||||
واي فاي | وحدة المعالجة المركزية0 | ||||
الأحداث | ؟ | ||||
المهام الخاملة | ipcx * | الجميع* | 24 | (داخلي) | المهام الخاملة التي تم إنشاؤها (وتثبيتها) لكل وحدة معالجة مركزية. |
* - تعمل بعض المهام على وحدات معالجة مركزية متعددة، كمهام منفصلة.
struct
. انظر المناقشة هنا. كحل اكتشفت أنه من الأسهل استخدام strncpy
الذي يتم تضمينه/تحسينه._binary_src_
أثناء الوصول إلى تسميات البداية/النهاية لكتل البيانات المضمنة (كما هو الحال في الماكرو GENERATE_HTTPD_HANDLER_FOR_EMBEDDED_FILE
)، فهذا غير صحيح. تبدو المستندات قديمة أو غير صالحة في بعض المناطق، على الأقل بالنسبة إلى esp-idf
. ومع ذلك فقد وجدت الحل : استخدم كلاً من board_build.embed_files
في platformio.ini
وأيضًا EMBED_FILES
في CMakeLists.txt
. في الكود، استخدم _binary_
، بدون جزء src_
.snake_case
مع camelCase
لأننا نستخدم مكتبات C من ESP-IDF وبعض الأجزاء تستخدمها كثيرًا. ومن أقبح من ركوب جمل واحد وسط الثعابين.ESP_LOGV
و ESP_LOGD
بسهولة لملف واحد، لذا أعيد تعريف وحدات الماكرو هذه إلى ESP_LOGI
كحل بديل.esp32-camera
التي يستخدمها المشروع على بعض المشكلات الغريبة، إليك بعضها:camera.py
، والذي يتضمن مهمة إرساله عبر WiFi:string_view
s، كما هو الحال في التعليمات البرمجية ذات الصلة بـ config/JSON. واجهت مشكلة مؤخرًا مع كون strlen
غير آمن ...vTaskList
/ uxTaskGetSystemState
Kconfig
الخاص بنا للاحتفاظ بالميزات الاختيارية هناك، بما في ذلك بعض عمليات تصحيح الأخطاء. راجع أيضًا https://esp32tutorials.com/esp32-static-fixed-ip-address-esp-idf/esp32-camera
fb_size
عند استخدام JPEG للسماح لأصغر 96 × 96 بالعمل. يبدو أن الحد الأدنى من 2048 يعمل، ويبدو أنه من المستحسن استخدام المزيد من أجل حسن التدبير. (المشكلة على جيثب).xclk_freq_hz = 10'000'000,
للكاميرا_ camera_config_t
؟ قد يكون 10 ميجا هرتز أفضل من 20 ميجا هرتز، راجع espressif/esp32-camera#15COM8_AGC_EN
في الكاميرا يسجل التعريفات بمقدار 1؟constexpr
لوظيفة IP 4