การเชื่อมต่อ บอร์ด Arduino Nano กับ IR sensor วัดความเร็วรอบ Oled 0.96


 การเชื่อมต่อ บอร์ด Arduino Nano กับ IR sensor วัดความเร็วรอบ Oled 0.96

หรือ งานเปิด-ปิดสวิสซ์ แบบสัมผัส,การควบคุมอุปกรณ์ไฟฟ้าต่าง ๆ 

การเชื่อมต่อ บอร์ด Arduino Nano กับ Oled 096

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

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

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

SCL ---------------> SCL (BASE Or A5)

SDA ---------------> SDA (BASE Or A4)


ติดตั้ง ไลบราลี่ที่จำเป็น 

1. Open your Arduino IDE and go to Sketch > Include Library > Manage Libraries

2. Type “SSD1306” in the search box and install the SSD1306 library from Adafruit.

3. Type “GFX” in the search box and install the library.

#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);


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() { 

  delay(1000);

  display.clearDisplay();

  display.setTextSize(2);

  display.setTextColor(WHITE);

  display.setCursor(0, 0);   

  display.print("RPM:1200");  

  display.display();

}

// End Nano & OLED code


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

GND  ------> GND

3.3V ------> VCC

2    ------> OUT

เขียนโปรแกรมเพื่อสั่งให้จอ Oled แสดงผล และทดสอบการทำงาน


// code oled 0.96 +IR 

#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("RPM:");  

  display.print(ir_val);   

  display.display();

  delay(100);

}

// END code oled 0.96 +IR 

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

รูปแบบคำสั่ง 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 RPM


Ref:

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

https://projecthub.arduino.cc/mircemk/arduino-tachometer-rpm-meter-with-ir-sensor-module-a36d7c

https://www.w3schools.com/tags/canvas_fillrect.asp



ความคิดเห็น