arduino 3 phase motor speed control · โปรแกรม Arduino NANO ขับโมดูล TM-35 เวอร์ชั่นปี 2019 // 3 phase PWM sine // (c) 2016 C. Masenas // ดัดแปลงเพิ่มเติม จากต้นฉับ DDS generator ของ KHM 2009 / Martin Nawrath // Modified Y2018 By Seree2004 #include //เรียกโปรแกรมคำสั่งการใช้งานจอแสดงผล LCD เข้ามาร่วมด้วย // ตารางข้อมูลซายเวฟ ชุดละ 256 ตัว //Amplitude_245 PROGMEM const unsigned char Sine_Table[256] = {123,126,129,132,135,137,140,143,146,149,152,155,158,161,164,167,169,172,175,178,180,183,185,188,191,193,195,198,200,203,205,207, 209,211,213,215,217,219,221,223,224,226,228,229,231,232,233,234,236,237,238,239,240,241,241,242,243,243,244,244,244,245,245,245, 245,245,245,245,244,244,244,243,243,242,241,241,240,239,238,237,236,234,233,232,231,229,228,226,224,223,221,219,217,215,213,211, 209,207,205,203,200,198,195,193,191,188,185,183,180,178,175,172,169,167,164,161,158,155,152,149,146,143,140,137,135,132,129,126, 123,119,116,113,110,108,105,102,99,96,93,90,87,84,81,78,76,73,70,67,65,62,60,57,54,52,50,47,45,42,40,38, 36,34,32,30,28,26,24,22,21,19,17,16,14,13,12,11,9,8,7,6,5,4,4,3,2,2,1,1,1,0,0,0, 0,0,0,0,1,1,1,2,2,3,4,4,5,6,7,8,9,11,12,13,14,16,17,19,21,22,24,26,28,30,32,34, 36,38,40,42,45,47,50,52,54,57,60,62,65,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,110,113,116,119}; // เปลี่ยนวิธีการสั่งเซทค่าของรีจีสเตอร์ภายในของ Arduino ใหม่เพื่อให้เรียกใช้ง่ายขึ้น #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // เปลี่ยนชื่อเรียกขาของ Arduino ใหม่เพื่อให้จำง่ายในการต่อวงจร #define PWM_OUT_UL 6 // PWM1 UL output #define PWM_OUT_UH 5 // PWM1 UH output #define PWM_OUT_VL 9 // PWM2 VL output #define PWM_OUT_VH 10 // PWM2 VH output #define PWM_OUT_WL 11 // PWM3 WL output #define PWM_OUT_WH 3 // PWM3 WH output #define testPin 13 // Test OutPut เพื่อกระพริบหลอดไฟ LED #define enablePin 8 // เพื่อปิด/เปิดภาค Power Driver #define single_3ph 12 //เพือตัวจั้มเปอร์ ให้เป็นแบบ ซิงเกิลเฟส หรือ แบบ 3 เฟส #define FAULT_DETECT 2 //เพื่อตรวจรับสัญญาณผิดพลาดต่างๆจะได้ปิดภาค Power Driver ก่อนที่จะทำให้อุปกรณ์เสียหาย #define FREQ_POT 0 // เพื่อเต่อกับวอลลุ่มปรับความถี่ analog input A0 //#define CURRENT_POT 1 // สำรองไว้ analog input A1 #define WATER 1 // สวิตช์ลูกลอย #define USER1 6 // สำรองไว้ analog input A6 #define USER2 7 // สำรองไว้ analog input A7 // ตั้งชื่อการกำหนดค่า DeadTime #define DT_LOW 5 // DeadTime Low Side #define DT_HIGH DT_LOW*2 // DeadTime High Side // ตั้งชื่อการกำหนดค่าของ วอลลุ่มปรับความเร็วรอบ (Hz)ต่ำสุดและสูงสุด #define FREQ_MIN 7 // default: 15 #define FREQ_MAX 60 // default: 90 #define MAX_AMP_AT 50 // ให้ความแรง Amplitude สูงสุดที่ 50 Hz // เปลี่ยนชื่อเรียกค่าตายตัวของตัวปรับวอลลุ่มของ Arduino ซึ่งเป็นความสามารถของ MCU ในแต่ละเบอร์อาจต่างกัน #define POT_MIN 0 // default: 0 #define POT_MAX 1023 // default: 1023 #define MAX_Amplitude 64 #define TABLE_DIV 64 // การตั้งชื่อตัวแปรต่าง ๆ ที่ใช้ในตัวโปรแกรม volatile float freq = 15; const float refclk = 3921 ; // ค่าตายตัวที่ได้มาจากการคำนวน คริสตอลที่ใช้ 16 MHz/8/510/256 = 15.318 // ตั้งชื่อตัวแปรที่ใช้ในการคำนวนรอบของสัญญาณซายเวฟและต่อเนื่องกันอย่างสมบูรณ์ interrupt service declared as voilatile volatile unsigned long sigma; // phase accumulator volatile unsigned long delta; // phase increment volatile unsigned long c4ms; // counter incremented every 4ms //ตั้งชื่อตัวแปรต่าง ๆ byte character1[8] = {0,18,18,18,18,18,27,0}; byte character2[8] = {0,14,17,29,21,21,25,0}; byte character3[8] = {0,4,4,4,4,4,6,0}; byte character4[8] = {0,2,31,1,29,19,25,0}; byte character5[8] = {1,15,6,9,14,1,6,0}; byte phase0, phase1, phase2, freq_old, freq_new,temp,temp2,Amplitude; unsigned int temp_ocr0a, temp_ocr0b, temp_ocr1a, temp_ocr1b, temp_ocr2a, temp_ocr2b; unsigned int SW_WATER = 0; bool single = false; bool testPin_status = false; // ตั้งชื่อค่าตายตัวที่เรากำหนดในการต่อขาต่าง ๆ ของ Arduino เข้ากับจอ LCD เพื่อให้จำง่าย const int RS = 7, EN = 4, D4 = A2, D5 = A3, D6 = A4, D7 = A5; // แล้วสั่งให้กำหนดตามนี้ได้เลย LiquidCrystal lcd(RS, EN, D4, D5, D6, D7); //*********** เปลี่ยน Version ที่นี่ **************************** char My_Version[] = "TM35V-21-01-2019"; //********************************************************* // เริ่มต้นตัวโปรแกรมโดยคำสั่งตั้งค่าต่าง ๆ ก่อน void setup(){ //------------------------------------ pinMode(FAULT_DETECT,OUTPUT); digitalWrite(FAULT_DETECT, LOW); //------------------------------------ pinMode(enablePin, OUTPUT); // สั่งเซตให้เป็นขาสัญญาณออก digitalWrite(enablePin, LOW); // สั่งให้ขานี้ ปิด (เป็น0) เพื่อทำให้ภาค Power Drive อย่าเพิ่งทำงานตอนนี้ pinMode(testPin, OUTPUT); // สั่งเซตให้เป็นขาสัญญาณออก pinMode(single_3ph, INPUT_PULLUP); // สั่งเซตให้เป็นขารับสัญญาณเข้า และ พูลอัพ pinMode(PWM_OUT_UL, OUTPUT); // สั่งเซตให้เป็นขาสัญญาณออก pinMode(PWM_OUT_UH, OUTPUT); // สั่งเซตให้เป็นขาสัญญาณออก pinMode(PWM_OUT_VL, OUTPUT); // สั่งเซตให้เป็นขาสัญญาณออก pinMode(PWM_OUT_VH, OUTPUT); // สั่งเซตให้เป็นขาสัญญาณออก pinMode(PWM_OUT_WL, OUTPUT); // สั่งเซตให้เป็นขาสัญญาณออก pinMode(PWM_OUT_WH, OUTPUT); // สั่งเซตให้เป็นขาสัญญาณออก if (digitalRead(single_3ph) == LOW){single = true;} // ตรวจสอบว่าขาจั้มเปอร์จั้มเป็นซิงเกิลเฟสหรือเปล่า ถ้าจั้มก็บอกว่า จริง ถ้าไม่จ้ัมก็บอกว่า เท็จ lcd.begin(16,2); // เริ่มเปิดใช้งานจอแสดงผล LCD lcd.createChar(0,character1); lcd.createChar(1,character2); lcd.createChar(2,character3); lcd.createChar(3,character4); lcd.createChar(4,character5); lcd.setCursor(5, 0); // สังให้แสดงผลคอลั่มที่ 5 ในบรรทัดแรก (0) lcd.write(byte(0)); lcd.write(byte(1)); lcd.write(byte(1)); lcd.write(byte(2)); lcd.write(byte(3)); lcd.write(byte(4)); lcd.setCursor(0, 1); for (temp=0; temp <= 16; temp++){ lcd.print(My_Version[temp]); delay(200); } delay(1000); // หน่วงเวลาให้แสดงผลนี้ เป็นเวลานาน 3 วินาที //----------------------------------------------------------------------------- if (single == true){ // ถ้าตัวจั้มเปอร์เป็นจริงก็ให้แสดงผล ที่ คอลั่ม 13 บรรทัดแรก 1PH lcd.setCursor(11, 0); lcd.print("~J1PH"); } else{ lcd.setCursor(11, 0); // หรือถ้าตัวจั้มเปอร์เป็นเท็จ ก็ให้แสดงผลที่ คอลั่ม 13 บรรทัดแรก 3PH lcd.print("~J3PH"); } //---------------------------------------------------------------------------- lcd.setCursor(0, 0); // แสดงผลที่คอลั่ม 1 บรรทัดแรก คำว่า Amplitude รอไว้ก่อนเพื่อให้ค่าจริงมาต่อ lcd.print("Amplitude:"); lcd.setCursor(0, 1); // แสดงผลที่คอลั่ม 1 บรรทัด 2 คำว่า Frequency รอไว้ก่อนเพื่อให้ค่าจริงมาต่อ lcd.print("Frequency:"); //----------------------------------------------------------------------------- // ไปเรียกโปรแกรมการตั้งค่า ไทม์เเมอร์ เพื่อกำหนดค่าการสร้างสัญญาณ PWM 3 ชุด โดยใช้ตัวไทม์เมอร์ของ Arduino ทั้ง 3 ตัว Setup the timers setup_timer0(); setup_timer1(); setup_timer2(); // ส่วนนี้เป็นการคำนวนตามสูตรเพื่อ ให้ได้สัญญาณซายเวฟครบวงรอบต่อเนื่องต้องใช้ความละเอียดถึง 32 บิต และจะได้ผลลับที่ 8 บิต สูงสุด แต่เวลาใช้งานจะต้องเลื่อนบิตกลับมาใชั 8 บิตล่าง delta = pow(2,32)*freq/refclk ; //----------------------------------------------------------------------------- digitalWrite(FAULT_DETECT, HIGH); pinMode(FAULT_DETECT, INPUT_PULLUP); // สั่งเซตให้เป็นขารับสัญญาณเข้า และ พูลอัพ attachInterrupt(0, fault, LOW); //----------------------------------------------------------------------------- freq_old = 5; //----------------------------------------------------------------------------- digitalWrite(enablePin, HIGH); // เปิด ภาค Power Drive ให้เริ่มทำงานได้ freq_new = map(analogRead(FREQ_POT), POT_MIN, POT_MAX, FREQ_MIN, FREQ_MAX); changeFreq_ramp(freq_new); freq_old = freq_new; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- void loop(){ if (testPin_status){ freq_new = map(analogRead(FREQ_POT), POT_MIN, POT_MAX, FREQ_MIN, FREQ_MAX); SW_WATER = map(analogRead(WATER), POT_MIN, POT_MAX, 0, 100); if (freq_new != freq_old){ changeFreq(freq_new); freq_old = freq_new; } if (SW_WATER >= 15){ digitalWrite(enablePin, LOW); // ปิด ภาค Power Drive ให้หยุดทำงาน digitalWrite(testPin, HIGH); cbi (TIMSK2,TOIE2); // หยุดพการทำงานของไทม์เมอร์ 2 disable timer2 overflow detect OCR0A=0; OCR0B=0; OCR1A=0; OCR1B=0; OCR2A=0; OCR2B=0; detachInterrupt(0); lcd.setCursor(10, 1); lcd.print("!WAIT!"); //-------------------หยุดรอจนกว่าสวิตช์ลูกลอยเปิด------------------ while(map(analogRead(WATER), POT_MIN, POT_MAX, 0, 100) >= 15); //------------------------------------------------------------ freq_old = 5; freq_new = map(analogRead(FREQ_POT), POT_MIN, POT_MAX, FREQ_MIN, FREQ_MAX); digitalWrite(enablePin, HIGH); // เปิด ภาค Power Drive ให้เริ่มทำงาน attachInterrupt(0, fault, LOW); changeFreq_ramp(freq_new); freq_old = freq_new; } } delay(10); } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // ชุดคำสั่งในการเปลี่ยนความถี่ void changeFreq(float _freq){ temp2 = _freq; Amplitude = temp2 + 20; if (Amplitude >= MAX_Amplitude){Amplitude = MAX_Amplitude;} // ล๊อค Amplitude lcd.setCursor(10, 0); lcd.print(Amplitude); lcd.setCursor(10, 1); lcd.print(temp2); lcd.print(" Hz "); cbi (TIMSK2,TOIE2); // หยุดการทำงานของไทม์เมอร์ 2 disable timer2 overflow detect freq = _freq; delta=pow(2,32)*freq/refclk; // อัพเดทความถี่ใหม่ update phase increment sbi (TIMSK2,TOIE2); //เปิดให้ไทม์เมอร์ 2 ทำงาน enable timer2 overflow detect while(c4ms); } //---------------------------------------------------------------------------- // ชุดคำสั่งในการเปลี่ยนความถี่_RAMP void changeFreq_ramp(float _freq){ if (_freq > freq_old){ for (temp2 = freq_old; temp2 <= _freq; temp2++){ Amplitude = temp2 +20; if (Amplitude >= MAX_Amplitude){Amplitude = MAX_Amplitude;} // ล๊อค Amplitude lcd.setCursor(10, 0); lcd.print(Amplitude); lcd.setCursor(10, 1); lcd.print(temp2); lcd.print(" Hz "); cbi (TIMSK2,TOIE2); // หยุดการทำงานของไทม์เมอร์ 2 disable timer2 overflow detect freq = temp2; delta=pow(2,32)*freq/refclk; // อัพเดทความถี่ใหม่ update phase increment sbi (TIMSK2,TOIE2); //เปิดให้ไทม์เมอร์ 2 ทำงาน enable timer2 overflow detect while(c4ms); } } } //------------------------------------------------------------------------------ // ชุดคำสั่งในการตั้งค่า ไทม์เมอร์ ตัวแรก (0) // timer0 setup // set prescaler to 8, PWM mode to phase correct PWM, 16000000/512/8 = 3.9kHz clock void setup_timer0(void){ // Timer0 Clock Prescaler to :ตั้งค่าไทม์เมอร์ให้ หารอีก 8 เพื่อจะได้ความถี่ PWM ขนาด 3.9 Khz ให้เหมาะกับ IPM เบอร์เก่า ๆ cbi (TCCR0B, CS00); sbi (TCCR0B, CS01); cbi (TCCR0B, CS02); // Timer0 PWM Mode set to Phase Correct PWM cbi (TCCR0A, COM0B0); // ตั้งค่าให้ชุดส่งสัญญาณช่อง แรก (OCR0B) ให้ส่งสัญญาณออกเป็น Sine PWM ปรกติ + sbi (TCCR0A, COM0B1); sbi (TCCR0A, COM0A0); // ตั้งค่าให้ชุดส่งสัญญาณช่อง แรก (OCR0A) ให้ส่งสัญญาณออกเป็น Sine PWM กลับเฟส Invert เป็น - sbi (TCCR0A, COM0A1); sbi (TCCR0A, WGM00); //ตั้งค่าให้สัญญาณพัลซ์ทุกลูกอยู่แนวเดียวกันเสมอในทุกเฟส (Mode 1 / Phase Correct PWM) cbi (TCCR0A, WGM01); cbi (TCCR0B, WGM02); } //------------------------------------------------------------------------------ // timer1 setup // set prescaler to 8, PWM mode to phase correct PWM, 16000000/512/8 = 3.9kHz clock ให้เหมาะกับ IPM เบอร์เก่า ๆ void setup_timer1(void){ // Timer1 Clock Prescaler to :ตั้งค่าไทม์เมอร์ให้ หารอีก 8 เพื่อจะได้ความถี่ PWM ขนาด 3.9 Khz cbi (TCCR1B, CS10); sbi (TCCR1B, CS11); cbi (TCCR1B, CS12); // Timer1 PWM Mode set to Phase Correct PWM cbi (TCCR1A, COM1B0); // ตั้งค่าให้ชุดส่งสัญญาณช่อง 2(OCR1B) ให้ส่งสัญญาณออกเป็น Sine PWM ปรกติ + sbi (TCCR1A, COM1B1); sbi (TCCR1A, COM1A0); // ตั้งค่าให้ชุดส่งสัญญาณช่อง 2(OCR1A) ให้ส่งสัญญาณออกเป็น Sine PWM กลับเฟส Invert เป็น - sbi (TCCR1A, COM1A1); sbi (TCCR1A, WGM10); //ตั้งค่าให้สัญญาณพัลซ์ทุกลูกอยู่แนวเดียวกันเสมอในทุกเฟส (Mode 1 / Phase Correct PWM) cbi (TCCR1A, WGM11); cbi (TCCR1B, WGM12); cbi (TCCR1B, WGM13); } //------------------------------------------------------------------------------ // timer2 setup // set prescaler to 8, PWM mode to phase correct PWM, 16000000/512/8 = 3.9kHz clock ให้เหมาะกับ IPM เบอร์เก่า ๆ void setup_timer2(void){ // Timer1 Clock Prescaler to :ตั้งค่าไทม์เมอร์ให้ หารอีก 8 เพื่อจะได้ความถี่ PWM ขนาด 3.9 Khz // Timer2 Clock Prescaler to : /8 cbi (TCCR2B, CS20); sbi (TCCR2B, CS21); cbi (TCCR2B, CS22); // Timer2 PWM Mode set to Phase Correct PWM cbi (TCCR2A, COM2B0); // ตั้งค่าให้ชุดส่งสัญญาณช่อง 3(OCR2B) ให้ส่งสัญญาณออกเป็น Sine PWM ปรกติ + sbi (TCCR2A, COM2B1); sbi (TCCR2A, COM2A0); // ตั้งค่าให้ชุดส่งสัญญาณช่อง 3(OCR2A) ให้ส่งสัญญาณออกเป็น Sine PWM กลับเฟส Invert เป็น - sbi (TCCR2A, COM2A1); sbi (TCCR2A, WGM20); //ตั้งค่าให้สัญญาณพัลซ์ทุกลูกอยู่แนวเดียวกันเสมอในทุกเฟส (Mode 1 / Phase Correct PWM) cbi (TCCR2A, WGM21); cbi (TCCR2B, WGM22); } //------------------------------------------------------------------------------ // ส่งInterrupt Service Routine attached to INT0 vector void fault(){ digitalWrite(enablePin, LOW); // สั่งให้ขานี้ ปิด (เป็น0) เพื่อทำให้ภาค Power Drive อย่าเพิ่งทำงานตอนนี้ digitalWrite(testPin, HIGH); cbi (TIMSK2,TOIE2); // หยุดพการทำงานของไทม์เมอร์ 2 disable timer2 overflow detect OCR0A=0; OCR0B=0; OCR1A=0; OCR1B=0; OCR2A=0; OCR2B=0; lcd.clear(); lcd.setCursor(0, 0); // สังให้แสดงผลคอลั่มที่ 1 ในบรรทัดแรก (0) lcd.print("!!Detect Error!!"); // แสดงผล Error lcd.setCursor(0, 1); // สังให้แสดงผลคอลั่มที่ 1 ในบรรทัด 2 (1) lcd.print(" Pls Switch OFF "); while(1){}; // หยุดการทำงานตลอดไป จนกว่าจะ รีเซต หรือปิด เปิด ไฟเข้าเครื่องใหม่ } //------------------------------------------------------------------------------ //การที่จะได้สัญญาณ ซายเวฟ ที่มีความถี่แม่นยำตามที่เราตั้งค่าต่าง ๆ ไว้ ต้องอาศัยการนับเวลาของตัวไทม์ เมอร์ 2 และเมื่อนับครบตามที่เราตั้งไว้ต้องมาทำตามคำสั่งชุดนี้ // Timer2 Interrupt Service at 31372,550 KHz = 32uSec // this is the timebase REFCLOCK for the DDS generator // runtime : 8 microseconds ( inclusive push and pop) ISR(TIMER2_OVF_vect) { // สูตรการคำนวน ความถี่กลับมา แล้วเลื่อน จาก 32 บิต กลับมาใช้เพียง 8 บิตล่าง sigma=sigma+delta; // soft DDS, phase accu with 32 bits phase0=sigma >> 24; // use upper 8 bits for phase accu as frequency information //ชุดคำสั่งนี้แบ่งเป็น 2 ส่วน ชุดแรกเพื่อ ส่งสัญญาณ ซายเวฟ ทั้ง 3 คู่ ให้มีเฟสต่างกัน 0-90-180 เพื่อใช้กับมอร์เตอร์ซิงเกิ้ลเฟส และ ชุดต่อมา สำหรับ 3 เฟส 0-120-120 if (single == true){ // ถ้าจั้มเปอร์เป็นจริง ให้ทำงานส่วนนี้ คือแบบซิงเกิลเฟส phase1 = phase0 +127 ; // ค่าเฟส 1 phase2 = phase0 +63 ; // ค่าเฟส 2 //สำหรับแบบซิงเกิ้ลเฟส เฟสคู่ที่ 0 กับ เฟสคู่ที่ 1 จะกลับกัน เพื่อให้มอร์เตอร์ หมุนทิศทางเดียวกันทั้งแบบ ซิงเกิ้ล และ แบบ 3 เฟส // นำค่าที่อ่านได้จากตาราง ซายเวฟ + ความแรงของสัญญาณ (Amplitude) + เฟส + ค่า DeadTime ออกไปที่ ขาสัญญาณออกทั้ง 3 คู่ // OCR0A=(uint8_t)pgm_read_byte_near((Sine_Table + ADD_AMPD) + phase1)+DT_LOW; temp_ocr0a = pgm_read_byte_near(Sine_Table + phase1) * (Amplitude) / (TABLE_DIV) + DT_HIGH; temp_ocr0b = pgm_read_byte_near(Sine_Table + phase1) * (Amplitude) / (TABLE_DIV) + DT_LOW; temp_ocr1a = pgm_read_byte_near(Sine_Table + phase0) * (Amplitude) / (TABLE_DIV) + DT_HIGH; temp_ocr1b = pgm_read_byte_near(Sine_Table + phase0) * (Amplitude) / (TABLE_DIV) + DT_LOW; temp_ocr2a = pgm_read_byte_near(Sine_Table + phase2) * (Amplitude) / (TABLE_DIV) + DT_HIGH; temp_ocr2b = pgm_read_byte_near(Sine_Table + phase2) * (Amplitude) / (TABLE_DIV) + DT_LOW; OCR0A=(uint8_t) temp_ocr0a; // pin D6 OCR0B=(uint8_t) temp_ocr0b; // pin D5 OCR1A=(uint8_t) temp_ocr1a; // pin D9 OCR1B=(uint8_t) temp_ocr1b; // pin D10 OCR2A=(uint8_t) temp_ocr2a; // pin D11 OCR2B=(uint8_t) temp_ocr2b; // pin D3 } //---------------------- ถ้าจั้มเปอร์เป็นเท็จ ให้ทำงานส่วนนี้ คือแบบ 3 เฟส ที่มีเฟสต่างกัน 120 องศา------------------------------------------------------------------ else{ phase1 = phase0 +85 ; // ค่าเฟส 1 phase2 = phase0 +170 ; // ค่าเฟส 2 // นำค่าที่อ่านได้จากตาราง ซายเวฟ + ความแรงของสัญญาณ (Amplitude) + เฟส + ค่า DeadTime ออกไปที่ ขาสัญญาณออกทั้ง 3 คู่ temp_ocr0a = pgm_read_byte_near(Sine_Table + phase0) * (Amplitude) / (TABLE_DIV) + DT_HIGH; temp_ocr0b = pgm_read_byte_near(Sine_Table + phase0) * (Amplitude) / (TABLE_DIV) + DT_LOW; temp_ocr1a = pgm_read_byte_near(Sine_Table + phase1) * (Amplitude) / (TABLE_DIV) + DT_HIGH; temp_ocr1b = pgm_read_byte_near(Sine_Table + phase1) * (Amplitude) / (TABLE_DIV) + DT_LOW; temp_ocr2a = pgm_read_byte_near(Sine_Table + phase2) * (Amplitude) / (TABLE_DIV) + DT_HIGH; temp_ocr2b = pgm_read_byte_near(Sine_Table + phase2) * (Amplitude) / (TABLE_DIV) + DT_LOW; OCR0A=(uint8_t) temp_ocr0a; // pin D6 OCR0B=(uint8_t) temp_ocr0b; // pin D5 OCR1A=(uint8_t) temp_ocr1a; // pin D9 OCR1B=(uint8_t) temp_ocr1b; // pin D10 OCR2A=(uint8_t) temp_ocr2a; // pin D11 OCR2B=(uint8_t) temp_ocr2b; // pin D3 } if (c4ms++ == 500){ c4ms = 0; digitalWrite(testPin, testPin_status); testPin_status = !testPin_status; } } //จบโปรแกรมแล้วครับใครจะเขียนเพิ่มเติมอะไรได้ครับ แต่อย่าลืมให้เครดิตผู้ที่เขียนต้นฉบับด้วยครับsompong-tungmepol: Analog Control Arduino

sompong-tungmepol: Analog Control Arduino

ความคิดเห็น

โพสต์ยอดนิยมจากบล็อกนี้

ความดับทุกข์#อนิมิตตวิโมกข์#อัปปณิหิตวิโมกข์#สุญญตวิโมกข์#เธออย่าได้กล่า...เข้าสู่ระบบหรือลงทะเบียน หน้าแรก เว็บบอร์ด > พุทธศาสนา > พระไตรปิฎก > เรื่องเด่นคนกิเลสหนากับการบรรลุธรรม ในห้อง 'พระไตรปิฎก' ตั้งกระทู้โดย rachotp, 4 พฤศจิกายน 2021. แท็ก: เพิ่มแท็ก rachotp rachotp เป็นที่รู้จักกันดี สมาชิก Premium ผู้สนับสนุนเว็บพลังจิต วันที่สมัครสมาชิก:9 ตุลาคม 2020 โพสต์:1,214 กระทู้เรื่องเด่น:251 ค่าพลัง:+23,278 A.PNG การบรรลุธรรมของคนที่มีกิเลสหนา เรื่องน่าคิดจากพระไตรปิฎก หลายท่านอาจจะสงสัยว่า “คนที่มีกิเลสหนา บรรลุธรรมไม่ได้” และเชื่อกันมาแบบนี้ แต่พระพุทธเจ้าตรัสถึงเรื่องนี้ไว้ในพระสูตรที่มีชื่อว่า วิตถารสูตร ถึงการบรรลุธรรมของคนที่มีกิเลสหนา ไว้ว่า… บุคคลบางคนในโลกนี้ ตามปกติเป็นผู้มีความกำหนัดยินดีในกาม (ราคะ) ย่อมได้เสวยทุกข์โทมนัสอันเกิดจากความกำหนัดยินดีในกามตลอด เป็นผู้มีความโกรธ (โทสะ) รุนแรง ย่อมได้เสวยทุกข์โทมนัสที่เกิดจากความโกรธตลอด เป็นผู้ที่มีความหลง (โมหะ) รุนแรง ย่อมได้เสวยทุกข์โทมนัสที่เกิดจากความหลงตลอด G.PNG แต่อินทรีย์ 5 ประการ ได้แก่ ศรัทธา วิริยะ สติ สมาธิ และปัญญา เหล่านี้มีความแรงกล้า เขาย่อมบรรลุธรรมอย่างฉับพลัน แต่หากคนผู้นั้นมีกิเลสเป็นราคะ โทสะ และโมหะเบาบาง ไม่ได้มีความทุกข์โทมนัสจากราคะ โทสะ และโมหะ แต่อินทรีย์ทั้ง 5 ประการนี้อ่อน เขาย่อมได้บรรลุมรรคผลล่าช้า การบรรลุธรรมจึงขึ้นอยู่กับอินทรีย์ 5 ประการ F.PNG ระดับของการบรรลุธรรม การบรรลุธรรมของคนที่มีกิเลสหนาถึงจะขึ้นอยู่กับอินทรีย์ 5 แต่ก็มีความช้าและความเร็วแตกต่างกันไป พระพุทธเจ้าทรงจัดระดับไว้ 4 ระดับด้วยกันคือ 1) ทุกขาปฏิปทา ทันธาภิญญา หมายถึง ผู้ที่มีกิเลสหนา แต่มีอินทรีย์ 5 ประการบาง จึงบรรลุธรรมได้ช้า 2) ทุกขาปฏิปทา ขิปปาภิญญา หมายถึง ผู้ที่มีกิเลสหนา แต่มีอินทรีย์ 5 ประการแรงกล้า จึงบรรลุธรรมได้ไว 3) สุขาปฏิปทา ทันธาภิญญา หมายถึง ผู้ที่ไม่มีกิเลส แต่มีอินทรีย์ 5 ประการบาง จึงบรรลุธรรมช้า 4) สุขาปฏิปทา ขิปปาภิญญา หมายถึง ผู้ที่ไม่มีกิเลส และมีอินทรีย์ 5 ประการแรงกล้า จึงบรรลุธรรมได้ไว H.png ทำไมการบรรลุธรรมจึงเกี่ยวข้องกับอินทรีย์ 5 ประการ? อินทรีย์ 5 ได้แก่ ศรัทธา วิริยะ สติ สมาธิ และปัญญา เป็นองค์ธรรมที่ช่วยให้โลภะ โทสะ และโมหะ ลดลง เมื่อมีความเชื่อมั่น (ศรัทธา) ต่อคำสอนของพระพุทธเจ้า จะเกิดความเพียร (วิริยะ) การระลึกรู้ได้ก็จะตามมา (สติ) เมื่อเกิดการระลึกได้สมาธิก็จะตามมา เมื่อมีสมาธิผลที่ได้คือปัญญา ผู้บรรลุอรหันต์ล้วนผ่านองค์ธรรม 5 ประการนี้ D.PNG ตัวอย่างเช่น เจ้าหญิงอภิรูปนันทา เป็นสตรีชนชั้นสูงที่มีความงามเป็นเลิศ จึงมีอุปนิสัยรักสวยรักงาม พอผนวชเป็นภิกษุณี ก็ยังไม่ทรงละอุปนิสัยรักสวยรักงามอยู่ดี พระพุทธเจ้าทรงต้องการโปรดเจ้าหญิงอภิรูปนันทาให้ทราบถึงโทษของการรักสวยรักงาม พระพุทธเจ้าทรงเนรมิตสตรีนางหนึ่งขึ้นมาให้มีความงามประดุจนางฟ้า เจ้าหญิงทรงหลงใหลแล้วชมว่า สตรีนางนี้ช่างมีความงดงามมากกว่าสตรีใดๆที่้เคยพบเห็นมา ไม่นานสตรีนางนี้ก็ค่อยๆ แก่ลง แล้วตายกลายสภาพเป็นศพ และเริ่มเน่าส่งกลิ่นเหม็น แล้วกลายเป็นโครงกระดูกในที่สุด E.PNG เมื่อเจ้าหญิงอภิรูปนันทาทอดพระเนตรดังนั้นแล้วทรงเชื่อ (ศรัทธา) ในคำสอนของพระพุทธเจ้าแล้วว่าการยึดติดในความงามเป็นสิ่งที่เที่ยง แท้ที่จริงแล้วมันเป็นสิ่งที่ไม่เที่ยง เมื่อเจ้าหญิงทรงพิจารณาร่างของสตรีนางนั้นด้วยความตั้งใจ (วิริยะ) เมื่อทรงสังเกตพินิจพิจารณาจนถึงตอนที่สตรีนางนั้นสิ้นลม การระลึกรู้ (สติ) ถึงคำสอนของพระพุทธเจ้าก็บังเกิดขึ้นในบัดนั้นทันที พอทรงมีสติพิจารณาใคร่ครวญอย่างถี่ถ้วนดีแล้ว จึงบังเกิดความสงบ (สมาธิ) ขึ้น เจ้าหญิงอภิรูปนันทาเกิดความเข้าพระทัยว่า สิ่งที่พระนางหลงใหล (โลภะ) ในความงามนั้น เป็นความเขลาเบาปัญญา ทำให้พระนางตรึงอยู่ในกระแสแห่งการเวียนว่ายตายเกิดต่อไป B.PNG พระนางทรงข้ามฝั่งแห่งน่านน้ำอวิชชามาถึงฝั่งแห่งวิชชา อันเกิดจากการพิจารณาร่างของสตรีซึ่งถูกเนรมิต จนทำให้พระนางบรรลุธรรม เจ้าหญิงอภิรูปนันทา เป็นตัวอย่างที่ทำให้เห็นว่าคนที่มีกิเลสหนา ที่บรรลุธรรมได้นั้นมีอยู่จริง แต่อินทรีย์ 5 ประการของพระนางถึงพร้อม พระพุทธเจ้าทรงเห็นจึงได้มาโปรดพระนางด้วยวิธีนี้จนพระนางบรรลุธรรม C.PNG Credit: ขอขอบพระคุณที่มาจาก วิตถารสูตร ว่าด้วยปฏิปทาโดยพิสดาร พระไตรปิฎกเล่มที่ ๒๑ พระสุตตันตปิฎกเล่มที่ ๑๓ [ฉบับมหาจุฬาฯ] อังคุตตรนิกาย จตุกกนิบาต "นะโม วิมุตตานัง นะโม วิมุตติยา" "ชินะปัญชะระ ปะริตตังมัง รักขะตุสัพพะทา" "มะอะอุ นะโม วิมุตตานัง นะโมวิมุตติยา ราหุ สุริยัง จันทัง ปะมุจจะสุ" "พุท ธะ สัง วิ หะ ระ ตัง ปุญ ญัง วะ ทา มิ"