TinLethax

ESP32CAM_CARCODE

May 18th, 2023
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.29 KB | None | 0 0
  1. //OpenCV Lane Detection 04
  2. const char* ssid = "LAB_SIEMENS_6";
  3. const char* password = "123456789";
  4.  
  5. //AP http://192.168.4.1
  6. const char* apssid = "esp32-cam";
  7. const char* appassword = "12345678";
  8.  
  9. #include <WiFi.h>
  10. #include "soc/soc.h"
  11. #include "soc/rtc_cntl_reg.h"
  12. #include <esp32-hal-ledc.h>
  13.  
  14. #include "esp_http_server.h"
  15. #include "esp_camera.h"
  16. #include "img_converters.h"
  17.  
  18. String Feedback="";
  19.  
  20. String Command="";
  21. String cmd="";
  22. String P1="";
  23. String P2="";
  24. String P3="";
  25.  
  26. ////////////////////////////////////////////////
  27. String F = "0";
  28. String L = "1";
  29. String R = "-1";
  30. String U = "0";
  31. String R2 = "-3";
  32. String L2 = "3";
  33. int SpeedR=180,SpeedL=180,VALUE_R ,VALUE_L ;
  34. int Set_Point = 0;
  35. int Max_Set_Point = 8;
  36. bool Revert = 1 ;
  37. //////////////////////////////////////////////
  38.  
  39. byte ReceiveState=0;
  40. byte cmdState=1;
  41. byte strState=1;
  42. byte questionstate=0;
  43. byte equalstate=0;
  44. byte semicolonstate=0;
  45.  
  46. typedef struct {
  47. httpd_req_t *req;
  48. size_t len;
  49. } jpg_chunking_t;
  50.  
  51. #define PART_BOUNDARY "123456789000000000000987654321"
  52. static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
  53. static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n";
  54. static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n";
  55.  
  56. httpd_handle_t stream_httpd = NULL;
  57. httpd_handle_t camera_httpd = NULL;
  58.  
  59. #define PWDN_GPIO_NUM 32
  60. #define RESET_GPIO_NUM -1
  61. #define XCLK_GPIO_NUM 0
  62. #define SIOD_GPIO_NUM 26
  63. #define SIOC_GPIO_NUM 27
  64.  
  65. #define Y9_GPIO_NUM 35
  66. #define Y8_GPIO_NUM 34
  67. #define Y7_GPIO_NUM 39
  68. #define Y6_GPIO_NUM 36
  69. #define Y5_GPIO_NUM 21
  70. #define Y4_GPIO_NUM 19
  71. #define Y3_GPIO_NUM 18
  72. #define Y2_GPIO_NUM 5
  73. #define VSYNC_GPIO_NUM 25
  74. #define HREF_GPIO_NUM 23
  75. #define PCLK_GPIO_NUM 22
  76.  
  77. // L298N pinout (ESP32)
  78. #define L_PWM 12
  79. #define ENA_L 13
  80. #define ENB_L 15
  81. #define ENA_R 14
  82. #define ENB_R 2
  83. #define R_PWM 16
  84.  
  85. void setup() {
  86. WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);
  87.  
  88. WiFi.disconnect(true);
  89. WiFi.mode(WIFI_OFF);
  90.  
  91. Serial.begin(115200);
  92. Serial.setDebugOutput(true);
  93. Serial.println();
  94.  
  95. camera_config_t config;
  96. config.ledc_channel = LEDC_CHANNEL_0;
  97. config.ledc_timer = LEDC_TIMER_0;
  98. config.pin_d0 = Y2_GPIO_NUM;
  99. config.pin_d1 = Y3_GPIO_NUM;
  100. config.pin_d2 = Y4_GPIO_NUM;
  101. config.pin_d3 = Y5_GPIO_NUM;
  102. config.pin_d4 = Y6_GPIO_NUM;
  103. config.pin_d5 = Y7_GPIO_NUM;
  104. config.pin_d6 = Y8_GPIO_NUM;
  105. config.pin_d7 = Y9_GPIO_NUM;
  106. config.pin_xclk = XCLK_GPIO_NUM;
  107. config.pin_pclk = PCLK_GPIO_NUM;
  108. config.pin_vsync = VSYNC_GPIO_NUM;
  109. config.pin_href = HREF_GPIO_NUM;
  110. config.pin_sscb_sda = SIOD_GPIO_NUM;
  111. config.pin_sscb_scl = SIOC_GPIO_NUM;
  112. config.pin_pwdn = PWDN_GPIO_NUM;
  113. config.pin_reset = RESET_GPIO_NUM;
  114. config.xclk_freq_hz = 20000000;
  115. config.pixel_format = PIXFORMAT_JPEG;
  116.  
  117. if(psramFound()){
  118. config.frame_size = FRAMESIZE_UXGA;
  119. config.jpeg_quality = 10;
  120. config.fb_count = 2;
  121. } else {
  122. config.frame_size = FRAMESIZE_SVGA;
  123. config.jpeg_quality = 12;
  124. config.fb_count = 1;
  125. }
  126.  
  127. esp_err_t err = esp_camera_init(&config);
  128. if (err != ESP_OK) {
  129. Serial.printf("Camera init failed with error 0x%x", err);
  130. ESP.restart();
  131. }
  132.  
  133. sensor_t * s = esp_camera_sensor_get();
  134. // initial sensors are flipped vertically and colors are a bit saturated
  135. if (s->id.PID == OV3660_PID) {
  136. s->set_vflip(s, 1); // flip it back
  137. s->set_brightness(s, 1); // up the brightness just a bit
  138. s->set_saturation(s, -2); // lower the saturation
  139. }
  140.  
  141. s->set_framesize(s, FRAMESIZE_QVGA); //程式內定使用QVGA(320x240),不可改此設定
  142.  
  143. ledcAttachPin(4, 4);
  144. ledcSetup(4, 5000, 8);
  145.  
  146. // Setup Left and right motor PWM
  147. ledcAttachPin(L_PWM, 5);
  148. ledcSetup(5, 15000, 8);
  149. ledcAttachPin(R_PWM, 6);
  150. ledcSetup(6, 15000, 8);
  151. // Setup Left and right motor control
  152. pinMode(ENA_L, OUTPUT);
  153. pinMode(ENB_L, OUTPUT);
  154. pinMode(ENA_R, OUTPUT);
  155. pinMode(ENB_R, OUTPUT);
  156.  
  157. //WiFi.mode(WIFI_AP_STA); //其他模式 WiFi.mode(WIFI_AP); WiFi.mode(WIFI_STA);
  158. WiFi.mode(WIFI_STA); //其他模式 WiFi.mode(WIFI_AP); WiFi.mode(WIFI_STA);
  159.  
  160. for (int i=0;i<2;i++) {
  161. WiFi.begin(ssid, password); //執行網路連線
  162.  
  163. delay(1000);
  164. Serial.println("");
  165. Serial.print("Connecting to ");
  166. Serial.println(ssid);
  167.  
  168. long int StartTime=millis();
  169. while (WiFi.status() != WL_CONNECTED) {
  170. delay(500);
  171. if ((StartTime+5000) < millis()) break; //等待10秒連線
  172. }
  173.  
  174. if (WiFi.status() == WL_CONNECTED) { //若連線成功
  175. WiFi.softAP((WiFi.localIP().toString()+"_"+(String)apssid).c_str(), appassword); //設定SSID顯示客戶端IP
  176. Serial.println("");
  177. Serial.println("STAIP address: ");
  178. Serial.println(WiFi.localIP());
  179. Serial.println("");
  180.  
  181. for (int i=0;i<3;i++) { //若連上WIFI設定閃光燈快速閃爍
  182. ledcWrite(4,10);
  183. delay(200);
  184. ledcWrite(4,0);
  185. delay(200);
  186. }
  187. break;
  188. }
  189. }
  190.  
  191.  
  192. startCameraServer();
  193.  
  194. pinMode(4, OUTPUT);
  195. digitalWrite(4, LOW);
  196.  
  197. }
  198.  
  199. unsigned long period = 100; //ระยะเวลาที่ต้องการรอ
  200. unsigned long last_time = 0; //ประกาศตัวแปรเป็น global เพื่อเก็บค่าไว้ไม่ให้ reset จากการวนloop
  201. unsigned int Count_Stop = 0 ;
  202. unsigned int Count_R2 = 0 ;
  203. bool Python_Offline = 0;
  204.  
  205. void loop() {
  206. if( millis() - last_time > period) {
  207. last_time = millis();
  208. if ( P1 != "" ){
  209. int Buf = P1.toInt();
  210. P1 = "" ;
  211. Set_Point = Buf ;
  212.  
  213. if ( Set_Point == 0 ) {
  214. VALUE_R = SpeedR ;
  215. VALUE_L = SpeedL ;
  216. }
  217. else if ( Set_Point < 0 ) {
  218. VALUE_R = SpeedR + ( Set_Point );
  219. VALUE_L = SpeedL ;
  220. }
  221. else{
  222. VALUE_R = SpeedR ;
  223. VALUE_L = SpeedL - ( Set_Point );
  224. }
  225.  
  226. Serial.print(P1);Serial.print(" ");
  227. Serial.print(Set_Point);Serial.print(" ");
  228. Serial.print(VALUE_R);Serial.print(" ");
  229. Serial.println(VALUE_L);
  230.  
  231. if ( Revert == 0 ){
  232. ledcWrite(5, VALUE_L);// Left motor PWM
  233. ledcWrite(6, VALUE_R);// Right motor PWM
  234. digitalWrite(ENA_L, 1);
  235. digitalWrite(ENB_L, 0);
  236. digitalWrite(ENA_R, 1);
  237. digitalWrite(ENB_R, 0);
  238. }
  239. if ( Revert == 1 ){
  240. ledcWrite(5, VALUE_L);// Left motor PWM
  241. ledcWrite(6, VALUE_R);// Right motor PWM
  242. digitalWrite(ENA_L, 0);
  243. digitalWrite(ENB_L, 1);
  244. digitalWrite(ENA_R, 0);
  245. digitalWrite(ENB_R, 1);
  246. }
  247. Count_Stop = 0;Python_Offline = 0;
  248. }
  249.  
  250. if ( Count_Stop != 10 ) { Count_Stop++; }
  251. else {
  252. // Do soft break
  253. ledcWrite(5, 0);// Left motor PWM
  254. ledcWrite(6, 0);// Right motor PWM
  255. digitalWrite(ENA_L, 0);
  256. digitalWrite(ENB_L, 0);
  257. digitalWrite(ENA_R, 0);
  258. digitalWrite(ENB_R, 0);
  259. if ( Python_Offline == 0){
  260. Python_Offline =1;
  261. Serial.println("Python Offline");
  262. }
  263. }
  264. }
  265.  
  266. }
  267. static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){
  268. jpg_chunking_t *j = (jpg_chunking_t *)arg;
  269. if(!index){
  270. j->len = 0;
  271. }
  272. if(httpd_resp_send_chunk(j->req, (const char *)data, len) != ESP_OK){
  273. return 0;
  274. }
  275. j->len += len;
  276. return len;
  277. }
  278.  
  279. static esp_err_t capture_handler(httpd_req_t *req){
  280. camera_fb_t * fb = NULL;
  281. esp_err_t res = ESP_OK;
  282. fb = esp_camera_fb_get();
  283. if (!fb) {
  284. Serial.println("Camera capture failed");
  285. httpd_resp_send_500(req);
  286. return ESP_FAIL;
  287. }
  288. httpd_resp_set_type(req, "image/jpeg");
  289. httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
  290. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  291.  
  292. size_t fb_len = 0;
  293. if(fb->format == PIXFORMAT_JPEG){
  294. fb_len = fb->len;
  295. res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
  296. } else {
  297. jpg_chunking_t jchunk = {req, 0};
  298. res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
  299. httpd_resp_send_chunk(req, NULL, 0);
  300. fb_len = jchunk.len;
  301. }
  302. esp_camera_fb_return(fb);
  303. return res;
  304. }
  305.  
  306. static esp_err_t cmd_handler(httpd_req_t *req){
  307. char* buf;
  308. size_t buf_len;
  309. char variable[128] = {0,};
  310. char value[128] = {0,};
  311. String myCmd = "";
  312.  
  313. buf_len = httpd_req_get_url_query_len(req) + 1;
  314. if (buf_len > 1) {
  315. buf = (char*)malloc(buf_len);
  316.  
  317. if(!buf){
  318. httpd_resp_send_500(req);
  319. return ESP_FAIL;
  320. }
  321. if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
  322. if (httpd_query_key_value(buf, "var", variable, sizeof(variable)) == ESP_OK &&
  323. httpd_query_key_value(buf, "val", value, sizeof(value)) == ESP_OK) {
  324. }
  325. else {
  326. myCmd = String(buf);
  327. }
  328. }
  329. } else {
  330. httpd_resp_send_404(req);
  331. return ESP_FAIL;
  332. }
  333.  
  334. //Serial.println(myCmd);//Serial.print(" ");
  335. if (myCmd=="Revert") { Revert != Revert ; P1 = "";myCmd = "" ; }
  336.  
  337. P1 = myCmd;
  338. // if (myCmd=="Front") { P1 = F; }
  339. // else if (myCmd=="Left") { P1 = L; }
  340. // else if (myCmd=="Right") { P1 = R; }
  341. // else if (myCmd=="U_turn") { P1 = U; }
  342. // else if (myCmd=="R2") { P1 = R2; }
  343. // else if (myCmd=="L2") { P1 = L2; }
  344.  
  345.  
  346.  
  347. const char *resp = Feedback.c_str();
  348. httpd_resp_set_type(req, "text/html"); //設定回傳資料格式
  349. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); //允許跨網域讀取
  350. return httpd_resp_send(req, resp, strlen(resp));
  351.  
  352. }
  353. static esp_err_t stream_handler(httpd_req_t *req){
  354. camera_fb_t * fb = NULL;
  355. esp_err_t res = ESP_OK;
  356. size_t _jpg_buf_len = 0;
  357. uint8_t * _jpg_buf = NULL;
  358. char * part_buf[64];
  359.  
  360. res = httpd_resp_set_type(req, _STREAM_CONTENT_TYPE);
  361. if(res != ESP_OK){
  362. return res;
  363. }
  364.  
  365. httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
  366.  
  367. while(true){
  368. fb = esp_camera_fb_get();
  369. if (!fb) {
  370. Serial.println("Camera capture failed");
  371. res = ESP_FAIL;
  372. } else {
  373. if(fb->format != PIXFORMAT_JPEG){
  374. bool jpeg_converted = frame2jpg(fb, 80, &_jpg_buf, &_jpg_buf_len);
  375. esp_camera_fb_return(fb);
  376. fb = NULL;
  377. if(!jpeg_converted){
  378. Serial.println("JPEG compression failed");
  379. res = ESP_FAIL;
  380. }
  381. } else {
  382. _jpg_buf_len = fb->len;
  383. _jpg_buf = fb->buf;
  384. }
  385. }
  386.  
  387. if(res == ESP_OK){
  388. res = httpd_resp_send_chunk(req, (const char *)_jpg_buf, _jpg_buf_len);
  389. }
  390. if(res == ESP_OK){
  391. res = httpd_resp_send_chunk(req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
  392. }
  393. if(res == ESP_OK){
  394. size_t hlen = snprintf((char *)part_buf, 64, _STREAM_PART, _jpg_buf_len);
  395. res = httpd_resp_send_chunk(req, (const char *)part_buf, hlen);
  396. }
  397. if(fb){
  398. esp_camera_fb_return(fb);
  399. fb = NULL;
  400. _jpg_buf = NULL;
  401. } else if(_jpg_buf){
  402. free(_jpg_buf);
  403. _jpg_buf = NULL;
  404. }
  405. if(res != ESP_OK){
  406. break;
  407. }
  408. }
  409.  
  410. return res;
  411. }
  412.  
  413.  
  414. void startCameraServer(){
  415. httpd_config_t config = HTTPD_DEFAULT_CONFIG(); //可在HTTPD_DEFAULT_CONFIG()中設定Server Port
  416.  
  417. //http://192.168.xxx.xxx/control
  418. httpd_uri_t cmd_uri = {
  419. .uri = "/control",
  420. .method = HTTP_GET,
  421. .handler = cmd_handler,
  422. .user_ctx = NULL
  423. };
  424.  
  425. //http://192.168.xxx.xxx/capture
  426. httpd_uri_t capture_uri = {
  427. .uri = "/capture",
  428. .method = HTTP_GET,
  429. .handler = capture_handler,
  430. .user_ctx = NULL
  431. };
  432.  
  433. //http://192.168.xxx.xxx:81/stream
  434. httpd_uri_t stream_uri = {
  435. .uri = "/stream",
  436. .method = HTTP_GET,
  437. .handler = stream_handler,
  438. .user_ctx = NULL
  439. };
  440.  
  441. Serial.printf("Starting web server on port: '%d'\n", config.server_port); //Server Port
  442. if (httpd_start(&camera_httpd, &config) == ESP_OK) {
  443. httpd_register_uri_handler(camera_httpd, &cmd_uri);
  444. httpd_register_uri_handler(camera_httpd, &capture_uri);
  445. }
  446.  
  447. config.server_port += 1; //Stream Port
  448. config.ctrl_port += 1; //UDP Port
  449. Serial.printf("Starting stream server on port: '%d'\n", config.server_port);
  450. if (httpd_start(&stream_httpd, &config) == ESP_OK) {
  451. httpd_register_uri_handler(stream_httpd, &stream_uri);
  452. }
  453. }
Advertisement
Add Comment
Please, Sign In to add comment