การวัดรอบมอเตอร์ ด้วยบอร์ด Arduino UNO R3 กับ IR sensor และ Oled 0.96



 การวัดรอบมอเตอร์ ด้วยบอร์ด Arduino UNO R3 กับ IR sensor  และ Oled 0.96 

การเชื่อมต่อ บอร์ด Arduino UNO R3 กับ IR sensor  

GND  ------> GND

3.3V ------> VCC

2    ------> OUT

เชื่อมต่อ Oled 0.96 กับ Arduino UNO R3

Vin ---------------> 5V

GND ---------------> GND

SCL ---------------> SCL or A4

SDA ---------------> SDA or A5

// code test oled detect object 

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int ir_pin =2;

int ir_val;


void setup() {

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))  { // Address 0x3D for 128x64

    Serial.println(F("SSD1306 allocation failed"));

    for(;;);

  }

  display.display(); //Display logo

  delay(1000); 

  display.clearDisplay();

}

  

void loop() { 

  ir_val = digitalRead(ir_pin);//อ่านค่าสัญญาณ digital ขา D2 ที่ต่อกับ เซ็นเซอร์ตรวจจับวัตถุ IR Infrared  

  display.clearDisplay();

  display.setTextSize(2);

  display.setTextColor(WHITE);

  display.setCursor(0, 0);   

  display.print("Detect:");  

  if (ir_val>0) {

    display.print("No");    

  }else{

    display.print("Yes");    

  }

  display.setCursor(0, 25);     

  display.print("ir_val:");      

  display.print(ir_val);    

  display.display();

  delay(500);

}

// END code test oled detect object 

การเขียนโปรแกรม การวัดรอบของใบพัด 

รูปแบบคำสั่ง attachInterrupt(digitalPinToInterrupt(ir_sensor), IRinterrupt, FALLING);

digitalPinToInterrupt(ir_sensor) คือลำดับขาอินเตอร์รัพท์ตามที่ได้ดูไปในตารางที่ผ่านมา ใน Arduino Due สามารถใส่หมายเลขขาลงไปได้เลย

IRinterrupt คือชื่อฟังก์ชั่นที่จะไปถูกเรียกขึ้นมาเมื่อเกิดอินเตอร์รัพท์

mode รูปแบบที่จะให้เกิดอินเตอร์รัพท์ มีทั้งหมด 4 รูปแบบดังนี้

LOW จะเกิดอินเตอร์รัพท์ต่อเมื่อพอร์ตที่กำหนดไว้มีสถานะเป็น LOW

CHANGE จะเกิดอินเตอร์รัพท์เมื่อพอร์ตที่กำหนดไว้มีการเปลี่ยนสถานะ เช่น จากสถานะ HIGH เป็น LOW หรือจาก LOW เป็น HIGH

RISING จะเกิดอินเตอร์รัพท์เมื่อพอร์ตที่กำหนดไว้มีการเปลี่ยนสถานะจาก LOW เป็น HIGH

FALLING จะเกิดอินเตอร์รัพท์เมื่อพอร์ตที่กำหนดไว้มีการเปลี่ยนสถานะจาก HIGH เป็น LOW

HIGH จะเกิดอินเตอร์รัพท์ต่อเมื่อพอร์ตที่กำหนดไว้มีสถานะเป็น HIGH


volatile unsigned int counter = 0;  // Counter variable for revolutions

volatile: คำสำคัญนี้บ่งบอกให้คอมไพเลอร์ (compiler) ทราบว่า ค่าของตัวแปร counter อาจเปลี่ยนแปลงได้โดยกระบวนการอื่นที่โปรแกรม 

ไม่สามารถควบคุมได้ เช่น อินเทอร์รัปต์ (interrupt) หรือฮาร์ดแวร์ภายนอก ดังนั้น คอมไพเลอร์จะไม่พยายามเพิ่มประสิทธิภาพโค้ด โดยการเก็บค่าของ 

counter ไว้ในแคช (cache) หรือรีจิสเตอร์ (register) แต่จะเข้าไปอ่านค่าจากหน่วยความจำจริงทุกครั้งที่ใช้ตัวแปรนี้

unsigned int: นี่คือชนิดข้อมูลของตัวแปร counter ซึ่งหมายถึงตัวแปรนี้จะเก็บค่าจำนวนเต็มบวกเท่านั้น (ไม่มีเครื่องหมายลบ) 

และมีขนาดที่ขึ้นอยู่กับสถาปัตยกรรมของระบบ (โดยทั่วไปจะใช้ 2 หรือ 4 ไบต์)

counter: นี่คือชื่อของตัวแปรที่ใช้เก็บค่าจำนวนเต็มบวก


unsigned long currentMillis = millis();  

ฟังก์ชัน millis() คืออะไร?

millis() เป็นฟังก์ชันที่พบได้บ่อยในภาษาโปรแกรมที่เกี่ยวข้องกับไมโครคอนโทรลเลอร์ เช่น Arduino โดยฟังก์ชันนี้จะคืนค่าเวลาที่ผ่านไป

นับตั้งแต่เริ่มต้นโปรแกรมทำงานเป็นหน่วยมิลลิวินาที (milliseconds) หรือ 1/1000 ของหนึ่งวินาที

การวัดเวลา: ใช้ในการวัดระยะเวลาที่ผ่านไป เพื่อควบคุมการทำงานของโปรแกรมให้เกิดขึ้นในช่วงเวลาที่กำหนด เช่น การกระพริบ LED ในช่วงเวลาที่แน่นอน 

การอ่านค่าเซ็นเซอร์ในช่วงเวลาที่กำหนด เป็นต้น

การสร้างการหน่วงเวลา: แม้ว่าจะมีฟังก์ชัน delay() ที่ใช้ในการหน่วงเวลา แต่ฟังก์ชัน millis() จะให้ความยืดหยุ่นมากกว่าในการสร้างการหน่วงเวลา

ที่ซับซ้อนหรือการทำงานหลายอย่างพร้อมกัน

การควบคุมการทำงานแบบไม่บล็อก (Non-blocking): เมื่อใช้ millis() ร่วมกับโครงสร้างการควบคุม เช่น if-else หรือ switch-case 

จะทำให้โปรแกรมสามารถทำสิ่งอื่นๆ ได้ในขณะที่รอให้เวลาผ่านไป ไม่เหมือนกับการใช้ delay() ที่จะทำให้โปรแกรมหยุดทำงานชั่วคราว


// Complete code IR RPM

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

int ir_pin =2;

int ir_val;

//const int IR_PIN = 2;  // IR sensor input pin

int PPR=4; // Pulse per rotation

volatile unsigned int counter = 0;  // Counter variable for revolutions

unsigned long previousMillis = 0;  // Variable to store previous time

unsigned int rpm = 0;  // Variable to store RPM value


void IRinterrupt() {

  counter++;

}

void setup() {

  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C))  { // Address 0x3D for 128x64

    Serial.println(F("SSD1306 allocation failed"));

    for(;;);

  }

  display.display(); //Display logo

  delay(1000); 

  display.clearDisplay();

  pinMode(ir_pin, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(ir_pin), IRinterrupt, FALLING);


}

  

void loop() { 

  unsigned long currentMillis = millis();  

  //จับเวลา 1 วินาที ถ้าครบ ก็หยุดการทำงานของ ตัวนับ counter

  if (currentMillis - previousMillis >= 1000) {

    detachInterrupt(digitalPinToInterrupt(ir_pin));

    rpm = (counter / PPR) * 60;  // Calculate RPM  perminute 

    counter = 0;    

    attachInterrupt(digitalPinToInterrupt(ir_pin), IRinterrupt, FALLING);

    previousMillis = currentMillis;    

    //ir_val = digitalRead(ir_pin);//อ่านค่าสัญญาณ digital ขา D2 ที่ต่อกับ เซ็นเซอร์ตรวจจับวัตถุ IR Infrared  

    //display.fillRect(x, y, width, height,BLACK);    

    display.clearDisplay();

    display.fillRect(0, 25, 128, 12,BLACK);

    display.fillRect(0,25, map(rpm, 0, 1600, 0, 126), 8,WHITE);

    display.display();

    display.setTextSize(2);

    display.setTextColor(WHITE);

    display.setCursor(0, 0);   

    display.print("RPM:");  

    display.print(rpm);   

    display.display();

    delay(100);

  }  

}

// END


Ref:

https://www.allnewstep.com/article/252/

https://www.youtube.com/watch?v=NvXb7dr-ETw


ความคิดเห็น