How to fix number of steps (not time) in Matlab simulink - matlab

This may be a simple question.But I couldn't find a way to go around this.I am using an s function block to input a wave signal to my algorithm.wave signal is being read from file of about 2000 points
First i started with simulation time equal to 50.Then it read only 50 points.I checked the 'tout' variable. It was 0,1,2,....50
Then i increased simulation time to 100.still result is same.only 50 points read.But tout is 0,2,4,6..50
I tried up to 10000.Whatever i do it reads 50 values only with wide time step like 0,200,400,600 etc.
Is it a problem with my s-function or simulink settings?
Here is the c s-function file
/* Give S-function a name */
#define S_FUNCTION_NAME Readip
#define S_FUNCTION_LEVEL 2
/* Include SimStruct definition and file I/O functions */
#include "simstruc.h"
#include <stdio.h>
#include <stdlib.h>
static FILE* file2;
/* Called at the beginning of the simulation */
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumSFcnParams(S, 0);
if (ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S)) {
return;
}
if (!ssSetNumOutputPorts(S, 3)) return;
ssSetNumContStates(S, 0);
ssSetNumDiscStates(S, 0);
ssSetOutputPortWidth(S, 0, 1);
ssSetOutputPortDataType(S,0,DYNAMICALLY_SIZED);
ssSetOutputPortOptimOpts(S, 0, SS_REUSABLE_AND_LOCAL);
ssSetOutputPortWidth(S, 1, 1);
ssSetOutputPortDataType(S,1,DYNAMICALLY_SIZED);
ssSetOutputPortOptimOpts(S, 1, SS_REUSABLE_AND_LOCAL);
ssSetOutputPortWidth(S, 2, 1);
ssSetOutputPortDataType(S,2,DYNAMICALLY_SIZED);
ssSetOutputPortOptimOpts(S, 2, SS_REUSABLE_AND_LOCAL);
ssSetNumPWork(S,1);
ssSetNumSampleTimes(S, 1);
}
/* Set sample times for the block */
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
}
#define MDL_START /* Change to #undef to remove function */
#if defined(MDL_START)
/* Function: mdlStart ========
===============================================
* Abstract:
* This function is called once at start of model execution. If you
* have states that shou
ld be initialized once, this is the place
* to do it.
*/
static void mdlStart(SimStruct *S)
{
/*at start of model execution, open the file and store the pointer
*in the pwork vector */
void** pwork = ssGetPWork(S);
FILE *datafile;
datafile = fopen("table.data","r");
pwork[0] = datafile;
}
#endif /* MDL_START */
/* Function: mdlOutputs =======================================================
* Abstract:
* In this function, you compute the outputs of your S-function
* block. Generally outputs are placed in the output vector, ssGetY(S).
*/
static void mdlOutputs(SimStruct *S, int_T tid)
{
//get pointer to the block's output signal
real_T *y1 = ssGetOutputPortSignal(S,0);
real_T *y2 = ssGetOutputPortSignal(S,1);
real_T *y3 = ssGetOutputPortSignal(S,2);
char a[10];
char b[10];
char c[10];
/*get pointer to array of pointers, where the first element is the address
*of the open file */
void** pwork = ssGetPWork(S);
/*read a floating point number and then the comma delimiter
*store the result in y*/
fscanf(pwork[0],"%s %s %s",&a,&b,&c);
*y1=atof(a);
*y2=atof(b);
*y3=atof(c);
}
/* Function: mdlTerminate =====================================================
* Abstract:
* In this function, you should perform any actions that are necessary
* at the termination of a simulation. For example, if memory was
* allocated in mdlStart, this is the place to free it.
*/
static void mdlTerminate(SimStruct *S)
{
//close the file
void** pwork = ssGetPWork(S);
FILE *datafile;
datafile = pwork[0];
fclose(datafile);
}
/*=============================*
* Required S-function trailer *
*=============================*/
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
#include "simulink.c" /* MEX-file interface mechanism */
#else
#include "cg_sfun.h" /* Code generation registration function */
#endif

This appears to just be a settings issue. If you do not specify a step-size for your solver and your blocks do not indicate sample time, Simulink will choose a default of Simulation Time / 50. Simply open the Model Configuration Parameters dialog and click on solvers in the left-hand pane. If you are using a fixed-step solver, you can explicitly set the step size. If you are using a variable-step solver, you can specify the max/min step sizes.
Additionally, if you are looking to specify a discrete sample period specifically for your S-function, then you may want to look in to this link to be sure that you are implementing mdlInitializeSampleTimes as desired.

You need to use the fixed step discrete solver.
Set Periodic sample time constraint to 'Unconstrined'
Enter the Fixed-step size and Simulation Stop time so that you get 2000 steps.
For example 1s/step and 2000s stop time, or 0.1s/step and 200s stop time.

Related

Using STM32 FMC HAL driver with parallel DAC

Im trying to generate sinusoidal signal with STM32f767 and DAC8412. DAC have 12 bit data bus and 2 bit address to select one of the four analog outputs. I've configuried FMC in CubeIDE for a SRAM memory with 16 bit data and 2 bit addres. I was able to create buffer with 4096 integer values of sin(). Then i've tried to write them to addres 0x60000000, but it only writes 4 values. After that, program goes to HardFault_Handler().
#define SRAM_BANK_ADDR ((uint32_t)0x60000000)
#define RESOLUTION_T ((uint32_t)0x1000)
#define RESOLUTION_Y ((uint32_t)0x1000)
uint32_t aTxBuffer[RESOLUTION_T];
uint32_t address = SRAM_BANK_ADDR;
Thats how i try to send data to DAC:
for (uint32_t i = 0; i<RESOLUTION_T; i++ )
{
*(__IO uint32_t*) address = aTxBuffer[i];
}
Thats how i fill buffer:
static void Fill_Buffer(uint32_t *pBuffer, uint32_t res_T, uint32_t res_Y)
{
uint32_t tmpIndex = 0;
double sinVal;
/* Put in global buffer different values */
for (tmpIndex = 0; tmpIndex < res_T; tmpIndex++ )
{
sinVal = round((sin(M_TWOPI*tmpIndex/res_T)+1)*res_Y/2);
pBuffer[tmpIndex] = sinVal;
}
}

Is there any difference between declaring #param[in] and #param (without [in]) in C libraries?

Add info to question:
I'm very new writting this kind of descriptions for my functions.
I can't see any difference between declare function variables description in the library (anylib.h) like
#ifndef MYLIB_H
# define MYLIB_H
/**
* My function description.
*
* #param[in] x Mtrx size x.
* #param[in] y Mtrx size y.
*
* #return Result.
*/
int *my_function(int x, int y);
#endif
(Sorry if image is an url instead image, is because low reputation)
VSCode showing function description in file.c using #param[in]
or declare like
#ifndef MYLIB_H
# define MYLIB_H
/**
* My function description.
*
* #param x Mtrx size x.
* #param y Mtrx size y.
*
* #return Result.
*/
int *my_function(int x, int y);
#endif
VSCode showing function description in file.c using #param
The library is included with -I ( i ) flag
INC = -I include -I ./mylibdir/ -I ./inc/anotherdir/
...
$(OBJDIR)%.o:$(SRCDIR)%.c
#$(CC) $(CFLAGS) $(INC) -o $# -c $<
...
Here I call the function. The path to my lib is no necessary, only the name
#include "mylib.h"
int main(int argc, char *argv[])
{
int a = 3;
int b = 2;
printf("my function result: %i", my_function(a, b));
}
Exist a difference between this?
pd: I dont know the version of Dox. Im in my college mac computer, and i know i have some depracated software versions, idk if its the case

Calibrating STM32 ADC (VREFINT)

I'm trying to read VDDA on an STM32F042 microcontroller. I'm getting unexpected results with VDD at 3.29V. I must be missing something fundamental.
output:
VREFINT=1917; VREFINT_CAL=1524; VDDA=2623 mV
VREFINT=1885; VREFINT_CAL=1524; VDDA=2668 mV
VREFINT=1913; VREFINT_CAL=1524; VDDA=2628 mV
VREFINT=1917; VREFINT_CAL=1524; VDDA=2623 mV
VREFINT=1917; VREFINT_CAL=1524; VDDA=2623 mV
adc_test.c:
#include <stdio.h>
#include "stm32f0xx.h"
#define VREFINT_CAL_ADDR 0x1FFFF7BA /* datasheet p. 19 */
#define VREFINT_CAL ((uint16_t*) VREFINT_CAL_ADDR)
extern void initialise_monitor_handles(void);
int main(void)
{
RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; /* enable ADC peripheral clock */
RCC->CR2 |= RCC_CR2_HSI14ON; /* start ADC HSI */
while (!(RCC->CR2 & RCC_CR2_HSI14RDY)); /* wait for completion */
/* calibration */
ADC1->CR |= ADC_CR_ADCAL; /* start ADc CALibration */
while (ADC1->CR & ADC_CR_ADCAL); /* wait for completion */
ADC1->CR |= ADC_CR_ADEN; /* ADc ENable */
while (!(ADC1->ISR & ADC_ISR_ADRDY)); /* wait for completion */
ADC1->SMPR |= ADC_SMPR1_SMPR_0 | /* sampling mode: longest */
ADC_SMPR1_SMPR_1 |
ADC_SMPR1_SMPR_2;
/* VDD reference */
ADC->CCR |= ADC_CCR_VREFEN; /* VREF Enable */
ADC1->CHSELR = ADC_CHSELR_CHSEL17; /* CH17 = VREFINT */
initialise_monitor_handles(); /* enable semihosting */
while (1) {
ADC1->CR |= ADC_CR_ADSTART; /* start ADC conversion */
while (!(ADC1->ISR & ADC_ISR_EOC)); /* wait for completion */
uint32_t vdda = 3300UL * *VREFINT_CAL / ADC1->DR; /* ref. manual p. 252; constant and result in millivolts */
printf("VREFINT=%lu; VREFINT_CAL=%lu; VDDA=%lu mV\n",
(unsigned long)ADC1->DR,
(unsigned long)*VREFINT_CAL,
(unsigned long)vdda);
}
}
Screenshot from Datasheet:
Screenshot from Reference Manual
note this refers to .3V, but I believe this to be a typo, as the datasheet above and the longer formula below refer to 3.3V, and .3V is below minimum operating voltage for this part
I'm currently developing an ADC driver for STM32L4. During implementation I encounter almost the same problem. In my opinion the first formula
is not calculating the VDDA, but VREF+. It's the voltage against which the ADC is evaluating the ADC-IN channels.
Further the VREFINT_DATA is not measured VREF+ voltage, but an internal reference voltage which is controller dependent. In my case it defined in controller datasheet:
Here's a pic how I am using the posted formulas:
Some comments:
ln 102: calculating VREF+ not VDDA
ln 105-110: calculate all ranks/configured sequence
ln 108: calculate voltage measured by ADCpin_x
ln 109: multiply by gain to get real value
In my opinion by calculating the VREF+ for each conversion sequence, I'll get better results, because so some ripples on VREF+ are compensated.
as #Artur said Vref + is not Vdda, but usually (that's how I have it in my hardware design) Vref + is connected to Vdda (with the corresponding filters according to the datasheet), so calculating Vdda is the same as calculating Vref +.
I will show you how to calculate vdda, as I have it based on the STM32L431.
. You must first configure the ADC to measure VREFINT:
void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_VREFINT;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC1_Init 2 */
/* USER CODE END ADC1_Init 2 */
}
. Now I will show you the code where the equation is executed:
vdda = 3.0 * (VREFINT_CAL /average);
vch = VREF * (average / ADC_RESOLUTION);
log("vdd = %.5f - ", vdda);
log("vchn = %.5f", vch);
where:
#define ADC_RESOLUTION 4095.0 // adc resolution 12 bits
#define VREFINT_CAL 1655.00 // Raw data acquired at a temperature of 30 °C (± 5 °C), VDDA = VREF+ = 3.0 V (± 10 mV)
#define VREF 3.3 // voltage reference 3.3V
note:
'average' is an average of 256 samples taken by the adc (it's just a simple filter).
'log' is a function created by me similar to printf for the uart.
'VREFINT_CAL' varies according to the model.
result:
vdd = 3.28035 - vchn = 1.21343
as we see VREFINT matches the datasheet (1.212V typ.):
VREFINT
Actually it is calculating Vdda, since the Vref calculation is very simple, you have to read the corresponding channel of the ADC with a sample time longer than the one marked in the data sheet (usually 10 us). If Vdda is 2.0 V, a value of 4095 corresponds to 2.0 (or more) V absolute (related GND). In a linear way, the value of Vref will be much higher than if it is read with Vdda = 3.30 V. Therefore, the compensation of the values ​​read with 2.0 V is necessary to know the absolute values ​​of voltage that the ADC is measuring. If they are not compensated, they will be values ​​relative to the voltage level that Vdda has at that moment.
In addition, the power supply value is achieved, which will be useful in order not to go beyond the specifications of the microcontroller.
The answer (big thanks to #jasonharper) is a missing ground connection. Jason't comments on the OP are the best source of wisdom in this thread. I post a summary here so this question can have an accepted answer.
The board went through a number of revisions and in this iteration we forgot to connect the thermal pad, which on this part is the only ground connection. The chip was getting ground through ESD diodes on pins that were connected to ground. It's surprising to me that it worked at all. I was able to increase the current to the chip by configuring grounded GPIOs as outputs and setting them low.

FreeRTOS getting the current time

I have code that runs with FreeRTOS and I want to edit it,
its a code that measure the pressure and the temperature, and I want to have the time when these measures are token.
Could anyone tell me how to get the current time in my machine or the date?
Thank you.
This is the code that I am using right now.
//#include <stdio.h>
//#include <stdlib.h>
#include <stdint.h>
#include <math.h>
#include "platform.h"
#include "printf.h"
#include "lps331ap.h"
static void app_task(void *);
int main(int argc, char *argv[])
{
// Initialize the platform
platform_init();
// Create a task for the application
xTaskCreate(app_task, (const signed char * const) "lps331", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
// Run
platform_run();
return 0;
}
static void app_task(void *param)
{
uint32_t pres;
int16_t temp;
int count=0;
// FILE* fichier = NULL;
printf("# Testing LPS331AP\n");
printf("# Initializing LPS331AP...\n");
lps331ap_powerdown();
printf("# Setting LPS331AP pressure sensor\n");
lps331ap_set_datarate(LPS331AP_P_12_5HZ_T_12_5HZ);
while (1)
{
lps331ap_read_pres(&pres);
lps331ap_read_temp(&temp);
//fichier = fopen("test.txt", "w");
//fprintf(fichier,"%f", pres / 4096.0);
//fprintf(fichier,"%f", 42.5 + temp / 480.0 );
printf("%d\t",count);
printf("%f\t", 42.5 + temp / 480.0);
printf("%f\n", pres / 4096.0);
count=count+1;
//fclose(fichier);
//vTaskDelay(configTICK_RATE_HZ / 10);
vTaskDelay(2000);
//vTaskDelay(600000);
}
}
For measuring time, there's xTaskGetTickCount, but this will be limited to the resolution of your tick rate.
Alternatively, you can create another task that ticks at 1 Hz to increment a counter and use that as system time.
To get an actual date however, you'll need to consult your development board and see if it has an RTC. Otherwise, you'll need to get the time manually somehow and maintain this count using your development board's hardware timers.
There's bound to be some hardware clocks in your development board that you can use to measure time as well.

No Symbols Loaded: libmex.pdb not loaded (throw_segv_longjmp_seh_filter() = EXCEPTION_CONTINUE_SEARCH : C++ exception)

In order to create a MEX function and use it in my MATLAB code, like this:
[pow,index] = mx_minimum_power(A11,A12,A13,A22,A23,A33);
I've created the file mx_minimum_power.cpp and written the following code in it:
#include <math.h>
#include <complex>
#include "mex.h"
#include "matrix.h"
#include "cvm.h"
#include "blas.h"
#include "cfun.h"
using std::complex;
using namespace cvm;
/* The gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
const int arraysize = 62172;
const int matrixDimention = 3;
float *inMatrixA11 = (float *)mxGetPr(prhs[0]);
complex<float> *inMatrixA12 = (complex<float> *)mxGetPr(prhs[1]);
complex<float> *inMatrixA13 = (complex<float> *)mxGetPr(prhs[2]);
float *inMatrixA22 = (float *)mxGetPr(prhs[3]);
complex<float> *inMatrixA23 = (complex<float> *)mxGetPr(prhs[4]);
float *inMatrixA33 = (float *)mxGetPr(prhs[5]);
basic_schmatrix< float, complex<float> > A(matrixDimention);
int i = 0;
for (i = 0; i < arraysize; i++)
{
A.set(1, 1, inMatrixA11[i]);
A.set(1, 2, inMatrixA12[i]);
A.set(1, 3, inMatrixA13[i]);
A.set(2, 2, inMatrixA22[i]);
A.set(2, 3, inMatrixA23[i]);
A.set(3, 3, inMatrixA33[i]);
}
}
And then in order to be able to debug the code, I've created the mx_minimum_power.pdb and mx_minimum_power.mexw64 files, using the following code in the Matlab Command Window:
mex -g mx_minimum_power.cpp cvm_em64t_debug.lib
The files blas.h, cfun.h, cvm.h and cvm_em64t_debug.lib are in the same directory as mx_minimum_power.cpp.
They are the headers and library files of the CVM Class Library.
Then I've attached MATLAB.exe to Visual Studio 2013, using the way explained here.
and have set a breakpoint at line40:
When I run my MATLAB code, there's no error until the specified line.
But if I click on the Step Over button, I'll encounter the following message:
With the following information added to the Output:
First-chance exception at 0x000007FEFCAE9E5D in MATLAB.exe: Microsoft C++ exception: cvm::cvmexception at memory location 0x0000000004022570.
> throw_segv_longjmp_seh_filter()
throw_segv_longjmp_seh_filter(): C++ exception
< throw_segv_longjmp_seh_filter() = EXCEPTION_CONTINUE_SEARCH
Can you suggest me why libmex.pdb is needed at that line and how should I solve the issue?
If I stop debugging, I'll get the following information in MATLAB Command Window:
Unexpected Standard exception from MEX file.
What() is:First index value 0 is out of [1,4) range
Right before pressing the step over button, we have the following values for A11[0],A12[0],A13[0],A22[0],A23[0],A33[0]:
that are just right as my expectations, according to what MATLAB passes to the MEX function:
Maybe the problem is because of wrong allocation for matrix A, it is as follows just before pressing the step over button.
The problem occurs because we have the following code in lines 48 to 53 of the cvm.h file:
// 5.7 0-based indexing
#if defined (CVM_ZERO_BASED)
# define CVM0 TINT_ZERO //!< Index base, 1 by default or 0 when \c CVM_ZERO_BASED is defined
#else
# define CVM0 TINT_ONE //!< Index base, 1 by default or 0 when \c CVM_ZERO_BASED is defined
#endif
That makes CVM0 = 1 by default. So if we press the Step Into(F11) button at the specified line two times, we will get into line 34883 of the file cvm.h:
basic_schmatrix& set(tint nRow, tint nCol, TC c) throw(cvmexception)
{
this->_set_at(nRow - CVM0, nCol - CVM0, c);
return *this;
}
Press Step Into(F11) at line this->_set_at(nRow - CVM0, nCol - CVM0, c); and you'll go to the definition of the function _set_at:
// sets both elements to keep matrix hermitian, checks ranges
// zero based
void _set_at(tint nRow, tint nCol, TC val) throw(cvmexception)
{
_check_lt_ge(CVM_OUTOFRANGE_LTGE1, nRow, CVM0, this->msize() + CVM0);
_check_lt_ge(CVM_OUTOFRANGE_LTGE2, nCol, CVM0, this->nsize() + CVM0);
if (nRow == nCol && _abs(val.imag()) > basic_cvmMachMin<TR>()) { // only reals on main diagonal
throw cvmexception(CVM_BREAKS_HERMITIANITY, "real number");
}
this->get()[this->ld() * nCol + nRow] = val;
if (nRow != nCol) {
this->get()[this->ld() * nRow + nCol] = _conjugate(val);
}
}
pressing Step Over(F10) button,you'll get the result:
so in order to get nRow=1 and nCol=1 and not nRow=0 and nCol=0, which is out of the range [1,4), you should write that line of code as:
A.set(2, 2, inMatrixA11[i]);