Go Down

Topic: Programming PWM for Generating 0~3Mhz  (Read 148 times) previous topic - next topic

DrVoid

Hi guys i need a lot of helps.

I upload sketch file from ard_newbie.
Original code from https://forum.arduino.cc/index.php?topic=396125.0 at #4
And im customizing for mine.

I made a function to use easy.
using 2MHz/CPRD = x Hz -> CPRD = 2000000/xHz

void setCPRD(unsigned int hz){
  PWM->PWM_CH_NUM[2].PWM_CPRD=(2000000/hz);
  }

Second Question

PIOC->PIO_PDR |= PIO_PDR_P7;
Above the sentence what is that exactly saying.
extra question
 I checked due's pin out and see PWMH2.
 Does it can ues only labled PWMH2?
I want to know exactly.
Third Question

If i use the code digital pin39 generate 1khz pulse with 5% duty rate?

Forth Question
About PWM_handler is it for test?

ard_newbie


DrVoid

#2
Today at 01:32 am Last Edit: Today at 08:25 am by DrVoid
Im watching and found some.
About why P7 is digital pin 39 from under link
https://www.arduino.cc/en/Hacking/PinMappingSAM3X

First about setCPRD i just compiled and compiler gives me error "expression can not be used as a function" but i want to use it as function.

Second when i alloc another pin for pwm to generate to pulse does the pin must be PWMH? or can use PWML?

Code: [Select]


void setCPRD(int num, unsigned int hz);
void setup () {
  PWM_Init();
  setCPRD(1,1);//output1 :1hz (duty rate 50%) for test
  setCPRD(2,2);//Output2 :2hz(duty rate 50%) for test
}

void loop() {
 
  // Todo : update frequency with PWM_CPRDUPD in loop()
  // update duty with PWM_CDTUPD in loop()
 
}
 
void PWM_Init() {
  // PWM Set-up on pins PC7 and PA20 (Arduino Pins 39(PWMH2) : see Datasheet chap. 38.5.1 page 973
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                    // PWM power ON
  PWM->PWM_DIS = PWM_DIS_CHID2;                         // Disable PWM channel 2
  PWM->PWM_DIS = PWM_DIS_CHID2;                         // Disable PWM channel 3
  // Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pin 39, see pinout diagram) ; Peripheral type B
  PIOC->PIO_PDR |= PIO_PDR_P7;                          // Set the pin to the peripheral PWM, not the GPIO
  PIOC->PIO_ABSR |= PIO_PC7B_PWMH2;                     // Set PWM pin perhipheral type B
  //  Select Intancd=PWMl Signal=PWMH3 (channel 2); I/O LIne=PC9 (P9, Arduino pin 41, see pinout diagram) ; Peripheral type B
  //Added by me for generate another pulse
  PIOC->PIO_PDR |= PIO_PDR_P9;                          // Set the pin to the peripheral PWM, not the GPIO
  PIOC->PIO_ABSR |= PIO_PC9B_PWMH3;                     // Set PWM pin perhipheral type B
 
  PWM->PWM_CLK = PWM_CLK_PREB(0) | PWM_CLK_DIVB(28);    // Set the PWM clock rate to 3MHz (84MHz/28).
  PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_CPRE_CLKB;       // clock source as CLKB on channel 2, waveform left aligned
  //Added by me
  PWM->PWM_CH_NUM[3].PWM_CMR = PWM_CMR_CPRE_CLKB;       // clock source as CLKB on channel 3, waveform left aligned
 
  PWM->PWM_CH_NUM[2].PWM_CPRD = 3000;                   // Channel 2 : Set the PWM frequency 3MHz/CPRD = 1 KHz ;
  PWM->PWM_CH_NUM[2].PWM_CDTY = 1500;                    // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ;
  //Added by me for another pulse out
  PWM->PWM_CH_NUM[3].PWM_CPRD = 3000;                   // Channel 3 : Set the PWM frequency 3MHz/CPRD = 1 KHz ;
  PWM->PWM_CH_NUM[3].PWM_CDTY = 1500;                    // Channel 3: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ;
 
  PWM->PWM_IER1 = PWM_IER1_CHID2;                       // Interrupt on Channel 2 Counter match
  //Added by me for channel 3
  PWM->PWM_IER1 = PWM_IER1_CHID3;                       // Interrupt on Channel 3 Counter match
  NVIC_EnableIRQ(PWM_IRQn);                             // Enable interrupt
 
  PWM->PWM_ENA = PWM_ENA_CHID2;                         // Enable PWM Channel 2
  //Added by me
  PWM->PWM_ENA = PWM_ENA_CHID3;                         // Enable PWM Channel 3
}
void setCPRD(int num,unsigned int hz){
  if(num==1)
    PWM->PWM_CH_NUM[2].PWM_CPRD=(3000000/hz);
  else (num==2)
    PWM->PWM_CH_NUM[3].PWM_CPRD=(3000000/hz);
  }

ard_newbie


Edit your post and post your code between code tags </>

Read:
https://www.arduino.cc/reference/en/language/structure/control-structure/else/


Read the datasheet pages 996 and 1048

DrVoid

#4
Today at 08:54 am Last Edit: Today at 09:13 am by DrVoid
Umm i reading very carefully and it is pricipal of pwm.
And else cause the compiler says it can not work.

Please understand that my personal circumstances prevent me from experimenting with adino for about three weeks. why i upload my codes.

And i see my sourcecode it has same PWM clock rate.
Following datasheet in this case i can use Synchronous Channels(datasheet pages 999 chapter39.6.2.7) and i have a question.
Can output rate could be another if i change?  <- i understood synchronous channels should same output rate & duty rate. And also change interrupt
Am i understand well?

Code: [Select]



void setCPRD(int num, unsigned int hz);
void setup () {
  PWM_Init();
  setCPRD(1,1);//output1 :1hz (duty rate 50%) for test
  setCPRD(2,2);//Output2 :2hz(duty rate 50%) for test
}

void loop() {
 
  // Todo : update frequency with PWM_CPRDUPD in loop()
  // update duty with PWM_CDTUPD in loop()
 
}
 
void PWM_Init() {
  // PWM Set-up on pins PC7 and PA20 (Arduino Pins 39(PWMH2) : see Datasheet chap. 38.5.1 page 973
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                    // PWM power ON
  PWM->PWM_DIS = PWM_DIS_CHID2;                         // Disable PWM channel 2
  PWM->PWM_DIS = PWM_DIS_CHID2;                         // Disable PWM channel 3
  // Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pin 39, see pinout diagram) ; Peripheral type B
  PIOC->PIO_PDR |= PIO_PDR_P7;                          // Set the pin to the peripheral PWM, not the GPIO
  PIOC->PIO_ABSR |= PIO_PC7B_PWMH2;                     // Set PWM pin perhipheral type B
  //  Select Intancd=PWMl Signal=PWMH3 (channel 2); I/O LIne=PC9 (P9, Arduino pin 41, see pinout diagram) ; Peripheral type B
  //Added by me for generate another pulse
  PIOC->PIO_PDR |= PIO_PDR_P9;                          // Set the pin to the peripheral PWM, not the GPIO
  PIOC->PIO_ABSR |= PIO_PC9B_PWMH3;                     // Set PWM pin perhipheral type B
 
  PWM->PWM_CLK = PWM_CLK_PREB(0) | PWM_CLK_DIVB(28);    // Set the PWM clock rate to 3MHz (84MHz/28).
  PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_CPRE_CLKB;       // clock source as CLKB on channel 2, waveform left aligned
  //Added by me
  PWM->PWM_CH_NUM[3].PWM_CMR = PWM_CMR_CPRE_CLKB;       // clock source as CLKB on channel 3, waveform left aligned
 
  PWM->PWM_CH_NUM[2].PWM_CPRD = 3000;                   // Channel 2 : Set the PWM frequency 3MHz/CPRD = 1 KHz ;
  PWM->PWM_CH_NUM[2].PWM_CDTY = 1500;                    // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ;
  //Added by me for another pulse out
  PWM->PWM_CH_NUM[3].PWM_CPRD = 3000;                   // Channel 3 : Set the PWM frequency 3MHz/CPRD = 1 KHz ;
  PWM->PWM_CH_NUM[3].PWM_CDTY = 1500;                    // Channel 3: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ;
 
  PWM->PWM_IER1 = PWM_IER1_CHID2;                       // Interrupt on Channel 2 Counter match
  //Added by me for channel 3
  PWM->PWM_IER1 = PWM_IER1_CHID3;                       // Interrupt on Channel 3 Counter match
  NVIC_EnableIRQ(PWM_IRQn);                             // Enable interrupt
 
  PWM->PWM_ENA = PWM_ENA_CHID2;                         // Enable PWM Channel 2
  //Added by me
  PWM->PWM_ENA = PWM_ENA_CHID3;                         // Enable PWM Channel 3
}
void setCPRD(int num,unsigned int hz){
 PWM->PWM_CH_NUM[num].PWM_CPRD=(3000000/hz);
}



ard_newbie


Your code is still wrong, read Sam3x datasheet page 1048, plus you don't disable PWM channel 3 at the beginning of Pwm_init().



Can output rate could be another if i change?  <- i understood synchronous channels should same output rate & duty rate. And also change interrupt
Am i understand well?
Sorry, I don't understand...


BTW, is it a school assignment ?

DrVoid

#6
Today at 10:33 am Last Edit: Today at 10:45 am by DrVoid
Thank you for answering my questions every time.
I am an active Korean soldier six months before I leave the army.
I ask you every time during my personal grooming session.
The military can not upload programs to arduino.
What I can do is write the code and compile it.
When I'm out of the army, I make presents for myself with the salaries I collect from the army.
The gift is Equatorial Mout, which is made with Harmonic Drive.
Some Koreans have already tried and have had success stories.
I'm combining their advice and what I want.
Previous people used AstroEQ or ASCOM.
However, I have to create my own telescope control system because it is not compatible with AstroEQ. I am in the process step by step. And i'm struggling with my motordriver.(using 5phase stepping motor)
Also changed about disable PWM channel 3.
still left? may be i needs to watch more.
About your Question.(duty rate is 50%)
while output 1 is generating 3hz does output2 should be 3hz or can changable?
if i need to use Synchronous Channels than i have to change my code.
but i add some codes to alloc another pin to generate pulse.
I needs two pulse out and original code can generate one pulse out.
You teach me if i alloc one more another pin could generate pulse.
so i add some codes like orignal style.

ard_newbie


In your code, channels are NOT synchro, so PWM channel 2 frequency can be different from PWM channel 3 frequency and you can select any duty cycle.

DrVoid

#8
Today at 11:16 am Last Edit: Today at 12:09 pm by DrVoid
oh than doese the codes good to generate 0~3Mhz?
and two more question.
Inside of code there is 
PWM->PWM_IER1 = PWM_IER1_CHID3;                       // Interrupt on Channel 3 Counter match
i think needs to change this code because PWM_IER1 is for chennel2 how to change?
if i want to increse more than 3mhz
change clock rate for my rate?
Code: [Select]

void setCPRD(int num, unsigned int hz);
void setup () {
  PWM_Init();
  setCPRD(1,1);//output1 :1hz (duty rate 50%) for test
  setCPRD(2,2);//Output2 :2hz(duty rate 50%) for test
}

void loop() {
 
  // Todo : update frequency with PWM_CPRDUPD in loop()
  // update duty with PWM_CDTUPD in loop()
 
}
 
void PWM_Init() {
  // PWM Set-up on pins PC7 and PA20 (Arduino Pins 39(PWMH2) : see Datasheet chap. 38.5.1 page 973
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                    // PWM power ON
  PWM->PWM_DIS = PWM_DIS_CHID2;                         // Disable PWM channel 2
  PWM->PWM_DIS = PWM_DIS_CHID3;                         // Disable PWM channel 3
  // Select Instance=PWM; Signal=PWMH2 (channel 2); I/O Line=PC7 (P7, Arduino pin 39, see pinout diagram) ; Peripheral type B
  PIOC->PIO_PDR |= PIO_PDR_P7;                          // Set the pin to the peripheral PWM, not the GPIO
  PIOC->PIO_ABSR |= PIO_PC7B_PWMH2;                     // Set PWM pin perhipheral type B
  //  Select Intancd=PWMl Signal=PWMH3 (channel 2); I/O LIne=PC9 (P9, Arduino pin 41, see pinout diagram) ; Peripheral type B
  //Added by me for generate another pulse
  PIOC->PIO_PDR |= PIO_PDR_P9;                          // Set the pin to the peripheral PWM, not the GPIO
  PIOC->PIO_ABSR |= PIO_PC9B_PWMH3;                     // Set PWM pin perhipheral type B
 
  PWM->PWM_CLK = PWM_CLK_PREB(0) | PWM_CLK_DIVB(28);    // Set the PWM clock rate to 3MHz (84MHz/28).
  PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_CPRE_CLKB;       // clock source as CLKB on channel 2, waveform left aligned
  //Added by me
  PWM->PWM_CH_NUM[3].PWM_CMR = PWM_CMR_CPRE_CLKB;       // clock source as CLKB on channel 3, waveform left aligned
 
  PWM->PWM_CH_NUM[2].PWM_CPRD = 3000;                   // Channel 2 : Set the PWM frequency 3MHz/CPRD = 1 KHz ;
  PWM->PWM_CH_NUM[2].PWM_CDTY = 1500;                    // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ;
  //Added by me for another pulse out
  PWM->PWM_CH_NUM[3].PWM_CPRD = 3000;                   // Channel 3 : Set the PWM frequency 3MHz/CPRD = 1 KHz ;
  PWM->PWM_CH_NUM[3].PWM_CDTY = 1500;                    // Channel 3: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ;
 
  PWM->PWM_IER1 = PWM_IER1_CHID2;                       // Interrupt on Channel 2 Counter match
  //Added by me for channel 3
  PWM->PWM_IER1 = PWM_IER1_CHID3;                       // Interrupt on Channel 3 Counter match
  NVIC_EnableIRQ(PWM_IRQn);                             // Enable interrupt
 
  PWM->PWM_ENA = PWM_ENA_CHID2;                         // Enable PWM Channel 2
  //Added by me
  PWM->PWM_ENA = PWM_ENA_CHID3;                         // Enable PWM Channel 3
}
void setCPRD(int num,unsigned int hz){
 PWM->PWM_CH_NUM[num].PWM_CPRD=(3000000/hz);
}

Go Up