Notices
ECU Flash

EVOscan love for PLX?

Thread Tools
 
Search this Thread
 
Old Nov 14, 2006 | 12:57 AM
  #16  
evo4mad's Avatar
Former Sponsor
iTrader: (4)
 
Joined: Dec 2003
Posts: 723
Likes: 1
From: TGA, New Zealand
https://www.evolutionm.net/forums/sh...31#post3668831
Reply
Old Jan 6, 2008 | 01:22 PM
  #17  
RelentlessEVO's Avatar
Evolving Member
iTrader: (4)
 
Joined: Oct 2007
Posts: 122
Likes: 2
From: South Jersey
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
Reply
Old Jan 6, 2008 | 03:42 PM
  #18  
evo4mad's Avatar
Former Sponsor
iTrader: (4)
 
Joined: Dec 2003
Posts: 723
Likes: 1
From: TGA, New Zealand
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.
Reply
Old Jan 6, 2008 | 03:43 PM
  #19  
evo4mad's Avatar
Former Sponsor
iTrader: (4)
 
Joined: Dec 2003
Posts: 723
Likes: 1
From: TGA, New Zealand
or sell your PLX and get a ZT2 or LC1
Reply
Old Feb 22, 2008 | 11:42 AM
  #20  
silex's Avatar
Evolved Member
iTrader: (26)
 
Joined: Nov 2005
Posts: 717
Likes: 0
From: San Diego, CA
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.
Reply
Old Feb 22, 2008 | 04:53 PM
  #21  
evo4mad's Avatar
Former Sponsor
iTrader: (4)
 
Joined: Dec 2003
Posts: 723
Likes: 1
From: TGA, New Zealand
yeah send it on over. I'm doing more wideband support development today for v2.2
Reply
Old Feb 22, 2008 | 09:09 PM
  #22  
silex's Avatar
Evolved Member
iTrader: (26)
 
Joined: Nov 2005
Posts: 717
Likes: 0
From: San Diego, CA
Should have the .csv for you over the weekend
Reply
Old Aug 13, 2009 | 12:21 PM
  #23  
SWOLN's Avatar
Evolved Member
20 Year Member
Photogenic
Liked
Loved
iTrader: (6)
 
Joined: Sep 2005
Posts: 1,791
Likes: 13
From: In the Florida Swamps
Was this ever resolved ? Thanks
Reply
Old Aug 13, 2009 | 03:26 PM
  #24  
gear head's Avatar
Evolving Member
iTrader: (3)
 
Joined: Sep 2005
Posts: 333
Likes: 0
From: Utah
I have mine wired into the ecu as per this thread....

https://www.evolutionm.net/forums/ec...ial-cable.html
Reply
Old Sep 15, 2009 | 05:58 PM
  #25  
funks's Avatar
Evolving Member
iTrader: (4)
 
Joined: Jul 2007
Posts: 488
Likes: 0
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.
Reply
Old Sep 17, 2009 | 10:59 PM
  #26  
funks's Avatar
Evolving Member
iTrader: (4)
 
Joined: Jul 2007
Posts: 488
Likes: 0
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 = 0; i < 1000; i++)
            {
                Console.WriteLine("{0:o},{1:F2}", DateTime.Now, reader.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(comPortName, 1, new fuelTypeFunction(new FuelType().Gasoline))
        {
        }

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

        public PLXWidebandReader(String comPortName, int instanceNumber, fuelTypeFunction fuelType)
        {

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


            if (instanceNumber < 1 || 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 = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x0F, 0x40 };

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

            return packet[sampleBytePacketIndex++];

        }

        private double GetDataFromPacket(List<byte> packetContentBuffer)
        {

            double afrReading = 0;

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

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

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

                        break;
                    }
                }
            }

            return afrReading;
        }

        private void InitiateReading()
        {

            List<byte> packetContentBuffer = 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 (x / 3.75 + 68) / 100d;
            }

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

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

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

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

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

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

        enum PacketDataOffset : int { AddressMSB = 0, AddressLSB = 1, Instance = 2, DataMSB = 3, DataLSB = 4 };

        public delegate double fuelTypeFunction(double x);
    }

} 

Last edited by funks; Sep 25, 2009 at 01:11 AM.
Reply
Old Sep 18, 2009 | 02:46 AM
  #27  
evo4mad's Avatar
Former Sponsor
iTrader: (4)
 
Joined: Dec 2003
Posts: 723
Likes: 1
From: TGA, New Zealand
thanks funks, i'll add that PLX parser to my code now, cheers.
Reply
Old Sep 24, 2009 | 08:37 PM
  #28  
funks's Avatar
Evolving Member
iTrader: (4)
 
Joined: Jul 2007
Posts: 488
Likes: 0
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..
Reply
Old Sep 25, 2009 | 12:11 AM
  #29  
codgi's Avatar
Evolved Member
20 Year Member
Photogenic
Liked
Loved
Community Favorite
iTrader: (22)
 
Joined: Aug 2004
Posts: 2,493
Likes: 41
From: Seattle, WA
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....
Reply
Old Sep 25, 2009 | 12:39 AM
  #30  
funks's Avatar
Evolving Member
iTrader: (4)
 
Joined: Jul 2007
Posts: 488
Likes: 0
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.
Reply



All times are GMT -7. The time now is 01:29 AM.