พื้นที่เก็บข้อมูลนี้มีโค้ด เอกสาร และสิ่งอื่นๆ ที่เกี่ยวข้องกับโครงการรถของเล่นสีเหลืองที่ฉันสร้างขึ้น
ฉันยังสร้างแอปมือถือ 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.
ชื่อที่เป็นมิตร | ชื่อ | ความสัมพันธ์ | ลำดับความสำคัญ | ไฟล์ต้นฉบับ | คำอธิบาย |
---|---|---|---|---|---|
งานไอพีซี | ipcx * | ทั้งหมด* | 0 | (ภายใน) | งาน IPC ถูกใช้เพื่อใช้คุณลักษณะการโทรระหว่างโปรเซสเซอร์ |
หลัก | main | ซีพียู0 | 1 | main.cpp | เริ่มต้นทุกอย่าง เริ่มงานอื่นๆ จากนั้นดำเนินตรรกะเบื้องหลัง |
สตรีมกล้อง | httpd | ซีพียู0 | 5 | camera.cpp | |
แอลดับบลิวไอพี | - | ||||
อินเตอร์เน็ตไร้สาย | ซีพียู0 | ||||
กิจกรรม | - | ||||
งานที่ไม่ได้ใช้งาน | ipcx * | ทั้งหมด* | 24 | (ภายใน) | งานที่ไม่ได้ใช้งานที่สร้างขึ้นสำหรับ (และปักหมุดไว้ที่) CPU แต่ละตัว |
* - งานบางอย่างทำงานบน CPU หลายตัว โดยเป็นงานแยกกัน
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 libraries จาก 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 เพื่อให้ขนาด 96x96 ที่เล็กที่สุดทำงานได้ ดูเหมือนว่าการมีอย่างน้อย 2,048 จะได้ผล แนะนำให้ใช้มากกว่านี้เพื่อการวัดผลที่ดี (ปัญหาบน GitHub).xclk_freq_hz = 10'000'000,
สำหรับ camera_config_t
? 10 MHz อาจดีกว่า 20 MHz โปรดดู espressif/esp32-cam#15COM8_AGC_EN
ในกล้องไม่ได้ลงทะเบียนคำจำกัดความออก 1 หรือไม่constexpr
ที่รวดเร็วและ C ++ เป็นฟังก์ชัน IP 4