1

I've been trying to create a sine wave using the pwm function of the Arduino DUE. The sine wave has te be at higher rates than the analogWrite() function can handle, so I've been using the native capabilties of the SAM3X8E.

To test it, instead of creating sinus I've been doing it linear. The code to do that is:

  REG_PWM_ENA = REG_PWM_SR | B11111111; //enable output
  REG_PWM_CMR3 = 0x00000; //deadtime 0
  REG_PWM_CPRD3 = value;
  REG_PWM_CMR2 = 0x00000; //deadtime 0
  REG_PWM_CPRD2 = value;
  int i =0 ;
  waittime = 100;
  value = 30

  while (!Serial.available()) {
    REG_PWM_OS = 0x0000C;

for (i = 0; i < value; i++) {
      pwmc_duty(i);
      pwmc_duty4(i);
      wait(waittime);
    }

for (i = value; i > 0; i--) {
  pwmc_duty(i);
  pwmc_duty4(i);
  wait(waittime);
}
REG_PWM_OS = 0xC000C;
wait(1);
pwmc_duty(value);
pwmc_duty4(value);
REG_PWM_OS = 0xC0000;

for (i = value; i > 0; i--) {
  pwmc_duty(i);
  pwmc_duty4(i);
  wait(waittime);
}

for (i = 0; i < value; i++) {
  pwmc_duty(i);
  pwmc_duty4(i);
  wait(waittime);
}

REG_PWM_OS = 0xC000C;
wait(1);
pwmc_duty(0);
pwmc_duty4(0);  
}

inline void pwmc_duty(unsigned short duty0) {
   // REG_PWM_CPRD3 = duty0;
    REG_PWM_CDTY3 = duty0;
}
inline void pwmc_duty4(unsigned short duty0) {
   // REG_PWM_CPRD3 = duty0;
    REG_PWM_CDTY2 = duty0;
}

void wait(int times){
  for (int i =0;  i < times; i++){
    __asm__("nop\n\t");
  }
}

I expect the code to gradually increase the duty cycle of the signal and than slowly decrease. And that works! The problem is that i do not get a normal PWM signal out of it.

I've attached one of the previous test signals to this post, with a bit different code, to show the problem. The output signal

i've expected the pwm more clear like demonstrated in this paint picture: Expected result

How do I get from these spikes to a more normal block signal?

VE7JRO
  • 2,497
  • 15
  • 24
  • 29
  • "I expect the code to gradually increase the duty cycle of the signal and than slowly decrease. And that works! The problem is that i do not get a normal PWM signal out of it." - what exactly doesn't work?! Or, how do you know that incrementing the duty cycle works? – Sim Son Nov 12 '19 at 13:46
  • Maybe its just an aliasing problem, can you configure a lower pwm frequency? – Sim Son Nov 12 '19 at 13:48
  • @SimSon I saw on the scope that the pwm increased and decreased as expected. The picture is not really showing it, but it does show the problem. It could indeed be an aliasing problem, but I have tried slowing it down and it was without a different result. – Calvin Bootsman Nov 12 '19 at 14:04
  • Or play with the scope settings. Zooming into a signal that strong probably won't work... also, I still don't understand: if you see the pwm increase and decrease, **what** is "the problem" then?! – Sim Son Nov 12 '19 at 14:22
  • 3
    why you don't use the DAC of DUE? – Juraj Nov 12 '19 at 14:38
  • 1
    By "create a sinus" I assume you mean that you want to generate a sine wave? – Duncan C Nov 12 '19 at 14:45
  • The scope works with 12.5 kS/sec so according to Pete (ahh no) according to Nyquist you can measure signals up to 6.25kHz (sinus wave). That's a theoretical limit, the scope must also be capable of reconstructing the original wave. As you have a rectangle PWM wave, there are much higher frequencies in the signal than the PWM frequency. So I would say, you have aliasing problems. Can you configure the oscilloscope to a higher sampling rate? e.g 500 kHz? It is also possible that your PWM Frequency is too low for the sinus wave you want to modulate on it. – Peter Paul Kiefer Nov 12 '19 at 14:47
  • As @Juraj mentions - the DUE has a real 12-bit DAC built in. Use that to create an actual analog waveform rather than trying to emulate one with PWM. – Majenko Nov 12 '19 at 14:59
  • @DuncanC I meant sine wave, yes. – Calvin Bootsman Nov 12 '19 at 15:18

0 Answers0