Implementing the C Function Call
Implementing the C Function Call
Hello Lubin,
I've been looking at your blockset and it is really amazing. For me being a seasoned PIC and dsPIC programmer, it is just amazing how much leverage your tool gives. Congrats on a great product. One thing I am trying to implement is the QEI, now I've already read that you currently have no plans to suport it, and honestly I would much rather see you devote time to an interrupt driven (virtual buffer) UART, SPI and CAN.
So I think (correct me if I am wrong) that using the C-Fucntion Call shall allow me to completely use the QEI in the following way:
1.- Create a C function to initialize the QEI and call it once when the model starts execution; and,
2.- Create a C function to read the status of the QEI registers (specially POSCNT) and send the data to Simulink to further use it.
So I was wondering if you could post a simple example of the usage of the function call, and I will do the QEI Example and make it available here on the forum for your registered users.
Cheers
Mariano
I've been looking at your blockset and it is really amazing. For me being a seasoned PIC and dsPIC programmer, it is just amazing how much leverage your tool gives. Congrats on a great product. One thing I am trying to implement is the QEI, now I've already read that you currently have no plans to suport it, and honestly I would much rather see you devote time to an interrupt driven (virtual buffer) UART, SPI and CAN.
So I think (correct me if I am wrong) that using the C-Fucntion Call shall allow me to completely use the QEI in the following way:
1.- Create a C function to initialize the QEI and call it once when the model starts execution; and,
2.- Create a C function to read the status of the QEI registers (specially POSCNT) and send the data to Simulink to further use it.
So I was wondering if you could post a simple example of the usage of the function call, and I will do the QEI Example and make it available here on the forum for your registered users.
Cheers
Mariano
Re: Implementing the C Function Call
Hello,
I am working on touching up the example for the QEI. I have a
couple of requests in order to make this happen and I think that it
would overall help make the usage of the C function call block more diverse.
1.- Function prototype: In my previous email I forgot to include one
detail. Sometimes you need to implement an interrupt (like in this
case for the QEI), but as I am sure you know if I implement an
interrupt it has to have a given prototype, which it does not work
since I must adhere to the required prototype by your function call
block.
2.- Interrupts sometimes require access to a global variable,
generally a switch to indicate something changed. So if you could do a
very simple (I think
) source block that was a global variable,
then, I could change the value inside my interrupt and be done with
it.
I have probably not made myself clear, so I will put the scenario in
front of you and let you decide:
I initialize the QEI with this function:
This is clearly doable using your c function call block
then, every time the QEI overflows or underflows I increment a global
variable that keeps track of the turn count of the motor (i.e. the
motor can do more than one turn). This happens inside an interrupt.
This I can not do it using the c function call block because: 1.- I can not
change the function prototype and 2.- I have no way of declaring from
simulink the global variable ct_turns.
Then I use it n the code to compute the actual position of the motor:
Maybe you can suggest a work around this limitation (maybe adding an
external file from the project properties dialog?) or you can
implement the changes in the block.
I have attached a Simulink model Image of how I see it working inside
simulink if you were to modify/add the suggeted blocks.
Concretely in the C function call, I think it would be great if you
were to provide the following modifications:
1.- A way to override your default function prototype
2.- A way to decide whether it should be called once at the beginning
(which I think you can by setting the sample time to inf), every cycle
(by setting the sample time) or never (like an interrupt which is
called by the microcontroller interrupt engine).
And then provide a small block that declares a global variable (with a
given name) and initializes it a to given value and returns the
current value each sample time.
Also, how do I add the dsPIC library QEI.h? From the project properties dialog?
Sorry for the extra long post, I hope I have made myself clear. I
will try to look for workarounds for this in the mean while.
Thanks Lubin!!
I am working on touching up the example for the QEI. I have a
couple of requests in order to make this happen and I think that it
would overall help make the usage of the C function call block more diverse.
1.- Function prototype: In my previous email I forgot to include one
detail. Sometimes you need to implement an interrupt (like in this
case for the QEI), but as I am sure you know if I implement an
interrupt it has to have a given prototype, which it does not work
since I must adhere to the required prototype by your function call
block.
2.- Interrupts sometimes require access to a global variable,
generally a switch to indicate something changed. So if you could do a
very simple (I think

then, I could change the value inside my interrupt and be done with
it.
I have probably not made myself clear, so I will put the scenario in
front of you and let you decide:
I initialize the QEI with this function:
Code: Select all
void QEIInit(void){
ConfigIntQEI (QEI_INT_ENABLE & // Enable interrupts
QEI_INT_PRI_5); // Set Priority to 5
POSCNT = 0; // Set Current Position to 0
MAXCNT = 0xFFFF; // Use the full 16bit counter
OpenQEI (QEI_DIR_SEL_CNTRL & // UPDN bit decides direction count
QEI_INT_CLK & // Use FCY for clocking
QEI_INDEX_RESET_DISABLE &
QEI_CLK_PRESCALE_1 & // 1:1 Prescale
QEI_GATED_ACC_DISABLE &
QEI_NORMAL_IO & // QEI Control state of IO pin
QEI_INPUTS_NOSWAP & // Channels A and B are not swapped
QEI_MODE_x2_MATCH & // X2 mode with counter reset by match
QEI_UP_COUNT & // Read only for this mode
QEI_IDLE_STOP, // Stop in idle operation
MATCH_INDEX_INPUT_PHASEA &
QEI_QE_CLK_DIVIDE_1_16 &// Filter 1:16 divider
QEI_QE_OUT_ENABLE); // Enable the input digital filter
}
then, every time the QEI overflows or underflows I increment a global
variable that keeps track of the turn count of the motor (i.e. the
motor can do more than one turn). This happens inside an interrupt.
Code: Select all
void __attribute__((__interrupt__, no_auto_psv)) _QEIInterrupt(void){
// if it overflowed
if (ReadQEI() < 0x3FFF){
ct_turns++;
} else {
ct_turns--;
}
// clear the interrupt flag
IFS2bits.QEIIF =0;
}
change the function prototype and 2.- I have no way of declaring from
simulink the global variable ct_turns.
Then I use it n the code to compute the actual position of the motor:
Code: Select all
thePID.y_m = (float)(ct_turns*65535 + POSCNT)*angle_ratio;
//where POSCNT is a register
Maybe you can suggest a work around this limitation (maybe adding an
external file from the project properties dialog?) or you can
implement the changes in the block.
I have attached a Simulink model Image of how I see it working inside
simulink if you were to modify/add the suggeted blocks.
Concretely in the C function call, I think it would be great if you
were to provide the following modifications:
1.- A way to override your default function prototype
2.- A way to decide whether it should be called once at the beginning
(which I think you can by setting the sample time to inf), every cycle
(by setting the sample time) or never (like an interrupt which is
called by the microcontroller interrupt engine).
And then provide a small block that declares a global variable (with a
given name) and initializes it a to given value and returns the
current value each sample time.
Also, how do I add the dsPIC library QEI.h? From the project properties dialog?
Sorry for the extra long post, I hope I have made myself clear. I
will try to look for workarounds for this in the mean while.
Thanks Lubin!!
- Attachments
-
- Suggested Modifications to the C-Function Block and addition of Constant Source
- CFunCallQEI.JPG (44.58 KiB) Viewed 36253 times
Re: Implementing the C Function Call
Hello All,
It is with great pleasure that I give you an example Simulink Model of how to use the C function call to implement the QEI in a dsPIC30F4011. This is proven to work and if anybody has a question feel free to post it. Attached to this are two files: the Simulink model and the C file. Note that if you roll your own you need to add the C file to the Simulink options. The example is fully interrupt driven and supports more than one turns (in any direction of course
)
I guess using the C function call is a great reason to buy any of the registered versions
Hope this is helpful to anyone looking to use the QEI.
It is with great pleasure that I give you an example Simulink Model of how to use the C function call to implement the QEI in a dsPIC30F4011. This is proven to work and if anybody has a question feel free to post it. Attached to this are two files: the Simulink model and the C file. Note that if you roll your own you need to add the C file to the Simulink options. The example is fully interrupt driven and supports more than one turns (in any direction of course

I guess using the C function call is a great reason to buy any of the registered versions

Hope this is helpful to anyone looking to use the QEI.
- Attachments
-
- myQEI.c
- This is the C file. Make sure you add it to your model by: Simulation -> Configuration Parameters -> Custom C code -> Source file
- (2.23 KiB) Downloaded 1565 times
-
- QEITest.mdl
- Using a dsPIC30F4011 at 40MHZ
- (34.99 KiB) Downloaded 1410 times
-
- Site Admin - Expert
- Posts: 616
- Joined: Wed Mar 07, 2007 11:23 pm
- Location: Bayonne- France
- Contact:
Re: Implementing the C Function Call
Hi Mariano,
I was working on this post while you posted your solution.
I keep it there since it was a piece of work.
to resume,
I declared the global variable using a different way. (yours may be better for this example).
I do not like the way you initialize the QEI peripheral. It would make better C code to set its sampling time to inf !
------
It was quite long to make the example; I respond quickly, refer to the example for further details.
You must declare (in the Data Store Memory) the variable as global, assign its name in order to be able to use this variable in your C function written. In your C file, the variable will be declared as external. You must declare the variable with the same datatype.
The following example compile but has not been tested. I don't know if this implementation of QEI function is working. I guess modifications will be required. I hope that the example is not too hard to read.
The model and C file can be download at the end of the post.
I also attached a basic example (the one I sent to you Mariano) that shows how to use different calling method to transfer data between simulink and C functions (using pointer or direct value...this example is not described on this post).
I noticed that some images do not load correctly. It is a strange behaviour of the forum ; I guess there is too many image in this post. Reloading the page seems to gives results... (Press F5)
C file content (Modified versioin of Mariano's proposition):
Considere downloading the QEI implementation from the previous post (realized and tested by Mariano)
I was working on this post while you posted your solution.
I keep it there since it was a piece of work.
to resume,
I declared the global variable using a different way. (yours may be better for this example).
I do not like the way you initialize the QEI peripheral. It would make better C code to set its sampling time to inf !
------
It was quite long to make the example; I respond quickly, refer to the example for further details.
To implement a function that has no "interface" with the model (kind of internal function, like interrupt) . You do not need to use the C function call block. Just add the function in the C file that you declared in the Configuration Parameters dialog box.malife wrote:1.- A way to override your default function prototype
You already have the solution! I think it is better to enter into the simulink logic rather than adding a option for initialization.malife wrote:2.- A way to decide whether it should be called once at the beginning
(which I think you can by setting the sample time to inf), every cycle
(by setting the sample time) or never (like an interrupt which is
called by the microcontroller interrupt engine).
- initialization (call only once at startup) ==> sample time = inf
call ==> sample time = sampling time desired
Interrupt ==> do not need using a C function call block.
It is possible to use block 'Data Store Memory', 'Data Read Memory' and 'Data Write Memory' which are block of the standard simulink library.malife wrote:And then provide a small block that declares a global variable (with a
given name) and initializes it a to given value and returns the
current value each sample time.
You must declare (in the Data Store Memory) the variable as global, assign its name in order to be able to use this variable in your C function written. In your C file, the variable will be declared as external. You must declare the variable with the same datatype.
The following example compile but has not been tested. I don't know if this implementation of QEI function is working. I guess modifications will be required. I hope that the example is not too hard to read.
The model and C file can be download at the end of the post.
I also attached a basic example (the one I sent to you Mariano) that shows how to use different calling method to transfer data between simulink and C functions (using pointer or direct value...this example is not described on this post).
I noticed that some images do not load correctly. It is a strange behaviour of the forum ; I guess there is too many image in this post. Reloading the page seems to gives results... (Press F5)
C file content (Modified versioin of Mariano's proposition):
Code: Select all
#include <p30f4011.h>
#include <qei.h>
/*------------------------------------------------------------------*/
void QEIInit(void){
ConfigIntQEI (QEI_INT_ENABLE & // Enable interrupts
QEI_INT_PRI_5); // Set Priority to 5
POSCNT = 0; // Set Current Position to 0
MAXCNT = 0xFFFF; // Use the full 16bit counter
OpenQEI (QEI_DIR_SEL_CNTRL & // UPDN bit decides direction count
QEI_INT_CLK & // Use FCY for clocking
QEI_INDEX_RESET_DISABLE &
QEI_CLK_PRESCALE_1 & // 1:1 Prescale
QEI_GATED_ACC_DISABLE &
QEI_NORMAL_IO & // QEI Control state of IO pin
QEI_INPUTS_NOSWAP & // Channels A and B are not swapped
QEI_MODE_x2_MATCH & // X2 mode with counter reset by match
QEI_UP_COUNT & // Read only for this mode
QEI_IDLE_STOP, // Stop in idle operation
MATCH_INDEX_INPUT_PHASEA &
QEI_QE_CLK_DIVIDE_1_16 &// Filter 1:16 divider
QEI_QE_OUT_ENABLE); // Enable the input digital filter
}
/*------------------------------------------------------------------*/
long GetQEI()
{
extern volatile unsigned int ct_turns;
return (long) ct_turns * 65535 + POSCNT;
}
/*------------------------------------------------------------------*/
void __attribute__((__interrupt__)) _QEIInterrupt(void)
{
extern volatile unsigned int ct_turns;
// if it overflowed
if (ReadQEI() < 0x3FFF){
ct_turns++;
} else {
ct_turns--;
}
// clear the interrupt flag
IFS2bits.QEIIF =0;
}
Considere downloading the QEI implementation from the previous post (realized and tested by Mariano)
- Attachments
-
- C_functionCall_Example.zip
- Another example to demonstrate different call possiblity for the C function call block. No picture shown here
- (10.39 KiB) Downloaded 1398 times
-
- QEI_CFunction_v02.zip
- QEITest2 model (.mdl file) with the C file "QEI_Functions.c"
- (10.28 KiB) Downloaded 1408 times
Re: Implementing the C Function Call
Great Example Lubin. Thanks for the tip on the ct_turns variable. I find that more elegant than declaring a "ghost" variable from the code since in my example directly from the Simulink Model you can't really see that there is a global variable. Anyways, between the two examples it should be now more than clear how to use the C Function Call. Thanks !
One thing though. I might be mistaken but I think that even if you put for sample time inf on the C Function call, it still is called on every step, at least it was on my case, but maybe I was doing something wrong. I had to import the code to MPLab and using the debugger figure out what was going on. That is why I choose the enabled system approach. Could you confirm that?
Thanks!
Mariano
One thing though. I might be mistaken but I think that even if you put for sample time inf on the C Function call, it still is called on every step, at least it was on my case, but maybe I was doing something wrong. I had to import the code to MPLab and using the debugger figure out what was going on. That is why I choose the enabled system approach. Could you confirm that?
Thanks!
Mariano
-
- Site Admin - Expert
- Posts: 616
- Joined: Wed Mar 07, 2007 11:23 pm
- Location: Bayonne- France
- Contact:
Re: Implementing the C Function Call
Will check that. One advantage to initialize the way you do is that your initialization is last (not erased by the "standard initialisation code)
However, I noticed a possible bug on the file myQEI.c, in the initialisation function :
about the ADPCFG and TRISB register, ONLY the concerned bit used by the peripheral QEI should be modified (when required). Modifying the whole register could erase configuration of other peripheral.
considere using binary mask (It is done in the comment I guess )
Lubin
However, I noticed a possible bug on the file myQEI.c, in the initialisation function :
Code: Select all
void QEIInit(void)
{
// Configure I/O Ports
ADPCFG = 0xFFFF; //ADPCFG | 0x0030; // Disable the A/D pins 4 and 5
TRISB = 0xFFFF; //TRISB | 0x0030; // configure pins 4 and 5 as inputs
...
considere using binary mask (It is done in the comment I guess )
Lubin
Who is online
Users browsing this forum: No registered users and 23 guests