Insanely Group

Insanely Group คือ ชื่อของกลุ่มของนักศึกษาที่รวมตัวกันเพื่อทำงานที่ใช้ความรู้ความสามารถที่ได้จากการศึกษาเล่าเรียนเพื่อสร้างสรรค์ชิ้นงานตามที่คณะอาจารย์มีข้อกำหนดมาให้ เพื่อหวังไว้ว่า ผลงานที่ถูกสร้างสรรค์ขึ้นมา จะเป็นผลงานที่ดีและสามารถนำไปใช้ให้เกิดประโยชน์แก่ตัวผู้สร้างและผู้สนใจ
Insanely Group คือ กลุ่มของนักศึกษาภาควิชา วิศวกรรมระบบควบคุมและเครื่องมือวัด
คณะ วิศวกรรมศาสตร์ มหาวิทยาลัยเทคโนโลยีพระจอมเกล้าธนบุรี โดยมีสมาชิกดังนี้

1.               นาย จตุกร      ดาราเย็น          รหัสนักศึกษา 52281203
2.               นาย ธนวิทย์    ทองกุล            รหัสนักศึกษา 52281213
3.               นาย นิธิโรจน์   โยชัยเหลี่ยม     รหัสนักศึกษา 52281220
4.               นาย ปริญญา   วิริยา               รหัสนักศึกษา 52281223
5.               นาย พงศักดิ์   จุมพุลพงษ์        รหัสนักศึกษา 52281225
6.               นาย วิษุวัต     โภคา               รหัสนักศึกษา 52281235


หัวข้อการทำงานในครั้งนี้ คือ สร้าง Plant การทำงานของระบบการจ่ายน้ำให้ได้ระดับที่ต้องการและระบบผสมน้ำให้ได้ตามที่อุณหภูมิที่ต้องการโดยมีข้อกำหนดตามที่อาจารย์กำหนดให้







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