Sprinter 4WD Conversion Idea, GMT-800 IFS.

luthj

Engineer In Residence
Eventually you will come to the realization that hydraulic bumpstops are in your future.

Care to elaborate?

The GM foam bumpstops are pretty tall, and I can add a foam bumper to the shock shaft as well.
 

luthj

Engineer In Residence
For giggles I calculated the front suspensions natural frequency.
https://eibach.com/us/p-101-suspension-worksheet.html

With 1850lbs sprung weight, and 1100lb springs, the frequency is right at 1.5hz. Which is about the top end of what i would want for a mostly road going car. Higher frequencies would be better for high speed stability, especially if you are pushing the vehicle hard over rough terrain. But the ride would be pretty stiff, and low speed performance would suffer. In fact, with a sway bar connected, it may be difficult to get hit the bump stop with the other wheel in the air at 2.0hz.

If I had more travel, I could push that closer to 1.2hz or so for better road comfort. That is part of the reason that GM used the torsion bars, is it allows for more preload with the limited travel. Which allows for a reasonable ride height without a crazy high suspension frequency. The progressive bumpstop design helps mitigate harsh bottom-out which can be produced by the lower spring rates.
 

Len.Barron

Observer
For giggles I calculated the front suspensions natural frequency.
https://eibach.com/us/p-101-suspension-worksheet.html

With 1850lbs sprung weight, and 1100lb springs, the frequency is right at 1.5hz. Which is about the top end of what i would want for a mostly road going car. Higher frequencies would be better for high speed stability, especially if you are pushing the vehicle hard over rough terrain. But the ride would be pretty stiff, and low speed performance would suffer. In fact, with a sway bar connected, it may be difficult to get hit the bump stop with the other wheel in the air at 2.0hz.

If I had more travel, I could push that closer to 1.2hz or so for better road comfort. That is part of the reason that GM used the torsion bars, is it allows for more preload with the limited travel. Which allows for a reasonable ride height without a crazy high suspension frequency. The progressive bumpstop design helps mitigate harsh bottom-out which can be produced by the lower spring rates.
You need a garage...you've got way too much time on your hands! LOL!!
 

luthj

Engineer In Residence
You need a garage...you've got way too much time on your hands! LOL!!

While I really enjoy being a bum (2 years now without a real job), I very much look forward to having some disposable income, and a place to work at the same time.

I am hoping to get the van rolling on the new suspension by August. Things should progress pretty quickly once I can tear down the van. The real challenge right now is finding a rental home (no HOA) that won't got batshit crazy if I take the front wheels off a vehicle in my driveway.
 

b dkw1

Observer
Care to elaborate?

The GM foam bumpstops are pretty tall, and I can add a foam bumper to the shock shaft as well.

A hydro bump will do way more than a foam bump. You can use it to band-aid a poor spring rate. Set-up with the proper oil level, it's spring rate can go from almost zero extended to almost solid at bump.
 

luthj

Engineer In Residence
An engineering contact volunteer his time (thanks M!). He wrote a arduino program that reads input pulses on two channels, and outputs a square wave (digital output) on two lines. Frequency is converted at will. I will likely need some tweaking of various values. It may need a bit of logic to appropriately handle wheel lock up. I am confident the microprocessor is fast enough to produce accurate results though. The code is written below.

Since the WSS outputs a variable AC voltage (between 2-9V?). I need a filter circuit for the input. Both to protect the controller against voltage excursions, and to convert the sine wave to a digital square waveform. My thoughts are to use a schmitt trigger circuit. Essentially this is a crossing zero comparator. When the sine wave crosses zero, the OP-amp goes high, when it goes below zero, it goes low. The circuit below uses a voltage divider, noise and peak current suppression capacitor, etc. I will need to adjust the capacitor and resister values, but it should suppress ambient RF noise and produce a nice clean square wave.

https://electronics.stackexchange.com/questions/163253/sine-wave-to-square-wave-schmitt-trigger
513303
513304



For the output to the ESP/ABS module, I need to do some testing to see what works. It would be great if the unit accepts a 0-5V square wave (no negative excursions). If not, I am thinking of using a 9-12V supply chip and center tap the output ground, and have the ardino switch a transistor to drive the output to plus/minus 4-6V. This will be a square wave of course. If the controller still doesn't like that, I will have to simulate an actual sine wave. I doubt that will be necessary though.



C++:
// Arudino code for Sprinter Wheel Sensor frequency conversion

// Serial output constants
const bool SERIAL_OUTPUT = true; // set to true to send data out serial line
const bool SERIAL_DIAGNOSE = false; // set to true to send back what was recieved
const long SERIAL_REPORT = 1e6; // report over serial every second

// Conversion constants
const bool ENABLE_CONVERSION = false; // Set to true to turn on conversion
const float freq_to_mph = 30.0 * 3.1416 / 55 / 12 / 5280 * 60 * 60; // Hz to mph conversion; assumes 30in wheel diameter, 55 ticks per revolution
const float freq_to_rpm = 1.0 / 55 * 60; // Hz to rpm conversion; assumes 55 ticks per revolution
const float stall_time = 1e6; // If wheel is stopped for 1 second, force speed to 0
float time_conversion = 55.0 / 44; // converts from real sensor with 55 ticks to 44 ticks

// Input/Output pins
const int INPUT_PIN_L = 2; // left wheel input
const int INPUT_PIN_R = 3; // right wheel input
const int OUTPUT_PIN_L = 4;  // left wheel output
const int OUTPUT_PIN_R = 5; // right wheel output

// Time variables
unsigned long start_time_left = micros();  // For output cycle
unsigned long start_time_right = micros();
unsigned long last_time_left = micros();  // For input cycle
unsigned long last_time_right = micros();
unsigned long serial_time = micros();
unsigned long current_time = micros();

// Main variables
float t_out_left = 1e6; // period, in microseconds
float t_out_right = 1e6;
float t_in_left = 1e6; // period, in microseconds
float t_in_right = 1e6;
bool high_left = false;
bool high_right = false;
float avg_speed = 0;


// Initial set-up code
void setup() {

  // Setup Pin Modes
  pinMode(INPUT_PIN_L, INPUT_PULLUP);
  pinMode(INPUT_PIN_R, INPUT_PULLUP);
  pinMode(OUTPUT_PIN_L, OUTPUT);
  pinMode(OUTPUT_PIN_R, OUTPUT);

  // Setup Interrupts
  //attachInterrupt(INPUT_PIN_L, ISR_L, RISING);
  //attachInterrupt(INPUT_PIN_R, ISR_R, RISING);
  attachInterrupt(digitalPinToInterrupt(INPUT_PIN_L), ISR_L, RISING);
  attachInterrupt(digitalPinToInterrupt(INPUT_PIN_R), ISR_R, RISING);

  // Begin Serial
  Serial.begin(115200);

  // Setup variables
  if (! ENABLE_CONVERSION) time_conversion = 1;
  start_time_left = micros();
  start_time_right = micros();
  serial_time = micros();

  if (SERIAL_OUTPUT) {
    if (ENABLE_CONVERSION) Serial.println("Speed Conversion is ON");

    Serial.print("Time (ms)");  // Overall Time
    Serial.print("\t");
    Serial.print("Left Wheel Input (rpm)");  // Speed from left wheel sensor
    Serial.print("\t");
    Serial.print("Right Wheel Input (rpm)");  // Speed from right wheel sensor
    Serial.print("\t");
    Serial.print("Left Wheel Output (mph)");  // Speed output to car
    Serial.print("\t");
    Serial.println("Right Wheel Output (mph)");  // Speed output to car
  }
}


void loop() {

  // update times
  current_time = micros();
  if (current_time - start_time_left > t_out_left) {
    t_out_left = t_in_left * time_conversion;
    if (current_time - last_time_left > stall_time) t_out_left = 1e9;
    start_time_left = current_time;
  }
  if (current_time - start_time_right > t_out_right) {
    t_out_right = t_in_right * time_conversion;
    if (current_time - last_time_right > stall_time) t_out_right = 1e9;
    start_time_right = current_time;
  }

  // write output waveform
  if (current_time - start_time_left < t_out_left/2) { // write HIGH during 1st half of cycle
    if (! high_left) {
      digitalWrite(OUTPUT_PIN_L, HIGH);
        high_left = true;
    }
  }
  else {  // write LOW
    if (high_left) {
      digitalWrite(OUTPUT_PIN_L, LOW);
        high_left = false;
    }
  }
  if (current_time - start_time_right < t_out_right/2) { // write HIGH during 1st half of cycle
    if (! high_right) {
      digitalWrite(OUTPUT_PIN_R, HIGH);
        high_right = true;
    }
  }
  else {  // write LOW
    if (high_right) {
      digitalWrite(OUTPUT_PIN_R, LOW);
        high_right = false;
    }
  }

  // write to serial
  if (SERIAL_OUTPUT && current_time - serial_time > SERIAL_REPORT) {

    Serial.print(millis()); // Overall Time
    Serial.print("\t");
    Serial.print(1e6 / t_in_left * freq_to_rpm);  // Speed from left wheel sensor
    Serial.print("\t");
    Serial.print(1e6 / t_in_right * freq_to_rpm);  // Speed from right wheel sensor
    Serial.print("\t");
    Serial.print(1e6 / t_out_left * freq_to_mph);  // Speed output to car
    Serial.print("\t");
    Serial.println(1e6 / t_out_right * freq_to_mph);  // Speed output to car

    serial_time = current_time;
  }
}
// end loop

// Interrupt Routines - runs once on each input cycle (when encoder rises)
void ISR_L() {
  // Update times
  current_time = micros();
  t_in_left = current_time - last_time_left;
  last_time_left = current_time;
}

void ISR_R() {
  // Update times
  current_time = micros();
  t_in_right = current_time - last_time_right;
  last_time_right = current_time;
}
 

luthj

Engineer In Residence
I was curious if the Arduino UNO would be fast enough to produce a reasonably accurate waveform. So I did some math. The Uno's clock is 16mhz. thats 1,000,000 cycles per second. It takes about 8 microseconds to execute a basic digital write command. Thats .000008 seconds, or about 100,000 per second. Now there is plenty of other overhead, and we have 2 input and 2 output channels. So lets assume the actual overhead is about 20 times that, so the unit can run the program 5,000 times per second.

https://learn.sparkfun.com/blog/1687

245/75R16 tires have 660 revs per mile. At 60mph that is 11rpm. The GM tone rings are 55 pulses/ticks, so thats a 605hz signal. So in theory the Uno can run update the waveform 5000/600=8.3 times per waveform cycle (at 60mph). That should result in very short lag between changes in input and output frequency.

The program above takes an approach I had not considered (I don't have much microcontroller experience at all). It attaches an interrupt to the input pins (which are digital filtered with the shmitt trigger). When the input goes high, the program records the time, and continues to count until the pin goes low. Every cycle of the program it checks again. When the pin goes low, it calculates the pulse length, adjusts it as necessary, and write the pulse to the output in. Every cycle it checks how long the output has been high/low, and compares it to the desired length.

Now it may be necessary to put some averaging logic in there. However, I believe with a good input filter to remove noise, it should be fine counting each input pulse individually.
 

Stingy49

Member
Your stall time logic could be percentage based on current speed. Makes sense to have a longer stall time when your going 5 mph compared to 50mph.

I like how t_out_right/left is only updated at the end of each cycle. That is a nice touch to prevent uneven square waves.

If you find that this code isn't fast enough you could always directly run the PWM module on the atmel 328p (arduino uno) chip. https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM

This would mean that the waveform generation is handled by dedicated hardware and leaves the CPU free to do other stuff. You can also have an interrupt fire every time the wave completes a cycle to calculate the updated times, achieving the same as your "update times" block of code but without it needing to check the time constantly.

I have an e-series but my younger brother is a ski bum with the long T1N and he would love 4wd. Great work so far, very inspiring!
 

luthj

Engineer In Residence
Yeah, I was thinking about the PWM pins. It looks like there are a few pre-built libraries that allow relatively easy control of the output frequency. Otherwise digging into the control registers sounds like a pain.

I am packing up my stuff in storage tomorrow. Hopefully my leasing company will get back to me, so I can move in the 17th... The lease (like most commercial leasing companies) has a clause forbidding "vehicle repair". I figure worst case, I get a big RV cover for the van, or rig up some fake wheels, to make it look normal...
 

Stingy49

Member
Yeah those would be a good idea.

I love the stealth workspace idea. I can't wait to move out of the city and get some space.

An easy way to measure code speed is to toggle an output pin every iteration. You'd need an oscope or maybe the rpm counter on a multimeter to read it though. You could also track the total time with the micros() function.
 
Yeah, I was thinking about the PWM pins. It looks like there are a few pre-built libraries that allow relatively easy control of the output frequency. Otherwise digging into the control registers sounds like a pain.

I am packing up my stuff in storage tomorrow. Hopefully my leasing company will get back to me, so I can move in the 17th... The lease (like most commercial leasing companies) has a clause forbidding "vehicle repair". I figure worst case, I get a big RV cover for the van, or rig up some fake wheels, to make it look normal...

Just a thought...
Since you looking for a place to work on your van, and since you are moving to NC, maybe you can partner with Ujoint to complete your project. Chris may like to add Sprinter vans to the mix.
 
Last edited:

luthj

Engineer In Residence
Long time no post. We are moved in and started working, so my time is limited again. As a plus I have income, so its a mixed bag. I need to unpack my garage, and get some work tables, a new welder, bench vise, grinder, etc...

I ordered an arduino due, and I will get that setup for the van. Should be easy enough to do some testing.

I need the van to be operational until I get a vehicle for my wife. So until then I am holding off of tearing it down. First step is to loosen and lower the subframe about half an inch, that will let me measure the mounting bolts and engine mount location. If everything looks good, I will order shocks, springs, and new GM wear parts. If those all match my model, I will do final tweaks, generate the DXFs, and send for fabrication. An aggressive timeline would be about 8 weeks. Likely 12.
 

Forum statistics

Threads
185,544
Messages
2,875,706
Members
224,922
Latest member
Randy Towles
Top