2018년 11월 19일 월요일

MCP3202 - 12bit ADC

1. MCP3202란?

 Analog to Digital Converter (ADC) 칩의 하나로 12비트, SPI 통신지원 등이 특성이다. ESP8266이 analog핀이 하나인 관계로,  동시에 2개 채널을 읽기 위하여 사용하기 위하여 사용법을 연구하였지만, 사실 속도와 관계 없다면 ESP8266에서 몇개의 아날로그 센서를 붙이는 것은 편법이 존재한다. 아날로그 센서의 특징에 따라서 관계되지만, 3V 정도로 동작하면서 소비전력이 지극히 적은 센서들은 ESP8266의 디지털 핀들을 이용하여 여러개 제어 가능하다.  다만 센서가 소비 전력이 좀 되거나, 정상 동작 레벨까지 1분정도 걸리는 미세 먼지 센서등은 ESP8266에 여러개 붙이기 위하여 노력하기 보다는 그냥 ESP32를 사용하는 것을 추천한다.

2. MCP3202의 특성

 12비트로 결과값이 나온다는 것은 이미 알려  드렸고, 이하 제조사가 제공하는 데이터시트에서 발췌한 내용으로 설명한다.  (이 포스트에 사용된 모든 그림은 제조사가 제공하는 데이터 시트에서 발췌하였다.)


위의 그림에서 CS, CLK, Dout(MISO), Din(MOSI)는 SPI통신의 기본이니 다들 아실테고, Vref는 기준전압이 되겠다.  MCP3202가 동작하는 주 전원이며 이 입력에 따라서 샘플링 속도나 frequency가 정해진다. 당연하겠지만 최고 속도를 위해서는 5V 가 공급되어야 한다. Vss는 전체 공통 Ground이니, 시스템이나 측정 프로브와 연결해 주면 된다. CH0과 CH1은 측정 프로브의 +측에 연결하면 된다.
 스펙에 Vref에는 최대 7V라고 했지만, 다들 그리 사용하지 않으리라 생각한다. 이유는 간단하다. 5V에서 이미 최대 기능을 발휘하니, 일부러 높은 전압을 입력할 필요도 없으며, 7V라는 전압을 따로 구성해야 하는 불편함을 감수하지 않아도 되기 때문이다.


 MCP3202의 통신 Timing에 관련된 그림을 보면 MSBFIRST 먼저 오는 것을 알수 있고, 일반적인 SPI_MODE0 으로 동작함을 알 수 있다. (아.. 내 능력으로는 남들이 그렇다고 해서 그런가 보다 하는 정도이다.)


친절하게도 스펙에 Output Value가 어떤 숫자를 의미하는지 계산식을 보여주고 있엇다. 기준전압대비 측정전압의 비율에 4096을 곱하여 계산한다고 적혀있다. 즉 기준전압이 5V 일때 측정 전압이 2.5V 라 가정하면 MCP3202는 2048 이라는 값을 반환해 준다.



3. 소스코드

아래의 소스코드를 실행시키면 1초마다 측정하여 Serial 창에 표시한다.

// MCP3202 12비트 Analog-to-Digital Converter이다.
// MCP3202  테스트한 바로는 클럭을 14MHz 동작 시키면
// 7마이크로초 정도에 1 읽을수 있지만,
// 샘플링 속도의 한계를 고려 한다면 의미가 있는 것은 아니다.
// 1.8MHz 클럭이 스펙상 최대;;;
// 또한 스펙상 5V 상태에서 100Ksps 한계이다.. ... 1 헤르츠 정도면.. 신뢰도 급감.
#include <SPI.h>
#define CS_3202  D1      // 15
//#define SPI_SETTING     SPISettings(1800000, MSBFIRST, SPI_MODE0)

void setup()
{
  Serial.begin(115200);
  pinMode(A0, INPUT);
  pinMode(CS_3202, OUTPUT);
  digitalWrite(CS_3202, HIGH);

  SPI.begin();
  SPI.setFrequency(2000000);  // 2MHz 동작. mcp3202 기준으로 12MHz 정도가 한계이다.
                              // 다만 10MHz 이상되면, 신뢰성은 이미 바닥..
}

void loop()
{
  int ch0, ch1;
  Read3002_EX(CS_3202, &ch0, &ch1);

  Serial.print("CH0 =");
  Serial.println(ch0);
  Serial.print("CH1 =");
  Serial.println(ch1);

  delay(1000);
}

// 2 채널 모두 읽는 버전
void Read3002_EX(int CS, int *ch0, int* ch1) {
  int msb;
  int lsb;
  digitalWrite(CS, LOW);
  SPI.transfer (B00000001);// Start bit
  msb = SPI.transfer(B10100000) ;  // ch0
  msb = msb & B00001111;
  lsb = SPI.transfer(0x00);
  *ch0 = ((int) msb) << 8 | lsb;

  digitalWrite(CS, HIGH);
  digitalWrite(CS, LOW);

  SPI.transfer (B00000001);// Start bit
  msb = SPI.transfer(B11100000) ; // ch1
  msb = msb & B00001111;
  lsb = SPI.transfer(0x00);
  *ch1 = ((int) msb) << 8 | lsb;
  digitalWrite(CS, HIGH);
}

// 1 채널만 읽는 버전
int Read3202(int CHANNEL, int CS) {
  int msb;
  int lsb;
  int commandBytes = B10100000 ;// channel 0
  if (CHANNEL == 1) commandBytes = B11100000 ; // channel 1
  digitalWrite(CS, LOW);
  SPI.transfer (B00000001);// Start bit
  msb = SPI.transfer(commandBytes) ;
  msb = msb & B00001111;
  lsb = SPI.transfer(0x00);
  digitalWrite(CS, HIGH);
  return ((int) msb) << 8 | lsb;
}






댓글 없음:

댓글 쓰기

3단 6핀 스위치로 DC 모터의 회전 방향을 바꾸어 보자

1. 필요는 연구의 어머니 항상 느끼는 부분이다. 필요하지 않으면 연구하지 않으며, 필요하면 연구한다. DC 모터를 조건에 따라서 정방향 또는 역방향으로 회전시켜야 하는 필요가 생겼다. 처음에는 MCU 및 Relay Switch를 이용하는 방법을 생각...