Electoday 2025

ไมโครคอนโทรลเลอร์ => AVR and Arduino => Topic started by: nutzty on February 05, 2015, 08:09:57 PM

Title: ADC กับ ATmega8
Post by: nutzty on February 05, 2015, 08:09:57 PM
ขอคำปรึกษาเกี่ยวกับ ADC ของ ATmega8 หน่อยครับ พอดีอ่าน datasheet แล้วสงสัยว่าหลังจาก conversion เสร็จแล้วค่าที่อ่านมาได้จะถูกเก็บไว้ที่ ADCH/ADCL ใน ADLAR ถูกไหมครับ และถ้าเราจะนำค่าที่อ่านได้มาใช้ต่อเนี่ย สามารถเขียนโค้ดในลักษณะใดได้บ้างครับ

ปล. ADC ที่จะใช้คือรับค่ามาจาก infrared distance sensor แล้วจะนำค่าที่อ่านได้ที่ระยะต่างๆมาใช้ครับ
Title: Re: ADC กับ ATmega8
Post by: skytec on February 05, 2015, 08:18:41 PM
Quote from: nutzty on February 05, 2015, 08:09:57 PM
ขอคำปรึกษาเกี่ยวกับ ADC ของ ATmega8 หน่อยครับ พอดีอ่าน datasheet แล้วสงสัยว่าหลังจาก conversion เสร็จแล้วค่าที่อ่านมาได้จะถูกเก็บไว้ที่ ADCH/ADCL ใน ADLAR ถูกไหมครับ และถ้าเราจะนำค่าที่อ่านได้มาใช้ต่อเนี่ย สามารถเขียนโค้ดในลักษณะใดได้บ้างครับ

ปล. ADC ที่จะใช้คือรับค่ามาจาก infrared distance sensor แล้วจะนำค่าที่อ่านได้ที่ระยะต่างๆมาใช้ครับ

ผมใช้แบบโง่ๆ เลยครับ คือ ใช้  Arduino  ครับ แล้วเลือกพรอตเป็น ATMEGA8 ครับ เขียนตามตัวอย่างของมันเลย ง่ายดี
Title: Re: ADC กับ ATmega8
Post by: nutzty on February 05, 2015, 08:27:35 PM
ถ้าใช้ arduino มันง่ายก็ใช่ครับ ผมลองใช้แล้ว แต่ตัวงานถูกบังคับให้ใช้ ATmeg8 ครับ
Title: Re: ADC กับ ATmega8
Post by: JENG on February 05, 2015, 10:13:46 PM
//analog initial
void analog_initial(void){


    //Set ADC prescalar to 128 - 125KHz sample rate @ 16MHz
    ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);


    //Set ADC prescalar to 64 - 125KHz sample rate @ 8MHz
    //ADCSRA |= (1<<ADPS2)|(1<<ADPS1);




    //ADMUX |= (1<<REFS1);            //Set ADC reference to 2.56v
    ADMUX |= (1<<REFS0);            //Set ADC reference to AVCC
    //ADMUX |= (1<<ADLAR);            //Left adjust ADC result to allow
    //ADCSRA |= (1<<ADFR);            //Set ADC to Free-Running Mode
    ADCSRA |= (1<<ADEN);            //Enable ADC
    //ADCSRA |= (1<<ADSC);            //Start A2D Conversions


}


//analog read
unsigned int analog_read(unsigned char mux_ch){


    ADMUX &= 0b11100000;
    ADMUX |= mux_ch;                //Select ADC Channel ch must be 0-7
    ADCSRA |= (1<<ADSC);            //Start Single conversion
    while(!(ADCSRA&(1<<ADIF)));        //Wait for conversion to complete
    ADCSRA |= (1<<ADIF);            //Clear ADIF by writing one to it


    return ADC;

}
Title: Re: ADC กับ ATmega8
Post by: az on February 05, 2015, 10:14:21 PM
Quote from: nutzty on February 05, 2015, 08:09:57 PM
ขอคำปรึกษาเกี่ยวกับ ADC ของ ATmega8 หน่อยครับ พอดีอ่าน datasheet แล้วสงสัยว่าหลังจาก conversion เสร็จแล้วค่าที่อ่านมาได้จะถูกเก็บไว้ที่ ADCH/ADCL ใน ADLAR ถูกไหมครับ และถ้าเราจะนำค่าที่อ่านได้มาใช้ต่อเนี่ย สามารถเขียนโค้ดในลักษณะใดได้บ้างครับ

ปล. ADC ที่จะใช้คือรับค่ามาจาก infrared distance sensor แล้วจะนำค่าที่อ่านได้ที่ระยะต่างๆมาใช้ครับ

ประกาศตัวแปรมารับค่าจาก port ADC ได้เลยครับ

unsigned  w_sensor = ADC;  // ADC คือ port regidter(16 bit) ประกอบด้วย ADCH(8 bit), ADCL(8bit)

ถ้าใช้ 10 bit หลังจะได้ค่า 0 - 1023

(http://i.imgur.com/I9bhbgV.png)

ปล. ADLAR คือ การกำหนดว่าจะใช้ 10 bit หน้า หรือ 10 bit หลังครับ
Title: Re: ADC กับ ATmega8
Post by: nutzty on February 06, 2015, 01:23:51 AM
Quote from: JENG on February 05, 2015, 10:13:46 PM
//analog initial
void analog_initial(void){


    //Set ADC prescalar to 128 - 125KHz sample rate @ 16MHz
    ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);


    //Set ADC prescalar to 64 - 125KHz sample rate @ 8MHz
    //ADCSRA |= (1<<ADPS2)|(1<<ADPS1);




    //ADMUX |= (1<<REFS1);            //Set ADC reference to 2.56v
    ADMUX |= (1<<REFS0);            //Set ADC reference to AVCC
    //ADMUX |= (1<<ADLAR);            //Left adjust ADC result to allow
    //ADCSRA |= (1<<ADFR);            //Set ADC to Free-Running Mode
    ADCSRA |= (1<<ADEN);            //Enable ADC
    //ADCSRA |= (1<<ADSC);            //Start A2D Conversions


}


//analog read
unsigned int analog_read(unsigned char mux_ch){


    ADMUX &= 0b11100000;
    ADMUX |= mux_ch;                //Select ADC Channel ch must be 0-7
    ADCSRA |= (1<<ADSC);            //Start Single conversion
    while(!(ADCSRA&(1<<ADIF)));        //Wait for conversion to complete
    ADCSRA |= (1<<ADIF);            //Clear ADIF by writing one to it


    return ADC;

}


ไม่ใช่ว่าบรรทัดก่อน return เนี่ย ต้องใส่ 0 ให้ ADIF หรือครับ

Quote from: az on February 05, 2015, 10:14:21 PM
Quote from: nutzty on February 05, 2015, 08:09:57 PM
ขอคำปรึกษาเกี่ยวกับ ADC ของ ATmega8 หน่อยครับ พอดีอ่าน datasheet แล้วสงสัยว่าหลังจาก conversion เสร็จแล้วค่าที่อ่านมาได้จะถูกเก็บไว้ที่ ADCH/ADCL ใน ADLAR ถูกไหมครับ และถ้าเราจะนำค่าที่อ่านได้มาใช้ต่อเนี่ย สามารถเขียนโค้ดในลักษณะใดได้บ้างครับ

ปล. ADC ที่จะใช้คือรับค่ามาจาก infrared distance sensor แล้วจะนำค่าที่อ่านได้ที่ระยะต่างๆมาใช้ครับ

ประกาศตัวแปรมารับค่าจาก port ADC ได้เลยครับ

unsigned  w_sensor = ADC;  // ADC คือ port regidter(16 bit) ประกอบด้วย ADCH(8 bit), ADCL(8bit)

ถ้าใช้ 10 bit หลังจะได้ค่า 0 - 1023

(http://i.imgur.com/I9bhbgV.png)

ปล. ADLAR คือ การกำหนดว่าจะใช้ 10 bit หน้า หรือ 10 bit หลังครับ

อ๋อ คือหลังจากเลือก ADLAR แล้วก็ค่อยมาดูอีกทีว่า แต่ละแบบค่าที่ถูกแปลงแล้วถูกเก็บไว้ที่ ADCH/ADCL bit ไหนบ้างใช่ไหมครับ เช่น ADLAR = 1 ก็จะแบ่งไปเก็บใน ADCH 8 bit และ ADCL 2 bit แบบนี้เข้าใจถูกไหมครับ
Title: Re: ADC กับ ATmega8
Post by: JENG on February 06, 2015, 10:38:53 AM
อ่านเพิ่มเติมจาก data sheet เอาคับ ห้ามอ่านแบบผ่านๆนะ ผมเงิบมาแล้วเรื่อง adc ของ avr น่ะ
Title: Re: ADC กับ ATmega8
Post by: nutzty on February 07, 2015, 03:15:54 AM
Quote from: JENG on February 06, 2015, 10:38:53 AM
อ่านเพิ่มเติมจาก data sheet เอาคับ ห้ามอ่านแบบผ่านๆนะ ผมเงิบมาแล้วเรื่อง adc ของ avr น่ะ

คือใน datasheet เนี่ย ผมอ่านแล้วนะ แต่มันงงอ่ะครับ ก็เลยมาถามเอาให้แน่ใจว่าตัวเองเข้าใจถูกแล้วใช่ไหม ตอนนี้กำลังลองเขียนโปรแกรมเพื่อเช็คไปด้วยอีกทีครับ
Title: Re: ADC กับ ATmega8
Post by: JENG on February 07, 2015, 08:55:23 AM
code ที่แปะเป็น code ที่ใช้งานจริงคับ ยังมีตรงไหนไม่แน่ใจอีกหรือ  ;D
Title: Re: ADC กับ ATmega8
Post by: skytec on February 07, 2015, 10:17:24 AM
Quote from: nutzty on February 05, 2015, 08:27:35 PM
ถ้าใช้ arduino มันง่ายก็ใช่ครับ ผมลองใช้แล้ว แต่ตัวงานถูกบังคับให้ใช้ ATmeg8 ครับ

ATMEGA8 ใช้ Arduino ได้ครับ เลือก   Board : Arduino NG order W .... ครับ พอเรา comply แล้วมันจะอยู่ที่ c:\...user...\temp\.....  ครับ โดย Folder  นี้มันจะมองไม่เห็น ต้องกำหนดที่ window ให้แสดง folder ที่ซ่อนไว้ เราจะได้ file   :  ???.hex  เรา เอาตัวนี้ไปอัดลงบอร์ดเรา ครับ  ผมใช้วิธีนี้ครับ
Title: Re: ADC กับ ATmega8
Post by: nutzty on February 07, 2015, 11:11:15 PM
Quote from: JENG on February 07, 2015, 08:55:23 AM
code ที่แปะเป็น code ที่ใช้งานจริงคับ ยังมีตรงไหนไม่แน่ใจอีกหรือ  ;D

อยากลองเขียนเองไปด้วยน่ะครับ เขียนเองจะเข้าใจได้มากกว่านั่งอ่านเฉยๆ
Quote from: skytec on February 07, 2015, 10:17:24 AM
Quote from: nutzty on February 05, 2015, 08:27:35 PM
ถ้าใช้ arduino มันง่ายก็ใช่ครับ ผมลองใช้แล้ว แต่ตัวงานถูกบังคับให้ใช้ ATmeg8 ครับ

ATMEGA8 ใช้ Arduino ได้ครับ เลือก   Board : Arduino NG order W .... ครับ พอเรา comply แล้วมันจะอยู่ที่ c:\...user...\temp\.....  ครับ โดย Folder  นี้มันจะมองไม่เห็น ต้องกำหนดที่ window ให้แสดง folder ที่ซ่อนไว้ เราจะได้ file   :  ???.hex  เรา เอาตัวนี้ไปอัดลงบอร์ดเรา ครับ  ผมใช้วิธีนี้ครับ

อ้อ ผมลืมไปเลย เดี๋ยวไว้ไปลองประยุกต์ใช้อีกทีครับ
Title: Re: ADC กับ ATmega8
Post by: nai102 on February 13, 2015, 12:57:12 AM
ดาต้าชีทบอกว่า ถ้า ADLAR=1  ค่า ADC จะอยุ่ 10 bit บน
ถ้า ADLAR=จ  ค่า ADC จะอยุ่ 10 bit ล่าง

สำคัญคือ ค่า ADC จะยังไม่เปลี่ยนแปลงจนกว่าเราจะอ่านค่า ADCH
ดังนี้เพื่อให้ค่าที่ได้ถูกต้อง เราจึงต้องอ่าน ADCL ก่อน ADCH เสมอ
Title: Re: ADC กับ ATmega8
Post by: az on February 13, 2015, 09:06:55 AM
Quote from: nai102 on February 13, 2015, 12:57:12 AM
สำคัญคือ ค่า ADC จะยังไม่เปลี่ยนแปลงจนกว่าเราจะอ่านค่า ADCH
ดังนี้เพื่อให้ค่าที่ได้ถูกต้อง เราจึงต้องอ่าน ADCL ก่อน ADCH เสมอ

ถ้าอ้างอิง code จากท่าน JENG

ADLAR ค่า default = 0 (10 bit ล่าง)

ซึ่งค่า return ADC; จะได้ค่า 0 - 1023

โดยการ return ADC; สามารถอ่านค่าจาก  ADCH,ADCL พร้อมกันในคำสั่งเดียวได้เลยครับ


Quote from: JENG on February 05, 2015, 10:13:46 PM
//analog initial
void analog_initial(void){


    //Set ADC prescalar to 128 - 125KHz sample rate @ 16MHz
    ADCSRA |= (1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);


    //Set ADC prescalar to 64 - 125KHz sample rate @ 8MHz
    //ADCSRA |= (1<<ADPS2)|(1<<ADPS1);




    //ADMUX |= (1<<REFS1);            //Set ADC reference to 2.56v
    ADMUX |= (1<<REFS0);            //Set ADC reference to AVCC
    //ADMUX |= (1<<ADLAR);            //Left adjust ADC result to allow
    //ADCSRA |= (1<<ADFR);            //Set ADC to Free-Running Mode
    ADCSRA |= (1<<ADEN);            //Enable ADC
    //ADCSRA |= (1<<ADSC);            //Start A2D Conversions


}


//analog read
unsigned int analog_read(unsigned char mux_ch){


    ADMUX &= 0b11100000;
    ADMUX |= mux_ch;                //Select ADC Channel ch must be 0-7
    ADCSRA |= (1<<ADSC);            //Start Single conversion
    while(!(ADCSRA&(1<<ADIF)));        //Wait for conversion to complete
    ADCSRA |= (1<<ADIF);            //Clear ADIF by writing one to it


    return ADC;

}

Title: Re: ADC กับ ATmega8
Post by: nutzty on February 14, 2015, 07:42:03 PM
ถ้างั้นจากโค้ดของคุณ JENG ผมก็จะเขียนได้ว่า

int adc_value=0;

adc_value = analog_read(5); //สมมติว่าผมใช้ADC5

ผมก็จะได้ค่า 0-1023 มาเก็บไว้ใบ adc_value ทันทีโดยไม่ต้องไปอ่าน ADCH/ADCL เลยสินะครับ
Title: Re: ADC กับ ATmega8
Post by: az on February 15, 2015, 11:45:02 AM
Quote from: nutzty on February 14, 2015, 07:42:03 PM
ถ้างั้นจากโค้ดของคุณ JENG ผมก็จะเขียนได้ว่า

int adc_value=0;

adc_value = analog_read(5); //สมมติว่าผมใช้ADC5

ผมก็จะได้ค่า 0-1023 มาเก็บไว้ใบ adc_value ทันทีโดยไม่ต้องไปอ่าน ADCH/ADCL เลยสินะครับ

int var. เปลี่ยนเป็น unsigned short ก็พอครับ

การ return ADC; สามารถอ่านค่าจาก  ADCH,ADCL พร้อมกันในคำสั่งเดียวได้เลยครับ




Title: Re: ADC กับ ATmega8
Post by: Nhimbuzz on February 17, 2015, 06:31:08 PM
 ;D ขอบคุณครับ
Title: Re: ADC กับ ATmega8
Post by: nutzty on February 17, 2015, 11:49:53 PM
Quote from: az on February 15, 2015, 11:45:02 AM
Quote from: nutzty on February 14, 2015, 07:42:03 PM
ถ้างั้นจากโค้ดของคุณ JENG ผมก็จะเขียนได้ว่า

int adc_value=0;

adc_value = analog_read(5); //สมมติว่าผมใช้ADC5

ผมก็จะได้ค่า 0-1023 มาเก็บไว้ใบ adc_value ทันทีโดยไม่ต้องไปอ่าน ADCH/ADCL เลยสินะครับ

int var. เปลี่ยนเป็น unsigned short ก็พอครับ

การ return ADC; สามารถอ่านค่าจาก  ADCH,ADCL พร้อมกันในคำสั่งเดียวได้เลยครับ

ขอบคุณครับ ชัดแจ่มแจ้งแล้ว ตอนเขียนผมใช้ int8u ครับ