WEBVTT

00:00.000 --> 00:09.280
All right, everyone, I recommend to this presentation about all the reverse engineer your

00:09.280 --> 00:15.880
canvas and build an ECU with using elixir, I'm Tibo Poncele in a software engineer, and together

00:15.880 --> 00:20.400
with two colleagues, we have built a spin for Tico, which is an IT and a constituency

00:20.400 --> 00:28.400
and product company, and for about seven years we've built an open banking regulator using

00:28.400 --> 00:33.800
elixir, and after so much time in finance, we wanted to explore new opportunities and

00:33.800 --> 00:39.240
see how far we could go with elixir, and if you could be a good fit for the automotive

00:39.240 --> 00:47.520
use case, so in 2024 we took a sabbatical and we've built the open vehicle control system,

00:47.520 --> 00:53.840
which is an elixir-based decade, allowing you to upgrade any vehicle, and by upgrade

00:53.840 --> 00:59.480
we mean converting it to an EV, swapping the engine, creating a new influence on the

00:59.480 --> 01:04.240
maintenance system, and hopefully at some point we hope to allow you to transform your

01:04.240 --> 01:13.160
vehicle into an autonomous one. So in our case we use the two or seven diesel Polo, and the

01:13.160 --> 01:21.320
first thing we did was to convert it into an EV by putting Nissan Leaf electric motor in

01:21.320 --> 01:25.880
it. I won't go into the details of the mechanical work, and there is a lot to say there,

01:25.880 --> 01:31.680
but that's not the topic of the day, and today to show you how to do the reversing engineering

01:31.680 --> 01:38.600
in practice, we will just focus on a very simple use case, which is how to make the VW

01:38.600 --> 01:45.720
dashboard display the RPM value from the Leaf motor, so that's one of the things you need

01:45.720 --> 01:54.440
to do if you want to have a seamless integration between parts from different manufacturers.

01:54.440 --> 01:59.800
So you may know it or not, but in all of your cars you have a canvas, so that's a controller

01:59.800 --> 02:08.040
RR network, and that's basically a twisted pair of copper to on which of the components

02:08.040 --> 02:13.920
of your car are connected and are sending frames, and that's a standard protocol used in

02:13.920 --> 02:19.960
automotive, but also in planes, trains, even for used-car machines, and the good thing is that

02:19.960 --> 02:26.800
you have built-in support in the New York Journal using Hipsocket can, and then the way to

02:26.800 --> 02:33.600
send frames on that boost is standard, but the content of the data, the values that are

02:33.600 --> 02:41.440
sent are not at all, and of course, care manufacturers are not providing any kind of documentation.

02:41.440 --> 02:48.440
So this is what can be frames are looking like, what it looks like, so you have here a list

02:48.440 --> 02:53.800
of frames that are exchanged on the boost of the Polo, you have a list of frames that

02:53.800 --> 02:58.880
are IDs, the frequency at which they are emitted, so it's broadcasted and all the components

02:58.880 --> 03:05.520
can receive all the frames, and then you have the whole bytes that you have to make sense

03:05.520 --> 03:09.920
of, and so when the color of it changing means that something happens, so if you put the

03:10.000 --> 03:15.360
end break, you will have some bits changing somewhere, and you have to find which frame

03:15.360 --> 03:23.360
is linked to what and which value is what, so yeah, the main IDs that you have these frames

03:23.360 --> 03:32.080
emitted periodically on the boost, then the tools that we used, first you need to physically

03:32.080 --> 03:43.040
connect to that boost, so we use the device, which we could put the laptop, and then the

03:43.040 --> 03:47.040
screen you've seen before is from Savica and that's an open source GUI that allows you to

03:47.040 --> 03:55.120
display the values and also replay frames and so on, and then one tool that is a bit less

03:55.120 --> 03:59.760
known, it's a kit can deal, that's the demand that allows you to stream a kit with the IP,

04:00.640 --> 04:04.240
and that's quite useful because then if you put a Raspberry Pi and in this in your care,

04:04.240 --> 04:09.120
you can work from your desk on your laptop, and you can send and receive frames in three

04:09.120 --> 04:18.880
times, so that you can have a smaller cycles. All right, so first thing we need to do is to be able

04:18.880 --> 04:27.760
to receive that FPM value, so the rotation terminates from the leaf motor, and we chose the leaf

04:28.400 --> 04:32.880
the leaf motor because you have kind of a large community of thinkers that already reverse

04:32.880 --> 04:39.760
engineer, actually, the frames are underneath and leave, so we could find some DPC-5 on the internet,

04:39.760 --> 04:46.960
so the DPC-5, it's a frames specification, and in one of these files, but while bossing it,

04:46.960 --> 04:56.480
we could find the inverter status frame in which you have that two by 15 bits of output

04:56.480 --> 05:02.000
revolution, which is supposed to be a big identity, I'm going to call it an design integer,

05:03.280 --> 05:09.120
and then yeah, to validate this because that's a community source, we just connected to the

05:09.120 --> 05:14.960
engine, to the motor, make it run, and then actually it seems to be the two full bytes,

05:14.960 --> 05:21.120
so the 16 bits, it's big identity, but it's a design integer because the motor can go both ways,

05:21.120 --> 05:27.840
so it can go backward too, so that was easy, no, that much of reverse engineering,

05:29.680 --> 05:34.240
so we can hit it, we also have to be able to send the value to the Poro dashboard,

05:35.520 --> 05:42.480
and in that case, we made kind of a big mistake, because when we got the care, we jumped ahead,

05:42.480 --> 05:47.520
removed the engine, and all the parts we didn't hit it, and then we started thinking about,

05:47.600 --> 05:55.600
okay, but how do we reverse engineer that now? So if you want to do this, before doing anything,

05:55.600 --> 06:02.640
just go for a drive, you recurled the word can, so that you have an example of all the frames,

06:03.920 --> 06:13.200
anyway, so there is not such a big community about the VWPoro, but still we could find

06:13.200 --> 06:21.360
someone else that did some research on another Volkswagen of the same generation, so it seems that

06:21.360 --> 06:31.200
the frame 280 has the RPM value in the second and third bytes in little Indians, it's shifting

06:31.200 --> 06:39.600
the bytes, so using that hint, what we did to validate it is that we used the frame center interface

06:39.680 --> 06:45.920
of silicon, where you can define a frame that you want to send, which data at which frequency,

06:48.320 --> 06:53.680
it turns out that the dashboard of the Poro is also validating the frequency at which it's emitted,

06:53.680 --> 07:00.960
so we have to try a few values for this, and after a few tries, we had that needed moving,

07:01.040 --> 07:11.520
so that was already quite a success, but actually on a canvas, you often don't send the value as

07:11.520 --> 07:20.160
is, it's most of the time it scales and sometimes offset it, so you need to reverse engineer that

07:20.160 --> 07:28.080
scale value, again the usual way for that kind of value is to drive the car, you recur the

07:28.080 --> 07:33.200
picture of the dashboard, and then you match the timestamp of the canvas that you have recorded as

07:33.200 --> 07:41.920
well, and then you try to match them, in this case it was not possible again, but actually that was

07:41.920 --> 07:49.280
even simpler, because since we could control the value that was emitted, then we just have to

07:49.280 --> 07:55.280
read the approximate value displayed by the leader, and you put that in a spreadsheet, and then

07:55.280 --> 08:01.360
it's quite easy to guess the scale value, and once you have the two curves that matches, you know,

08:01.360 --> 08:08.000
that you have the right scale, so yeah, it's a bit tedious, but actually you don't have any encryption,

08:08.000 --> 08:13.440
you don't have any anti-reversion engineering methods, so it's just about finding the right bits,

08:14.160 --> 08:21.840
and then how to interact with them. All right, so though we know how to read the value, we know how to send it,

08:22.400 --> 08:28.560
it's we are missing something in between that will do the conversion, so that's the ECU,

08:28.560 --> 08:35.520
we are building today, so the vehicle management system, and we put this in between the two

08:35.520 --> 08:43.200
basis, we don't mix the components from the leaf and from the pull on the same physical canvas,

08:44.080 --> 08:50.160
because you could have the same ID used by the two manufacturers for different use cases, so we

08:50.160 --> 08:58.080
could keep this super segregated, and then we will be with some codes in LXI that we do this

08:58.080 --> 09:06.480
translation and proxy the value in between. What let's do this, why LXI were felt because we liked it,

09:06.480 --> 09:12.800
and also if you may know it, but that's a functional language running on the beam, which is the

09:13.360 --> 09:20.080
machine, and that the machine has been designed by a song a long time ago, to build

09:20.080 --> 09:26.240
Tiffany's features, and so that's designed to build some real-time applications, and it's also,

09:26.240 --> 09:33.280
the can use cases quite close to that the telephone use case, because you receive bytes,

09:33.280 --> 09:40.400
you have to handle them and then just allow them to somewhere else, so you can see that the language

09:40.480 --> 09:46.880
is really fitting, the truth is pretty well, and the pattern matching feature that they have built

09:46.880 --> 09:53.600
is really nice to pass the frames and extract data in a maintainable and reliable way.

09:55.200 --> 10:04.720
concretely, that's all the lines you need to connect to a canvas, and sorry, and receive one frame,

10:04.800 --> 10:11.200
so you have the first few lines that are about connecting to the to the sockets and binding it,

10:11.200 --> 10:16.320
and then you have that sockets receiver function that will block until a frame comes in on the bus,

10:17.440 --> 10:25.280
and then from 9-8 to 13 you have that pattern matching where we assign to the ID variable

10:25.280 --> 10:33.440
the first 16 bits as an integer encoding in LXI, we skip to bits, we extract the number of bytes in the

10:33.440 --> 10:40.960
data, skip three bits again, and then we extract the whole data based on that number, we just form,

10:42.080 --> 10:50.720
and then if the ID matches, we will extract the RPM value as that begin the unsigned integer

10:52.560 --> 10:58.320
and then just show it from the console, so it's quite concise, it's quite feasible, like according to me,

10:58.720 --> 11:04.240
it's quite different to what we would see in some other languages, if you already did that,

11:05.520 --> 11:13.200
you could feel that it's a good patch. Still, when you have to receive and send a lot of

11:14.640 --> 11:20.240
frames, it can be a bit tedious to do everything manually, so while we were building the open vehicle

11:20.240 --> 11:26.720
control system, we also extract it, an open subscribery, that we just focus on providing

11:27.200 --> 11:34.640
an easy interface to emit and receive frames, so basically you will define a YML file in which

11:34.640 --> 11:39.120
you define all your canvases and all the frames and the signals to the values in it,

11:40.080 --> 11:44.800
and a contestic will make sure it converts with the right scale of settings on for you,

11:44.800 --> 11:50.880
you don't have to think about it, and you could also then spawn one process, so in the

11:50.880 --> 11:57.040
Excel that's a gen server, per network to have a receiving loop and then it will dispatch the frame

11:57.040 --> 12:03.600
to all the all the processes that you that's supplied to it, and finally you will have one

12:03.600 --> 12:11.600
emitter process, per emitter frame, and it will take care of emitting it, so you add the right

12:12.640 --> 12:20.160
frequency and do the conversion of the values, all right, so let's build this using

12:20.160 --> 12:28.320
contestic then, so on the on the left you have the YML file with that leaf driver can network,

12:28.960 --> 12:34.480
and then we have received frames of the investor status one that we found on the DBC file,

12:35.200 --> 12:41.760
and we defined that rotation terminates as a big Indian integer, and then on the right you have

12:41.760 --> 12:49.040
all simple business logic code that is primitive also as a gen server, so we spawn a process,

12:49.520 --> 12:55.760
when it starts it will subscribe to the inverteus investor status frame, and then contestic

12:56.560 --> 13:04.080
will send, will send a message to the that process every time the frame is received,

13:04.080 --> 13:09.920
we extract the RPM value, and then the only thing we have to do is send it to the dashboard process,

13:10.240 --> 13:18.240
on the dashboard side we define just one emitted frame, so the engine status one,

13:18.880 --> 13:25.680
we apply the scale that we reverse engineer, so we don't have to take take think about it on the

13:25.680 --> 13:31.680
in the business logic, and here we will just configure the emitter so that it starts emitting immediately

13:31.760 --> 13:41.520
with RPM of 0, and we implement that set rotation per minute function that we just update the emitter

13:41.520 --> 13:47.680
with the new value, of course, VW didn't expect it to be as an engine to run backward,

13:47.680 --> 13:55.840
so we use the absolute function call to only send positive values, and the good thing is that

13:55.920 --> 14:02.320
this call is recalled every 10 milliseconds, because that's the frequency of the live frame,

14:02.320 --> 14:08.400
but the emitter will only send it every one of that milliseconds as expected by the dashboard.

14:12.000 --> 14:18.240
Okay, so now we have the application code, and let's build a real ECU, so an electric

14:18.800 --> 14:26.160
controls unit, so that's the concrete component that we put in the car, and for that we use

14:26.160 --> 14:34.480
a Raspberry Pi with a few Canvas modules, and we are packaging this using now, so now this

14:35.200 --> 14:41.040
an electric platform that we will use build roads to create a very minimal Linux, on which

14:41.200 --> 14:51.600
that we immediately boot on a link, and if we also use FW app to update over the RUSB directly

14:51.600 --> 15:02.480
on the SDK, that's a really nice project too, and yeah, so we package this, we put that in the

15:02.480 --> 15:18.080
car, connect it, and it works, we now have a, thank you, so yeah, we now have that needle moving

15:18.080 --> 15:26.000
at the right, to the right value, when the the leaf motor is running, of course that was just

15:26.000 --> 15:32.560
one little example, and we had to reverse engineer the speed, the handbrake, the throttle pedal,

15:32.560 --> 15:37.120
everything to have a running car, that's not the topic of today, but at least you have the

15:37.120 --> 15:42.880
AIG, again it's not that complicated, and when you start working on this you start

15:42.880 --> 15:51.280
worrying about the security of your car, you can see that it was not designed when the car was

15:51.280 --> 15:59.680
connected to the internet, so maybe things could be, could be improved anyway, and so that's it,

16:00.400 --> 16:06.240
if you want to know more about about to be seen itself, my two colleagues are also presenting

16:06.240 --> 16:11.280
to more afternoon, so don't hesitate to join them, any questions?

16:11.600 --> 16:26.720
Yeah, first of all, great talk, thank you. So when I'm teaching Alexa to people, one of

16:26.720 --> 16:31.680
distinction or one example I usually use of soft real-time versus hard real-time is that you would

16:31.680 --> 16:39.280
not want to use Alexa for say example driving a car, so I'm really curious about how you're

16:39.360 --> 16:44.080
approaching this, and what sort of things you're actually using OVCS for in practice?

16:45.280 --> 16:52.160
Yes, so it's not meant for a vehicle that would go up on an open road, it's not yet certified,

16:53.280 --> 17:00.880
it's open-source, but try it at your own pace, and then we have some parts today running on

17:00.880 --> 17:05.760
our windows, we didn't see, like you really need to control the brakes or things like that,

17:05.840 --> 17:13.680
might be a better idea indeed, but actually for most of the cases you already, you anyway have delays,

17:13.680 --> 17:19.120
you have a horse on the roof, so for none, you have a lot of non-critical

17:20.320 --> 17:26.400
features on your car, but actually the soft real-time part is good enough for what's in it.

17:27.120 --> 17:34.320
And then yeah in practice we still have issues to work on, that's true, but we really wanted to see

17:34.320 --> 17:42.480
how far we could go with that in Excel, it's like, you said a process permitted frame,

17:42.480 --> 17:46.960
do you mean permitted frame type of every single frame is a new process, is that that works?

17:46.960 --> 17:52.640
Yeah, so you have the inverter status frame, that is immediately with 10 milliseconds,

17:52.640 --> 18:00.720
so you have one process for that, but in Elixir, the processes are really cheap, so you could

18:01.280 --> 18:06.400
have dozens of even millions of process without any issues, it's really lighter than the

18:06.400 --> 18:15.440
kernel process. Yeah, just a quick question about reverse engineering, the cam protocol,

18:16.000 --> 18:23.840
easier some kind of community driven effort to have, I'd say, most build-in model,

18:24.800 --> 18:29.360
and that a base of knowledge base of all these protocols and all these things,

18:29.360 --> 18:33.520
like I did some kind of the fact that one might be in the blue car, because I had to fix

18:33.520 --> 18:40.640
an apartment system, but it's only on my blog, it's not somewhere in the, it might be interesting to

18:40.640 --> 18:44.960
also have as a side project, these kind of knowledge base, because you might have come here.

18:44.960 --> 18:50.160
Yeah, so you have some communities on specific cars, like the Nissan Leaf, you have

18:50.160 --> 18:56.400
on tire firms, about it, you also have come out of the AI that is providing an open-dBC

18:57.360 --> 19:03.840
GitHub repository, where they are trying to aggregate this, this gives us engineering,

19:03.840 --> 19:08.080
so yeah, it exists, but not for all cars, not for all generations.

19:09.440 --> 19:15.680
A few besides reverse engineering, the canvas, that you also consider replacing the RPM

19:15.760 --> 19:19.280
reader on the dashboard, for one that's compatible with the...

19:19.280 --> 19:23.920
Yeah, so that's the usual way, when you convert to an EV, when you do retrofitting,

19:23.920 --> 19:29.680
most of the time people are just putting a new screen and it works, it's easy,

19:30.240 --> 19:35.360
but then it doesn't feel as simple as it could, so in this case we really

19:35.360 --> 19:40.320
reverse engineer the ignition block as well, so that it starts the electric engine and so on.

19:41.200 --> 19:47.280
So yeah, it's... yeah, I'll test, I would say. But it's really nice to see the old dashboard

19:47.280 --> 19:53.600
displaying the new value. Also, we didn't do it, but the goal is to display the battery

19:53.600 --> 20:02.960
a level with the tank. So you mentioned during the talk and a few moments ago that you've

20:02.960 --> 20:08.560
got all these communities, all these DBC files for different cars and things, and then you're loading

20:08.640 --> 20:13.040
all these descriptions in the ammo. So you're wondering, is there a converter

20:13.040 --> 20:18.240
why you're not just using the provided DBC? I could show you an example, but the DBC file,

20:18.240 --> 20:24.960
it's a property format, and it's really ugly. But it's the default format, so I couldn't...

20:26.240 --> 20:31.440
Yeah, it was a sabbatical year where we did... we did some fun things, and I could...

20:32.640 --> 20:38.320
push myself in implementing this. But the idea would be to have a conversion tool to go from

20:38.320 --> 20:46.880
the ammo to the... because here it's easy for anybody to hear, and in the DBC file it's like

20:46.880 --> 20:55.920
impossible without GUI, that's really ugly too. But I GUI, that could be a good idea.

20:57.440 --> 20:58.880
We should support those, probably.

20:59.840 --> 21:08.640
Yeah, thanks for the talk. Do you know if we're obitly too connected or also expose this,

21:08.640 --> 21:16.240
we can come on so that you can reverse and linear it without going to the motor and getting

21:16.240 --> 21:24.480
your kin through this from where? So the problem on the obitly, that's the socket you have in all

21:24.480 --> 21:30.880
cars to do the diagnostic. It exposes some things in a standard format, but you don't have access

21:30.880 --> 21:36.800
to all the values. So it's just like the speed, the RPM, so you would probably have, but it's

21:36.800 --> 21:42.480
probably not at the same frequency, but you won't have access like to the endbreak by state,

21:42.480 --> 21:47.760
or the door state, or things like that. So if you want to go as far as possible,

21:48.480 --> 21:59.440
you need to reverse the property frames. Do you want to say that the canvas lines

21:59.440 --> 22:04.480
from the connector are different from the other? Yes, so there's a proxy or something.

22:04.480 --> 22:09.920
Yeah, there is in most of this, so it depends. Like in the leaf, they expose in DODB to

22:10.720 --> 22:17.120
two lines for the internal one and also for the standard one. But on the VW, you just have a filter

22:18.000 --> 22:21.440
version of the other kind.

22:30.560 --> 22:37.680
Yes, one more question. Is there any way to use the XR code and run it on like the speed of it

22:37.680 --> 22:44.000
you or we might call controller a platform instead of full-flage Linux board?

22:44.960 --> 22:51.600
There are some projects, but yeah, to run the beam, you normally need a line XR.

22:52.640 --> 22:58.240
But I think there are some both that were designed to run a line on the metallic self,

22:59.120 --> 23:03.360
but we didn't try it. We also tried to use the cheapest

23:03.360 --> 23:08.000
both and easiest available, so we are using a very price in our windows.

23:08.000 --> 23:12.160
But if you want to go further with that, you should definitely use something else.

23:12.480 --> 23:15.840
It's called XMVM? Yeah, thank you.

23:15.840 --> 23:20.160
Does the open vehicle control platform support automotive Ethernet and

23:20.160 --> 23:23.680
encrypted frames and these kinds of things? Sorry.

23:23.680 --> 23:28.880
The open vehicle control platform supports automotive Ethernet and encrypted frames?

23:29.680 --> 23:33.600
We're not yet. It could easily be added, but

23:33.680 --> 23:46.960
if we don't have one aspect. Just to follow up on what the person was asking here.

23:46.960 --> 23:57.120
What kind of wrong footprint does your beam elixir have? How much space does it occupy?

23:58.080 --> 24:01.520
All the binders and the interpreters and everything with the virtual machine?

24:02.800 --> 24:08.000
Very, very, also what kind of memory requirement does it have?

24:09.040 --> 24:14.560
I don't think it's expensive, but it's really small, and the footprint is really a few megabytes.

24:15.680 --> 24:22.240
What about RAM? A few megabytes too, but on this pair, I should have, which should try.

24:22.640 --> 24:25.360
I don't know. I don't know. I don't know. I don't know how to prepare you.

24:27.680 --> 24:32.240
It's interesting to have an embedded solution,

24:32.240 --> 24:37.440
eliminating memory fragmentation, which can be difficult, because I assume this language is

24:37.440 --> 24:40.800
data-quare, you know, heap, and use heap extensively.

24:42.640 --> 24:49.360
Yeah, it's, you need an OS, and so on, so it's not, okay. Thank you.

