Voyager I Graduation build

Voyager I Graduation build

Specs

  • P42A 20s3p Primary Battery 20s2p Secondary Battery
  • Makerx Go-Foc D100
  • Maytech 6365 110Kv
  • Apex Air Trucks
  • Apex Jump Drive
  • Trampa Phatlads and Mud pluggers
  • Haero Bro 2021 Dawid Rzaca Pro Mountainboard Deck
  • And the rest is all DIY
Story

Introducing Voyager I, a symbol of new beginnings, a testament to the untrodden path that lies before us. This is a story waiting to unfold, with no knowledge of where it will lead or how it will end. But let us embark on this journey with the determination to make the best of it, for along the way, we may carve a legendary tale, just like the first man-made object to venture into interstellar space.

As an Electromechanical Engineering Student, I am on the verge of graduating this June 2023 and making my parents proud. However, whether it’s striving to complete my studies or building an extraordinary esk8, I have encountered obstacles along the way.

Last June of 2022, an unfortunate incident occurred that altered my course. It was just before my final exam period, a time when I would often take a break and cruise through the charming streets of Leuven the city where i study. But that day, fate had a different plan. A child darted out from between parked cars, causing me to swerve and lose control. I collided with the ground, hitting my head in the process. The next thing I knew, I found myself in the emergency room, bewildered and disoriented.

Thankfully, my parents were by my side, patiently answering the same questions multiple times. After spending a night in the ER, I was transferred to the neurology department cause i suffered from a brain hemorrhage i had to stay a week for observation. When I was finally discharged from the hospital, my exams had already begun. I reached out to my school, explaining the situation, and they graciously agreed to postpone my exams. Although the delay wasn’t extensive, I still faced difficulties concentrating for long periods, making studying and taking exams a significant challenge. Consequently, when the time came to tackle my exams, I faced a profound setback.


But here’s the thing: setbacks don’t define us; how we rise from them does. It was in this moment of adversity that I realized the power of resilience and determination. Instead of succumbing to despair, I found solace in the idea of creating something extraordinary. I channeled my energy into designing and building the perfect esk8, pouring my passion into every aspect – from its weightlessness to its incredible speed, advanced features, and unwavering reliability.

The journey to craft Voyager I became my motivation. It served as a reminder that life is unpredictable, and we must make the most of every opportunity. Each push of the skateboard’s wheels symbolizes my resilience, my refusal to let setbacks define me. It is a testament to the strength within me and the relentless pursuit of my dreams.

So, as I approach graduation, I look back at the hurdles I faced, the lessons I learned, and the determination that fueled my journey. Voyager I is not just an electric skateboard; it represents the indomitable spirit within us all. May it inspire others to rise above their own challenges, to pursue their passions, and to embrace the unknown with unwavering courage. Together, let us create our own legends, shaping our futures one extraordinary story at a time.

The Build

Following the approach of a diligent engineer, I initiated the planning phase by creating an Excel spreadsheet containing an exhaustive list of available options. The primary emphasis was placed on achieving lightweight solutions, and each option was associated with its respective weight measurement and cost.

After ordering the components on Black Friday Apex trucks, Jump Drive, Trampa Phatlads and Haero Bro 2021 Dawid Rzaca Pro Mountainboard Deck.

Simultaneously, during this period, we commenced the design of the battery enclosure. Meanwhile, the decision regarding whether to house the speed controller in a separate rear case or position it in the middle was still under consideration, as each choice had its advantages and disadvantages. Opting to place the ESC in the middle offers the benefit of improved weight distribution, and it eliminates the need for an additional case. However, there are downsides, such as the potential for added points of failure due to the intricacies of routing all the motor wires, including the hall sensor wires, to the back. Ensuring tidy wire management also presents a challenge, although ultimately, this configuration promises a more streamlined and organized build.

Footpad

To route the wire to the rear, I designed pads with spaces in between on the TPU-printed deck. These pads serve two primary purposes: achieving effective cable routing and providing a slight cushioning effect for the feet. To ensure accurate dimensions, I covered the deck with painter’s tape and marked out several key positions. Subsequently, I imported a canvas and the precise measurements into Fusion 360. The canvas proved instrumental in obtaining the correct curves for the design.


Battery

To determine the battery configuration, size, and dimensions, I employed the Ducttaperules tool within Fusion. This involved coloring in the sides of the cells, allowing me to visualize and plan the current pathway throughout the battery.

Finnaly deceided on this 20s3p Molicell P42A Main Battery config.


As you might notice the bms had been taken out cause the first one that i got only saw the last 6 series of the pack.

Enclosure

Next, let’s move on to discussing the enclosure. When considering the case, I aimed to use the lightest material possible. Initially, I chose ABS, but encountered consistent warping issues even with a heated chamber. After that, I attempted ASA, but the warping problem persisted. Finally, I settled on PETG Carbon Fiber filled, which not only provides stiffness and water resistance but also has the added bonus of looking really cool.



I utilized CNC machining to craft the heatsink out of some 6061 aluminum, and for the enclosure lids, I CNC-machined matte ABS material that I found on sale. Although carbon fiber could have been a desirable option, its CNC machining process is rather intricate due to the particles and other complexities involved.


Finished Case

Motors

I chose not to opt for the Apex motors for my setup due to several reasons. Firstly, I’m constructing a 20s build, and the lowest available kv of 140kv would prove too high for my preferences. I preferred sacrificing some top speed in favor of gaining additional torque. Additionally, the only motor size they offer is 6384, which is larger and heavier than what I require for my project.

The positive aspect they offered was a circlip groove on the motor that would prove useful on their gear drive, providing secure attachment for the motor pulley. Despite this, I embarked on a search for a smaller motor featuring a customized winding and the necessary circlip groove.

I also want to express my gratitude to the Apex team for sharing the shaft schematic, which greatly assisted me in finding a suitable motor.

After some searching and attempts to request custom motors from various vendors, Maytech’s 6365 motor with a customized winding caught my attention. Although the axle was slightly longer by 1mm, this proved to be a minor concern. Adjusting the pulley’s offset by 1mm from the circlip was achievable through the use of a few shims.

Anti-Sinkplate & Lights

The Anti-Sinkplate was designed with multiple functionalities in mind. Primarily, its purpose was to prevent the bolts from sinking into the deck, as the name suggests. Additionally, it served as a convenient cable routing point, allowing for tidy cable organization. Lastly, it offered a suitable mounting location for the ws2812 LEDs.

Ensuring symmetry, I aimed to create identical sinkplates. To achieve this, the front utilized a single pair of offset plates, while the back utilized two pairs due to the need for extra space to route the phase wires through. The only discernible distinction existed at the lower section of the sinkplate, where a 3D-printed component facilitated cable routing.

Moving on to the installation of the lights, I employed a magnetic connector equipped with three pins. This setup allowed for the transmission of 5V, GND, and the signal to the LEDs. To enhance stability, I incorporated stacks of magnets at each corner, guaranteeing the LEDs’ secure placement. In a subsequent update, I introduced an additional threaded hole—providing an extra option—especially useful for more intense off-roading scenarios. After all, more options usually lead to better outcomes, don’t they?






To manage the LEDs, I employed an ESP8266 which operates as a web server accessible from any device with a Wi-Fi connection. Toggling the LEDs on and off is achievable through switches, while the selection of a specific LED enables the customization of its color. Additionally, I integrated a braking feature: when you apply the brakes, the rear lights begin to flicker, serving as a signal to notify other road users that you are slowing down.


Assembly

After getting the drivetrain assembled and everything connected


The process involved simply inserting the battery, accessing the VESC tool to configure the VESC settings, and making slight adjustments to the PWM filtering to fine-tune the brake feature of the LEDs. With these steps completed, we were ready to hit the road.

In summary, the project was truly remarkable, and the initial ride was even more incredible. If there’s sufficient interest, I’ll provide a follow-up on the secondary battery. Stay safe on your rides!

Best regards,
Kutvis

Esk8 Porn here




VIDEO'S




18 Likes
Code

//============================================
//ESP8266 Web Server (HTML + CSS + JavaScript)
//============================================
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include “webpageCode.h”;

ESP8266WebServer server(80);
bool toggle1State = true;
bool toggle2State = true;
bool toggle3State = true;
String FrontColor; // Front
String RearColor; // Rear
int RedValueFront=255;
int GreenValueFront=255;
int BlueValueFront=255;

int RedValueRear;
int GreenValueRear;
int BlueValueRear;
//=================================================================
#include <FastLED.h>
#define FRONT_LED_COUNT 7
#define REAR_LED_COUNT 7
#define FRONT_LED_PIN D1
#define REAR_LED_PIN D2
#define RCPin D5

unsigned long previousTime = 0;
int RCValue;
bool rearLedOn = false;
CRGB frontLeds[FRONT_LED_COUNT];
CRGB rearLeds[REAR_LED_COUNT];
//=================================================================
void webpage()
{
server.send(200,“text/html”, webpageCode);
}
//=================================================================
void handleToggle() {
// update the state of the toggle switches
if (server.hasArg(“toggle1”) && server.arg(“toggle1”) == “true”) {
toggle1State = true;
} else {
toggle1State = false;
}
if (server.hasArg(“toggle2”) && server.arg(“toggle2”) == “true”) {
toggle2State = true;
} else {
toggle2State = false;
}
if (server.hasArg(“toggle3”) && server.arg(“toggle3”) == “true”) {
toggle3State = true;
} else {
toggle3State = false;
}

// set the front colors
if (server.hasArg(“bg1”)) {
FrontColor = (server.arg(“bg1”));
Serial.println(FrontColor);
int commaIndex1 = FrontColor.indexOf(‘,’);
int commaIndex2 = FrontColor.indexOf(‘,’, commaIndex1 + 1);
RedValueFront = FrontColor.substring(0, commaIndex1).toInt();
GreenValueFront = FrontColor.substring(commaIndex1 + 1, commaIndex2).toInt();
BlueValueFront = FrontColor.substring(commaIndex2 + 1).toInt();
}
if (server.hasArg(“bg2”)) {
RearColor = (server.arg(“bg2”));
Serial.println(RearColor);
int commaIndex1 = RearColor.indexOf(‘,’);
int commaIndex2 = RearColor.indexOf(‘,’, commaIndex1 + 1);
RedValueRear = RearColor.substring(0, commaIndex1).toInt();
//Serial.println(RedValueRear);
GreenValueRear = RearColor.substring(commaIndex1 + 1, commaIndex2).toInt();
//Serial.println(GreenValueRear);
BlueValueRear = RearColor.substring(commaIndex2 + 1).toInt();
//Serial.println(BlueValueRear);

}

// send a response to the client
server.send(200, “text/plain”, “OK”);
}

//=================================================================
void setup()
{
Serial.begin(115200);
WiFi.softAP(“Apollo LED”, “password”); // set the access point name and password
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);

server.on(“/toggle”, HTTP_POST, handleToggle);
server.on(“/”, webpage);
server.begin();

FastLED.addLeds<NEOPIXEL, FRONT_LED_PIN>(frontLeds, FRONT_LED_COUNT).setCorrection(TypicalLEDStrip);
FastLED.addLeds<NEOPIXEL, REAR_LED_PIN>(rearLeds, REAR_LED_COUNT).setCorrection(TypicalLEDStrip);
pinMode(RCPin, INPUT);
}

//=================================================================
void loop()
{
//=================================================================
//=================================================================
// read the PWM signal
RCValue = pulseIn(RCPin, HIGH);
//Serial.println(RCValue);

if (toggle1State){
// set color to front and rear
for (int i = 0; i < FRONT_LED_COUNT; i++) {
frontLeds[i].setRGB(RedValueFront,GreenValueFront,BlueValueFront);
}
}else {
for (int i = 0; i < FRONT_LED_COUNT; i++) {
frontLeds[i] = CRGB::Black; // set color to black
}
}
if (toggle2State){
if (toggle3State){
if (RCValue < 1400) {
// toggle the state of the rear LEDs every 100ms
EVERY_N_MILLISECONDS(100) {
if (rearLedOn) {
for (int i = 0; i < REAR_LED_COUNT; i++) {
rearLeds[i] = CRGB::Black;
}
rearLedOn = false;
} else {
for (int i = 0; i < REAR_LED_COUNT; i++) {
rearLeds[i] = CRGB::Red;
}
rearLedOn = true;
}
}
} else {
for (int i = 0; i < REAR_LED_COUNT; i++) {
rearLeds[i] = CRGB::Red; // set color to red
}
}} else {
for (int i = 0; i < REAR_LED_COUNT; i++) {
rearLeds[i].setRGB(RedValueRear,GreenValueRear,BlueValueRear);
}
}
}else {
for (int i = 0; i < REAR_LED_COUNT; i++) {
rearLeds[i] = CRGB::Black;
}
}
FastLED.show(); // display the colors on the LEDs
unsigned long currentTime = millis();
if (currentTime - previousTime >= 50) {
// update the LEDs here
previousTime = currentTime;
}
server.handleClient();
}

//=========================================
//HTML + CSS + JavaScript codes for webpage
//=========================================
const char webpageCode[] =
R"=====(

body {background-color: rgb(200, 200, 200)}
@media (prefers-color-scheme: dark) {
body {background-color: rgb(53, 55, 58.5)}
img {filter:invert(100%)}
}

  .img-container{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    transform: scale(2.5);
  }

  .foto {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  #colorPicker {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 500px;
    padding: 5px;
    background-color: rgb(53, 55, 58.5);
    border: 1px solid #cccccc;
    border-radius: 5px;
  }
  
  .colorBox {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 200px;
    height: 200px;
    border-radius: 100px;
    border: 5px solid rgb(255, 255, 255);
  }
  
  .slider1 {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -165%);
    width: 180px;
  }
  .slider2 {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, 70%);
    width: 180px;
  }

  .cone1 {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -300%);
    width: 200px;
    height: 100px;
    --bg-color1: #FFFFFF;
    background: radial-gradient(farthest-side, var(--bg-color1), #ceb8b800);
    -webkit-mask: conic-gradient(from -45deg at bottom, #0000, #000 1deg 90deg, #0000 91deg);
  }
  
  .cone2 {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, 200%) rotate(180deg);
    width:200px;
    height:100px;
    --bg-color2: #ff3232;
    background:radial-gradient(farthest-side,var(--bg-color2) ,#ceb8b800);
    -webkit-mask:conic-gradient(from -45deg at bottom,#0000, #000 1deg 90deg, #0000 91deg);
  }

  .toggle-container {
    position: absolute;
    font-family: monospace;
    color: rgb(255, 255, 255);
    font-size: 24px;
    font-weight: bold;
    left: 90px;
    top: 135px;
    transform: scale(2);
  } 
  .toggle-button {
    position: relative;
    top: -30px; 
    left: 0px;
    display: block;
    width: 120px;
    height: 34px;
  }
  .toggle-button input {
    position: a;
    opacity: 0;
    width: 0;
    height: 0;
  }
  .toggle-button label {
    position: relative;
    display: block;
    width: 50%;
    height: 100%;
    background: #7e7e7e;
    border-radius: 34px;
    transition: background 0.4s;
    cursor: pointer;
  }
 
  .toggle-button label:before {
    position: absolute;
    content: ". ";
    width: 26px;
    text-align: center;
    font-size: 17px;
    line-height: 26px;
    font-weight: bold;
    left: 4px;
    top: 4px;
    background: #fff;
    border-radius: 26px;
    transition: 0.4s;
  }
  .toggle-button input:checked + label:before {
    position: absolute;
    left: 30px;
    width: 26px;
    content: ".";
    bottom: 4px;
    line-height: 26px;
  }
  
  .toggle-button input:checked + label {
    position: relative;
    background: #23d100;
  }

  .momentary-button {
    position: absolute;
    display: inline-block;
    border: none;
    background-color: #7e7e7e;
    color: white;
    font-size: 16px;
    font-weight: bold;
    padding: 10px 20px;
    border-radius: 5px;
    transition: background-color 0.3s ease-out;
    top: 50px;
    right: 110px;
    transform: scale(2.5);
  }
  
  .momentary-button:active {
    background-color: #23d100;
  }
</style>
<div class="img-container">
  <div class="foto">
    <img src="data:image/png;base64GUZ1ZX2p+B5nw2KWmR9JcWlzy7YpC340ONneIaytDlnZm32r8EHd1Jwuzg/op/S7Ybeu7xKLvBJNKcd/HYTfu3sKNliOXfUUQYM/uvYSemb/z/G013o2E3EGHHMhp2yGFHwr4e/iTW0XqWgrAjeKbRaNhhDTvQmPto2I2G3WjYDZ16lhF48AEH42g9S1a6g4SdzGjYERV2qSSHnc9o2OEKO3aCYRcxGnZYw451NOyQQBQRYQc7l0dKAXQmOa3vJxtCYYc/FfWCxj4lV0A4TBkyoHSHP+yodK72sAg70FrLeCgvKIEd2L7DG3bsIyrs2AmkOw5mrTCoGrZcHxZeRyF23Fuv2Tn2Lhs5YceDY+c8cAMlcIO6oiEL88KFsBOe9gknzCp+u1s1EgRU4QCJFxx8YfeICbuJu4ODg+GhUHoEsk/tyJGdkPBZ9tnIyogZHrr7GERzZi0/m4cDnAWC5dwjJuzCdgP9iyMgQGGxPFaKHSNFgg+cAJ7YAT/fiRV0gAfoDAoODvYRE3QMHMAQgJwUxQYHoKOmWEHCwADhwHZwF+SYEQ7w6fPQ0zs4YeeZjCAA3kbOCU5AsHO2QOkInIRQjhEBAHg9AKT8TLlZAAAAAElFTkSuQmCC" width="200">
  </div>

  <div class="cone1" id="cone1"></div>
  <div class="cone2" id="cone2"></div>

  <div id="colorPicker1" style="display:none" class="colorPicker">
    <div class="colorBox" style="background-color: #ffffff;"></div>
    <input type="range" class="slider1" min="0" max="360" value="0">
    <input type="range" class="slider2" min="0" max="100" value="50" >
  </div>

  <div id="colorPicker2" style="display:none" class="colorPicker">
    <div class="colorBox" style="background-color: #ff3232;"></div>
    <input type="range" class="slider1" min="0" max="360" value="0">
    <input type="range" class="slider2" min="0" max="100" value="50" >
  </div>
</div>

<div class="toggle-container">
  <label for="toggle-input-all">All</label>
  <div class="toggle-button">
    <input type="checkbox" id="toggle-input-all" />
    <label for="toggle-input-all"></label>
  </div>
  
  <label for="toggle-input-1">Front</label>
  <div class="toggle-button">
    <input type="checkbox" id="toggle-input-1" />
    <label for="toggle-input-1"></label>
  </div>

  <label for="toggle-input-2">Rear</label>
  <div class="toggle-button">
    <input type="checkbox" id="toggle-input-2" />
    <label for="toggle-input-2"></label>
  </div>

  <label for="toggle-input-3">Brake</label>
  <div class="toggle-button">
    <input type="checkbox" id="toggle-input-3" />
    <label for="toggle-input-3"></label>
  </div>
</div>

<button class="momentary-button" id="reset-button">Reset Color</button>

)=====";

1 Like

Reserved 1

Reserved 2

Reserved 3

Hell of a build!

1 Like

Wow, very impressive build and write-up!

Why did you choose to make your own footpads instead of just buying Apex ones?

How does your microcontroller detect the board braking? Is it taking input from the remote PWM signal, or from vesc tool?

Also really cool to know the required shaft length and circlip dimensions to use Jump Drives in the safest way posible. Thanks for sharing! :smiley:

1 Like

Huge fan of having the ESC in the box with the battery!

Super slick build wish mine looked like this lol

3 Likes

Thank you <3

The grooves for the wires are not straight if i remember correctly and i wasn’t sure if all the cables would fit. + doing them yourself is cheaper. And for the braking i use the pwm from the receiver.

1 Like

Heck of a story and build man. Glad you were able to push forward and hop back on. Sucks that you had to go through that.

1 Like