 First we'll go through the API structure and the call and how the libraries are all structured in the FOC abstract layer as we call it. So we're now on the last section there which is the final development. So we're going to have a look at how the architecture of the firmware is, so the motor control and the FOC libraries. Then we're going to play around with building again using various functions, adding various functions, putting more feedback inside the loop as well. And then we'll start adding extra peripheries that aren't part of the motor control part of the application to show you how to add normal comms, normal other features that are going on within the application if driving a motor is not the only thing you're doing in the task. So the firmware architecture. So the motor control library is split into three different parts. You've got the user interface library. So these are the commands that you're normally talking to get it to do things out the serial comport, sending information in, getting the data out the DAX, things like that. Then we've got something called the motor control cockpit. I'll explain that in a bit more detail in a second. And we've got the motor control libraries themselves. So these are what's actually doing all the main procedures that we're using. So the PID regulation, the feedback encoder alignment, things like that. They're all the dedicated algorithms that do the specific tasks that's part of the libraries. The motor control cockpit is actually again split into another three subsections. You've got the interface part for driving your two motors. The library can drive up to two motors. We've got all the initialization and configuration elements for doing the setting up of all the elements that make up the library structure. And then we've got all the dynamic parts. So these are the loops themselves that are generating the FOC, the safety and things like that. So these are all separate subsections within the library. So the library is actually segmented into multiple sections to make finding things a bit easier and a bit more logical for you. The APIs for those of you who've used SDM32 before with the HAL, if you remember, everything starts HAL. So it's a common interface that we have to make sure you're accessing the dedicated libraries. So we have exactly the same here with the FOC library. And it means it gives you a nice logical step into the substructure that's there to do all the motor driving. So it's a consistent method. So everything will start MC underscore something as a command. So you know exactly what it is. It's to do with the HAL library or start HAL. If it's low layer library, it starts LL underscore something. So it makes programming quite simple. You know which commands belong to which library. And then it's the easy way to expose all the functions with all the rest of the commands that follow the start of the MC parts. So this is really what the machine-to-machine interface is doing so that you can access the subsections. So the high-level commands that you're putting in will call potentially two, three, four different sub-layer commands to do the various tasks. It won't just call the one that you're calling. There'll be sub-layer ones below that as well. This is also split into two sections. So you've got the one that's controlling the interface, and then you've got the one that's controlling the fine-tuning of the various objects, which I think is probably what you're trying to do here, the fine-tuning parts, which we were having a little difficulty with. So the interface ones are fairly basic commands, like start and stop motors. The tuning will be more the complex commands, which I think is some of the commands that you're trying to send in at the moment, which are the set the KP for the PID, things like that. So you can access them directly the tuning ones, but normally you'll go through the interface first and only use the tuning ones as and when you need them. It won't be a normal function that you'll be calling. For the interface sites, there's two types of commands. There's buffered ones, which will come round every time the state machine passes the certain task. It'll then take that information into account as it goes through, and then you've got non-buffered ones, which have to happen instantaneously. So things like buffered will be program speed ramp-ups, and unbuffered will be start and stop because they have to happen as and when you hit that particular line of code inside there. So all our commands look like this. Everything starts MC underscore something inside the software. And then when you're doing the tuning ones, they don't start with the MC anymore because they're not part of the main functions. They're now the specialized functions, so they all start with different commands. So the more optimized commands are a different interface structure than the main commands that you were using inside the libraries. Every time we write any code that's going to use any of these commands, be it tuning ones or interface ones, we need to make sure that you've included, at the top of your software, MCconfig.h. It has to be included inside your project workspace. So we'll have to remember to do that when we get to our software examples in a bit. That line of code has to go inside for otherwise you'll get a nice error message with it unable to find things. When it comes to certain variables, the format needs, you need to pay a bit of attention to. So inside the library, things are referred to as 0.1 of a hertz when we're talking to some of the references. So for example, if you want to run ramp up to 600 rpms in one second, you've got to convert the rpms into hertz. So you have to do a bit of mathematical calculations. And the timing is always in milliseconds. So that comes from the sys tic timer, so one millisecond sys tic timer. So therefore your time delay is a thousand, which represents you one second. Your 600 rpms is referred to there by 100 because that's what you have to put it in. Basically it's 600 over 6. So you've always got to divide it by 6. And then the conversion there puts it into 0.1 of a hertz. So when you come to filling that particular line in later on, when you're doing the hands on, always remember it's 0.1 of a hertz. So you're running the variable at and one millisecond for the timing variable in that loop. And then we've also got digit per PWM. And that one's in a nice mathematical calculation to get your angular position. We're not going to use that in the libraries today, but it's one of the variables and equations that is worthwhile knowing when you're playing around with the libraries. And again, current and talk units are, again, another nice calculation for you as well. So, for those of you who've not played with Cubamex very often, this is the typical structure of what is generated from our Cubamex tool. So inside we'll have all the initialisations, and then we'll usually provide you with a template of an empty while one loop. Dot it all the way down the code. You'll see these user code begins and user code ends. This is so that when you're writing code and you want to regenerate with either the motor control workbench or the Cubamex tool separately, if you type between the begin and an end, your code will be maintained when you regenerate with the cube. If you typed outside of that area, say at line 133, then your code will be overwritten by a standard template again. Now, we've put enough of these begins and ends all the way down the main.c file so it won't restrict you from writing code. There's one loop being included. There's one in variables. There's one in function prototypes. There's one in the sys in it there. Two in the while one loop, one in the while, and then there's number three down there as well that fit in the while loop. So they shouldn't really impact what you're writing with your code and where you want to put things. You can even add more. As long as you choose a different label that's not already used, you can add more into there for begin and ends if you want to. So normally your main code that you're calling all the time will be in your while one and your initialisation bits or something that has to be configured before you start your infinite loop will usually go into user code begin to. It's the way we structured the code. So, as I say, there's plenty of them around the code. Up at the start of main you've got another one and then you've got initialisation ones as well. So, and as I say, you can place them wherever you want in the code. So now, what I would like you to do is write the software to do that waveform. So you're going to ramp up to 700rpms over a three second interval. Then run at full speed for the 700rpms for five seconds. Then stop, wait two seconds, and then go in the opposite direction. Like most compilers, so in the etolic, if you start typing and then go control space, it brings up a list of all the commands that are available to you to help you with what you're typing. You've got the assistance of the tool, but what I want to see out of your motors now is that type of flow. Ramping up speed, running, stopping, changing direction, and then running and stopping again. So remember this variable is in the tenth of hertz. So this is your tenth of hertz variable. This variable is in milliseconds. This is what your code should look like. If you've done it correctly, your code should look like this. So you can then use your workbench and go into the monitor, as some of you have already been doing, to see exactly how your motors behaving. Most of you are noticing that it's not ramping up to match that diagram. You have to remember that the FOC algorithm doesn't kick in till you get to a certain rpm level. I think it was programmed at 500rpms, if I remember rightly, which means at that point then the FOC algorithm's only got 200rpms to do the ramp up, and you're getting a massive overshoot you're probably noticing if you've gone into the monitor program, because it's too short a period. This is where you're going to have to do some tuning. So we've got the two gentlemen here playing around and analysing it all for us here, for the way the start-up algorithm is actually working, before it kicks in, before it hands over to the FOC algorithms and does this. So these are things that you've got to be aware about. Before you switch to FOC, there's a default ramp-up stage that's not under your control. I think it's open loop into it, working in before it goes into FOC control. So you've got to be aware of that as you're looking it and designing your graph. So just so you know in your documentation, these sections of code here that we have, they're already pre-written somewhere on that folder that you've got, in a something called lab.zip, and you need to extract it. You can import them into your Tovic. So you open your workspace, you right-click in the workspace section or go file and import, and then it's existing projects into workspace in the general tab, and then you can go and pull in the three final examples that we have available. And then you can import multiple projects at the same time. It's one of the features of Eclipse. You can click on all the projects that are in that archive or that are in that folder, and then you can bring them all directly into the workspace. So you'll end up with multiple projects in your workspace, and then you just have to be very careful with which one you're highlighting when you hit the build or the debug icon because you might end up building or debugging not the project that you're currently writing code to. So it's something that you have to be careful with multi-project workspace formats. Easiest way is those little icons there are showing the open folder. You can right-click on them and say close folders as well. So then you can't build it if it's closed. It won't let you build. So if you accidentally click on the wrong one that's already closed. So we're using a define statement in our software. So this is the software as it's written inside the complete example. So we've got the if-def statements in there for the defines for us. Right. So hopefully when things are working correctly you should see the graph that looks like that which hopefully is what you've managed to get, Thomas, was it? So it resembles that. So there we go. So section two is the start-up and alignment from zero speed which is that predefined thing before it switches over to FOC. Then number three at that point that's when you're ramp-up starting. And then number four is the seven hundred four three seconds. Or the five seconds. Right. So if you've opened that dot lab can you right-click on it and say close folder please just so we don't get confused with what's there. So if you right-click on LAB and there should be one called close folder and it should disappear and it should shut the folder up in the icons. So this icon should change to just a plain blue one so it's like a shut folder now if you've opened that. Because it just makes it easier for when you're clicking build and debug if you clicked on the wrong item. So now we're going to add some control in there. We're going to use the NTC now to get the temperature and we're going to compare that to a value of 29 degrees. I think the ambient here is probably about 25 at the moment. Feels quite warm in here. So if you set it to be 29 which means if you put your finger on it you should be able to raise it 4 degrees and we want to slow the speed down. So if it's less than 29 degrees we want to run at 1,400 rpm and if it's above 29 degrees we want to run at the 700 rpm which is what you've currently got today in your software. You've got to remember to make sure you've still got your include in there. I think you can do it in the same piece of software. Most of it is going to remain the same but it's just the speed that you're going to ramp up to. So it's line 1 is the only line that will be changing and it will be going inside an if statement based on the NTC value. So you should be looking a line that looks something like that. So at the moment you've just got that line there for three seconds you now need to add that, the two brackets and the L statement around there. Same for the negative as well. If the temperature you've got is greater than 29, we will run at 700. If it's less than 29 or else you will run at 1,400 rpm. So you're now going to do some feedback from an external device. So we're now not just driving a motor now, we're now putting a bit of sensory input at temperature to control how your motor behaves. So normally if it was driving just a fan blade you'd have the statement the other way around. You'd want the fan running faster if it's over 29 and slower when it's less than 29. We're doing it the other way around so when it gets too hot we don't want some of the motor generating excess heat. We're doing it the other way around, we want to slow the system down when it gets too warm. And again, you can watch it in your monitor program to make sure or your console to make sure it's actually behaving at the right speeds. You do have the temperature gauge in your console so you can see exactly what temperature you've currently got coming from your NTC and all you've got to do is grab hold of this corner of your little PCB to get hold of your motor and make sure you've put your include mcconfig.h. So hopefully your code should look like this where you're doing the test and then the remaining line should be the same as you had previously and you should be able to see in your console window or your monitor window to make sure your speed is behaving correctly. Change your temperature from 29 to something lower. You've now added some feedback to your code using the NTC part so you've now started to put feedback in. What do you do now when you want to add other features to your project? So you want to add SPI to talk to some mem sensor. You want to add something else to do something else. This is where you now got to play around with Cubamex and the Workbench software. So I'll show you that. The only feature I've got available to me is the blue button. The only feature I've got available to me is the blue button. On the nuclear board there is not much else connected. So we are going to manually set up the blue button now. So we're going to have to tell the workbench because the workbench knows it's a nuclear board. I have a blue button. So we're going to have to disable that in the workbench and then we're going to manually add it in the cube side. As if you were manually adding the SPI interface to talk to a mem chip. So we're going to use the blue button to do exactly what we were doing previously. Start and stop is what it's going to be used for. We can find the connections to see where the blue button is first on our schematics. We then got to disable it in the motor control library because it knows it already exists. And then we've got to set that pin as an external interrupt in our Cubamex environment as we would doing anything else. And then we have to write some callback function. So when that interrupt executes or that button detects is red inside the software we then have to do the code to match start, motor, stop, motor. It's just one or two lines of code but configuration inside Cubamex. So on the schematic diagrams our blue push button is PC 13. So that's the pin that we need to add inside our Cubamex. So we are going to disconnect our button from the tool itself. So that's under user interface and we've got to deselect it there. And then we're going to save it as a new project. Completely new project. So if you go into your workbench and create a new project. So close etolic down, close your consoles down and close the project that you've currently got in your workbench and click on new project. I want to go file close project. I'm going to click new project. So it's the same thing, custom. Select the inverter section so we can find our pair of boards. Select our motor. Say OK. That will launch our project. We need to go into the user interface and we need to disable our button. So once you've deselected your button that means the workbench tool isn't going to automatically pull in the bit of software that does that for you. And then you want to generate. So you click on your blue down arrow. We're going to save this as I want to call it number four this time. Different numbers. So you want to save it as number two. I'm going to save mine as number four because I've already got a two and a three. You have to select your tools as you did before and then you generate. Now don't close this screen. This is where you need this update button later on. You're going to need this update button later on in this. You can still open the project again, don't worry. But this is where the update part is going to get used now. So when we're clicking generate this is now going to generate our IOC file which is our cube file. So our Cubamex will now be able to open this file in a minute. So we can close that screen there, that one. Now we want to go and launch our Cubamex folder. So again you can double click on the items here in your log menu at the bottom. There we go. And now we want to launch our IOC. If you click on the IOC file it should automatically launch your Cubamex. If it doesn't, so in that case you'll have to go to your start menu, launch Cubamex if it gives you any errors. I know mine's going to give me the wrong one because it's going to launch the wrong version of Cubamex. So I have to go into that one. So I have to go through this way to make sure I'm in the right version of Cubamex and I have to load my IOC file. So now we need to add our push button. So remember it was PC 13. So if you left click on PC 13 which is pin number two on the diagram. And we want external interrupt. So it's EXTI-13 but it's the bottom one on the list you need to tick. There we go. So we get external interrupt. So that our software can use it so remember our software's pre-written we've got to give it the correct label now so it matches our software. So any labels you define for pins here are carried through into the software. So right click on the button and enter user label. And what you need to type in is there. So ignore the speech marks. So don't put that in. Type everything else and don't put the speech mark in at the end. So start slash stop space square bracket push button. Now what's in the square bracket is purely for your reference. That's not going to get carried through into the label. So stop is going to get carried into our defines here which will go into main.h and because we're putting the speech marks in windows or C will automatically replace that which is a legal character for an underscore inside the software. So they'll do it automatically. So I'll go back on my label. So start slash s-t-o-p square bracket push d-d-o-n There we go. So start stop push button. We all got that part done. Now we need to go into the configuration tab and we now have to tell that the pin is an interrupt. So you want to go to the GPIO section in the configuration tab. Highlight line for PC 13. And because of the way the pin is wired it needs to be external interrupt falling edge. By default it's rising edge but our circuit diagram tells us it needs to be falling edge. So external interrupt mode with falling edge. And then you click apply and OK. So that's configured the pin as an interrupt. There is another section we've got to tell the core that that pin is now an interrupt. So we have to go into the controller or the nested vector interrupt controller and we have to tick for exd lines 10 to 15. So they're grouped together on one vector lines 10 through 15. So we need to tick that one or 15 through 10. And we need to give it a priority of 7. Lowest priority. Zero is high and high numbers are low. So you can apply that and OK. And now we want to go project generate code. Right. So coder says it's been generated successfully. We need to say close to that. We don't want to launch the project. So you say close. You can reduce your QMX. I can reduce that. Now we want to go back in here and we want to generate code again. And this time it's update. So now it's going to be the update button. Because this is now going to update motor control features but keep everything you've just generated from the QMX which is the GPIO configuration. So we need to click on update this time. So the workbench is now looking at what differences we've done to see if it needs to change anything in the way the motor control part of the project works. So the motor control is the last thing that gets updated in the project. So mine's completed. So I can say close on that one. And now I can go in the same way before. Double click on that line. Double click on true studio. Into there. And click on the project file. And that should automatically launch my programme. I will close my workshop number three. Right. We need to add some code now. And we're going to put this code in user code beginning and end number four. The reason we say user code beginning and end number four because this is an interrupt service routine we tend to group our interrupt service routines at the bottom of the main code. So this is what you need to type. If you've got it from the pre-save file which is lab six, it's already there. So this is your GPIO external interrupt callback routine. So your interrupt service routine. And we're going to say find out what the pin is doing. And then depending on the state we either start the motor or stop the motor. So if you're copying from here you don't need to copy this only from the saved example that you can find from the lab. You don't need the if-def statements. So that's the end of the hands-on. So you've now seen how to add external code that's developed in Cubamex using that update feature in the cube. Or you have to remember when you want to do things, Generate creates the IOC file which is what Cubamex opens. Update takes the changes you've made and merges it back into your motor control software. So you're now prepared to do all that.