Electoday 4.0

ไมโครคอนโทรลเลอร์ => AVR and Arduino => Topic started by: samira on February 19, 2013, 03:15:48 am

Title: ต้องการ PWM 3 channels พร้อมกัน
Post by: samira on February 19, 2013, 03:15:48 am
ขอถามกูรูทั้งหลายหน่อยครับ

ผมมีความจำเป็นต้องใช้  PWM 3 channels.
ไปเปิดดู ใน atmega 48 (ถูกตังหน่อย ว่าจะใช้ attiny 44/45 มีไม่พอให้ใช้ ) พบว่า มี pwm ให้ใช้ 6 channels

จะใช้ Fast PWM mode
ไปที่ Timer/counter0 มันให้ใช้
ที่ COM0A0/A1 ได้ 1 channel
ที่ COM0B0/B1 ได้อีก 1 channel

สงสัยว่า ผมจะใช้พร้อมกันได้หรือเปล่าครับ ยังไม่เคยลอง
ก่อนจะลุยเอง...... อยากจะถามผู้ที่เคยเล่นก่อนว่า

"ใช้พร้อมกันได้หรือเปล่า" โดยอาศัยจาก Timer/counter เดียวกัน
( ในที่นี้คือ Timer/Counter0 โดยจะเปิดใช้ com0a & com0b พร้อมกัน และใช้ pwm ค่าต่างกัน ) 
เคยเล่นแต่ ช่องเดียว ไม่เคยใช้ ทีละมากกว่า หนึ่งช่อง

หากได้ เหลืออีก channel คงต้องไปเอามาจาก Timer/Counter2  8 bits เช่นกัน

ขอบคุณสำหรับคำแนะนำ/ชี้แนะ
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: firmware.c on February 19, 2013, 07:47:28 am
ได้ครับครับ แต่ความถี่ต้องเหมือนกัน duty แต่ละ Chanel ปรบเปลี่ยนอิสระโดย OCxA, OCxB, OCxC
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: crywolf on February 19, 2013, 08:02:25 am
ถ้าใช้ attiny 45 สามารถใช้ Software PWM ได้ครับ ได้ถึง 6 Channel
ลองดู Application Note (AVR136) ของ ATMEL นะครับ มีตัวอย่าง Code ด้วย
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: JMew on February 19, 2013, 10:38:20 am
ฉันเอา Timer0 มานับค่ะ ตั้งแต่ 0-255 เสร็จแล้วในรูทีน Timer ฉันเอา Array ของแต่ละขามารับเอา

สมมติจะเอาออกที่พอร์ต B จำนวน 8 Channel ก็ทำได้ (แต่ต้องที่ความถี่เดียวกัน)

ตัวอย่างเช่น อยากให้พอร์ต B0 ถึง B7 เป็น PW(0) ถึง PW(7) แล้วเอาสัญญาณออกช่องนี้ด้วยความถี่เดียวกัน แต่ duty ต่างกัน ทำแบบนี้นะคะ

Dim Pw(7) as Byte
Dim Tik as Byte

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

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
  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

แบบนี้จะได้ PWM ตั้ง 8 ช่องที่ความถี่เดียวกัน แต่ Duty ไม่ซ้ำกันเลย

(http://cmu.mine.nu/teach/avr/pwm/pwm.JPG)

ส่วนนี่ Code + HEX + Proteus DSN ค่ะ

http://cmu.mine.nu/teach/avr/pwm (http://cmu.mine.nu/teach/avr/pwm)
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: AppleIIe on February 19, 2013, 11:03:11 am
ในความเห็นผม
ถ้าความถี่สูงๆหน่อย ใช้ Hardware ที่เป็น PWM จะดีกว่าครับ (ไม่กินแรง CPU เลย เพราะให้่ Hardware ทำงานไปอย่าง อิสระ อาจต้อง Syncronize บ้างตอนเปลี่ยนค่า)
แต่ถ้าความถี่ไม่สูงนัก ใช้ Software อย่างที่ท่าน Crywolf ได้แนะนำไว้ก็ได้ครับ จะกินแรง CPU นิดหน่อย เพราะต้อง interrupt cpu เป็นระยะ แต่ได้ช่องมากแน่นอน
http://www.atmel.com/Images/doc8020.pdf
http://howaboutanorange.com/avrpwm
http://jeelabs.org/2010/10/03/software-pwm-at-1-khz

อันนี้ เขาคุยกันเรื่อง PWM HW/SW
http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=107185&start=0
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: AppleIIe on February 19, 2013, 11:12:38 am
ขอถามกูรูทั้งหลายหน่อยครับ

ผมมีความจำเป็นต้องใช้  PWM 3 channels.
ไปเปิดดู ใน atmega 48 (ถูกตังหน่อย ว่าจะใช้ attiny 44/45 มีไม่พอให้ใช้ ) พบว่า มี pwm ให้ใช้ 6 channels

จะใช้ Fast PWM mode
ไปที่ Timer/counter0 มันให้ใช้
ที่ COM0A0/A1 ได้ 1 channel
ที่ COM0B0/B1 ได้อีก 1 channel

สงสัยว่า ผมจะใช้พร้อมกันได้หรือเปล่าครับ ยังไม่เคยลอง
ก่อนจะลุยเอง...... อยากจะถามผู้ที่เคยเล่นก่อนว่า

"ใช้พร้อมกันได้หรือเปล่า" โดยอาศัยจาก Timer/counter เดียวกัน
( ในที่นี้คือ Timer/Counter0 โดยจะเปิดใช้ com0a & com0b พร้อมกัน และใช้ pwm ค่าต่างกัน ) 
เคยเล่นแต่ ช่องเดียว ไม่เคยใช้ ทีละมากกว่า หนึ่งช่อง

หากได้ เหลืออีก channel คงต้องไปเอามาจาก Timer/Counter2  8 bits เช่นกัน

ขอบคุณสำหรับคำแนะนำ/ชี้แนะ

ขอตอบ สำหรับ atmega48 นะครับ

Q: "ใช้พร้อมกันได้หรือเปล่า" โดยอาศัยจาก Timer/counter เดียวกัน
( ในที่นี้คือ Timer/Counter0 โดยจะเปิดใช้ com0a & com0b พร้อมกัน และใช้ pwm ค่าต่างกัน ) 
เคยเล่นแต่ ช่องเดียว ไม่เคยใช้ ทีละมากกว่า หนึ่งช่อง


A: ใช้พร้อมกันได้ครับ ตั้งที่ OCR0A และ OCR0B ของ Timer 0 ได้เลย

Q: หากได้ เหลืออีก channel คงต้องไปเอามาจาก Timer/Counter2  8 bits เช่นกัน

A : ใช้ที่ Timer 2 ก็ได้ครับ ตั้งที่ OCR2A และ OCR2B เป็็นของ Timer 2 ครับ

Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: samira on February 20, 2013, 01:38:11 am
ขอขอบคุณทุกท่านที่มาชี้แนะ และ อธิบายครับ

คิดว่าคงจะใช้ ความถี่เดียวกันครับ
ผมต้องการเอาไปคุม พัดลม ( เล็กๆ ) 3 ตัว ด้วยความเร็วไม่เท่ากัน 

ส่วน channel 3 คงต้องไปเอามาจาก timer/counter2

ครับ attiny45 ใช้ได้ ผมดูผิด อ่านเร็วไปเอง ขอบคุณมากครับ ท่าน crywolf

คงต้องศึกษาตัวอย่างที่ อ. Jmew เอามาแสดง น่าสนใจ ขอบคุณครับ

ต่อไปนี้ ก็ลุย................................
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: firmware.c on February 21, 2013, 09:26:17 pm
Soft PWM ทำได้ครับหาก load CPU ไม่เยอะมาก avr atmega ไม่มี multiple interrupt โดย hardware
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: p_chusak on February 22, 2013, 10:10:59 am
HW PWM ใช้พร้อมกันได้ แต่จะต้องใช้ที่ความถี่เดี่ยวกันใน timer เดียวกัน แต่หากเป็น timer คนละตัวก็ใช้คนละความถี่ได้ครับ
ส่วน Soft pwm นั้น หากความถี่ไม่สูงสามารถใช้ได้ดีครับ อย่างการขับ rc-servo ผมก็ยังใช้ soft pwm เนื่องจาก ใช้ความถี่ต่ำ mega48 เอามาขับ rc-servo 20 ช่อง ยังไหวครับ
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: samira on February 22, 2013, 07:58:01 pm
soft PWM ( AVR 136)  เท่าที่ไปอ่านดู หากผมเข้าใจไม่ผิด
ที่ clk = 8 MHz จะได้ frequency ราว 8MHz  / 256/256 ≈ 122 Hz แค่นั้นเอง

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

หากผมเข้าใจผิด กรุณาช่วยชี้แจงด้วยครับ
ขอบคุณมากที่กรุณาเข้ามาชี้แจง
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: JMew on February 23, 2013, 03:02:47 am
ถ้าเอา 8 ระดับ จะได้ความถี่ประมาณ 4 kHz ค่ะ แต่ถ้าจะเอา 16 ระดับ ก็จะได้ประมาณ 2 kHz ยิ่งระดับมากขึ้น soft loop ก็จะมากขึ้นค่ะ คุณ samira ต้องการกี่ระดับคะ?

(http://image.ohozaa.com/i/g1d/n33nL7.PNG)
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: samira on February 23, 2013, 08:45:12 am
ถ้าเอา 8 ระดับ จะได้ความถี่ประมาณ 4 kHz ค่ะ แต่ถ้าจะเอา 16 ระดับ ก็จะได้ประมาณ 2 kHz ยิ่งระดับมากขึ้น soft loop ก็จะมากขึ้นค่ะ คุณ samira ต้องการกี่ระดับคะ?

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

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

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

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


Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: JMew on February 23, 2013, 10:21:17 am
ตรง 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
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: crywolf on February 23, 2013, 03:14:25 pm
PWM 3CH ความถี่ประมาณ 4KHz บน ATtiny45 ใช้ Timer 2 ตัว

Code: [Select]
    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);
    }
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: samira on February 23, 2013, 08:28:09 pm
PWM 3CH ความถี่ประมาณ 4KHz บน ATtiny45 ใช้ Timer 2 ตัว

Code: [Select]
    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 เคยใช้ แต่... ไม่ได้แตะมานานแล้ว ลืมไปหมดแล้ว :-[
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: firmware.c on February 23, 2013, 09:32:50 pm
Quote
ปกติ ผมไล่ code คนอื่นแล้วมักจะงง เพราะขี้เกียจนั่งไล่ว่า ตัวแปร r b หรือ g มันคืออะไร 
เลยชอบนั่งขุดจาก datasheet เอง ค่อยตามได้หน่อย
จริงๆผมมองว่าเราไม่จำเป็นต้อง coding ใหม่หมดเลยทุกอย่าง โดยเฉพาะการ programming แบบต่อยอดผมมองว่าพัฒนาไปได้เร็วกว่าการที่เรานั่ง coding เองหมดทุกอย่างครับ  ;)
Title: Re: ต้องการ PWM 3 channels พร้อมกัน
Post by: samira on February 24, 2013, 01:01:25 am

Quote
จริงๆผมมองว่าเราไม่จำเป็นต้อง coding ใหม่หมดเลยทุกอย่าง โดยเฉพาะการ programming แบบต่อยอดผมมองว่าพัฒนาไปได้เร็วกว่าการที่เรานั่ง coding เองหมดทุกอย่างครับ  ;)

ครับ เห็นด้วยในแง่ของผู้ที่ต้องผลิตชิ้นงาน หรือประกอบอาชีพด้านนี้

ผมสนใจในแง่ที่ "อยากรู้" และ ที่มาที่ไป( mechanic กลไกใส้ใน ของการทำงานของ microcontroller )
จากมุมมองของผู้เล่นเป็นงานอดิเรก และมีความสนุกสนานกับการเรียนรู้ของมันมากๆ
และโดยเฉพาะอย่างยิ่ง เมื่อได้เห็นผลงานจริงของเรา  จากที่ได้อ่านและทำเอง 
( แปลว่า ทำทดลองบอร์ด เขียน Code "เอง" ให้มันทำตามที่เราต้องการ ) เมือได้ผล ก็แปลว่า เราเข้าใจเนื้อในใส้พุงของมัน สนุกกว่าการไปลอก code เขามา

ประการสำคัญ ผมถูกพ่อแม่สอนให้หัดทำอะไรเองตั้งแต่เด็ก :'( ( ในเรื่องที่พอทำเองได้ )
และที่ผ่านมาหลายปี ก็มีความสนุกกับงานอดิเรกใหม่ ( mcu & electronics ) มาก แม้จะมีเรื่องต้องเรียน อีกแยะมากกกกกกกกกกกกกกกกกกก
ขอบคุณมาก สำหรับความคิดเห็นครับ  ;D