Skip to content

11. Machine design

This week I teammed up with the students in Hong Kong to make a laser pointer for cats that can be controlled via the Internet.

Group assignment

  • actuate and automate your machine
  • document the group project and your individual contribution

What I did this week

  1. prepare HTML code for touch interface
  2. set up and program ESP32-CAM using Arduino IDE
  3. second group meeting
  4. test Arduino code for our project

Research

As my task is about designing the touch interface, I set out to digest as much as I can on websocket protocol and HTML code.

Setting up a websocket

The very first thing I did is watching a tutorial on WebSocket Server Home Automation using ESP32 or NodeMCU board.

Explore HTML code for touch interface

I copied the HTML code from this link to a HTML-visualization interface provided by w3schools.

Adding a button

Changing button appearance

Setting up ESP32 in Arduino IDE

I followed the steps below to install ESP32.

  1. Launch Arduino IDE (mine is version 1.8.1.13).
  2. Click on File menu at the top menu bar.
  3. Select Preferences
  4. On the Settings tab in the Preferences dialog box, look for “Additional Boards Manager URLs”. If there is already text in this box add a coma at the end of it, then follow the next step.
  5. Paste the following link into the text box – https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  6. Click Ok to save.

Install libraries for ESP32

Our code will make use of two libraries - ArduinoWebsockets and ESP32 Async Web Server - which we need to install.

Navigate to Tools > Manage Libraries. In the Library Manager, type ArduinoWebsockets and click Install on the suggested library.

Once done, you will see the words “installed” next to the library’s name.

The other library, ESP32 Async Web Server, is not available to download from the Arduino Library Manager so I first have to download it from this link. After that we can go to Sketch > Include Library > Add .zip Library and select the library that has just been downloaded.

If done successfully, Arduino will inform “Library added to your libraries. Check “include library” menu.”

Next, I selected AI-ESP32 CAM board and the right port, which is COM14 my case, before flashing a blank program.

void setup() {
  // put your setup code here, to run once:

}

void loop() {
  // put your main code here, to run repeatedly:

}

Great news! The program was succesfully uploaded.

Next, I went to Files > Examples and selected WifiScan. The WifiScan sketch will open in a new window.

I started the Serial monitor, selected 115200 Baud rate, and immediately there was an outpouring of wifi networks available on the screen.

Streaming from ESP32-CAM

I went to Files > Examples and selected CameraWebserver. This opened a new sketch.

A couple of changes should be made in this code. Firstly, I uncommented the correct camera model.

The second thing is to change the SSID and password for the wifi network being used.

Having successfully uploaded the sketch, I started the serial monitor and pressed the reset button on the ESP32-CAM. The IP address of the camera is printed on the screen. I copied and pasted it in a new browser window.

At first, there was no response from that IP address. I immediately realized that this is because my computer was on a different Wifi network.

Having made sure that the ESP32-CAM and my laptop connect to the same Wifi, I refreshed the browser, and voila!

To start streaming, click on Start Streaming button, and you should see a live view.

Coding ESP32 for our group project

This is the code written by my teammate in Hong Kong.

#include <ArduinoWebsockets.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include "esp_camera.h"
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"

int index_html_gz_len = 3863;
const uint8_t index_html_gz[] = {
 0x1f ,0x8b ,0x08 ,0x08 ,0x21 ,0x68 ,0x68 ,0x60 ,0x00 ,0xff ,0x69 ,0x6e ,0x64 ,0x65 ,0x78 ,0x2e ,0x68 ,0x74 ,0x6d ,0x6c ,0x2e ,0x67 ,0x7a ,0x00 ,0x95 ,0x58 ,0x7b ,0x6f ,0x1b ,0xb9 ,0x11 ,0xff ,0xdb ,0xfa ,0x14 ,0x3c ,0x19 ,0xcd ,0x4a ,0x8d ,0xb4 ,0x2b ,0x4b ,0xc9 ,0x35 ,0x56 ,0x24 ,0x17 ,0xbd ,0xb3 ,0x81 ,0x04 ,0x48 ,0x70 ,0x41 ,0xed ,0x36 ,0x36 ,0x8a ,0xc2 ,0xa0 ,0x76 ,0x29 ,0x89 ,0x39 ,0x2e ,0xb9 ,0x25 ,0xb9 ,0x7a ,0xf4 ,0xce ,0xdf ,0x3d ,0x33 ,0x5c ,0xee ,0x4b ,0x96 ,0x0d ,0x47 ,0x7f ,0x48 ,0xbb ,0xe4 ,0xfc ,0xe6 ,0xc5 ,0x79 ,0x51 ,0xb3 ,0xb5 ,0x4d ,0xc5 ,0x45 ,0x67 ,0xb6 ,0x66 ,0x34 ,0x81 ,0x9f ,0x94 ,0x59 ,0x4a ,0x24 ,0x4d ,0xd9 ,0x3c ,0xd8 ,0x70 ,0xb6 ,0xcd ,0x94 ,0xb6 ,0x01 ,0x29 ,0x3f ,0xb1 ,0x92 ,0x96 ,0x49 ,0x3b ,0x0f ,0xb6 ,0x3c ,0xb1 ,0xeb ,0x79 ,0xc2 ,0x36 ,0x3c ,0x66 ,0x43 ,0xf7 ,0x32 ,0xa8 ,0x88 ,0xb8 ,0xe4 ,0x96 ,0x53 ,0x31 ,0x34 ,0x31 ,0x15 ,0x6c ,0x7e ,0x16 ,0x8e ,0xea ,0xad ,0xdc ,0x30 ,0xed ,0xd6 ,0xe9 ,0x02 ,0xb6 ,0xa4 ,0x0a ,0x48 ,0x04 ,0x22 ,0x2d ,0xb7 ,0x82 ,0x5d ,0x7c ,0xa1 ,0x92 ,0x50 ,0x99 ,0x90 ,0x1b ,0x2e ,0x2c ,0xb9 ,0xba ,0xfe ,0x32 ,0x19 ,0x0f ,0x7f ,0xfd ,0xc7 ,0xe7 ,0x59 ,0x54 ,0xec ,0x76 ,0x66 ,0xc6 ,0xee ,0xe1 ,0x97 ,0x74 ,0x4e ,0x51 ,0x09 ,0xca ,0x25 ,0xd3 ,0xe4 ,0x8f ,0x8e ,0xe3 ,0xea ,0xe4 ,0x4f ,0xc9 ,0xd9 ,0x68 ,0xf4 ,0x97 ,0xf7 ,0xc5 ,0xca ,0x9a ,0xf1 ,0xd5 ,0xda ,0x4e ,0xc9 ,0x9b ,0xf3 ,0xcd ,0xda ,0x2f ,0x2d ,0x68 ,0xfc ,0xfb ,0x4a ,0xab ,0x5c ,0x26 ,0xc3 ,0x58 ,0x09 ,0xa5 ,0xa7 ,0xe4 ,0x74 ,0x32 ,0x99 ,0xf8 ,0xcd ,0x84 ,0x9b ,0x4c ,0xd0 ,0xfd ,0x94 ,0x2c ,0x05 ,0xdb ,0xf9 ,0x35 ,0x2a ,0xf8 ,0x4a ,0x0e ,0xb9 ,0x65 ,0xa9 ,0x99 ,0x92 ,0x18 ,0xac ,0x66 ,0xda ,0xef ,0x7c ,0xcb ,0x8d ,0xe5 ,0xcb ,0x3d ,0xf0 ,0x71 ,0xde ,0x38 ,0xd8 ,0x55 ,0x1b ,0xa6 ,0x97 ,0x42 ,0x6d ,0xa7 ,0x64 ,0xcd ,0x93 ,0x84 ,0xc9 ,0x52 ,0xbe ,0xd2 ,0x09 ,0x18 ,0xaf ,0x69 ,0xc2 ,0x73 ,0x60 ,0xf8 ,0xb7 ,0xac ,0x94 ,0x63 ,0x55 ,0x1e ,0xaf ,0x87 ,0x34 ,0xb6 ,0x5c ,0xc9 ,0x29 ,0x91 ,0x4a ,0xb2 ,0xf7 ,0x9d ,0x87 ,0xce ,0x29 ,0x0a ,0x7e ,0x6c ,0x60 ,0x85 ,0x2a ,0x2d ,0x6c ,0xae ,0x3d ,0x36 ,0x51 ,0xaf ,0x16 ,0xbd ,0xf1 ,0x9b ,0xb7 ,0x03 ,0x32 ,0x9e ,0xc0 ,0x29 ,0x9c ,0x9f ,0xf7 ,0x5b ,0xca ,0x20 ,0x3a ,0xdb ,0x11 ,0xa3 ,0x04 ,0x4f ,0x90 ,0x94 ,0xf6 ,0xce ,0x26 ,0x3f ,0x0f ,0x48 ,0xfd ,0x15 ,0xbe ,0x6d ,0x03 ,0x2a ,0xed ,0xdf ,0x56 ,0x9e ,0x3e ,0xa6 ,0x7d ,0xe3 ,0xa8 ,0x99 ,0x60 ,0x31 ,0x68 ,0xd9 ,0xb2 ,0x6a ,0x8a ,0xd4 ,0x1b ,0x56 ,0x1a ,0x77 ,0x54 ,0x6b ,0x50 ,0xe5 ,0xe7 ,0x77 ,0xa0 ,0xf6 ,0x19 ,0x7e ,0x8d ,0x41 ,0x77 ,0x08 ,0xa3 ,0x11 ,0x28 ,0x53 ,0xb2 ,0x58 ,0xa3 ,0x97 ,0x4b ,0x0e ,0x71 ,0xae ,0x0d ,0xe2 ,0x32 ,0xc5 ,0x1b ,0xe7 ,0xe0 ,0x55 ,0xf6 ,0xbe ,0x1b ,0x3b ,0x37 ,0x01 ,0x9c ,0x6a ,0x46 ,0x4b ,0x60 ,0xa6 ,0x0c ,0x84 ,0x2a ,0x2a ,0xbe ,0xe4 ,0x3b ,0x96 ,0x78 ,0xa0 ,0x2e ,0x3c ,0x3b ,0xaa ,0x2c ,0xcc ,0xdc ,0xcb ,0x43 ,0xa7 ,0x73 ,0x6a ,0x2c ,0xa0 ,0x53 ,0x77 ,0xf0 ,0x2e ,0x02 ,0x3d ,0x9f ,0x23 ,0xe1 ,0x96 ,0xd1 ,0x24 ,0xe1 ,0x72 ,0x35 ,0x2d ,0xb9 ,0xa4 ,0x54 ,0xaf ,0xb8 ,0x3c ,0x78 ,0x1d ,0x2e ,0x84 ,0x8a ,0x7f ,0x1f ,0x1a ,0x4b ,0xb5 ,0x3d ,0xbe ,0xc5 ,0x64 ,0x72 ,0xb8 ,0xc1 ,0xa5 ,0x00 ,0xd1 ,0xc7 ,0x41 ,0x7e ,0xcf ,0xa1 ,0x08 ,0x5a ,0x7b ,0xa8 ,0x30 ,0xe1 ,0xe9 ,0xca ,0x2b ,0x5d ,0xc6 ,0xbc ,0x13 ,0x54 ,0xb1 ,0xd9 ,0x79 ,0x87 ,0x35 ,0x92 ,0x29 ,0x05 ,0xc6 ,0xde ,0xc2 ,0x66 ,0x3e ,0xb5 ,0x22 ,0xe2 ,0x4d ,0x15 ,0x84 ,0x5e ,0x13 ,0xf4 ,0xda ,0x3b ,0x08 ,0x2e ,0x74 ,0xdb ,0x2c ,0x2a ,0x72 ,0x17 ,0x1e ,0x7c ,0x91 ,0x59 ,0xa8 ,0x64 ,0x0f ,0x3f ,0x5c ,0x66 ,0xb9 ,0x25 ,0x76 ,0x9f ,0x41 ,0xb1 ,0xb1 ,0x6c ,0x07 ,0x16 ,0x31 ,0x1a ,0x10 ,0x9e ,0xcc ,0x83 ,0xe2 ,0x09 ,0x54 ,0xc4 ,0x42 ,0x91 ,0xb8 ,0x2a ,0x91 ,0xf0 ,0x8d ,0xdb ,0x52 ,0x39 ,0x9c ,0xf1 ,0xaf ,0xa5 ,0x41 ,0xc1 ,0x05 ,0x88 ,0xad ,0xf6 ,0x2a ,0x3b ,0xdd ,0x72 ,0x63 ,0x03 ,0x83 ,0x26 ,0xb8 ,0x20 ,0xb3 ,0x08 ,0x16 ,0x1c ,0xa2 ,0x7a ,0xf0 ,0x14 ,0xdd ,0x43 ,0x4f ,0x75 ,0x49 ,0x2c ,0xa8 ,0x31 ,0xf3 ,0x2e ,0x4f ,0xe9 ,0x8a ,0x35 ,0xd6 ,0x1d ,0xe7 ,0x19 ,0xf8 ,0xb1 ,0x01 ,0xeb ,0x12 ,0xa3 ,0xe3 ,0x79 ,0xd7 ,0xed ,0x79 ,0xd6 ,0xe5 ,0x8f ,0x89 ,0x35 ,0xcf ,0xec ,0x45 ,0x07 ,0x18 ,0x18 ,0x4b ,0xb0 ,0xa4 ,0x92 ,0x39 ,0x49 ,0x54 ,0x9c ,0xa7 ,0x50 ,0x34 ,0xc2 ,0x15 ,0xb3 ,0x57 ,0x82 ,0xe1 ,0xe3 ,0x2f ,0xfb ,0x8f ,0x49 ,0x2f ,0x28 ,0xd8 ,0x05 ,0x10 ,0xe9 ,0x05 ,0xfd ,0xd7 ,0xeb ,0xfb ,0x7f ,0xfd ,0xf3 ,0x13 ,0x20 ,0xba ,0x5b ,0x33 ,0x8d ,0xa2 ,0x2e ,0x79 ,0x0d ,0xc5 ,0x40 ,0x26 ,0x6a ,0x1b ,0xc2 ,0xa9 ,0x51 ,0x8c ,0xdd ,0x70 ,0xad ,0x80 ,0xee ,0x35 ,0xe9 ,0x4e ,0xdf ,0x8d ,0xbb ,0x25 ,0x6c ,0x6b ,0x00 ,0x22 ,0x41 ,0xd4 ,0x57 ,0xb6 ,0xb8 ,0x86 ,0xe3 ,0x65 ,0xb6 ,0x57 ,0x70 ,0x02 ,0xc6 ,0x27 ,0x27 ,0x9d ,0xad ,0x09 ,0x95 ,0x4c ,0x99 ,0x31 ,0x60 ,0x19 ,0x10 ,0x56 ,0x4f ,0x17 ,0x90 ,0x18 ,0x27 ,0x7c ,0x49 ,0x7a ,0x7e ,0x25 ,0x4c ,0x28 ,0x34 ,0x03 ,0x0e ,0x1c ,0xa9 ,0x8c ,0x99 ,0x5a ,0x92 ,0x5f ,0x84 ,0x5a ,0xf4 ,0x91 ,0x88 ,0x90 ,0x0d ,0xd5 ,0x24 ,0xd7 ,0xe2 ,0xb7 ,0xc5 ,0x37 ,0xc8 ,0x70 ,0x60 ,0x02 ,0xcc ,0xc3 ,0x18 ,0x94 ,0xb7 ,0xac ,0x58 ,0x82 ,0xf7 ,0x16 ,0x1b ,0x94 ,0x0c ,0x28 ,0xb0 ,0x3f ,0x04 ,0x5f ,0x01 ,0xa0 ,0x02 ,0xc3 ,0xc6 ,0x43 ,0xe7 ,0xe1 ,0x7d ,0xa7 ,0x83 ,0x2c ,0x13 ,0x4d ,0x57 ,0x1f ,0xb1 ,0xf4 ,0x35 ,0x9c ,0xf4 ,0xbf ,0x9c ,0xe9 ,0xfd ,0xb5 ,0x2b ,0x25 ,0x4a ,0xf7 ,0x02 ,0x57 ,0x01 ,0xd0 ,0x45 ,0x48 ,0x5f ,0x47 ,0xf6 ,0x33 ,0x80 ,0x3a ,0x2c ,0x0e ,0x51 ,0x5f ,0x31 ,0xd8 ,0x01 ,0x5a ,0x2d ,0x84 ,0x6a ,0xb9 ,0x34 ,0xcc ,0xba ,0xf5 ,0x03 ,0xda ,0x0f ,0x2e ,0x07 ,0x8e ,0x10 ,0x17 ,0x1b ,0x05 ,0x35 ,0x64 ,0xd0 ,0x25 ,0x98 ,0xf0 ,0x41 ,0x69 ,0xfe ,0x7f ,0x24 ,0x13 ,0x4d ,0xfa ,0x42 ,0x5a ,0x44 ,0xc6 ,0x2d ,0xda ,0x7f ,0x33 ,0x6d ,0x39 ,0xf4 ,0xc4 ,0x26 ,0xa5 ,0x97 ,0xe5 ,0x48 ,0x9f ,0x0c ,0x16 ,0x97 ,0x24 ,0xfd ,0x70 ,0x43 ,0x45 ,0x8e ,0xc7 ,0x58 ,0x34 ,0xe5 ,0x29 ,0x09 ,0x20 ,0x1a ,0x1e ,0xab ,0xf1 ,0x1a ,0xd6 ,0xcb ,0x3a ,0xd5 ,0xa0 ,0x28 ,0x85 ,0x17 ,0x1a ,0xf9 ,0xca ,0x3c ,0x27 ,0x4b ,0x2a ,0x0c ,0x54 ,0x6c ,0x67 ,0x7f ,0xae ,0x35 ,0x88 ,0xbc ,0x6d ,0xbd ,0xdd ,0x15 ,0x6f ,0xbe ,0xd5 ,0xfb ,0x3d ,0xff ,0xe6 ,0xf7 ,0x76 ,0xbf ,0x39 ,0xe7 ,0x00 ,0x33 ,0x28 ,0x52 ,0xb8 ,0xb0 ,0x3f ,0x5c ,0x80 ,0xfc ,0xb2 ,0x37 ,0x90 ,0xf6 ,0x03 ,0xf7 ,0x74 ,0x0d ,0x55 ,0x6b ,0x40 ,0x0c ,0x7c ,0xdf ,0xf0 ,0x94 ,0x41 ,0x96 ,0xbb ,0x60 ,0xf6 ,0x8e ,0x86 ,0x6a ,0x7a ,0xb5 ,0x01 ,0xb9 ,0x9f ,0xb8 ,0x81 ,0x96 ,0xcb ,0xe0 ,0x50 ,0x5d ,0xe3 ,0x71 ,0x45 ,0x30 ,0x18 ,0xb8 ,0xa8 ,0xb9 ,0xc6 ,0xe7 ,0x41 ,0xa1 ,0x79 ,0x91 ,0x3f ,0xcf ,0x63 ,0x41 ,0x90 ,0x47 ,0x5e ,0xa1 ,0xe0 ,0x17 ,0xe3 ,0x52 ,0x68 ,0x3d ,0x1e ,0xf8 ,0x32 ,0x54 ,0xaa ,0xa0 ,0x17 ,0x42 ,0xca ,0xca ,0x1f ,0x57 ,0xd4 ,0x41 ,0xf3 ,0xec ,0x47 ,0xf5 ,0x74 ,0xb0 ,0xa3 ,0x7a ,0x76 ,0x96 ,0xb9 ,0x74 ,0xbd ,0xba ,0xd6 ,0xa4 ,0xc7 ,0x30 ,0xa3 ,0xdd ,0xe0 ,0x06 ,0x99 ,0xcf ,0x42 ,0x2c ,0xc7 ,0x64 ,0x3e ,0x87 ,0x78 ,0x6a ,0xb8 ,0xb8 ,0x24 ,0x69 ,0xcc ,0x77 ,0xb7 ,0x70 ,0x90 ,0x40 ,0xed ,0x5c ,0x69 ,0xfe ,0x33 ,0xfa ,0x6f ,0x18 ,0x0b ,0x8e ,0x71 ,0x42 ,0x86 ,0xe5 ,0xd1 ,0xfb ,0x8e ,0x50 ,0x43 ,0xee ,0x8e ,0x43 ,0xee ,0x00 ,0xe2 ,0x83 ,0xa3 ,0x80 ,0x3c ,0x10 ,0x06 ,0xea ,0x3e ,0x25 ,0xf2 ,0xa5 ,0x72 ,0x9e ,0x62 ,0xde ,0xb4 ,0x15 ,0x9a ,0x15 ,0x46 ,0x24 ,0x58 ,0x5b ,0x16 ,0x9e ,0xa6 ,0xa5 ,0x55 ,0x3a ,0x58 ,0x9d ,0x97 ,0x73 ,0x0d ,0x7c ,0x30 ,0x46 ,0x7b ,0xc1 ,0xf0 ,0xfc ,0xfc ,0x7c ,0x80 ,0x5f ,0x50 ,0x54 ,0x88 ,0xe7 ,0x0c ,0xcd ,0xae ,0xe5 ,0x60 ,0x38 ,0xb1 ,0x86 ,0x7b ,0x6b ,0x23 ,0xea ,0x9c ,0x3a ,0xd0 ,0xba ,0x4e ,0xaf ,0x96 ,0x7c ,0x9f ,0x8e ,0xb5 ,0x70 ,0x94 ,0x5d ,0x8a ,0x3e ,0x14 ,0xda ,0x3e ,0xd0 ,0x82 ,0x47 ,0xd3 ,0x2a ,0x16 ,0x66 ,0x9a ,0x61 ,0xc0 ,0x5c ,0xb2 ,0x25 ,0xcd ,0x85 ,0xed ,0x95 ,0x43 ,0xde ,0x53 ,0x21 ,0xe0 ,0x22 ,0xa9 ,0xc9 ,0xc1 ,0x0f ,0x5d ,0xce ,0x84 ,0xa7 ,0xa3 ,0xa0 ,0x2e ,0x0e ,0x47 ,0x70 ,0xcf ,0x84 ,0x42 ,0x5d ,0x46 ,0x4a ,0xcc ,0xa3 ,0x78 ,0x78 ,0xa4 ,0xc0 ,0x0f ,0x49 ,0x7d ,0x56 ,0x54 ,0xf5 ,0x54 ,0xd7 ,0xaf ,0xf6 ,0x69 ,0xe1 ,0xa7 ,0x2e ,0x65 ,0xed ,0x03 ,0x2b ,0x5d ,0xf8 ,0x99 ,0xda ,0x75 ,0x48 ,0x17 ,0xa6 ,0x57 ,0x6e ,0xf7 ,0xc9 ,0xec ,0x51 ,0xb9 ,0x7f ,0xf5 ,0x8a ,0x1c ,0xd2 ,0xdd ,0x36 ,0xe8 ,0xea ,0xda ,0x7d ,0xe8 ,0x7a ,0x90 ,0x7c ,0xa3 ,0xa9 ,0x34 ,0x02 ,0x9a ,0x6d ,0x85 ,0x1c ,0x54 ,0xaa ,0x14 ,0x39 ,0xef ,0x62 ,0xf9 ,0x98 ,0x5d ,0x2f ,0x6e ,0x27 ,0xb7 ,0x45 ,0xa3 ,0xa8 ,0xfc ,0x8c ,0x1d ,0xe4 ,0xae ,0xb5 ,0xe6 ,0xad ,0x2e ,0x78 ,0xe3 ,0x11 ,0xfd ,0xd1 ,0xa9 ,0x13 ,0x21 ,0x8a ,0x88 ,0xe0 ,0x29 ,0xb7 ,0x2e ,0x62 ,0x61 ,0x14 ,0x86 ,0x41 ,0x9a ,0xc0 ,0x35 ,0xa0 ,0x9a ,0x36 ,0x20 ,0x04 ,0xf5 ,0x9e ,0x4c ,0x46 ,0x24 ,0x35 ,0x48 ,0xbb ,0xb6 ,0x36 ,0xc3 ,0x11 ,0x67 ,0xc5 ,0xed ,0x3a ,0x5f ,0x84 ,0xb1 ,0x4a ,0x23 ,0xc9 ,0x94 ,0xe4 ,0x50 ,0xca ,0x22 ,0xb8 ,0x4d ,0x7d ,0x33 ,0xf7 ,0xcc ,0x64 ,0x93 ,0xf1 ,0x3d ,0xdb ,0xd1 ,0x34 ,0x13 ,0xcc ,0x44 ,0x30 ,0xb7 ,0x2e ,0xa2 ,0x14 ,0x1a ,0x07 ,0xd3 ,0x15 ,0xe5 ,0x3d ,0x08 ,0x88 ,0x62 ,0x26 ,0x44 ,0xb6 ,0x86 ,0xa7 ,0x7b ,0xac ,0x91 ,0x5a ,0x09 ,0x98 ,0x20 ,0xef ,0x75 ,0x7c ,0x1f ,0x53 ,0x1d ,0x6d ,0xb7 ,0xdb ,0x08 ,0xe6 ,0x27 ,0xb6 ,0x0b ,0xf1 ,0xd6 ,0x5b ,0xe7 ,0x8d ,0xcb ,0x2a ,0xbb ,0xb3 ,0xa5 ,0xab ,0xb1 ,0x3d ,0x49 ,0x85 ,0xa3 ,0x1a ,0x4e ,0x51 ,0x97 ,0xe8 ,0xe8 ,0x3e ,0x3a ,0x0c ,0x5b ,0x53 ,0x99 ,0x2f ,0x7c ,0xd9 ,0x2b ,0xfb ,0x96 ,0x4b ,0x16 ,0xb8 ,0xc1 ,0xb0 ,0x25 ,0x54 ,0xe4 ,0x84 ,0xfc ,0xf9 ,0xa7 ,0x03 ,0x0f ,0xab ,0xbe ,0x46 ,0x2e ,0xe6 ,0x60 ,0x69 ,0xf3 ,0x1c ,0x2d ,0xd8 ,0xde ,0x3e ,0x55 ,0x18 ,0xca ,0x2a ,0x2d ,0xda ,0xc1 ,0x5b ,0x4b ,0x79 ,0x46 ,0x9b ,0xf2 ,0xa3 ,0x99 ,0xcd ,0x75 ,0x79 ,0xe9 ,0x74 ,0xb9 ,0x03 ,0x73 ,0x62 ,0xbc ,0xae ,0x8b ,0x42 ,0xe3 ,0x2e ,0x0f ,0x37 ,0x3f ,0x06 ,0x83 ,0x24 ,0x56 ,0x8c ,0xc3 ,0x48 ,0x29 ,0xbe ,0xcb ,0x0e ,0x8d ,0x25 ,0x70 ,0xe7 ,0xeb ,0x27 ,0x98 ,0xfd ,0x53 ,0xa3 ,0x4b ,0x37 ,0xd9 ,0xba ,0xa1 ,0x06 ,0x47 ,0xcf ,0x4a ,0xe3 ,0x9f ,0x5a ,0x7e ,0xf9 ,0x3b ,0x1e ,0xf7 ,0x90 ,0xf4 ,0xda ,0xce ,0xe9 ,0x93 ,0x29 ,0xac ,0x37 ,0x13 ,0xa8 ,0x07 ,0x4c ,0x66 ,0x64 ,0xd4 ,0x6f ,0xe9 ,0xeb ,0x18 ,0x37 ,0xc8 ,0x1a ,0x3a ,0xc0 ,0x06 ,0xe6 ,0x44 ,0xf1 ,0xd2 ,0xeb ,0xf5 ,0x8b ,0x49 ,0xb6 ,0x9d ,0x32 ,0x4d ,0x62 ,0x99 ,0x0b ,0x18 ,0x78 ,0x0e ,0xf7 ,0xdd ,0x69 ,0xa2 ,0xb5 ,0x4d ,0x67 ,0x0c ,0x40 ,0xae ,0x7f ,0x6f ,0x97 ,0xf7 ,0x56 ,0x12 ,0xee ,0xbe ,0x28 ,0x33 ,0x20 ,0x7b ,0xf7 ,0xcd ,0xaa ,0x7c ,0x65 ,0x22 ,0x74 ,0x17 ,0x9f ,0xd0 ,0x22 ,0xe1 ,0x52 ,0x69 ,0x9c ,0x6a ,0x03 ,0xf7 ,0x82 ,0xa8 ,0x09 ,0xe4 ,0x1c ,0xe4 ,0x12 ,0x62 ,0x31 ,0xb7 ,0xb2 ,0xdd ,0xc0 ,0xe5 ,0x16 ,0x72 ,0x29 ,0xdf ,0x47 ,0xfd ,0xa0 ,0x90 ,0x8d ,0x9e ,0xcd ,0xa8 ,0xbc ,0x64 ,0x2b ,0xcd ,0x18 ,0x3a ,0xc2 ,0xa1 ,0xfe ,0x4a ,0xce ,0x47 ,0x30 ,0x23 ,0x3e ,0x2a ,0x18 ,0x35 ,0xc6 ,0xc2 ,0x9f ,0x29 ,0x35 ,0xc8 ,0xb1 ,0x6e ,0x83 ,0xea ,0xf9 ,0xef ,0xc4 ,0xf9 ,0xa0 ,0x21 ,0x04 ,0x74 ,0x18 ,0xa0 ,0x42 ,0x0d ,0x1e ,0xee ,0x06 ,0x0e ,0xd7 ,0x39 ,0x7f ,0xa7 ,0x99 ,0x45 ,0xfe ,0x22 ,0x17 ,0xb9 ,0xff ,0x90 ,0xbe ,0x03 ,0x97 ,0x76 ,0xc7 ,0xd7 ,0x4a ,0x12 ,0x00 ,0x00
 };

const char* ssid = "CMY";
const char* password = "22222222";

#define PWDN_GPIO_NUM     32
#define RESET_GPIO_NUM    -1
#define XCLK_GPIO_NUM      0
#define SIOD_GPIO_NUM     26
#define SIOC_GPIO_NUM     27
#define Y9_GPIO_NUM       35
#define Y8_GPIO_NUM       34
#define Y7_GPIO_NUM       39
#define Y6_GPIO_NUM       36
#define Y5_GPIO_NUM       21
#define Y4_GPIO_NUM       19
#define Y3_GPIO_NUM       18
#define Y2_GPIO_NUM        5
#define VSYNC_GPIO_NUM    25
#define HREF_GPIO_NUM     23
#define PCLK_GPIO_NUM     22

camera_fb_t * fb = NULL;

using namespace websockets;
WebsocketsServer WSserver;
AsyncWebServer webserver(80);

// Arduino like analogWrite
// value has to be between 0 and valueMax
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 180) {
  // calculate duty, 8191 from 2 ^ 13 - 1
  uint32_t duty = (8191 / valueMax) * min(value, valueMax);
  ledcWrite(channel, duty);
}

void setup() {
  WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
  Serial.begin(115200);
  // Ai-Thinker: pins 2 and 12
  ledcSetup(2, 50, 16); //channel, freq, resolution
  ledcAttachPin(2, 2); // pin, channel
  ledcSetup(4, 50, 16);
  ledcAttachPin(4, 4);
  pinMode(12, OUTPUT);
  camera_config_t config;
  config.ledc_channel = LEDC_CHANNEL_0;
  config.ledc_timer = LEDC_TIMER_0;
  config.pin_d0 = Y2_GPIO_NUM;
  config.pin_d1 = Y3_GPIO_NUM;
  config.pin_d2 = Y4_GPIO_NUM;
  config.pin_d3 = Y5_GPIO_NUM;
  config.pin_d4 = Y6_GPIO_NUM;
  config.pin_d5 = Y7_GPIO_NUM;
  config.pin_d6 = Y8_GPIO_NUM;
  config.pin_d7 = Y9_GPIO_NUM;
  config.pin_xclk = XCLK_GPIO_NUM;
  config.pin_pclk = PCLK_GPIO_NUM;
  config.pin_vsync = VSYNC_GPIO_NUM;
  config.pin_href = HREF_GPIO_NUM;
  config.pin_sscb_sda = SIOD_GPIO_NUM;
  config.pin_sscb_scl = SIOC_GPIO_NUM;
  config.pin_pwdn = PWDN_GPIO_NUM;
  config.pin_reset = RESET_GPIO_NUM;
  config.xclk_freq_hz = 20000000;
  config.pixel_format = PIXFORMAT_JPEG;
  //init with high specs to pre-allocate larger buffers
  if (psramFound()) {
    config.frame_size = FRAMESIZE_UXGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 12;
    config.fb_count = 1;
  }

  // camera init
  esp_err_t err = esp_camera_init(&config);
  if (err != ESP_OK) {
    Serial.printf("Camera init failed with error 0x%x", err);
    return;
  }

  sensor_t * s = esp_camera_sensor_get();
  s->set_framesize(s, FRAMESIZE_QVGA);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.print("Connected to ");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());

  webserver.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
    AsyncWebServerResponse *response = request->beginResponse_P(200, "text/html", index_html_gz, sizeof(index_html_gz));
    response->addHeader("Content-Encoding", "gzip");
    request->send(response);
  });

  webserver.begin();
  WSserver.listen(82);
}


void handle_message(WebsocketsMessage msg) {
  int commaIndex = msg.data().indexOf(',');
  int panValue = msg.data().substring(0, commaIndex).toInt();
  int tiltValue = msg.data().substring(commaIndex + 1).toInt();

  if (panValue > 900 || panValue < -900)
  {
    panValue > 900 ? digitalWrite(12, LOW) : digitalWrite(12, HIGH);
  }

  else
  {
    panValue = map(panValue, -90, 90, 0, 180); // 0-180
    tiltValue = map(tiltValue, -90, 90, 180, 0); // 0-180 reversed

    ledcAnalogWrite(2, panValue); // channel, value
    ledcAnalogWrite(4, tiltValue);
  }
}

//Drawing Circle used subfunction convert to moter coordinate
int convert2motor(int orgCo)
{
    int temp;
    temp = orgCo / 10 + 90;
    return temp;
}

//Drawing part of Circle, divid a cirlce into 4 zones
void partOfCircle(int degStart, int degEnd) {
  int deg;
  int  x;
  int  y;
  int r=300;
  double pi = 3.14;

  for (deg = degStart; deg < degEnd; ++deg)
  {
    x = convert2motor(r *cos(deg*pi/180));
    y = convert2motor(r *sin(deg*pi/180));
    printf ("%c , %c \n", x, y);
    //cout << x << "," << y << endl;

  }
}

//Drawing whole circle
void Circle()
{
    int circleIndex = msg.data().indexOf('circle:');
    int circleClick = msg.data().substring(0, circleIndex+1).toInt();

    // If circleClick == 1, start to draw circle
    if (circleClick ==1)
    {
      //cout << "draw zone 1" << endl;
      partOfCircle(1,90); //zone 1

      //cout << "draw zone 2" << endl;
      partOfCircle(91,180); //zone 2

      //cout << "draw zone 3"<<  endl;
      partOfCircle(181,270); //zone 3

      //cout << "draw zone 4"<<  endl;
      partOfCircle(270,360); //zone 4
    }

  }

}



void loop() {
  auto client = WSserver.accept();
  client.onMessage(handle_message);
  Circle();
  while (client.available()) {
    client.poll();
    fb = esp_camera_fb_get();
    client.sendBinary((const char *)fb->buf, fb->len);
    esp_camera_fb_return(fb);
    fb = NULL;
  }
}

Last update: June 6, 2021