Notices
ECU Flash

EVOscan love for PLX?

Thread Tools
 
Search this Thread
 
Old Nov 14, 2006, 12:57 AM
  #16  
Former Sponsor
iTrader: (4)
 
evo4mad's Avatar
 
Join Date: Dec 2003
Location: TGA, New Zealand
Posts: 723
Likes: 0
Received 1 Like on 1 Post
https://www.evolutionm.net/forums/sh...31#post3668831
Old Jan 6, 2008, 01:22 PM
  #17  
Evolving Member
iTrader: (4)
 
RelentlessEVO's Avatar
 
Join Date: Oct 2007
Location: South Jersey
Posts: 122
Likes: 0
Received 2 Likes on 2 Posts
Hamish,

The PLX M-300 does not come with a serial port, as far as I know. So how can I connect it to my laptop to get you the .csv file? I really would love to get my current WB to work with EvoScan (which I have purchased and now use, instead of ECU+ which had already been installed on the car before I got it).

Can anyone explain to me how to hook up the M-300 to my laptop?

-Bill
Old Jan 6, 2008, 03:42 PM
  #18  
Former Sponsor
iTrader: (4)
 
evo4mad's Avatar
 
Join Date: Dec 2003
Location: TGA, New Zealand
Posts: 723
Likes: 0
Received 1 Like on 1 Post
it should be simple, you just need to get the data inputted via a comport. you can get innovate devices that takes a voltage input from any source (plx,300 if it has one) and hook it to evoscan. some evos, and if you are into programming, you can connect it directly to one of the spare ADC ports on your ecu, and log it directly from the ecu. I haven't done it, but i know its possible.
Old Jan 6, 2008, 03:43 PM
  #19  
Former Sponsor
iTrader: (4)
 
evo4mad's Avatar
 
Join Date: Dec 2003
Location: TGA, New Zealand
Posts: 723
Likes: 0
Received 1 Like on 1 Post
or sell your PLX and get a ZT2 or LC1
Old Feb 22, 2008, 11:42 AM
  #20  
Evolved Member
iTrader: (26)
 
silex's Avatar
 
Join Date: Nov 2005
Location: San Diego, CA
Posts: 717
Likes: 0
Received 0 Likes on 0 Posts
Once I finish hooking up my PLX R-500, I will try to get a .csv over to evo4mad. It connects via USB which is translated to a serial comm port so it should fit the bill. I still don't believe that PLX widebands are still not supported since 1.5yrs after this post.
Old Feb 22, 2008, 04:53 PM
  #21  
Former Sponsor
iTrader: (4)
 
evo4mad's Avatar
 
Join Date: Dec 2003
Location: TGA, New Zealand
Posts: 723
Likes: 0
Received 1 Like on 1 Post
yeah send it on over. I'm doing more wideband support development today for v2.2
Old Feb 22, 2008, 09:09 PM
  #22  
Evolved Member
iTrader: (26)
 
silex's Avatar
 
Join Date: Nov 2005
Location: San Diego, CA
Posts: 717
Likes: 0
Received 0 Likes on 0 Posts
Should have the .csv for you over the weekend
Old Aug 13, 2009, 12:21 PM
  #23  
Evolved Member
iTrader: (6)
 
SWOLN's Avatar
 
Join Date: Sep 2005
Location: In the Florida Swamps
Posts: 1,791
Received 13 Likes on 13 Posts
Was this ever resolved ? Thanks
Old Aug 13, 2009, 03:26 PM
  #24  
Evolving Member
iTrader: (3)
 
gear head's Avatar
 
Join Date: Sep 2005
Location: Utah
Posts: 333
Likes: 0
Received 0 Likes on 0 Posts
I have mine wired into the ecu as per this thread....

https://www.evolutionm.net/forums/ec...ial-cable.html
Old Sep 15, 2009, 05:58 PM
  #25  
Evolving Member
iTrader: (4)
 
funks's Avatar
 
Join Date: Jul 2007
Posts: 488
Likes: 0
Received 0 Likes on 0 Posts
They also have a newer unit out which also supports SERIAL LOGGING (EvoSCAN doesn't support it though) and daisy chaining - similar to Innovate (MTS).





The dongle thing (converts serial -> USB) uses FTDI drivers, my assumption is that it just shows up as a virtual com port under windows, just a matter of parsing its data output. Some of the older units didn't have serial output..

The SM-AFR + MD5 Gauge can be had for 240$ (StreetRays.com). The USB Dongle Cable thing costs 66$ dollars though.

They also have the M300 Tuner Edition



Can be had for 270$ (StreetRays.com), also needs the optional serial dongle cable though if logging via computer.

Last edited by funks; Sep 15, 2009 at 06:16 PM.
Old Sep 17, 2009, 10:59 PM
  #26  
Evolving Member
iTrader: (4)
 
funks's Avatar
 
Join Date: Jul 2007
Posts: 488
Likes: 0
Received 0 Likes on 0 Posts
Hamish,

PLX iMFD serial protocol info

I believe the following code will work (as an example), I'll verify it once the controller get's here..

PHP Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.IO.Ports;

namespace 
PLXWidebandReader
{
    class 
Program
    
{
        static 
void Main(string[] args)
        {
            
Console.WriteLine("Defaulting to PLX on COM4, testmode enabled.");
            
IWidebandReader reader = new PLXWidebandReader("COM4");
            
// IWidebandReader reader = new PLXWidebandReader("COM4", 1, new PLXWidebandReader.fuelTypeFunction(new PLXWidebandReader.FuelType().Gasoline));
            
((PLXWidebandReader)reader).TestMode true// keep looping through test packet

            
reader.Start();

            
Console.WriteLine("Timestamp,AFR");
            for (
int i 01000i++)
            {
                
Console.WriteLine("{0:o},{1:F2}"DateTime.Nowreader.LatestReading);
                
Thread.Sleep(250);
            }

            
reader.Stop();

        }
    }

    interface 
IWidebandReader
    
{
        
double LatestReading
        
{
            
get;
        }

        
void Start();
        
void Stop();

    }


    class 
PLXWidebandReader IWidebandReader
    
{

        private 
Object locker = new Object();
        private 
fuelTypeFunction fuelCalcFunction;

        private 
double latestReading;
        public 
double LatestReading
        
{
            
get { return latestReading; }
        }

        private readonly 
int instanceNumber;
        private 
SerialPort comPort;
        private 
Thread worker;
        
bool continueRunning false;

        
// test related bits

        
int sampleBytePacketIndex 0// this is only used for testing.
        
private bool testMode false// if true, test mode
        
public bool TestMode
        
{
            
get { return testMode; }
            
set testMode value; }
        }

        public 
PLXWidebandReader(String comPortName)
            : 
this(comPortName1, new fuelTypeFunction(new FuelType().Gasoline))
        {
        }

        public 
PLXWidebandReader(String comPortNameint instanceNumber)
            : 
this(comPortNameinstanceNumber, new fuelTypeFunction(new FuelType().Gasoline))
        {
        }

        public 
PLXWidebandReader(String comPortNameint instanceNumberfuelTypeFunction fuelType)
        {

            if (
false == IsSerialPortNameValid(comPortName))
            {
                throw new 
ArgumentException(comPortName ", is invalid.");
            }


            if (
instanceNumber || instanceNumber 32)
            {
                
// Note: 1 should be passed if there's only one AFR module.
                
throw new ArgumentOutOfRangeException("instance number is required to be between 1 and 32.");
            }

            
init(comPortName);

            
this.fuelCalcFunction fuelType;
            
this.instanceNumber instanceNumber;
        }

        private 
bool IsSerialPortNameValid(String comPortName)
        {

            
bool serialPortNameValid false;

            foreach (
String serialPortName in SerialPort.GetPortNames())
            {
                if (
true == serialPortName.Equals(comPortName))
                {
                    
serialPortNameValid true;
                }
            }

            return 
serialPortNameValid;
        }

        private 
void init(String comPortName)
        {

            
comPort = new SerialPort();
            
comPort.PortName comPortName;
            
comPort.BaudRate 19200// per iMFD 19200 baud
            
comPort.DataBits 8// per iMFD 8
            
comPort.Parity Parity.None// per iMFD N
            
comPort.StopBits StopBits.One// per iMFD 1
            
comPort.Handshake Handshake.None;

        }

        
/*
         * This method is only used for testing
         */
        
private byte GetByteFromSamplePacket()
        {
            
byte[] packet = { 0x800x000x000x000x000x040x000x000x010x000x050x000x010x000x000x0F0x40 };

            if (
sampleBytePacketIndex >= packet.Length)
            {
                
sampleBytePacketIndex 0;
            }

            return 
packet[sampleBytePacketIndex++];

        }

        private 
double GetDataFromPacket(List<bytepacketContentBuffer)
        {

            
double afrReading 0;

            for (
int i 1; (5) < packetContentBuffer.Count 5)
            {
                
// Address MSB == 0 && Address LSB == 0 is a wideband.
                
if (== packetContentBuffer[+ (int)PacketDataOffset.AddressMSB] && == packetContentBuffer[+ (int)PacketDataOffset.AddressLSB])
                {
                    
// instance number is ordinal, 0-based.  Need to add one before comparing.
                    
if (instanceNumber == ((packetContentBuffer[+ (int)PacketDataOffset.Instance]) + 1))
                    {
                        
// we found the correct instance number

                        
int dataMSB packetContentBuffer[+ (int)PacketDataOffset.DataMSB];
                        
int dataLSB packetContentBuffer[+ (int)PacketDataOffset.DataLSB];

                        
afrReading fuelCalcFunction((dataMSB << 6) | dataLSB);

                        break;
                    }
                }
            }

            return 
afrReading;
        }

        private 
void InitiateReading()
        {

            List<
bytepacketContentBuffer = new List<byte>();
            
bool packetStarted false;

            while (
true == continueRunning)
            {

                try
                {

                    
byte aByte 0;

                    if (
testMode)
                    {
                        
aByte GetByteFromSamplePacket(); // test packet
                    
}
                    else
                    {
                        
aByte = (byte)comPort.ReadByte(); // to read from the serial port
                    
}

                    switch (
aByte)
                    {
                        case 
0x80:
                            
// start byte
                            
packetContentBuffer.Clear();
                            
packetContentBuffer.Add(aByte);
                            
packetStarted true;
                            break;
                        case 
0x40:
                            
// stop byte
                            
if (packetStarted)
                            {
                                
packetContentBuffer.Add(aByte);
                                
latestReading GetDataFromPacket(packetContentBuffer);
                                
packetStarted false;
                            }
                            
Thread.Sleep(0);
                            break;
                        default:
                            if (
packetStarted)
                            {
                                
packetContentBuffer.Add(aByte);
                            }
                            break;
                    }

                }
                catch (
ThreadInterruptedException)
                {
                    
packetStarted false;
                }

            }

        }

        public 
void Start()
        {
            
lock (locker)
            {
                if (
null == worker || false == worker.IsAlive)
                {
                    
continueRunning true;
                    
comPort.Open();
                    
worker = new Thread(new ThreadStart(InitiateReading));
                    
worker.Start();
                }
                else
                {
                    throw new 
InvalidOperationException("Already started.");
                }
            }

        }

        public 
void Stop()
        {
            
lock (locker)
            {

                if (
true == continueRunning)
                {
                    
continueRunning false;
                    
worker.Join(TimeSpan.FromSeconds(5));

                    if (
true == worker.IsAlive)
                    {
                        
// if worker is still alive, most likely still blocked on readByte, interrupt
                        
worker.Interrupt();
                    }

                    
comPort.Close();

                }
                else
                {
                    throw new 
InvalidOperationException("Not started.");
                }
            }
        }

        public class 
FuelType
        
{

            public 
double Lambda(double x)
            {
                return (
3.75 68) / 100d;
            }

            public 
double Gasoline(double x)
            {
                return (
2.55 100) / 10d;
            }

            public 
double Diesel(double x)
            {
                return (
2.58 100) / 10d;
            }

            public 
double Methanol(double x)
            {
                return (
5.856 43.5) / 10d;
            }

            public 
double Ethanol(double x)
            {
                return (
4.167 61.7) / 10d;
            }

            public 
double LPG(double x)
            {
                return (
2.417 105.6) / 10d;
            }

            public 
double CNG(double x)
            {
                return (
2.18 117) / 10d;
            }
        }

        enum 
PacketDataOffset int AddressMSB 0AddressLSB 1Instance 2DataMSB 3DataLSB };

        public 
delegate double fuelTypeFunction(double x);
    }



Last edited by funks; Sep 25, 2009 at 01:11 AM.
Old Sep 18, 2009, 02:46 AM
  #27  
Former Sponsor
iTrader: (4)
 
evo4mad's Avatar
 
Join Date: Dec 2003
Location: TGA, New Zealand
Posts: 723
Likes: 0
Received 1 Like on 1 Post
thanks funks, i'll add that PLX parser to my code now, cheers.
Old Sep 24, 2009, 08:37 PM
  #28  
Evolving Member
iTrader: (4)
 
funks's Avatar
 
Join Date: Jul 2007
Posts: 488
Likes: 0
Received 0 Likes on 0 Posts
evo4mad,

I updated the source sample above, made it more readable (the old one was harder to follow - lol). Nevertheless, I tested the code on my car - works just fine. I'm getting about 10 samples per second which is in-line with the iMFD docs..
Old Sep 25, 2009, 12:11 AM
  #29  
Evolved Member
iTrader: (22)
 
codgi's Avatar
 
Join Date: Aug 2004
Location: Seattle, WA
Posts: 2,491
Received 41 Likes on 37 Posts
Code with my comments:

Code:
        public PLXWidebandReader(String comPortName, int instanceNumber, fuelTypeFunction fuelType)
        {
Any reasons why you check the validity of the first two arguments but not the last?

Code:
            if (false == IsSerialPortNameValid(comPortName))
Is the same as

Code:
             if (!IsSerialPortNameValid(comPortName))
Code:
            for (int i = 1; i < packetContentBuffer.Count; i = i + 5)
            {

                // make sure we don't overrun our buffer
                if ((i + 5) < packetContentBuffer.Count)
                {
If you use a variation of the condition in the if statement as the ending condition for the for loop, you don' t need this if statement.

As before

Code:
                if (continueRunning == true)
Can be

Code:
if (continueRunning)
Nitpicking I know but....
Old Sep 25, 2009, 12:39 AM
  #30  
Evolving Member
iTrader: (4)
 
funks's Avatar
 
Join Date: Jul 2007
Posts: 488
Likes: 0
Received 0 Likes on 0 Posts
Damn, code ****! - lol.

I just like being verbose - updated sample posted above. I also wrote a sample LM1 Wideband Reader, if anybody would like to test it out for me, that would be great. Somebody else might find it useful.

Last edited by funks; Sep 25, 2009 at 11:47 PM.


Quick Reply: EVOscan love for PLX?



All times are GMT -7. The time now is 08:31 PM.