Browse Source

For later design

master
Englebert 3 years ago
parent
commit
06d969220d
  1. 503
      OpenFlightRX.ino

503
OpenFlightRX.ino

@ -15,6 +15,12 @@
#include "Arduino.h"
#include <EEPROM.h>
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <Update.h>
// #define USE_SONAR
// #define DEBUG
@ -62,6 +68,313 @@
uint32_t nextWireUpdate = 0;
#endif
// Starting up Webserver
WebServer server(80);
/*** Firmware Upgrade Page ***/
const char* firmware_upgrade_html PROGMEM = R"rawliteral(
<script>
var iBytesUploaded = 0;
var iBytesTotal = 0;
var iPreviousBytesLoaded = 0;
var iMaxFilesize = 1048576; // 1MB
var oTimer = 0;
var sResultFileSize = '';
function secondsToTime(secs) {
var hr = Math.floor(secs / 3600);
var min = Math.floor((secs - (hr * 3600))/60);
var sec = Math.floor(secs - (hr * 3600) - (min * 60));
if (hr < 10) {hr = "0" + hr; }
if (min < 10) {min = "0" + min;}
if (sec < 10) {sec = "0" + sec;}
if (hr) {hr = "00";}
return hr + ':' + min + ':' + sec;
};
function bytesToSize(bytes) {
var sizes = ['Bytes', 'KB', 'MB'];
if (bytes == 0) return 'n/a';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
};
function fileSelected() {
document.getElementById('upload_response').style.display = 'none';
document.getElementById('error').style.display = 'none';
document.getElementById('error2').style.display = 'none';
document.getElementById('abort').style.display = 'none';
document.getElementById('warnsize').style.display = 'none';
var oFile = document.getElementById('image_file').files[0];
var rFilter = /^(image\/bmp|image\/gif|image\/jpeg|image\/png|image\/tiff)$/i;
if (! rFilter.test(oFile.type)) {
document.getElementById('error').style.display = 'block';
return;
}
if (oFile.size > iMaxFilesize) {
document.getElementById('warnsize').style.display = 'block';
return;
}
var oImage = document.getElementById('preview');
var oReader = new FileReader();
oReader.onload = function(e){
oImage.src = e.target.result;
oImage.onload = function () { // binding onload event
sResultFileSize = bytesToSize(oFile.size);
document.getElementById('fileinfo').style.display = 'block';
document.getElementById('filename').innerHTML = 'Name: ' + oFile.name;
document.getElementById('filesize').innerHTML = 'Size: ' + sResultFileSize;
document.getElementById('filetype').innerHTML = 'Type: ' + oFile.type;
document.getElementById('filedim').innerHTML = 'Dimension: ' + oImage.naturalWidth + ' x ' + oImage.naturalHeight;
};
};
oReader.readAsDataURL(oFile);
}
function startUploading() {
iPreviousBytesLoaded = 0;
document.getElementById('upload_response').style.display = 'none';
document.getElementById('error').style.display = 'none';
document.getElementById('error2').style.display = 'none';
document.getElementById('abort').style.display = 'none';
document.getElementById('warnsize').style.display = 'none';
document.getElementById('progress_percent').innerHTML = '';
var oProgress = document.getElementById('progress');
oProgress.style.display = 'block';
oProgress.style.width = '0px';
var vFD = new FormData(document.getElementById('upload_form'));
var oXHR = new XMLHttpRequest();
oXHR.upload.addEventListener('progress', uploadProgress, false);
oXHR.addEventListener('load', uploadFinish, false);
oXHR.addEventListener('error', uploadError, false);
oXHR.addEventListener('abort', uploadAbort, false);
oXHR.open('POST', '/update');
oXHR.send(vFD);
oTimer = setInterval(doInnerUpdates, 300);
}
function doInnerUpdates() {
var iCB = iBytesUploaded;
var iDiff = iCB - iPreviousBytesLoaded;
if (iDiff == 0)
return;
iPreviousBytesLoaded = iCB;
iDiff = iDiff * 2;
var iBytesRem = iBytesTotal - iPreviousBytesLoaded;
var secondsRemaining = iBytesRem / iDiff;
var iSpeed = iDiff.toString() + 'B/s';
if (iDiff > 1024 * 1024) {
iSpeed = (Math.round(iDiff * 100/(1024*1024))/100).toString() + 'MB/s';
} else if (iDiff > 1024) {
iSpeed = (Math.round(iDiff * 100/1024)/100).toString() + 'KB/s';
}
document.getElementById('speed').innerHTML = iSpeed;
document.getElementById('remaining').innerHTML = '| ' + secondsToTime(secondsRemaining);
}
function uploadProgress(e) {
if (e.lengthComputable) {
iBytesUploaded = e.loaded;
iBytesTotal = e.total;
var iPercentComplete = Math.round(e.loaded * 100 / e.total);
var iBytesTransfered = bytesToSize(iBytesUploaded);
document.getElementById('progress_percent').innerHTML = iPercentComplete.toString() + '%';
document.getElementById('progress').style.width = (iPercentComplete * 4).toString() + 'px';
document.getElementById('b_transfered').innerHTML = iBytesTransfered;
if (iPercentComplete == 100) {
var oUploadResponse = document.getElementById('upload_response');
oUploadResponse.innerHTML = '<h1>Please wait...processing</h1>';
oUploadResponse.style.display = 'block';
}
} else {
document.getElementById('progress').innerHTML = 'unable to compute';
}
}
function uploadFinish(e) {
var oUploadResponse = document.getElementById('upload_response');
oUploadResponse.innerHTML = e.target.responseText;
oUploadResponse.style.display = 'block';
document.getElementById('progress_percent').innerHTML = '100%';
document.getElementById('progress').style.width = '400px';
document.getElementById('filesize').innerHTML = sResultFileSize;
document.getElementById('remaining').innerHTML = '| 00:00:00';
clearInterval(oTimer);
}
function uploadError(e) {
document.getElementById('error2').style.display = 'block';
clearInterval(oTimer);
}
function uploadAbort(e) {
document.getElementById('abort').style.display = 'block';
clearInterval(oTimer);
}
</script>
<style>
.container {
margin: auto;
width: 50%;
}
.upload_form_cont {
background: -moz-linear-gradient(#ffffff, #f2f2f2);
background: -ms-linear-gradient(#ffffff, #f2f2f2);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #f2f2f2));
background: -webkit-linear-gradient(#ffffff, #f2f2f2);
background: -o-linear-gradient(#ffffff, #f2f2f2);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f2f2f2');
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f2f2f2')";
background: linear-gradient(#ffffff, #f2f2f2);
color:#000;
overflow:hidden;
}
#upload_form {
float:center;
padding:20px;
width:700px;
}
#preview {
background-color:#fff;
display:block;
float:right;
width:200px;
}
#upload_form > div {
margin-bottom:10px;
}
#speed,#remaining {
float:left;
width:100px;
}
#b_transfered {
float:right;
text-align:right;
}
.clear_both {
clear:both;
}
input {
border-radius:10px;
-moz-border-radius:10px;
-ms-border-radius:10px;
-o-border-radius:10px;
-webkit-border-radius:10px;
border:1px solid #ccc;
font-size:14pt;
padding:5px 10px;
}
input[type=button] {
background: -moz-linear-gradient(#ffffff, #dfdfdf);
background: -ms-linear-gradient(#ffffff, #dfdfdf);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ffffff), color-stop(100%, #dfdfdf));
background: -webkit-linear-gradient(#ffffff, #dfdfdf);
background: -o-linear-gradient(#ffffff, #dfdfdf);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dfdfdf');
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#dfdfdf')";
background: linear-gradient(#ffffff, #dfdfdf);
}
#image_file {
width:400px;
}
#progress_info {
font-size:10pt;
}
#fileinfo,#error,#error2,#abort,#warnsize {
color:#aaa;
display:none;
font-size:10pt;
font-style:italic;
margin-top:10px;
}
#progress {
border:1px solid #ccc;
display:none;
float:left;
height:14px;
border-radius:10px;
-moz-border-radius:10px;
-ms-border-radius:10px;
-o-border-radius:10px;
-webkit-border-radius:10px;
background: -moz-linear-gradient(#66cc00, #4b9500);
background: -ms-linear-gradient(#66cc00, #4b9500);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #66cc00), color-stop(100%, #4b9500));
background: -webkit-linear-gradient(#66cc00, #4b9500);
background: -o-linear-gradient(#66cc00, #4b9500);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#66cc00', endColorstr='#4b9500');
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#66cc00', endColorstr='#4b9500')";
background: linear-gradient(#66cc00, #4b9500);
}
#progress_percent {
float:right;
}
#upload_response {
margin-top: 10px;
padding: 20px;
overflow: hidden;
display: none;
border: 1px solid #ccc;
border-radius:10px;
-moz-border-radius:10px;
-ms-border-radius:10px;
-o-border-radius:10px;
-webkit-border-radius:10px;
box-shadow: 0 0 5px #ccc;
background: -moz-linear-gradient(#bbb, #eee);
background: -ms-linear-gradient(#bbb, #eee);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #bbb), color-stop(100%, #eee));
background: -webkit-linear-gradient(#bbb, #eee);
background: -o-linear-gradient(#bbb, #eee);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#bbb', endColorstr='#eee');
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr='#bbb', endColorstr='#eee')";
background: linear-gradient(#bbb, #eee);
}
</style>
<body>
<header>
<h2 align='center'>*** OpenFlightRX - Firmware Uploader ***</h2>
</header>
<div class='container'>
<div class='contr'><h2>Please select a file to upload the firmware.</h2></div>
<div class='upload_form_cont'>
<form method='POST' action='/update' enctype='multipart/form-data' id='upload_form'>
<div>
<div><label for='image_file'>Please select image file</label></div>
<div><input type='file' name='update' id='image_file' onchange='fileSelected();' /></div>
</div>
<div><input type='button' value='Upload' onclick='startUploading()' /></div>
<div id='fileinfo'>
<div id='filename'></div>
<div id='filesize'></div>
<div id='filetype'></div>
<div id='filedim'></div>
</div>
<div id='error'>You should select valid image files only!</div>
<div id='error2'>An error occurred while uploading the file</div>
<div id='abort'>The upload has been canceled by the user or the browser dropped the connection</div>
<div id='warnsize'>Your file is very big. We can't accept it. Please select more small file</div>
<div id='progress_info'>
<div id='progress'></div>
<div id='progress_percent'>&nbsp;</div>
<div class='clear_both'></div>
<div>
<div id='speed'>&nbsp;</div>
<div id='remaining'>&nbsp;</div>
<div id='b_transfered'>&nbsp;</div>
<div class='clear_both'></div>
</div>
<div id='upload_response'></div>
</div>
</form>
</div>
</div>
</div>
</body>
)rawliteral";
/*** Index Page ***/
const char* index_html PROGMEM = R"rawliteral(<pre><strong>OpenFlightRX v1.0.0</strong>
)rawliteral";
// WebPages ----- END
// For NRF24L01 (E01) - EByte
// #include "nRF24L01.h"
#include "RF24.h"
@ -95,14 +408,17 @@ TaskHandle_t NRFTask;
* to suit you needs. For the 5 seconds frame... if not connected over wifi, it will stop the wifi syncing process.
*/
// TTTT TTTT TTTT ---- YYYY YYYY YYYY ---- PPPP PPPP PPPP ---- RRRR RRRR RRRR ---- SSSS SSSS = 72-bits ( 9 bytes )
// 1234 5TTT TTTT TTTT 6789 AYYY YYYY YYYY ---- -PPP PPPP PPPP ---- -RRR RRRR RRRR (8-Bytes for AERT and switch commands!!)
// Data Structure
// 1234 5678 9TTT TTTT TTTT -YYY YYYY YYYY -PPP PPPP PPPP -RRR RRRR RRRR (7 Bytes)
struct RxMessage {
uint16_t throttle;
uint16_t yaw;
uint16_t pitch;
uint16_t roll;
uint8_t switches;
uint8_t Byte00;
uint8_t Byte01;
uint8_t Byte02;
uint8_t Byte03;
uint8_t Byte04;
uint8_t Byte05;
uint8_t Byte06;
};
RxMessage rxmessage;
@ -149,6 +465,7 @@ int nrf_received_count_raw = 0;
uint32_t last_seconds = 0;
uint32_t last_telnet_seconds = 0;
uint32_t last_webserver_seconds = 0;
bool ip_shown = false;
bool socket_connected = true;
@ -160,6 +477,83 @@ uint32_t nrf_last_receive = 0;
uint8_t freq_channel = 0;
uint64_t pipe_code = 0;
// Replace with your network credentials
const char* ssid = "BERTFPV";
const char* password = "LetMeIn1234"; // Must be >= 8 characters
/* Put IP Address details */
IPAddress local_ip(192,168,1,1);
IPAddress gateway(192,168,1,1);
IPAddress subnet(255,255,255,0);
void setup_webserver(void) {
// Create HostAP
Serial.println(F("Starting SoftAP"));
WiFi.softAP(ssid, password);
Serial.println(F("Setting IP"));
WiFi.softAPConfig(local_ip, gateway, subnet);
delay(100); // Delay 100mS
IPAddress IP = WiFi.softAPIP();
Serial.print(F("AP IP address: "));
Serial.println(IP);
// init and get the time
// configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
// Setting up OTA
/*** Index Page ***/
server.on("/", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", firmware_upgrade_html);
});
/*** Firmware Upgrade Page ***/
server.on("/firmware_upgrade", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", firmware_upgrade_html);
});
// ################### HANDLING UPLOAD FIRMWARE HERE #########################
/*** handling uploading firmware file ***/
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK. Device is rebooting");
// Try to delay a bit...
delay(1000);
ESP.restart();
}, []() {
HTTPUpload& upload = server.upload();
if(upload.status == UPLOAD_FILE_START) {
// Serial.printf("Update: %s\n", upload.filename.c_str());
if(!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
Update.printError(Serial);
}
} else if(upload.status == UPLOAD_FILE_WRITE) {
/*** flashing firmware to ESP ***/
if(Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if(upload.status == UPLOAD_FILE_END) {
if(Update.end(true)) {
//true to set the size to the current progress
// Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
// Starting up Server
server.begin();
// Just to debug...
// if(WiFi.status() == WL_CONNECTED)
// Serial.println(WiFi.localIP());
}
void setup() {
// For USB Debugging
Serial.begin(115200);
@ -268,8 +662,12 @@ void setup() {
// NRF Setup
Serial.println(F("Setting up NRF"));
setup_nrf_rx();
// Setup OTA
Serial.println(F("Setting up webserver"));
setup_webserver();
}
void loop() {
@ -278,7 +676,6 @@ void loop() {
nrf_received_count = nrf_received_count_raw;
nrf_received_count_raw = 0;
Serial.print("NRF:");
Serial.println(nrf_received_count);
@ -293,7 +690,17 @@ void loop() {
*/
}
nrf_recv();
// Handling web services every 100mS
if(millis() > last_webserver_seconds) {
server.handleClient();
last_webserver_seconds = millis() + 100;
}
// Temporary
////// nrf_recv();
// socket_client();
// telnet_server();
#ifdef USE_SONAR
@ -336,8 +743,8 @@ void loop() {
uint32_t last_reconnect = 0;
uint32_t last_sent = 0;
const char * host = "192.168.4.1";
const uint16_t port = 1001;
// const char * host = "192.168.4.1";
// const uint16_t port = 1001;
// void socket_client(void) {
// if(WiFi.status() == WL_CONNECTED) {
@ -457,17 +864,17 @@ void sbusPreparePacket(uint8_t packet[], int channels[], bool isSignalLoss, bool
if (isFailsafe) {
stateByte |= SBUS_STATE_FAILSAFE;
}
packet[0] = SBUS_FRAME_HEADER; //Header
packet[1] = (uint8_t) (output[0] & 0x07FF);
packet[2] = (uint8_t) ((output[0] & 0x07FF)>>8 | (output[1] & 0x07FF)<<3);
packet[3] = (uint8_t) ((output[1] & 0x07FF)>>5 | (output[2] & 0x07FF)<<6);
packet[4] = (uint8_t) ((output[2] & 0x07FF)>>2);
packet[5] = (uint8_t) ((output[2] & 0x07FF)>>10 | (output[3] & 0x07FF)<<1);
packet[6] = (uint8_t) ((output[3] & 0x07FF)>>7 | (output[4] & 0x07FF)<<4);
packet[7] = (uint8_t) ((output[4] & 0x07FF)>>4 | (output[5] & 0x07FF)<<7);
packet[8] = (uint8_t) ((output[5] & 0x07FF)>>1);
packet[9] = (uint8_t) ((output[5] & 0x07FF)>>9 | (output[6] & 0x07FF)<<2);
packet[0] = SBUS_FRAME_HEADER; //Header
packet[1] = (uint8_t) (output[0] & 0x07FF);
packet[2] = (uint8_t) ((output[0] & 0x07FF)>>8 | (output[1] & 0x07FF)<<3);
packet[3] = (uint8_t) ((output[1] & 0x07FF)>>5 | (output[2] & 0x07FF)<<6);
packet[4] = (uint8_t) ((output[2] & 0x07FF)>>2);
packet[5] = (uint8_t) ((output[2] & 0x07FF)>>10 | (output[3] & 0x07FF)<<1);
packet[6] = (uint8_t) ((output[3] & 0x07FF)>>7 | (output[4] & 0x07FF)<<4);
packet[7] = (uint8_t) ((output[4] & 0x07FF)>>4 | (output[5] & 0x07FF)<<7);
packet[8] = (uint8_t) ((output[5] & 0x07FF)>>1);
packet[9] = (uint8_t) ((output[5] & 0x07FF)>>9 | (output[6] & 0x07FF)<<2);
packet[10] = (uint8_t) ((output[6] & 0x07FF)>>6 | (output[7] & 0x07FF)<<5);
packet[11] = (uint8_t) ((output[7] & 0x07FF)>>3);
packet[12] = (uint8_t) ((output[8] & 0x07FF));
@ -490,32 +897,30 @@ void sbusPreparePacket(uint8_t packet[], int channels[], bool isSignalLoss, bool
void setPPMValuesFromData(void) {
static bool firstload = true;
/*
* The values for:
* - throttle
* - yaw
* - pitch
* - roll
*/
rcChannels[2] = rxmessage.throttle; // Throttle
rcChannels[3] = rxmessage.yaw; // Yaw
rcChannels[1] = rxmessage.pitch; // Pitch
rcChannels[0] = rxmessage.roll; // Roll
// Misc: (64 * channel_a) | (32 * channel_b) | (16 * channel_d) | (8 * channel_e) | (4 * channel_f) | (2 * channel_g) | (1 * channel_h);
// ch6 reserved for the moment
// 2021 New Data format for saving 2 bytes:
// 1234 5678 9TTT TTTT TTTT -YYY YYYY YYYY -PPP PPPP PPPP -RRR RRRR RRRR (7 Bytes)
// |-------| |-------| |-------| |-------| |-------| |-------| |-------|
// Byte 00 Byte 01 Byte 02 Byte 03 Byte 04 Byte 05 Byte 06
// Extracting data
// Processing switches channel....
rcChannels[5] = (rxmessage.switches & (1 << 0)) ? 2000 : 1000;
rcChannels[6] = (rxmessage.switches & (1 << 1)) ? 2000 : 1000;
rcChannels[7] = (rxmessage.switches & (1 << 2)) ? 2000 : 1000;
rcChannels[8] = (rxmessage.switches & (1 << 3)) ? 2000 : 1000;
rcChannels[9] = (rxmessage.switches & (1 << 4)) ? 2000 : 1000;
rcChannels[10] = (rxmessage.switches & (1 << 5)) ? 2000 : 1000;
rcChannels[11] = (rxmessage.switches & (1 << 6)) ? 2000 : 1000;
rcChannels[12] = (rxmessage.switches & (1 << 7)) ? 2000 : 1000;
rcChannels[4] = ((rxmessage.Byte00 >> 7) & 0x01) ? 2000 : 1000; // 1
rcChannels[5] = ((rxmessage.Byte00 >> 6) & 0x01) ? 2000 : 1000; // 2
rcChannels[6] = ((rxmessage.Byte00 >> 5) & 0x01) ? 2000 : 1000; // 3
rcChannels[7] = ((rxmessage.Byte00 >> 4) & 0x01) ? 2000 : 1000; // 4
rcChannels[8] = ((rxmessage.Byte00 >> 3) & 0x01) ? 2000 : 1000; // 5
rcChannels[9] = ((rxmessage.Byte00 >> 2) & 0x01) ? 2000 : 1000; // 6
rcChannels[10] = ((rxmessage.Byte00 >> 1) & 0x01) ? 2000 : 1000; // 7
rcChannels[11] = ((rxmessage.Byte00 >> 0) & 0x01) ? 2000 : 1000; // 8
rcChannels[12] = ((rxmessage.Byte01 >> 7) & 0x01) ? 2000 : 1000; // 9
rcChannels[2] = ((rxmessage.Byte01 & 0X7F) << 4) | (rxmessage.Byte02 & 0xF0) >> 4; // Throttle
rcChannels[3] = ((rxmessage.Byte02 & 0x07) << 8) | rxmessage.Byte03; // Yaw
rcChannels[1] = ((rxmessage.Byte04 & 0x7F) << 4) | (rxmessage.Byte05 & 0xF0) >> 4; // Pitch
rcChannels[0] = ((rxmessage.Byte05 & 0x07) << 8) | rxmessage.Byte06; // Roll
// Static values... so leave it
if(!firstload) {
rcChannels[4] = 1000; // Channel C
rcChannels[13] = 1000; // Not in use
rcChannels[14] = 1000; // Not in use
rcChannels[15] = 1000; // Not in use
@ -524,11 +929,13 @@ void setPPMValuesFromData(void) {
}
void resetData(void) {
rxmessage.throttle = 900;
rxmessage.yaw = 900;
rxmessage.pitch = 900;
rxmessage.roll = 900;
rxmessage.switches = 0;
rxmessage.Byte00 = 0;
rxmessage.Byte01 = 0;
rxmessage.Byte02 = 0;
rxmessage.Byte03 = 0;
rxmessage.Byte04 = 0;
rxmessage.Byte05 = 0;
rxmessage.Byte06 = 0;
setPPMValuesFromData();
}

Loading…
Cancel
Save