Problems with Cpp block for PWM generation

So i am trying to generate center aligned PWM with a variable duty.
I did watch a few examples but i cant figure what is not working with my code.

When in code i type the duty it works well but any external input does not work as in it does not change the PWM duty. As I experimented this following line has a fixed output for some reason.

Dutty=Duty/100 *3/20 * Counter_period;

Logic: Duty is in % and i have a % from 30% of half a period.
Does anyone has any idea what i am doing wrong?

Semnale_MCU_1.qsch (18.2 KB)
semnale_mcu_x1.cpp (2.3 KB)
semnale_mcu_x1.dll (19.5 KB)

@immortal,

I think I know what when wrong. I’ve made some changes to your .qsch and to your .cpp.

The biggest reason you were having issues with the external input to set the duty cycle is that you were declaring the input as an integer.

However, the math you performed to calculate the timing delays took your duty cycle (Duty is integer from 0% to 100%) and divided it by 100 (ie Duty/100 will ALWAYS equal 0).

Therefore I changed some variables from int to double.

See if you get better results now.
Semnale_MCU_1.qsch (18.2 KB)
semnale_mcu_x1.cpp (2.3 KB)

Len

2 Likes

THX noq it works well .
the variable i was putting the math into was a float from what i remembered so i though all was typecast ed to it automatically during math.

@immortal,

There is a hierarchy and rules regarding automatic math calculations.

Years ago I had a similar problem as yours. I wise SW expert told me: "Never assume an automatic conversion. Type casting forces your intent.

Len

1 Like

Wait i thought Qspice automatically did typecasting,
So if i read a analogue value i should use Float?

@Robert_1 ,

Typecasting is a C++ compiler thing.

I suggest you use “double”. double is a 64-bit floating val and seems to be the default “float” in QSpice/The C++ compiler.

You can use the “short float” (32-bit floating). However, since your CPU is most likely 64-bit, the double is most native to the CPU. Converting down to the short float may be extra processing steps and will not yield you a more accurate value or may not save you computing time.

Think of typecasting this way: The compiler can’t read your mind no matter how intelligent it is. It might have been possible that a programmer may intended to take an integer and divide it by 100. It may be intended that the decimal portion of the result to be not used. I have done that in certain situations when needed. Therefore, typecasting leaves the compiler no choice but to convert to your intended value type.

Len

This is not related to the discussion, but 32-bit vs 64-bit remind me a mistake I made before.
If, for example, you need to calculate delta time (dT = t - inst->lastT) using the pre-instance variable inst->lastT to save the value of t in the previous execution, inst->lastT must be defined as a double and not a float. I mistakenly defined inst->lastT as a float in one of my projects and spent an hour troubleshooting why dT sometimes returns a negative value. It turned out that t is a double (64 bits) but inst->lastT is a float (32 bits), which is why I may get a negative value.

In the DLL hierarchy, depending on the data type you have defined, it may preprocess its input before passing it to C, such as logic input. The input is always an analog value (the Qspice voltage node is always analog). However, the DLL hierarchy block input pin can be defined as a boolean. If it is defined as a boolean, it will rely on its instance parameter REF (default is 0.5) to determine whether the input is true (1) or false (0).

In short, the input and output data types should defined in the DLL hierarchy block, Data Type in Port right-click menu. The standard workflow is that if the input and output data types in the DLL hierarchy block are changed, it requires regenerating the C++ template OR copying the port definition to the C++ code.

1 Like

@KSKelvin ,

Therefore, I’m assuming in your example that the C++ compiler did not correctly (automatically) convert t (as double [64-bit]) to your inst->lastT (as float [32-bit]).

This is where forcing a typecast should have helped.

Len