การเชื่อมต่อLCD1602 I2C บอร์ด ESP8266



 //https://www.etechnophiles.com/tachometer-using-arduino/

//GPIO ทุกขาสามารถใช้คำสั่ง Interrupt ได้ ยกเว้นขา GPIO16

การเชื่อมต่อLCD1602 I2C บอร์ด ESP8266  

I2C module   ESP8266

VCC  ------> 5V 

GND  ------> Ground 

SDA  ------> D2 GPIO 4

SCL  ------> D1 GPIO 5

ติดตั้งไลบรารี LiquidCrystal ให้ไปที่ Arduino IDE:

ไปที่เมนู Sketch > Include Library > Manage Libraries...

ติดตั้งไลบรารี LiquidCrystal ให้ไปที่ Arduino IDE:

ไปที่เมนู Sketch > Include Library > Manage Libraries...

ค้นหา LiquidCrystal I2C และติดตั้ง


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

GND  ------> GND

3.3V ------> VCC

D8    ------> OUT

เขียนโปรแกรมเพื่อสั่งให้จอ LCD แสดงผล

และทดสอบการทำงาน


// Code Detect Object From IR 

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);  

int ir_pin =15;  //D8

int ir_val;

void setup(){

  // initialize LCD

  lcd.init();

  lcd.backlight();

  Serial.begin(115200);  

}


void loop(){

  // set cursor to first column, first row

  lcd.setCursor(0, 0);

  lcd.print("IR Value:");

  lcd.print(ir_val);  

  delay(1000);

  lcd.clear();


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

  if (ir_val>0){

    Serial.print("No Detect VaLue:");

    Serial.println(ir_val);

  } else{

    Serial.print("Detect Value:");

    Serial.println(ir_val); 

  }  

}


// END Code Detect Object From IR 

///////////////////////////////////////

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

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

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

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

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

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

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

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

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

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

ทำไมต้องใช้ ICACHE_RAM_ATTR?

ICACHE_RAM_ATTR ทำหน้าที่บังคับให้ตัวแปร counter ถูกจัดเก็บไว้ในส่วนของ RAM ที่เรียกว่า I-Cache (Instruction Cache) 

ซึ่งเป็นส่วนหนึ่งของ RAM ที่ใช้เก็บคำสั่งของโปรแกรม โดยการจัดเก็บตัวแปรไว้ใน I-Cache จะทำให้การเข้าถึงตัวแปรนั้น เร็วขึ้น 

เพราะไมโครคอนโทรลเลอร์สามารถเข้าถึงข้อมูลใน I-Cache ได้โดยตรงโดยไม่ต้องผ่านขั้นตอนการเข้าถึง RAM ทั่วไป

Attribute นี้มักจะใช้กับไมโครคอนโทรลเลอร์ ที่ใช้ชิป ESP8266 หรือ ESP32 และอาจมีการใช้งานที่แตกต่างกันไปในไมโครคอนโทรลเลอร์รุ่นอื่นๆ

คุณสมบัติ ICACHE_RAM_ATTR volatile

วัตถุประสงค์ เพิ่มความเร็วในการเข้าถึง ป้องกันการเพิ่มประสิทธิภาพที่ผิดพลาด

ผลกระทบต่อการจัดเก็บ บังคับให้เก็บใน I-Cache ไม่ได้ระบุตำแหน่งการจัดเก็บ

เหตุผลในการใช้ ตัวแปรที่ใช้บ่อย,สำคัญ ตัวแปรที่ใช้ในการสื่อสารกับฮาร์ดแวร์ 


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() ที่จะทำให้โปรแกรมหยุดทำงานชั่วคราว

// Full code IR LCD1602 RPM 

#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);  

int ir_pin =15;  //D8

int ir_val;

int PPR=3; // Pulse per rotation

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

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

ICACHE_RAM_ATTR int counter=0;

void ICACHE_RAM_ATTR IRinterrupt(){

  counter++;

}


void setup(){

  // initialize LCD

  lcd.init();

  lcd.backlight();

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

  Serial.begin(9600);  

}


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;    

    lcd.clear();

    lcd.setCursor(0,0);

    lcd.print("RPM=");

    lcd.print(rpm);

    Serial.println(rpm);

    delay(100);  

  }

}






Ref:

https://randomnerdtutorials.com/interrupts-timers-esp8266-arduino-ide-nodemcu/

https://www.allnewstep.com/article/61/nodemcu-esp8266-esp8285-arduino-32-esp8266-nodemcu-interrupt


ความคิดเห็น