0
$\begingroup$

I have Arduino and Matlab which has hardware support package for Arduino. I want to create SPWM signal (sinusoidal pulse width modulation) to be the output of the Arduino board. I could generate the signal required in Matlab using this code

function spwm = SinWave(frequency)
nsamples = 1250 * frequency;
t = linspace(0,1,nsamples);
sn = sin(2*pi*frequency*t);
st = sawtooth(2*pi*frequency*10*t);
spwm = abs(sn) > abs(st);
plot(t, sn);
hold on;
plot(t, st);
plot(t,spwm);
axis([0,1,-1.2,1.2]);

Now SPWM has the samples for the signal, I tried sending it on pin 13 using the following function

function writeSPWM(arduino, spwm)
for k=1:length(spwm)
    writeDigitalPin(arduino, 'D13' ,spwm(k))
end

Then I used the following two lines in command window

a = arduino()
writeSPWM(a, SinWave(5))

I getting my signal shape with very low frequency(it is really much bigger) Is there a better way to achieve my goal? using Matlab is necessary but I have no problem if I have to combine coding throw Matlab and Arduino C.

$\endgroup$

1 Answer 1

1
$\begingroup$

It seems that all the code you wrote is in Matlab, and at each cycle it should communicate via the USB port with arduino to turn the pin on or off. This take a lot of time.

The fastest solution would be to write the whole algorithm as an Arduino sketch, and only get the current desired frequency via the Serial (USB) connection from Matlab. Matlab would set the desired frequency, send it via serial to the arduino. From there the latency of the USB (Serial) connection would not intervene.

When you do the Arduino programming, make sure to use the PWM pins in PWM mode and not as a simple digital output turned on or off.

EDIT:

Here is a PWM tutorial for the arduino.

for SPWM the duty cycle has to be changed frequently. You will not be able to change it for each cycle, but maybe for every 10 cycles. It will be still ok.

You could start by calculating a sinus on the arduino using an interrupt that is set for maybe every 2 milliseconds. That interrupt should increment your time variable (make sure that it does not overflow, or it overlfows in a controlled manner and make sure to use some sort of scaling to get seconds).

This will be the t from the sinus time signal equation: $SPWM(t) = A\sin (\omega t + \phi)$

A (amplitude) I think in this case is irrelevant. probably the phase shift ($\phi$) is also irrelevant. $\omega$ you can calculate form your frequency.

$\omega = 2 \pi f$, where $f$ is the frequency. You set to constant value at first, afterwards you make function that gets it form the serial port form Matlab (make sure NOT to include this in the interrupt, because it is slow)

At the end of the interrupt you update the PWM duty cycle basted on the SPWM(t) value the interrupt calculated.

I am sure there are many other approaches, but for me this seems the simplest one which delivers acceptable performance. Also, please make sure that the cycle time of the interrupt is longer than the runtime of the code in the interrupt.

$\endgroup$
1
  • $\begingroup$ Welcome to Robotics @AmmarAtef. Comments are for helping to improve questions and answers, and are distracting, so we try to keep them to a minimum. While it may seem nice to thank people for their questions or answers, thanks and me too comments are just noise. A better way to show your thanks would be to vote up the question or answer, which rewards the poster with a reputation boost. Comments should be considered ephemeral, any comment which no longer actively helps to improve a question or answer may be deleted at any time to tidy up a post. $\endgroup$
    – Mark Booth
    May 15, 2017 at 8:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.