วันเสาร์ที่ 20 ธันวาคม พ.ศ. 2557

การทดลองปฏิบัติเกี่ยวกับ ultrasonic sensor, timers, external interrupt, pin change interrupt

โจทย์


- ทดลองใช้งานโมดูล HC-SR04
- เขียนโค้ด Arduino โดยไม่ใช้คำสั่ง PulseIn() ของ Arduino แต่ให้ใช้ Timer 1 เพื่อวัดความกว้างของช่วงเวลา(ใช้ Timer1 สร้างฐานเวลาในการนับ)
- ใช้ External Interrupt 0 หรือ 1 และใช้ ISR ที่เกี่ยวข้องอ่านค่าเวลา 2 ครั้ง (ขอลขาขึ้นและขอบขาลงของสัญญาณ ECHO) แล้วนำมาคำนวณช่วงกว้างของ HIGH แล้วนำค่าที่ได้ไปคำนวฯระยะห่างจากสิ่งกีดขวาง
- ใช้ออสซิลโลสโคปดูสัญญาณทั้ง TRIG และ ECHO
- ต่อวงจรใช้งานโมดูล 16 x 2 LCD เพื่อแสดงผล


อุปกรณ์ที่ใช้ในการทดลอง


บอร์ด Arduino                        1       บอร์ด
เซนเซอร์ HC-SR04                1       ชิ้น


ข้อมูลเชิงเทคนิคของเซนเซอร์ HC-SR04

    Working Voltage DC        5V
    Working Current               15mA 
    Working Frequency           40Hz
    Max Range                         4m
    Min Range                          2cm
    Measuring                           15 degree
    Trigger Input                       10uS TTL Level signal and the range in propotion
    Dimention                            45*20*15mm

ref : www.aimagin.com

การต่อวงจร



การทำงานของโปรแกรม





ผลการทดลอง







วันพฤหัสบดีที่ 25 กันยายน พ.ศ. 2557

Assignment 3

โจทย์ฝึกปฏิบัติ

1) เขียนโค้ดสำหรับบอร์ด Arduino โดยสร้างเป็น C++ Class ดังต่อไปนี้
- Class StringQueue เป็นโครงสร้างข้อมูลแบบ Queue สำหรับเก็บ String objects 
- สร้างคลาส StringQueue และทดสอบการทำงานโดยใช้โค้ดตัวอย่างต่อไปนี้ 
- ทดสอบโดยใช้ฮาร์ดแวร์จริง (ใช้บอร์ด Arduino และแสดงผลผ่าน Serial Monitor ของ Arduino IDE)

อุปกรณ์ที่ใช้ในการทดลอง

1. Arduino Uno rev.3                                                            1                 บอร์ด
2. USB connector type B                                                     1                 เส้น

code arduino



ผลการทดลอง
http://www.youtube.com/watch?v=IEt4IPuZ5Hk&feature=youtu.be


2) ใช้คลาส StringQueue ในข้อแรก นำมาเขียนโค้ด Arduino เพื่อให้มีพฤติกรรมการทำงานดังนี้ กำหนดให้มีความจุเช่น 10 ข้อความ
2.1) บอร์ด Arduino มีวงจรปุ่มกด Get ทำงานแบบ Active-Low (ใช้ตัวต้านทานแบบ Pull-up, 10k)
2.2) ผู้ใช้สามารถส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่เกิน 16 ตัวอักขระต่อบรรทัด) จากคอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino ใช้ baudrate 115200
2.3) ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringQueue ถ้าไม่เต็มความจุ แต่ถ้าเต็มความจุ ไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "Full" กลับมา และมี LED "Full" ติด
2.4) เมื่อมีการกดปุ่ม Get แล้วปล่อยหนึ่งครั้ง ข้อความแรก (ถ้ามี) ของ StringQueue จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์ และนำไปแสดงผลบนจอ 16x2 LCD ที่ต่อกับบอร์ด Arduino ด้วย แต่ถ้าไม่ข้อความใดๆ Arduino จะต้องส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย และให้มี LED "Empty" ติด
2.5) บรรทัดแรกของ LCD แสดงข้อความที่ถูกอ่านออกมาล่าสุดจาก StringQueue บรรทัดที่สอง ให้แสดงจำนวนข้อความที่มีอยู่ใน StackQueue ในขณะนั้น
2.6 16x2 LCD module สามารถยืมได้จากห้อง ESL และการเขียนโค้ดเพื่อใช้งาน LCD สามารถใช้ไลบรารี่ของ Arduino ได้



อุปกรณ์ที่ใช้ในการทดลอง

1. Arduino Uno rev.3                                                            1                 บอร์ด
2. USB connector type B                                                     1                 เส้น
3. LCD 16 X 2                                                                      1                 อัน
4. LED                                                                                 2                 อัน
5. Push button switch                                                          1                 อัน
6. ตัวต้านทานขนาด 330 ohm                                                2                 ตัว
7. ตัวต้านทานขนาด 300 ohm                                                1                 ตัว
8. สายไฟสำหรับเชื่อมต่อวงจร                                                1                 ชุด                                                                          


Wiring Diagram ด้วย Fritzing




code arduino

ประกาศตัวแปร
- ส่วนของการ import Lib สำหรับ  LCD 16X2, StringQueue
- ประกาศตัวแปรเริ่มต้นต่างๆ(State_Button, Delay, LCD)


void setup()
- set ขนาด กว้าง x ยาวของ LCD
- ตั้งค่า Timer_1 สำหรับ Delay 1 s
- และตั้งค่า push_Button, LED


Get() เมื่อมีการกดแล้วปล่อย..ปุ่ม
- จะทำการ get ค่าจาก Queue แบบ FIFO (First-In-First-Out)
- ทำการแสดงผล ตัวที่ get ผ่านทาง LCD และเมื่อหมดแล้วจะแสดงข้อความ isEmpty

* lcd.setCursor( บรรทัดไหน?(0 = บรรทัดบน 1 = บรรทัดล่าง), เริ่มตัวที่เท่าไร? )



put ไปใน Queue
- รับข้อความผ่านทาง SerialPort ขนาดไม่เกิน 16 ตัวอักษร

- จะแสดงผลผ่านทาง LCD เมื่อใส่ไปเต็ม จะแสดงว่า isFull !


ผลการทดลอง

 - ภาพแสดงการต่อวงจร




- การแสดงผลข้อมูลบน LCD
http://www.youtube.com/watch?v=k5AZPddwGpI&feature=youtu.be

วันศุกร์ที่ 12 กันยายน พ.ศ. 2557

Assignment 2

โจทย์ฝึกปฏิบัติสำหรับสัปดาห์นี้



1) เขียนโค้ดสำหรับบอร์ด Arduino โดยสร้างเป็น C++ Class ดังต่อไปนี้
=> Class StringStack เป็นโครงสร้างข้อมูลแบบ Stack (กองซ้อน) สำหรับเก็บ String objects (http://arduino.cc/en/Reference/StringObject) และกำหนด API สำหรับคลาสดังกล่าว เป็นดังนี้


/////////////////////////////////////////////////////////////////////////
‪#include <String.h>
class StringStack {
public:
StringStack( int capacity=10 ); // constructor
boolean put( String s ); // put a String object on stack
boolean get( String &s ); // get a String object from stack
inline int size(); // return the number of String objects on the stack
inline boolean isEmpty(); // return true if stack is empty, otherwise false
inline boolean isFull(); // return true if stack is full, otherwise false
private:
int capacity; // the max. capacity of the stack
int count; // used to count the number of string objects stored
String *buf; // used to store String objects on stack
};
/////////////////////////////////////////////////////////////////////////


จงสร้างคลาส StringStack และทดสอบการทำงานโดยใช้โค้ดตัวอย่างต่อไปนี้
และทดสอบโดยใช้ฮาร์ดแวร์จริง (ใช้บอร์ด Arduino และแสดงผลผ่าน Serial Monitor ของ Arduino IDE)
/////////////////////////////////////////////////////////////////////////


int num = 10; // capacity
StringStack st( num );
void setup() {
Serial.begin(115200);
}
char buf[20];
String str;
void loop() {
Serial.print( "\nPut strings: " );
for ( int i=0; i < num; i++ ) {
str = String( (i+1)*10 );
if ( !st.put( str ) ) {
Serial.println( "\nPut string error!" );
break;
} else {
Serial.print( str );
Serial.print( " " );
}
str = NULL;
delay(50);
}
delay(500);
Serial.print( "\nGet strings: " );
for ( int i=0; i < num; i++ ) {
if ( st.get( str ) ) {
str.toCharArray( buf, 20 );
Serial.print( buf );
Serial.print( " " );
} else {
Serial.println( "\nGet string error!" );
break;
}
delay(50);
}
delay(500);
}
/////////////////////////////////////////////////////////////////////////



2) ใช้คลาส StringStack ในข้อแรก นำมาเขียนโค้ด Arduino เพื่อให้มีพฤติกรรมการทำงานดังนี้
2.1) บอร์ด Arduino มีวงจรปุ่มกด Get ทำงานแบบ Active-Low (ใช้ตัวต้านทานแบบ Pull-up, 10k)
2.2) ผู้ใช้สามารถส่งข้อความ (ภาษาอังกฤษ) ทีละบรรทัด (ไม่เกิน 20 ตัวอักขระต่อบรรทัด) จากคอมพิวเตอร์ โดยส่งผ่าน Serial Monitor ของ Arduino IDE ไปยังบอร์ด Arduino
2.3) ข้อความแต่ละบรรทัดที่ถูกส่งไปยัง Arduino จะถูกจัดเก็บใน StringStack (เก็บบนกองซ้อน) ถ้าไม่เต็มความจุ แต่ถ้าเต็มความจุ ไม่สามารถเก็บข้อความใหม่ได้ Arduino จะต้องส่งข้อความ "Full" กลับมา
2.4) เมื่อมีการกดปุ่ม Get แล้วปล่อยหนึ่งครั้ง ข้อความบนสุด (ถ้ามี) ของ StringStack จะถูกดึงออกมาแล้วส่งผ่าน Serial Monitor ไปยังคอมพิวเตอร์
แต่ถ้าไม่ข้อความใดๆ Arduino จะต้องส่งข้อความ "Empty" กลับมา เมื่อกดปุ่มแล้วปล่อย


อุปกรณ์ที่ใช้ในการทดลอง
    1. Arduino Uno rev.3                                                        1                    บอร์ด
    2. ตัวต้านทาน 10 k-ohm                                                    1                    ตัว
    3. push button                                                                  1                    ตัว
    4. สายไฟ             

                                                             
การทดลองที่ 1
1.1 เขียน Class StringStack ทีทำงานได้โดย Code ที่กำหนดมาให้ด้านบน

# Constructor 
- รับค่า Capacity มากำหนด ขนาดของ Stack
- กำหนดค่าเริ่มต้นต่างๆ
StringStack::StringStack(int capacity) {              // Constructor
  count = 0;
  this->capacity = capacity;
  buf = new String [capacity];
}
# put(String s)
- จะตรวจสอบถ้า ณ ตอนนี้ Stack เต็มหรือไม่? ถ้าไม่ ก็เพิ่มเข้าไป
boolean StringStack::put(String s){               
 boolean v;
 if( isFull() == false ){     // No Full
  buf[count] = s;
  count += 1;    
  v = true;
 }
 else{        // String is Full!
  v = false;
 }
 return v;
}
# get(String s)
- จะตรวจสอบว่า ณ ตอนนี้ Stack ว่างหรือไม่? ถ้าไม่ก็เปลี่ยนตำแหน่งชี้ไปยังตัวก่อนหน้า
boolean StringStack::get(String &s){
 boolean v;
 if(isEmpty() == false){     
             count -= 1;
     *&s = buf[count];
  v = true;
 }
 else{       
  v = false;
 }
 return v;
}
# size()
- จะคืนค่า count ณ ตอนนั้น
inline int StringStack::size(){ return count; }
# isEmpty()
- จะตรวจสอบว่า Stack ณ ขณะนั้นว่างหรือไม่ ?
inline boolean StringStack::isEmpty(){
 if( size() <= 0){ 
  return true;    // isEmpty
 }  
 else{
  return false;    // Not! Empty
 }
}
# isFull()
- จะตรวจสอบว่า Stack ณ ขณะนั้นเต็มหรือไม่ ?
inline boolean StringStack::isFull(){ if( size() >= capacity){ return true; // isFull } else{ return false; // Not! Full } }
----------------------------
Output 1

(รุปแสดง Output ที่ได้)



2.1 ออกแบบวงจรปุ่มกดโดย Program Fritzing 

รูป-การออกแบบวงจรปุ่มกด

รูปแสดงการต่อวงจรปุ่มกด

Output 2

รูป output ที่ได้


Code ที่แนบ มา => Code :: 2
---------------------------------










วันศุกร์ที่ 29 สิงหาคม พ.ศ. 2557

Assignment1# Arduino LED::RGB


1# LED-RGB



Part.

  1. LED-RGB Commond Cathods          1               ตัว
  2. r 330 ohm                                      6               ตัว
  3. push_button                                   3               ตัว
  4. Arduino Broad                                1               บอร์ด
  5. สายไฟสำหรับต่อวงจร
  6. บอร์ดต่อทดลอง

Schematic.






Code.

1. TEST_SW : ทดสอบการทำงานของปุ่มกดทั้ง 3 โดย เมื่อปุ่มประจำสีใดๆ(R,G,B)ถูกกด จะทำให้ เพิ่มค่า Duty ของสีๆนั้นขึ้น ในช่วง 0-255 เมื่อครบแล้วจึงกลับไปเริ่มที่ 0 ใหม่

// file : Test_Push_Button.ino

#define red_in 10
#define green_in 9
#define blue_in 8

uint8_t red_duty = 0;   // RED_Duty (0-255)
uint8_t green_duty = 0; // GREEN_Duty (0-255)
uint8_t blue_duty = 0;  // BLUE_Duty (0-255)
boolean s1 = true;      // State_1
boolean s2 = false;     // State_2

void setup(){
  Serial.begin(9600);
  pinMode(red_in, INPUT);
  pinMode(green_in, INPUT);
  pinMode(blue_in, INPUT);
}

void loop(){
  if( s1 ){
    if((digitalRead(red_in) == LOW)||(digitalRead(green_in) == LOW)||(digitalRead(blue_in) == LOW)){ 
      delay(10); 
      s1 = false; 
      s2 = true; 
    }
  }
  if( s2 ){
    // Increase Duty ..
    if(digitalRead(red_in) == LOW){ delayMicroseconds(100); red_duty += 8; }
    else if(digitalRead(green_in) == LOW){ delayMicroseconds(100); green_duty += 8; }
    else if(digitalRead(blue_in) == LOW){ delayMicroseconds(100); blue_duty += 8; }
    
    if((digitalRead(red_in) == HIGH)||(digitalRead(green_in) == HIGH)||(digitalRead(blue_in) == HIGH)){ 
      delay(10); 
      s2 = false; 
      s1 = true; 
    }
  }
  
  // Check
  Serial.print("R");
  Serial.print( red_duty );
  Serial.print(", G");
  Serial.print( green_duty );
  Serial.print(", B");
  Serial.println(blue_duty );
}


( รูปการต่อวงจรทดสอบปุ่มกด )

( แสดงค่า Duty ของแต่ละสี ณ เวลานั้น )



2. Class RGB_LED : เป็น Class ที่เก็บหมายเลข Pin ของแต่ละสีเอาไว้ และมี Mathods สำหรับเขียนค่าให้ RGB_LED เปล่งแสงแต่ละสีออกมา

- ประกอบด้วย 
   - Constructors
      RGB_LEDint red_pin, int green_pin, int blue_pin )
      * ไว้ใช้เก็บหมายเลข Pin แต่ละสี
   -  Methods 
      set_Coloruint8_t redDuty, uint8_t greenDutyuint8_t blueDuty )
      * ไว้ใช้สำหรับกำหนดค่าสีของ LED_RGB ตามพารามิตเตอร์ที่รับมา

// file : RGB_LED.h

#include <Arduino.h>
#include <String.h>
#include <iostream>
using namespace std;

class RGB_LED {
 // Attribute
 private:
  int _red_pin;
  int _green_pin;
  int _blue_pin;
 public:
  RGB_LED(int red_pin, int green_pin, int blue_pin );
  void set_Color(uint8_t redDuty, uint8_t greenDuty, uint8_t blueDuty);
};

// file : RGB_LED.cpp

#include "RGB_LED.h"

RGB_LED::RGB_LED(int red_pin, int green_pin, int blue_pin ){ // Constructors Set Pin R,G and B
 _red_pin = red_pin;
 _green_pin = green_pin;
 _blue_pin = blue_pin;
 pinMode( _red_pin, OUTPUT );
   pinMode( _green_pin, OUTPUT );
   pinMode( _blue_pin, OUTPUT );
}

// Method Set_Color of RGB LED
void RGB_LED::set_Color(uint8_t redDuty, uint8_t greenDuty,uint8_t blueDuty){
 analogWrite( _red_pin, redDuty );
   analogWrite( _green_pin, greenDuty );
   analogWrite( _blue_pin, blueDuty );
}


3. Arduino_CODE : นำ 2 ส่วนที่กล่าวไปด้านบน มารวมกัน และใช้ Delay จากการนับตัวแปร Timer_1 ตั้ง Interrupt ไว้ที่ 1 ms

// file : RGB_LED_Ver1.ino 

#include <RGB_LED.h>

// Set_pin
#define red_in 10                            // input_SW_RED
#define green_in 9                           // input_SW_GREEN
#define blue_in 8                            // input_SW_BLUE

int redPin = 6;                              // output_RED
int greenPin = 5;                            // output_GREEN
int bluePin = 3;                             // output_BLUE

uint8_t red_duty = 0;                        // RED_Duty (0-255)
uint8_t green_duty = 0;                      // GREEN_Duty (0-255)
uint8_t blue_duty = 0;                       // BLUE_Duty (0-255)
boolean s1 = true;                           // State_1
boolean s2 = false;                          // State_2

// Delay
boolean state_debounce = false;
boolean debounce = false;
uint8_t count10ms = 10;
boolean state_100ms = false;
boolean past100ms = false;
uint8_t count100ms = 100;

RGB_LED obj( redPin, greenPin, bluePin );    // Create object from class RGB_LED

void setup(){
  T1_init();                                 // Set Timer_1 OverflowInterrupt 1 ms
  pinMode(red_in, INPUT);                    // Input red_sw
  pinMode(green_in, INPUT);                  // Input green_sw
  pinMode(blue_in, INPUT);                   // Input blue_sw
  Serial.begin(9600);
}

void loop(){
  
  // State_Input_SW
  if( s1 ){
    if((digitalRead(red_in) == LOW)||(digitalRead(green_in) == LOW)||(digitalRead(blue_in) == LOW)){
      state_debounce = true; 
      if( debounce ){                        // Debounce SW => Delay 10 ms
        s1 = false; 
        s2 = true;
        debounce = false;
      }
    }
  }
  if( s2 ){
    // Increase Duty ..(With Delay 100 ms)
    if(digitalRead(red_in) == LOW){
      state_100ms = true;                    
      if( past100ms ){ red_duty += 8; past100ms = false;}
    }
    else if(digitalRead(green_in) == LOW){ 
      state_100ms = true;
      if( past100ms ){ green_duty += 8; past100ms = false;}
    }
    else if(digitalRead(blue_in) == LOW){
      state_100ms = true;
      if( past100ms ){ blue_duty += 8; past100ms = false;}
    }
    
    if((digitalRead(red_in) == HIGH)||(digitalRead(green_in) == HIGH)||(digitalRead(blue_in) == HIGH)){ 
      state_debounce = true; 
      if( debounce ){                        // Debounce SW => Delay 10 ms
        s2 = false; 
        s1 = true;
        debounce = false;
      } 
    }
  }
  
  // Check
  Serial.print("R");
  Serial.print( red_duty );
  Serial.print(", G");
  Serial.print( green_duty );
  Serial.print(", B");
  Serial.println(blue_duty );
  
  obj.set_Color( red_duty, green_duty, blue_duty);      // Set Color
}

/* T1_init from Jannarong */
void T1_init()
{
   TCNT1  = 0;
   OCR1A  = 0;
   OCR1B  = 0;
   ICR1   = 0;
   TCCR1A = 0;
   TCCR1B = 0;
   TIMSK1 = 0; /* DISABLE ALL INTERRUPTS */
   TIFR1  = (1<<ICF1) | (1<<OCF1B) | (1<<OCF1A) | (1<<TOV1);
   
   TCNT1  = 65286; /* 2^16 - 250 = 65286 => 1 msec */
   /* USE TIMER/COUNT1 IN NORMAL MODE(NO OUTPUT COMPARE, NO PWM) */
   TCCR1B |= (1<<CS11) | (1<<CS10); /* PRESCALER = 64 */
   TIMSK1 = (1<<TOIE1); /* Timer/Countern, Overflow Interrupt Enable */
}

ISR(TIMER1_OVF_vect){
   TCNT1 = 65286;
   // Delay => debounce_SW
   if( state_debounce ){
     if( count10ms <= 0 ){
       count10ms = 10;
       state_debounce = false;
       debounce = true;
     }else{ count10ms -= 1; }
   }else{ count10ms = 10; }
   
   // Delay => increase_Duty
   if( state_100ms ){
     if( count100ms <= 0 ){
       count100ms = 100;
       state_100ms = false;
       past100ms = true;
     }else{ count100ms -= 1; }
   }else{ count100ms = 100; }
   
}



( รูปภาพแสดงการทำงาน )