Controller (Microcontroller ATmega16)

            Controller
      ในส่วนของไมโครคอนโทรลเลอร์ เราใช้ไมโครคอนโทรลตระกูล AVR เราเลือกใช้ ATmega16 ซึ่งมีport ให้เลือกใช้ 4 port และมีฟังก์ชั่นการทำงานหลากหลาย





       รูปตัวไมโครคอนโทรลเลอร์ ATmega16



รูปตัว IC 74HC154




รูปตัว IC 74LS48


โค้ดโปรแกรมของกลุ่ม Insanely ซึ่งกลุ่มเราใช้ microcontroller แค่ตัวเดียวนะครับ คือ ATmega16 และสามารถควบคุมการทำงานได้ทั้งหมดของโครงงาน ซึ่งเป็นการใช้ทรัพยากรได้อย่างคุ้มค่า และง่ายดายสำหรับการแก้โปรแกรมควบคุมของงานเพราะแก้ที่ คอนโทรลเลอร์แค่จุดเดียว และยังประหยัดงบประมาณอีกด้วยครับ อิอิ ซึ่งโค้ดโปรแกรมของกลุ่มเรามีรายละเอียดดังต่อไปนี้
/****************************************************************** Includes */
#include <avr/io.h>                                        // AVR device-specific IO definitions
#include <avr/interrupt.h>                                          // Interrupt Service routine
#include <compat/deprecated.h>                           // Deprecated items
#include <stdio.h>                                                          // Standard Input/Output
#define F_CPU 8000000UL                           // 8 MHz
#include <util/delay.h>                                 // header file implement simple delay loops
#define DSP_DATA_POUT           PORTC      // DSPx enable (DIGIT PORT)
#define DSP_DATA_DDR                              DDRC

#define DSP_DATA_POUT1        PORTD      // DSPx enable (DIGIT PORT)
#define DSP_DATA_DDR1                           DDRD

#define LED_DATA_POUT                           PORTB                  // LED Display (DATA_PORT)
#define LED_DATA_DDR                              DDRB

unsigned int level = 0x00;
unsigned int dc_motor = 0x00;
unsigned int step_motor = 0x00;
unsigned int count_sampling = 0;
unsigned int dl = 0;
unsigned int state=0;
ในส่วนแรกจะเป็นการประกาศ Header และ Global Variable ต่างๆที่ใช้ในโปรแกรมควบคุมทั้งหมด

/********************************************************** Global variables */
const unsigned char num_led[17] = {
                                                                                0x00, 0x10, 0x20, 0x30, 0x40,  //0,1,2,3,4
                    0x50, 0x60, 0x70, 0x80, 0x90,  //5,6,7,8,9
                    0xA0, 0xB0, 0xC0, 0xD0, 0xE0,  //A,b,C,d,E
                    0xF0                          //F,.
                    };                                                                        

unsigned char num[9];                   // buffer number led
ในส่วนนี้จะเป็นการประกาศ Global Variables ของ ค่าของตัวเลขที่จะแสดงออก 7 segment เพื่อที่จะเรียกใช้ได้ง่ายในรูปแบบ อาร์เรย์
//***************************************************************
uint8_t fs1p[4] = { 0x10,0x20,0x40,0x80 };  //data full step 1 phase
ส่วนนี้จะเป็นการประกาศ Global Variables ของค่าที่จะไปขับ สเต็ปมอเตอร์ ซึ่งในที่นี้จะขับเป็นแบบ 1 เฟส Full step ซึ่งเก็บในรูปแบบของอาร์เรย์เพื่อให้เรียกใช้ได้ง่าย
//***************************************************************
unsigned int a_to_d(unsigned char ch_adc)
{
                // AVCC with external capacitor at AREF pin
                // ADC Enable & Auto Trigger Disable
                ADCSRA = (1<<ADEN)|(0<<ADATE);
                ADCSRA |= (0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);         // XTAL/8
                ADMUX   = 0<<REFS1|1<<REFS0|ch_adc;
                ADCSRA |= (1<<ADSC);
                while(!(ADCSRA &(1<<ADIF))); // wait until finish a2d
                return(ADCW);
}
ส่วนนี้จะเป็นฟังก์ชั่นเรียกใช้ ADC Converter จะถูกเรียกใช้จาก main ฟังก์ชั่น และนำค่าที่อ่านได้ไปคำนวณต่อจากนั้นก็ส่งออกจอแสดงผล
/*************************************************************** display_led */
void display_led(unsigned int dly)
{
    int i;

    for (i=0;i<dly;i++) {
               
                                DSP_DATA_POUT = 0x00 ;           // 0b1011 (DSP1 enable active)
        LED_DATA_POUT = (num_led[num[0]]|level);                                          
        _delay_ms(dl);

                                DSP_DATA_POUT = 0x01;           // 0b1101 (DSP2 enable active)
        LED_DATA_POUT = (num_led[num[1]]|0x01|level);
        _delay_ms(dl);

                                DSP_DATA_POUT = 0x02;           // 0b1110 (DSP3 enable active)
        LED_DATA_POUT = (num_led[num[2]]|level);
        _delay_ms(dl);

                                DSP_DATA_POUT = 0x03;
        LED_DATA_POUT = (num_led[num[3]]|level);                                          
        _delay_ms(dl);

                    DSP_DATA_POUT = 0x04;
        LED_DATA_POUT = (num_led[num[4]]|0x01|level);                                              
        _delay_ms(dl);

                    DSP_DATA_POUT = 0x05;
       LED_DATA_POUT = (num_led[num[5]]|level);                                           
        _delay_ms(dl);


                                DSP_DATA_POUT = 0x06;
        LED_DATA_POUT = (num_led[num[6]]|level);                                          
        _delay_ms(dl);

                                DSP_DATA_POUT = 0x07;
        LED_DATA_POUT = (num_led[num[7]]|0x01|level);                                              
        _delay_ms(dl);

                                DSP_DATA_POUT = 0x08;
        LED_DATA_POUT = (num_led[num[8]]|level);                                          
        _delay_ms(dl);                                                                                        
    }
}
ส่วนของฟังก์ชั่นนี้จะเป็นฟังก์ชั่นของการแสดงผลออกหน้าจอ โดยนำค่าที่คำนวณได้แล้วส่งออกจอ 7 segment เพื่อแสดงค่าอนาล็อกและค่าอุณหภูมิเป้าหมายรวมไปถึงการแสดงสถานะของระดับน้ำในระดับต่างๆอีกด้วย
/************************************************************ Main Functions */
int main(void)
{  

                unsigned int adc[2];
                unsigned int rom=0;
                unsigned int rom2=0;
                unsigned int count=0;
                LED_DATA_DDR = 0xFF;                                // PORTB All output
                DSP_DATA_DDR = 0x0F;                   // PORT PA0-PA3 Output
                DSP_DATA_DDR1 = 0xFF;
                num[8] = 0;
                num[7] = 0;
                num[6] = 0;
                num[5] = 0;
                num[4] = 0;
                num[3] = 0;
                num[2] = 0;
                num[1] = 0;
                num[0] = 0;
ส่วนนี้จะเป็นการ Initial ค่าเริ่มต้นการทำงานของ main function
//*********************************************************
                TCCR0 = (1<<CS02)|(0<<CS01)|(1<<CS00); //clk_IO/1024(from prescaler)
                TIMSK = (1<<TOIE0); // T/C0 overflow interrupt enable
                sei(); //set I-bit global interrupt
ส่วนนี้จะเป็นการเปิดการใช้งาน Interrupt Timer0
//*******************************************************
                                if((PINC&(1<<PINC7))!=0 && state ==0)
                                {
                                                unsigned char n = 3;
                                                unsigned int step = 2000;
                                 while(step--) {
                step_motor = fs1p[n];
                if (n-- == 0)
                n = 3;
                                                if((PINC&(1<<PINC7))==0)
                                                                step = 0;
                DSP_DATA_POUT1 = dc_motor|step_motor;
                                                display_led(1);
                                                _delay_us(100);
                                }
                                                count_sampling = 0;                      
                                }
ส่วนนี้จะเป็นการเซทสถานะของ control valve สเต็ปมอเตอร์ ให้กลับมายังจุดเริ่มต้นหรือทำให้วาล์วสเต็ปมอเตอร์ปิดสนิทก่อน(ถ้ากรณีที่วาล์วเริ่มต้นยังคงเปิดอยู่) ซึ่งส่วนนี้อยู่ใน main function
                while (1) {           
                               
                                if((PINC&(1<<PINC4))==0 && count<500){
                                                count++;
                                                _delay_ms(1);
                                                }
                                if((PINC&(1<<PINC5))==0 && count>0){
                                                count--;
                                                _delay_ms(1);
                                                }
                                if((PINC&(1<<PINC6))==0 && state == 0){
                                                dc_motor = 0x0F;
                                                state = 1;
                                                _delay_ms(1);
                                                }
                                if(rom >= 26 && state ==1){                        //edit level 30
                                                dc_motor = 0x03;
                                                level = 0x08;
                                                state = 2;
                                                }
                                if(rom >= 26 && state ==2 && (PINC&(1<<PINC6))==0){
                                                dc_motor = 0x0F;
                                                state = 3;
                                                }
                                if(rom >= 38 && state ==3){                        //edit level 40
                                                dc_motor = 0x03;
                                                level = 0x0C;
                                                state = 4;
                                                }
                                if(rom >= 38 && state ==4 && (PINC&(1<<PINC6))==0){
                                                state = 5;
                                }
                                if(rom >=38 && state ==5){
                                                state = 6;
                                                unsigned char n = 0;
                                                unsigned int step =400;
                while(step--) {
                step_motor = fs1p[n];
                if (n++ == 3)
            n = 0;
                DSP_DATA_POUT1 = dc_motor|step_motor;
                                                display_led(1);
                                                _delay_us(100);
                                }
                                count_sampling =0;
                                }
                                if(rom2 <= count+2 && state ==6 && rom >= 38){
                                                level = 0x0E;
                                                state = 7;
                                                unsigned char n = 3;
                                                unsigned int step = 2000;
                                 while(step--) {
                step_motor = fs1p[n];
                if (n-- == 0)
                n = 3;
                                                if((PINC&(1<<PINC7))==0)
                                                                step = 0;
                DSP_DATA_POUT1 = dc_motor|step_motor;
                                                display_led(1);
                                                _delay_us(100);
                                }
                                                count_sampling =0;
                                                }
ส่วนนี้จะเป็นส่วนหลักที่ใช้ในการเช็คสถานะของการทำงานว่าให้ทำงานในสถานะใด รวมไปถึงการรับอินพุทสวิทซ์ interface ด้วย และส่วนนี้จะเป็นส่วนที่สั่งการไปยังทุกส่วนให้ทำงานให้ตรงตามเป้าหมายด้วย
//****************************************************************
                                adc[0] = a_to_d(0x00);
                                adc[1] = a_to_d(0x01);

                                if(adc[0]>0 && adc[0] <= 204){
                                                adc[0] = 0;}
                                if(adc[1]>0 && adc[1] <=204){
                                                adc[1] = 0;}
                                if(adc[0]>204){
                                                adc[0] = adc[0]-204;}
                                if(adc[1]>204){
                                                adc[1] = adc[1]-204;}

                                rom = 0.1221001221*adc[0];
                                rom2 = 0.6105006105*adc[1];

                if(count_sampling == 2)
                {
                                num[8] = (rom2%1000)/100;
                    num[7] = ((rom2%1000)%100)/10;
        num[6] = ((rom2%1000)%100)%10;

                                num[2] = (rom%1000)/100;
                    num[1] = ((rom%1000)%100)/10;
        num[0] = ((rom%1000)%100)%10;
                                count_sampling =0;
                }
                                num[5] = (count%1000)/100;
                    num[4] = ((count%1000)%100)/10;
        num[3] = ((count%1000)%100)%10;
                 
                  

                                DSP_DATA_POUT1 = dc_motor|step_motor;
                                display_led(8);
    }

    return 0;
}
ส่วนนี้เป็นส่วนของการคำนวณค่าเพื่อที่จะแสดงผลออกทางหน้าจอแสดงผลทั้งหมด นั่นก็คือ อุณหภูมิที่วัดได้ อุณหภูมิเป้าหมาย ระดับน้ำ สถานะ นอกจากนั้นยังรวมไปถึงการขับวาล์วทั้งสองวาล์วอีกด้วย
//***********************************************************T/C0 Overflow Interrupt
ISR (TIMER0_OVF_vect)
{
                count_sampling ++;
}
ส่วนนี้เป็นส่วนของ Interrupt timer0 overflow ซึ่งเมื่อ Timer0 นับขึ้นไปเรื่อย จนเกิด Overflow ตัวแปร count_sampling ก็จะบวกค่าขึ้นไปเรื่อยๆ เพื่อที่จะนำไปใช้ใน main function เป็นตัวกำหนด sampling rate ให้กับโปรแกรม และเงื่อนไขอื่นๆ  จากนั้นก็นำไปคำนวณหาค่าเวลาที่ต้องการเอาไปใช้ และนำไปใช้ในส่วนของโปรแกรมที่ต้องการ โดย จะใช้ if, else หรือ while, do while ยังไงก็ได้แล้วแต่เงื่อนไขที่ต้องการเขียนขึ้นมาจากความคิดของเราเอง
หมดแล้วครับ โปรแกรมของเรานี้ ถ้าใครสนใจที่จะนำไป พัฒนาต่อหรือจะเอาไปศึกษาเพื่อความรู้ ทางกลุ่มเรายินดีเป็นอย่างยิ่งครับ ทางเราก็หวังว่าคงจะมีประโยชน์กับท่านไม่มากก็น้อย ขอบคุณครับ

 



  
รูปการออกแบบเเละการ Simulation บน Proteus software





รูปการออกแบบลายปริ้นบน ORCAD software

ไม่มีความคิดเห็น:

แสดงความคิดเห็น