Skip to content

10. Mechanical Design, Machine Design

This week task as below:

  • Individual assignment:

Document your individual contribution.

My duty is about writing the programming for INO and part of website scripting programming.

Preparation job before ESP 32 programming

This is my second time for using C to programming the code in ardunio IDE.

Step 1:

Since our project need connecting to the network, including necessary library are needed.

In Arduino IDE, sketch \ include library \ manage library.

Step 2:

For the library ESPAsyncWebServer, I need to obtain the library in Github and download the library.

Step 3:

In Arduino IDE, I could also include library in ZIP format. sketch \ include library \ Add a zip library.

Step 4:

For the library AsyncTCP, I need to obtain the library in Github and download the library.

Step 5:

In File \ Preferences.

A suitable additional boards managers urls are also needed.

Step 6:

In Library manager, a ArduinoWebSockets are needed to be installed.

Step 7:

In Library manager, a esp32 are needed to be installed.

Step 8:

After including and installing suitable library.

A board - ESP32 Wrover module is needed for this project.

Step 9: Partition scheme : huge app(3MB No OTA/1MB SPIFFS) is needed

Step 10:

I need to ensure all tools are set correctly.

Message prototype between front end and back end

In order to communcate between front end and back end.

There are 4 types of messages are used.

Message 1: - When the user is draging the yellow button in the website, it is used for controling the laser pointer pointing location.

A + pan value + tilevalue

For example:

A120,130

Message 2: - Start to turn on the laser pointer for drawing a circle

There is only 1 character :

B

Message 3: - Turn on the Laser pointer

There is only 1 character :

C

Message 4: - Turn off the Laser pointer

There is only 1 character :

D

By using the above four message, it is enough to notify the back end (ino ardunio program) to behave expected results.

front end - webpage. Using javascript and html

Please click here to download the html file

Here is the complete html file.

<html>
<head>
<meta name='viewport'         content='width=device-width,         initial-scale=1.0,         user-scalable=no' />
<title>Pan and Tilt ESP32-CAM</title>
<style> 
#container {
     width: 100%;
     height: 49vh;
     background-color: #333;
     display: flex;
     align-items: center;
     justify-content: center;
     overflow: hidden;
     border-radius: 7px;
     touch-action: none;
}
#item {
     width: 100px;
     height: 100px;
     background-color: rgb(245, 230, 99);
     border: 10px solid rgba(136, 136, 136, .5);
     border-radius: 50%;
     touch-action: none;
     user-select: none;
}
#item:active {
     background-color: rgba(168, 218, 220, 1.00);
}
#item:hover {
     cursor: pointer;
     border-width: 20px;
}
#area {
     position: fixed;
     right: 0;
     top: 0;
}

#stream-container{
     height: 49vh;
     padding:0;
     margin:0;
     margin-block-start:0;
     margin-block-end:0;
     margin-inline-start:0;
     margin-inline-end:0 
}
#stream-container img{
     display:block;
     max-width:100%;
     min-height:49vh;
     border-radius:4px;
     margin-top:8px 
}

</style>
</head>
<body>



 <!-- This adds a blank and 2 buttons below drag fields
Reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/button -->  
<p></p>


<form>
<input type="button"  onclick="drawCircleFunction()" value="Drawing Circle control" id="activate">
</form>
<p>Drag the circle below.</p>



<input type='textarea' id='area' disabled />
<div id='outerContainer'>
  <div id='container'>
    <div id='item'> </div>
  </div>
  <div id="stream-container" class="image-container">
   <img id="stream" src="">
  </div>
</div>
<script>
const view = document.getElementById('stream');
const WS_URL = "ws://" + window.location.host + ":82";
const ws = new WebSocket(WS_URL);

ws.onmessage = message => {
    if (message.data instanceof Blob) {
      var urlObject = URL.createObjectURL(message.data);
      view.src = urlObject;
    }
};

var dragItem = document.querySelector('#item');
var container = document.querySelector('#container');
var containerWidth = container.offsetWidth;
var containerHeight = container.offsetHeight;
var maxDragHorizontal = containerWidth / 2;
var maxDragVertical = containerHeight / 2;
document.getElementById('area').value = 'width: ' + maxDragHorizontal + ' height: ' + maxDragVertical;
var active = false;
var currentX;
var currentY;
var initialX;
var initialY;
var xOffset = 0;
var yOffset = 0;
var lastText, lastSend, sendTimeout;
container.addEventListener('touchstart', dragStart, false);
container.addEventListener('touchend', dragEnd, false);
container.addEventListener('touchmove', drag, false);
container.addEventListener('mousedown', dragStart, false);
container.addEventListener('mouseup', dragEnd, false);
container.addEventListener('mousemove', drag, false);

function dragStart(e) {
    if (e.type === 'touchstart') {
        initialX = e.touches[0].clientX - xOffset;
        initialY = e.touches[0].clientY - yOffset;
    } else {
        initialX = e.clientX - xOffset;
        initialY = e.clientY - yOffset;
    }
    if (e.target === dragItem) {
        active = true;
        send('C'); //on laser
    }
}

function dragEnd(e) {
    initialX = currentX;
    initialY = currentY;
    active = false;
    send('D'); //off laser
}

function drag(e) {
    if (active) {
        e.preventDefault();
        if (e.type === 'touchmove') {
            currentX = e.touches[0].clientX - initialX;
            currentY = e.touches[0].clientY - initialY;
        } else {
            currentX = e.clientX - initialX;
            currentY = e.clientY - initialY;
        }
        xOffset = currentX;
        yOffset = currentY;
        if (Math.abs(currentY) < maxDragVertical && Math.abs(currentX) < maxDragHorizontal) {
            setTranslate(currentX, currentY, dragItem);
        }
        document.getElementById('area').value = 'X: ' + currentX + ' Y: ' + currentY;
    }
    else{

    }
}

// limit sending to one message every 30 ms
// https://github.com/neonious/lowjs_esp32_examples/blob/master/neonious_one/cellphone_controlled_rc_car/www/index.html
function send(txt) {
    var now = new Date().getTime();
    if(lastSend === undefined || now - lastSend >= 30) {
        try {
            ws.send(txt);
            lastSend = new Date().getTime();
            return;
        } catch(e) {
            console.log(e);
        }
    }
    lastText = txt;
    if(!sendTimeout) {
        var ms = lastSend !== undefined ? 30 - (now - lastSend) : 30;
        if(ms < 0)
            ms = 0;
        sendTimeout = setTimeout(() => {
            sendTimeout = null;
            send(lastText);
        }, ms);
    }
}

function setTranslate(xPos, yPos, el) {
    el.style.transform = 'translate3d(' + xPos + 'px, ' + yPos + 'px, 0)';
    var panDegrees = xPos * 90 / maxDragHorizontal;
    var tiltDegrees = yPos * 90 / maxDragVertical;
    send('A' + panDegrees + ',' + tiltDegrees);
}


function drawCircleFunction()
{
    send('B');

}



</script>
</body>
</html>

back end - ino file . Using C for programing

Please click here to download the ino file

Here is the complete ino file.

#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;

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

 };

//const char* ssid = "CMA_WiFi_Egg_03";
const char* ssid = "fablab";
const char* password = "27796851";

//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(8888);
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 1, Laserpointer: pin 12
  ledcSetup(2, 50, 16); //channel, freq, resolution
  ledcAttachPin(2, 2); // pin, channel
  ledcSetup(4, 50, 16);
  ledcAttachPin(4, 1);
  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);
}




//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=100;
  double pi = 3.14;

  for (deg = degStart; deg < degEnd; ++deg)
  {
    x = convert2motor(r *cos(deg*pi/180));
    y = convert2motor(r *sin(deg*pi/180));
    Serial.print ( x);
    Serial.print ( ",");
    Serial.println ( y);


    ledcAnalogWrite(2, x); // channel, value
    ledcAnalogWrite(4, y);
      // wait for the servo to get there
  delay(10);
  }
}

//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 handle_message(WebsocketsMessage msg) {
  int commaIndex = msg.data().indexOf(',');
      int panValue = msg.data().substring(1, commaIndex).toInt();
      int tiltValue = msg.data().substring(commaIndex + 1).toInt();

  Serial.println ("Start to handle message");
    Serial.println (msg.data()[0]);
   Serial.println ("check panDegrees and tiltdegree: "+msg.data());
  char msgHead = msg.data()[0];

 /* if (panValue == 999 || panValue === -999)
  {
    panValue > 900 ? digitalWrite(12, LOW) : digitalWrite(12, HIGH);
  }*/
  //C is on laser
  if (msgHead=='C')
  {
    Serial.println ("msgHead==C");
    Serial.println ("On laser");
    digitalWrite(12, LOW);

    }
    //D is off laser
  else if (msgHead=='D')
  {
    Serial.println ("msgHead==D");
    Serial.println ("Off laser");
    digitalWrite(12, HIGH);

  }
   else if ( msgHead=='A')
    {
      Serial.println ("Start to move laser pointer manually");
    Serial.println ("before mapping panDegrees: "+panValue);
        Serial.println ("before mapping tiltValue: "+tiltValue);
      panValue = map(panValue, -90, 90, 0, 180); // 0-180
      tiltValue = map(tiltValue, -90, 90, 180, 0); // 0-180 reversed
      Serial.println ("after mapping panDegrees: "+panValue);
        Serial.println ("after mapping tiltValue: "+tiltValue);
      ledcAnalogWrite(2, panValue); // channel, value
      ledcAnalogWrite(4, tiltValue);
    }

    else if ( msgHead=='B')
    {
      Serial.println ("Start to draw circle");
      Serial.println ("On laser");
      digitalWrite(12, LOW);
      Circle();
      Serial.println ("Off laser");
      digitalWrite(12, HIGH);
      Serial.println ("Finish to draw circle");
    }

}


void loop() {
/*
  Serial.print("start to draw");
  Circle();
  Serial.print("end to draw");
*/

  auto client = WSserver.accept();
  client.onMessage(handle_message);
  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;
  }

}

}

Feature 1: controling laser pointer to draw a circle - from front end (html) to back end (ino)

Step 1:

Below is the html code and display appearance in browser.

It is the feature that is used for start up the drawing circle feature.

Please be remined that there is a onlick=”drawCircleFunction”.

For the demostration, please read the website from my groupmates. I only mainly explain on how the code and html.

Step 2:

After the user clicking the onclick javascript, a message ‘B’ will be sent to backend.

Step 3:

In the ino file, the below code is used to handle message B.

If message “B” is found, it will turn on laser pointer by set low into pin12.

It will then start up the run circle function. It is used to draw a circle by using laser pointer.

After circle function is completed, setting high into pin 12 in order to turn off laser pointer.

Step 4:

There are three functions used to draw circle.

The first function is Circle().

It is used to divied the circle into four parts.

They are zone 1, 2, 3 and 4.

It will continue to draw zone by zone.

However, later , I have found that there is no needed to divide circles into four parts.

It is because sin and cos function will correctly calculate netgative value for zone 2-4.

In partOfCircle function.

By using radius, sin and cos function, it will calculate the accurate x and y coordination.

In convert2moter function.

Since the moter vibrating degree is only between 60 degree to 120 degree. I need to convert the x,y coordination into suitable moter degree.

Finally, the program will loop for totally 360 times that is 360 degress. therefore a whole drawing circle is complete.

For each point, x and y value will be set into pin 2 and 4 for displaying laser point on the floor.

Please be reminded that my groupmate will do the demostration .

Feature 2: By drawing the location in website, control laser pointer location - from front end (html) to back end (ino)

Step 1:

In the html, function dragstart, dragend and draw javascript functions are used.

Step 2:

At first, user will hold the location in website, it will call drawStart.

message ‘C’ will be send to backend.

the below is the C program in ino. after receiving message C, setting low into pin 12 to turn on laser pointer.

Step 3:

Then, user will move finger around in the website.

x and y location will be moved.

Message “A” with coordination will be sent to backend.

Step 4:

After message A is received, program will adjust the x, y coordination to match the motor rotation angle.

Suitable rotation angle will be set to pin 2 and 4 respectivitly.

Step 5:

Finally, user will leave their finger from website, message D will be sent to backend.

The program will set high into pin 12 in order to turn off laser pointer.


Last update: April 6, 2021