ต้องการ PWM 3 channels พร้อมกัน

Started by samira, February 19, 2013, 03:15:48 AM

Previous topic - Next topic

p_chusak

HW PWM ใช้พร้อมกันได้ แต่จะต้องใช้ที่ความถี่เดี่ยวกันใน timer เดียวกัน แต่หากเป็น timer คนละตัวก็ใช้คนละความถี่ได้ครับ
ส่วน Soft pwm นั้น หากความถี่ไม่สูงสามารถใช้ได้ดีครับ อย่างการขับ rc-servo ผมก็ยังใช้ soft pwm เนื่องจาก ใช้ความถี่ต่ำ mega48 เอามาขับ rc-servo 20 ช่อง ยังไหวครับ

samira

soft PWM ( AVR 136)  เท่าที่ไปอ่านดู หากผมเข้าใจไม่ผิด
ที่ clk = 8 MHz จะได้ frequency ราว 8MHz  / 256/256 ≈ 122 Hz แค่นั้นเอง

อยากจะได้ frequency ~ 4K-8K ครับ ( ที่จริงก็ไม่จำเป็นว่าต้องใช้เร็วขนาดนี้ แต่อยากทำตามที่โครงการเขาแนะนำมา)

หากผมเข้าใจผิด กรุณาช่วยชี้แจงด้วยครับ
ขอบคุณมากที่กรุณาเข้ามาชี้แจง
" If you're born poor, it's not your mistake. But if you die poor, it's your mistake"
Bill Gates.

JMew

ถ้าเอา 8 ระดับ จะได้ความถี่ประมาณ 4 kHz ค่ะ แต่ถ้าจะเอา 16 ระดับ ก็จะได้ประมาณ 2 kHz ยิ่งระดับมากขึ้น soft loop ก็จะมากขึ้นค่ะ คุณ samira ต้องการกี่ระดับคะ?

โครงการกะเทยท่องโลก


samira

Quote from: JMew on February 23, 2013, 03:02:47 AM
ถ้าเอา 8 ระดับ จะได้ความถี่ประมาณ 4 kHz ค่ะ แต่ถ้าจะเอา 16 ระดับ ก็จะได้ประมาณ 2 kHz ยิ่งระดับมากขึ้น soft loop ก็จะมากขึ้นค่ะ คุณ samira ต้องการกี่ระดับคะ?

ไม่แน่ใจว่าเข้าใจคำว่า "ระดับ"  ของ อ Jmew ถูกต้องหรือเปล่า ผมจะเดาว่า อ หมายถึง 8 channels ใช่หรือเปล่า

หากใช่ คิดว่า แค่ 4K ผมก็คงจะเอาไปใช้ได้ครับ

ที่จะทำ คือ จะใช้ Potentiometer( POT)  เป็นตัวกำกับความเร็วของแต่ละช่อง กล่าวคือ จะเอาค่าของมัน ( ADC )  ไปใช้เป็นตัวปรับ กำหนดค่า duty cycle ครับ

อยากถาม อ Jmew ว่า วิธีของ อ นั้น คำนวน frequency ได้อย่างไร ??
ขอบคุณครับ


" If you're born poor, it's not your mistake. But if you die poor, it's your mistake"
Bill Gates.

JMew

ตรง code นี้ค่ะ

Dim Pw(7) as Byte
Dim Tik as Byte

Config Timer0 = Timer, Prescale=1 '<<<< ตรงนี้เปลี่ยนความถี่ได้ค่ะ

Enable Interrupts
Enable Timer0

On Timer0 Pwms

Start Timer0

Pw(0)=1 'กำหนด Duty cycle ของแต่ละ Channel ตรงนี้นะคะ
Pw(1)=7 'กำหนด Duty cycle ตรงนี้นะคะ
Pw(2)=15 'กำหนด Duty cycle ตรงนี้นะคะ
Pw(3)=31 'กำหนด Duty cycle ตรงนี้นะคะ
Pw(4)=63 'กำหนด Duty cycle ตรงนี้นะคะ
Pw(5)=127 'กำหนด Duty cycle ตรงนี้นะคะ
Pw(6)=255 'กำหนด Duty cycle ตรงนี้นะคะ
Pw(7)=0 'กำหนด Duty cycle ตรงนี้นะคะ

Pwms:

Incr Tik
If Tik = 255 Then < ระดับอยู่ตรงนี้ ตั้งแต่ 0 ถึง 255 มี 256 ระดับ เราเปลี่ยนตรงนี้ได้นะคะ
  Tik = 0
Portb = 0
End If

If Tik > Pw(7) Then PortB.7 = 1
If Tik > Pw(6) Then PortB.6 = 1
If Tik > Pw(5) Then PortB.5 = 1
If Tik > Pw(4) Then PortB.4 = 1
If Tik > Pw(3) Then PortB.3 = 1
If Tik > Pw(2) Then PortB.2 = 1
If Tik > Pw(1) Then PortB.1 = 1
If Tik > Pw(0) Then PortB.0 = 1

Return

ที่ prescale = 1 นะคะ Timer0 จะ overflow ทุก ๆ 0.000032 วินาที และจะนับ Tik ขึ้นทีละ 1 จนถึง 255
ทำให้ความถี่ลดลง เหลือ ประมาณ 8000000/256/256 = 122.07 Hz

แต่ถ้าเราเปลี่ยนให้ Tik นับแค่ 8 ระดับ ความถี่ที่ได้ก็จะเป็น 8000000/256/8 = 3906.25 Hz

แต่ถ้าเปลี่ยนให้ Tik นับ 16 ระดับ ความที่ที่ได้ก็จะเป็น 8000000/256/16 = 1953.125 Hz ค่ะ

มีอีกวิธีหนึ่ง คือใช้ Timer1 แล้ว Match Compare ค่ะ

คือทำแบบนี้

Config Timer1 = Timer , Prescale = 1 , Clear Timer = 1       
On Compare1a Pwms
Enable Oc1a


Compare1a = 80       ' จะเกิด interrupt ทุก ๆ 10 us ถ้าใช้ clock 8 MHz คราวนี้เราก็กำหนดเวลาตรงนี้ค่ะ 
Enable Interrupts
โครงการกะเทยท่องโลก

crywolf

PWM 3CH ความถี่ประมาณ 4KHz บน ATtiny45 ใช้ Timer 2 ตัว

    uint8_t r=0, g=85, b=170;

    DDRB = 1<<DDB4 | 1<<DDB1 | 1<<DDB0;

    TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00;
    TCCR0B = 0<<WGM02 | 3<<CS00;

    TCCR1 = 0<<PWM1A | 0<<COM1A0 | 7<<CS10;
GTCCR = 1<<PWM1B | 2<<COM1B0;

OCR1C = 255;

    for (;;)
    {
        OCR0A = r++;
OCR0B = g++;
        OCR1B = b++;

        _delay_ms(10);
    }

samira

Quote from: crywolf on February 23, 2013, 03:14:25 PM
PWM 3CH ความถี่ประมาณ 4KHz บน ATtiny45 ใช้ Timer 2 ตัว

    uint8_t r=0, g=85, b=170;

    DDRB = 1<<DDB4 | 1<<DDB1 | 1<<DDB0;

    TCCR0A = 2<<COM0A0 | 2<<COM0B0 | 3<<WGM00;
    TCCR0B = 0<<WGM02 | 3<<CS00;

    TCCR1 = 0<<PWM1A | 0<<COM1A0 | 7<<CS10;
GTCCR = 1<<PWM1B | 2<<COM1B0;

OCR1C = 255;

    for (;;)
    {
        OCR0A = r++;
OCR0B = g++;
        OCR1B = b++;

        _delay_ms(10);
    }

โอ้โห ให้ code หมดเลย ขอบคุณมากๆครับ

ปกติ ผมไล่ code คนอื่นแล้วมักจะงง เพราะขี้เกียจนั่งไล่ว่า ตัวแปร r b หรือ g มันคืออะไร 
เลยชอบนั่งขุดจาก datasheet เอง ค่อยตามได้หน่อย
อย่างไรก็ดี ขอบคุณมากครับ

วิธีของ อ Jmew ก็ว่ากันตาม Bascom เคยใช้ แต่... ไม่ได้แตะมานานแล้ว ลืมไปหมดแล้ว :-[
" If you're born poor, it's not your mistake. But if you die poor, it's your mistake"
Bill Gates.

firmware.c

Quote
ปกติ ผมไล่ code คนอื่นแล้วมักจะงง เพราะขี้เกียจนั่งไล่ว่า ตัวแปร r b หรือ g มันคืออะไร 
เลยชอบนั่งขุดจาก datasheet เอง ค่อยตามได้หน่อย
จริงๆผมมองว่าเราไม่จำเป็นต้อง coding ใหม่หมดเลยทุกอย่าง โดยเฉพาะการ programming แบบต่อยอดผมมองว่าพัฒนาไปได้เร็วกว่าการที่เรานั่ง coding เองหมดทุกอย่างครับ  ;)
IAR Embedded Workbench for ARM
AVR-Studio + AVR-GCC
CodeBlocks + MinGw
CodeBlocks + Gtk+