CAN Bus is Simple and Actually Really Cool | Explained by Ken Tindell

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
In this video, we are going to talk about CAN bus, because it's like super popular, it's used in many devices, and it's not as simple as I2C. CAN is differential, that's I think what everyone knows, but what also makes difference is like some kind of higher level of like protocols or something. Yes, so well, first of all, it's a lot longer than I2C. CAN bus, you can run 100 meters of CAN bus quite straightforwardly. And the other thing it is, it is multi it's a multi-master bus, multi-drop. So it's a broadcast bus and multiple different nodes can be wanting to transmit at the same time. So there is a frame format for working out who shall go first onto the bus. So as you know from Ethernet type protocols, is everyone has a go and then you will collide at the same time and everything goes wrong and you all back off with a randomized thing. And when the bus is very highly loaded, the whole real-time performance collapses. So CAN was designed so that there would be a proper prioritization of the most urgent things will go first and the least urgent things will go last. So at the beginning of every CAN frame, there's an identifier which indicates what's in the frame to the application, but it also indicates the priority, so that CAN ID 0 is the highest priority CAN frame. And then the ID can be either 11 or 29 bits long, surface 29, that's several billion CAN identifier priority levels. And then the rest of the data frame follows, CRC check to make sure there's been no noise and then the next frame can begin so basically, the CAN controller on each node runs out the protocol and just basically works out, collectively they work out who goes first and who goes next and who goes next and the system is arbitrated by that. Does it mean, is it like hard to work with CAN? How do you do software for CAN? Because it looks like, you know, it's not as simple as I2C. Actually, it can be. It's very, very simple. If you don't need this any kind of high-level protocols, if you've got some data to send, you put it into a CAN frame in the CAN controller memory map, and there are registers you fill in the data and you fill in the identifier, and then you say go. And then that frame will be entered into the arbitration rounds that begin on the bus, and it will go out when it's the highest priority frame. It's pretty straightforward. Can we have a look? You have example. Alright. Right, so I have a very simple system I made. They made the easiest way of getting started with CAN. If you want to write embedded software within C and you have to write drivers and stuff, I've published some drivers for some of the popular CAN hardware and you can try it out, but the easiest way to try it out is with these little CAN Pico boards. And I can show you. There's a couple here running. Okay, so these are two CAN Pico boards and what they are is a Raspberry Pi Pico, which, of course, is available everywhere. And then there's like a subboard on there which puts the CAN hardware on. So here we have the subboard and the the Pico is wired down. This is the wireless Pico and then this one is a non-wireless older version. And here is the CAN controller chip. And here is the CAN transceiver chip. So the CAN controller is a chip from Microchip, that's the MCP251. Can we find these boards and components on the internet? We can go through. So here's the CAN Pico board. And there's a video introduction to it there. But you can see on this here, here is the Pico that's soldered down onto the board and then this is the Microchip CAN controller that will actually do a more advanced version of CAN also called CAN FD. And then this is the CAN transceiver. So this talks SPI to to the CAN controller, and you push frames in through a register map, and you just write to the data, and then you say go. And this takes care of all the hardware buffering, so you can put quite a few frames into here at the same time. And then this runs the arbitration process, and it talks to the CAN transceiver with the TX and RX pins. TX is the transmit pin, and then a CAN transceiver converts that into CAN high, CAN low voltages. Differential pairs. On differential voltages. So here we've got a little screw terminal block here, and they also come out on these headers, so you can put oscilloscopes on if you want to trace something. And then these boards also have a couple of jumpers, and one of them is the termination resistor. So that's the 120 ohms at each end. So I have a couple of questions. Can you buy this baseboard or this carrier board? Ah, yes. Ah, you designed this carrier board. Yes, and you can get it at SKPank. Okay. There we go. Okay. Yeah, so that's easy. And then there's [inaudible]. I have more questions. Okay. So, about the termination, you already mentioned termination. So, CAN bus need to use termination, how do we use it? Okay, so you need to put a resistor over the end of each CAN bus, 120 ohm, and you should use CAN cable that's 120 ohm characteristic impedance cable. So if you use Ethernet CAT5 cable, people do that, and because CAN is tolerant to a lot of things going wrong, that generally works, but you shouldn't do that if you're in a critical application that has to tolerate all the different temperature ranges and so on. So the specifications for CAN is a 120-ohm cabling. This is the CAN cable, so this is an automotive CAN cable. So it's twisted pair. And normally, red, the convention is that a red stripe on the cable is CAN high and low and you can see it comes in here into the screw terminals. And so this is characteristically 120-ohm cable and you want to do that if you're doing a proper install on a system that's got to run over different temperature ranges. If you're playing on the desktop, you can just use a piece of ribbon cable. It doesn't really matter, but it does start to matter when the when the CAN cable is very long, because that's when you start to get these reflections back and forward that make a big difference to how the signal will go. And if you have more than two boards, you need to place termination resistor only at the beginning and the end, or how? And only at the end. Now, if you're going to have like a T piece or a stub cable that's coming out, then there are guidelines on they should be very short non-terminated ones, they should be very short. If you have very long stubs, then you start to need much more attention paid to exactly how you do the termination. So basically, ideally you would like to place all the boards kind of on one wire? Exactly. Yes, that's the ideal. And obviously, physically, sometimes that isn't possible so sometimes it's very short, so if it's kept to like a meter or so, unterminated, then the reflections won't be too bad off of that. It can be very tolerant to to signal errors. So what is the other jumper on your board? So I see the yellow one is termination, the blue one is? So that one is very simple, so that actually takes away the TX pin. Why we would like to? And that's if you are, if you have a system that's a critical bus, very, very important, a CAN bus, so for example, CAN is using all kinds of things, even spaceships, there's even one on Mars at the moment. People use them in things like cranes and equipment like that. And if you are sitting with some sort of Wi-Fi system on the bus, and you're just listening to sensor values to do some diagnostics and upload that to the internet. But somebody breaks in over the internet into your board, you don't want them to be able to transmit onto the CAN bus so you can pull this jumper out. They're physically isolated from sending anything to the CAN bus. So it's like a security interlock there, we wanted to put that in because people have put Wi-Fi access points that connect onto CAN and people have been able to break through over Wi-Fi into real systems and... Okay, what else is special on your board? So, that's pretty much it, it's not particularly special, it's a CAN controller, CAN transceiver and some connectors, and then some nice debug headers. That's what we see in the camera, so you have probes connected to this header. Yes, exactly. And then you have you have what? Logic analyzer? I have a logic analyzer, in fact it's a Saleae logic analyzer, that's a little analogue for the CAN high-low and digital for the TX RX, so you can see. So, in this video, when you will be sending something between the boards, we can actually also see the specific signals. Yes, so if you'd like to see that working, I can show you that. Yeah, we will move there. So, my next question is, how do you talk to this controller? You say you are using SPI bus, but you need some kind of driver or... Exactly. So they're fairly straightforward to do something very simple with CAN, so if you want to send a CAN frame, if you're building your own application and everything is on the bus, you can just simply define, I want to... CAN uses a communications paradigm called publish-subscribe, so you publish a sensor value, for example, and then all the other devices that need to subscribe to that, receive the, choose to receive the frame and then process the data. I'm curious how it is done. But did you write the driver or can anyone write the driver? Yeah, anyone can write the driver. Because, you know, if someone has their own systems, how they can use CAN? Yeah, it's very simple. Yeah, the datasheet is quite straightforward. It's no more difficult than writing an SPI driver, for example. There's a frame format and you choose the identifiers you want and you choose how the data is going to be put into the CAN frames, up to 8 bytes per frame and you write into a register for where the ID is and you write it into a register for the data and then you write to another register to say it's now ready to go. Do we have some examples? Yeah. Do you have example of this controller, for example? What kind of registers are there? Oh, yes, I have. And you can enable your camera again. Yep. [inaudible]. Yes, so if you go to this GitHub repository, a CAN API, and I've written some drivers and all the source codes available, all open source. So there's some very simple Hello world here where you print a frame out and have an interrupt handler for when a frame comes in. And yeah, if you just want to send a frame, it's really, really simple, you can just send a CAN frame to the controller you want with the frame that's been filled in with the ID and payload and it goes. And yeah, if you want a receiver. It looks short, but can we also open datasheet of the chip? Yes, I guess so. You can leave this open, maybe we will need this later. You can just open next tab. Yeah. I'll do it from microchip. Okay. Yep. That's the datasheet. There we go. It's a very simple. So what is inside? What kind of registers are inside? Yeah, so it's a very simple package. And you can see it's got about 2 kilobytes of buffer space inside the message memory. And yeah, SPI writing. There's a register format. There's an SPI format that says you send the address, and then you send 4 bytes for the register values. It's kind of a 32-bit model and you can see. This is the chip's internal memory and there's the 2 kilobytes of buffer space. And then these are the register maps. Bit of complication to set it up at the beginning, because you have to set up, you have to tell it what bitrate you want and that means you have to set clock dividers and so on. Okay, so let's have a look on the signal, I'm curious. And then maybe we can go back to these registers, but first I would like to see how these signal physically looks. Yep okay so I will share. So we can talk about something physical. Yeah so I will share if you want the logic analyzer. In fact, here is a signal I captured earlier. I'll capture again if you want. So here's CAN high-low, this is the differential signal. It floats without the transceivers being actively driven. It floats to about 2,5 volts on on the high and low, so the differential is very small. And then when he wants to signal what's called a dominant bit, you drive the bus CAN high is driven high and CAN low is driven low. So the transceiver takes care of driving that from it, so you have a logic in of the zero, and that will cause these two lines to be pulled apart. And then when you go back to recessive, basically it lets it float back to these 2,5 volt points there. Why RX and TX are exactly the same? Okay, so... Oh, they are not exactly the same, the last one... Not exactly the same. Yeah. So what happens is, RX is pulled in off the bus based on these differential signals. So when you are transmitting, and so here I've got the digital. So the analogue is measured off of one end of the bus, but the digital is off the other device. So it transmits. This is the frame it's trying to transmit. In fact, it's an empty frame with no bytes, just like that [inaudible]. So it drives the signal on the bus here and then the RX is what the bus is actually signaling. So when CAN is transmitting, it sends a thing out and it loops back to check that what it's sending is also what it's receiving. Now, the dominant state means that any device can pull these CAN high-low apart and effectively drive the bus to logic zero. So you see this is logic zero, so this here is called starter frame. So when everyone is synchronized up, they all assert all the devices that want to talk, pull the bus apart to send a zero bit for starter frame. Then that begins arbitration. So it sends out the data of the the frame that the controller wants to send on the bus. And then by the end, I'll come back to this in a minute, but by the end it's finished, so it then goes on to do the data, which there isn't in this one, the CRC. And now, CAN has a thing called acknowledgement, so the transmit line here is sending a resettive bit for this acknowledgement field, but it expects all receivers that are online to drive that to zero, to a logic zero. So, when someone is sending out a message, it is expecting that it will receive acknowledgement from the from the device where the message was sent? In fact, from all the devices that are online and received it correctly, they will all drive that. So, they'll all be driving their transceivers now to drive CAN high and low to this. Oh, even if the message was not like addressed to this... No, there's no addressing with CAN on the protocol level. No addressing at all. It's just sent, it's published, and then it's up to the receiver to decide if they want it or not. Oh, so in this physical layer there is no like, there are no like bit for address, bits for something, bits for... It's just data, basically poor data and then you have to... The identifier and then the data and then the CRC. Okay. So, what the identifier is exactly used for? So, the identifier is used to identify the frame. So what it says is, so the identifier picked 700 here, so on the 11 bit, there are two types of CAN frame, a short identifier and a long identifier. The short identifier ones are 11 bits, and it was designed so that an automotive controller would say, this is the wheel speeds of the car. And then any ECU that wants to know what the wheel speeds are doing picks up that CAN frame and reads the data out. So there is some kind of standard for these identifiers? Yes and no. It's like Bluetooth, [inaudible] ZigBee. It's like ZigBee. So, different, so, in car companies don't define a standard. They have their own internal database, if you like, what identifiers mean and what the the fields mean. There are some standards for defining how certain things work, so, for example, there's a standard for diagnostics that you've probably heard of called OBD, OBD2, there's a standard connector in fact for the wiring side of this and then there are standard identifiers and standard ways that you are supposed to fill the data in and then get the responses back and that's for a handheld tester to plug into a car to ask it what the emissions are and various other diagnostics. That's for automotive, for cars and it's a legal requirement for cars. So, it's not really addressed, it's some kind of description. Yes, yes. And in fact, this is one of the biggest problems I think that CAN has had over the years is no one has really said what that's for because it's not part of the standard, the core protocol. And so people start to say, well, maybe we should have the source address, maybe destination address in certain fields. And that runs into all kinds of complications later. So the extended CAN identifies with 29 bits. The reason that came into existence, so the very first version of CAN only had 11 bit identifiers, and then they extended it with version B of CAN. The reason for that is the truck industry wanted to start chopping the fields, the identifier into various fields to include source address, priority, and then various description identifiers. And that's because of the way trucks are built, is that the people that build trucks aren't the people that manufacture trucks, they're the people that decide that maybe even someone that just owns a few trucks for a fleet. They decide where to buy engines from, where to buy gearboxes from, and they decide how to integrate that together. And so there are standards in the trucking industry for this is how what the identifier means and this is what the content is. And they have literally a book that you can buy, I think it's published twice a year by the Society of Automotive Engineers that describes the full entire catalogue of all the information if it's available, how it looks. And then there's another standard for the marine industry for ships and yachts that have taken the concepts from J1939, the truck standard, and then made it specific to marine equipment. Can we find something on internet? I'm just curious. J1939, yes. Unfortunately, you have to pay for that quite a lot to subscribe because you need to buy it every year because it changes. So yeah, you can see up here. Oh, I don't see the explorer. Oh, sorry. Let me share explorer. There you go. Yeah, so that's J1939. Okay, so let's be more specific. Can we go back to the analyzer? So, let's say we have couple of boards connected together, so one will be like processor board or microcontroller board. I can't see it. Okay, I can see now. So, one will be the processor or microcontroller board, then there will be three sensors or two sensors and then there will be, I don't know, some kind of motor controller board. So, how would you implement the data transition inside of this, like, on hardware level without using any special protocol? Yeah, so what normally happens for control systems is there will be frames being published periodically. If you want to keep it very simple, you have in your microcontroller a simple loop with a timer that starts the loop, and you read your sensor values, your analogue, digital or whatever, and then you just feed these into frames and you send them on the bus, and that's the sensor values and you might have four or five different boards with four or five different sensor arrangements. And on the receiver side, maybe you're doing electric motor control, and you have receivers that each control one motor of many and you receive frames coming in. And the way the controllers work is there are two usual, usually two ways you can control them. One is to have an interrupt come in when a frame is received that you want. And you set what are called receive identify filters. So you give a mask, a bit mask and a bit match registers, and you say, I want to receive these identifiers and all the rest I don't care about. I just want microcontrollers, so I just want these sensors. And you receive those in, and sometimes you can program it if you want to give you an interrupt, and then the microcontroller can pull the data out of the receive FIFO. Or, and this microchip device has it quite nicely because it's got lots of buffers, you can say, please put this frame identifier into this buffer slot, and it allows you to have multiple buffer slots. And then every 10 milliseconds, you can just go to the controller and read out all the frames that were in the buffer slots, and they either did turn up or they didn't. If they didn't turn up, then you can say, well, maybe there's a fault because it wasn't sent. And it's all very straightforward. One of the nicest features of the CAN protocol that beats every other protocol I know of for free buses is it has atomic broadcast of values. So what this means is if there was a noise error, on one receiver and it saw a corrupted frame, it doesn't throw it away. What happens is it sees an error, so if in here there was a corruption of a bit, by the time you get to the end of the CRC, you know that the data was corrupted and what it does is it sends an error flag. And what an error flag is, is six dominant bits. And that breaks the bit stuffing rule that we talked about. And that causes the transmitter and all other receivers to go, ah, something's wrong. And that goes through a recovery synchronization process and then it re-enters arbitration and then the harsh priority frame goes. So the frame will be resent automatically. So this means if you've got say two motors and you're controlling two sides of some piece of equipment and this one sees the frame is okay and this one sees it's bad, this one will kill the ongoing part of that frame so this one won't see it either and then it's resent and then they both get it. So automatically, you have consensus of you have a sense of value. And that's incredibly useful to do that in software requires acknowledgments, maybe the frame needs to be sent multiple times, so in ethernet, for example, if you get a bad CRC, you just throw the frame away. So if two or three or four ethernet devices are listening and they're all controlling things independently and they pull a sense of value in, and some get it and some don't, you now have divergence of state. So one side of a vehicle may not see a sense of value correctly and the other side doesn't know you've got how do you control the other ones don't work. It's not like known state, it's kind of unknown state. Well, because when you receive a frame, you know that everyone else who's connected to the bus has also received. They should receive. If there is this correction, then you know, yeah, everyone receives it. I understand. So, it's really powerful way of doing control systems from sensor to actuator processing. It's very good to point out because, for example, there are many problems with UART, like you can receive garbage and you will never know you receive garbage. Yeah, and you need a CRC to check for garbage. And then pretty quickly, when you start building up with UART, you need to build all the things, you need to know which type of message came down, so you need a little header with a identifier in it and then the payload and then a CRC, and pretty quickly you're building CAN. So basically, if I understand right, the CAN controller itself, it may have some kind of register where you tell its identifier or something, so you kind of set the address of the controller or something. If you like I mean, if you're building your own application, you can decide how you want to set those identifiers up. But it's kind of address, yeah? So that's how it recognized like, oh, this message was for me. It's not for you, it's on the bus and then you recognize that you want it. Yes, so they call it address filtering. So, you say I want that one, that one, that one and that one, and another device may want the same frames, so it's not, it's not sent. Okay. It's broadcast and you decide what you want. Okay, I understand now. So, in the controller you, there is physically a register and you say like I would like to receive all these messages which are, I don't know, which have the identifier AAA or something, and then basically the controller will pass the message only when there is AAA. Exactly. So, you don't need to care about any other messages, you don't need to process them by your microcontroller, you only receive the messages what you want. Exactly. So, then, yes, it makes it much more simple, so the software doesn't need to do anything, it just pulls frames that it wanted. So, basically, let's go back to our system. So, we have this microcontroller board, and we have a couple of sensors, and we have also the motor controller or something. So, what you were saying, this sensor, they can be sending, for example, temperature every one second, and the controller board will just automatically receive it, and they can, it can buffer these messages, and then these messages can be processed by software. Yep. Yeah, so and you might have, yes, you might have temperature every one second. But you might also have some sort of Hall effect rotating disk with a position of some rotating piece of equipment and that might be going every 5 milliseconds. So it's very, very accurate position information of a turning piece of mechanical equipment, like an engine crank angle and it's spinning very fast. And so the data is coming on the bus 100 times a second, or 200 times a second. And then you pull the data you want. And the reason for this buffer, instead of an interrupt, where it puts it into the buffer slot, is if you were receiving all of the sensor data as fast as possible to do some control algorithm for, say, a motor, but another device wants to see the frame information, but it doesn't care about all of them, it just wants the latest value. That can go into a buffer slot that is just overwritten every time a new frame comes in, and it just reads the latest one. So, the software doesn't even need to get lots and lots of interrupts or anything, it reads the latest value of the CAN frame, and it just reads at the speed it needs to read it at. So, what is the advantage of broadcasting all these values, because it increases power consumption, it makes the bus very busy, there are data flowing all the time, if you compare it to getting data based on request, like okay I need temperature, so I will ask this sensor, send me temperature. So what is the difference? Okay, well, in fact, with CAN, there is a second type of frame, it's not used much today because generally, everyone, the system is designed to send the data to the enough times for everyone to use it. And it doesn't send it if no one is using it. So it's designed that way. But when CAN was originally conceived, it's exactly as you say. What about sensor values that the receiver chooses how often that the're sent on the bus for power consumption So they invented a second type of frame called a remote frame. And the remote frame doesn't have any data, and it has a remote frame flag on it and it says, I want to receive the data of this identifier. Oh, really? Yeah. So you say... So if the temperature is being updated in some controller quite quickly, because the controller is dealing with that, you can transmit a frame that says, I would like that and then the receiving end transmits the frame. And then you get it back after after some time. Is this done automatically or on the like, CAN level or you have to process this by software somehow? It's not specified in the protocol, so some hardware does and some hardware doesn't. Okay. So, the microchip chip, you can program it so that it will in fact do exactly that so you you can write into the controller the sensor values. Temperature or something. Not send them of temperature, yeah, but not send them. And then when a remote frame comes in with the matching thing, when you configure the controller you can say whenever you see a remote frame then send it. Cool! These are really... Actually, I'm starting loving CAN now. Yeah, no, it's lovely protocol. It's super robust, it broadcast data to multiple devices so it's super efficient. Yeah, the [inaudible] broadcast. Yeah, it's really clean. And it's really tolerant to noise. The whole error detection and retransmit protocol works. Okay, can we have some examples? Let's see how difficult it is to send a message or something. Yeah, I can't actually induce noise very easily. I was thinking about getting a hairdryer or something. No, we don't need to see noise. But if you'd like to see how you transfer a data between one board to the other one. Yeah, okay, so what I will do is I will open up, this is the... Okay, so what this is here, if you can see... No, I don't see it. That... Right, so let's try this. So, they turn up as serial ports. So, what do we see now? This is what, virtual machine or what is it? Yeah, so this is running Ubuntu, and then the two micro-python boards, when you plug them in, they turn up under the USB and serial ports. And in fact, each one in the custom firmware we've built, you get a second serial port. So the first one is designed for logging into and getting a command line on micropython. And then the second one is designed for applications to send serial data to a host. So if you wanted to collect data on CAN and then throw it up to a USB serial port. So there are two serial ports also on the board? Or how do you... No, these are... So it's only USB. You don't... So it's not running UART, so it's running USB serial. And the Pico RP2040 has got... It's got a USB transceivers in there. And then there's a whole tiny USB framework. But there is only one, no? So how can you create two serial ports? There's one USB port, well USB is very complicated. Also with one USB you can actually create two UARTs? Oh, they're not really UARTs, they are USB serial. Yeah, I know what you mean. But I didn't know you can do this. I always thought you can only have one serial port. Yeah, no, you can have as many as you like. Well, you have to make the firmware do it. Yeah, you can have lots of serial ports and then they're down one physical connection, but they're multiplexed in the USB is very complicated and all kinds of stuff, I'm sure you've seen it. Okay, so let's start this. So if we log into one of these boards. Okay. So that's, this is a, rshell is a standard tool for talking to micropython. So now the home/ken that's we are on the, we are connected to the board. Yeah. So that's my shell. That's how you log into the boards. And then it's got a bunch of commands because you can copy files. It's got a file system and things. You can copy files back and forth to the PC and stuff. But the command repl is basically log into the board. Okay. So now this is logged into the, the Python, MicroPython board, and so inside the RP2 package, which is the Raspberry Pi Pico RP2040. So you are writing directly in the MicroPython code right now. Yes. That's right. So I've imported all the packages, and so we can, in MicroPython, I can create a can frame, so I can say frame = CANFrame. And then we'll have a CAN ID and we'll make that 123 So that's the identifier. And then we can say the payload is hello. That's the CAN frame. So it has a length code of 5, that's ASCII hex for hello, and it's got an identifier of 123. Did you capture this with the logic analyzer? We can do in a moment. Yes, so I have to flip between applications, but yes. So that's the CAN frame, and so what we do is we initialize the CAN controller. So you only created the frame, you haven't sent it yet. No exactly. That's the frame there. And then you can do... So you get DLC and it tells you it's 5. So you can write Python programs here. So the data is hello. So we can play with that. But that's basically we write the software and we create these CAN frames. So in Python, if you wanted to send a frame every 10 milliseconds, you could write a loop and a delay and so so you could read from an analogue port on the boards and you can send the analogue value encapsulated as a bunch of bytes. There's Python commands to turn a number into bytes and all that stuff. I have a question, so RP2, it's, in the first line you wrote, from RP2 import everything, so RP2 is like standard library or what is it? So, RP2 is the standard MicroPython library for the RP2040 microcontroller. Okay, so anyone can use it? Yes, so what we've done is we've extended that API... You some kind of officially... I'm hoping, I mean, I'm talking to the guys about pushing this into the upstream, and so it becomes a standard CAN API that might happen into MicroPython. Okay, so let's send something. Okay, so we've initialized the CAN controller there, so we then need to log into the other board. How big data can be? 8 bytes, up to 8 bytes. So we log into the other board, should be on board two. So we logged in here now, and we initialize the CAN controller. It didn't help. I need to bring that package in. So that's created an instance of the CAN drivers and then they know how to talk, and so at the moment, so as soon as I wrote that over SPI, it set up board rates defaults to 500 kilobits, you can change all of these things with, but Python has defaults. So it was a nice simple default. So we need to do is to send a frame is to say send frame. Now, if I fire up the logic analyzer and set the trigger, so I'll reshare the logic analyzer. You can just say... Oh, okay. Yeah, so I'll set the trigger going there. Okay. And then if we go... Presenter. Yeah, and then I'll reshare that. Oops, sorry. I'll have to edit all this out in post-processing. Where's my desktop? Okay so now we'll send that. Moment of the truth. Yeah, let's see. So then we call the receive and this will this, the software by default for the Python is simplified, so it just has one receive FIFO. And there's the CAN frame. So we can send it again. And then, we probably should say it returns a list of frames. So, frames 0 is the CAN frame and we can say frame that's the first one in a list of one. So, right now it is listening to everything. Yes, there is another API extension for saying I only want to listen to these things and these things. So, for simplicity, I want, it was designed to make it really easy to get started and then you can add these extra features and turn them on. So, there is a whole filtering scheme with all the stuff. And you'll see here the timestamp. So there is a, this particular controller has got a very nice, and I've set it up for microsecond accurate timestamps. So if you want to measure the exact time of start a frame, the controller will tell you exactly when the frame went. And in fact, it fills in on the sending side. So, this is the sending controller's timestamp, so that's when the sender's microcontroller took a timestamp, and on the other side is the receiver microcontroller timestamp. And if you, if the sender was to send its timestamp, and then second message, you could start to do a global time clock synchronization between the two, and then you could synchronize everything off of a CAN frame. So, how this time is synchronized across the boards? So you would look at, so the idea of time synchronization is that you receive a frame and you have its timestamp on your local crystal in the controller. And then this one has its timestamp on its local controller. Then you send another frame, but the payload is this timestamp. When this receives it, it knows the difference between send and receive. And that delta is the clock synchronization difference. And in fact, I had a nice little program I wrote for this, you can watch it drifting in real time by a few microseconds every second. And that tells you how good the crystals are on the two boards. They're very slightly different. So, when this timestamp starts from zero again? When it gets power on reset to the controller. So, how long it can be? It's a 32-bit timer, so microseconds, I'm not sure how many. An hour and a bit, 17 minutes, I can't remember. But yes, that's 4, what was it, 4 billion microseconds. And then it starts from zero again. And then, of course, you wrap it with the zero again, yeah. So, if you really would like to see the difference, you have to do it immediately, you have to kind of ask for timestamp almost immediately after you receive the frame, because if you ask next day, then it's going to... No, not because this timestamp was taken in hardware on the start of frame when it was sent. And this is taken in hardware, and so they're not going to drift, they're fixed now, and then you can take, you could send this every one second and get a little delta between the clocks. So, if you then wanted to coordinate some actions that happened exactly the same time, you could send a frame, and the frame could have enough time to get through all the software, and then you could say, right now, fire the actuators at exactly the same time. Let's have a look on the analyzer. Yes, that should have triggered for us. So let's share. There you go. So that's the identifier 123. And then the data, 68, 65, 60, 68. So this is the hello. [inaudible] CRC and then the acknowledge. Yeah. That's the analog. It's actually simple. I always thought like, CAN is also all these other higher layers with all the messages and I don't know what, I didn't know it can be so simple. Yeah, yeah, I mean if you are building a system and you are in control of all of the boards, then you don't need to follow any of that stuff. And you can just make up some, choose some identifiers, pick the priorities based on how often they're sent, so faster moving control sensors go at a high priority and the slow temperature goes at a low priority, and then you just write some simple code. It's like lots of systems in that you can start simple. But can you set priority also for this short frame with 11 identifiers? Sorry, what do you mean? I mean if you can set priority also in this short frame. Yes, well, that's the identifier. So, higher identifier means that's more... Bigger number is a lower priority. Lower priority, okay. 0 is the highest priority. So, basically, if there are like, what, two messages or something coming, then... What does it mean? What does it mean higher priority? If you've got a sensor going every 10 milliseconds and a temperature going every 1000 milliseconds, you give the temperature sensor a higher number or lower priority than the 10 millisecond sensor. Oh, so for example, when the bus is busy and the next transition or something next will happen, then next should be the transfer with the higher priority. Exactly. So yeah, we didn't discuss actually arbitration field and how arbitration works. It's very clever. So when a controller has something to send, and if it's a busy bus, it will probably have something to send. Every controller that's on the bus, if you've got 20 nodes and they all have something to send, at the end of the last frame you get a starting point. Every device that wants to send sends start a frame simultaneously. They all do it together. So that sends a 0 on the bus because remember this is a dominant, so they all pull that temperature value, that voltages apart. That sets a 0 onto the bus. And then what happens is they then send from highest significant bit to lowest significant bit the identifier. And if you send a 1 and you read back a 0, somebody else was asserting... The higher priority needs the bus. And they must have higher priority. So you back off and you give up. Then carry on through and CAN as a rule that you cannot send two frames with the same identifier, it's protocol rule. So what happens is by the time you get to the end of the identifier, if you've received back exactly what you sent, then you must be by definition the highest priority on the bus because everyone else has given up. That's very clever. Yeah, it's beautiful. I think CAN is one of the most beautiful bus field bus protocols. It's so clever. It's got so many nice features. But then this is interesting because does it mean, for example, temperature sensors may have like some kind of range of identifiers? Yes, so if you've got multiple boards, they must have different identifiers, because you can't transmit on the same identifier. Yeah, but I mean like if you have really automotive specification and they say like, this is identifier for temperature sensor, so there will be some kind of range of temperature sensors, and each of them will have their unique identifier? Let's say there will be temperature sensors are from 0x100 to 0x120. Well, normally they'll say something like, identifier 123 is sent from engine management and contains engine temperature, for example. Okay, so it would be like very specific. Yes, so the car manufacturer defines exactly what identifiers are used and exactly what they contain. And then normally you just send that frame again and again and again. So, it wouldn't be like temperature sensor and then you have to… No, no, no. So, it's not like some of these protocols where you say this is a temperature sensor and then this is a type A sensor that has this scale. Yeah, so it's not done like that. You just say value, so you would normally pack multiple sensor values into one CAN frame. So, you would normally send a full 8 bytes so that the overheads are minimized because you're sending lots of data. And every 10 milliseconds, you would send, let's say, oil temperature, engine coolant temperature, blah, blah, blah. And you put them all into a frame, and then you say, right, the first byte contains oil temperature. And 0 means 100 degrees Celsius. And 1 means 101 or something like that. And so you define the range and then the people who write the software for receiving that will know what the value of that means. There is a standard for describing this kind of arrangement of packing signals into frames and then converting them into SI units. So there's a thing called DBC files, which is like a database, a configuration database. And lots of car manufacturers use DBC as a standard way of describing the networking on the bus, and they send their suppliers a DBC file, and it says how to decode. And then you can buy tools that will receive these frames, and then on your screen, decode them all into what they mean in standard temperature scales. Yeah, so that's a... But again, that's how people choose to use CAN, so lots of these standards have emerged from common usage patterns, so that someone makes a tool, and then different manufacturers agree they'll just use this file format to exchange details between their suppliers, and then it becomes a standard. So, so it's not really a high level protocol or anything, it's just a in old days, I guess it was spreadsheets being mailed, emailed around, or sent in the post on floppy disks. It was probably that far ago they defined these things, and then explains how to build these systems. So yeah, so cars are very, very proprietary. They've defined everything and then that's how they build it. And a different car manufacturer will do it a different way. And then, yeah, they use some common tools, but they don't define common car format. So, what kind of tools do you use for debugging CAN? What is your... My preferred tool is a logic analyzer. Which one do you have? So, this is the Saleae. This is like the gold standard logic analyzers. They're fantastic. So, they've got lots of protocol decoders, I mean, they've got loads and loads of protocol decoders, SPI and stuff like that. So, this is like USB or...? And they are USB, so there's two families, there's logic, there's the standard logic and then logic pro and the standard logic one was relatively low speed and relatively simple and now this second level, the pro versions, we've got analog, so any input pin can be read as an analog or a digital. So, you can use it also like oscilloscope? Yes, and of course you're getting on the same timeline trace. So, I mean, you can use a logic analyzer and these mixed signal scopes you can buy and do the same. How much does it cost? Yeah. Yeah, so this is it. Okay, I thought it's something cheaper. Okay. That's a lot. I didn't expect... So that is the the very best. Okay. So, but I'm pretty sure it will save you some time, so you, because you don't have to decode all the messages and... If you are a professional engineer then, yeah, professional engineers don't mind good tools. I mean, the sampling rates are, you know, 500 mega samples a second on the digital channels and up to 50 mega samples a second on the analog, oscilloscope lines, it's a great tool. If you want to to be cheaper, there are 10 USD logic analyzers that will do 20 megahertz or 10 megahertz, which for CAN is completely okay. And you can run a piece of software called Sigrok, I don't know if you've come across that. You can find it. Yeah, so there's a standard called Sigrok. It's an open source standard and they support lots and lots and lots and lots and lots of logic analyzers and oscilloscopes and stuff like that. So this is again some kind of, this is some kind of GUI, it's a software you can install and then... It's really smart, so they have a really nice partitioning, so you can have a command line driven logic analyzer, so if you're trying to build test scripts and things you want, it's really nice. And then they have a graphical interface called PulseView. So, I don't know if they talk about PulseView on the homepage. And then you just select like serial port where your analyzer is connected or something and recognize some of the analyzers automatically? Yes, so it's really smart. So, it will talk GPIB protocols, it will talk USB, it will talk serial ports, it will talk Ethernet. It supports lots and lots and lots of different... Devices. Manufacturers, so all logic analyzer, the oscilloscopes they support. And there are some very low-cost logic analyzers they support that you can buy, you know, from eBay or Amazon. These are good tips I really hope this will help some people. So these they use a standard chip. Forget the name of the chip now. But it's a very common oscilloscope logic analyzer chip, very cheap. Yeah, I see, 5 USD to 15 USD. Yeah. And the nice thing is I've actually built an... Cypress, main chip, Cypress. The Cypress chip, yeah, that's right. Yeah, that's right, this one here. So lots and lots of manufacturers use these. And the Sigrok software works with this. And there are more protocol decoders for Sigrok than there are for any other logic analyzer I've seen. And I've released a CAN protocol decoder. So you can hook this up and then use the CAN protocol decoder. All the decoders are written in Python, so it's a really easy API, and you can write your own custom decoders, and you can put high-level... The decoders will stack so that you could take, for example, the payload out of one decoder and put it into another, but would then decode what that meant in the protocol. It's a really nice system. So, yeah, so you can see all of the stuff I was showing you in the logic analyzer there, you can get because CAN, a maximum 1 megabit, 24 megahertz, is completely fine for sampling CAN on the logic state TX RX. And then you can see what's happening on the bus. And the nice thing is a proper timeline view tells you exactly what the time gaps between frames were and when a frame was and when it came back. So it's a nice clean way of seeing what's happening on the CAN bus. And I think it's one of the best ways of debugging CAN, I think. So what do you do actually? I don't know what you do. I'm mostly working on CAN security because these things are all used in cars and now people are attacking the CAN bus to steal cars. So I work on how to stop people attacking CAN bus and defending it from thieves. You might have come across a story that broke earlier this year on the Toyota vehicles that were being stolen by JBL Bluetooth speakers, the headline said. And they were actually building, somebody had built a theft device into JBL speakers with the CAN high, CAN low outputs and you connect it up to a CAN bus in Toyota cars and you got at them by pulling the [inaudible] off and pulling the headlight connector, which has got CAN to the headlight control unit, and you put the CAN high-low pins on that and you press a button and it injects onto the CAN bus a frame that says open the doors and deactivate the immobilizer. I can't believe it it would be so simple to open the door, just sending a frame. Send a frame and you say I would like the doors open, please. And in fact, the way it works is there's an ECU in a control unit in the cars that's called a smart key ECU. And it is very smart. It talks wirelessly to the key in your pocket when you come up to the door. And then they exchange cryptographic keys and it's public private keys and they're all cryptographically signed and stuff and it's really very smart. And then the ECU says, okay, so the driver is here, and then it sends a CAN frame to say the driver is here, turn off the engine immobilizer. So, the way the thieves work is they just directly send the message. I know, yeah. As if it's from the the smart key ECU. And then that's it. Who cares about, you know, encrypting everything, you just... So, then how do you work on security, CAN security? It means you kind of introduce encryption into the CAN protocol. Yes, so that's one thing. Yes, so there's several things I've been working on. One is... One is by sending extra data inside a CAN frame, extra bits, because CAN is quite slow. So you saw there was 500 kilobits, so that's two microseconds per bit. And CAN, the reason that CAN has a certain speed limit is it needs to make sure the signal goes up and then back down the bus for this arbitration part to work. But that requirement is not needed for after arbitration is finished because there's only one transmitter. So what we've designed is a scheme that around the sample points, but not through them, you can send high-speed data, and all the CAN hardware, regular CAN hardware ignores all of that data outside the sample point. But if that data encodes an actual physical source address that you encode in a hardware chip on the device, so the software can't even see it on the sending and they receiving hardware can't see it. But if you encode it into that chip and then there is a security, you see there's listening for that data, it can tell exactly where it's come from physically. Then it can say, hey, this is not from the smart keys, this is from a different device. And then it uses the same error mechanism we've talked about, it sends six... And reset everything. It resets the whole thing and kills it. So then, every time you try and send a fake frame from an ECU that you're trying to, so [inaudible], it's just destroyed, erased, popped. Unfortunately, the theft device for these Toyota cars actually defeats that because it's not a CAN transceiver. It's not a real CAN transceiver. So I said earlier, if you remember, we drive the voltage apart and they float back to recessive. It does something else. It drives the voltage apart, but it drives them recessive. So then when another device decides it wants to kill that CAN frame, because there are other security things that work the same way, and they send and they pull the voltage apart, this transceiver is driving them together. And it has a much higher drive strength than the device trying to take it away, so it doesn't destroy it. It doesn't reset. And then the fake frame goes through. So now you come up with something else or it's even better. And you can't tell us and you can't talk about it and... Yeah. So you have to mix your defenses things. So the CAN hardware protection is for protecting when some piece of software has gone got malware in it and it's using the ECU's own transceiver because that won't then have this special drive strength transceiver that thieves are using but in the case for thieves attacking the wires, you also need encryption cryptography on the CAN bus. So here you need a mix of different solutions and work in some cases and some work in other cases. And then you probably, when designing cars, need to make sure that thieves can't easily get access to the CAN wires. So Toyota have issued a fix for the RAV4, you can take your car to the dealer and then you pay the dealer to fit some metal plates over the connector to stop thieves taking the connector out. So, that's probably expected, at least for that particular attack. But I mean, you can obviously get a wire, a pair of wires are going to go through the car. And I've seen pictures where they know the wires are going past this panel and they've punched a hole in the door panel. I was exactly thinking about these like... So in the end, it becomes very difficult because cars are parked on the street and left unattended, I think, so you know. So lots of the security stuff that you design for data centers and PCs in secure environments, the car is left in an insecure environment, so all kinds of physical attacks are perfectly possible on a car that you wouldn't expect on a data center. Yeah, so security is very, very difficult to get perfect security. And in the end I don't think you'll be perfect security for street thieves. All you can ever do is make it much harder and then they'll go and steal someone else's car. So why did you design your board? Because you use it every day? No, because it's the best teaching device, so we wanted to be able to talk to people about CAN, show them how CAN works, so it's an educational board. Can you show me your website? So what do you have on your website? So you also do education? We haven't done that recently. So, yeah, so that's the canpico board and we use that as a rapid prototyping system. I mean, I use it a lot for making tests, to write little bits of Python to generate test messages quite easily. So that's very nice. And then CryptoCAN is the encryption system I talked about and again we have that available on MicroPython and in fact that's in the firmware I've got here with CryptoCAN working. So, you can encrypt frames on the bus between the two. So, this is not the hardware physical fitting bits between the bits and bytes, but this is... This is software. ...or data level. Yes, exactly. So, CryptoCAN works by taking taking a plain text CAN frame in like our hello frame and putting it through an encode process and it produces... two Ciphertext frames and then you send them both then all the receivers you do the decode and you get back the plain text back. So that's a way of protecting CAN frames there. So yes, that would be mixed with some of the other hardware protections. So this is the is the way of... Here is a... What do you have in open source? There is the library? Oh, this is how it looks? Okay, so this is the high-speed frame, so at the top here, here's the identifier and in fact this is the protocol decoder for Sigrok. So the top here is the CAN ID and then we go and here's the payload frames and this is a frame that on CAN is 000000. So, these are stuff bits here, you can see. And then CAN HG is these high-speed bits, and you can see these little gaps, these sample points to make sure that a CAN, ordinary CAN controller receiving it isn't upset by this data. So, this is how you kind of modulated extra information inside of the existing CAN protocol. Yeah, so yeah, so if your CAN bus is running, say, at 250 kilobits, which is how J1939 normally runs, and you're sending an 8-byte frame, you can actually get inside 276 payload bytes. You can squeeze in the gaps. So if you're trying to do, if you've got two ECUs together in a truck and they're doing some really tight real-time control, maybe some kind of special traction control or something, you can send really high-rate, high amounts of sensor data in an ordinary 8-byte frame. And so all the other devices just ignore it and then the two devices talking to each other. But I guess this may be limited by, I don't know, length of the bus or something? It's, yes. Length of the wire, I mean, because higher speed it means these bits can be more disturbed and... Yes, so, these bits are running at 10 megabits, so that's 100, by standard they're 104 nanoseconds long, these bits. And how fast that works on a standard bus through a truck is an interesting, I've got a video here and in fact it's not the length that is the biggest issue, it's to do with the quality of the cabling and the impedance match. So I'll stop that and do a new share. So I can show you here. So this is based on a model of a CAN bus and looking at the reflectivity off the end from impedance mismatching and you can see there's a reflection coefficient here. So this is starting at 0 here, so this is a perfect CAN bus, and this is what it said [inaudible]. But if we, so this video is a run through of all the different reflectivity values and what it does then to these signals on the bus, so you can see as the bus starts to amplify signals, so it's a positive reflection, it looks like that. If we go back down again through 0 and then we look at the negative pulse coming off the end, you can see here you get the ringing of these and these are reflections up and down the bus, so the reflections will bang up and down the bus slowly attenuating. So this is basically situation for example if your termination is not right. Or if your cable is very cold, for example, because the polythene insulation changes the impedance of the bus. Oh, so basically, for example, if it's outside, if there is below 0 or deep below 0, then the resistance of the cable is going to change and it means your termination resistors are now out of the proper termination values and... I'm not sure about the resistance, I think it's more of the dielectric effect of the, I mean, this is not my field, but the dielectric effect of the polythene is temperature dependent. So if it's at -40, which most cars are designed to work at -40. We have to say -40 Celsius, but I think it's also Fahrenheit. Or is it? I don't remember. Yes, I think they're the same, aren't they? I think they are the same, yeah. They are, we don't need the units for that one. Different in Kelvin. So you can see here, there's quite a lot of oscillation here, and so this isn't to do really with the length of the bus, it's to do with the reflections, and what happens is CAN transceivers have a hysteresis function in them, so that they won't flip between the digital states until it's gone too far the other way. This is enough to overpower the hysteresis, so you see on the digital side you get glitches corresponding with these reflection poles. So when CAN is sampling at low rates, low bit rates, these glitches are finished by the time you take a sample point because the the bits are very long and there's plenty of attenuation. So this is why CAN at low rates will work on bad pieces of cable, bad wiring and stuff. And if you want it to work faster so that these glitches go away, then you need to do more things. In CAN HD, we have some digital side glitch-filtering that actually removes a bunch of this from a physical layer. So we have a research and development agreement with the US Army at the moment, looking at CAN HD for security on army vehicles. That is exactly how to process signals that are in bad environments and still retain high bandwidth throughput. So, basically, this sampling is happening far away from this rising edge? Yes. When does sampling is happening? Yes, so normally the default on J1939, for example, is to set the sample point at 87.5% into... 87.5%, okay. So, lots of people, when they first come to Canis, they go, I don't know what the sample was to be, so they pick 50%, but that's a mistake because you want to be as far away from this reflection. Yeah, because there can be also this... Yeah, exactly so. And in fact, on this reflectivity, it's on the rising edges, it's particularly bad. And what this often means, in fact, even if you don't get glitches, what it can do on the rising edge is it can cause... Because of the way the hysteresis works, it can cause the rising edge to be delayed. So the bit gets shortened, the rising edge is a delay. So there being 2 microseconds, it might be 1.9 microseconds because that's been delayed. And in fact, you can actually use that as a characteristic fingerprint of that change in timing can be used as a characteristic fingerprint of where the can frame is being sent from because the bus is a fixed place and there's a fixed reflection pattern, and thus the place where you're sampling this data is a fixed place. So for example, if the engine is sending some signaling value on a car, the time taken for the reflections to bounce back and the effect that has on the timing of this should be fixed based on where the engine management is, so if you see pulses that don't fit the timing patterns, then probably not coming from that physical location. and if they pretend to be the engine but they're not physically coming from the engine, then they're probably fake frames used by a thief or something to try and unlock the car. So, there are all kinds of interesting ways of detecting security attacks on the CAN bus. Okay, I have one more question. I don't know what the time. We are still okay. So, at the beginning, I didn't understand well how how does it know how long or when the next bit is coming? How much it has to cut to? That's the configuration. So, when we look at those TSEG registers in the controller, you say the clock is clocked to the certain rates with the board rate pre-scaler. So, you have to calculate it? Yes, so there's a formula for how to set up the TSEG 1 and 2. From a... Say you want to... Okay, I thought it's some kind of intelligent, it will kind of measure it. So, no, you have to set all the devices which are connected to the same bus, you have to set them to specific speed. Yes, so the number of time quanta per bit is not a bus-wide thing, it's only the receiver needs to set that up, so it needs to define a bit time. And that depends on its local crystal and the board rate divider that it picks, and then you pick a number of time quanta per bit, and then you pick a comparative value in that for when the sample point is taken, and you pick a board rate that nicely divides, and you pick a sample point that is close to the end of the bit. So, there is some kind of board rate in CAN, like official which... There's nothing official, it just defines this little state machine and then you set the parameters of the state machine. You can choose any board rate you want. Yes, some don't divide very nicely. So that if one device has a crystal of 10 megahertz and one has a crystal of 12 megahertz, you can pick board rates that are really bad. It's like a UART setting, UART board rates. It's the same kind of, pretty similar scheme. You have a pre-scaler and then a bit counter. Are there some kind of standard board rates like on UART? Yes, so J1939 normally picks 250 kilobits. There is a substandard that allows it to go to 500, but 250. Okay, I understand. So, basically, as UART is, I don't know, 115, 200, then for CAN you would say 250. So the standard board rates in cars is normally 500 for all the powertrain sensors, and then 125 and 250 for depending on how long the bus is. Okay, I understand now, I understand. So yes, if you're picking CAN board rates, the ones that everyone goes for is 100, 125, 250, 500, and sometimes 1 megabit. And they're the ones that nicely divide into the crystals, just like the 115, 200 [inaudible]. It's a nice choice. Is there anything else what we should talk about? We can, in terms of the lower layers, I think we've kind of covered it quite nicely. So, what is on the higher layers? Yeah. Where everyone can go with CAN? Well, people start to design their own exotic schemes and some of them don't work and some of them don't work. But if you don't want to design it by yourself, are there some kind of open standards what you can just use in your systems? Only for cars. No, not really. There's... Yeah, there's car stuff, but the car manufacturer's picking its own mappings. There's J1939, but if you're not a truck, then it doesn't fit very well. There's the NMEA2000 for marine vehicles. So usually an industry settles. So there's an organization called CAN in Automation, and they've defined a protocol called CANopen and that defines a very simple use of CAN and then different sectors have defined their own. Can we search for it? Yeah, so they're called the CiA. You need to share it again. So these guys, they organize the International CAN Conference, which is coming up next year, and do a lot of outreach work. But they define a thing called CANopen, which is designed for factory automation, for elevators, for stuff like that. So lots and lots of machinery. And it's a way of connecting up sensors and actuators in, say, a production line. And then different industry sectors have got together, so earth movement equipment, building machinery and stuff, have defined their own sector specific things to do with, if you're an elevator, there are certain application level messages you need to send. So all the kind of components are compatible, even if manufacturers are different? That's the goal. Yeah, so they have sector-specific things, because anytime anyone tries to do a universal thing, it's like the world is not fit for universal. [inaudible] So yeah, so that's a very popular system, so there's literally thousands of manufacturers conforming to that standard. Okay. Okay. Lots of things with CAN. So your name Ken actually, it's like saying what you do. Yeah, exactly. Exactly. You find your... The job was actually exactly for you, yeah. Yeah. Okay. Thank you very much Ken for all this information. I always thought CAN is like very complicated and it doesn't look like it's complicated and it actually, it looks like it's very useful and kind of intelligent. Maybe I will use it next time. Yeah, yeah. So, thank you very much. You're welcome. And, that's everything. Thank you very much for watching this video. By the way, we are preparing some very interesting tutorials, so if you don't want to miss them, hit the subscribe button. If you want, you can also check out our FEDEVEL online courses, where you will find everything important from basic board design up to advanced hardware design and PCB layout. The link is in the description. That's all for this video, thank you again, don't forget to leave your comments and see you next time. Bye!
Info
Channel: Robert Feranec
Views: 33,501
Rating: undefined out of 5
Keywords:
Id: OqN7xNn92pc
Channel Id: undefined
Length: 78min 12sec (4692 seconds)
Published: Thu Nov 16 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.