From 52c64a162d6ef003b17aae2e66ea4905c2b35166 Mon Sep 17 00:00:00 2001 From: Englebert <=> Date: Sun, 27 Feb 2022 20:40:23 +0800 Subject: [PATCH] Working BLE --- OpenSCAD/.M5CoreTX-V1.scad.swp | Bin 65536 -> 0 bytes OpenSCAD/M5CoreTX-V1.scad | 1492 ++++++++++++++++---------------- README.md | 13 +- platformio.ini | 1 + src/BLE.cpp | 51 ++ src/BLE.h | 25 + src/BLEGamepad.cpp | 61 ++ src/BLEGamepad.h | 24 + src/GimbalGraph.cpp | 5 + src/GimbalGraph.h | 14 + src/Inputs.cpp | 259 ++++++ src/Inputs.h | 56 ++ src/Screen.cpp | 10 + src/Screen.h | 10 +- src/StickCalibration.cpp | 44 + src/StickCalibration.h | 21 + src/main.cpp | 44 +- src/main.h | 4 + 18 files changed, 1395 insertions(+), 739 deletions(-) delete mode 100644 OpenSCAD/.M5CoreTX-V1.scad.swp create mode 100644 src/BLE.cpp create mode 100644 src/BLE.h create mode 100644 src/BLEGamepad.cpp create mode 100644 src/BLEGamepad.h create mode 100644 src/GimbalGraph.cpp create mode 100644 src/GimbalGraph.h create mode 100644 src/Inputs.cpp create mode 100644 src/Inputs.h create mode 100644 src/StickCalibration.cpp create mode 100644 src/StickCalibration.h diff --git a/OpenSCAD/.M5CoreTX-V1.scad.swp b/OpenSCAD/.M5CoreTX-V1.scad.swp deleted file mode 100644 index e81188d5c532c8aec132215d5c8d0bf0218ab0ff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 65536 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 diff --git a/OpenSCAD/M5CoreTX-V1.scad b/OpenSCAD/M5CoreTX-V1.scad index 3299029..5dc2d7e 100644 --- a/OpenSCAD/M5CoreTX-V1.scad +++ b/OpenSCAD/M5CoreTX-V1.scad @@ -1,763 +1,680 @@ -// For printing individually -// gimbal_ring(); - -// translate([0,0,0]) -// display_backcover(); -// battery_backcover_full(); -// body_full(); - -round_quality = 100; // round_quality = 200; -// round_quality = 20; -// draft = true; -draft = false; - -/**** -translate([0,0,5]) - back_cover_full(); - -translate([0,0,-20]) - difference() { - backcover_lowprofile(); - - translate([-21.5,-12.5,-46]) - rotate([0,0,0]) - cube([25,46,15], center=true); - - translate([-21.5,-12.5,-36]) - rotate([0,0,0]) - cube([25,37.4,2], center=true); - +// draft = false; +// show_m5 = true; +// show_gimbal_r = true; // Rings +// show_right_g = false; // Only show one gimbal +// show_gimbal = true; // Gimbals +// show_gimbal_u = false; // Upper +// show_left = true; +// show_right = true; +// show_left_b = true; +// show_right_b = true; +// show_gimbal_b = false; // Lower +// show_battery = true; +// show_bars = true; +// show_bars_1 = true; +// show_bars_2 = true; + +round_quality = 200; +draft = true; +show_top_only = false; +show_bottom_only = false; +show_m5 = true; +show_gimbal_r = true; // Rings +show_right_g = false; // Only show one gimbal +show_gimbal = true; // Gimbals +show_gimbal_u = false; // Upper +show_left = true; +show_right = true; +show_left_b = true; +show_right_b = true; +show_gimbal_b = false; // Lower +show_battery = true; +show_bars = false; +show_bars_1 = false; +show_bars_2 = false; +show_bottom_legs = false; +show_bottom_single = false; +show_bottom_H = true; +show_top_bars = true; +show_bottom_spacers = true; +show_bottom_extenders = true; +show_top_spacers = true; +show_top_cover = true; + +//round_quality = 200; +//draft = true; +//show_top_only = false; +//show_bottom_only = false; +//show_m5 = false; +//show_gimbal_r = false; // Rings +//show_right_g = false; // Only show one gimbal +//show_gimbal = false; // Gimbals +//show_gimbal_u = false; // Upper +//show_left = false; +//show_right = true; +//show_left_b = true; +//show_right_b = true; +//show_gimbal_b = false; // Lower +//show_battery = false; +//show_bars = false; +//show_bars_1 = false; +//show_bars_2 = false; +//show_bottom_legs = false; +//show_bottom_single = false; +//show_bottom_H = false; +//show_top_bars = false; +//show_bottom_spacers = false; +//show_bottom_extenders = false; +//show_top_spacers = true; +//show_top_cover = false; + +if(show_top_cover) { + translate([-20,11,6]) { + top_cover(); } - - -translate([0,0,-20]) - difference() { - transceiver_cover(); - translate([-25.8,6,-39]) - rotate([90,0,0]) - cube([5.5,13,10], center=true); - } - -translate([0,-80,-20]) - battery_backcover_full(); -translate([0,0,-25]) - display_backcover(); -translate([0,0,20]) - gimbal_ring(); -translate([-41,0,40]) { - translate([135,0,-20]) - gimbal_ring(); } - ****/ -// back_cover_full(); - -// translate([0,0,10]) -// battery_backcover_full(); - -// all(); - -// m5core2(); -body_full(); -translate([0,-20,12]) - rotate([180,0,180]) - m5_body(); - -module m5core2() { - translate([0,-25,10]) - cube([54,54,18], center=true); +if(show_top_spacers) { + top_spacers(); } -module transceiver_cover() { - translate([-21.5,-14.2,-46.5]) - cube([24,42.4,1.3], center=true); - translate([-21.5,6.5,-42.9]) - rotate([90,0,0]) - cube([24,8.5,1.3], center=true); - translate([-21.5,-36,-45.2]) - rotate([0,0,0]) - cube([24.5,5,1.3], center=true); - translate([-25.5,-3,-44.4]) - rotate([0,0,0]) - cube([14.5,3,3], center=true); - translate([-25.5,-9,-44.4]) - rotate([0,0,0]) - cube([14.5,3,3], center=true); - translate([-25.5,-21,-44.4]) - rotate([0,0,0]) - cube([14.5,3,3], center=true); - translate([-25.5,-27,-44.4]) - rotate([0,0,0]) - cube([14.5,3,3], center=true); - translate([-12.5,-15,-44.4]) - rotate([0,0,90]) - cube([34.5,3,3], center=true); - - translate([-21.5,5,-44.4]) - rotate([0,0,0]) - cube([24,3,3], center=true); - - translate([-25.5,-15,-44.4]) - rotate([0,0,0]) - cube([14.5,3,3], center=true); - difference() { - translate([-21.5,5.2,-39]) - rotate([90,0,0]) - cube([24,6.5,1.3], center=true); +module top_spacers() { + translate([-18,7,15.3]) + cube([20,3,10], center=true); + translate([18,7,15.3]) + cube([20,3,10], center=true); +} - translate([-21.5,5.5,-43]) - rotate([-45,0,0]) - cube([25.5,6.5,1.3], center=true); - } - translate([-21.5,6,-36.3]) - rotate([90,0,0]) - cube([24,1.1,1.3], center=true); +module top_cover() { + top_legs(); + translate([40,0,0]) + top_legs(); + // Battery Cover + translate([20,-1.5,4.5]) + difference() { + cube([50,1.5,54], center=true); + translate([0,0,4.5]) + rotate([90,0,0]) + cylinder(h=4, d=10, center=true, $fn=round_quality); + translate([0,0,7]) + cube([10,10,5], center=true); + } } -module backcover_lowprofile() { +module top_legs() { + translate([0,0,4.5]) + rotate([0,0,180]) difference() { - battery_backcover(); + cube([14,4.5,54], center=true); - // Left Screw Hold on the Battery Cover - translate([41,-23,-30]) - cylinder(h=round_quality, d=2, center=true, $fn=round_quality); + // Screw top + translate([0,0,5]) + rotate([90,0,0]) + cylinder(h=10, d=2, center=true, $fn=round_quality); + translate([0,-2,5]) + rotate([90,0,0]) + cylinder(h=4, d=4.6, center=true, $fn=round_quality); - // Right Screw Hold on the Battery Cover - translate([-41,-23,-30]) - cylinder(h=round_quality, d=2, center=true, $fn=round_quality); + // Screw bottom + translate([0,0,-8]) + rotate([90,0,0]) + cylinder(h=10, d=2, center=true, $fn=round_quality); + translate([0,-2,-8]) + rotate([90,0,0]) + cylinder(h=4, d=4.6, center=true, $fn=round_quality); - // Charger Port - // translate([0,-50,-30]) - // cube([10,3,6], center=true); - translate([0,-23,-30]) - cube([76,58,5], center=true); + // Sides + translate([10,0,0]) + rotate([0,0,45]) + cube([20,4.5,63], center=true); + translate([-10,0,0]) + rotate([0,0,-45]) + cube([20,4.5,63], center=true); } +} - translate([0,6.35,-37.5]) - rotate([90,0,0]) - cube([78,17,1.3], center=true); - - translate([0,-52.35,-37.5]) - rotate([90,0,0]) - cube([78,17,1.3], center=true); - - translate([-38.6,-23,-37.5]) - rotate([90,0,90]) - cube([60,17,1.3], center=true); - - translate([38.6,-23,-37.5]) - rotate([90,0,90]) - cube([60,17,1.3], center=true); - translate([0,-23,-46.5]) - rotate([0,0,0]) - cube([78.5,60,1.3], center=true); +if(show_bottom_extenders) { + translate([-20,-57,17]) + bottom_extenders(); + translate([20,-57,17]) + bottom_extenders(); +} +module bottom_extenders() { difference() { - translate([0,-51.1,-30.5]) - rotate([90,0,0]) - cube([75,5,1.3], center=true); + cube([14,3,8], center=true); - translate([0,-51.1,-33.5]) - rotate([45,0,0]) - cube([75,5,1.3], center=true); + // Screw top + translate([0,0,-2]) + rotate([90,0,0]) + cylinder(h=10, d=2, center=true, $fn=round_quality); } } - -// Battery back cover -module battery_backcover() { - translate([0,-23,-30]) - cube([90,60,2], center=true); +if(show_bottom_spacers) { + translate([-20,-61,6]) + bottom_spacers(); } -module back_cover() { - translate([-47,-25,-8]) - cube([67.4,67.4,2], center=true); - translate([47,-25,-8]) - cube([67.4,67.4,2], center=true); - translate([0,-23,-8]) - cube([29,62,2], center=true); - translate([-53,20,-8]) - cube([43.5,27.5,2], center=true); - translate([53,20,-8]) - cube([43.5,27.5,2], center=true); - - // PCB & Battery Holder - translate([0,-23,-12]) { - difference() { - cube([90,60,10], center=true); - cube([88,58,12], center=true); - } - translate([41,0,0]) - difference() { - cube([7,10,6], center=true); - cylinder(h=round_quality, d=3, center=true); - } - translate([-41,0,0]) - difference() { - cube([7,10,6], center=true); - cylinder(h=round_quality, d=3, center=true); - } - translate([0,28,0]) - cube([90,2,6], center=true); - translate([0,-28,0]) - cube([90,2,6], center=true); - } - - // Left Holder - translate([-63,-25,6]) - rotate([90,0,0]) - difference() { - cylinder(h=67, d=45.5, center=true); - translate([0,10,0]) - cube([50,50,70], center=true); - } +module bottom_spacers() { + translate([0,0,0]) + bottom_legs(); + translate([20,0,-1]) + rotate([0,90,0]) + bottom_legs(); + translate([40,0,0]) + bottom_legs(); +} - // Right Holder - translate([63,-25,6]) - rotate([90,0,0]) - difference() { - cylinder(h=67, d=45.5, center=true); - translate([0,10,0]) - cube([50,50,70], center=true); - } - /**** - // Battery + Capacitor Area - translate([0,6,-19]) - cube([70,2,20], center=true); - translate([0,-52,-19]) - cube([70,2,20], center=true); - translate([36,-23,-19]) - cube([2,60,20], center=true); - translate([-36,-23,-19]) - cube([2,60,20], center=true); - - // Back Cover Holder - translate([41,-23,-19]) - cylinder(h=round_quality, d=10, center=true); - translate([39,-23,-19]) - cube([5,10,20], center=true); - translate([-41,-23,-19]) - cylinder(h=round_quality, d=10, center=true); - translate([-39,-23,-19]) - cube([5,10,20], center=true); - ***/ +if(show_bottom_H) { + translate([-85,-61,6]) { + bottom_H(); + } + translate([45,-61,6]) { + bottom_H(); + } } -// Display BackCover -module display_backcover() { - difference() { - translate([0,21,7]) { - difference() { - cube([45.5,29.5,2], center=true); - - translate([21.5,13.5,0]) - cylinder(h=3, d=1, center=true); - - translate([-21.5,13.5,0]) - cylinder(h=3, d=1, center=true); - - translate([-21.5,-8.5,0]) - cylinder(h=3, d=1, center=true); - - translate([21.5,-8.5,0]) - cylinder(h=3, d=1, center=true); +module bottom_H() { + translate([0,0,0]) + bottom_legs(); + translate([20,0,0]) + rotate([0,90,0]) + bottom_legs(); + translate([40,0,0]) + bottom_legs(); +} - translate([0,-27,0]) - cube([50,35,5], center=true); - } - } - } - /* - translate([9,23,11]) { - cube([5,10,9], center=true); - translate([2,0,-2]) - cube([10,2,3], center=true); +if(show_top_bars) { + translate([-85,11,6]) { + rotate([180,0,0]) + bottom_H(); } - - translate([-9,23,11]) { - cube([5,10,9], center=true); - translate([-2,0,-2]) - cube([10,2,3], center=true); + translate([45,11,6]) { + rotate([180,0,0]) + bottom_H(); } - */ } -module battery_backcover_full() { +module top_bars() { + rotate([0,0,180]) difference() { - battery_backcover(); + cube([14,4.5,30], center=true); - // Left Screw Hold on the Battery Cover - translate([41,-23,-30]) - cylinder(h=round_quality, d=2, center=true, $fn=round_quality); + // Screw top + translate([0,0,9]) + rotate([90,0,0]) + cylinder(h=10, d=2, center=true, $fn=round_quality); + translate([0,-2,9]) + rotate([90,0,0]) + cylinder(h=4, d=4.6, center=true, $fn=round_quality); - // Right Screw Hold on the Battery Cover - translate([-41,-23,-30]) - cylinder(h=round_quality, d=2, center=true, $fn=round_quality); + // Screw bottom + translate([0,0,-6]) + rotate([90,0,0]) + cylinder(h=10, d=2, center=true, $fn=round_quality); + translate([0,-2,-6]) + rotate([90,0,0]) + cylinder(h=4, d=4.6, center=true, $fn=round_quality); - // Charger Port - // translate([0,-50,-30]) - // cube([10,3,6], center=true); - translate([0,-23,-30]) - cube([76,50,5], center=true); + // Sides + translate([10,0,0]) + rotate([0,0,45]) + cube([20,4.5,33], center=true); + translate([-10,0,0]) + rotate([0,0,-45]) + cube([20,4.5,33], center=true); } - // Upper box area - translate([0,-23,-45]) { - difference() { - cube([77,54,31.4], center=true); - translate([0,0,3.5]) - cube([74,51,35.4], center=true); - translate([27,25,11]) - cube([6.6,12,14], center=true); - translate([0,-15,-19]) - cube([2,5,12], center=true); - } - } } -module back_cover_full() { - translate([53,20,-10]) { - rotate([0,0,30]) - cube([45,2,2], center=true); - rotate([0,0,-30]) - cube([45,2,2], center=true); - cube([10,10,2], center=true); +if(show_bottom_legs) { + translate([-85,-61,6]) { + bottom_legs(); } - - translate([-53,20,-10]) { - rotate([0,0,30]) - cube([45,2,2], center=true); - rotate([0,0,-30]) - cube([45,2,2], center=true); - cube([10,10,2], center=true); + translate([-45,-61,6]) { + bottom_legs(); + } + translate([45,-61,6]) { + bottom_legs(); } + translate([85,-61,6]) { + bottom_legs(); + } +} else if(show_bottom_single) { + translate([0,0,0]) + rotate([-90,0,0]) + bottom_legs(); + translate([20,0,0]) + rotate([-90,0,0]) + bottom_legs(); + translate([40,0,0]) + rotate([-90,0,0]) + bottom_legs(); + translate([60,0,0]) + rotate([-90,0,0]) + bottom_legs(); + translate([80,0,0]) + rotate([-90,0,0]) + bottom_legs(); + translate([100,0,0]) + rotate([-90,0,0]) + bottom_legs(); + translate([120,0,0]) + rotate([-90,0,0]) + bottom_legs(); + translate([140,0,0]) + rotate([-90,0,0]) + bottom_legs(); +} +module bottom_legs() { difference() { - back_cover(); + cube([14,4.5,30], center=true); - // Left Holder Hollow area - translate([-63,-25,9]) + // Screw top + translate([0,0,9]) rotate([90,0,0]) - difference() { - cylinder(h=60, d=45.5, center=true); - translate([0,10,0]) - cube([50,50,70], center=true); - } - - // Right Holder Hollow area - translate([63,-25,9]) + cylinder(h=10, d=2, center=true, $fn=round_quality); + translate([0,-2,9]) rotate([90,0,0]) - difference() { - cylinder(h=60, d=45.5, center=true); - translate([0,10,0]) - cube([50,50,70], center=true); - } + cylinder(h=4, d=4.6, center=true, $fn=round_quality); + // Screw bottom + translate([0,0,-6]) + rotate([90,0,0]) + cylinder(h=10, d=2, center=true, $fn=round_quality); + translate([0,-2,-6]) + rotate([90,0,0]) + cylinder(h=4, d=4.6, center=true, $fn=round_quality); - translate([0,-20,-10]) - cube([20,20,10], center=true); - - // Left Screw Hold on the Battery Cover - translate([41,-23,-30]) - cylinder(h=round_quality, d=2, center=true); - - // Right Screw Hold on the Battery Cover - translate([-41,-23,-30]) - cylinder(h=round_quality, d=2, center=true); - - /************* - // Screw Holes at backcover gimbal area - translate([-79.5,7.5,-10]) - cylinder(h=10, d=1, center=true); - translate([79.5,7.5,-10]) - cylinder(h=10, d=1, center=true); - translate([79.5,-57.5,-10]) - cylinder(h=10, d=1, center=true); - translate([-79.5,-57.5,-10]) - cylinder(h=10, d=1, center=true); - translate([-14.5,-57.5,-10]) - cylinder(h=10, d=1, center=true); - translate([14.5,-57.5,-10]) - cylinder(h=10, d=1, center=true); - - // Screws holes at switches panel - translate([73.5,12.5,-10]) - cylinder(h=10, d=1, center=true); - translate([32.5,12.5,-10]) - cylinder(h=10, d=1, center=true); - translate([32.5,32.5,-10]) - cylinder(h=10, d=1, center=true); - translate([73.5,32.5,-10]) - cylinder(h=10, d=1, center=true); - - translate([-32.5,32.5,-10]) - cylinder(h=10, d=1, center=true); - translate([-32.5,12.5,-10]) - cylinder(h=10, d=1, center=true); - translate([-73.5,12.5,-10]) - cylinder(h=10, d=1, center=true); - translate([-73.5,32.5,-10]) - cylinder(h=10, d=1, center=true); - ********/ + // Sides + translate([10,0,0]) + rotate([0,0,45]) + cube([20,4.5,33], center=true); + translate([-10,0,0]) + rotate([0,0,-45]) + cube([20,4.5,33], center=true); } -} - -module body_full() { - body(); - translate([-16,0,0]) - gimbal_ring(); - translate([110,0,0]) { - gimbal_ring(); - } } -module all() { - // Display Backcover - display_backcover(); - - // Battery Backcover - battery_backcover_full(); - - // Main BackCover - back_cover_full(); - - // Full Body - body_full(); - - // Gimbal Ring - gimbal_ring(); - - translate([-41,0,20]) { - translate([135,0,-20]) - gimbal_ring(); +if(show_top_only) { + difference() { + body_full(); + translate([0,0,-37.5]) + cube([200,200,100], center=true); } +} else if(show_bottom_only) { + difference() { + body_full(); + translate([0,0,27]) + cube([200,200,30], center=true); + } +} else { + body_full(); } +// Ruler only +// translate([24.5,0,0]) +// rotate([0,0,0]) +// cube([10,10,10], center=true); -module body() { - // Left Switch Panel - // switch_panel(); +if(show_bars) { + if(show_bars_1) { + translate([0,-10,0]) + difference() { + show_bars_plate(0); - // Right Switch Panel - // mirror([-1,0,0]) - // switch_panel(); + translate([15,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); - // Top Display of the OLED Area - // translate([0,2,0]) - // top_display(); + translate([45,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); - // Center GAP - // translate([0,0,-5]) - // center_face(); + translate([45,20,15]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); - // Left gimbal - translate([25,0,20]) - gimbal_unit_face(); + translate([85,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); - // translate([-87,-25,6]) - // gimbal_side(); - - // Right gimbal - translate([-25,0,20]) { - mirror([-1,0,0]) - gimbal_unit_face(); + translate([85,20,15]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-15,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-45,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); - // mirror([-1,0,0]) - // translate([-107,-25,-14]) - // gimbal_side(); + translate([-45,20,15]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-85,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-85,20,15]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + } + } + if(show_bars_2) { + translate([0,-80,0]) { + difference() { + show_bars_plate(1); + + translate([15,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([45,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([45,20,15]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([85,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([85,20,15]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-15,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-45,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-45,20,15]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-85,20,0]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + + translate([-85,20,15]) + rotate([90,0,0]) + cylinder(h=5, d=1.5, center=true, $fn=round_quality); + } + } } } -/*********** -// To measure the size and location to put the PCB. To be hidden once done. -translate([0,-22,-12.5]) - tx_board(); - ************/ - -module pcb_case() { +if(show_m5) { + translate([0,-20,28]) + rotate([180,0,180]) + m5_body(); } -//display_bracket(); -module display_bracket() { - translate([0,18.5,22]) - difference() { - cube([50,25,3], center=true); - - translate([0,-0.5,0]) - rotate([0,0,90]) - cube([13.4,23.5,5], center=true); +if(show_gimbal_r) { + if(show_right_g) { + translate([-16,0,0]) + gimbal_ring(); + } else { + translate([-16,0,0]) + gimbal_ring(); + translate([110,0,0]) + gimbal_ring(); } } -// OLED Display -module top_display() { - // Measurement: 13.4mm x 23.5mm - translate([0,20.8,20]) - difference() { - cube([50,26.4,2], center=true); - - translate([0,0.5,0]) - rotate([0,0,90]) - cube([17.4,24.9,5], center=true); +module show_bars_plate(bar_types) { + if(bar_types == 0) { + translate([0,20,0]) + rotate([0,0,0]) + difference() { + cube([180,2,8], center=true); + translate([0,0,4]) + rotate([90,0,0]) + cylinder(h=4, d=10, center=true, $fn=round_quality); + } + } else { + translate([0,20,0]) + rotate([0,0,0]) + cube([180,2,8], center=true); } + + translate([85,20,10]) + rotate([0,0,0]) { + cube([10,2,20], center=true); + } - // Top cover - translate([0,35,13.5]) - rotate([90,0,0]) - cube([50,15,2], center=true); - - // Bottom Cover - translate([0,8,13.5]) - rotate([90,0,0]) - cube([50,15,2], center=true); + translate([45,20,10]) + rotate([0,0,0]) + cube([10,2,20], center=true); - // Top Cover Left - translate([-24,21.5,13.5]) - rotate([90,0,90]) - cube([25,15,2], center=true); + translate([-85,20,10]) + rotate([0,0,0]) + cube([10,2,20], center=true); - // Top Cover Right - translate([24,21.5,13.5]) - rotate([90,0,90]) - cube([25,15,2], center=true); + translate([-45,20,10]) + rotate([0,0,0]) + cube([10,2,20], center=true); +} - // Screws - Top Left - translate([-21.5,32.5,14]) - difference() { - cylinder(h=13, d=4, center=true); - cylinder(h=33, d=1.5, center=true); +module body_full() { + if(show_gimbal) { + if(show_right_b && show_left_b) { + body(); + } else if(show_right_b && !show_left_b) { + difference() { + body(); + translate([-60,0,0]) + cube([80,200,80], center=true); + } + } else if(!show_right_b && show_left_b) { + difference() { + body(); + translate([60,0,0]) + cube([80,200,80], center=true); + } } + } - // Screws - Top Right - translate([21.5,32.5,14]) - difference() { - cylinder(h=13, d=4, center=true); - cylinder(h=33, d=1.5, center=true); - } + if(show_battery) { + translate([0,-20,17]) + rotate([180,0,180]) { + difference() { + battery_area(); - // Screw - Bottom Left - translate([-21.5,10.5,14]) - difference() { - cylinder(h=13, d=4, center=true); - cylinder(h=33, d=1.5, center=true); - } + translate([-30,-6,22]) + rotate([0,0,0]) + cube([10,30,7], center=true); - // Screw - Bottom Right - translate([21.5,10.5,14]) - difference() { - cylinder(h=13, d=4, center=true); - cylinder(h=33, d=1.5, center=true); + translate([30,-6,22]) + rotate([0,0,0]) + cube([10,30,7], center=true); + } + } } } -// Switch Panels -module switch_panel() { - difference() { - translate([-53,20,20]) - rotate([0,0,0]) - cube([45,30,2], center=true); +module body() { + // Left gimbal + if(show_left) { + translate([25,0,20]) { + if(show_gimbal_u) { + difference() { + gimbal_unit_face(); + + translate([-85,-15,-55]) + cube([90,90,80], center=true); + } + } else if(show_gimbal_b) { + difference() { + gimbal_unit_face(); + + translate([-85,-15,25]) + cube([90,90,80], center=true); + } + } else { + gimbal_unit_face(); + } + } + } - translate([-66,22,20]) - rocker_switch(false); + // Right gimbal + if(show_right) { + translate([-25,0,20]) + mirror([-1,0,0]) + if(show_gimbal_u) { + difference() { + gimbal_unit_face(); - translate([-53,22,20]) - rocker_switch(false); + translate([-85,-15,-55]) + cube([90,90,80], center=true); + } + } else if(show_gimbal_b) { + difference() { + gimbal_unit_face(); - translate([-40,22,20]) - rocker_switch(false); + translate([-85,-15,25]) + cube([90,90,80], center=true); + } + } else { + gimbal_unit_face(); + } } - - // Side - Left - translate([76,23,6]) - rotate([0,90,0]) - cube([30,24,2], center=true); - - // Side - Right - translate([30,23,6]) - rotate([0,90,0]) - cube([30,24,2], center=true); - - // Side - Top - translate([53,35,6]) - rotate([90,0,0]) - cube([48,30,2], center=true); - - // Screw holders - // Screw - Top Left - translate([73.5,32.5,7]) - difference() { - cylinder(h=28, d=4, center=true); - cylinder(h=29, d=1.5, center=true); - } - - // Screw - Top Right - translate([32.5,32.5,7]) - difference() { - cylinder(h=28, d=4, center=true); - cylinder(h=29, d=1.5, center=true); - } - - // Screw - Bottom Left - translate([73.5,12.5,7]) - difference() { - cylinder(h=28, d=4, center=true); - cylinder(h=29, d=1.5, center=true); - } - - // Screen - Bottom Right - translate([32.5,12.5,7]) - difference() { - cylinder(h=28, d=4, center=true); - cylinder(h=29, d=1.5, center=true); - } } -// Center Top Part -module center_face() { - // Side Walls - translate([-10,-22.5,11]) - rotate([90,0,90]) - cube([65,20,2], center=true); - translate([10,-22.5,11]) - rotate([90,0,90]) - cube([65,20,2], center=true); - +module gimbal_ring() { difference() { - // Center Gap - translate([0,-25,20]) - rotate([0,0,90]) - cube([70,20,2], center=true); - - // Center - Top Switch - translate([0,-10,18]) - rotate([0,90,90]) - rocker_switch(false); - - // Center - Middle Switch - translate([0,-25,18]) - rotate([0,90,90]) - rocker_switch(false); - - // Center - Bottom Switch - translate([0,-40,18]) - rotate([0,90,90]) - rocker_switch(false); + gimbal_ring_full(); - // Remove bottom... - translate([0,-60,20]) - rotate([0,0,90]) - cube([10,30,5], center=true); + translate([-47,-25,23.5]) + cylinder(h=6, d1=47.5, d2=57.5, center=true, $fn=round_quality); } +} - // Bottom - translate([0,-55.5,8.5]) - rotate([90,0,0]) - cube([22,25,2], center=true); +module battery_area() { + // Battery base top + /*** + translate([0,-5,18]) + rotate([0,0,0]) + difference() { + cube([60,67,1], center=true); - // Top - translate([0,9.5,11]) - rotate([90,0,0]) - cube([22,30,3], center=true); + // Side hole for Throttle, Yaw, Pitch and Roll connectors + translate([16,3,0]) + cube([15,55,2], center=true); - // Bottom HOOK - translate([0,-57.5,18.5]) { - difference() { - rotate([90,0,0]) - cube([10,5,5], center=true); - translate([0,-2,0]) - cylinder(h=6, d=5, center=true); - } - translate([0,-3,0]) - difference() { - cylinder(h=5, d=10, center=true); - cylinder(h=6, d=5, center=true); - } - } + // Hole for Power input + translate([0,-19.5,0]) + cube([10,10,2], center=true); + } + ***/ - /*** - // Screw - Top Left - translate([-7.5,7,11]) - difference() { - cylinder(h=16, d=4, center=true); - cylinder(h=round_quality, d=1.5, center=true); - } + // Battery base top side left + // translate([28.5,-5,13]) + // rotate([0,90,0]) + // cube([10,65,3], center=true); + + // Battery base top side right + // translate([-28.5,-5,13]) + // rotate([0,90,0]) + // cube([10,65,3], center=true); - // Screw - Top Right - translate([7.5,7,11]) - difference() { - cylinder(h=16, d=4, center=true); - cylinder(h=round_quality, d=1.5, center=true); - } + // Battery base top side bottom + translate([0,-38,15]) + rotate([90,0,0]) { + difference() { + cube([60,20,1], center=true); - // Screw - Bottom Left - translate([-7.5,-53,11]) - difference() { - cylinder(h=16, d=4, center=true); - cylinder(h=round_quality, d=1.5, center=true); - } + translate([15,-3,0]) + cylinder(h=10, d=1.5, center=true, $fn=round_quality); - // Screw - Bottom Right - translate([7.5,-53,11]) - difference() { - cylinder(h=16, d=4, center=true); - cylinder(h=round_quality, d=1.5, center=true); + translate([-15,-3,0]) + cylinder(h=10, d=1.5, center=true, $fn=round_quality); + } } - ***/ -} + translate([0,-37,15]) + rotate([90,0,0]) + cube([60,20,2], center=true); -// Rocker Switch Hole Dimension 8.5mm x 13.2mm (Bracket size 10.3mm x 14.8mm) -module rocker_switch(bracket = false) { - if(bracket) - cube([10.7,15.2,9.5], center=true); - else - cube([9,14.2,9.5], center=true); -} + // Battery base top side top + translate([0,27,12]) + rotate([90,0,0]) { + difference() { + cube([60,10,3], center=true); -// The MOCK UP PCB -module tx_board() { - difference() { - translate([0,0,0]) - rotate([0,0,0]) - cube([75,50,1.2], center=true); - - // Left groove - groove(); + translate([0,-4,0]) + cylinder(h=4, d=10, center=true, $fn=round_quality); - // Right Groove - mirror([1,0,0]) { - groove(); + translate([15,-1,0]) + cylinder(h=10, d=1.5, center=true, $fn=round_quality); + + translate([-15,-1,0]) + cylinder(h=10, d=1.5, center=true, $fn=round_quality); + } + translate([0,6,0]) + cube([60,10,3], center=true); } - } -} -module groove() { - translate([-35,0,0]) - rotate([90,0,90]) - cube([20,2,5], center=true); - - translate([-38,10,0]) - rotate([0,0,45]) - cube([8,8,2.5], center=true); + // Supporters + translate([0,27.5,28]) + cube([2,2,10], center=true); + translate([10,27.5,28]) + cube([2,2,10], center=true); + translate([-10,27.5,28]) + cube([2,2,10], center=true); + translate([-20,27.5,28]) + cube([2,2,10], center=true); + translate([20,27.5,28]) + cube([2,2,10], center=true); + + // Seperator + // translate([0,-5,23]) + // rotate([0,0,0]) { + // cube([60,67,1], center=true); + // } + + // Battery base bottom + translate([0,-5,33]) + rotate([0,0,0]) { + cube([60,67,1], center=true); + } - translate([-38,-10,0]) - rotate([0,0,45]) - cube([8,8,2.5], center=true); -} + // Battery base top cover + translate([0,-38,28]) + rotate([90,0,0]) + cube([62,10,1], center=true); -module gimbal_ring() { - difference() { - gimbal_ring_full(); + // Battery base bottom sides + translate([28.5,-5,26]) + rotate([0,90,0]) + cube([15,67,2], center=true); + translate([28.5,-5,23.5]) + rotate([0,90,0]) + cube([10,67,2], center=true); + translate([-28.5,-5,26]) + rotate([0,90,0]) + cube([15,67,2], center=true); + translate([-28.5,-5,23.5]) + rotate([0,90,0]) + cube([10,67,2], center=true); - translate([-47,-25,23.5]) - cylinder(h=6, d1=47.5, d2=57.5, center=true, $fn=round_quality); - } + } module gimbal_ring_full() { @@ -849,27 +766,120 @@ module gimbal_unit_face() { translate([-88,-25,0]) { // Left translate([-32.5,0,-14]) - rotate([90,0,90]) + rotate([90,0,90]) { cube([63,30,2], center=true); + translate([0,0,41.4]) + rotate([0,90,0]) + difference() { + cylinder(h=67, d=90, center=true, $fn=800); + + translate([-2.6,0,0]) + cube([90,90,90], center=true); + } + } + // Right - translate([32.5,0,-14]) + translate([32.5,0,-14]) { rotate([90,0,90]) difference() { cube([63,30,2], center=true); translate([-27.5,6.1,0]) cylinder(h=64, d=3, center=true, $fn=100); + translate([0,-2.5,0]) + cube([20,20,5], center=true); } + // Rod Holder + /*** + if(!show_gimbal_b) { + if(show_right && show_left) { + translate([32,-27.5,6]) + rotate([0,90,0]) + difference() { + cylinder(h=62, d=10.5, center=true, $fn=100); + cylinder(h=69, d=2, center=true, $fn=100); + + // Small Gaps between the Rods + translate([0,0,0]) + rotate([0,0,0]) + cube([20,20,60], center=true); + + } + } + } + ***/ + + if((show_left) && (!show_right)) { + translate([32,-27.5,6]) + rotate([0,90,0]) + difference() { + cylinder(h=62, d=10.5, center=true, $fn=100); + cylinder(h=69, d=2, center=true, $fn=100); + + // Small Gaps between the Rods + translate([0,0,1]) + rotate([0,0,0]) + cube([20,20,62], center=true); + + } + } + + if((!show_left) && (show_right)) { + translate([32,-27.5,6]) + rotate([0,90,0]) + difference() { + cylinder(h=62, d=10.5, center=true, $fn=100); + cylinder(h=69, d=2, center=true, $fn=100); + + // Small Gaps between the Rods + translate([0,0,1]) + rotate([0,0,0]) + cube([20,20,62], center=true); + + } + } + } + // Bottom translate([0,-32.5,-14]) - rotate([90,0,0]) - cube([67,30,2], center=true); + rotate([90,0,0]) { + difference() { + cube([67,30,2], center=true); + + translate([-22,9,0]) + cylinder(h=8, d=1.5, center=true, $fn=100); + + translate([-22,-6,0]) + cylinder(h=8, d=1.5, center=true, $fn=100); + + translate([18,-6,0]) + cylinder(h=8, d=1.5, center=true, $fn=100); + + translate([18,9,0]) + cylinder(h=8, d=1.5, center=true, $fn=100); + } + } // Top translate([0,32.5,-14]) - rotate([90,0,0]) - cube([67,30,2], center=true); + rotate([90,0,0]) { + difference() { + cube([67,30,2], center=true); + + translate([-22,9,0]) + cylinder(h=8, d=1.5, center=true, $fn=100); + + translate([-22,-6,0]) + cylinder(h=8, d=1.5, center=true, $fn=100); + + translate([18,-6,0]) + cylinder(h=8, d=1.5, center=true, $fn=100); + + translate([18,9,0]) + cylinder(h=8, d=1.5, center=true, $fn=100); + } + } difference() { translate([0,0,0]) @@ -900,81 +910,67 @@ module gimbal_unit_face() { translate([27.25,-27.25,0]) rotate([0,0,0]) cylinder(h=5,d=5.6, center=true, $fn=round_quality); - /* - translate([0,0,0]) - rotate([0,0,0]) - cube([77,51,4], center=true); - */ } } - // Just a ruler - /*** - translate([-13.9,-44.4]) - cube([100,10,10], center=true); - ***/ - - // Screw Holders - // Top Left - /********** - translate([70.5,7.5,-13]) - difference() { - cylinder(h=27, d=4, center=true, $fn=round_quality); - cylinder(h=33, d=1.5, center=true, $fn=round_quality); - } - - // Top Right - translate([-55.5,7.5,-13]) - difference() { - cylinder(h=27, d=4, center=true, $fn=round_quality); - cylinder(h=33, d=1.5, center=true, $fn=round_quality); - } - - // Bottom Left - translate([70.5,-57.5,-13]) + if(!show_gimbal_u) { + // Back cover... difference() { - cylinder(h=27, d=4, center=true, $fn=round_quality); - cylinder(h=33, d=1.5, center=true, $fn=round_quality); - } - - // Bottom Right - translate([-55.5,-57.5,-13]) - difference() { - cylinder(h=27, d=4, center=true, $fn=round_quality); - cylinder(h=33, d=1.5, center=true, $fn=round_quality); + back_cover_slim(); + + translate([39,4.5,-38]) + rotate([45,0,0]) + cube([66,40,6], center=true); + + translate([39,-60.4,-32.3]) + rotate([-45,0,0]) + cube([65,40,6], center=true); + + translate([69,-25,-35.3]) + rotate([0,-36,0]) + cube([12,67,6], center=true); } - *******/ + } } +module back_cover_slim() { + translate([34,-25,-35.5]) + cube([55,55,2], center=true); + translate([39,4.5,-32.3]) + rotate([45,0,0]) + cube([66,10,2], center=true); + translate([39,-54.5,-32.3]) + rotate([-45,0,0]) + cube([65,10,2], center=true); + translate([66,-25,-32.3]) + rotate([0,-36,0]) + cube([12,67,2], center=true); + translate([5.5,-25,-32.3]) + rotate([0,90,0]) + cube([8.4,67,2], center=true); +} -// module roundedcube(size = [1, 1, 1], center = false, radius = 0.5, apply_to = "all") { module m5_body() { + translate([0,0,-1]) difference() { if(!draft) { - rounded_corner_cube(8, [56.6,56.6,18]); + rounded_corner_cube(8, [56.6,56.6,17.5]); } else { - roundedcube([56.6,56.6,18], center = true, 0.5); + roundedcube([56.6,56.6,17.5], center = true, 0.5); } // cube([50.6, 50.6, 25], center=true); if(!draft) { - rounded_corner_cube(8, [50.6,50.6,18]); + rounded_corner_cube(8, [50.6,50.6,17.5]); } else { - roundedcube([50.6,50.6,18], center = true, 0.5); + roundedcube([50.6,50.6,17.5], center = true, 0.5); } translate([0,0,1]) if(!draft) { - rounded_corner_cube(8, [54.6,54.6,18]); + rounded_corner_cube(8, [54.6,54.6,17.5]); } else { - roundedcube([54.6,54.6,18], center = true); + roundedcube([54.6,54.6,17.5], center = true); } - // Reset Button - /***** - translate([-16,-30,0]) - rotate([90,0,0]) - cylinder(h=10, d=8, center=true, $fn=round_quality); - *****/ - // Power Button translate([25,13,0]) rotate([90,90,90]) @@ -985,9 +981,42 @@ module m5_body() { rotate([0,90,90]) cube([4,18.5,10], center=true); + // Speaker Holes + translate([-25,11,0]) + rotate([90,0,90]) + cylinder(h=10, d=3, center=true, $fn=round_quality); + translate([-25,5,0]) + rotate([90,0,90]) + cylinder(h=10, d=3, center=true, $fn=round_quality); + translate([-25,-1,0]) + rotate([90,0,90]) + cylinder(h=10, d=3, center=true, $fn=round_quality); + translate([-25,-7,0]) + rotate([90,0,90]) + cylinder(h=10, d=3, center=true, $fn=round_quality); + translate([-25,-13,0]) + rotate([90,0,90]) + cylinder(h=10, d=3, center=true, $fn=round_quality); } + // Center Holder + translate([0,-31.5,4.3]) + rotate([0,0,0]) { + difference() { + cube([58,8,28], center=true); + + // Screw Holders + translate([20,-3,9]) + rotate([90,0,0]) + cylinder(h=10, d=2, center=true, $fn=round_quality); + translate([-20,-3,9]) + rotate([90,0,0]) + cylinder(h=10, d=2, center=true, $fn=round_quality); + } + } + // Center Rod + /**** translate([0,-32.5,0]) rotate([0,90,0]) difference() { @@ -998,41 +1027,36 @@ module m5_body() { translate([0,0,28]) rotate([0,0,0]) cube([20,20,0.5], center=true); + translate([0,0,30.7]) + rotate([0,0,0]) + cube([20,20,5], center=true); translate([0,0,-28]) rotate([0,0,0]) cube([20,20,0.5], center=true); + translate([0,0,-30.7]) + rotate([0,0,0]) + cube([20,20,5], center=true); } - - // Battery base top - translate([0,-5,18]) - rotate([0,0,0]) + ***/ + // Bottom HOOK + rotate([0,0,0]) { + translate([0,-35,-7.2]) { difference() { - cube([60,67,1], center=true); - - // Side hole for Throttle, Yaw, Pitch and Roll connectors - translate([16,3,0]) - cube([15,55,2], center=true); - - // Hole for Power input - translate([0,-19.5,0]) - cube([10,10,2], center=true); + rotate([90,0,0]) + cube([10,5,5], center=true); + translate([0,-2,0]) + cylinder(h=6, d=5, center=true, $fn=round_quality); } - - // Battery base top side bottom - translate([0,-38,11]) - rotate([90,0,0]) - cube([60,20,1], center=true); - - // Battery base top side top - translate([0,28,14]) - rotate([90,0,0]) + translate([0,3.5,0]) + cube([10,5,5], center=true); + translate([0,-3,0]) difference() { - cube([60,10,1], center=true); - - translate([0,-4,0]) - cylinder(h=4, d=10, center=true, $fn=round_quality); + cylinder(h=5, d=10, center=true, $fn=round_quality); + cylinder(h=6, d=5, center=true, $fn=round_quality); } + } + } } module rounded_corner_cube(diameter, dimension) { diff --git a/README.md b/README.md index 67a9ffe..ec61824 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ ESP32 Dev Pinout: U2_TXD / GPIO17 | [ ] [ ] | GPIO26 / ADC2_9 / DAC2 V_SPI_CS0 / GPIO5 | [ ] ___________ [ ] | GPIO25 / ADC2_8 / DAC1 SCK / V_SPI_CLK / GPIO18 | [ ] | | [ ] | GPIO33 / ADC1_5 / Touch8 / XTAL32 - U0_CTS / MSIO / V_SPI_Q / GPIO19 | [ ] | | [ ] | GPIO32 / ADC1_4 / Touch9 / XTAL32 + U0_CTS / MISO / V_SPI_Q / GPIO19 | [ ] | | [ ] | GPIO32 / ADC1_4 / Touch9 / XTAL32 SDA / V_SPI_HD / GPIO21 | [ ] | | [ ] | GPIO35 / ADC1_7 CLK2 / U0_RXD / GPIO3 | [ ] | | [ ] | GPIO34 / ADC1_6 CLK3 / U0_TXD / GPIO1 | [ ] | | [ ] | GPIO39 / ADC1_3 / SensVN @@ -64,3 +64,14 @@ ESP32 Dev Pinout: # REF: Pinout and labels - https://docs.m5stack.com/en/core/core2_for_aws MP3 Sound generator - https://ttsmp3.com/ + +GPIO35 - Throttle +GPIO36 - Yaw +GPIO32 - Pitch +GPIO33 - Roll + +GPIO27 - CSN - BLUE +GPIO19 - CE - WHITE + - SCK - GREEN + - MOSI - YELLOW + - MISO - RED diff --git a/platformio.ini b/platformio.ini index 05a619e..9d5610a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -18,3 +18,4 @@ board_build.partitions = bert2M_fat12M_16MB.csv lib_deps = m5stack/M5Core2@^0.1.0 lorol/LittleFS_esp32@^1.0.6 + lemmingdev/ESP32-BLE-Gamepad@^0.3.4 diff --git a/src/BLE.cpp b/src/BLE.cpp new file mode 100644 index 0000000..ee495b3 --- /dev/null +++ b/src/BLE.cpp @@ -0,0 +1,51 @@ +#include "BLE.h" + +BleGamepad bleGamepad; + +BLE::BLE(void) { + updated = true; +} + +void BLE::begin(void) { + updated = true; + ble_begin = true; +} + + +void BLE::end(void) { + ble_begin = false; + ble_started = false; + + Serial.printf("BLEGamepad is disconnected"); + bleGamepad.end(); +} + + +void BLE::update(void) { + // Starts to connect when receive this... + if(ble_begin) { + if(!ble_started) { + Serial.printf("Starting BLEGamepad."); + bleGamepad.begin(); + Serial.printf("BLEGamepad OK"); + ble_started = true; + } + + + if(bleGamepad.isConnected()) { + if((uint32_t)(millis() - last_updated) > 30) { + int16_t throttle = map(inputs.throttle, 0, 4096, -32767, 32767); // Throttle + int16_t yaw = map(inputs.yaw, 0, 4096, -32767, 32767); // Yaw + int16_t pitch = map(inputs.pitch, 0, 4096, -32767, 32767); // Pitch + int16_t roll = map(inputs.roll, 0, 4096, -32767, 32767); // Roll + + bleGamepad.setAxes(yaw, throttle, roll, pitch, 0, 0, DPAD_CENTERED); + + last_updated = millis(); + // Serial.printf("Sent\n"); + } + } + } +} + +BLE ble; diff --git a/src/BLE.h b/src/BLE.h new file mode 100644 index 0000000..04fb17b --- /dev/null +++ b/src/BLE.h @@ -0,0 +1,25 @@ +#ifndef _BLE_H +#define _BLE_H + +#include +#include +#include +#include "Inputs.h" + +class BLE { + public: + bool ble_begin = false; + bool updated = false; + bool ble_started = false; + + BLE(void); + void begin(void); + void end(void); + void update(void); + + private: + uint32_t last_updated = 0; +}; + +extern BLE ble; +#endif diff --git a/src/BLEGamepad.cpp b/src/BLEGamepad.cpp new file mode 100644 index 0000000..173e85d --- /dev/null +++ b/src/BLEGamepad.cpp @@ -0,0 +1,61 @@ +#include "BLEGamepad.h" + +BLEGamepad::BLEGamepad(void) { + updated = true; +} + +void BLEGamepad::begin(void) { + updated = true; +} + + +void BLEGamepad::show(TFT_eSprite *m) { + if(!ble_begin) { + ble_begin = true; + ble.begin(); + } + + if((uint32_t) (millis() - last_updated) > 50) { + updated = true; + } + + if(updated) { + m->fillRect(0, 0, 320, 240, BLACK); + m->setTextColor(WHITE, BLACK); + m->setTextSize(2); + m->setCursor(0,0); + m->print(String(inputs.throttle)); + m->setCursor(0,16); + m->print(String(inputs.yaw)); + m->setCursor(0,32); + m->print(String(inputs.pitch)); + m->setCursor(0,48); + m->print(String(inputs.roll)); + + m->setCursor(64,64); + m->print("BLE GAMEPAD"); + + m->pushSprite(0,0); + + updated = false; + last_updated = millis(); + } + + + // Key Input Handler + if(M5.BtnC.wasPressed()) { + if(ble_begin) { + ble_begin = false; + ble.end(); + } + + screen.current_screen = SCREEN_MENU; + screen.updated = true; + } + + // Temporary connect from here... + if(M5.BtnA.wasPressed()) { + } +} + +BLEGamepad blegamepad; diff --git a/src/BLEGamepad.h b/src/BLEGamepad.h new file mode 100644 index 0000000..676e99c --- /dev/null +++ b/src/BLEGamepad.h @@ -0,0 +1,24 @@ +#ifndef _BLEGAMEPAD_H +#define _BLEGAMEPAD_H + +#include +#include +#include "BLE.h" +#include "Inputs.h" +#include "Screen.h" + +class BLEGamepad { + public: + bool ble_begin = false; + bool updated = false; + + BLEGamepad(void); + void begin(void); + void show(TFT_eSprite *m); + + private: + uint32_t last_updated = 0; +}; + +extern BLEGamepad blegamepad; +#endif diff --git a/src/GimbalGraph.cpp b/src/GimbalGraph.cpp new file mode 100644 index 0000000..7349516 --- /dev/null +++ b/src/GimbalGraph.cpp @@ -0,0 +1,5 @@ +#include "GimbalGraph.h" + +GimbalGraph::GimbalGraph(void) { +} + diff --git a/src/GimbalGraph.h b/src/GimbalGraph.h new file mode 100644 index 0000000..4df5ec3 --- /dev/null +++ b/src/GimbalGraph.h @@ -0,0 +1,14 @@ +#ifndef _GIMBAL_GRAPH_H +#define _GIMBAL_GRAPH_H + +#include + +class GimbalGraph { + public: + GimbalGraph(void); + + private: +}; + +extern GimbalGraph gimbalgraph; +#endif diff --git a/src/Inputs.cpp b/src/Inputs.cpp new file mode 100644 index 0000000..e04e8fd --- /dev/null +++ b/src/Inputs.cpp @@ -0,0 +1,259 @@ +#include "Inputs.h" + +Inputs::Inputs(void) { +} + + +void Inputs::begin(void) { + throttle_raw = 0; + yaw_raw = 0; + pitch_raw = 0; + roll_raw = 0; + + // Prepare the storage engine for TYPR + for(int i = 0; i < MEDIAN_TOTAL; i++) { + throttle_pool[i] = 0; + yaw_pool[i] = 0; + pitch_pool[i] = 0; + roll_pool[i] = 0; + } +} + + +void Inputs::read(void) { + throttle_raw = analogRead(THROTTLE_PIN); + yaw_raw = analogRead(YAW_PIN); + pitch_raw = analogRead(PITCH_PIN); + roll_raw = analogRead(ROLL_PIN); + + throttle = pool_insert(THROTTLE, throttle_raw); + yaw = pool_insert(YAW, yaw_raw); + pitch = pool_insert(PITCH, pitch_raw); + roll = pool_insert(ROLL, roll_raw); +} + + +/* + * median_get: + * To get the median from the data depending on the median_type + * + * E.g.: + * retval = median_get(THROTTLE); + */ +uint16_t Inputs::median_get(uint8_t median_type) { + bool inserted = false; + + uint16_t median_tmp[MEDIAN_TOTAL]; + + // Loop through the variable to determine position to insert + // [ 12, 32, 4 ,0, 50, 2, 10, 10, 5, 20, 0 ] + /* + [ 12 ] + [ 12, 32 ] + [ 4, 12, 32 ] + [ 0, 4, 12, 32 ] + [ 0, 4, 12, 32, 50 ] + [ 0, 2, 4, 12, 32, 50 ] + + */ + + // Initial + uint16_t temp_val = 0; + uint16_t total_insert = 1; + + // Search on type + if(median_type == THROTTLE) { + median_tmp[0] = throttle_pool[0]; + } else if(median_type == YAW) { + median_tmp[0] = yaw_pool[0]; + } else if(median_type == PITCH) { + median_tmp[0] = pitch_pool[0]; + } else if(median_type == ROLL) { + median_tmp[0] = roll_pool[0]; + } + + // Loop insert and sort + for(int raw_count = 1; raw_count < MEDIAN_TOTAL; raw_count++) { + inserted = false; + + if(median_type == THROTTLE) { + temp_val = throttle_pool[raw_count]; + } else if(median_type == YAW) { + temp_val = yaw_pool[raw_count]; + } else if(median_type == PITCH) { + temp_val = pitch_pool[raw_count]; + } else if(median_type == ROLL) { + temp_val = roll_pool[raw_count]; + } + + for(int median_count = 0; median_count < total_insert; median_count++) { + if(!inserted) { + + if(temp_val < median_tmp[median_count]) { + inserted = true; + + // Reverse copy and insert + for(int median_reverse = total_insert + 1; median_reverse > median_count; median_reverse--) { + median_tmp[median_reverse] = median_tmp[median_reverse - 1]; + } + + // Insert the detected + median_tmp[median_count] = temp_val; + + // Increase total insertion + total_insert++; + } + } + } + + // Nothing was inserted... so put at the last. + if(!inserted) { + median_tmp[total_insert++] = temp_val; + } + } + + // Return the result + // return median_tmp[MEDIAN_POS]; + // Using RC dead band way....**** NEED TO IMPROvE!! + if(median_type == THROTTLE) { + if(throttle > median_tmp[MEDIAN_POS]) { + if(throttle - median_tmp[MEDIAN_POS] > RC_DEADBAND) { + return median_tmp[MEDIAN_POS]; + } else { + if(median_tmp[MEDIAN_POS] - throttle > RC_DEADBAND) { + return median_tmp[MEDIAN_POS]; + } else { + return throttle; + } + } + } + } else if(median_type == YAW) { + if(yaw > median_tmp[MEDIAN_POS]) { + if(yaw - median_tmp[MEDIAN_POS] > RC_DEADBAND) { + return median_tmp[MEDIAN_POS]; + } else { + if(median_tmp[MEDIAN_POS] - yaw > RC_DEADBAND) { + return median_tmp[MEDIAN_POS]; + } else { + return yaw; + } + } + } + } else if(median_type == PITCH) { + if(pitch > median_tmp[MEDIAN_POS]) { + if(pitch - median_tmp[MEDIAN_POS] > RC_DEADBAND) { + return median_tmp[MEDIAN_POS]; + } else { + if(median_tmp[MEDIAN_POS] - pitch > RC_DEADBAND) { + return median_tmp[MEDIAN_POS]; + } else { + return pitch; + } + } + } + } else if(median_type == ROLL) { + if(roll > median_tmp[MEDIAN_POS]) { + if(roll - median_tmp[MEDIAN_POS] > RC_DEADBAND) { + return median_tmp[MEDIAN_POS]; + } else { + if(median_tmp[MEDIAN_POS] - roll > RC_DEADBAND) { + return median_tmp[MEDIAN_POS]; + } else { + return roll; + } + } + } + } + +} + + +uint16_t Inputs::throttle_insert(uint16_t val) { + // Insert to the array...at the last + for(int i = 1; i < MEDIAN_TOTAL; i++) + // Shift to left + throttle_pool[i - 1] = throttle_pool[i]; + + throttle_pool[MEDIAN_TOTAL - 1] = val; + + // Find median.... + return median_get(THROTTLE); +} + + +uint16_t Inputs::yaw_insert(uint16_t val) { + // Insert to the array...at the last + for(int i = 1; i < MEDIAN_TOTAL; i++) + // Shift to left + yaw_pool[i - 1] = yaw_pool[i]; + + yaw_pool[MEDIAN_TOTAL - 1] = val; + + // Find median.... + return median_get(YAW); +} + + +uint16_t Inputs::pitch_insert(uint16_t val) { + // Insert to the array...at the last + for(int i = 1; i < MEDIAN_TOTAL; i++) + // Shift to left + pitch_pool[i - 1] = pitch_pool[i]; + + pitch_pool[MEDIAN_TOTAL - 1] = val; + + // Find median.... + return median_get(PITCH); +} + + +uint16_t Inputs::roll_insert(uint16_t val) { + // Insert to the array...at the last + for(int i = 1; i < MEDIAN_TOTAL; i++) + // Shift to left + roll_pool[i - 1] = roll_pool[i]; + + roll_pool[MEDIAN_TOTAL - 1] = val; + + // Find median.... + return median_get(ROLL); +} + + +/* + * pool_insert: + * To insert the data into the median pool depending on type of the variable + * + * E.g.: + * throttle_value = pool_insert(THROTTLE); + */ +uint16_t Inputs::pool_insert(uint8_t pool_type, uint16_t val) { + // Insert to the array...at the last of the array + for(int i = 1; i < MEDIAN_TOTAL; i++) { + // Shift to left + if(pool_type == THROTTLE) { + throttle_pool[i - 1] = throttle_pool[i]; + } else if(pool_type == YAW) { + yaw_pool[i - 1] = yaw_pool[i]; + } else if(pool_type == PITCH) { + pitch_pool[i - 1] = pitch_pool[i]; + } else if(pool_type == ROLL) { + roll_pool[i - 1] = roll_pool[i]; + } + } + + // Find median.... + if(pool_type == THROTTLE) { + throttle_pool[MEDIAN_TOTAL - 1] = val; + } else if(pool_type == YAW) { + yaw_pool[MEDIAN_TOTAL - 1] = val; + } else if(pool_type == ROLL) { + roll_pool[MEDIAN_TOTAL - 1] = val; + } else if(pool_type == PITCH) { + pitch_pool[MEDIAN_TOTAL - 1] = val; + } + return median_get(pool_type); +} + + +Inputs inputs; diff --git a/src/Inputs.h b/src/Inputs.h new file mode 100644 index 0000000..b077a6e --- /dev/null +++ b/src/Inputs.h @@ -0,0 +1,56 @@ +#ifndef _INPUTS_H +#define _INPUTS_H + +#include + +#define THROTTLE_PIN 35 +#define YAW_PIN 36 +#define PITCH_PIN 32 +#define ROLL_PIN 33 + +#define MEDIAN_TOTAL 11 +#define MEDIAN_POS MEDIAN_TOTAL/2 + +// For RC Deadband +#define RC_DEADBAND 5 + +enum input_names { + THROTTLE = 0, + YAW, + PITCH, + ROLL +}; + +class Inputs { + public: + uint16_t throttle = 0; + uint16_t yaw = 0; + uint16_t pitch = 0; + uint16_t roll = 0; + + Inputs(void); + void begin(void); + void read(void); + + private: + uint16_t throttle_pool[MEDIAN_TOTAL]; + uint16_t yaw_pool[MEDIAN_TOTAL]; + uint16_t pitch_pool[MEDIAN_TOTAL]; + uint16_t roll_pool[MEDIAN_TOTAL]; + uint16_t tmp_median_store[MEDIAN_TOTAL]; + + uint16_t throttle_raw; + uint16_t yaw_raw; + uint16_t pitch_raw; + uint16_t roll_raw; + + uint16_t median_get(uint8_t median_type); + uint16_t throttle_insert(uint16_t val); + uint16_t yaw_insert(uint16_t val); + uint16_t pitch_insert(uint16_t val); + uint16_t roll_insert(uint16_t val); + uint16_t pool_insert(uint8_t pool_type, uint16_t val); +}; + +extern Inputs inputs; +#endif diff --git a/src/Screen.cpp b/src/Screen.cpp index fac842d..7e44a93 100644 --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -20,6 +20,9 @@ void Screen::begin(void) { */ // Initial value updated = true; + + stickcalibration.begin(); + M5.Lcd.fillScreen(BLACK); mainscreen_buffer.createSprite(320, 240); } @@ -36,6 +39,10 @@ void Screen::update(void) { menu_reboot(); } else if(current_screen == SCREEN_MENU_POWEROFF) { menu_poweroff(); + } else if(current_screen == SCREEN_MENU_BLUETOOTH) { + blegamepad.show(&mainscreen_buffer); + } else if(current_screen == SCREEN_MENU_STICK_CALIBRATION) { + stickcalibration.mydebug(&mainscreen_buffer); } last_screen_update = millis(); @@ -171,6 +178,9 @@ void Screen::menu(void) { current_screen = SCREEN_MENU_POWEROFF; } else if(current_menu == MENU_BLUETOOTH) { current_screen = SCREEN_MENU_BLUETOOTH; + } else if(current_menu == MENU_STICK_CALIBRATION) { + current_screen = SCREEN_MENU_STICK_CALIBRATION; + stickcalibration.updated = true; } updated = true; } diff --git a/src/Screen.h b/src/Screen.h index 20ec59b..4c4d6b5 100644 --- a/src/Screen.h +++ b/src/Screen.h @@ -3,7 +3,9 @@ #include #include +#include "BLEGamepad.h" #include "Speak.h" +#include "StickCalibration.h" #define REFRESH_TIME 1 #define INTRO_TIME 100 @@ -19,7 +21,8 @@ enum screen_names { SCREEN_MENU, SCREEN_MENU_REBOOT, SCREEN_MENU_POWEROFF, - SCREEN_MENU_BLUETOOTH + SCREEN_MENU_BLUETOOTH, + SCREEN_MENU_STICK_CALIBRATION }; enum menu_items { @@ -46,6 +49,9 @@ enum selection_choice_yesno { class Screen { public: + uint8_t current_screen = SCREEN_INTRO; + bool updated = false; + Screen(void); void begin(void); void intro(void); @@ -56,9 +62,7 @@ class Screen { void update(void); private: - uint8_t current_screen = SCREEN_INTRO; uint32_t last_screen_update = 0; - bool updated = false; }; extern Screen screen; diff --git a/src/StickCalibration.cpp b/src/StickCalibration.cpp new file mode 100644 index 0000000..0ca9461 --- /dev/null +++ b/src/StickCalibration.cpp @@ -0,0 +1,44 @@ +#include "StickCalibration.h" + +StickCalibration::StickCalibration(void) { + updated = true; +} + +void StickCalibration::begin(void) { + updated = true; +} + + +void StickCalibration::mydebug(TFT_eSprite *m) { + if((uint32_t) (millis() - last_updated) > 50) { + updated = true; + } + + if(updated) { + m->fillRect(0, 0, 320, 240, BLACK); + m->setTextColor(WHITE, BLACK); + m->setTextSize(2); + m->setCursor(0,0); + m->print(String(inputs.throttle)); + m->setCursor(0,16); + m->print(String(inputs.yaw)); + m->setCursor(0,32); + m->print(String(inputs.pitch)); + m->setCursor(0,48); + m->print(String(inputs.roll)); + + m->pushSprite(0,0); + + updated = false; + last_updated = millis(); + } + + + // Key Input Handler + if(M5.BtnC.wasPressed()) { + screen.current_screen = SCREEN_MENU; + screen.updated = true; + } +} + +StickCalibration stickcalibration; diff --git a/src/StickCalibration.h b/src/StickCalibration.h new file mode 100644 index 0000000..2a5722b --- /dev/null +++ b/src/StickCalibration.h @@ -0,0 +1,21 @@ +#ifndef _STICK_CALIBRATION_H +#define _STICK_CALIBRATION_H + +#include +#include +#include "Inputs.h" +#include "Screen.h" + +class StickCalibration { + public: + StickCalibration(void); + void begin(void); + void mydebug(TFT_eSprite *m); + bool updated = false; + + private: + uint32_t last_updated = 0; +}; + +extern StickCalibration stickcalibration; +#endif diff --git a/src/main.cpp b/src/main.cpp index 51d943c..23e2209 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -23,9 +23,11 @@ void setup() { storage.begin(); customwifi.begin(); + inputs.begin(); web.begin(); speak.welcome(); + // Task Creation xTaskCreatePinnedToCore( taskScreen, @@ -39,7 +41,7 @@ void setup() { xTaskCreatePinnedToCore( taskWeb, - "TaskWeb", // Name of the process + "TaskWeb", // Name of the process 4096, // This stack size can be checked & adjusted by reading the Stack Highwater NULL, 4, // Priority @@ -57,6 +59,26 @@ void setup() { CPU_0 ); + xTaskCreatePinnedToCore( + taskInput, + "TaskInput", // Name of the process + 8192, // This stack size can be checked & adjusted by reading the Stack Highwater + NULL, + 4, // Priority + NULL, + CPU_0 + ); + + xTaskCreatePinnedToCore( + taskBLE, + "TaskBLE", // Name of the process + 8192, // This stack size can be checked & adjusted by reading the Stack Highwater + NULL, + 4, // Priority + NULL, + CPU_0 + ); + } @@ -101,3 +123,23 @@ void taskWeb(void *pvParameters) { vTaskDelay(100); } } + + +void taskInput(void *pvParameters) { + (void) pvParameters; + + for(;;) { + inputs.read(); + vTaskDelay(10); + } +} + + +void taskBLE(void *pvParameters) { + (void) pvParameters; + + for(;;) { + ble.update(); + vTaskDelay(10); + } +} diff --git a/src/main.h b/src/main.h index 03f6483..a6cbdaf 100644 --- a/src/main.h +++ b/src/main.h @@ -6,6 +6,8 @@ #define CPU_0 0 #include +#include "Inputs.h" +#include "BLE.h" #include "Speak.h" #include "Screen.h" #include "Storage.h" @@ -16,5 +18,7 @@ void taskScreen(void *pvParameters); void taskSpeak(void *pvParameters); void taskWeb(void *pvParameters); +void taskInput(void *pvParameters); +void taskBLE(void *pvParameters); #endif