วันศุกร์ที่ 17 กุมภาพันธ์ พ.ศ. 2560

การสร้างเอาต์พุต-แอนะล็อกโดยใช้ไอซี MCP41010 ร่วมกับ Arduino

ตัวต้านทานปรับค่าได้ (Potentiometer) เป็นอุปกรณ์พื้นฐานทางไฟฟ้าและอิเล็กทรอนิกส์ ซึ่งโดยทั่วไปมีสามขา (ขา A, B และ W) และสามารถหมุนปรับค่าความต้านทานด้วยมือได้ (เลื่อนตำแหน่งของขาสัมผัส W หรือ Wiper Position) ในปัจจุบันมีตัวต้านทานปรับค่าได้แบบดิจิทัล (Digitally Controlled Potentiometer ) ที่สามารถปรับเลือกค่าความต้านทานโดยการโปรแกรม และสื่อสารข้อมูลผ่านบัสอย่างเช่น SPI หรือ I2C   บทความนี้กล่าวถึงการทดลองใช้งานไอซี MCP41010 Digital Potentiometer ของบริษัท Microchip เพื่อนำมาสร้างวงจรที่ให้แรงดันเอาต์พุตปรับระดับได้โดยการโปรแกรมจาก Arduino
คำสำคัญ / Keywords: Arduino, MCP41010, Digital Potentiometer, SPI, Analog Output

ไอซี MCP41010

ในปัจจุบันมีผู้ผลิตหลายรายที่ผลิตไอซีประเภท Digital Potentiometer ออกมาขาย เช่น Microchip MCP41010 (SPI), Maxim MAX5402 DCP (SPI), Intersil ISL23711 DCP (I2C) ซึ่งสามารถโปรแกรมเลือกค่าความต้านทานผ่านบัส SPI หรือ I2C ได้ ไอซีประเภทนี้ สามารถนำไปใช้เป็นส่วนหนึ่งของวงจรอย่างเช่น วงจรขยายสัญญาณที่ใช้ออปแอมป์ (OpAmp) และมีตัวต้านทานปรับค่าได้เพื่อปรับค่าอัตราขยาย (Programmable Gain Amplifier) และวงจรแรงดันอ้างอิงแบบปรับระดับได้ (Adjustable Voltage Reference) เป็นต้น   ในบทความนี้ จะสาธิตการใช้งานไอซี MCP41010 โดยนำมาสร้างเป็นวงจรแบ่งแรงดันและใช้เอาต์พุตที่ได้เป็นแรงดันอ้างอิง แล้วนำไปผ่านวงจร OpAmp (ใช้เบอร์ LM358N) ที่ทำหน้าที่เป็น Voltage Buffer

ข้อมูลเชิงเทคนิคของไอซี MCP41010
  • ใช้แรงดันไฟเลี้ยงได้ในช่วง 2.7V ถึง 5.5V
  • ปรับค่าความต้านทนได้ 256 ระดับ (8 บิต)
  • มีค่าความต้านทานประมาณ 10kΩ ±2kΩ (เมื่อวัดความต้านทานที่ขาด้านนอก PA0 และ PB0)
  • ใช้ตัวถังแบบ PDIP-8
  • เชื่อมต่อแบบ SPI โหมด 0 หรือ 3 ใช้ความเร็วของ SCK ได้ถึง 10MHz (max.)

ศึกษาข้อมูลเพิ่มเติมได้จากไฟล์เอกสารของผู้ผลิต (MCP41010 datasheet)
 
รูปแสดงตำแหน่งขาของไอซี MCP41010 ตัวถัง 8-pin Plastic DIP

 
รูปแสดงการคำนวณค่าความต้านทาน 
Dn เป็นค่าที่โปรแกรมได้ในช่วง 0 ถึง 255 
MCP41010 มีตัวต้านทานปรับค่าได้ชุดเดียว ดังนั้น n=0

การโปรแกรมค่าให้ไอซี MCP41010 จะต้องทำผ่านบัส SPI โดยจะส่งข้อมูล 2 ไบต์ ซึ่งไบต์แรกเป็น Command Byte (Write) และไบต์ที่สองเป็นข้อมูลไบต์ (D7..D0 ซึ่งมีค่าระหว่าง 0..255) เมื่อต้องการเขียนค่าใหม่ เมื่อป้อนแรงดันไฟเลี้ยงและยังไม่มีการโปรแกรมค่าใดๆ ค่าเริ่มต้นจะเป็น 127 (เปรียบเทียบได้กับกรณีที่ตำแหน่งของขาสัมผัส W อยู่ตรงกลาง) และเมื่อปิดไฟเลี้ยง ไอซีจะไม่จำค่าที่ได้โปรแกรมไว้ในขณะนั้น
 
รูปแสดงคลื่นสัญญาณในการสื่อสารข้อมูลแบบ SPI

การสร้างสัญญาณเอาต์พุตแอนะล็อกโดยใช้ไอซี MCP41010 และ LM358

ในการสร้างสัญญาณที่เป็นแอนะล็อก จะใช้ไอซี MCP41010 เป็นตัวสร้างแรงดันอ้างอิง คือต่อวงจรให้เป็นวงจรแบ่งแรงดัน สำหรับช่วง 0..+5V (ขา PA0 ต่อกับ VCC, ขา PB0 ต่อกับ GND และขา PW0 เป็นขาเอาต์พุต) และสามารถปรับค่าแรงดันเอาต์พุตได้โดยการโปรแกรมจาก Arduino เอาต์พุตที่ได้จากวงจรแบ่งแรงดัน (จากขา PW0) จะถูกป้อนให้วงจรบัฟเฟอร์แรงดันที่สร้างได้จากไอซีออปแอมป์ LM358 และนำไปจ่ายกระแสให้วงจร LED ที่มีตัวต้านทานต่ออนุกรมอยู่ด้วย (กระแสสูงสุดไม่เกิน 20mA)

Arduino Sketch

โค้ดตัวอย่างแรกเป็นการโปรแกรมค่าให้ไอซี MCP41010 สร้างเอาต์พุตเป็นสัญญาณมีคาบ และมีรูปคลื่นแบบสามเหลี่ยม (Triangular Wave)
Sourcecode: mcp41010_triangular_wave.ino
///////////////////////////////////////////////////////////////////////////////
// Author: RSP @ ESL (Embedded System Lab), KMUTNB, Thailand
// Date: 2014-Apr-28
// Board: Arduino with ATmega168/328P (5V/16MHz)
// Arduino IDE: version 1.0.5
// Description:
//   This Arduino Sketch shows how to control the MCP41010
//   digital potentiometer which is used as a programmable
///  voltage divider. It generates a low-frequency triangular wave.
///////////////////////////////////////////////////////////////////////////////

/*
    Uno      MCP41010
    D10  --> CS
    D11  --> DI
    D13  --> SCLK
    
             PA0 to VCC
             PB0 to GND
             PW0 to output (connected to a voltage buffer)
 */

#include <SPI.h>

#define CMD_WRITE  (0b01)
#define SEL_CH0    (0b01)

void writeValue( uint8_t value ) {
  digitalWrite( SS, LOW );
  SPI.transfer( (CMD_WRITE << 4) | SEL_CH0 );
  SPI.transfer( value );
  digitalWrite( SS, HIGH );
}

void setup() {
  pinMode ( SS, OUTPUT );
  SPI.begin();
}

#define DELAY_US (200)  // The delay value must be less than 16383.

void updateOutput() { // generate a triangular wave
  static int level = 0;
  while (1) {
    if (level > 255 ) {
       writeValue( 511 - level );
    } else {
       writeValue( level );
    }
    level = (level+1) % 512;
    delayMicroseconds( DELAY_US );
  }
}

void loop() {
  updateOutput();
}
///////////////////////////////////////////////////////////////////////////////

ไม่มีความคิดเห็น:

แสดงความคิดเห็น