Overland Sprinter Build

luthj

Engineer In Residence
Decided to DIY double pane the factory rear window.









Testing some storage on the aft side of the slider opening.







Do some work to stop the rear doors squeaking. New upper striker plate, and new latch pin.

 

luthj

Engineer In Residence
How is it held in place? Caulk?
Clear RTV silicone adhesive. The outdoor stuff that's ~8$ a tube. There are clear urethanes that work as well, just not as common.

A couple notes on doing that to a window. You need to make sure that dust can't get behind the pane. My windows have a small drain around the pinch weld on the inside. So I had to seal that before putting in the plastic pane. Otherwise it would eventually fill with dust. You also need a single small hole to equalize pressure. This can be a 1/16" hole in the pane, or in my case I poked a small hole in the sealant at the bottom before it cured. You don't want more than one hole though, as that can cause air circulation which is undesirable in some situations.
 

Recommended books for Overlanding

Dreaming of Jupiter
by Ted Simon
From $16.83
Cycling the Great Divide: From Canada to Mexico on North ...
by Michael McCoy, venture Cycling Association
From $9.99
Bushcraft 101: A Field Guide to the Art of Wilderness Sur...
by Dave Canterbury
From $9.99

RVflyfish

What comes next?
Thanks for the tips and posting that mod. I have an E350 and an Astro, both of which are passenger vans. Double pane windows would be a big win.
 

luthj

Engineer In Residence
Thanks for the tips and posting that mod. I have an E350 and an Astro, both of which are passenger vans. Double pane windows would be a big win.
No problem. I used 0.1" polycarbonate, but 0.08-0.125 would work well. The acrylic panes are stiffer, and more scratch resistant, so I would go that route if you can source them. The local place here was out of acrylic in the right size for some reason.
 
Last edited:

RVflyfish

What comes next?
Ok I'll look for that, thanks.

Probably out of stock because covid. Seems like most everything is in short supply these days.
 

luthj

Engineer In Residence
We are somewhere in central Utah. I was looking for rodent damage (long story), and spotted Broken sway bar bracket. I guess the bolt came loose, and the bending fatigued the bracket. I might get it welded if l spot an open shop. Otherwise I have a new set going to a nearby post office. I'll just remove the bar for now.
Screenshot_20201126-093158.png
 

luthj

Engineer In Residence
All right, here is the semi final parts list and code for the temperature control setup. There is also a 5V zener diode, and some 20A PV panel blocking diodes to prevent back feeding on the engine pump control.


C++:
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define TempBus 3

//output pins
const int PUMPEngine = 5;
const int PUMPGray = 6;
const int PUMPHeater = 7;
const int MechFan = 8;
const int D5heater = 9;
const int BLight = 10;
/*relays 6, 7, and 8 are reserved for future use.
  const int Relay6 = 11;
  const int Relay7 = 12;
  const int Relay8 = 13;
*/


//Target Temps

//Water Heater temperature for showers
const int ShowerTempH = 120;
const int ShowerTempL = 105;
//Antifreeze Loop Low
const int FreezeTemp = 45;
//Water Heater minimum temp for antifreeze operation
const int StandbyTemp = 60;
//Engine temp for preheat and switchover
const int EngineTarget = 145;




//LEDS



//Variables
float EngineT = 200;
float WaterT = 200;
float AntiFreezeT = 200;
float AmbientT = 200;
float MechCompT = 200;

float EngineT1;
float WaterT1;
float AntiFreezeT1;
float AmbientT1;
float MechCompT1;

int EngineTC = 0;
int WaterTC = 0;
int AntiFreezeTC = 0;
int AmbientTC = 0;
int ErrCount = 0;
int MechCompTC = 0;

bool PUMPEngineS = 0;
bool PUMPGrayS = 0;
bool PUMPHeaterS = 0;
bool MechFanS = 0;



bool EngineheatS = 0;
bool WaterheatS = 0;
bool AntifreezeS = 0;
bool DplusS = 0;
bool D5heaterS = 0;
bool ShowerHeat = 0;
bool EngSwitch = 0;
bool BLightS = 0;

int HeaterTarget = 0;
int FreezeTarget;
int CutIn = 0;
int CutOut = 0;


//Timers
long currentmillis;
long LastTemp = 0;
long LastPump = 0;

long LastGray = 0;
long LastLCD = 0;
long LastSwitch = 0;
long ShowerStart = 0;
long PUMPStart = 0;


//input pins
const int Engineheat = 0 ;
const int Waterheat = 1;
const int Antifreeze = 2;

const int Dplus = 4;



OneWire oneWire(TempBus);

//Pass onewire refference to Dallas Temperature function
DallasTemperature sensors(&oneWire);

//Sensor addresses
/*
   1=EngineTAD
   2=WaterTAD
   3=AntiFreezeTAD
   4=AmbientTAD
   5=Spare

*/
//Temp Sensor  addresses
DeviceAddress EngineTAD = {0x28, 0x15, 0x99, 0x07, 0xD6, 0x01, 0x3C, 0x7D};
DeviceAddress WaterTAD = {0x28, 0xF2, 0xDE, 0x79, 0xA2, 0x01, 0x03, 0x5A};
DeviceAddress AntiFreezeTAD = {0x28, 0xC0, 0x2F, 0x07, 0xD6, 0x01, 0x3C, 0x81};
DeviceAddress AmbientTAD = {0x28, 0x76, 0x32, 0x07, 0xD6, 0x01, 0x3C, 0xA4};
DeviceAddress MechCompTAD = {0x28, 0xEA, 0x3D, 0x07, 0xD6, 0x01, 0x3C, 0x07};

//Set LCD address and define lcd type
//Pins are A4 and A5 for LCD Control
LiquidCrystal_I2C lcd(0x27, 20, 4);

void setup() {

  //Set pin mode to output.  Write pins immeadiately high to prevent relay  closing during startup.
  pinMode(PUMPEngine, OUTPUT);
  digitalWrite(PUMPEngine, HIGH);
  pinMode(PUMPGray, OUTPUT);
  digitalWrite(PUMPGray, HIGH);
  pinMode(PUMPHeater, OUTPUT);
  digitalWrite(PUMPHeater, HIGH);
  pinMode(MechFan, OUTPUT);
  digitalWrite(MechFan, HIGH);
  pinMode(D5heater, OUTPUT);
  digitalWrite(D5heater, HIGH);
  /*relay outputs are reserved for future use
    pinMode(Relay6, OUTPUT);
    pinMode(Relay7, OUTPUT);
    pinMode(Relay8, OUTPUT);
  */

  //Switches  on control panel are all switched  to ground.  The D+ engine running signal is HIGH when active and LOW with engine off.
  pinMode(Engineheat, INPUT_PULLUP);
  pinMode(Waterheat, INPUT_PULLUP);
  pinMode(Antifreeze, INPUT_PULLUP);
  pinMode(BLight, INPUT_PULLUP);
  pinMode(Dplus, INPUT);
  //attachInterrupt(digitalPinToInterrupt(Waterheat), ShowerTime, FALLING);




  //start temp sensor bus and set resolution to 10 bits
  sensors.begin();
  sensors.setResolution(10);




  //initial LCD setup
  lcd.init();
  lcd.setCursor ( 0, 0 );
  lcd.print("AMB ENG WTR GRY MEC ");
  lcd.setCursor ( 0, 1 );
  lcd.print("XXX XXX XXX XXX XXXF");
  lcd.setCursor ( 0, 2 );
  lcd.print("    HX  X   X       ");
  lcd.setCursor ( 0, 3 );
  lcd.print("    PX  X   X   XFAN");
  sensors.begin();
  sensors.setResolution(10);

}

void loop()
{
  //Start timer
  currentmillis = millis();
  /*Do the things, Temperatures are  updated every 10 seconds, pump status is updated every second to prevent odd behavior.
    Some pumps are switched outside of the Updatepump function.  This is to prevent the D5 heater from seeing no pump current, and faulting.
  */

  if ((currentmillis - LastTemp) > 10000)  UpdateTemp();
  if ((currentmillis - LastPump) > 1000)  UpdatePump();
  if ((currentmillis - LastSwitch ) > 1000) UpdateSwitch();
  HydronicControl();
  AntifreezeControl();
  if ((currentmillis - LastLCD) > 1000) LCDUpdate();
  /*
    if (ShowerHeat)
    {
     if ((currentmillis - ShowerStart) > 1200000)
     {
       WaterheatS = 0;
       ShowerHeat = 0;
     }
     else WaterheatS = 1;
    }
  */
}

void UpdateTemp() {
  //This commmand tells alll the sensors to prepare to transmit the temperature.  Depending on sensor resolution there is a certain cooldown time before it can be requested again.
  //If no response  is recieved,  or if its funky, the sensor library will return a specific temperature value as error. Not all of them are documented.
  sensors.requestTemperatures();

  EngineT1 = sensors.getTempF(EngineTAD);

  WaterT1 = sensors.getTempF(WaterTAD);

  AntiFreezeT1 = sensors.getTempF(AntiFreezeTAD);

  AmbientT1 = sensors.getTempF(AmbientTAD);

  MechCompT1 = sensors.getTempF(MechCompTAD);


  //Sanity Checks.  If sensor does not respond the getTempF returns -196.6F.  If temps are below -50, the function uses the previous value for 30 seconds.
  //If no update is found in that time, the error value of 999 is used.  ErrCount is incremented for debug reasons, I may remove in newer revisions.
  if (EngineT1 < -50)
  {
    ErrCount++;
    if (EngineTC > 3) EngineT = 999;
    else EngineTC++;
  }
  else
  {
    EngineT = EngineT1;
    EngineTC = 0;
  }

  if (WaterT1 < -50)
  {
    ErrCount++;
    if (WaterTC > 3) WaterT = 999;
    else WaterTC++;
  }
  else
  {
    WaterT = WaterT1;
    WaterTC = 0;
  }

  if (AntiFreezeT1 < -50)
  {
    ErrCount++;
    if (AntiFreezeTC > 3) AntiFreezeT = 999;
    else AntiFreezeTC++;
  }
  else
  {
    AntiFreezeT = AntiFreezeT1;
    AntiFreezeTC = 0;
  }

  if (AmbientT1 < -50)
  {
    ErrCount++;
    if (AmbientTC > 3) AmbientT = 999;
    else AmbientTC++;
  }
  else
  {
    AmbientT = AmbientT1;
    AmbientTC = 0;
  }

  if (MechCompT1 < -50)
  {
    ErrCount++;
    if (MechCompTC > 3) MechCompT = 999;
    else MechCompTC++;
  }
  else
  {
    MechCompT = MechCompT1;
    MechCompTC = 0;
  }



  /*if (WaterT1 < -50) WaterT = 999;
    if (AntiFreezeT1 < -50) AntiFreezeT = 999;
    if (EngineT1 < -50) EngineT = 999;
    if (MechCompT1 < -50) MechCompT = 999;
    if (AmbientT1 < -50) AmbientT = 999;
  */
  currentmillis = millis();
  LastTemp = millis();

}
 

luthj

Engineer In Residence
Continued code
C++:
void UpdatePump() {



  //If  engine is running, turn off engine coolant pump (ECU controls, but engine pump also is sufficient).

  if (DplusS)

    PUMPEngineS = 0;



  //If engine is running, Noe engine preheat/boost is selected, and D5 is currently off

  if (DplusS && !EngineheatS && !D5heaterS)

  {

    //If engine is warmed up, and water heataer is less than minimum, run the D5 coolant pump to heat water heater.

    if ((EngineT > EngineTarget) && (WaterT  < ShowerTempL))

    {

      PUMPHeaterS = 1;

    }

    //If engine isn't warmed up, or water heater is above max tank temp, turn off D5 pump.

    if ((EngineT < EngineTarget) || (WaterT > ShowerTempH))

    {

      PUMPHeaterS = 0;

    }

  }



  //Otherwise, let D5 heater control its pump

  else

  {



    PUMPHeaterS = 0;

  }









  digitalWrite (PUMPEngine, !PUMPEngineS);

  digitalWrite (PUMPGray, !PUMPGrayS);

  digitalWrite (PUMPHeater, !PUMPHeaterS);

  digitalWrite (MechFan, !MechFanS);

}



//read switches.  Due to use of pullup status, some are inverted

void UpdateSwitch() {

  EngineheatS = !digitalRead(Engineheat);

  WaterheatS = !digitalRead(Waterheat);

  AntifreezeS = !digitalRead(Antifreeze);

  DplusS = digitalRead(Dplus);

  BLightS = !digitalRead(BLight);



}



//Hydronic Heater Control

void HydronicControl()

{

  //If engine preheat/boost is selected

  if (EngineheatS)

    //if D5 is on and  engine is above preheat/boost target, turn off D5

  { if (D5heaterS && EngineT > EngineTarget)

    {



      digitalWrite(D5heater, HIGH);

      D5heaterS = 0;



    }



    //If D5 is off, and engine temp more than 30 degrees below preheat target, then turn on D5 heater, and give D5 control of its pump.  D5 status variable is updated.

    if (D5heaterS == 0 && EngineT < (EngineTarget - 30))

    {

      digitalWrite(PUMPHeater, HIGH);

      digitalWrite(D5heater, LOW);

      D5heaterS = 1;



    }

    //If engine is off

    if (!DplusS)

    {

      //If engine is more than 20 degrees below preheat target, and engine pump is off, turn it back on to check temperature.

      if ( EngineT < (EngineTarget - 20) && PUMPEngineS == 0)

      {

        PUMPEngineS = 1;

      }



      //if the engine is greater than the target temperature and the pump is running, turn it  off to conserve power.

      if (EngineT > EngineTarget && PUMPEngineS == 1)

      {

        PUMPEngineS = 0;

      }

    }

    //if the  engine is running, turn off the engine pump.

    if (DplusS)

    {

      PUMPEngineS = 0;

    }

  }



  //if engine preheat is not active

  else

  {



    //if water heating or gray tank antifreeze is active

    if (WaterheatS || AntifreezeS)

    {

      //for water heating set the cut in/out temps to the higher values

      if (WaterheatS)

      {

        CutIn = ShowerTempH;

        CutOut = ShowerTempL;



      }

      //if only gray tank antifreeze is selected, use lower temps

      else

      {

        if (AntifreezeS)

        {

          CutIn = StandbyTemp;

          CutOut = ShowerTempL;

        }

      }



      //if water heater is below cutout and D5 is on, keep heating, D5 controls pump

      if ((WaterT < CutOut) && D5heaterS  )

      {

        digitalWrite(PUMPHeater, HIGH);

        digitalWrite(D5heater, LOW);

        D5heaterS = 1;

        PUMPHeaterS = 0;

      }



      //If water heater is above cutout and D5 heater is active, turn off D5.

      if ((WaterT > CutOut) && D5heaterS )

      {

        digitalWrite(D5heater, HIGH);

        D5heaterS = 0;



      }



      //if water heater is above cutin, and d5 is off, d5 stays off.

      if (WaterT > CutIn && D5heaterS == 0) {

        digitalWrite(D5heater, HIGH);

        D5heaterS = 0;

      }



      //If water heater is less than cutin, turn on D5 and D5 controls its pump

      if (WaterT < CutIn)

      {

        digitalWrite(PUMPHeater, HIGH);

        digitalWrite(D5heater, LOW);

        D5heaterS = 1;

        PUMPHeaterS = 0;

      }





    }



    //otherwise D5 is off

    else

    {

      digitalWrite(D5heater, HIGH);

      D5heaterS = 0;

    }



    PUMPEngineS = 0;



  }



}



//this controls the gray tank antifreeze pump/loop

void AntifreezeControl()

{

  //if the ambient temp is below 40 and the gray tank antifreeze is active

  if ( AmbientT < 40 && AntifreezeS)

  {

    //If the mechanical cabinet  is below 45F, run the fan to circulate cabin air.

    if (MechCompT < 45) MechFanS = 1;





    //The gray tank loop target temp

    FreezeTarget = FreezeTemp;



    //if the engine is running or water heating is active, increase the gray loops target temperature to 90F, as free heat is available.

    if (DplusS || WaterheatS ) FreezeTarget = 90;



    //if the gray tank loop is below the target temp, turn on the pump

    if (AntiFreezeT < FreezeTarget) PUMPGrayS = 1;



    //if the loop more than 20 degrees above the target, and the pump is running, turn it off.  Update the last pump time.

    if (AntiFreezeT > (FreezeTarget  + 20) && PUMPGrayS)

    {

      PUMPGrayS = 0;

      LastGray = currentmillis;

    }



    //if the loop is above the target, cycle the pump

    if (AntiFreezeT > FreezeTarget  )

    {

      //if the time since the pump was last cycled is greater than 30 minutes, turn the pump on, and reset pump start timer

      if ((currentmillis - LastGray) >  1800000 && !PUMPGrayS )

      {

        PUMPStart = currentmillis;

        PUMPGrayS = 1;

      }



      //if the pump is running and its been more than 2 minutes, turn the pump off and reset the last pump timer.

      if ((currentmillis - PUMPStart) > 120000 && PUMPGrayS )

      {

        PUMPGrayS = 0;

        LastGray = currentmillis;

      }

    }

  }





  //otherwise turn off the pump and mechanical fan

  else

  {

    PUMPGrayS = 0;

    MechFanS = 0;

  }





}



/*

  void ShowerTime()

  {

  ShowerHeat = 1;

  ShowerStart = currentmillis;

  }

*/



//update LCD screen with temperatures and statuses. To account for temperature length changes, each 3 digit position is written to blank/space before the temp is written.

void LCDUpdate()

{

  //switch backlight based on switch status

  lcd.setBacklight(BLightS);



  // Format for cursor position is  (column, row)  Each row is written with each variable starting left and working right. Each floating temperature value is printed with no decimals

  lcd.setCursor ( 0, 1 );

  lcd.print("   ");

  lcd.setCursor ( 0, 1 );

  lcd.print(AmbientT, 0);



  lcd.setCursor ( 4, 1 );

  lcd.print("   ");

  lcd.setCursor ( 4, 1 );

  lcd.print(EngineT, 0);



  lcd.setCursor ( 8, 1 );

  lcd.print("   ");

  lcd.setCursor ( 8, 1 );

  lcd.print(WaterT, 0);



  lcd.setCursor ( 12, 1 );

  lcd.print("   ");

  lcd.setCursor ( 12, 1 );

  lcd.print(AntiFreezeT, 0);



  lcd.setCursor ( 16, 1 );

  lcd.print("   ");

  lcd.setCursor ( 16, 1 );

  lcd.print(MechCompT, 0);



  lcd.setCursor ( 5, 2 );

  lcd.print(EngineheatS);



  lcd.setCursor ( 8, 2 );

  lcd.print(WaterheatS);



  lcd.setCursor ( 12, 2 );

  lcd.print(AntifreezeS);



  lcd.setCursor ( 5, 3 );

  lcd.print(PUMPEngineS);



  lcd.setCursor ( 8, 3 );

  lcd.print(PUMPHeaterS);



  lcd.setCursor ( 12, 3 );

  lcd.print(PUMPGrayS);



  lcd.setCursor ( 16, 3 );

  lcd.print(MechFanS);



  lcd.setCursor (0, 3 );

  lcd.print(ErrCount);







  //update last LCD time



  LastLCD = currentmillis;



}
 

PlethoraOfGuns

Adventurer
Eh, you don't really "need" sway bars, they are just suggested. Kinda like a GPS, as they give you "suggestions" and not always directions.
 

luthj

Engineer In Residence
My 9 foot tall van definitely need sway bars, both to prevent motion sickness and for safety. Without them the van can become a rollover hazard in emergency evasion situations.

I had a friend roll over his wrangler which was top-heavy with a roof rack when merging an on ramp to the interstate. He had removed to sway bars, lifted it, and installed tall tires. I am sure it had great articulation though.

Prior to installing decent shocks, the stiff sway bars did produce pretty violent rocking when I went through washes at certain speeds and angles. 😂

The being said my front sway bar is still working just fine, so the van is okay for now.
 

Alloy

Well-known member
Clear RTV silicone adhesive. The outdoor stuff that's ~8$ a tube. There are clear urethanes that work as well, just not as common.

A couple notes on doing that to a window. You need to make sure that dust can't get behind the pane. My windows have a small drain around the pinch weld on the inside. So I had to seal that before putting in the plastic pane. Otherwise it would eventually fill with dust. You also need a single small hole to equalize pressure. This can be a 1/16" hole in the pane, or in my case I poked a small hole in the sealant at the bottom before it cured. You don't want more than one hole though, as that can cause air circulation which is undesirable in some situations.
When there's allot of moisture holes are needed top and bottom. Condensation won't drain out with 1 hole and air circulation is needed to dry the space out.
 

Recommended books for Overlanding

Overlanding the Americas: La Lucha
by Mr Graeme Robert Bell
From $20
Drive Nacho Drive: A Journey from the American Dream to t...
by Brad Van Orden, Sheena Van Orden
From $15.95
The Longest Line on the Map: The United States, the Pan-A...
by Eric Rutkow
From $16.72

DzlToy

Explorer
^^
Makrolon

The solution to dust intrusion between the panels and preventing condensation is to either vacuum the space between the panes or fill it with an inert gas such as Argon or Krypton. This is how commercial, insulated glass is made. Drill a hole in the top Lexan pane, as high up as you can get it and seal everything else up, tight. Fill the space with gas, which is heavier than air, pull the tube out, et Voila!

Seal up the hole with some silicone or caulking and Bob's your uncle.
 
Last edited:
Top