Sunday, April 6, 2014

Arduino Uno interface to BMW 325i M50 Harmonic Damper 1.0





This posting relates to some of the work that has been done in the study of the BMW electronics and how it can be interfaced to the speedometer cluster and the Soliton 1 power controller.
 
If one could retain the original BMW harmonic damper (Picture DSC05268), then the speedometer RPM gauge might operate without modification or the purchase of other shaft mounted sensors.  Of additional interest is the fact that the harmonic damper has an integral 142x20 mm pulley which can be used for air conditioning or other utilities.  What complicates the use of the harmonic damper is the fact that it has 58 teeth present and 2 teeth missing.  Although this may allow for determining the positional shaft  rotation of an ICE, it has no obvious utility with an EV.  The missing teeth complicates the use of the damper since each time the missing teeth pass the photo, or Hall effect style sensor, the measurement will be distorted  and unstable.



      Picture DSC05268 of the harmonic damper from the 1992 BMW 325i M50 engine showing
                          the 58 teeth and the missing 2 teeth at the upper left at about 10:30.

One possible solution is to ignore the missing teeth, and instead just count all 58 teeth as they pass by.  Once 58 teeth are counted, then output a signal.  The output result would always be independent of the starting point of the count on the harmonic damper.
 
Investigation suggested that an Arduino Uno style programmable controller might be a very inexpensive and readily available (Ebay) platform to use.  The Arduino Uno is an open source platform with a large body of open source software available to make the device perform in different ways.  Having no formal training in software, the availability of down loadable sketches (programs) was very attractive.  YouTube also offers many tutorials which were found to be helpful at this stage of the project. 

The following were found to be quite informative: 

Lewis Loflin at:   https://www.youtube.com/watch?v=yMP3mfdEbRQ 
and Jeremy Blum at :  https://www.youtube.com/watch?v=fCxzA9_kg6s 



Picture DSC00827 of the Arduino Uno set up with two status LEDs and a pushbutton switch.  The yellow wire, connected to Arduino Digital pin 8, was later attached to an HP33121A waveform generator.  Final testing involved connecting this yellow input wire to the sensor output of the BMW harmonic damper (after signal conditioning!!).

 
The test of the concept started with the patching together of portions of various other sketches from the Arduino home page at http://www.arduino.cc/ .  After trial and error, a gradual understanding of how the code works slowly began to sink in, and the sketch came together.  A full listing of the sketch can be found at the bottom of this posting.

Initially the sketch was tested using the push button on the prototype board (right side of  Picture DSC00827 above).  The red LED is on the Arduino Uno (top left), and the second green LED is on the proto board at the upper right.  By stepping through the code, it was possible to make every mistake possible, and then finally have the sketch work properly.  At that point a Hewlett Packard 331240A 15MHz Function/Arbitrary Waveform Generator was substituted for the pushbutton.  It was possible to select on the front panel of the generator an output of 5 volts peak to peak, with a +2.5 volt offset.  Thus, the square wave signal was between 0.0 volts and 5.0 volts peak.  The grounds of both the Arduino Uno proto board and the HP signal generator were connected together.  After setting the output to about 60 Hz, it was possible to demonstrate and record the signals on the Tektronix TDS 3012 Oscilloscope.  The upper trace (in gold) was the 60 Hz signal, and the bottom trace (blue) was the output of the count as the 58th pulse was counted.  Careful examination indicated that the output was in fact 1 pulse for every 58 counts and the signal produced was now available for input into a Soliton 1 or other controller device.



                        Picture DSC00821 with HP3312A frequency set to about 60 Hz.

To confirm that the Arduino Uno would be able to keep up with the frequency of the signal of the BMW harmonic damper, two additional frequency tests were performed.  Typical idle speed for the 1992 BMW 325i M50 is about 700 RPM.  This results in 700x58=40,600 pulses per minute that would be picked up from the metal damper teeth and a Hall effect style sensor.  Viewing it differently, at ICE idle speed there would be 40,600/60=676.667 pulses each second, thus 676.667 Hz.  The HP33121A was set at about 666.5 Hz, and the waveform produced can be seen in Picture DSC00823.



                         Picture DSC00823 with HP3312A frequency set to about 666.5 Hz. 
                       This frequency corresponds to an motor idle speed of about 700 RPM.

Typical ICE rotational speed for the 1992 BMW 325i M50 at about 70 mph is expected to be about 2500 RPM.  This is a little different than what is expected for the Warp 11, where the red line speed might be about 4000 RPM.  A measurement was taken at 4,169 Hz, and from calculation, 4,169 cycles per  second, works out to be 4,169x60=250,140 pulses per minute, thus 250,140/58=4312.75 RPM.  The waveform indicates that the signal remains very stable and the Arduino Uno can easily keep pace with the pulse stream.



                             Picture DSC00824 with HP3312A frequency set to about 4169 Hz.  
                           This frequency corresponds to a motor speed of about 4312.76 RPM.

The next posting will relate to the interface required between the Arduino Uno inputs and the high voltage output of the BMW OEM harmonic damper sensor.

**************************

The sketch below is what was used for this series of tests.   It is certain that the software can be done more elegantly by someone who is familiar with the art of programming, but for now, this is what is being used.  If readers have any questions or would like to share ideas or input regarding ways to improve the sketch, or the project, please contact us at sales@narchem.com  .

/*
sketch_apr06a_BMW_Harmonic_Damper_v1_0

The purpose of this sketch, is the development of an Arduino interface between a 1992 BMW 325i OEM harmonic damper and the digital electronics of a Soliton1 power control unit.  The Arduino
interface will facilitate replacement of the original M50 Internal Combustion Engine with an all electric drive.

For purposes of testing the software, two LEDs were used to monitor the count sequence. 
Arduino pin DO-13 is set HIGH and LED1 is turned ON from count 1 through 57. 
Arduino pin DO-13 goes LOW and LED1 is turned off for count number 58.
Arduino pin DO-13 then goes HIGH again on count number 59, and the count begins all over.
Arduino pin DO-12 is connected to LED2 (with a 330 ohm resistor to ground). 
Arduino pin DO-12 stays LOW and LED2 remains off from count 1 through 57. 
Arduino pin DO-12 goes HIGH on count number 58 and LED2 turns on.
Arduino pin DO-12 then goes LOW again for count number 59, and the LED goes out,
as the count begins all over.

The serial output cycles are follows:
Serial Output        1,2,3,4,5,...,56,57,0,1,2,3,4,5,....,56,57,0,1,2,3,4,5, etc.
LED1 (1 = On)     1,1,1,1,1,...., 1,  1,0,1,1,1,1,1,....., 1, 1, 0,1,1,1,1,1, etc.
LED2                    0,0,0,0,0,...., 0,  0,1,0,0,0,0,0,....., 0, 0, 1,0,0,0,0,0, etc.

For initial testing a push button switch was used to provide the signal to Arduino Uno Digital input pin 8. 
Later, an HP 33120A waveform generator was used, and then final testing was carried out using the OEM BMW sensor and the OEM harmonic damper that was  mounted on the Warp 11 drive shaft..

It is necessary to click on "Tools" at the top of the sketch and select "Serial Monitor" to be able to collect data on the PC.

Created April-6-2014
 by William McDaniel
 This example code is open source and it is available for use by anyone in the public domain.
*/


const int LED1 = 13;                 // HIGH on this output indicates +5 volt input signal
                                                  // this pin goes LOW on the 58th pulse and the LED is
                                                  //extinguished
const int LED2 = 12;                // High of this output illuminates the LED on the 58th  pulse
int state=LOW;
int lastState=LOW;
int count=0;
void setup(){
  
pinMode(LED1, OUTPUT);    //defines Digital pin 13 as an output
pinMode(LED2, OUTPUT);    //defines Digital pin 12 as an output
Serial.begin(9600);                   //enables the Serial communications with the PC
                                                  //when the USB cable is connected to the PC
pinMode(8, INPUT);               //defines Digital pin 8 to be an input
state=digitalRead(8);
}
void loop(){
 
if (state==HIGH && lastState==LOW) 
                                                 //compares the previous state with the current state. 
                                                 //if the last state was LOW, and the current measurement is HIGH,
                                                //then increment the counter by 1.
{
count++;
if (count<58)                           //if the count is less than 58 then perform next 4 lines of code
{
digitalWrite(LED1, HIGH);  //turns on LED1 to indicate that the count is between 1 and 57
                                          
digitalWrite(LED2, LOW);  //turns off LED2 to indicate that a count between 1 and 57
                                              //is occurring
}
else                                        //otherwise, if the count is number 58, then perform the next
                                              //5 lines of code
{
digitalWrite(LED1, LOW);   //turns off LED1 to indicate that count number 58 is occurring
digitalWrite(LED2, HIGH);  //turns on LED2 to indicate that count number 58 is occurring
count = count - 58;                //subtracts 58 from the counter, to zero out the count and allow
                                              //a new count to begin.

Serial.println(count);             //prints the value of the count to the computer monitor
}
lastState=state;
state=digitalRead(8);
}  

No comments:

Post a Comment