mirror of
https://github.com/SasaKaranovic/winfidel-sensor.git
synced 2026-07-08 17:52:35 +02:00
Initial commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
github: [SasaKaranovic]
|
||||
custom: [https://shop.sasakaranovic.com]
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
# Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Linker output
|
||||
*.ilk
|
||||
*.map
|
||||
*.exp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
*.idb
|
||||
*.pdb
|
||||
|
||||
# Kernel Module Compile Results
|
||||
*.mod*
|
||||
*.cmd
|
||||
.tmp_versions/
|
||||
modules.order
|
||||
Module.symvers
|
||||
Mkfile.old
|
||||
dkms.conf
|
||||
|
||||
### PlatformIO ###
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
.pio
|
||||
|
||||
# Various Altium files
|
||||
*.PrjPCBStructure
|
||||
*.SchDocPreview
|
||||
*.PcbDocPreview
|
||||
__Previews
|
||||
*.PrjPcbStructure
|
||||
*.Dat
|
||||
*.REP
|
||||
*.TLT
|
||||
*.LOG
|
||||
*.log
|
||||
*.htm
|
||||
*.$$$
|
||||
|
||||
#useless dirs
|
||||
Project\ Outputs
|
||||
Project\ Logs
|
||||
Project Outputs for*
|
||||
|
||||
#History
|
||||
History
|
||||
|
||||
#Exports, but not manual ones
|
||||
exports/*
|
||||
!exports/manual
|
||||
|
||||
#Python stuff
|
||||
scripts/__pycache__/
|
||||
*.bak
|
||||
*.dwl
|
||||
*.dwl2
|
||||
@@ -0,0 +1,26 @@
|
||||
# How to build firmware
|
||||
|
||||
For our firmware development, we are going to use Arduino. Mainly because it's user friendly, easy to use and
|
||||
most hobbyists are familiar with it or have already used it. While we could build the same or even more efficient
|
||||
firmware using bare-metal C and ESP-IDF, we are going to stick with Arduino and hope that this allows the project to be
|
||||
more friendly and easier to use/modify by wider DIY/hacker community.
|
||||
|
||||
## How can I build/compile firmware?
|
||||
|
||||
### 1. Install PlatformIO
|
||||
Installing PlatformIO CLI is pretty straight-forward and also well documented for Windows, Linux and MacOS.
|
||||
You will need to follow few steps and get PlatformIO CLI installed, detailed tutorial can be found at https://platformio.org/install/cli
|
||||
Make sure to install [PlatformIO Core](https://docs.platformio.org/en/latest//core/installation.html#installation-methods 'https://docs.platformio.org/en/latest//core/installation.html#installation-methods') and allso that it is available trough [shell](https://docs.platformio.org/en/latest//core/installation.html#piocore-install-shell-commands 'PlatformIO Core - Install Shell Commands¶').
|
||||
|
||||
### 2. Build firmware
|
||||
Open shell/command-prompt and navigate to 'Firmware/platformio' folder.
|
||||
|
||||
1. Compile and upload the firmware with `pio run --target upload --upload-port <COM-PORT>`. Make sure to replace `<COM-PORT>` with your ESP32's COM port (ie COM1 or /dev/ttyACM0)
|
||||
2. Upload the file system (Web page) with `pio run --target uploadfs --upload-port <COM-PORT>`, again replace `<COM-PORT>` with your ESP32's COM port.
|
||||
3. Restart/power-cycle your board
|
||||
|
||||
Every time you make a firmware change, you need to run step #1.
|
||||
Every time you make a change to the web page (anything inside `data` folder) you only need to run step #2.
|
||||
|
||||
|
||||
[<- Go back to repository root](../README.md)
|
||||
+7
File diff suppressed because one or more lines are too long
+8
@@ -0,0 +1,8 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v4.0.0 (https://getbootstrap.com)
|
||||
* Copyright 2011-2018 The Bootstrap Authors
|
||||
* Copyright 2011-2018 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;-ms-overflow-style:scrollbar;-webkit-tap-highlight-color:transparent}@-ms-viewport{width:device-width}article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}dfn{font-style:italic}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent;-webkit-text-decoration-skip:objects}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto;-ms-overflow-style:scrollbar}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg:not(:root){overflow:hidden}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important}
|
||||
/*# sourceMappingURL=bootstrap-reboot.min.css.map */
|
||||
Vendored
+12
File diff suppressed because one or more lines are too long
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
*/
|
||||
@font-face{font-family:"Font Awesome 5 Brands";font-style:normal;font-weight:400;font-display:block;src:url(../webfonts/fa-brands-400.eot);src:url(../webfonts/fa-brands-400.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-brands-400.woff2) format("woff2"),url(../webfonts/fa-brands-400.woff) format("woff"),url(../webfonts/fa-brands-400.ttf) format("truetype"),url(../webfonts/fa-brands-400.svg#fontawesome) format("svg")}.fab{font-family:"Font Awesome 5 Brands";font-weight:400}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
body{padding-top:120px}pre{background:#f7f7f9}iframe{overflow:hidden;border:none}@media (min-width: 768px){body>.navbar-transparent{box-shadow:none}body>.navbar-transparent .navbar-nav>.open>a{box-shadow:none}}#home,#help{font-size:.9rem}#home .navbar,#help .navbar{background:#349aed;background:linear-gradient(145deg, #349aed 50%, #34d8ed 100%);transition:box-shadow 200ms ease-in}#home .navbar-transparent,#help .navbar-transparent{background:none !important;box-shadow:none}#home .navbar-brand .nav-link,#help .navbar-brand .nav-link{display:inline-block;margin-right:-30px}#home .nav-link,#help .nav-link{text-transform:uppercase;font-weight:500;color:#fff}#home{padding-top:0}#home .btn{padding:.6rem .55rem .5rem;box-shadow:none;font-size:.7rem;font-weight:500}.bs-docs-section{margin-top:4em}.bs-docs-section .page-header h1{padding:2rem 0;font-size:3rem}.dropdown-menu.show[aria-labelledby="themes"]{display:-ms-flexbox;display:flex;width:420px;-ms-flex-wrap:wrap;flex-wrap:wrap}.dropdown-menu.show[aria-labelledby="themes"] .dropdown-item{width:33.333%}.dropdown-menu.show[aria-labelledby="themes"] .dropdown-item:first-child{width:100%}.bs-component{position:relative}.bs-component+.bs-component{margin-top:1rem}.bs-component .card{margin-bottom:1rem}.bs-component .modal{position:relative;top:auto;right:auto;left:auto;bottom:auto;z-index:1;display:block}.bs-component .modal-dialog{width:90%}.bs-component .popover{position:relative;display:inline-block;width:220px;margin:20px}.source-button{display:none;position:absolute;top:0;right:0;z-index:100;font-weight:700}.source-button:hover{cursor:pointer}.bs-component:hover .source-button{display:block}#source-modal pre{max-height:calc(100vh - 11rem);background-color:rgba(0,0,0,0.7);color:rgba(255,255,255,0.7)}.nav-tabs{margin-bottom:15px}.progress{margin-bottom:10px}#footer{margin:5em 0}#footer li{float:left;margin-right:1.5em;margin-bottom:1.5em}#footer p{clear:left;margin-bottom:0}.splash{padding:12em 0 6em;background:#349aed;background:linear-gradient(145deg, #349aed 50%, #34d8ed 100%);color:#fff;text-align:center}.splash .logo{width:160px}.splash h1{font-size:3em;color:#fff}.splash #social{margin:2em 0 3em}.splash .alert{margin:2em 0;border:none}.splash .sponsor a{color:#fff}.section-tout{padding:6em 0 1em;border-bottom:1px solid rgba(0,0,0,0.05);background-color:#eaf1f1;text-align:center}.section-tout .icon{display:-ms-flexbox;display:flex;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center;width:80px;height:80px;margin:0 auto 1rem;background:#349aed;background:linear-gradient(145deg, #3b9cea 50%, #3db8eb 100%);border-radius:50%;font-size:2rem;color:rgba(0,0,0,0.5)}.section-tout p{margin-bottom:5em}.section-preview{padding:4em 0}.section-preview .preview{margin-bottom:4em;background-color:#eaf1f1}.section-preview .preview .image{position:relative}.section-preview .preview .image::before{box-shadow:inset 0 0 0 1px rgba(0,0,0,0.1);position:absolute;top:0;left:0;width:100%;height:100%;content:"";pointer-events:none}.section-preview .preview .options{padding:2em;border:1px solid rgba(0,0,0,0.05);border-top:none;text-align:center}.section-preview .preview .options p{margin-bottom:2em}.section-preview .dropdown-menu{text-align:left}.section-preview .lead{margin-bottom:2em}.sponsor #carbonads{max-width:240px;margin:0 auto}.sponsor .carbon-text{display:block;margin-top:1em;font-size:12px}.sponsor .carbon-poweredby{float:right;margin-top:1em;font-size:10px}@media (max-width: 767px){.splash{padding-top:8em}.splash .logo{width:100px}.splash h1{font-size:2em}#banner{margin-bottom:2em;text-align:center}}
|
||||
+5
File diff suppressed because one or more lines are too long
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
/*!
|
||||
* Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
|
||||
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
||||
*/
|
||||
@font-face{font-family:"Font Awesome 5 Free";font-style:normal;font-weight:900;font-display:block;src:url(../webfonts/fa-solid-900.eot);src:url(../webfonts/fa-solid-900.eot?#iefix) format("embedded-opentype"),url(../webfonts/fa-solid-900.woff2) format("woff2"),url(../webfonts/fa-solid-900.woff) format("woff"),url(../webfonts/fa-solid-900.ttf) format("truetype"),url(../webfonts/fa-solid-900.svg#fontawesome) format("svg")}.fa,.fas{font-family:"Font Awesome 5 Free";font-weight:900}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 2.5 KiB |
@@ -0,0 +1,85 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WInFiDEL v%FW_VERSION% - Sasa Karanovic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/custom.min.css">
|
||||
<link href="css/fontawesome.min.css" rel="stylesheet">
|
||||
<link href="css/brands.min.css" rel="stylesheet">
|
||||
<link href="css/solid.min.css" rel="stylesheet">
|
||||
<link rel="shortcut icon" type="image/jpg" href="favicon.png"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a href="index.html" class="navbar-brand">WInFiDEL</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarResponsive">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="settings.html">Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://sasakaranovic.com/projects/diy-camera-slider/" target="_blank">Project Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://github.com/SasaKaranovic/DIY-Camera-Slider" target="_blank">Source Code</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="p-5 text-center bg-body-tertiary">
|
||||
<h1 class="text-body-emphasis"><span id="reading-last">...</span>mm</h1>
|
||||
<p class="col-lg-8 mx-auto fs-5 text-muted">
|
||||
Min: <span id="reading-min">...</span>mm -
|
||||
Average: <span id="reading-avg">...</span>mm -
|
||||
Max: <span id="reading-max">...</span>mm
|
||||
</p>
|
||||
<p class="col-lg-8 mx-auto fs-5 text-muted">
|
||||
Based on <span id="reading-count">...</span> measurements.
|
||||
</p>
|
||||
<p class="col-lg-8 mx-auto fs-5 text-muted mb-4">
|
||||
<a href="#" onclick="javascript:reset_stats();">Reset min/max/avg</a>
|
||||
</p>
|
||||
|
||||
<canvas id="myChart" width="600" height="200"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container">
|
||||
|
||||
<footer class="w-100 py-2 flex-shrink-3 mt-3 dark-bg">
|
||||
<div class="row gy-4 gx-5">
|
||||
<div class="col-lg-6 col-md-6">
|
||||
<p class="small text-muted">
|
||||
WInFiDEL v%FW_VERSION% made by <a href="https://SasaKaranovic.com/" target="_blank">Saša Karanović</a><br>
|
||||
WInFiDEL is based on the original InFiDel sensor made by <a href="https://www.youtube.com/watch?v=RYgdLPe_T0c" target="_blank">Thomas Sanladerer</a>.<br>
|
||||
Released as open-source and open-hardware for you to hack and enjoy! :)<br>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-6">
|
||||
<a class="m-2" href="https://sasakaranovic.com/" target="_blank"><i class="fas fa-home"></i> Blog</a>
|
||||
<a class="m-2" href="https://youtube.com/c/sasakaranovic" target="_blank"><i class="fab fa-youtube"></i> YouTube</a>
|
||||
<a class="m-2" href="https://twitter.com/_sasakaranovic_" target="_blank"><i class="fab fa-twitter"></i> Twitter</a>
|
||||
<a class="m-2" href="https://github.com/sasakaranovic" target="_blank"><i class="fab fa-github"></i> GitHub</a>
|
||||
<a href="https://github.com/sponsors/SasaKaranovic" target="_blank" title="Sponsor on GitHub"><i class="fab fa-github"></i> Sponsor on GitHub</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
|
||||
<script src="js/jquery-3.6.0.min.js"></script>
|
||||
<script src="js/bootstrap.bundle.min.js"></script>
|
||||
<script src='js/chart.js'></script>
|
||||
<script src="js/winfidel_index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
+7
File diff suppressed because one or more lines are too long
Vendored
+7
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+2
File diff suppressed because one or more lines are too long
@@ -0,0 +1,118 @@
|
||||
var updateIntervalID;
|
||||
|
||||
$(document).ready(function(){
|
||||
refresh_reading();
|
||||
get_calibration();
|
||||
start_periodic_update();
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
|
||||
|
||||
$("#btn-calibrate").on( "click", function() {
|
||||
const cal_adc = $('#input-adc-last').val();
|
||||
const cal_mm = $('#input-cal-diameter').val();
|
||||
|
||||
if(!isNaN(parseFloat(cal_mm)))
|
||||
{
|
||||
$('#btn-calibrate').text('Please wait...');
|
||||
create_calibration_point(cal_adc, cal_mm);
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#invalid-value").show();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$("#adc-label").on("dblclick", function() {
|
||||
|
||||
|
||||
let manual = $("#input-adc-last").prop('disabled');
|
||||
if (manual == true)
|
||||
{
|
||||
alert("Enabling manual calibration!");
|
||||
$("#input-adc-last").prop('disabled', false);
|
||||
$("#input-adc-last").tooltip('disable');
|
||||
stop_periodic_update();
|
||||
$('#input-adc-last').val('');
|
||||
$('#input-adc-last').focus();
|
||||
}
|
||||
else
|
||||
{
|
||||
$("#input-adc-last").prop('disabled', true);
|
||||
$("#input-adc-last").tooltip('enable');
|
||||
start_periodic_update();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function get_calibration()
|
||||
{
|
||||
$.getJSON( '/api/calibration/read', function( data ) {
|
||||
|
||||
const total_points = data['data'].length;
|
||||
$('#calibration-points-count').text(total_points);
|
||||
$("#calibration-points > tbody").html("");
|
||||
|
||||
for (let i = 0; i < total_points; i++) {
|
||||
if(i==0 || i== total_points-1)
|
||||
{
|
||||
$('table#calibration-points').append('<tr class="d-flex"><td class="col-5">'+ data['data'][i][0] +'</td><td class="col-5">'+ data['data'][i][1] +' mm</td><td class="col-2"></td></tr>');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('table#calibration-points').append('<tr class="d-flex"><td class="col-5">'+ data['data'][i][0] +'</td><td class="col-5">'+ data['data'][i][1] +' mm</td><td class="col-2"><a href="javascript:remove_calibration_point('+ data['data'][i][1] +');">Remove</a></td></tr>');
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function create_calibration_point(adc, mm)
|
||||
{
|
||||
$.get( '/api/calibration/create?adc='+ adc +'&mm='+ mm, function( data ) {
|
||||
if (data['status'] == 'ok')
|
||||
{
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function remove_calibration_point(diameter)
|
||||
{
|
||||
$.get( '/api/calibration/remove?mm='+ diameter, function( data ) {
|
||||
console.log(data);
|
||||
|
||||
if (data['status'] == 'ok')
|
||||
{
|
||||
location.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refresh_reading()
|
||||
{
|
||||
$.getJSON( '/api/diameter/read', function( data ) {
|
||||
$('#input-adc-last').val(data['data']['adc']);
|
||||
});
|
||||
}
|
||||
|
||||
function reset_stats()
|
||||
{
|
||||
$.get( '/api/diameter/reset');
|
||||
}
|
||||
|
||||
|
||||
function start_periodic_update()
|
||||
{
|
||||
updateIntervalID = window.setInterval(function(){
|
||||
refresh_reading();
|
||||
}, 1000);
|
||||
|
||||
}
|
||||
|
||||
function stop_periodic_update()
|
||||
{
|
||||
clearInterval(updateIntervalID);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
let measurements_chart;
|
||||
|
||||
$(function() {
|
||||
// Take new reading
|
||||
// refresh_reading();
|
||||
|
||||
var intervalId = window.setInterval(function(){
|
||||
refresh_reading();
|
||||
}, 1000);
|
||||
|
||||
const ctx = document.getElementById('myChart');
|
||||
|
||||
measurements_chart = new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
datasets: [{
|
||||
data: []
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: false,
|
||||
suggestedMin: 1.35,
|
||||
suggestedMax: 2.25,
|
||||
ticks: {
|
||||
// forces step size to be 50 units
|
||||
stepSize: 0.05
|
||||
}
|
||||
},
|
||||
x: {
|
||||
beginAtZero: false,
|
||||
reverse: true
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
function chart_add_point(newData) {
|
||||
measurements_chart.data.datasets.forEach((dataset) => {
|
||||
// dataset.data.push(newData);
|
||||
dataset.data.unshift(newData);
|
||||
});
|
||||
|
||||
// measurements_chart.update();
|
||||
measurements_chart.update('none');
|
||||
}
|
||||
|
||||
|
||||
function refresh_reading()
|
||||
{
|
||||
$.getJSON( '/api/diameter/read', function( data ) {
|
||||
|
||||
$('#reading-last').text(data['data']['diameter']);
|
||||
$('#reading-min').text(data['data']['min']);
|
||||
$('#reading-avg').text(data['data']['avg']);
|
||||
$('#reading-max').text(data['data']['max']);
|
||||
$('#reading-count').text(data['data']['count']);
|
||||
|
||||
chart_add_point({x: get_timestamp(), y: data['data']['diameter']});
|
||||
});
|
||||
}
|
||||
|
||||
function reset_stats()
|
||||
{
|
||||
$.get( '/api/diameter/reset');
|
||||
}
|
||||
|
||||
function get_timestamp()
|
||||
{
|
||||
let date = new Date();
|
||||
return twoDigitPad(date.getHours()) +':'+ twoDigitPad(date.getMinutes()) +':'+ twoDigitPad(date.getSeconds());
|
||||
}
|
||||
|
||||
function twoDigitPad(num) {
|
||||
return num < 10 ? "0" + num : num;
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>WInFiDEL v%FW_VERSION% - Sasa Karanovic</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="css/custom.min.css">
|
||||
<link href="css/fontawesome.min.css" rel="stylesheet">
|
||||
<link href="css/brands.min.css" rel="stylesheet">
|
||||
<link href="css/solid.min.css" rel="stylesheet">
|
||||
<link rel="shortcut icon" type="image/jpg" href="favicon.png"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="navbar navbar-expand-lg fixed-top navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a href="index.html" class="navbar-brand">WInFiDEL</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarResponsive">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="settings.html">Settings</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://sasakaranovic.com/projects/diy-camera-slider/" target="_blank">Project Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="https://github.com/SasaKaranovic/DIY-Camera-Slider" target="_blank">Source Code</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="p-5 text-center bg-body-tertiary">
|
||||
<h1 class="text-body-emphasis">Using <span id="calibration-points-count"></span> calibration points</h1>
|
||||
|
||||
<div class="col-lg-6 mx-auto mt-4 mb-5">
|
||||
|
||||
<table id="calibration-points" class="table table-sm table-striped text-left">
|
||||
<thead>
|
||||
<tr class="d-flex">
|
||||
<th class="col-5">ADC</th>
|
||||
<th class="col-5">Diameter</th>
|
||||
<th class="col-2">Remove</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
<p class="col-lg-8 mx-auto fs-5 text-muted mb-4">
|
||||
We use above calibration points to estimate filament diameter using <a href="https://en.wikipedia.org/wiki/Linear_interpolation" target="_blank" class="text-muted">linear interpolation</a>.<br>
|
||||
First and last point are boundary items and can not be removed.<br>
|
||||
The firmware has been compiled to allow up to %MAX_CALIBRATION_POINTS% calibration points.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container">
|
||||
<div class="p-5 text-center bg-body-tertiary">
|
||||
<h1 class="text-body-emphasis">Create calibration point</h1>
|
||||
|
||||
<div class="text-left">
|
||||
<p class="col-lg-6 mx-auto fs-5 text-muted mt-4">
|
||||
Calibration procedure (using drill bit)
|
||||
</p>
|
||||
<p class="col-lg-6 mx-auto fs-5 text-muted mb-1">
|
||||
1. Measure drill bit using calipers and note the diameter size in mm
|
||||
</p>
|
||||
<p class="col-lg-6 mx-auto fs-5 text-muted mb-1">
|
||||
2. Insert the drill bit into WInFiDEL sensor and note the ADC value
|
||||
</p>
|
||||
<p class="col-lg-6 mx-auto fs-5 text-muted mb-1">
|
||||
3. In the input box below enter the measured diameter from step #1
|
||||
</p>
|
||||
<p class="col-lg-6 mx-auto fs-5 text-muted mb-1">
|
||||
4. Click on `Calibrate` button and wait for page to reload.
|
||||
</p>
|
||||
<p class="col-lg-6 mx-auto fs-5 text-muted mb-1">
|
||||
5. Verify that the list of calibration points has been updated.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p class="col-lg-6 mx-auto fs-5 mt-4">
|
||||
Current ADC value of
|
||||
</p>
|
||||
|
||||
<div class="input-group mb-3 mt-3 col-lg-2 mx-auto">
|
||||
<input type="text" class="form-control" disabled placeholder="" aria-label="" aria-describedby="basic-addon2" id="input-adc-last" data-toggle="tooltip" data-placement="top" title="This value is updated automatically.">
|
||||
<span class="input-group-text" id="adc-label">ADC</span>
|
||||
</div>
|
||||
|
||||
|
||||
<p class="col-lg-6 mx-auto fs-5 mt-4">
|
||||
should be calibrated as
|
||||
</p>
|
||||
|
||||
<div class="input-group mb-3 mt-3 col-lg-2 mx-auto">
|
||||
<input type="text" class="form-control" placeholder="" aria-label="" aria-describedby="basic-addon2" id="input-cal-diameter">
|
||||
<span class="input-group-text" id="basic-addon3">mm</span>
|
||||
</div>
|
||||
|
||||
<div id="invalid-value" class="invalid-feedback">Invalid diameter value!</div>
|
||||
|
||||
<div class="input-group mb-3 mt-3 col-lg-2 mx-auto">
|
||||
<button type="button" class="btn btn-primary" id="btn-calibrate">Calibrate</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="">
|
||||
<p class="col-lg-7 mx-auto fs-5 text-muted mt-4">
|
||||
Note: Update existing calibration point by specifying same `mm` diameter.<br>
|
||||
Note: If new point has same ADC or mm value as the existing one. Existing point will be updated.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div class="p-5 text-center bg-body-tertiary">
|
||||
<h1 class="text-body-emphasis">Firmware information</h1>
|
||||
|
||||
<table class="table table-sm table-striped text-left">
|
||||
<thead>
|
||||
<tr class="d-flex">
|
||||
<th class="col-4 text-break">Parameter</th>
|
||||
<th class="col-2">Value</th>
|
||||
<th class="col-6">Note</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">MAX_CALIBRATION_POINTS</td>
|
||||
<td class="col-2 text-break">%MAX_CALIBRATION_POINTS%</td>
|
||||
<td class="col-6">Maximum number of calibration points supported by firmware.</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">CALIBRATION_POINT_SAMPLE_COUNT</td>
|
||||
<td class="col-2 text-break">%CALIBRATION_POINT_SAMPLE_COUNT%</td>
|
||||
<td class="col-6">Number of ADC samples taken when creating a calibration point</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">CALIBRATION_POINT_ACCURACY_POINT</td>
|
||||
<td class="col-2 text-break">%CALIBRATION_POINT_ACCURACY_POINT%</td>
|
||||
<td class="col-6">When creating calibration point. All ADC samples must be within `%CALIBRATION_POINT_ACCURACY_POINT%` points of each other. Otherwise we will fail to create a calibration point due to ADC noise.</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">ADC_MIN</td>
|
||||
<td class="col-2 text-break">%ADC_MIN%</td>
|
||||
<td class="col-6">Minimum value ADC can provide</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">ADC_MIN_EQUALS_MM</td>
|
||||
<td class="col-2 text-break">%ADC_MIN_EQUALS_MM%</td>
|
||||
<td class="col-6">Minimum ADC value is treated as `%ADC_MIN_EQUALS_MM%`mm</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">ADC_MAX</td>
|
||||
<td class="col-2 text-break">%ADC_MAX%</td>
|
||||
<td class="col-6">Maximum value ADC can provide</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">ADC_MAX_EQUALS_MM</td>
|
||||
<td class="col-2 text-break">%ADC_MAX_EQUALS_MM%</td>
|
||||
<td class="col-6">Maximum ADC value is treated as `%ADC_MAX_EQUALS_MM%`mm</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">BUILD_TIME</td>
|
||||
<td class="col-2 text-break">%BUILD_TIME%</td>
|
||||
<td class="col-6">Time when firmware was compiled</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">BUILD_DATE</td>
|
||||
<td class="col-2 text-break">%BUILD_DATE%</td>
|
||||
<td class="col-6">Date when firmware was compiled</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">ADC_ALGO</td>
|
||||
<td class="col-2 text-break">%ADC_ALGO%</td>
|
||||
<td class="col-6">Which alghoritm is used to calculate final ADC value</td>
|
||||
</tr>
|
||||
<tr class="d-flex">
|
||||
<td class="col-4 text-break">ADC_CHIP</td>
|
||||
<td class="col-2 text-break">%ADC_CHIP%</td>
|
||||
<td class="col-6">Which ADC chip is populated on the board</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<div class="">
|
||||
<p class="col-lg-8 mx-auto fs-5 text-muted mb-4">
|
||||
Values in this table are provided for development/debugging purposes (and just for fun).<br>
|
||||
You should not have to worry about them during devices normal operation.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="container">
|
||||
|
||||
<footer class="w-100 py-2 flex-shrink-3 mt-5 dark-bg">
|
||||
<div class="row gy-4 gx-5">
|
||||
<div class="col-lg-6 col-md-6">
|
||||
<p class="small text-muted">
|
||||
WInFiDEL v%FW_VERSION% made by <a href="https://SasaKaranovic.com/" target="_blank">Saša Karanović</a><br>
|
||||
WInFiDEL is based on the original InFiDel sensor made by <a href="https://www.youtube.com/watch?v=RYgdLPe_T0c" target="_blank">Thomas Sanladerer</a>.<br>
|
||||
There are two types of people in the world: those who can extrapolate from incomplete data sets.<br>
|
||||
Released as open-source and open-hardware for you to hack and enjoy! :)<br>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-lg-6 col-md-6">
|
||||
<a class="m-2" href="https://sasakaranovic.com/" target="_blank"><i class="fas fa-home"></i> Blog</a>
|
||||
<a class="m-2" href="https://youtube.com/c/sasakaranovic" target="_blank"><i class="fab fa-youtube"></i> YouTube</a>
|
||||
<a class="m-2" href="https://twitter.com/_sasakaranovic_" target="_blank"><i class="fab fa-twitter"></i> Twitter</a>
|
||||
<a class="m-2" href="https://github.com/sasakaranovic" target="_blank"><i class="fab fa-github"></i> GitHub</a>
|
||||
<a href="https://github.com/sponsors/SasaKaranovic" target="_blank" title="Sponsor on GitHub"><i class="fab fa-github"></i> Sponsor on GitHub</a>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="js/jquery-3.6.0.min.js"></script>
|
||||
<script src="js/bootstrap.bundle.min.js"></script>
|
||||
<script src="js/winfidel_calibration.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,45 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
default_envs = esp32dev
|
||||
|
||||
[env:esp32_ota]
|
||||
extends = env:esp32dev
|
||||
upload_protocol = espota
|
||||
|
||||
[env:esp32dev]
|
||||
board_build.f_cpu = 160000000L
|
||||
board_build.f_flash = 80000000L
|
||||
board_build.flash_mode = qio
|
||||
board_build.filesystem = littlefs
|
||||
board_build.partitions = default.csv
|
||||
|
||||
framework = arduino
|
||||
platform = https://github.com/platformio/platform-espressif32.git
|
||||
board = esp32-c3-devkitm-1
|
||||
upload_protocol = esptool
|
||||
Monitor_speed = 115200
|
||||
build_flags =
|
||||
-DARDUINO_USB_MODE=1
|
||||
-DARDUINO_USB_CDC_ON_BOOT=1
|
||||
|
||||
lib_deps=
|
||||
LittleFS
|
||||
FS
|
||||
WiFi
|
||||
EEPROM
|
||||
Wire
|
||||
https://github.com/SasaKaranovic/ESPAsyncWebServer.git
|
||||
https://github.com/me-no-dev/AsyncTCP.git
|
||||
ESPmDNS @ 2.0.0
|
||||
Arduino_JSON
|
||||
https://github.com/tzapu/WiFiManager.git
|
||||
;arduino-libraries/Arduino_JSON @ 0.1.0
|
||||
@@ -0,0 +1,149 @@
|
||||
#include <Wire.h>
|
||||
|
||||
uint32_t adc_samples[ADC_MAX_SAMPLES] = {0};
|
||||
uint8_t rxBuff[2] = {0};
|
||||
uint8_t rxPos = 0;
|
||||
uint32_t nADCTimeoutTick = 0;
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
Wire.begin(I2C_SDA_PIN, I2C_SCL_PIN);
|
||||
}
|
||||
|
||||
|
||||
// Helper function to indicate (in the UI) which
|
||||
// algo is used for calculating final ADC value
|
||||
String adc_get_algo(void)
|
||||
{
|
||||
#ifdef ADC_FINAL_ADC_VALUE_USING_MEAN
|
||||
return String("MEAN");
|
||||
#else
|
||||
return String("AVERAGE");
|
||||
#endif
|
||||
}
|
||||
|
||||
String adc_get_chip(void)
|
||||
{
|
||||
#ifdef ADC_CHIP_IS_MCP3221
|
||||
return String("MCP3221");
|
||||
#else
|
||||
return String("MCP3021");
|
||||
#endif
|
||||
}
|
||||
|
||||
// This function will take `N` samples and store them into an array
|
||||
// After that we should use one of the available functions to calculate value
|
||||
// ie. calculate average, mean, trimmed_mean etc.
|
||||
uint32_t adc_sample_data(uint8_t nSamples)
|
||||
{
|
||||
if(nSamples > ADC_MAX_SAMPLES)
|
||||
{
|
||||
Serial.print("Limiting number of samples to ");
|
||||
Serial.println(ADC_MAX_SAMPLES);
|
||||
nSamples = ADC_MAX_SAMPLES;
|
||||
}
|
||||
else if (nSamples <= 0)
|
||||
{
|
||||
Serial.println("Requested invalid number of samples. Aborting.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t accumulator = 0;
|
||||
uint32_t sample = 0;
|
||||
rxPos = 0;
|
||||
|
||||
while(rxPos++ < nSamples)
|
||||
{
|
||||
// Request two bytes
|
||||
Wire.requestFrom(ADC_I2C_ADDRESS, 2);
|
||||
// // Wait for data to become available
|
||||
nADCTimeoutTick = millis() + 100;
|
||||
while((!Wire.available()) && (millis()<=nADCTimeoutTick));
|
||||
|
||||
// Read two bytes
|
||||
rxBuff[0] = Wire.read();
|
||||
rxBuff[1] = Wire.read();
|
||||
|
||||
// Accumulate value
|
||||
#ifdef ADC_CHIP_IS_MCP3221
|
||||
// Using MCP3221
|
||||
sample = ( (rxBuff[0] << 8 | (rxBuff[1])));
|
||||
#else
|
||||
// Using MCP3021
|
||||
sample = ( (rxBuff[0] << 6 | (rxBuff[1]) >> 2));
|
||||
#endif
|
||||
|
||||
adc_samples[rxPos] = sample;
|
||||
accumulator += sample;
|
||||
}
|
||||
|
||||
// Divide value with number of samples
|
||||
return (accumulator/nSamples);
|
||||
}
|
||||
|
||||
int qsort_compare( const void* a, const void* b)
|
||||
{
|
||||
uint32_t int_a = * ( (uint32_t*) a );
|
||||
uint32_t int_b = * ( (uint32_t*) b );
|
||||
|
||||
// an easy expression for comparing
|
||||
return (int_a > int_b) - (int_a < int_b);
|
||||
}
|
||||
|
||||
uint32_t adc_get_mean(void)
|
||||
{
|
||||
// We want to have 3 or more samples
|
||||
if (rxPos <= 2)
|
||||
{
|
||||
Serial.println("Insufficient number of samples. Returing the first value");
|
||||
return adc_samples[0];
|
||||
}
|
||||
// Sort samples
|
||||
qsort(adc_samples, rxPos, sizeof(uint32_t), qsort_compare);
|
||||
|
||||
// Get the "middle" element
|
||||
// (we will round up/down on even number of samples, but we can live with that for now)
|
||||
return adc_samples[rxPos/2];
|
||||
}
|
||||
|
||||
|
||||
|
||||
void i2c_scan_bus(void)
|
||||
{
|
||||
uint8_t error, address;
|
||||
int nDevices;
|
||||
|
||||
Serial.println("Scanning...");
|
||||
|
||||
nDevices = 0;
|
||||
for(address = 1; address < 127; address++ )
|
||||
{
|
||||
// The i2c_scanner uses the return value of
|
||||
// the Write.endTransmisstion to see if
|
||||
// a device did acknowledge to the address.
|
||||
Wire.beginTransmission(address);
|
||||
error = Wire.endTransmission();
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
Serial.print("I2C device found at address 0x");
|
||||
if (address<16)
|
||||
Serial.print("0");
|
||||
Serial.print(address,HEX);
|
||||
Serial.println(" !");
|
||||
|
||||
nDevices++;
|
||||
}
|
||||
else if (error==4)
|
||||
{
|
||||
Serial.print("Unknown error at address 0x");
|
||||
if (address<16)
|
||||
Serial.print("0");
|
||||
Serial.println(address,HEX);
|
||||
}
|
||||
}
|
||||
if (nDevices == 0)
|
||||
Serial.println("No I2C devices found\n");
|
||||
else
|
||||
Serial.println("done\n");
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
We will use a struct to hold all of our calibration points.
|
||||
Using known calibration points, we can interpolate what is the
|
||||
measured value for any ADC value as long as we have two calibration
|
||||
so that one is lower and the other is higher than the current reading.
|
||||
|
||||
Our calibration points look like: ADC_VALUE -> CALIBRATED_MM_VALUE
|
||||
* We will keep all of our calibration vales sorted by ASC value of ADC_VALUE
|
||||
|
||||
For example, let's assume we have below calibration points
|
||||
620 -> 2.0mm
|
||||
850 -> 1.5mm
|
||||
915 -> 1.0mm
|
||||
|
||||
In order to calculate what is the `mm` equivalent for ADC_VALUE value of `750`
|
||||
1) Find calibration point that is higher than current ADC_VALUE and use it as HIGH_POINT
|
||||
1.1) Make sure there that there is a lower (we use boundary items to guarantee this) and use it as LOW_POINT
|
||||
2) Calculate the slope between two points (LOW_POINT and HIGH_POINT)
|
||||
3) Calculate the Y(mm) value using LOW_POINT and the calculated slope
|
||||
*/
|
||||
#include "config_winfidel.h"
|
||||
|
||||
|
||||
static calibration_t cal = {0};
|
||||
char calibration_json[CALIBRATION_JSON_STR_MAX_LEN] = {0};
|
||||
|
||||
|
||||
void calibration_init(void)
|
||||
{
|
||||
bool res;
|
||||
|
||||
res = calibration_read_from_eeprom();
|
||||
if (res == false)
|
||||
{
|
||||
calibration_reset();
|
||||
}
|
||||
}
|
||||
|
||||
bool calibration_read_from_eeprom(void)
|
||||
{
|
||||
EEPROM.readBytes(0, (void *)&cal, sizeof(calibration_t));
|
||||
if (cal.valid == EEPROM_MAGIC_KEY)
|
||||
{
|
||||
Serial.println("Calibration loaded from EEPROM");
|
||||
return true;
|
||||
}
|
||||
Serial.println("Calibration in EEPROM is invalid");
|
||||
return false;
|
||||
}
|
||||
|
||||
void calibration_save_to_eeprom(void)
|
||||
{
|
||||
EEPROM.writeBytes(0, (void *)&cal, sizeof(calibration_t));
|
||||
EEPROM.commit();
|
||||
}
|
||||
|
||||
void calibration_reset(void)
|
||||
{
|
||||
for(uint8_t i=0; i<MAX_CALIBRATION_POINTS; i++)
|
||||
{
|
||||
cal.points[i] = CAL_POINT_EMPTY;
|
||||
}
|
||||
cal.points[0] = CAL_POINT_FIRST;
|
||||
cal.points[1] = CAL_POINT_LAST;
|
||||
cal.numPoints = 2;
|
||||
cal.valid = EEPROM_MAGIC_KEY;
|
||||
sort_calibration_points();
|
||||
calibration_save_to_eeprom();
|
||||
|
||||
Serial.println("Default calibration loaded");
|
||||
}
|
||||
|
||||
|
||||
// Create new calibration point using provided `mm` value
|
||||
// and sampled ADC value
|
||||
winfidel_status_t create_calibration_point(float mm)
|
||||
{
|
||||
// Check if we already have maximum number of point
|
||||
if(cal.numPoints >= MAX_CALIBRATION_POINTS)
|
||||
{
|
||||
return WINFIDEL_NO_SPACE;
|
||||
}
|
||||
|
||||
uint32_t adc_samples[CALIBRATION_POINT_SAMPLE_COUNT] = {0};
|
||||
uint32_t adc_min = ADC_MAX;
|
||||
uint32_t adc_max = ADC_MIN;
|
||||
uint32_t adc_average = 0;
|
||||
|
||||
// Sample the ADC value CALIBRATION_POINT_SAMPLE_COUNT times
|
||||
for(uint8_t i=0; i<CALIBRATION_POINT_SAMPLE_COUNT; i++)
|
||||
{
|
||||
// Sample ADC
|
||||
adc_samples[i] = adc_sample_data(1);
|
||||
|
||||
// Update minimum
|
||||
if(adc_samples[i] < adc_min)
|
||||
{
|
||||
adc_min = adc_samples[i];
|
||||
}
|
||||
|
||||
// Update maximum
|
||||
if(adc_samples[i] > adc_max)
|
||||
{
|
||||
adc_max = adc_samples[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Check our max-min is less than CALIBRATION_POINT_ACCURACY_POINT
|
||||
if( (adc_max-adc_min) > CALIBRATION_POINT_ACCURACY_POINT)
|
||||
{
|
||||
Serial.print("ADC accuracy was too low: ");
|
||||
Serial.print((adc_max-adc_min));
|
||||
Serial.print(" points between min and max!");
|
||||
|
||||
return WINFIDEL_LOW_ACCURACY;
|
||||
}
|
||||
|
||||
// Average out ADC
|
||||
for(uint8_t i=0; i<CALIBRATION_POINT_SAMPLE_COUNT; i++)
|
||||
{
|
||||
adc_average += adc_samples[i];
|
||||
}
|
||||
adc_average = adc_average/CALIBRATION_POINT_SAMPLE_COUNT;
|
||||
|
||||
manually_create_calibration_point(adc_average, mm);
|
||||
return WINFIDEL_OK;
|
||||
}
|
||||
|
||||
// Create calibration point wih given ADC value and MM diameter
|
||||
winfidel_status_t manually_create_calibration_point(uint32_t adc_average, float mm)
|
||||
{
|
||||
bool existing_point = false;
|
||||
|
||||
// Check if we already have maximum number of point
|
||||
if(cal.numPoints >= MAX_CALIBRATION_POINTS)
|
||||
{
|
||||
return WINFIDEL_NO_SPACE;
|
||||
}
|
||||
|
||||
// Check if we are creating new point or updating existing `mm` point with new ADC value
|
||||
for(uint8_t i=0; i<MAX_CALIBRATION_POINTS; i++)
|
||||
{
|
||||
if(cal.points[i].mm == mm || cal.points[i].adc == adc_average)
|
||||
{
|
||||
existing_point = true;
|
||||
cal.points[i].adc = adc_average;
|
||||
cal.points[i].mm = mm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// We didn't find existing calibration point with same `mm` value
|
||||
if (existing_point == false)
|
||||
{
|
||||
// Create new point
|
||||
cal.points[cal.numPoints++] = { .adc = adc_average, .mm = mm };
|
||||
}
|
||||
|
||||
sort_calibration_points();
|
||||
calibration_save_to_eeprom();
|
||||
return WINFIDEL_OK;
|
||||
}
|
||||
|
||||
// Remove calibration point by using given mm value
|
||||
// We will find the position of this calibration point
|
||||
// and then use `remove_calibration_point_pos` to remove it
|
||||
winfidel_status_t remove_calibration_point_mm(float mm)
|
||||
{
|
||||
for(uint8_t i=0; i<MAX_CALIBRATION_POINTS; i++)
|
||||
{
|
||||
if(cal.points[i].mm == mm)
|
||||
{
|
||||
return remove_calibration_point_pos(i);
|
||||
}
|
||||
}
|
||||
|
||||
return WINFIDEL_MISSING;
|
||||
}
|
||||
|
||||
|
||||
// Remove calibration point at index N
|
||||
// We need to POP the N-th calibration point and shift all
|
||||
// calibration values up
|
||||
winfidel_status_t remove_calibration_point_pos(uint8_t pos)
|
||||
{
|
||||
// We don't allow removing first and last (cal.numPoints) calibration points
|
||||
if(pos == 0 || pos == cal.numPoints-1)
|
||||
{
|
||||
return WINFIDEL_FORBIDDEN;
|
||||
}
|
||||
|
||||
// Shift up all calibration points starting from pos
|
||||
for(uint8_t i=pos; i<MAX_CALIBRATION_POINTS-1; i++)
|
||||
{
|
||||
cal.points[i] = cal.points[i+1];
|
||||
}
|
||||
|
||||
// Decrement number of calibration points
|
||||
cal.numPoints--;
|
||||
calibration_save_to_eeprom();
|
||||
|
||||
return WINFIDEL_OK;
|
||||
}
|
||||
|
||||
// This function should only be called inside `sort_calibration_points`
|
||||
static void swap_calibration_points(uint8_t i, uint8_t j)
|
||||
{
|
||||
cal_point_t temp = cal.points[i];
|
||||
cal.points[i] = cal.points[j];
|
||||
cal.points[j] = temp;
|
||||
}
|
||||
|
||||
// Sort all calibration points in ASC order using ADC value
|
||||
void sort_calibration_points(void)
|
||||
{
|
||||
uint8_t i, j;
|
||||
for (i = 0; i < cal.numPoints - 1; i++)
|
||||
{
|
||||
// Last i elements are already
|
||||
// in place
|
||||
for (j = 0; j < cal.numPoints - i - 1; j++)
|
||||
{
|
||||
if (cal.points[j].adc > cal.points[j + 1].adc)
|
||||
{
|
||||
swap_calibration_points(j, j + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Format JSON string that contains all calibration points
|
||||
char *get_calibration_json(void)
|
||||
{
|
||||
int32_t pos = 0;
|
||||
int32_t len = 0;
|
||||
|
||||
// Start of JSON
|
||||
len = snprintf(calibration_json, CALIBRATION_JSON_STR_MAX_LEN-pos, "{\"status\":\"ok\",\"data\":[");
|
||||
pos += len;
|
||||
|
||||
// Append each calibration point
|
||||
#if 1
|
||||
for (uint8_t i=0; i<cal.numPoints; i++) // Send ONLY currently used calibration points
|
||||
#else
|
||||
for (uint8_t i=0; i<MAX_CALIBRATION_POINTS; i++) // Send ALL (used and unused) calibration points
|
||||
#endif
|
||||
{
|
||||
len = snprintf(&calibration_json[pos], CALIBRATION_JSON_STR_MAX_LEN-pos, "[%d, \"%.3f\"],",
|
||||
cal.points[i].adc, cal.points[i].mm);
|
||||
pos += len;
|
||||
}
|
||||
|
||||
// End of JSON
|
||||
snprintf(&calibration_json[pos-1], CALIBRATION_JSON_STR_MAX_LEN-pos, "]}");
|
||||
|
||||
return calibration_json;
|
||||
}
|
||||
|
||||
// Convert given ADC value to mm using available calibration points
|
||||
float adc_to_mm(uint32_t adc)
|
||||
{
|
||||
for (uint8_t i=0; i<cal.numPoints; i++)
|
||||
{
|
||||
if(cal.points[i].adc > adc)
|
||||
{
|
||||
float slope = ((float)cal.points[i].mm - cal.points[i-1].mm) / ((float)cal.points[i].adc - cal.points[i-1].adc);
|
||||
float indiff = ((float)adc - cal.points[i-1].adc);
|
||||
float outdiff = slope * indiff;
|
||||
float out = outdiff + cal.points[i-1].mm;
|
||||
return (out);
|
||||
}
|
||||
}
|
||||
|
||||
// We should never reach this section
|
||||
Serial.println("Failed to find calibration point. Returning 0.0mm");
|
||||
return 0.0f;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
#ifndef __WINFIDEL_CFG__
|
||||
#define __WINFIDEL_CFG__
|
||||
|
||||
#define MDNS_NAME "winfidel"
|
||||
#define WIFI_HOSTNAME "WInFiDEL by SK"
|
||||
|
||||
|
||||
#define CALIBRATION_POINT_SAMPLE_COUNT 32 // Number of ADC samples to take for new calibration point
|
||||
#define CALIBRATION_POINT_ACCURACY_POINT 50 // We expect all CALIBRATION_POINT_SAMPLE_COUNT samples to be
|
||||
// within CALIBRATION_POINT_ACCURACY_POINT of each other
|
||||
// in order to have successful calibration point creation
|
||||
|
||||
#define CALIBRATION_BOUNDARY_ITEMS 2 // We need lower and upper boundary item for safety
|
||||
#define MAX_CALIBRATION_POINTS (10 + CALIBRATION_BOUNDARY_ITEMS)
|
||||
#define ADC_MIN 0 // Minimum value we can get from our ADC (should be always 0)
|
||||
#define ADC_MIN_EQUALS_MM 5.0f // ADC_MIN should be considered this diameter (in mm)
|
||||
#define ADC_MAX 4095 // Maximum value we can get from our ADC (should be 2^n-bits)
|
||||
#define ADC_MAX_EQUALS_MM 0.0f // ADC_MAX should be considered this diameter (in mm)
|
||||
|
||||
#define CAL_POINT_EMPTY { .adc = ADC_MIN, .mm = ADC_MIN_EQUALS_MM }
|
||||
#define CAL_POINT_FIRST { .adc = ADC_MIN, .mm = ADC_MIN_EQUALS_MM }
|
||||
#define CAL_POINT_LAST { .adc = ADC_MAX, .mm = ADC_MAX_EQUALS_MM }
|
||||
|
||||
#define ADC_MAX_SAMPLES 64 // Maximum number of ADC samples we can take in one measurement cycle
|
||||
#define ADC_SAMPLES_PER_MEASUREMENT_CYCLE 16 // How many samples to take for each measurement cycle
|
||||
#define ADC_FINAL_ADC_VALUE_USING_MEAN // Use mean instead of average ADC value
|
||||
|
||||
#define ADC_CHIP_IS_MCP3221 // Specify which ADC chip we are using
|
||||
// #define ADC_CHIP_MCP3021 // Specify which ADC chip we are using
|
||||
#define ADC_I2C_ADDRESS 0x4D // 7-bit I2C address of our ADC IC
|
||||
#define I2C_SCL_PIN 0 // SCL pin number
|
||||
#define I2C_SDA_PIN 1 // SDA pin number
|
||||
|
||||
// String buffers
|
||||
#define SENSOR_STR_MAX_LEN 256
|
||||
#define CALIBRATION_JSON_STR_MAX_LEN 512
|
||||
|
||||
#define EEPROM_MAGIC_KEY 0x53 // Predefined value used to verify EEPROM has been initialized
|
||||
|
||||
|
||||
// Enum holding calibration results
|
||||
typedef enum winfidel_status
|
||||
{
|
||||
WINFIDEL_OK,
|
||||
WINFIDEL_FAIL,
|
||||
WINFIDEL_FORBIDDEN,
|
||||
WINFIDEL_INVALID_ARGUMENT,
|
||||
WINFIDEL_MISSING,
|
||||
WINFIDEL_NO_SPACE,
|
||||
WINFIDEL_LOW_ACCURACY
|
||||
|
||||
} winfidel_status_t;
|
||||
|
||||
|
||||
// Calibration point struct -> holds ADC value and equivalent mm diameter
|
||||
typedef struct cal_point
|
||||
{
|
||||
uint32_t adc;
|
||||
float mm;
|
||||
} cal_point_t;
|
||||
|
||||
// Calibration struct -> holds all calibration points and total number of valid calibration points
|
||||
typedef struct calibration
|
||||
{
|
||||
cal_point_t points[MAX_CALIBRATION_POINTS];
|
||||
uint32_t numPoints;
|
||||
uint8_t valid;
|
||||
} calibration_t;
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
/* SPDX-License-Identifier: MIT
|
||||
* Copyright(c) 2022 Lincoln Lavoie <lincoln.lavoie@gmail.com>
|
||||
*/
|
||||
|
||||
#include <Preferences.h>
|
||||
|
||||
#ifndef __PersistSettings__
|
||||
#define __PersistSettings__
|
||||
|
||||
template <class T>
|
||||
class PersistSettings{
|
||||
private:
|
||||
bool mValid;
|
||||
unsigned int mConfigVersion;
|
||||
uint16_t CRC16(byte *data, size_t data_len);
|
||||
public:
|
||||
T Config;
|
||||
PersistSettings(unsigned int ConfigVersion);
|
||||
void Begin(void);
|
||||
void Write(void);
|
||||
void ResetToDefault(void);
|
||||
bool Valid(void);
|
||||
};
|
||||
#endif
|
||||
|
||||
// PersistSettings Constructor
|
||||
// Use the Config structure as the class template for the object.
|
||||
// Provide a default version, preferable as a static member of the
|
||||
// config object.
|
||||
template <class T>
|
||||
PersistSettings<T>::PersistSettings(unsigned int version){
|
||||
mConfigVersion = version;
|
||||
mValid= false;
|
||||
}
|
||||
|
||||
// Initialize the settings object, read the config from the
|
||||
// persistent storage, and validate data. If the config object
|
||||
// can not be read, an error is detected, or the version mismatches,
|
||||
// the Config object will be reset to the default values.
|
||||
template <class T>
|
||||
void PersistSettings<T>::Begin(void){
|
||||
Preferences pref;
|
||||
|
||||
// Setup the preferences namespace, as read only
|
||||
if( !pref.begin("PersistSettings", true) ){
|
||||
log_e("Failed to open PersistSettings namespace, resetting and writing defaults.\r\n");
|
||||
this->ResetToDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the stored config version version, if it's not equal to then the version provided
|
||||
// with the the detail, we assume the DefaultConfig has a newer revision of the
|
||||
// Config object and we initialize to that value instead of stored values.
|
||||
// A value of 0 indicates the key didn't exist, assume no settings exist.
|
||||
unsigned int storedVersion = pref.getUInt("version", 0);
|
||||
if( storedVersion == 0 || storedVersion != mConfigVersion ){
|
||||
log_e("Version mismatch (saved: %d, current: %d), resetting to defaults.\r\n", storedVersion, mConfigVersion);
|
||||
this->ResetToDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// Read the settings from the persistent storage.
|
||||
size_t configLen = pref.getBytesLength("config");
|
||||
byte memBytes[configLen];
|
||||
if (sizeof(T)+2 != configLen ){
|
||||
log_e("Length read failure (read: %d, expected: %d), resetting to defaults.\r\n", configLen, sizeof(T)+2);
|
||||
this->ResetToDefault();
|
||||
return;
|
||||
}
|
||||
pref.getBytes("config", memBytes, configLen);
|
||||
|
||||
// Check the CRC16
|
||||
if( CRC16(memBytes, configLen) ){
|
||||
log_e("CRC16 check failed, resetting to default\r\n");
|
||||
this->ResetToDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// All checks passed, valid config, copy the data to the object.
|
||||
memcpy(&Config, memBytes, sizeof(T));
|
||||
|
||||
// Close the preferences
|
||||
pref.end();
|
||||
|
||||
// Indicate the config is valid
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
// Indicates the Config data object is valid.
|
||||
template <class T>
|
||||
bool PersistSettings<T>::Valid(void){ return mValid; }
|
||||
|
||||
// Resets the Config object to the default value and provided during the
|
||||
// construction of the PersistSettings object and writes those values to
|
||||
// the persistent storage.
|
||||
template <class T>
|
||||
void PersistSettings<T>::ResetToDefault(void){
|
||||
T newConfig;
|
||||
Config = newConfig;
|
||||
this->Write();
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
// Write the current values of the Config object to persistent storage.
|
||||
template <class T>
|
||||
void PersistSettings<T>::Write(void){
|
||||
Preferences pref;
|
||||
|
||||
// Setup the preferences namespace, as read only
|
||||
pref.begin("PersistSettings", false);
|
||||
|
||||
// Save the version
|
||||
pref.putUInt("version", mConfigVersion);
|
||||
|
||||
// Save the config, as a byte array, with 2-byte CRC on the end.
|
||||
byte memBytes[sizeof(T)+2];
|
||||
memcpy(memBytes, &Config, sizeof(T));
|
||||
uint16_t crc = CRC16(memBytes, sizeof(T));
|
||||
memBytes[sizeof(T)] = static_cast<byte>((crc&0xFF));
|
||||
memBytes[sizeof(T)+1] = static_cast<byte>((crc>>8));
|
||||
pref.putBytes("config", memBytes, sizeof(T)+2);
|
||||
|
||||
// Close the preferences
|
||||
pref.end();
|
||||
}
|
||||
|
||||
// Calculate the CRC16 over the provided data object (byte array) and
|
||||
// return the value.
|
||||
template <class T>
|
||||
uint16_t PersistSettings<T>::CRC16(byte *data, size_t data_len){
|
||||
uint16_t crc = 0xFFFF;
|
||||
for(unsigned int i = 0; i < data_len; i++){
|
||||
crc ^= data[i];
|
||||
for(unsigned char k = 0; k<8; ++k){
|
||||
if(crc & 1) crc = (crc >> 1) ^ 0x8005;
|
||||
else crc>>=1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
#include <ESPmDNS.h>
|
||||
#include <EEPROM.h>
|
||||
#include <WiFiManager.h>
|
||||
#include <Arduino_JSON.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include "WiFi.h"
|
||||
#include "ESPAsyncWebServer.h"
|
||||
#include "LittleFS.h"
|
||||
#include "include/PersistSettings.h"
|
||||
#include "config_winfidel.h"
|
||||
|
||||
WiFiManager wifiManager;
|
||||
AsyncWebServer server(80);
|
||||
volatile int WiFi_status = WL_IDLE_STATUS;
|
||||
const char mdnsName[] = MDNS_NAME;
|
||||
const char wifiName[] = WIFI_HOSTNAME;
|
||||
uint8_t dbgOTApercent = 100;
|
||||
|
||||
void setup()
|
||||
{
|
||||
// Configure Serial communication
|
||||
Serial.begin(115200);
|
||||
Serial.println("Wireless Inline Filament Estimator, Low-Cost - WInFiDEL");
|
||||
WiFi.setHostname(wifiName);
|
||||
|
||||
// wifiManager.resetSettings(); // Wipe WiFi settings. Uncomment for WiFi manager testing
|
||||
|
||||
delay(500);
|
||||
|
||||
bool res;
|
||||
res = wifiManager.autoConnect("SK-WInFiDEL-Setup", "letsrock");
|
||||
|
||||
if(!res) {
|
||||
Serial.println("Failed to connect or hit timeout");
|
||||
ESP.restart();
|
||||
}
|
||||
else {
|
||||
//if you get here you have connected to the WiFi
|
||||
Serial.println("Connected.");
|
||||
}
|
||||
|
||||
// Initialize LittleFS
|
||||
Serial.print("Starting LittleFS...");
|
||||
if(!LittleFS.begin()){
|
||||
Serial.println("An Error has occurred while mounting LittleFS");
|
||||
return;
|
||||
}
|
||||
Serial.println("done.");
|
||||
|
||||
Serial.print("WiFi IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
if (!MDNS.begin(mdnsName))
|
||||
{
|
||||
Serial.println("Error starting mDNS");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println((String) "mDNS http://" + MDNS_NAME + ".local");
|
||||
}
|
||||
|
||||
// Add service to MDNS-SD
|
||||
MDNS.addService("http", "tcp", 80);
|
||||
|
||||
EEPROM.begin(sizeof(calibration_t));
|
||||
calibration_init();
|
||||
|
||||
adc_init();
|
||||
|
||||
Serial.print("Starting WebServer...");
|
||||
setupWebServer();
|
||||
server.begin();
|
||||
Serial.println("done.");
|
||||
|
||||
Serial.print("WiFi IP: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
/**
|
||||
* Enable OTA update
|
||||
*/
|
||||
ArduinoOTA
|
||||
.onStart([]() {
|
||||
String type;
|
||||
if (ArduinoOTA.getCommand() == U_FLASH)
|
||||
type = "sketch";
|
||||
else // U_SPIFFS
|
||||
type = "filesystem";
|
||||
|
||||
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
|
||||
Serial.println("Start updating " + type);
|
||||
})
|
||||
.onEnd([]() {
|
||||
Serial.println("\nEnd");
|
||||
})
|
||||
.onProgress([](unsigned int progress, unsigned int total) {
|
||||
uint8_t percent = (progress / (total / 100));
|
||||
if (percent == dbgOTApercent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if ((percent%5) == 0)
|
||||
{
|
||||
Serial.printf("Progress: %u%%\r", percent);
|
||||
dbgOTApercent = percent;
|
||||
}
|
||||
})
|
||||
.onError([](ota_error_t error) {
|
||||
Serial.printf("Error[%u]: ", error);
|
||||
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
||||
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
||||
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
||||
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
||||
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
Serial.println("Arduino OTA is on");
|
||||
|
||||
// Debug message to signal we are initialized and entering loop
|
||||
Serial.println("Ready to go.");
|
||||
|
||||
i2c_scan_bus();
|
||||
}
|
||||
|
||||
|
||||
void loop()
|
||||
{
|
||||
Measurements_Tick();
|
||||
ArduinoOTA.handle();
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
float gReadingMax = 0.0; // Holds maximum reading
|
||||
float gReadingMin = 99999.9; // Holds minimum reading
|
||||
float gReadingAvg = 0.0; // Holds average reading
|
||||
float gReadingLast = 0.0; // Holds value of last reading
|
||||
uint32_t nLastADC = 0; // Last sampled ADC value
|
||||
uint32_t numMeasurements = 0; // Counts how many readings we had
|
||||
uint32_t nNextMeasurementTick = 0; // When next measurement should occur
|
||||
|
||||
|
||||
uint32_t adc_sample(void)
|
||||
{
|
||||
return random(512, 520);
|
||||
}
|
||||
|
||||
uint32_t adc_sample_RNG(void)
|
||||
{
|
||||
return random(470, 780);
|
||||
}
|
||||
|
||||
float get_last(void)
|
||||
{
|
||||
return gReadingLast;
|
||||
}
|
||||
float get_min(void)
|
||||
{
|
||||
return gReadingMin;
|
||||
}
|
||||
float get_max(void)
|
||||
{
|
||||
return gReadingMax;
|
||||
}
|
||||
float get_avg(void)
|
||||
{
|
||||
return gReadingAvg;
|
||||
}
|
||||
uint32_t get_adc(void)
|
||||
{
|
||||
return nLastADC;
|
||||
}
|
||||
uint32_t get_measurements_count(void)
|
||||
{
|
||||
return numMeasurements;
|
||||
}
|
||||
|
||||
void reset_stats(void)
|
||||
{
|
||||
gReadingMax = 0.0;
|
||||
gReadingMin = 99999.9;
|
||||
gReadingAvg = 0.0;
|
||||
numMeasurements = 0;
|
||||
}
|
||||
|
||||
|
||||
void Measurements_Tick(void)
|
||||
{
|
||||
if (millis() >= nNextMeasurementTick)
|
||||
{
|
||||
// Get latest measurement
|
||||
// nLastADC = adc_sample_RNG();
|
||||
|
||||
// Take `ADC_SAMPLES_PER_MEASUREMENT_CYCLE` number of ADC samples
|
||||
nLastADC = adc_sample_data(ADC_SAMPLES_PER_MEASUREMENT_CYCLE);
|
||||
|
||||
// Should we use mean or average (already calculated above)?
|
||||
#ifdef ADC_FINAL_ADC_VALUE_USING_MEAN
|
||||
// Use ADC mean
|
||||
nLastADC = adc_get_mean();
|
||||
#endif
|
||||
|
||||
if (nLastADC >= ADC_MAX)
|
||||
{
|
||||
Serial.print("Invalid ADC value of `");
|
||||
Serial.print(nLastADC);
|
||||
Serial.print("`. Clipping to `");
|
||||
Serial.print(ADC_MAX);
|
||||
Serial.println("`.");
|
||||
nLastADC = ADC_MAX;
|
||||
}
|
||||
|
||||
gReadingLast = adc_to_mm(nLastADC);
|
||||
|
||||
// Update average
|
||||
if (numMeasurements > 1)
|
||||
{
|
||||
gReadingAvg = (gReadingAvg + gReadingLast) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
gReadingAvg = gReadingLast;
|
||||
}
|
||||
|
||||
// Update min
|
||||
if (gReadingLast < gReadingMin)
|
||||
{
|
||||
gReadingMin = gReadingLast;
|
||||
}
|
||||
|
||||
// Update max
|
||||
if (gReadingLast > gReadingMax)
|
||||
{
|
||||
gReadingMax = gReadingLast;
|
||||
}
|
||||
|
||||
// Update reading counter
|
||||
numMeasurements++;
|
||||
|
||||
// Set next update timestamp
|
||||
nNextMeasurementTick = millis() + 200;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef __WINFIDEL_FW_VERSION_H__
|
||||
#define __WINFIDEL_FW_VERSION_H__
|
||||
|
||||
#define VERSION_MAJOR 0
|
||||
#define VERSION_MINOR 1
|
||||
#define VERSION_PATCH 0
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
Winfidel - Web
|
||||
Description: This file contains all the functions we use for receiving and responding to HTTP requests
|
||||
*/
|
||||
|
||||
#include "version.h"
|
||||
|
||||
char sensor_data[SENSOR_STR_MAX_LEN] = {0};
|
||||
|
||||
// Helper function that allows us to replace template variable in .html file
|
||||
// with a value from our code.
|
||||
String template_const_processor(const String& var)
|
||||
{
|
||||
if (var == "FW_VERSION") {
|
||||
return String(String(VERSION_MAJOR) + "." + String(VERSION_MINOR) + "." + String(VERSION_PATCH));
|
||||
}
|
||||
else if (var == "CALIBRATION_POINT_SAMPLE_COUNT")
|
||||
{
|
||||
return String(CALIBRATION_POINT_SAMPLE_COUNT);
|
||||
|
||||
}
|
||||
else if (var == "CALIBRATION_POINT_ACCURACY_POINT")
|
||||
{
|
||||
return String(CALIBRATION_POINT_ACCURACY_POINT);
|
||||
|
||||
}
|
||||
else if (var == "MAX_CALIBRATION_POINTS")
|
||||
{
|
||||
return String(MAX_CALIBRATION_POINTS);
|
||||
|
||||
}
|
||||
else if (var == "ADC_MIN")
|
||||
{
|
||||
return String(ADC_MIN);
|
||||
|
||||
}
|
||||
else if (var == "ADC_MIN_EQUALS_MM")
|
||||
{
|
||||
return String(ADC_MIN_EQUALS_MM);
|
||||
|
||||
}
|
||||
else if (var == "ADC_MAX")
|
||||
{
|
||||
return String(ADC_MAX);
|
||||
|
||||
}
|
||||
else if (var == "ADC_MAX_EQUALS_MM")
|
||||
{
|
||||
return String(ADC_MAX_EQUALS_MM);
|
||||
|
||||
}
|
||||
else if (var == "BUILD_DATE")
|
||||
{
|
||||
return String(__DATE__);
|
||||
|
||||
}
|
||||
else if (var == "BUILD_TIME")
|
||||
{
|
||||
return String(__TIME__);
|
||||
|
||||
}
|
||||
else if (var == "ADC_ALGO")
|
||||
{
|
||||
return adc_get_algo();
|
||||
}
|
||||
else if (var == "ADC_CHIP")
|
||||
{
|
||||
return adc_get_chip();
|
||||
}
|
||||
|
||||
Serial.print("Unknown template variable: ");
|
||||
Serial.println(var);
|
||||
return String();
|
||||
}
|
||||
|
||||
void setupWebServer(void)
|
||||
{
|
||||
server.onNotFound([](AsyncWebServerRequest *request) {
|
||||
Serial.println("404:");
|
||||
Serial.println(request->url());
|
||||
request->send(404);
|
||||
});
|
||||
|
||||
// send a file when /index is requested
|
||||
server.on("/index.html", HTTP_ANY, [](AsyncWebServerRequest *request){
|
||||
request->send(LittleFS, "/index.html", "text/html", false, template_const_processor);
|
||||
});
|
||||
|
||||
server.on("/settings.html", HTTP_ANY, [](AsyncWebServerRequest *request){
|
||||
request->send(LittleFS, "/settings.html", "text/html", false, template_const_processor);
|
||||
});
|
||||
|
||||
server.on("/", HTTP_ANY, [](AsyncWebServerRequest *request) {
|
||||
request->send(LittleFS, "/index.html", "text/html", false, template_const_processor);
|
||||
});
|
||||
|
||||
server.serveStatic("/js/", LittleFS, "/js/");
|
||||
server.serveStatic("/css/", LittleFS, "/css/");
|
||||
server.serveStatic("/webfonts/", LittleFS, "/webfonts/");
|
||||
server.serveStatic("/favicon.png", LittleFS, "/favicon.png");
|
||||
server.serveStatic("/favicon.ico", LittleFS, "/favicon.ico");
|
||||
|
||||
server.on("/api/diameter/read", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
format_sensor_data();
|
||||
request->send(200, "application/json", sensor_data);
|
||||
});
|
||||
|
||||
server.on("/api/diameter/reset", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
reset_stats();
|
||||
request->send(200, "application/json", "{\"status\":\"ok\"}");
|
||||
});
|
||||
|
||||
server.on("/api/calibration/read", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
request->send(200, "application/json", get_calibration_json());
|
||||
});
|
||||
|
||||
server.on("/api/calibration/create", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
if ( request->hasParam("mm") )
|
||||
{
|
||||
winfidel_status_t status;
|
||||
bool adc_provided = false;
|
||||
float cal_mm = request->getParam("mm")->value().toFloat();
|
||||
uint32_t cal_adc = 0;
|
||||
|
||||
// Check if ADC count was provided
|
||||
if (request->hasParam("adc"))
|
||||
{
|
||||
adc_provided = true;
|
||||
cal_adc = request->getParam("adc")->value().toInt();
|
||||
}
|
||||
|
||||
if (adc_provided == false)
|
||||
{
|
||||
status = create_calibration_point(cal_mm);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = manually_create_calibration_point(cal_adc, cal_mm);
|
||||
}
|
||||
|
||||
if (status == WINFIDEL_OK)
|
||||
{
|
||||
request->send(200, "application/json", "{\"status\":\"ok\"}");
|
||||
}
|
||||
else if (status == WINFIDEL_NO_SPACE)
|
||||
{
|
||||
request->send(500, "application/json", "{\"status\":\"fail\", \"message\": \"Maximum number of calibration points reached!\"}");
|
||||
}
|
||||
else if (status == WINFIDEL_LOW_ACCURACY)
|
||||
{
|
||||
request->send(500, "application/json", "{\"status\":\"fail\", \"message\": \"ADC failed to produce samples with sufficient accuracy!\"}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
request->send(400, "application/json", "{\"status\":\"fail\", \"message\": \"Missing argument `mm`!\"}");
|
||||
}
|
||||
});
|
||||
|
||||
server.on("/api/calibration/remove", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
if ( request->hasParam("mm") )
|
||||
{
|
||||
winfidel_status_t status;
|
||||
float rem_mm = request->getParam("mm")->value().toFloat();
|
||||
status = remove_calibration_point_mm(rem_mm);
|
||||
if (status == WINFIDEL_OK)
|
||||
{
|
||||
request->send(200, "application/json", "{\"status\":\"ok\"}");
|
||||
}
|
||||
else if (status == WINFIDEL_MISSING)
|
||||
{
|
||||
request->send(500, "application/json", "{\"status\":\"fail\", \"message\": \"Could not find calibration point!\"}");
|
||||
}
|
||||
else if (status == WINFIDEL_FORBIDDEN)
|
||||
{
|
||||
request->send(403, "application/json", "{\"status\":\"fail\", \"message\": \"Can not remove boundary points!\"}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
request->send(400, "application/json", "{\"status\":\"fail\", \"message\": \"Missing argument `mm`!\"}");
|
||||
}
|
||||
});
|
||||
|
||||
server.on("/api/calibration/reset", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
if ( request->hasParam("confirm") )
|
||||
{
|
||||
calibration_reset();
|
||||
request->send(200, "application/json", "{\"status\":\"ok\"}");
|
||||
}
|
||||
else
|
||||
{
|
||||
request->send(400, "application/json", "{\"status\":\"fail\", \"message\": \"Missing argument `confirm`!\"}");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
server.on("/api/wifi/reset", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
if ( request->hasParam("confirm") )
|
||||
{
|
||||
Serial.println("WiFi reset request recevied.");
|
||||
request->send(200, "application/json", "{\"status\":\"ok\", \"message\": \"WiFi configuration has been reset. Please connect to WInFiDEL WiFi and re-configure the device.\"}");
|
||||
wifiManager.resetSettings();
|
||||
}
|
||||
else
|
||||
{
|
||||
request->send(400, "application/json", "{\"status\":\"fail\", \"message\": \"Missing argument `confirm`!\"}");
|
||||
}
|
||||
});
|
||||
|
||||
server.on("/api/device/reboot", HTTP_GET, [] (AsyncWebServerRequest *request) {
|
||||
if ( request->hasParam("confirm") )
|
||||
{
|
||||
Serial.println("Device reboot request recevied. Rebooting...");
|
||||
ESP.restart();
|
||||
}
|
||||
else
|
||||
{
|
||||
request->send(400, "application/json", "{\"status\":\"fail\", \"message\": \"Missing argument `confirm`!\"}");
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
void format_sensor_data(void)
|
||||
{
|
||||
snprintf(sensor_data, SENSOR_STR_MAX_LEN, "{\"status\":\"ok\",\"data\":{\"diameter\":%.2f,\"min\":%.2f,\"max\":%.2f,\"avg\":%.2f,\"adc\":%d,\"count\":%d}}",
|
||||
get_last(), get_min(), get_max(), get_avg(), get_adc(), get_measurements_count());
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
BIN
Binary file not shown.
+74
@@ -0,0 +1,74 @@
|
||||
M48
|
||||
;Layer_Color=9474304
|
||||
;FILE_FORMAT=4:4
|
||||
METRIC,LZ
|
||||
;TYPE=PLATED
|
||||
T01F00S00C0.4000
|
||||
T02F00S00C0.6000
|
||||
T04F00S00C0.9000
|
||||
;TYPE=NON_PLATED
|
||||
T05F00S00C0.6500
|
||||
T06F00S00C3.1000
|
||||
%
|
||||
T01
|
||||
X00374Y00114
|
||||
X00408Y00116
|
||||
X00419Y00083
|
||||
X00467
|
||||
X00442Y00131
|
||||
X00331375Y0011
|
||||
X00263Y00147
|
||||
X00244Y00137
|
||||
X00245Y00162
|
||||
X00228375
|
||||
X00228875Y00188
|
||||
X002455
|
||||
X0021225
|
||||
X00195625
|
||||
X00179
|
||||
Y00153
|
||||
X00202771
|
||||
X00202Y00132
|
||||
X00192Y00125
|
||||
X0016295Y0013195
|
||||
X00144Y00109
|
||||
X00121Y001199
|
||||
X00098Y00112
|
||||
X00101541Y00096
|
||||
X00076
|
||||
X001025Y000629
|
||||
Y000471
|
||||
X00132Y00058
|
||||
Y00068
|
||||
X00157Y00063
|
||||
Y00074
|
||||
X00168
|
||||
X00179
|
||||
Y00063
|
||||
X00168
|
||||
Y00052
|
||||
X00157
|
||||
X00179
|
||||
X00199Y00035
|
||||
X00241Y00037
|
||||
X00264Y00035
|
||||
X002294Y0006
|
||||
X00174Y00009
|
||||
X00141Y00035
|
||||
T02
|
||||
X001524Y00170099
|
||||
X001651
|
||||
X001778
|
||||
T04
|
||||
X003762Y00183
|
||||
X004016
|
||||
X00427
|
||||
X004524
|
||||
X004778
|
||||
T05
|
||||
X004141Y000628
|
||||
X004719
|
||||
T06
|
||||
X00043Y00153
|
||||
X00331Y00048
|
||||
M30
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
M48
|
||||
;Layer_Color=9474304
|
||||
;FILE_FORMAT=4:4
|
||||
METRIC,LZ
|
||||
;TYPE=PLATED
|
||||
T03F00S00C0.6000
|
||||
;TYPE=NON_PLATED
|
||||
%
|
||||
G90
|
||||
G05
|
||||
T03
|
||||
G00X003998Y00022
|
||||
M15
|
||||
G01Y0003
|
||||
M16
|
||||
G00X003998Y000623
|
||||
M15
|
||||
G01Y000733
|
||||
M16
|
||||
G00X004862Y000623
|
||||
M15
|
||||
G01Y000733
|
||||
M16
|
||||
G00X004862Y00022
|
||||
M15
|
||||
G01Y0003
|
||||
M16
|
||||
M17
|
||||
M30
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
----------------------------------------------------------------------------------------------------------------------------------
|
||||
NCDrill File Report For: ESP_Infidel_PCB.PcbDoc 2023-12-31 02:15:29
|
||||
----------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Layer Pair : Top Layer to Bottom Layer
|
||||
ASCII RoundHoles File : ESP_Infidel_PCB-RoundHoles.TXT
|
||||
ASCII SlotHoles File : ESP_Infidel_PCB-SlotHoles.TXT
|
||||
|
||||
Tool Hole Size Hole Tolerance Hole Type Hole Count Plated Tool Travel
|
||||
----------------------------------------------------------------------------------------------------------------------------------
|
||||
T1 0.4mm (16mil) Round 44 PTH 125.24mm (4.93inch)
|
||||
T2 0.6mm (24mil) Round 3 PTH 2.54mm (0.10inch)
|
||||
T3 0.6mm (24mil) Slot 4 PTH 38.17mm (1.50inch)
|
||||
T4 0.9mm (35mil) Round 5 PTH 10.16mm (0.40inch)
|
||||
T5 0.65mm (26mil) Round 2 NPTH 5.78mm (0.23inch)
|
||||
T6 3.1mm (122mil) Round 2 NPTH 30.65mm (1.21inch)
|
||||
----------------------------------------------------------------------------------------------------------------------------------
|
||||
Totals 60
|
||||
|
||||
Total Processing Time (hh:mm:ss) : 00:00:00
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
------------------------------------------------------------------------------------------
|
||||
Gerber File Extension Report For: ESP_Infidel_PCB.GBR 2023-12-31 02:15:34
|
||||
------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
------------------------------------------------------------------------------------------
|
||||
Layer Extension Layer Description
|
||||
------------------------------------------------------------------------------------------
|
||||
.GTO Top Overlay
|
||||
.GTP Top Paste
|
||||
.GTS Top Solder
|
||||
.GTL Top Layer
|
||||
.G1 Layer 1
|
||||
.G2 Layer 2
|
||||
.GBL Bottom Layer
|
||||
.GBS Bottom Solder
|
||||
.GBP Bottom Paste
|
||||
.GBO Bottom Overlay
|
||||
.GM2 Route Tool Path
|
||||
.GD1 Drill Drawing
|
||||
.GM Profile
|
||||
------------------------------------------------------------------------------------------
|
||||
+1624
File diff suppressed because it is too large
Load Diff
+1004
File diff suppressed because it is too large
Load Diff
+1748
File diff suppressed because it is too large
Load Diff
+23848
File diff suppressed because it is too large
Load Diff
+16
@@ -0,0 +1,16 @@
|
||||
G04*
|
||||
G04 #@! TF.GenerationSoftware,Altium Limited,Altium Designer,24.0.1 (36)*
|
||||
G04*
|
||||
G04 Layer_Color=128*
|
||||
%FSLAX44Y44*%
|
||||
%MOMM*%
|
||||
G71*
|
||||
G04*
|
||||
G04 #@! TF.SameCoordinates,F64AAE0E-53C9-4E3E-96B2-16B86AA6748B*
|
||||
G04*
|
||||
G04*
|
||||
G04 #@! TF.FilePolarity,Positive*
|
||||
G04*
|
||||
G01*
|
||||
G75*
|
||||
M02*
|
||||
+1915
File diff suppressed because it is too large
Load Diff
+8587
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
G04*
|
||||
G04 #@! TF.GenerationSoftware,Altium Limited,Altium Designer,24.0.1 (36)*
|
||||
G04*
|
||||
G04 Layer_Color=0*
|
||||
%FSLAX44Y44*%
|
||||
%MOMM*%
|
||||
G71*
|
||||
G04*
|
||||
G04 #@! TF.SameCoordinates,F64AAE0E-53C9-4E3E-96B2-16B86AA6748B*
|
||||
G04*
|
||||
G04*
|
||||
G04 #@! TF.FilePolarity,Positive*
|
||||
G04*
|
||||
G01*
|
||||
G75*
|
||||
%ADD73C,0.0254*%
|
||||
D73*
|
||||
X8602Y0D02*
|
||||
G02*
|
||||
X0Y8602I0J8602D01*
|
||||
G01*
|
||||
Y191397D01*
|
||||
D02*
|
||||
G02*
|
||||
X8602Y200000I8602J0D01*
|
||||
G01*
|
||||
X491397D01*
|
||||
D02*
|
||||
G02*
|
||||
X499999Y191397I0J-8602D01*
|
||||
G01*
|
||||
Y8602D01*
|
||||
D02*
|
||||
G02*
|
||||
X491397Y0I-8602J0D01*
|
||||
G01*
|
||||
X8602D01*
|
||||
M02*
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
G04*
|
||||
G04 #@! TF.GenerationSoftware,Altium Limited,Altium Designer,24.0.1 (36)*
|
||||
G04*
|
||||
G04 Layer_Color=10066329*
|
||||
%FSLAX44Y44*%
|
||||
%MOMM*%
|
||||
G71*
|
||||
G04*
|
||||
G04 #@! TF.SameCoordinates,F64AAE0E-53C9-4E3E-96B2-16B86AA6748B*
|
||||
G04*
|
||||
G04*
|
||||
G04 #@! TF.FilePolarity,Positive*
|
||||
G04*
|
||||
G01*
|
||||
G75*
|
||||
M02*
|
||||
+2226
File diff suppressed because it is too large
Load Diff
+24217
File diff suppressed because it is too large
Load Diff
+308
@@ -0,0 +1,308 @@
|
||||
G04*
|
||||
G04 #@! TF.GenerationSoftware,Altium Limited,Altium Designer,24.0.1 (36)*
|
||||
G04*
|
||||
G04 Layer_Color=8421504*
|
||||
%FSLAX44Y44*%
|
||||
%MOMM*%
|
||||
G71*
|
||||
G04*
|
||||
G04 #@! TF.SameCoordinates,F64AAE0E-53C9-4E3E-96B2-16B86AA6748B*
|
||||
G04*
|
||||
G04*
|
||||
G04 #@! TF.FilePolarity,Positive*
|
||||
G04*
|
||||
G01*
|
||||
G75*
|
||||
%ADD18R,0.6000X1.1000*%
|
||||
%ADD19R,0.7000X0.9000*%
|
||||
%ADD20R,0.3500X0.3500*%
|
||||
%ADD21R,1.3000X1.0000*%
|
||||
%ADD22R,0.9000X0.7000*%
|
||||
%ADD23R,0.6000X1.1000*%
|
||||
%ADD24O,0.7500X0.2500*%
|
||||
%ADD25O,0.2500X0.7500*%
|
||||
%ADD26R,3.5000X3.8000*%
|
||||
%ADD27R,1.6000X0.9000*%
|
||||
%ADD28R,0.3500X0.3500*%
|
||||
%ADD29R,0.7500X0.8500*%
|
||||
%ADD30R,1.8000X0.4000*%
|
||||
%ADD31R,0.3000X1.1500*%
|
||||
%ADD32R,0.6000X1.1500*%
|
||||
D18*
|
||||
X254500Y176750D02*
|
||||
D03*
|
||||
X245000D02*
|
||||
D03*
|
||||
X235500D02*
|
||||
D03*
|
||||
Y148250D02*
|
||||
D03*
|
||||
X254500D02*
|
||||
D03*
|
||||
D19*
|
||||
X202100Y176500D02*
|
||||
D03*
|
||||
X217900D02*
|
||||
D03*
|
||||
X202100Y161500D02*
|
||||
D03*
|
||||
X217900D02*
|
||||
D03*
|
||||
X285600Y132500D02*
|
||||
D03*
|
||||
X301400D02*
|
||||
D03*
|
||||
Y117500D02*
|
||||
D03*
|
||||
X285600D02*
|
||||
D03*
|
||||
X229400Y52500D02*
|
||||
D03*
|
||||
X213600D02*
|
||||
D03*
|
||||
X214100Y37000D02*
|
||||
D03*
|
||||
X229900D02*
|
||||
D03*
|
||||
X213600Y82500D02*
|
||||
D03*
|
||||
X229400D02*
|
||||
D03*
|
||||
X213600Y67500D02*
|
||||
D03*
|
||||
X229400D02*
|
||||
D03*
|
||||
X164900Y141000D02*
|
||||
D03*
|
||||
X149100D02*
|
||||
D03*
|
||||
D20*
|
||||
X85358Y81313D02*
|
||||
D03*
|
||||
X91858D02*
|
||||
D03*
|
||||
D21*
|
||||
X349000Y112300D02*
|
||||
D03*
|
||||
Y131700D02*
|
||||
D03*
|
||||
X467000Y112800D02*
|
||||
D03*
|
||||
Y132200D02*
|
||||
D03*
|
||||
D22*
|
||||
X366500Y114600D02*
|
||||
D03*
|
||||
Y130400D02*
|
||||
D03*
|
||||
X381500Y114600D02*
|
||||
D03*
|
||||
Y130400D02*
|
||||
D03*
|
||||
X449500Y130400D02*
|
||||
D03*
|
||||
Y114600D02*
|
||||
D03*
|
||||
X434500Y130400D02*
|
||||
D03*
|
||||
Y114600D02*
|
||||
D03*
|
||||
X110000Y47100D02*
|
||||
D03*
|
||||
Y62900D02*
|
||||
D03*
|
||||
X80000Y47100D02*
|
||||
D03*
|
||||
Y62900D02*
|
||||
D03*
|
||||
X95000Y47100D02*
|
||||
D03*
|
||||
Y62900D02*
|
||||
D03*
|
||||
X303000Y170400D02*
|
||||
D03*
|
||||
Y154600D02*
|
||||
D03*
|
||||
X288000Y170400D02*
|
||||
D03*
|
||||
Y154600D02*
|
||||
D03*
|
||||
X272500Y154600D02*
|
||||
D03*
|
||||
Y170400D02*
|
||||
D03*
|
||||
X161000Y9600D02*
|
||||
D03*
|
||||
Y25400D02*
|
||||
D03*
|
||||
X130500Y9600D02*
|
||||
D03*
|
||||
Y25400D02*
|
||||
D03*
|
||||
X145500Y9600D02*
|
||||
D03*
|
||||
Y25400D02*
|
||||
D03*
|
||||
X131000Y173900D02*
|
||||
D03*
|
||||
Y158100D02*
|
||||
D03*
|
||||
X178000Y115100D02*
|
||||
D03*
|
||||
Y130900D02*
|
||||
D03*
|
||||
X113500Y119900D02*
|
||||
D03*
|
||||
Y104100D02*
|
||||
D03*
|
||||
X128500D02*
|
||||
D03*
|
||||
Y119900D02*
|
||||
D03*
|
||||
X381000Y40900D02*
|
||||
D03*
|
||||
Y25100D02*
|
||||
D03*
|
||||
Y63100D02*
|
||||
D03*
|
||||
Y78900D02*
|
||||
D03*
|
||||
D23*
|
||||
X417602Y136500D02*
|
||||
D03*
|
||||
Y108500D02*
|
||||
D03*
|
||||
X408102D02*
|
||||
D03*
|
||||
X398602Y136500D02*
|
||||
D03*
|
||||
Y108500D02*
|
||||
D03*
|
||||
D24*
|
||||
X143500Y80500D02*
|
||||
D03*
|
||||
Y75500D02*
|
||||
D03*
|
||||
Y70500D02*
|
||||
D03*
|
||||
Y65500D02*
|
||||
D03*
|
||||
Y60500D02*
|
||||
D03*
|
||||
Y55500D02*
|
||||
D03*
|
||||
Y50500D02*
|
||||
D03*
|
||||
Y45500D02*
|
||||
D03*
|
||||
X192500D02*
|
||||
D03*
|
||||
Y50500D02*
|
||||
D03*
|
||||
Y55500D02*
|
||||
D03*
|
||||
Y60500D02*
|
||||
D03*
|
||||
Y65500D02*
|
||||
D03*
|
||||
Y70500D02*
|
||||
D03*
|
||||
Y75500D02*
|
||||
D03*
|
||||
Y80500D02*
|
||||
D03*
|
||||
D25*
|
||||
X150500Y38500D02*
|
||||
D03*
|
||||
X155500D02*
|
||||
D03*
|
||||
X160500D02*
|
||||
D03*
|
||||
X165500D02*
|
||||
D03*
|
||||
X170500D02*
|
||||
D03*
|
||||
X175500D02*
|
||||
D03*
|
||||
X180500D02*
|
||||
D03*
|
||||
X185500D02*
|
||||
D03*
|
||||
Y87500D02*
|
||||
D03*
|
||||
X180500D02*
|
||||
D03*
|
||||
X175500D02*
|
||||
D03*
|
||||
X170500D02*
|
||||
D03*
|
||||
X165500D02*
|
||||
D03*
|
||||
X160500D02*
|
||||
D03*
|
||||
X155500D02*
|
||||
D03*
|
||||
X150500D02*
|
||||
D03*
|
||||
D26*
|
||||
X168000Y63000D02*
|
||||
D03*
|
||||
D27*
|
||||
X263000Y10000D02*
|
||||
D03*
|
||||
Y51000D02*
|
||||
D03*
|
||||
Y64500D02*
|
||||
D03*
|
||||
Y105500D02*
|
||||
D03*
|
||||
D28*
|
||||
X101541Y81301D02*
|
||||
D03*
|
||||
Y87801D02*
|
||||
D03*
|
||||
X76000Y81301D02*
|
||||
D03*
|
||||
Y87801D02*
|
||||
D03*
|
||||
D29*
|
||||
X151750Y109250D02*
|
||||
D03*
|
||||
X162250D02*
|
||||
D03*
|
||||
X151750Y122750D02*
|
||||
D03*
|
||||
X162250D02*
|
||||
D03*
|
||||
D30*
|
||||
X20500Y50000D02*
|
||||
D03*
|
||||
Y81000D02*
|
||||
D03*
|
||||
D31*
|
||||
X425500Y73550D02*
|
||||
D03*
|
||||
X430500D02*
|
||||
D03*
|
||||
X435500D02*
|
||||
D03*
|
||||
X460500D02*
|
||||
D03*
|
||||
X455500D02*
|
||||
D03*
|
||||
X450500D02*
|
||||
D03*
|
||||
X440500D02*
|
||||
D03*
|
||||
X445500D02*
|
||||
D03*
|
||||
D32*
|
||||
X467000D02*
|
||||
D03*
|
||||
X419000D02*
|
||||
D03*
|
||||
X475000D02*
|
||||
D03*
|
||||
X411000D02*
|
||||
D03*
|
||||
M02*
|
||||
+1716
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
Layer Pairs Export File for PCB: C:\Users\Sasa\Desktop\git\_shop\ESP-Infidel\ESP_Infidel_PCB.PcbDoc
|
||||
LayersSetName=Top_Bot_Thru_Holes|DrillFile=esp_infidel_pcb-roundholes.txt|DrillLayers=gtl,g1,g2,gbl
|
||||
LayersSetName=Top_Bot_Slot_Holes|DrillFile=esp_infidel_pcb-slotholes.txt|DrillLayers=gtl,g1,g2,gbl
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
D10 ROUNDED 9.842 9.842 0.000 LINE 0.000
|
||||
D11 ROUNDED 7.874 7.874 0.000 LINE 0.000
|
||||
D12 ROUNDED 11.811 11.811 0.000 LINE 0.000
|
||||
D13 ROUNDED 8.000 8.000 0.000 LINE 0.000
|
||||
D14 ROUNDED 7.000 7.000 0.000 LINE 0.000
|
||||
D15 ROUNDED 10.000 10.000 0.000 LINE 0.000
|
||||
D16 ROUNDED 5.906 5.906 0.000 LINE 0.000
|
||||
D17 ROUNDED 3.937 3.937 0.000 LINE 0.000
|
||||
D18 RECTANGULAR 23.622 43.307 0.000 FLASH 0.000
|
||||
D19 RECTANGULAR 27.559 35.433 0.000 FLASH 0.000
|
||||
D20 RECTANGULAR 13.780 13.780 0.000 FLASH 90.000
|
||||
D21 RECTANGULAR 39.370 51.181 0.000 FLASH 90.000
|
||||
D22 RECTANGULAR 27.559 35.433 0.000 FLASH 90.000
|
||||
D23 RECTANGULAR 43.307 23.622 0.000 FLASH 90.000
|
||||
D24 ROUNDED 9.842 29.528 0.000 FLASH 90.000
|
||||
D25 ROUNDED 9.842 29.528 0.000 FLASH 0.000
|
||||
D26 RECTANGULAR 137.795 149.606 0.000 FLASH 0.000
|
||||
D27 RECTANGULAR 35.433 62.992 0.000 FLASH 90.000
|
||||
D28 RECTANGULAR 13.780 13.780 0.000 FLASH 0.000
|
||||
D29 RECTANGULAR 33.465 29.528 0.000 FLASH 270.000
|
||||
D30 RECTANGULAR 70.866 15.748 0.000 FLASH 180.000
|
||||
D31 RECTANGULAR 11.811 45.276 0.000 FLASH 0.000
|
||||
D32 RECTANGULAR 23.622 45.276 0.000 FLASH 0.000
|
||||
D33 RECTANGULAR 31.622 51.307 0.000 FLASH 0.000
|
||||
D34 RECTANGULAR 35.559 43.433 0.000 FLASH 0.000
|
||||
D35 RECTANGULAR 21.779 21.779 0.000 FLASH 90.000
|
||||
D36 RECTANGULAR 47.370 59.181 0.000 FLASH 90.000
|
||||
D37 RECTANGULAR 35.559 43.433 0.000 FLASH 90.000
|
||||
D38 RECTANGULAR 51.307 31.622 0.000 FLASH 90.000
|
||||
D39 ROUNDED 17.843 37.528 0.000 FLASH 90.000
|
||||
D40 ROUNDED 17.843 37.528 0.000 FLASH 0.000
|
||||
D41 RECTANGULAR 145.795 157.606 0.000 FLASH 0.000
|
||||
D42 RECTANGULAR 43.433 70.992 0.000 FLASH 90.000
|
||||
D43 RECTANGULAR 21.779 21.779 0.000 FLASH 0.000
|
||||
D44 RECTANGULAR 41.465 37.528 0.000 FLASH 270.000
|
||||
D45 RECTANGULAR 78.866 23.748 0.000 FLASH 180.000
|
||||
D46 RECTANGULAR 19.811 53.276 0.000 FLASH 0.000
|
||||
D47 RECTANGULAR 31.622 53.276 0.000 FLASH 0.000
|
||||
D48 RECTANGULAR 67.055 67.055 0.000 FLASH 180.000
|
||||
D49 ROUNDED 67.055 67.055 0.000 FLASH 0.000
|
||||
D50 ROUNDED 51.622 96.976 0.000 FLASH 0.000
|
||||
D51 ROUNDED 8.000 8.000 0.000 FLASH 0.000
|
||||
D52 ROUNDED 33.591 33.591 0.000 FLASH 0.000
|
||||
D53 ROUNDED 90.677 49.339 0.000 FLASH 90.000
|
||||
D54 ROUNDED 86.740 47.370 0.000 FLASH 90.000
|
||||
D55 ROUNDED 35.559 35.559 0.000 FLASH 0.000
|
||||
D56 ROUNDED 19.685 19.685 0.000 LINE 0.000
|
||||
D57 ROUNDED 7.512 7.512 0.000 LINE 0.000
|
||||
D58 RECTANGULAR 59.055 59.055 0.000 FLASH 180.000
|
||||
D59 ROUNDED 59.055 59.055 0.000 FLASH 0.000
|
||||
D60 ROUNDED 43.622 88.976 0.000 FLASH 0.000
|
||||
D61 ROUNDED 25.591 25.591 0.000 FLASH 0.000
|
||||
D62 ROUNDED 82.677 41.339 0.000 FLASH 90.000
|
||||
D63 ROUNDED 78.740 39.370 0.000 FLASH 90.000
|
||||
D64 ROUNDED 31.496 31.496 0.000 FLASH 0.000
|
||||
D65 ROUNDED 27.559 27.559 0.000 FLASH 0.000
|
||||
D66 ROUNDED 31.496 31.496 0.000 LINE 0.000
|
||||
D67 ROUNDED 4.724 4.724 0.000 LINE 0.000
|
||||
D68 ROUNDED 5.000 5.000 0.000 LINE 0.000
|
||||
D69 ROUNDED 15.000 15.000 0.000 LINE 0.000
|
||||
D70 ROUNDED 1.000 1.000 0.000 LINE 0.000
|
||||
D71 ROUNDED 16.000 16.000 0.000 LINE 0.000
|
||||
D72 ROUNDED 14.000 14.000 0.000 LINE 0.000
|
||||
D73 ROUNDED 1.000 1.000 0.000 LINE 0.000
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
Altium Designer Pick and Place Locations
|
||||
C:\Users\Sasa\Desktop\git\_shop\ESP-Infidel\Project Outputs for ESP_Infidel\Pick Place\Pick Place for ESP_Infidel_PCB.txt
|
||||
|
||||
========================================================================================================================
|
||||
File Design Information:
|
||||
|
||||
Date: 31-12-23
|
||||
Time: 02:15
|
||||
Revision: Not in VersionControl
|
||||
Variant: No variations
|
||||
Units used: mil
|
||||
|
||||
Designator Comment Layer Footprint Center-X(mil) Center-Y(mil) Rotation Description
|
||||
P2 "Header 5" TopLayer Header_5x1 1681.102mil 720.472mil 180 "Header, 5-Pin"
|
||||
R12 Res TopLayer 0603 826.772mil 694.882mil 0 Resistor
|
||||
C21 Cap TopLayer 0603_-_CAP 1072.835mil 639.764mil 90 Capacitor
|
||||
C20 Cap TopLayer 0603_-_CAP 826.772mil 635.827mil 0 Capacitor
|
||||
U4 MCP3021A5T-E/OT TopLayer SOT95P270X145-5N 964.567mil 639.764mil 270 "10 Bit Analog to Digital Converter 1 Input 1 SAR SOT-23-5"
|
||||
U3 DRV5055A2QLPGM BottomLayer SS490A 650.000mil 669.680mil 0 "Hall Effect Sensor Single Axis Radial Lead"
|
||||
U1 "IC REG LINEAR 3.3V 300MA SOT23-5" TopLayer SOT-23-5 1606.701mil 482.284mil 90 "600mA null 3.3V positive 6V SOT-25 Linear Voltage Regulators (LDO) ROHS"
|
||||
R10 Res TopLayer 0603 1133.858mil 639.764mil 270 Resistor
|
||||
R9 Res TopLayer 0603 1192.913mil 639.764mil 270 Resistor
|
||||
C22 Cap TopLayer 0603_-_CAP 515.748mil 653.543mil 90 Capacitor
|
||||
C6 Cap TopLayer 0805 1374.016mil 480.315mil 90 Capacitor
|
||||
C5 Cap TopLayer 0603_-_CAP 1442.913mil 482.284mil 90 Capacitor
|
||||
C4 Cap TopLayer 0603_-_CAP 1501.968mil 482.284mil 90 Capacitor
|
||||
C2 Cap TopLayer 0603_-_CAP 1710.630mil 482.284mil 270 Capacitor
|
||||
C3 Cap TopLayer 0603_-_CAP 1769.685mil 482.284mil 270 Capacitor
|
||||
C1 Cap TopLayer 0805 1838.582mil 482.284mil 270 Capacitor
|
||||
A1 ANT3216LL00R2400A TopLayer ANT3216LL00R2400A 80.709mil 257.874mil 270 "RF ANT 2.45GHZ CHIP SOLDER SMD"
|
||||
X1 40MHz TopLayer XTAL-4LEAD-2016 618.110mil 456.693mil 270 "40MHz 9pF ±10ppm SMD2016-4P Crystals ROHS"
|
||||
U2 ESP32-C3-FNH4 TopLayer QFN50P500X500X100_HS-33N 661.417mil 248.031mil 0 "Ultra-Low-Power SoC with RISC-V Single-Core CPU 2.4 GHz Wi-Fi (802.11 b/g/n) and Bluetooth® 5 (LE)"
|
||||
SW2 Switch TopLayer Switch-XDTD-0304-215 1035.433mil 334.646mil 90 "50mA Surface Mount SPST 100MO 100,000 Times 12V 160gf@±50gf SMD Tactile Switches ROHS"
|
||||
SW1 Switch TopLayer Switch-XDTD-0304-215 1035.433mil 120.079mil 270 "50mA Surface Mount SPST 100MO 100,000 Times 12V 160gf@±50gf SMD Tactile Switches ROHS"
|
||||
R11 Res TopLayer 0201i_0603m 348.849mil 320.128mil 0 Resistor
|
||||
R8 Res TopLayer 0603 513.779mil 68.898mil 90 Resistor
|
||||
R7 Res TopLayer 0603 572.835mil 68.898mil 90 Resistor
|
||||
R6 Res TopLayer 0603 874.016mil 145.669mil 0 Resistor
|
||||
R3 Res TopLayer 0603 1155.512mil 521.653mil 180 Resistor
|
||||
R2 Res TopLayer 0603 1500.000mil 129.921mil 270 Resistor
|
||||
R1 Res TopLayer 0603 1500.000mil 279.528mil 90 Resistor
|
||||
C19 Cap TopLayer 0603_-_CAP 700.787mil 484.252mil 270 Capacitor
|
||||
C18 Cap TopLayer 0603_-_CAP 618.110mil 555.118mil 0 Capacitor
|
||||
C17 Cap TopLayer 0603_-_CAP 446.851mil 440.945mil 270 Capacitor
|
||||
C16 Cap TopLayer 0603_-_CAP 505.906mil 440.945mil 270 Capacitor
|
||||
C15 Cap TopLayer 0603_-_CAP 314.961mil 216.536mil 90 Capacitor
|
||||
C14 Cap TopLayer 0603_-_CAP 374.016mil 216.536mil 90 Capacitor
|
||||
C13 Cap TopLayer 0603_-_CAP 433.071mil 216.536mil 90 Capacitor
|
||||
C12 Cap TopLayer 0603_-_CAP 872.047mil 206.693mil 180 Capacitor
|
||||
C11 Cap TopLayer 0603_-_CAP 633.858mil 68.898mil 90 Capacitor
|
||||
C10 Cap TopLayer 0603_-_CAP 872.047mil 324.803mil 180 Capacitor
|
||||
C9 Cap TopLayer 0603_-_CAP 872.047mil 265.748mil 180 Capacitor
|
||||
C8 Cap TopLayer 0201i_0603m 399.769mil 332.879mil 270 Capacitor
|
||||
C7 Cap TopLayer 0201i_0603m 299.213mil 332.879mil 270 Capacitor
|
||||
R4 Res TopLayer 0603 1155.512mil 462.598mil 180 Resistor
|
||||
P1 "USB-C Recepticle" TopLayer GCT_USB4105-GF-A 1744.094mil 195.964mil 0 "3A 1 Surface Mount 16P Female -25?~+85? Type-C SMD USB Connectors ROHS"
|
||||
Binary file not shown.
@@ -0,0 +1,33 @@
|
||||
# WInFiDEL Sensor
|
||||
|
||||
**W**ireless
|
||||
**In**line
|
||||
**Fi**lament
|
||||
**D**iameter
|
||||
**E**stimator
|
||||
**L**ow-cost
|
||||
Sensor
|
||||
|
||||
## What is WInFiDEL?
|
||||
|
||||
WInFiDEL is an DIY open-source open-hardware Wireless 3D printing filament diameter sensor.
|
||||
|
||||
This design is heavily inspired by the design previously published by Made with Layers (Thomas Sanladerer) (video: https://www.youtube.com/watch?v=RYgdLPe_T0c)
|
||||
|
||||
:soon: (WIP) Soon I will publish a video that goes into more details on how this sensor works and how you can build one.
|
||||
This repository will be updated with additional information as soon as that video goes live.
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Sasa Karanovic
|
||||
|
||||
<a href="https://sasakaranovic.com/" target="_blank" title="Sasa Karanovic Home Page"><img src="https://raw.githubusercontent.com/SasaKaranovic/common/master/assets/img_home.png" width="16"> Home Page</a> ·
|
||||
<a href="https://youtube.com/c/sasakaranovic" target="_blank" title="Sasa Karanovic on YouTube"><img src="https://raw.githubusercontent.com/SasaKaranovic/common/master/assets/img_youtube.png" width="16"> YouTube</a> ·
|
||||
<a href="https://github.com/sasakaranovic" target="_blank" title="Sasa Karanovic on GitHub"><img src="https://raw.githubusercontent.com/SasaKaranovic/common/master/assets/img_github.png" width="16"> GitHub</a> ·
|
||||
<a href="https://twitter.com/_sasakaranovic_" target="_blank" title="Sasa Karanovic on Twitter"><img src="https://raw.githubusercontent.com/SasaKaranovic/common/master/assets/img_twitter.png" width="16"> Twitter</a> ·
|
||||
<a href="https://instagram.com/_sasakaranovic_" target="_blank" title="Sasa Karanovic on Instagram"><img src="https://raw.githubusercontent.com/SasaKaranovic/common/master/assets/img_instagram.png" width="16"> Instagram</a> ·
|
||||
<a href="https://github.com/sponsors/SasaKaranovic" target="_blank" title="Sponsor on GitHub"><img src="https://raw.githubusercontent.com/SasaKaranovic/common/master/assets/img_github.png" width="16"> Sponsor on GitHub</a>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 97 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 184 KiB |
Reference in New Issue
Block a user