Adding a C++ library to C code (Simulink S-function)

Hey guys,

I’m doing a project related to real-time control of an electromechanical model. I’m using Arduino Due and programming it with Simulink. Inside my Simulink model, I basically have an S-function Builder block into which I paste code that I previously tested out in the Arduino IDE.

Now, I wrote a piece of code to handle the reading of two optical encoders using interrupts. It compiles and works fine but sometimes it’s not fast enough to keep up with the encoders’ speeds. So I googled around and found this great library: Encoder Library, for Measuring Quadarature Encoded Position or Rotation Signals. I tried it out in the Arduino IDE and after some testing, it seems it’s much better than my previous code, since no encoder ticks were lost even at high rotation speeds. I’d love to use it in my Simulink project. This is the code I used in Arduino IDE:

/* Encoder Library - TwoKnobs Example
 * http://www.pjrc.com/teensy/td_libs_Encoder.html
 *
 * This example code is in the public domain.
 */

#include <Encoder.h>

Encoder knobLeft(2,3);
Encoder knobRight(4,5);

void setup()
{
  Serial.begin(9600);
  Serial.println("TwoKnobs Encoder Test:");
}

long positionLeft  = -999;
long positionRight = -999;

void loop()
{
  long newLeft, newRight;
  newLeft = knobLeft.read();
  newRight = knobRight.read();
  if (newLeft != positionLeft || newRight != positionRight) {
    Serial.print("Left = ");
    Serial.print(newLeft);
    Serial.print(", Right = ");
    Serial.print(newRight);
    Serial.println();
    positionLeft = newLeft;
    positionRight = newRight;
  }
}

Here comes the confusing part. I modified the code a little bit and pasted it into my S-function Builder block in Simulink like this:

“Libraries” pane:

# ifndef MATLAB_MEX_FILE

# include <Arduino.h>
# include <Encoder.h>

Encoder knobLeft(2,3);
Encoder knobRight(4,5);

long positionLeft  = -999;
long positionRight = -999;

# endif

“Outputs” pane:

/* wait until after initialization is done */
if (xD[0] == 1) {
    
    /* don't do anything for mex file generation */
    # ifndef MATLAB_MEX_FILE
            
        long newLeft, newRight;
        newLeft = knobLeft.read();
        newRight = knobRight.read();
        if (newLeft != positionLeft || newRight != positionRight)
        {
            pos1[0] = newLeft;
            pos2[0] = newRight;

            positionLeft = newLeft;
            positionRight = newRight;
        }

    # endif
    
}

I know, this is not a Simulink forum but the problem is not Simulink-specific. You might as well ignore the above code and the little overhead I needed to add.

The problem is specifically that I get the following compile error (I omitted a long list of include dirs):

The build failed with the following message: "C:/MATLAB/SupportPackages/R2015a/arduino-1.5.6-r2/hardware/tools/g++_arm_none_eabi/bin/arm-none-eabi-gcc" [a very long list of -I include directories] -c -g -Os -w -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -mcpu=cortex-m3 -mthumb -I. -D"MODEL=encoder_slsp" -D"NUMST=1" -D"NCSTATES=0" -D"HAVESTDIO=" -D"ON_TARGET_WAIT_FOR_START=1" -D"ONESTEPFCN=0" -D"EXT_MODE=1" -D"TERMFCN=1" -D"MAT_FILE=0" -D"MULTI_INSTANCE_CODE=0" -D"INTEGER_CODE=0" -D"MT=0" -D"CLASSIC_INTERFACE=0" -D"ALLOCATIONFCN=0" -D"TID01EQ=0" -D"printf=iprintf" -D"F_CPU=84000000" -D"_RUNONTARGETHARDWARE_BUILD_=" -D"_ROTH_DUE_=" -D"ARDUINO=156" -D"ARDUINO_SAM_DUE=" -D"ARDUINO_ARCH_SAM=" -D"__SAM3X8E__=" -D"USB_PID=0x003e" -D"USB_VID=0x2341" -D"USBCON=" -D"_RTT_NUMSERVOS_=0" -D"_RTT_SINGLE_TASKING_MODE_=" -D"EXIT_FAILURE=1" -D"EXTMODE_DISABLEPRINTF=" -D"EXTMODE_DISABLETESTING=" -D"EXTMODE_DISABLE_ARGS_PROCESSING=1"  ./IPAddress.cpp ./Print.cpp ./Reset.cpp ./RingBuffer.cpp ./Stream.cpp ./UARTClass.cpp ./USARTClass.cpp ./CDC.cpp ./HID.cpp ./USBCore.cpp ./WInterrupts.c ./WMath.cpp ./WString.cpp ./cortex_handlers.c ./cxxabi-compat.cpp ./hooks.c ./iar_calls_sam3.c ./itoa.c ./syscalls_sam3.c ./wiring.c ./wiring_analog.c ./wiring_digital.c ./wiring_pulse.cpp ./wiring_shift.c ./variant.cpp ./io_wrappers.cpp ./TimerTickScheduler.c ./arm_cortex_m_multitasking.c ./rtiostream_serial.cpp ./encoder_slsp.c ./encoder_slsp_data.c ./ert_main.c ./sfcn_encoder_wrapper.c ./ext_svr.c ./ext_work.c ./updown.c ./ext_serial_pkt.c ./ext_svr_serial_transport.c ./rtiostream_serial_interface.c ./rtiostream_utils.c
In file included from ./sfcn_encoder_wrapper.c:18:
D:/test/Encoder.h:69: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'Encoder'
./sfcn_encoder_wrapper.c:20: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'knobLeft'
./sfcn_encoder_wrapper.c:21: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'knobRight'
./sfcn_encoder_wrapper.c: In function 'sfcn_encoder_Outputs_wrapper':
./sfcn_encoder_wrapper.c:59: error: 'knobLeft' undeclared (first use in this function)
./sfcn_encoder_wrapper.c:59: error: (Each undeclared identifier is reported only once
./sfcn_encoder_wrapper.c:59: error: for each function it appears in.)
./sfcn_encoder_wrapper.c:60: error: 'knobRight' undeclared (first use in this function)
cs-make: *** [IPAddress.o] Error 1

By taking a closer look at the pointed lines, we can see the following:
Encoder.h

67 } Encoder_internal_state_t;
68 
69 class Encoder
70 {
71 public:
70	Encoder(uint8_t pin1, uint8_t pin2) {

sfcn_encoder_wrapper.c

20 Encoder knobLeft(2,3);
21 Encoder knobRight(4,5);
(...)
59 newLeft = knobLeft.read();
60 newRight = knobRight.read();

So I tried Googling again and found out that this might be caused by the fact that it’s trying to include an incompatible C++ library into a C program. It’s very frustrating to see code that runs perfectly in the IDE while it doesn’t even compile outside it.

Can you share any ideas on how to make this work? Any simple way to convert or incorporate the Encoder class into C code? :frowning:

Hi,
watch this video: How to integrate Arduino Libraries with Matlab Simulink? - YouTube
There is a method that probably help you.