jomjol 5 年 前
コミット
37e17618d8

+ 17 - 1
README.md

@@ -1 +1,17 @@
-# AI-on-the-edge-device
+# AI-on-the-edge-device
+
+This is an example of Artificial Intelligence (AI) calculations on a very cheap hardware.
+
+Details can be found on the Wiki pages.
+
+## Changelog - lastest version
+
+##### 0.1.0 (2020-08-07)
+
+* Inital Version
+
+
+
+## Know-Bugs
+
+* spontaneous reboot, especially in case of intensive web server access

BIN
firmware/bootloader.bin


BIN
firmware/firmware.bin


BIN
firmware/partitions.bin


BIN
images/Flash_Settings.png


+ 0 - 0
sd-card/config/analog.tfl → sd-card/config/ana0622.tfl


+ 4 - 3
sd-card/config/config.ini

@@ -12,7 +12,7 @@ SearchFieldX = 20
 SearchFieldY = 20
 
 [Digits]
-Model=/config/digits.tfl
+Model=/config/dig0622.tfl
 ModelInputSize 20, 32
 LogImageLocation = /log/digit
 digit1, 291, 97, 37, 67
@@ -20,7 +20,7 @@ digit2, 344, 97, 37, 67
 digit3, 394, 97, 37, 67
 
 [Analog]
-Model=/config/analog.tfl
+Model=/config/ana0622.tfl
 ModelInputSize 32, 32
 LogImageLocation = /log/analog
 analog1, 433, 207, 99, 99
@@ -35,8 +35,9 @@ AllowNegativeRates = False
 MaxRateValue = 0.1
 ErrorMessage = True
 
+
 [AutoTimer]
-AutoStart= true
+AutoStart= True
 Intervall = 4.85
 
 [Ende]

+ 0 - 0
sd-card/config/digits.tfl → sd-card/config/dig0622.tfl


+ 127 - 0
sd-card/html/index.html

@@ -0,0 +1,127 @@
+<html><head>
+	<title>jomjol - AI on the edge</title>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<style type="text/css" media="screen">
+		nav > ul {
+			list-style: none;
+			margin: 0;
+			padding: 0;
+			display: flex;
+			flex-direction: column;
+		}
+		
+		nav li {
+			margin: 0.5em;
+			padding: 0;
+			font-size: 1.5em;
+			flex: 1 1 0%;
+		}
+		
+		@media (min-width: 45em) {
+			nav > ul {
+				flex-direction: row;
+			}
+			nav li {
+				flex: 1;
+				font-size: 1em;
+			}
+		}
+		
+		nav a {
+			display: block;
+			padding: 0.4em;
+			text-decoration: none;
+			font-weight: bold;
+			text-align: center;
+			border: 1px solid darkblue;
+			border-radius: 10px;
+			box-shadow: 0 5px 10px white inset;
+			color: gold;
+			background-color: darkblue;
+			transition: all .25s ease-in;
+		}
+		
+		nav li[aria-current] a {
+			background-color: firebrick;
+			color: gold;
+		}
+		
+		nav a:focus,
+		nav a:hover,
+		nav li[aria-current] a:focus,
+		nav li[aria-current] a:hover {
+			color: darkblue;
+			background-color: gold;
+		}
+		
+
+		html, body {
+			height:100%;
+			width:100%;
+			margin:0;
+		}
+		.h_iframe iframe {
+			width:100%;
+			height:100%;
+		}
+		.h_iframe {
+			height: 100%;
+			width:100%;
+		}
+	</style>
+	<script type="text/javascript">
+		//<![CDATA[
+		//]]>
+
+	</script>
+</head>
+
+<body>
+	<h1>AI on the edge - an integrated water meter example</h1>
+	<nav>
+		<ul>
+			<li aria-current="page"><a href="#"onclick="document.getElementById('maincontent').src = '/wasserzaehler_roi.html';">wasserzaehler</a>	
+				<ul class="submenu">
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/prevalue_set.html';">PreValue</a> </li>
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/wasserzaehler.html?full';">wasserzaehler full</a> </li>
+				</ul>
+			</li>	
+			 
+			<li><a href="#" onclick="document.getElementById('maincontent').src = '/fileserver/';">File Server</a> </li>			
+			<li><a href="#">Manuel Mode</a>
+				<ul class="submenu">
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/doinit';">Init</a> </li>
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/doflow';">Recognize</a> </li>
+				</ul>
+			</li>
+
+			<li><a href="#">Image</a>
+				<ul class="submenu">
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/img_tmp/raw.jpg';">Raw</a> </li>
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/img_tmp/rot.jpg';">Rotated</a> </li>
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/img_tmp/alg.jpg';">Aligned</a> </li>
+				</ul>
+			</li>
+			<li><a href="#">System</a>
+				<ul class="submenu">
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/starttime';">Start time</a> </li>
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/ota_page.html';">OTA Update</a> </li>
+					<li><a href="#"onclick="document.getElementById('maincontent').src = '/reboot_page.html';">Reboot</a> </li>
+				</ul>
+			</li>
+
+		</ul>
+	</nav>
+	
+	<p>
+	
+	<div class="h_iframe">
+		 <iframe name="maincontent" id ="maincontent" src="/wasserzaehler_roi.html" title="fileserver" allowfullscreen></iframe> 
+	</div>
+
+
+
+
+
+</body></html>

+ 129 - 0
sd-card/html/ota_page.html

@@ -0,0 +1,129 @@
+<html><head>
+	<title>jomjol - AI on the edge</title>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<script type="text/javascript">
+		//<![CDATA[
+		//]]>
+
+	</script>
+</head>
+
+<body>
+<table class="fixed" border="0">
+    <td>
+        <table border="0">
+            <tr>
+                <td>
+                    <label for="newfile">Upload the firmware.bin</label>
+                </td>
+                <td colspan="2">
+                    <input id="newfile" type="file" onchange="setpath()" style="width:100%;">
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    <label for="filepath">Set path on server</label>
+                </td>
+                <td>
+                    <input id="filepath" type="text" style="width:100%;" readonly>
+                </td>
+                <td>
+                    <button id="upload" type="button" onclick="upload()">Upload</button>
+                </td>
+            </tr>
+        </table>
+    </td></tr>
+	<tr>
+		<td>
+			<button id="upload" type="button" onclick="doUpdate()">Do Firmware Update</button>
+		</td>
+	</tr>
+</table>
+
+<script>
+function doUpdate() {
+	if (confirm("Are you sure to update the firmware?")) {
+		var stringota = "/ota?file=firmware.bin";
+		window.location = stringota;
+		window.location.href = stringota;
+		window.location.assign(stringota);
+		window.location.replace(stringota);
+	}
+}
+
+function setpath() {
+    var fileserverpraefix = "/firmware/firmware.bin";
+    document.getElementById("filepath").value = fileserverpraefix;
+}
+
+function upload() {
+	var xhttp = new XMLHttpRequest();
+	
+	/* first delete the old firmware */	
+	xhttp.onreadystatechange = function() {
+		if (xhttp.readyState == 4) {
+			if (xhttp.status == 200) {
+				/* keine Reaktion, damit sich das Dokument nicht ändert */
+			} else if (xhttp.status == 0) {
+				alert("Server closed the connection abruptly!");
+				location.reload()
+			} else {
+				alert(xhttp.status + " Error!\n" + xhttp.responseText);
+				location.reload()
+			}
+		}
+	};
+	xhttp.open("GET", "/ota?delete=firmware.bin", false);
+	xhttp.send();
+	/* ----------------------------- */
+	
+    var filePath = document.getElementById("filepath").value;
+    var upload_path = "/upload/" + filePath;
+    var fileInput = document.getElementById("newfile").files;
+
+    /* Max size of an individual file. Make sure this
+     * value is same as that set in file_server.c */
+    var MAX_FILE_SIZE = 2000*1024;
+    var MAX_FILE_SIZE_STR = "2000KB";
+
+    if (fileInput.length == 0) {
+        alert("No file selected!");
+    } else if (filePath.length == 0) {
+        alert("File path on server is not set!");
+    } else if (filePath.indexOf(' ') >= 0) {
+        alert("File path on server cannot have spaces!");
+    } else if (filePath[filePath.length-1] == '/') {
+        alert("File name not specified after path!");
+    } else if (fileInput[0].size > 2000*1024) {
+        alert("File size must be less than 2000KB!");
+    } else {
+        document.getElementById("newfile").disabled = true;
+        document.getElementById("filepath").disabled = true;
+        document.getElementById("upload").disabled = true;
+		
+        xhttp.onreadystatechange = function() {
+            if (xhttp.readyState == 4) {
+                if (xhttp.status == 200) {
+					alert("Upload successfull!")
+					document.reload();
+                } else if (xhttp.status == 0) {
+                    alert("Server closed the connection abruptly!");
+                    location.reload()
+                } else {
+                    alert(xhttp.status + " Error!\n" + xhttp.responseText);
+                    location.reload()
+                }
+            }
+        };
+		
+
+        var file = fileInput[0];
+        xhttp.open("POST", upload_path, true);
+        xhttp.send(file);
+    }
+}
+</script>
+
+
+</body></html>

+ 43 - 0
sd-card/html/prevalue_set.html

@@ -0,0 +1,43 @@
+<html><head>
+	<title>jomjol - AI on the edge</title>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<script type="text/javascript">
+		//<![CDATA[
+		//]]>
+
+	</script>
+</head>
+
+<body>
+<table  style="width:100%">
+  <tr>
+    Current Value:<p>
+	<iframe name="currentvalue" id ="currentvalue" src="/setPreValue.html" title="fileserver" allowfullscreen></iframe>
+  </tr>	 
+  <tr>
+    Input (Format = 123.456):<p>
+	PreValue: 
+	 <input type="number" id="myInput" name="myInput"
+           pattern="[0-9]+([\.,][0-9]+)?" step="0.001"
+            title="This should be a number with up to 4 decimal places.">
+	<button type="button" onclick="setprevalue()">Set PreValue</button>
+  </tr>	
+  <tr>
+    Result:<p>
+	<iframe name="maincontent" id ="maincontent" src="" title="fileserver" allowfullscreen></iframe>
+  </tr>	 
+
+</table>
+
+<script>
+function setprevalue() {
+	var inputVal = document.getElementById("myInput").value;
+	inputVal = inputVal.replace(",", ".");
+	_value = "/setPreValue.html?value="+inputVal;
+	document.getElementById('maincontent').src = _value;
+	location.reload();	
+}
+</script>
+
+</body></html>

+ 34 - 0
sd-card/html/reboot_page.html

@@ -0,0 +1,34 @@
+<html><head>
+	<title>jomjol - AI on the edge</title>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<script type="text/javascript">
+		//<![CDATA[
+		//]]>
+
+	</script>
+</head>
+
+<body>
+<table class="fixed" border="0">
+	<tr>
+		<td>
+			<button id="reboot" type="button" onclick="doReboot()">Reboot</button>
+		</td>
+	</tr>
+</table>
+
+<script>
+function doReboot() {
+	if (confirm("Are you sure you want to reboot the ESP32?")) {
+		var stringota = "/reboot";
+		window.location = stringota;
+		window.location.href = stringota;
+		window.location.assign(stringota);
+		window.location.replace(stringota);
+	}
+}
+</script>
+
+
+</body></html>

+ 101 - 0
sd-card/html/upload_script.html

@@ -0,0 +1,101 @@
+<table class="fixed" border="0">
+    <col width="300px" /><col width="200px" />
+    <tr><td>
+        <h2>ESP32 File Server</h2>
+    </td><td>
+        <button id="dirup" type="button" onclick="dirup()">Directory up</button>
+    </td>
+    <td>
+        <table border="0">
+            <tr>
+                <td>
+                    <label for="newfile">Upload a file</label>
+                </td>
+                <td colspan="2">
+                    <input id="newfile" type="file" onchange="setpath()" style="width:100%;">
+                </td>
+            </tr>
+            <tr>
+                <td>
+                    <label for="filepath">Set path on server</label>
+                </td>
+                <td>
+                    <input id="filepath" type="text" style="width:100%;">
+                </td>
+                <td>
+                    <button id="upload" type="button" onclick="upload()">Upload</button>
+                </td>
+            </tr>
+        </table>
+    </td></tr>
+</table>
+<script>
+function setpath() {
+    var fileserverpraefix = "/fileserver";
+    var anz_zeichen_fileserver = fileserverpraefix.length;
+    var default_path = window.location.pathname.substring(anz_zeichen_fileserver) + document.getElementById("newfile").files[0].name;
+    document.getElementById("filepath").value = default_path;
+}
+
+function dirup() {
+    var str = window.location.href;
+    str = str.substring(0, str.length-1);
+	var zw = str.indexOf("/");
+	var found = zw;
+	while (zw >= 0)
+	{
+		zw = str.indexOf("/", found+1);  
+		if (zw >= 0)
+			found = zw;
+	}
+	var res = str.substring(0, found+1);
+	window.location.href = res;	
+}
+
+function upload() {
+    var filePath = document.getElementById("filepath").value;
+    var upload_path = "/upload/" + filePath;
+    var fileInput = document.getElementById("newfile").files;
+
+    /* Max size of an individual file. Make sure this
+     * value is same as that set in file_server.c */
+    var MAX_FILE_SIZE = 2000*1024;
+    var MAX_FILE_SIZE_STR = "2000KB";
+
+    if (fileInput.length == 0) {
+        alert("No file selected!");
+    } else if (filePath.length == 0) {
+        alert("File path on server is not set!");
+    } else if (filePath.indexOf(' ') >= 0) {
+        alert("File path on server cannot have spaces!");
+    } else if (filePath[filePath.length-1] == '/') {
+        alert("File name not specified after path!");
+    } else if (fileInput[0].size > 2000*1024) {
+        alert("File size must be less than 2000KB!");
+    } else {
+        document.getElementById("newfile").disabled = true;
+        document.getElementById("filepath").disabled = true;
+        document.getElementById("upload").disabled = true;
+
+        var file = fileInput[0];
+        var xhttp = new XMLHttpRequest();
+        xhttp.onreadystatechange = function() {
+            if (xhttp.readyState == 4) {
+                if (xhttp.status == 200) {
+                    document.open();
+                    document.write(xhttp.responseText);
+                    document.close();
+                } else if (xhttp.status == 0) {
+                    alert("Server closed the connection abruptly!");
+                    location.reload()
+                } else {
+                    alert(xhttp.status + " Error!\n" + xhttp.responseText);
+                    location.reload()
+                }
+            }
+        };
+        xhttp.open("POST", upload_path, true);
+        xhttp.send(file);
+    }
+}
+</script>

+ 99 - 0
sd-card/html/wasserzaehler_roi.html

@@ -0,0 +1,99 @@
+<html><head>
+	<title>jomjol - AI on the edge</title>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, initial-scale=1">
+	<style type="text/css" media="screen">
+		nav > ul {
+			list-style: none;
+			margin: 0;
+			padding: 0;
+			display: flex;
+			flex-direction: column;
+		}
+		
+		nav li {
+			margin: 0.5em;
+			padding: 0;
+			font-size: 1.5em;
+			flex: 1 1 0%;
+		}
+		
+		@media (min-width: 45em) {
+			nav > ul {
+				flex-direction: row;
+			}
+			nav li {
+				flex: 1;
+				font-size: 1em;
+			}
+		}
+		
+		nav a {
+			display: block;
+			padding: 0.4em;
+			text-decoration: none;
+			font-weight: bold;
+			text-align: center;
+			border: 1px solid darkblue;
+			border-radius: 10px;
+			box-shadow: 0 5px 10px white inset;
+			color: gold;
+			background-color: darkblue;
+			transition: all .25s ease-in;
+		}
+		
+		nav li[aria-current] a {
+			background-color: firebrick;
+			color: gold;
+		}
+		
+		nav a:focus,
+		nav a:hover,
+		nav li[aria-current] a:focus,
+		nav li[aria-current] a:hover {
+			color: darkblue;
+			background-color: gold;
+		}
+		
+
+		html, body {
+			height:100%;
+			width:100%;
+			margin:0;
+		}
+		.h_iframe iframe {
+			width:100%;
+			height:100%;
+		}
+		.h_iframe {
+			height: 100%;
+			width:100%;
+		}
+	</style>
+	<script type="text/javascript">
+		//<![CDATA[
+		//]]>
+
+	</script>
+</head>
+
+<body>
+<table  style="width:100%">
+  <tr>
+    <td> <img src="/img_tmp/alg_roi.jpg" alt="ROI-Image"> </td>
+    <td>
+		<table>
+			<tr>
+				Raw Value:<p>
+				<iframe name="maincontent" id ="maincontent" src="/wasserzaehler.html?rawvalue=true" title="fileserver" allowfullscreen></iframe>
+			</tr>
+			<tr>
+				Corrected Value:<p>
+				<iframe name="maincontent" id ="maincontent" src="/wasserzaehler.html" title="fileserver" allowfullscreen></iframe>
+			</tr>
+		</table>
+	</td>
+  </tr>
+</table>
+
+</body></html>