Audi A5 / S5 / RS5 Coupe & Cabrio (B9) Discussion forum for the B9 Audi A5, S5 and RS5 Coupe and Cabriolet 2018 model year and up

Active Lane Assist On/Off solution for non DAP cars

Thread Tools
 
Search this Thread
 
Old 09-09-2018, 04:40 PM
  #1  
AudiWorld Member
Thread Starter
 
Trade_it_all_4_more's Avatar
 
Join Date: Mar 2018
Location: NW Indiana / Chicagoland
Posts: 439
Likes: 0
Received 90 Likes on 53 Posts
Default Active Lane Assist On/Off solution for non DAP cars

Kudo’s to the OP of the thread with details on how to enable ALA:

https://www.audiworld.com/forums/a4-...sense-2907906/

I wanted to come up with a fairly easy to implement enable / disable for this feature. Based on the thread, there wasn’t any easy or cost-effective options, outside of using the traction control button. Seeing how I will drive my vehicle in the snow, I wanted a different method.

My theory was, if you can enable / disable it via one parameter change in OBD11 while driving, then I should be able to mimic that can-bus communications via a digital input. Step 1 – while driving the car I was able to use OBD11 to enable / disable ALA on the fly, without having to power off the car or anything else. Step 1 complete, on to the fun stuff.

I’m going to separate this into multiple posts (so if people do a quote/reply without editing the quote, the thread won’t be out of control long…)

Last edited by Trade_it_all_4_more; 09-09-2018 at 04:56 PM.
Old 09-09-2018, 04:41 PM
  #2  
AudiWorld Member
Thread Starter
 
Trade_it_all_4_more's Avatar
 
Join Date: Mar 2018
Location: NW Indiana / Chicagoland
Posts: 439
Likes: 0
Received 90 Likes on 53 Posts
Default

Step 2 – need a device that can speak can-bus and accept digital inputs. I must say, I was rather disappointed in the internet world here (or maybe my ability to search for what I wanted?) I found very few blogs about can-bus communications, specifically what the communication codes stood for. I did find a few generic examples where people used an Arduino. I’ve never used an Arduino, but how hard can it be? Eventually it’s all zero’s and one’s as I like to say:

https://www.amazon.com/gp/product/B008GRTSV6/ref=oh_aui_detailpage_o04_s01?ie=UTF8&psc=1 https://www.amazon.com/gp/product/B008GRTSV6/ref=oh_aui_detailpage_o04_s01?ie=UTF8&psc=1

and can-bus comms adapter:

https://www.amazon.com/gp/product/B076DSQFXH/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1 https://www.amazon.com/gp/product/B076DSQFXH/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1

There might be a better / smaller controller for doing this, but this was what I came up with.
Old 09-09-2018, 04:44 PM
  #3  
AudiWorld Member
Thread Starter
 
Trade_it_all_4_more's Avatar
 
Join Date: Mar 2018
Location: NW Indiana / Chicagoland
Posts: 439
Likes: 0
Received 90 Likes on 53 Posts
Default

Step 3 – need to sniff the can-bus traffic from OBD11 so I can replicate the changing of

A5 ADAPTATIONS: Switch-on condition, lane depart. warn. From on to off and then off to on.

I bought a Y connector so I could easily tap into the diagnostic can-bus:

https://www.amazon.com/gp/product/B00HJAMBI8/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1 https://www.amazon.com/gp/product/B00HJAMBI8/ref=oh_aui_detailpage_o04_s00?ie=UTF8&psc=1

From an Audi publication, it appears they follow the standard pins 6 and 14 for the can-bus on the OBD port.:





For the Arduino, I downloaded a can-bus library at: https://github.com/Seeed-Studio/CAN_BUS_Shield

You download it as a zip file, and in the Arduino Editor Select Sketch --> Import Library --> Add Library and then point it to the Zip file you downloaded.

Now you have access to can-bus examples in your editor, and I used the receive check program. Via the Arduino software, you can use Tools, serial monitor to see serial communication outputted from the Arduino. I downloaded the program, and hooked the Arduino can-bus H,L on pins 6 and 14, and sure enough, started seeing communications from the OBD11 to the car! I quickly realized, there is a bit of background comms:

0x74F 2 3E 0 55 55 55 55 55
0x7B9 2 7E 0 0 0 0 0

I wrote a filter in Arduino to eliminate seeing this from my results. Now, I had a clean screen with no data being captured. I then toggled the ALA on / off, and noticed there was a couple of different comms results, as one time the security code (20103) was required, and the other time it was not:

OFF TO ON - NO CODE
0x74F 6 2E F1 99 18 9 8 55
0x7B9 3 6E F1 99 0 0 0 0
0x74F 10 9 2E F1 98 7 73 28
0x7B9 30 0 0 0 0 0 0 0
0x74F 21 F6 30 39 55 55 55 55
0x7B9 3 6E F1 98 0 0 0 0
0x74F 4 2E 9 A1 40 55 55 55
0x7B9 3 7F 2E 78 0 0 0 0
0x7B9 3 6E 9 A1 0 0 0 0
0x74F 3 22 9 A1 55 55 55 55
0x7B9 4 62 9 A1 40 0 0 0

ON TO OFF - NO CODE
0x74F 6 2E F1 99 18 9 8 55
0x7B9 3 6E F1 99 0 0 0 0
0x74F 10 9 2E F1 98 7 73 28
0x7B9 30 0 0 0 0 0 0 0
0x74F 21 F6 30 39 55 55 55 55
0x7B9 3 6E F1 98 0 0 0 0
0x74F 4 2E 9 A1 0 55 55 55
0x7B9 3 7F 2E 78 0 0 0 0
0x7B9 3 6E 9 A1 0 0 0 0
0x74F 3 22 9 A1 55 55 55 55
0x7B9 4 62 9 A1 0 0 0 0

OFF TO ON – WITH CODE ENTERED
0x74F 2 10 3 55 55 55 55 55
0x7B9 6 50 3 0 32 1 F4 0
0x74F 6 2E F1 99 18 9 8 55
0x7B9 3 6E F1 99 0 0 0 0
0x74F 10 9 2E F1 98 7 73 28
0x7B9 30 0 0 0 0 0 0 0
0x74F 21 F6 30 39 55 55 55 55
0x7B9 3 6E F1 98 0 0 0 0
0x74F 4 2E 9 A1 40 55 55 55
0x7B9 3 7F 2E 33 0 0 0 0
0x74F 2 27 3 55 55 55 55 55
0x7B9 6 67 3 13 DE 3E 33 0
0x74F 6 27 4 13 DE 8C BA 55
0x7B9 2 67 4 0 0 0 0 0
0x74F 6 2E F1 99 18 9 8 55
0x7B9 3 6E F1 99 0 0 0 0
0x74F 10 9 2E F1 98 7 73 28
0x7B9 30 0 0 0 0 0 0 0
0x74F 21 F6 30 39 55 55 55 55
0x7B9 3 6E F1 98 0 0 0 0
0x74F 4 2E 9 A1 40 55 55 55
0x7B9 3 7F 2E 78 0 0 0 0
0x7B9 3 6E 9 A1 0 0 0 0
0x74F 3 22 9 A1 55 55 55 55
0x7B9 4 62 9 A1 40 0 0 0

Now on to analysis:
Old 09-09-2018, 04:48 PM
  #4  
AudiWorld Member
Thread Starter
 
Trade_it_all_4_more's Avatar
 
Join Date: Mar 2018
Location: NW Indiana / Chicagoland
Posts: 439
Likes: 0
Received 90 Likes on 53 Posts
Default

For the non security code version (not required as OBD11 has recently communicated using the code), it was rather simple to determine the 0x74F messages were the OBD11 outbound ones and the 0x7B9 were the outbound ones from the Audi. Additionally, the number “40” bolded below, was clearly the parameter being changed. That number is basically 40 or 0.

OFF TO ON - NO CODE
0x74F 6 2E F1 99 18 9 8 55
0x7B9 3 6E F1 99 0 0 0 0
0x74F 10 9 2E F1 98 7 73 28
0x7B9 30 0 0 0 0 0 0 0
0x74F 21 F6 30 39 55 55 55 55
0x7B9 3 6E F1 98 0 0 0 0
0x74F 4 2E 9 A1 40 55 55 55
0x7B9 3 7F 2E 78 0 0 0 0
0x7B9 3 6E 9 A1 0 0 0 0
0x74F 3 22 9 A1 55 55 55 55
0x7B9 4 62 9 A1 40 0 0 0

The security side was a bit more complicated. I captured 3 toggles requiring the security code. In each example the following line appeared to be the ‘send me a code’ request from Audi:

0x7B9 6 67 3 13 DE 3E 33 0

But… the HEX numbers 13,DE,3E,33 were different in each of my captures. Additionally, the ODB11 response:

0x74F 6 27 4 13 DE 8C BA 55

Also had different numbers where you see 13, DE, 8C, BA. At first I thought – dead end, project over. But rather quickly, I saw the following pattern:

33 from Audi became BA in ODB11 response. You’re adding “135” decimal. Checked the other 2 responses, same thing, expect the third result was greater than HEX FF, so there was a carry over to the next. 3E from Audi became 8C from ODB11 – you’re adding 78 decimal. DE from Audi beame DE (adding zero) – unless there was a carry over from the number to the right. The 13 stayed 13, and in my code, I just copied that number in my program, but I wonder if a carry bit addition might be necessary. Odds of that happening are slim, and a simple retry in the comms would likely render that moot.

My guess is, Audi is sending the random numbers for the security code to be added to, as that greatly increases the time of a brute force hack of the security code.

Now – I have my repeatable send and receives for changing ALA. Onto the coding.
Old 09-09-2018, 04:49 PM
  #5  
AudiWorld Member
Thread Starter
 
Trade_it_all_4_more's Avatar
 
Join Date: Mar 2018
Location: NW Indiana / Chicagoland
Posts: 439
Likes: 0
Received 90 Likes on 53 Posts
Default

C++ is not my typical programming language, so for the experienced C++ programmers, I’m sure my code is less than optimized, and maybe even laughable. I used (2) inputs on the Arduino for ease of getting the beta program up and running. Long term, I may go with a single toggle input, and add some messaging that polls the parameter and then toggles if vs. simply writing an ON or OFF based on the input. In theory, you could use a single switch, with 2 positions, or a 3 position (spring return to center) and use the 2 inputs vs. two physical buttons for the 2 inputs.

When input #2 comes on, my ALA lines show up on the Dash. When input #4 comes on, my ALA lines are gone.


Code:
// staring code used from can-bus example code:
// loovee, 2014-6-13
// can bus example code modified by JR 9/8/2018
// beta version 1.00.00
// use and implement at your own risk

#include <SPI.h>
#include "mcp_can.h"

// the cs pin of the version after v1.1 is default to D9
// v0.9b and v1.0 is default D10
const int SPI_CS_PIN = 9;
MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
const int OnbuttonPin = 2;
const int OffbuttonPin = 4;
int OnButtonState = 0;
int OffButtonState = 0;
int skip = 0;
int msgNumber = 0;
int SendMessageRequest = 0;
int LastMessageSent = 0;
int tempMath1 = 0;
int carryOne = 0;
int TimeOut = 0;
unsigned char canMsgInit[8] = {0x02, 0x10, 0x03, 0x55, 0x55, 0x55, 0x55, 0x55};
unsigned char canMsg1[8] = {0x06, 0x2E, 0xF1, 0x99, 0x18, 0x09, 0x08, 0x55};
unsigned char canMsg2[8] = {0x10, 0x09, 0x2E, 0xF1, 0x98, 0x07, 0x73, 0x28};
unsigned char canMsg3[8] = {0x21, 0xF6, 0x30, 0x39, 0x55, 0x55, 0x55, 0x55};
unsigned char canMsg4[8] = {0x04, 0x2E, 0x09, 0xA1, 0x40, 0x55, 0x55, 0x55};
unsigned char canMsg5[8] = {0x03, 0x22, 0x09, 0xA1, 0x55, 0x55, 0x55, 0x55};

unsigned char canCodeMsg1[8] = {0x02, 0x27, 0x03, 0x55, 0x55, 0x55, 0x55, 0x55};
unsigned char canCodeMsg2[8] = {0x06, 0x27, 0x04, 0x08, 0x53, 0x42, 0x78, 0x55};
unsigned char canCodeMsg3[8] = {0x06, 0x2E, 0xF1, 0x99, 0x18, 0x09, 0x08, 0x55};

unsigned char canResponseInit[8] = {0x06, 0x50, 0x03, 0x00, 0x32, 0x01, 0xF4, 0x00};
unsigned char canResponse1[8] = {0x03, 0x6E, 0xF1, 0x99, 0x00, 0x00, 0x00, 0x00};
unsigned char canResponse2[8] = {0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
unsigned char canResponse3[8] = {0x03, 0x6E, 0xF1, 0x98, 0x00, 0x00, 0x00, 0x00};
unsigned char canResponse4[8] = {0x03, 0x7F, 0x2E, 0x78, 0x00, 0x00, 0x00, 0x00};
unsigned char canResponse5[8] = {0x03, 0x6E, 0x09, 0xA1, 0x00, 0x00, 0x00, 0x00};
unsigned char canResponse6[8] = {0x04, 0x62, 0x09, 0xA1, 0x40, 0x00, 0x00, 0x00};
unsigned char canCodeResponse1[8] = {0x03, 0x7F, 0x2E, 0x33, 0x00, 0x00, 0x00, 0x00};
unsigned char canCodeResponse2[8] = {0x06, 0x67, 0x03, 0x08, 0x00, 0x00, 0x00, 0x00};
unsigned char canCodeResponse3[8] = {0x02, 0x67, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00};
void setup()
{
Serial.begin(115200);
pinMode(OnbuttonPin, INPUT);
pinMode(OffbuttonPin, INPUT);
while (CAN_OK != CAN.begin(CAN_500KBPS)) // init can bus : baudrate = 500k
{
// Serial.println("CAN BUS Shield init fail");
// Serial.println(" Init CAN BUS Shield again");
delay(100);
}
// Serial.println("CAN BUS Shield init ok!");
}

void loop()
{
OnButtonState = digitalRead(OnbuttonPin);
OffButtonState = digitalRead(OffbuttonPin);

unsigned char len = 0;
unsigned char buf[8];

if (CAN_MSGAVAIL == CAN.checkReceive()) // check if data coming
{
CAN.readMsgBuf(&len, buf); // read data, len: data length, buf: data buf then see if it matches a message we want to see
unsigned long canId = CAN.getCanId();
msgNumber = 0;
if ((buf[0] == canResponseInit[0]) && (buf[1] == canResponseInit[1]) && (buf[2] == canResponseInit[2]) && (buf[3] == canResponseInit[3]) && (buf[4] == canResponseInit[4]) && (buf[5] == canResponseInit[5]) && (buf[6] == canResponseInit[6]) && (buf[7] == canResponseInit[7]))
{
msgNumber = 99;
}
if ((buf[0] == canResponse1[0]) && (buf[1] == canResponse1[1]) && (buf[2] == canResponse1[2]) && (buf[3] == canResponse1[3]) && (buf[4] == canResponse1[4]) && (buf[5] == canResponse1[5]) && (buf[6] == canResponse1[6]) && (buf[7] == canResponse1[7]))
{
msgNumber = 1;
}
if ((buf[0] == canResponse2[0]) && (buf[1] == canResponse2[1]) && (buf[2] == canResponse2[2]) && (buf[3] == canResponse2[3]) && (buf[4] == canResponse2[4]) && (buf[5] == canResponse2[5]) && (buf[6] == canResponse2[6]) && (buf[7] == canResponse2[7]))
{
msgNumber = 2;
}
if ((buf[0] == canResponse3[0]) && (buf[1] == canResponse3[1]) && (buf[2] == canResponse3[2]) && (buf[3] == canResponse3[3]) && (buf[4] == canResponse3[4]) && (buf[5] == canResponse3[5]) && (buf[6] == canResponse3[6]) && (buf[7] == canResponse3[7]))
{
msgNumber = 3;
}
if ((buf[0] == canResponse4[0]) && (buf[1] == canResponse4[1]) && (buf[2] == canResponse4[2]) && (buf[3] == canResponse4[3]) && (buf[4] == canResponse4[4]) && (buf[5] == canResponse4[5]) && (buf[6] == canResponse4[6]) && (buf[7] == canResponse4[7]))
{
msgNumber = 4;
}
if ((buf[0] == canResponse5[0]) && (buf[1] == canResponse5[1]) && (buf[2] == canResponse5[2]) && (buf[3] == canResponse5[3]) && (buf[4] == canResponse5[4]) && (buf[5] == canResponse5[5]) && (buf[6] == canResponse5[6]) && (buf[7] == canResponse5[7]))
{
msgNumber = 5;
}
if ((buf[0] == canResponse6[0]) && (buf[1] == canResponse6[1]) && (buf[2] == canResponse6[2]) && (buf[3] == canResponse6[3]) && (buf[5] == canResponse6[5]) && (buf[6] == canResponse6[6]) && (buf[7] == canResponse6[7]))
{
msgNumber = 6;
}
if ((buf[0] == canCodeResponse1[0]) && (buf[1] == canCodeResponse1[1]) && (buf[2] == canCodeResponse1[2]) && (buf[3] == canCodeResponse1[3]) && (buf[4] == canCodeResponse1[4]) && (buf[5] == canCodeResponse1[5]) && (buf[6] == canCodeResponse1[6]) && (buf[7] == canCodeResponse1[7]))
{
msgNumber = 11;
}
if ((buf[0] == canCodeResponse2[0]) && (buf[1] == canCodeResponse2[1]) && (buf[2] == canCodeResponse2[2]))
{
msgNumber = 12;
}
if ((buf[0] == canCodeResponse3[0]) && (buf[1] == canCodeResponse3[1]) && (buf[2] == canCodeResponse3[2]) && (buf[3] == canCodeResponse3[3]) && (buf[4] == canCodeResponse3[4]) && (buf[5] == canCodeResponse3[5]) && (buf[6] == canCodeResponse3[6]) && (buf[7] == canCodeResponse3[7]))
{
msgNumber = 13;
}
}
if ((OnButtonState == HIGH) && (SendMessageRequest == 0)) // ALA on button pressed
{
SendMessageRequest = 1;
LastMessageSent = 0;
canMsg4[4] = 0x40; // on value
}
if ((OffButtonState == HIGH) && (SendMessageRequest == 0)) // ALA off button pressed
{
SendMessageRequest = 1;
LastMessageSent = 0;
canMsg4[4] = 0x00; // off value
}
if (SendMessageRequest == 1)
{
if (LastMessageSent == 0)
{
CAN.sendMsgBuf(0x74F, 0, 8, canMsgInit);
LastMessageSent = 99;
}
if ((LastMessageSent == 99) && (msgNumber == 99))
{
CAN.sendMsgBuf(0x74F, 0, 8, canMsg1);
LastMessageSent = 1;
}
if ((LastMessageSent == 1) && (msgNumber == 1))
{
CAN.sendMsgBuf(0x74F, 0, 8, canMsg2);
LastMessageSent = 2;
}
if ((LastMessageSent == 2) && (msgNumber == 2))
{
CAN.sendMsgBuf(0x74F, 0, 8, canMsg3);
LastMessageSent = 3;
}
if ((LastMessageSent == 3) && (msgNumber == 3))
{
CAN.sendMsgBuf(0x74F, 0, 8, canMsg4); ///// on / off actually sent here
LastMessageSent = 4;
}
if ((LastMessageSent == 4) && (msgNumber == 5))
{
CAN.sendMsgBuf(0x74F, 0, 8, canMsg5); // last message, all done
LastMessageSent = 0;
SendMessageRequest = 0;
TimeOut = 0;
delay(5000);
}
/// begin code request response
if ((LastMessageSent == 4) && (msgNumber == 11))
{
CAN.sendMsgBuf(0x74F, 0, 8, canCodeMsg1);
LastMessageSent = 12;
}
if ((LastMessageSent == 12) && (msgNumber == 12))
{
carryOne = 0;
tempMath1 = buf[6] + 135;
if (tempMath1 > 255)
{
tempMath1 = tempMath1 - 256;
carryOne = 1;
}
canCodeMsg2[6] = tempMath1;
if (carryOne == 1)
{
tempMath1 = buf[5] + 79;
}
else
{
tempMath1 = buf[5] + 78;
}
carryOne = 0;
if (tempMath1 > 255)
{
tempMath1 = tempMath1 - 256;
carryOne = 1;
}
canCodeMsg2[5] = tempMath1;
if (carryOne == 1)
{
canCodeMsg2[4] = buf[4] + 1;
}
else
{
canCodeMsg2[4] = buf[4];
}
canCodeMsg2[3] = buf[3];
CAN.sendMsgBuf(0x74F, 0, 8, canCodeMsg2);
LastMessageSent = 13;
}
if ((LastMessageSent == 13) && (msgNumber == 13))
{
CAN.sendMsgBuf(0x74F, 0, 8, canCodeMsg3);
LastMessageSent = 14;
}
if ((LastMessageSent == 14) && (msgNumber == 1))
{
CAN.sendMsgBuf(0x74F, 0, 8, canMsg2); // back to normal sequence #2
LastMessageSent = 2;
}
TimeOut = TimeOut + 1; // in case the send response handshake hangs up
if (TimeOut > 30000)
{
LastMessageSent = 0;
SendMessageRequest = 0;
TimeOut = 0;
}

}
}

Last edited by Trade_it_all_4_more; 09-09-2018 at 05:02 PM.
Old 09-09-2018, 04:51 PM
  #6  
AudiWorld Member
Thread Starter
 
Trade_it_all_4_more's Avatar
 
Join Date: Mar 2018
Location: NW Indiana / Chicagoland
Posts: 439
Likes: 0
Received 90 Likes on 53 Posts
Default

I have not finished the final implementation as to where I will put the button, wiring the Arduino into the accessory circuit, etc. yet. I just had a couple of hours to mess with it yesterday, and was happy it’s all good to go. I’m hoping to see some responses with some nice options on buttons (i.e. put something on the dash next near the auto-start stop button, maybe somewhere else creative?)

Once this is up and running full time in my vehicle, the next step is to find out the auto-start stop can-bus toggle command, and add an initialization ode that sends the OFF command after the vehicle is started. Lots of other fun possible projects too – hoping other posters will explore some possibilities.

Enjoy… Jason
Old 09-09-2018, 05:07 PM
  #7  
Permanent S Mode Member
 
MH62's Avatar
 
Join Date: Jul 2017
Location: Southern California
Posts: 1,819
Received 573 Likes on 376 Posts
Default

Well done. An auto selection of S mode once D mode is first selected may be popular with many. You might just have given me a project although I don't even have my car yet, LOL.
Old 09-09-2018, 05:12 PM
  #8  
AudiWorld Member
Thread Starter
 
Trade_it_all_4_more's Avatar
 
Join Date: Mar 2018
Location: NW Indiana / Chicagoland
Posts: 439
Likes: 0
Received 90 Likes on 53 Posts
Default

Originally Posted by MH62
Well done. An auto selection of S mode once D mode is first selected may be popular with many. You might just have given a project although I don't even have my car yet, LOL.
I have thought of that one as well and my 1st though was great - the car will take off and go once I send the command. Ha. Since you have to be in D to go to S, don't know if that's a requirement for the can-bus command, or if it will work otherwise. It's on my list, but sniffing the other can-bus items will be much more difficult as you have to tap into the actual bus that is on. (The ODB diagnostic bus doesn't repeat what the other busses are communicating.) Once your on a bus, such as the drivetrain bus, there will be tons of non-stop comms going on making it difficult to find what you are looking for.
Old 09-11-2018, 09:02 PM
  #9  
AudiWorld Senior Member
 
caranddriver's Avatar
 
Join Date: Feb 2018
Location: USA
Posts: 661
Received 59 Likes on 44 Posts
Default

Did not know you could turn it on/off while the car was in motion. I only turn it on for long freeway trips out of the Bay Area.
Old 09-16-2018, 08:58 PM
  #10  
AudiWorld Member
Thread Starter
 
Trade_it_all_4_more's Avatar
 
Join Date: Mar 2018
Location: NW Indiana / Chicagoland
Posts: 439
Likes: 0
Received 90 Likes on 53 Posts
Default

Got around to putting in the button today. I wanted an OEM look, an came across a used 'button console' on ebay for dirt cheap.



This gave me the opportunity to do some playing without breaking anything on the car. Also gave me the parts needed to complete the mod. The goal was to laser engrave one of these button with the ALA logo, and have it go back directly to the Arduino input and toggle the ALA via can bus. Everything turned out really well - the unit comes apart very easily, and I was able to steal a button from the used unit. Therefore, the ALA button looks, feels and operates just like the other buttons.



Finished product:

The following 2 users liked this post by Trade_it_all_4_more:
black.cat (06-24-2019), Shayne Wu (06-21-2019)


Quick Reply: Active Lane Assist On/Off solution for non DAP cars



All times are GMT -8. The time now is 02:48 PM.