VESC and Simulink in windows

General topics and discussions about the VESC and its development.
michael_wintergarden
Posts: 85
Joined: 10 Aug 2016, 16:14

Re: VESC and Simulink in windows

Postby michael_wintergarden » 21 Dec 2016, 03:00

Hi,

I think I don't really understand you. Maybe I'm wrong, I don't know.
I dont want to embarras you, but to make sure to understand I just want to explain something (I don't know if I'm right):

Wether you use external mode in matlab or not, you always have to generate C-code from your simulink model and upload it to your hardware (simulink is usually doing this automatically if you hit "Build Model").

This means, if you are creating a control-loop in Simulink, you always have to generate C-code of the loop and upload it to your hardware via bootloader (Simulink is doing this for you).
This means, your hardware can also run stand-alone after you uploaded the Simulink-generated C-code.

If you want to see how your control-loop performs, you can run Simulink in "External Mode" this means, you need to connect the USB to your Computer, Upload the Code to the hardware via Simulink and klick "Run" in order to start the code. Now you can see your actuall values etc. inside the Simulink model.
In order to update those values, you need to be in contact with your hardware via usb and this brings a (huge) time-delay with it. But the actual control loop is still running on your hardware and not on Simulink, am I right or wrong with that?

My question: If you run VESC in External Mode (VESC connected to Simulink), will the Control-loop also run slower? I mean the actual control loop is running on the hardware and not inside Simulink, right? Where does it say that it just runs with 0.005 second per cycle?

Here is more about Simulink and External Mode: https://se.mathworks.com/help/supportpk ... -mode.html
There are also some youtube-videos about Simulink and Hardware, e.g.: https://www.youtube.com/watch?v=QrteM1J4s2A

yosoufe
Posts: 50
Joined: 18 Jul 2016, 11:26
Location: USA

Re: VESC and Simulink in windows

Postby yosoufe » 21 Dec 2016, 21:20

What i did here is defferent from what you are describing.

Here the control loop is executed on pc and simulink (if you implement any on simulink).

This block only communicates with the VESC according to usage. You should not use the build button. You should not run the simulation in external mode.

This is a very simple implementation of the UART communication (which benjamin has a tutorial on it) on simulink. Nothing more.

This can be seen as a debugging tab of the bldc tool software, but implemented in simulink.

There is no C code generation and upload to the vesc here. PC sends one of the setter comands (speed, current or...) then sends the get_values command and it receives the values and shows them on output. All these communication is via usb, or serial (UART). There is also another s-function inside, which slows down the execution as close as to the real-time.

There is no need of program upload to VESC here. I hope now it is more clear.

yosoufe
Posts: 50
Joined: 18 Jul 2016, 11:26
Location: USA

Re: VESC and Simulink in windows

Postby yosoufe » 02 Jan 2018, 15:58

I just made it with more outputs. the same block. has anybody used it at all? I would be grateful for a feedback
Attachments
library.zip
(114.26 KiB) Downloaded 63 times

robertoquintal
Posts: 4
Joined: 08 Oct 2018, 12:27
Location: Poland

Re: VESC and Simulink in windows

Postby robertoquintal » 08 Oct 2018, 12:44

Hello Yosoufe,

nice S-Function, thanks a lot, although I have an issue with the values. I am using the VESC tool 0.87 to program my VESC and when I use your S-Funtion some of the values are not communicating correctly (see the attached screenshot)
For example the speed is "scaled" because I input a triangular signal from 3000 to 6000 erpm and I read very big values
And no battery voltage reading.

Thank you in advance for your help

Best Regards
Image

yosoufe
Posts: 50
Joined: 18 Jul 2016, 11:26
Location: USA

Re: VESC and Simulink in windows

Postby yosoufe » 08 Oct 2018, 16:36

robertoquintal wrote:Hello Yosoufe,

nice S-Function, thanks a lot, although I have an issue with the values. I am using the VESC tool 0.87 to program my VESC and when I use your S-Funtion some of the values are not communicating correctly (see the attached screenshot)
For example the speed is "scaled" because I input a triangular signal from 3000 to 6000 erpm and I read very big values
And no battery voltage reading.

Thank you in advance for your help

Best Regards
Image

Hi,
Thank you

The new VESC is outputting different stuff in different orders. Therefore it is needed to change the code. Currently I do not have access to VESC and unfortunately do not have time to change the code.

You have to go to the VESC code about the serial communication and check the new sequences of data. and then go to the VESC Simulink code and change the code to match the sequence of data that the VESC is sending through the serial bus.

Probably you need to change the following in data_types.h

Code: Select all

typedef struct {
   float v_in;
   float temp_mos1;
   float temp_mos2;
   float temp_mos3;
   float temp_mos4;
    float temp_mos5;
    float temp_mos6;
    float temp_pcb;
    float current_motor;
    float current_in;
    float rpm;
    float duty_now;
    float amp_hours;
    float amp_hours_charged;
    float watt_hours;
    float watt_hours_charged;
    int32_t tachometer;
    int tachometer_abs;
    mc_fault_code fault_code;
} mc_values

in BLDC_uart.cpp

Code: Select all

   case COMM_GET_VALUES:
      ind = 0;
      values.temp_mos1 = buffer_get_float16(data, 10.0, &ind);
      values.temp_mos2 = buffer_get_float16(data, 10.0, &ind);
      values.temp_mos3 = buffer_get_float16(data, 10.0, &ind);
      values.temp_mos4 = buffer_get_float16(data, 10.0, &ind);
      values.temp_mos5 = buffer_get_float16(data, 10.0, &ind);
      values.temp_mos6 = buffer_get_float16(data, 10.0, &ind);
      values.temp_pcb = buffer_get_float16(data, 10.0, &ind);
      values.current_motor = buffer_get_float32(data, 100.0, &ind);
      values.current_in = buffer_get_float32(data, 100.0, &ind);
      values.duty_now = buffer_get_float16(data, 1000.0, &ind);
      values.rpm = buffer_get_float32(data, 1.0, &ind);
      values.v_in = buffer_get_float16(data, 10.0, &ind);
      values.amp_hours = buffer_get_float32(data, 10000.0, &ind);
      values.amp_hours_charged = buffer_get_float32(data, 10000.0, &ind);
      values.watt_hours = buffer_get_float32(data, 10000.0, &ind);
      values.watt_hours_charged = buffer_get_float32(data, 10000.0, &ind);
      values.tachometer = buffer_get_int32(data, &ind);
      values.tachometer_abs = buffer_get_int32(data, &ind);
      values.fault_code = (mc_fault_code)data[ind++];

and in VESC.cpp

Code: Select all

static void mdlOutputs(SimStruct *S, int_T tid)
{
    //ssPrintf("mdlOutputs--");
   BLDC_uart      *motor =         (BLDC_uart *)ssGetPWork(S)[0];
    double         *ERPM =            (double*)ssGetOutputPortSignal(S,0);
    double         *Battery_voltage =   (double*)ssGetOutputPortSignal(S,1);
    double         *Battery_current =   (double*)ssGetOutputPortSignal(S,2);
   double         *Phase_current =   (double*)ssGetOutputPortSignal(S,3);
   double         *FET_temperature =   (double*)ssGetOutputPortSignal(S,4);
   double         *Duty_Cycle =      (double*)ssGetOutputPortSignal(S,5);
   
    double          *temp_pcb   =       (double*)ssGetOutputPortSignal(S,6);
    double          *amp_hours  =       (double*)ssGetOutputPortSignal(S,7);
    double          *amp_hours_charged =(double*)ssGetOutputPortSignal(S,8);
    double          *watt_hours =       (double*)ssGetOutputPortSignal(S,9);
    double          *watt_hours_charged=(double*)ssGetOutputPortSignal(S,10);
    int             *tachometer =       (int*)ssGetOutputPortSignal(S,11);
    int             *tachometer_abs =   (int*)ssGetOutputPortSignal(S,12);
    int             *fault_code =       (int*)ssGetOutputPortSignal(S,13);
   
    //int operation_mode = ssGetIWorkValue(S,0);
   motor->bldc_interface_get_values();
   motor->process_response();
   
   mc_values vals      = motor->get_values();
   *ERPM            = vals.rpm;
   *Battery_voltage   = vals.v_in;
   *Battery_current   = vals.current_in;
   *Phase_current      = vals.current_motor;
   *FET_temperature   = vals.temp_mos1;
   *Duty_Cycle         = vals.duty_now;
    *temp_pcb           = vals.temp_pcb;
    *amp_hours          = vals.amp_hours;
    *amp_hours_charged  = vals.amp_hours_charged;
    *watt_hours         = vals.watt_hours;
    *watt_hours_charged = vals.watt_hours_charged;
    *tachometer         = vals.tachometer;
    *tachometer_abs     = vals.tachometer_abs;
    *fault_code         = (int)vals.fault_code;
   UNUSED_ARG(tid);
}

robertoquintal
Posts: 4
Joined: 08 Oct 2018, 12:27
Location: Poland

Re: VESC and Simulink in windows

Postby robertoquintal » 09 Oct 2018, 15:56

Hello again Yosoufe,

thanks for the reply,
so I was checking the UART protocol of the firmware the VESC Tool 0.87 installed to my VESC: Firmware Version 3.34, Hardware: 410
And I noticed in the Github that there are some differences since 2016, still I wonder if I found the correct order of packets because I don't seem to find the rpm which some how appeared (uncorrectly displayed) in my last post.
The Github code I am referring to is: https://github.com/vedderb/bldc/blob/43 ... nds.c#L164

And this is the part I think is associated to the structure, side to side with the BLDC_uart.cpp your S-Function uses:
Image

yosoufe
Posts: 50
Joined: 18 Jul 2016, 11:26
Location: USA

Re: VESC and Simulink in windows

Postby yosoufe » 09 Oct 2018, 16:09

robertoquintal wrote:Hello again Yosoufe,

thanks for the reply,
so I was checking the UART protocol of the firmware the VESC Tool 0.87 installed to my VESC: Firmware Version 3.34, Hardware: 410
And I noticed in the Github that there are some differences since 2016, still I wonder if I found the correct order of packets because I don't seem to find the rpm which some how appeared (uncorrectly displayed) in my last post.
The Github code I am referring to is: https://github.com/vedderb/bldc/blob/43 ... nds.c#L164

And this is the part I think is associated to the structure, side to side with the BLDC_uart.cpp your S-Function uses:
Image

Hi

I don't get your question.

If you see in the vesc code, now it sends in this order: fet temp, motor temp and so on
but in my simulink code it reads in this order: fet1 temp, fet2 temp and so on

If one of these is wrong, it is going to corrupt all the others after that. So you have to change simulink code to match exact order of what VESC sends.

robertoquintal
Posts: 4
Joined: 08 Oct 2018, 12:27
Location: Poland

Re: VESC and Simulink in windows

Postby robertoquintal » 10 Oct 2018, 10:43

Hi Yosoufe,

so I finally understood the order of the data package in the new Frimware. I made the changes in the three files (datatypes.h, BLDC_uart.cpp and VESC.cpp) but I am having trouble compiling the mex file (with the new outputs for id and iq, no pcb temp)

Changes in datatypes.h :

Code: Select all

typedef struct {
   float v_in;
   float temp_mos1;
   //float temp_mos2;
   //float temp_mos3;
   //float temp_mos4;
       //float temp_mos5;
       //float temp_mos6;
       //float temp_pcb;
       float current_motor;
       float current_in;
   float id; //new
   float iq; //new
       float rpm;
       float duty_now;
       float amp_hours;
       float amp_hours_charged;
       float watt_hours;
       float watt_hours_charged;
       int32_t tachometer;
       int tachometer_abs;
       mc_fault_code fault_code;
} mc_values;


Changes in BLDC_uart.cpp :

Code: Select all

case COMM_GET_VALUES:
      ind = 0;
      values.temp_mos1 = buffer_get_float16(data, 10.0, &ind);
      //values.temp_mos2 = buffer_get_float16(data, 10.0, &ind);
      //values.temp_mos3 = buffer_get_float16(data, 10.0, &ind);
      //values.temp_mos4 = buffer_get_float16(data, 10.0, &ind);
      //values.temp_mos5 = buffer_get_float16(data, 10.0, &ind);
      //values.temp_mos6 = buffer_get_float16(data, 10.0, &ind);
      //values.temp_pcb = buffer_get_float16(data, 10.0, &ind);
      values.current_motor = buffer_get_float32(data, 100.0, &ind);
      values.current_in = buffer_get_float32(data, 100.0, &ind);
      values.id = buffer_get_float32(data, 100.0, &ind); //new
      values.iq = buffer_get_float32(data, 100.0, &ind); //new
      values.duty_now = buffer_get_float16(data, 1000.0, &ind);
      values.rpm = buffer_get_float32(data, 1.0, &ind);
      values.v_in = buffer_get_float16(data, 10.0, &ind);
      values.amp_hours = buffer_get_float32(data, 10000.0, &ind);
      values.amp_hours_charged = buffer_get_float32(data, 10000.0, &ind);
      values.watt_hours = buffer_get_float32(data, 10000.0, &ind);
      values.watt_hours_charged = buffer_get_float32(data, 10000.0, &ind);
      values.tachometer = buffer_get_int32(data, &ind);
      values.tachometer_abs = buffer_get_int32(data, &ind);
      values.fault_code = (mc_fault_code)data[ind++];
      //values.pid_pos_now = buffer_get_float32(data, 1e6, &ind); //new maybe not necessary
      //values.configuration = (controller_id)data[ind++]; //new maybe not neccesary
      /*
      if (rx_value_func) {
      rx_value_func(&values);
      }
      */
      break;


And changes in VESC.cpp :

Code: Select all

if (!ssSetNumOutputPorts(S, 15)) return;
       ssSetOutputPortWidth(S, 0, 1);
   ssSetOutputPortWidth(S, 1, 1);
   ssSetOutputPortWidth(S, 2, 1);
   ssSetOutputPortWidth(S, 3, 1);
   ssSetOutputPortWidth(S, 4, 1);
   ssSetOutputPortWidth(S, 5, 1);
       ssSetOutputPortWidth(S, 6, 1); //new
       ssSetOutputPortWidth(S, 7, 1); //new
       ssSetOutputPortWidth(S, 8, 1);
       ssSetOutputPortWidth(S, 9, 1);
       ssSetOutputPortWidth(S, 10, 1);
       ssSetOutputPortWidth(S, 11, 1);
       ssSetOutputPortWidth(S, 12, 1);
       ssSetOutputPortWidth(S, 13, 1);
   ssSetOutputPortWidth(S, 14, 1);
   
    // set the input data type to 3=unit8, 0=double, 6=int32
       ssSetOutputPortDataType(S,0,0);
   ssSetOutputPortDataType(S, 1, 0);
   ssSetOutputPortDataType(S, 2, 0);
   ssSetOutputPortDataType(S, 3, 0);
   ssSetOutputPortDataType(S, 4, 0);
   ssSetOutputPortDataType(S, 5, 0);
       ssSetOutputPortDataType(S, 6, 0); //new
       ssSetOutputPortDataType(S, 7, 0); //new
       ssSetOutputPortDataType(S, 8, 0);
       ssSetOutputPortDataType(S, 9, 0);
       ssSetOutputPortDataType(S, 10, 0);
   ssSetOutputPortDataType(S, 11, 0);
   ssSetOutputPortDataType(S, 12, 6);
       ssSetOutputPortDataType(S, 13, 6);
       ssSetOutputPortDataType(S, 14, 6);


Also in VESC.cpp :

Code: Select all

static void mdlOutputs(SimStruct *S, int_T tid)
{
    //ssPrintf("mdlOutputs--");
   BLDC_uart      *motor =         (BLDC_uart *)ssGetPWork(S)[0];
    double         *ERPM =            (double*)ssGetOutputPortSignal(S,0);
    double         *Battery_voltage =   (double*)ssGetOutputPortSignal(S,1);
    double         *Battery_current =   (double*)ssGetOutputPortSignal(S,2);
   double         *Phase_current =   (double*)ssGetOutputPortSignal(S,3);
   double         *FET_temperature =   (double*)ssGetOutputPortSignal(S,4);
   double         *Duty_Cycle =      (double*)ssGetOutputPortSignal(S,5);
   
    //double          *temp_pcb   =       (double*)ssGetOutputPortSignal(S,6);
   double          *id = (double*)ssGetOutputPortSignal(S,6);
   double          *iq = (double*)ssGetOutputPortSignal(S,7);
    double          *amp_hours  =       (double*)ssGetOutputPortSignal(S,8);
    double          *amp_hours_charged =(double*)ssGetOutputPortSignal(S,9);
    double          *watt_hours =       (double*)ssGetOutputPortSignal(S,10);
    double          *watt_hours_charged=(double*)ssGetOutputPortSignal(S,11);
    int             *tachometer =       (int*)ssGetOutputPortSignal(S,12);
    int             *tachometer_abs =   (int*)ssGetOutputPortSignal(S,13);
    int             *fault_code =       (int*)ssGetOutputPortSignal(S,14);
   
    //int operation_mode = ssGetIWorkValue(S,0);
   motor->bldc_interface_get_values();
   motor->process_response();
   
   mc_values vals      = motor->get_values();
   *ERPM         = vals.rpm;
   *Battery_voltage   = vals.v_in;
   *Battery_current   = vals.current_in;
   *Phase_current      = vals.current_motor;
   *FET_temperature   = vals.temp_mos1;
   *Duty_Cycle      = vals.duty_now;
       //*temp_pcb           = vals.temp_pcb;
        *id             = vals.id;
        *iq             = vals.iq;
       *amp_hours          = vals.amp_hours;
       *amp_hours_charged  = vals.amp_hours_charged;
       *watt_hours         = vals.watt_hours;
       *watt_hours_charged = vals.watt_hours_charged;
       *tachometer         = vals.tachometer;
       *tachometer_abs     = vals.tachometer_abs;
       *fault_code         = (int)vals.fault_code;
   UNUSED_ARG(tid);
}


As I mentioned the problem now is to compile the S-Function because evethough I downloaded the MinGW-w64 C/C++ Compiler I receive the following message:
Image

Thank you for your time and help with the S-functions

yosoufe
Posts: 50
Joined: 18 Jul 2016, 11:26
Location: USA

Re: VESC and Simulink in windows

Postby yosoufe » 10 Oct 2018, 13:04

You need to name all the files in the mex command, at least the cpp files. like this

Code: Select all

mex VESC.cpp BLDC_uart.cpp buffer.cpp crc.cpp MyUsb.cpp

robertoquintal
Posts: 4
Joined: 08 Oct 2018, 12:27
Location: Poland

Re: VESC and Simulink in windows

Postby robertoquintal » 11 Oct 2018, 12:31

Thank you Yosoufe,

I figured the changes out. Here I attach my version of the S-Function already working for the VESC Tool and Firmware 3.34
Image
Attachments
Simu_VESC_Firmware_3_34.zip
(344.43 KiB) Not downloaded yet


Return to “General”

Who is online

Users browsing this forum: No registered users and 5 guests