'Arduino'에 해당되는 글 104건

  1. 2018.07.24 Hardware | SSD1306 에 로고를 세겨보자
  2. 2018.07.01 Hardware | 압력 센서를 가지고 놀아보자
  3. 2018.05.16 Hardware | ATtiny85 를 사용해 보자 - 2
  4. 2018.05.16 Hardware | ATtiny85 를 사용해 보자 - 1 2
  5. 2018.04.03 Hardware | TCS230/TCS3200 color sensor 를 사용해 보자
  6. 2018.03.04 Hardware | Arduino 의 AREF pin 에 대해 알아보자
  7. 2018.03.01 Hardware | HC-SR501 PIR motion sensor - 2 2
  8. 2018.02.28 Hardware | Arduino 로 Photoresister 가지고 놀기 - 2
  9. 2018.02.19 Hardware | Digitial Compass - HMC5883L 사용기 - 1
  10. 2018.02.11 Hardware | MAX4466 마이크 앰프 breakout board 사용해 보기

Hardware | SSD1306 에 로고를 세겨보자

|

1. 이제 때가 되었군


그렇습니다.

OLED 를 사용하다 보면, 커스텀 로고 새기는 방법을 익혀야 하는 경우가 몇번 있었습니다만,

대세에 지장이 없어서 무시하고 왔습니다.


그러나 UV Meter 를 가지로 놀려고 아래 링크를 따라해 보니,

커스텀 로고를 새기는 방법을 익혀야 할 때가 된걸 느꼈습니다.


* Arduino UV Meter using the UV31A Ultraviolet Sensor

http://www.electronics-lab.com/project/arduino-uv-meter-using-uv30a-ultraviolet-sensor/


아래 그림처럼, 처음 시작을 커스텀 로고로 시작되는 것을 볼 수 있습니다.



또한, 예전에 VU Meter 를 만들 때, 제작자가 한번 언급한 경우도 있었습니다.

이때는 그냥 제작자 코드를 따라하기만 하면 되는거였죠.


* Hardware | SSD1306 monochrome OLED 를 가지고 VU meter 를 만들어보자

 - http://chocoball.tistory.com/entry/Hardware-VU-meter-using-SSD1306-monochrome-OLED


자 그럼, 한번 시작해 볼까요?





2. Arduino micro 의 I2C 연결


여기서 잠깐.

평소 사용하는 Arduino Nano 와는 다르게, 요즘 자주 사용하고 있는 Arduino Micro 의 I2C pinout 이 달라 조금 헤매었습니다.



OLED 의 SCL / SDA 연결을 위해서는 D3 / D2 pin 을 이용해야 합니다.


 SSD1306  | Arduino Micro
--------------------------
   VCC    |     3.3V
   GND    |     GND
   SDL    |     D3
   SDA    |     D2
--------------------------


연결은 다음과 같아요.






3. OLED 의 너비와 높이를 구해보자


우선 사용할 OLED 의 가로, 세로 pixel 수를 구해야 합니다.

이는 최종적으로 만들 그림의 크기를 정하기 위한거죠.


연결한 OLED 에 가로, 세로 pixel 수를 알아보기 위해 아래 code 를 사용합니다.


#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
 
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

void setup() {
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
	display.clearDisplay();
	display.display();
}

void loop() {
	display.clearDisplay();
	
	display.setTextColor(WHITE);
	display.setCursor(0,0);
	display.setTextSize(2);
	display.println(display.width());
	display.print(display.height());
	
	display.display();
}


결과는 다음과 같습니다.



SSD1306 이지만 128x64 가 아닌, 128x32 군요.

높이가 일반적인 OLED 보다 반쪽이라서 그림을 신경써야 합니다.





4. 필요한 그림파일 찾기


UV Meter 를 위해서는, 우선 태양 그림이 필요합니다.

Googling 하여 태양 그림을 찾아 봅니다.

키워드는 "sun shining icon image" 로 검색했습니다.


주르륵 뜨는군요. 적당한 것을 하나 골라 봅니다.







5. 흑백 및 적당한 크기로


그림을 생성하기 위해 Paint.net 이라는 어플을 사용합니다.


* paint.net

https://www.getpaint.net/


우선 OLED 의 크기가 128x32 이므로, 그림 크기를 OLED 크기에 맞게 생성해 줍니다.



태양 그림 파일을 불러와서 크기를 줄여줍니다.

OLED 가 32 이므로, 32로 하면 그림이 다 들어가겠지만, 그렇게 되면 너무 작아 보여,

64x64 로 줄여줍니다.



또한 OLED 에 표시하기 위해서는 on/off, 0/1, white/black 으로 표시해야 합니다.

최대한 근접하게 우선 Brightness / Contrast 를 설정해 줍니다.



전체적으로 다음과 같이 꾸며 봅니다.


Contrast 를 최대로 높히면 Bitmap 생성시 완전한 흑백으로 근접하게 만들 수 있습니다.



마지막으로 Windows 에 기본으로 들어 있는,

mspaint ( %windir%\system32\mspaint.exe ) 를 사용하여,

최종적으로 Monochrome BMP 파일로 생성해 줍니다.


Save as Monochrome Bitmap 으로 하면서 완전히 white/black 으로 변경됩니다.






6. LCD Assistant


이제 C 코드용 bitmap 을 만들어주는 어플을 다운로드 받아서 실행합니다.


* LCD Assistant

http://en.radzio.dxp.pl/bitmap_converter/



실행한 후, 위에서 만든 파일을 load 합니다.



이제 "Save output" 으로 최종적으로 text 파일로 export 합니다.



Output 된 text 파일을 열어보면 아래와 같이 생성되어 있습니다.



Monochrome Bitmap 으로만 잘 만들면,

LCD Assistant 를 이용하여 C code map 을 만드는데 쉽게 진행됩니다.





7. OLED 에 커스텀 코드를 올려보자


C code map 을 array 로 올린 다음,

display.drawBitmap 을 이용하여 표현할 수 있는 준비가 되었습니다.


최종 코드는 다음과 같습니다.


#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
 
#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

static const unsigned char PROGMEM UVMeter[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x18, 0x03, 0x18, 0x01, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x18, 0x03, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x1C, 0x03, 0x1C, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x07, 0xC0, 0x07, 0x00, 0x00, 0x1C, 0x03, 0x0C, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xC0, 0x0F, 0xC0, 0x0E, 0x00, 0x00, 0x1C, 0x03, 0x0C, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xE0, 0x0F, 0xE0, 0x3E, 0x00, 0x00, 0x1C, 0x03, 0x0E, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x0F, 0xF0, 0x7E, 0x00, 0x00, 0x1C, 0x03, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x0F, 0xF8, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x06, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xDF, 0xFD, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x07, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x18, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x1C, 0x03, 0x03, 0x98, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x00, 0x00, 0x1C, 0x07, 0x01, 0x98, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x7F, 0x03, 0xE0, 0x7F, 0x00, 0x00, 0x0C, 0x06, 0x01, 0xB0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFC, 0x3F, 0xFE, 0x1F, 0x3F, 0xF0, 0x0E, 0x0E, 0x01, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x06, 0x0F, 0xF8, 0xFF, 0xFF, 0x8F, 0xFF, 0xC0, 0x07, 0xFC, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x07, 0xFF, 0xF1, 0xFF, 0xFF, 0xC7, 0xFF, 0x80, 0x03, 0xF8, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x03, 0xFF, 0xE7, 0xFF, 0xFF, 0xF3, 0xFF, 0x00, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x00, 0x00,
0x03, 0xFF, 0xCF, 0xFF, 0xFF, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x20, 0x00, 0x00,
0x01, 0xFF, 0x9F, 0xFF, 0x7F, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x70, 0x38, 0x00, 0x20, 0x00, 0x00,
0x00, 0xFF, 0x9F, 0xF0, 0x07, 0xFC, 0xFE, 0x00, 0x00, 0x00, 0x58, 0x28, 0x38, 0x78, 0x38, 0x48,
0x00, 0x7F, 0x3F, 0xC0, 0x01, 0xFE, 0x7E, 0x00, 0x00, 0x00, 0x58, 0x68, 0x6E, 0x78, 0xCC, 0x7C,
0x00, 0x3E, 0x7F, 0x80, 0x00, 0xFF, 0x3E, 0x00, 0x00, 0x00, 0x48, 0x48, 0xC6, 0x20, 0x84, 0x60,
0x00, 0x1E, 0x7F, 0x00, 0x00, 0x7F, 0x3C, 0x00, 0x00, 0x00, 0x4C, 0xC8, 0xC2, 0x21, 0x86, 0x40,
0x00, 0x1E, 0x7E, 0x00, 0x00, 0x3F, 0x3C, 0x00, 0x00, 0x00, 0x4C, 0x88, 0xFE, 0x21, 0xFE, 0x40,
0x00, 0x3C, 0xFE, 0x00, 0x00, 0x3F, 0x9F, 0x00, 0x00, 0x00, 0x46, 0x88, 0x80, 0x21, 0x80, 0x40,
0x00, 0x7C, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xF0, 0x00, 0x00, 0x47, 0x88, 0xC0, 0x21, 0x80, 0x40,
0x00, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFC, 0x00, 0x00, 0x43, 0x08, 0x42, 0x30, 0xC0, 0x40,
0x03, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFE, 0x00, 0x00, 0x43, 0x08, 0x7E, 0x1C, 0x7C, 0x40,
0x07, 0xFC, 0xFC, 0x00, 0x00, 0x1F, 0x9F, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};


void setup() {
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
	display.clearDisplay();
	display.display();
}

void loop() {
	display.clearDisplay();
	
	display.drawBitmap(0, 0, UVMeter, 128, 32, WHITE);

	display.display();
}


짜잔~!!!

잘 나오는군요.






FIN


사실 이렇게까지 만드는데 거진 8시간정도 걸렸습니다.

Arduino micro 의 I2C pinout 이나, 순수한 Monochrome Bitmap 을 만드는 방법을 찾는데 많이 걸렸네요.

본 포스트가 다른 분들에게 많이 도움이 되었으면 합니다.


And

Hardware | 압력 센서를 가지고 놀아보자

|

1. FSR


FSR 은 Force Sensitive Resistor 의 약자입니다.

당장에야 어디에 붙여서 사용할 필요는 없지만, 미리 경험해 본다 샘 치고 구입해 봅니다.

한개만 해도 되는데, 실제 무게 대비 어떤식으로 반응하는지 궁금하여,
각각 스케일이 다른 센서가 한 set 인 제품을 구매합니다.

선호되는 제품이 아닌지라 약 1만원 정도로 비싼 축에 속합니다.


* WALFRONT 5pcs/Lot Thin Film Pressure Sensor DF9-40 High Precise Force Sensing Resistor Resistance-type Flexible Pressure Sensor

https://www.aliexpress.com/item/WALFRONT-5pcs-Lot-Thin-Film-Pressure-Sensor-DF9-40-High-Precise-Force-Sensing-Resistor-Resistance-type/32847434125.html




특징은 다음과 같다고 합니다.


Features:


This flexible pressure sensor is based on new nanometer pressure-sensitive materials supplemented by ultra-thin film substrate.

Highly sensitive flexible nanometer materials can realize highly sensitive detection of pressure.

It has pressure sensitive function as well as water-resistant function.

When sensor detects outside pressure, the resistance of sensor will change.

Pressure signal can be converted into a corresponding electrical signal output using simple circuit.

Specifications:


Measuring Range: 0-500g, 0-2kg, 0-5kg, 0-10kg, 0-20kg

Thickness: <0.25mm

Precision: ±2.5%(85% measuring range)

Repeatability: <±5.8(50% load)

Lifespan: >1million times

Initial Resistance: >10MΩ(no load)

Response Time: <1ms

Restore Time: <15ms

Test Voltage: DC 3.3V (typical)

EMI: Not generate

EDS: Not sensitive


Sensing Area Outer Diameter: 9mm

Sensing Area Inner Diameter: 7.5mm

Pin Spacing: 2.54mm


Range 는 500g / 2kg / 5kg / 10kg / 20kg 각각 다른 5개의 FSR 이 한 set 입니다.




2. 도착


얇은 막 같은 형태인지라 납짝한 포장지로 왔습니다.



봉지에 각 FSR 의 range 값이 적혀 있을 뿐, 센서 자체에는 없어서 어디서 꺼냈는지 잘 외워 둬야 합니다.



어떤것은 앞뒤가 검은색, 흰색으로 되어 있고...



또 어떤것은 회로선으로 구성되어 있고, 제각각입니다.





3. LED 연동


일단 간단하게 LED 를 연결하여 누르는 힘의 세기에 따라 밝기 조절이 되는 회로를 구성해 봅니다.

아래 website 를 참고하였습니다.


* Using an FSR

https://learn.adafruit.com/force-sensitive-resistor-fsr/using-an-fsr


회로 구성은 다음과 같습니다.


주의할 점은, 저항이 꼭 필요하다는 것.

FSR 출력값은 저항과 같이 연결된 부분에서 A0 에 연결하면 됩니다.



이쁘게 연결 되었습니다.



저항은 꼭 연결되어야 합니다.

/* FSR testing sketch.

Connect one end of FSR to 5V, the other end to Analog 0.
Then connect one end of a 10K resistor from Analog 0 to ground
Connect LED from pin 11 through a resistor to ground

For more information see www.ladyada.net/learn/sensors/fsr.html */

int fsrAnalogPin = 0;  // FSR is connected to analog 0
int LEDpin = 11;  // connect Red LED to pin 11 (PWM pin)
int fsrReading;  // the analog reading from the FSR resistor divider
int LEDbrightness;
 
void setup(void) {
	Serial.begin(9600); // We'll send debugging information via the Serial monitor
	pinMode(LEDpin, OUTPUT);
}
 
void loop(void) {
	fsrReading = analogRead(fsrAnalogPin);
	Serial.print("Analog reading = ");
	Serial.println(fsrReading);
	
	// we'll need to change the range from the analog reading (0-1023) down to the range
	// used by analogWrite (0-255) with map!
	LEDbrightness = map(fsrReading, 0, 1023, 0, 255);
	// LED gets brighter the harder you press
	analogWrite(LEDpin, LEDbrightness);
	
	delay(100);
}


sketch 는 위와 같습니다.

열결된 FSR 을 통해 analog 값을 읽어들이고, LED 밝기 범위 안으로 mapping 시키는 방법 입니다.



어때요, 잘 동작하쥬?




4. FSR 에 걸리는 voltage / resistance 도출


아래 sketch는 실제 값을 측정해 보는 소스 입니다.

사용된 법칙은 아래 두가지 입니다.


The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V

FSR = ((Vcc - V) * R) / V

/* FSR testing sketch. 
 
Connect one end of FSR to power, the other end to Analog 0.
Then connect one end of a 10K resistor from Analog 0 to ground 
 
For more information see www.ladyada.net/learn/sensors/fsr.html */
 
int fsrPin = 0;     // the FSR and 10K pulldown are connected to a0
int fsrReading;     // the analog reading from the FSR resistor divider
int fsrVoltage;     // the analog reading converted to voltage
unsigned long fsrResistance;  // The voltage converted to resistance, can be very big so make "long"
unsigned long fsrConductance; 
long fsrForce;       // Finally, the resistance converted to force
 
void setup(void) {
//  Serial.begin(9600);   // We'll send debugging information via the Serial monitor
  Serial.begin(19200);   // We'll send debugging information via the Serial monitor
}
 
void loop(void) {
  fsrReading = analogRead(fsrPin);  
  Serial.print("Analog reading = ");
  Serial.println(fsrReading);
 
  // analog voltage reading ranges from about 0 to 1023 which maps to 0V to 5V (= 5000mV)
  fsrVoltage = map(fsrReading, 0, 1023, 0, 5000);
  Serial.print("Voltage reading in mV = ");
  Serial.println(fsrVoltage);  
 
  if (fsrVoltage == 0) {
    Serial.println("No pressure");  
  } else {
    // The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
    // so FSR = ((Vcc - V) * R) / V        yay math!
    fsrResistance = 5000 - fsrVoltage;     // fsrVoltage is in millivolts so 5V = 5000mV
    fsrResistance *= 10000;                // 10K resistor
    fsrResistance /= fsrVoltage;
    Serial.print("FSR resistance in ohms = ");
    Serial.println(fsrResistance);
 
    fsrConductance = 1000000;           // we measure in micromhos so 
    fsrConductance /= fsrResistance;
    Serial.print("Conductance in microMhos: ");
    Serial.println(fsrConductance);
 
    // Use the two FSR guide graphs to approximate the force
    if (fsrConductance <= 1000) {
      fsrForce = fsrConductance / 80;
      Serial.print("Force in Newtons: ");
      Serial.println(fsrForce);      
    } else {
      fsrForce = fsrConductance - 1000;
      fsrForce /= 30;
      Serial.print("Force in Newtons: ");
      Serial.println(fsrForce);            
    }
  }
  Serial.println("--------------------");
  delay(600);
}


회로는 LED만 빼면 같고 소스만 다릅니다.

그 결과는 다음과 같습니다.



각 소자마다 아마 값이 달라지겠지만,

누르는 힘에 따라 저항값이 바뀌며, 세게 누르면 저항값이 낮아져 전류가 많이 흐르는 것을 보여주고 있습니다.





5. 각 소자별 반응 차이 측정


그럼 위의 소스를 살짝 수정하여,

각 소자의 특성을 확인해 보기로 합니다.


이 값이 있어야, 특정 목적에 사용시 적절한 소자를 선택할 수 있겠죠?



그냥 각 소자를 추가하고, 저항을 각각 연결하여 값을 입력받는 방식입니다.


사진은 찍지 못했지만, 저기 소자들을 한대 모아서 같은 손가락으로 누르면서 측정하였습니다.

사진 찍을 여유가 없네요.


소스는 다음과 같습니다.

바로 위의 소스를 조금 수정했고, 소자에 흐르는 voltage 와 resistance 값만을 한줄에 출력하도록 했습니다.


/* FSR testing sketch. 

Connect one end of FSR to power, the other end to Analog 0.
Then connect one end of a 10K resistor from Analog 0 to ground

For more information see www.ladyada.net/learn/sensors/fsr.html */
 
int fsrVoltage_00;  // the analog reading converted to voltage
int fsrVoltage_01;
int fsrVoltage_02;
int fsrVoltage_03;
unsigned long fsrResistance_00;  // The voltage converted to resistance, can be very big so make "long"
unsigned long fsrResistance_01;
unsigned long fsrResistance_02;
unsigned long fsrResistance_03;

void setup(void) {
	Serial.begin(19200);  // We'll send debugging information via the Serial monitor
	
	pinMode(A0,INPUT);
	pinMode(A1,INPUT);
	pinMode(A2,INPUT);
	pinMode(A3,INPUT);
	
	Serial.println("500g        2Kg       5Kg      10Kg");
	Serial.println("------------------------------------------");
}
 
void loop(void) {
	// analog voltage reading ranges from about 0 to 1023 which maps to 0V to 5V (= 5000mV)
	fsrVoltage_00 = map(analogRead(A0), 0, 1023, 0, 5000);
	Serial.print(fsrVoltage_00);
	Serial.print("   ");
	
	fsrVoltage_01 = map(analogRead(A1), 0, 1023, 0, 5000);
	Serial.print(fsrVoltage_01);
	Serial.print("   ");
	
	fsrVoltage_02 = map(analogRead(A2), 0, 1023, 0, 5000);
	Serial.print(fsrVoltage_02);
	Serial.print("   ");
	
	fsrVoltage_03 = map(analogRead(A3), 0, 1023, 0, 5000);
	Serial.print(fsrVoltage_03);
	Serial.print("   ");
	
	
	// The voltage = Vcc * R / (R + FSR) where R = 10K and Vcc = 5V
	// so FSR = ((Vcc - V) * R) / V        yay math!
	fsrResistance_00 = ((5000 - fsrVoltage_00)*10000)/fsrVoltage_00;  // fsrVoltage is in millivolts so 5V = 5000mV
	Serial.print(fsrResistance_00);
	Serial.print("   ");
	
	fsrResistance_01 = ((5000 - fsrVoltage_01)*10000)/fsrVoltage_01;
	Serial.print(fsrResistance_01);
	Serial.print("   ");
	
	fsrResistance_02 = ((5000 - fsrVoltage_02)*10000)/fsrVoltage_02;
	Serial.print(fsrResistance_02);
	Serial.print("   ");
	
	fsrResistance_03 = ((5000 - fsrVoltage_03)*10000)/fsrVoltage_03;
	Serial.print(fsrResistance_03);
	Serial.println();
	
	delay(600);
}


Serial Monitor 에 나타나는 모양은 다음과 같습니다.



각 값을 보면 정말 linear 하게 값이 움직이는지 알 수 없으나,

그래프화 시켜보면 다음과 같습니다.


각 센서마다 반응하는 range 가 다른 것을 알 수 있습니다.



한가지 문제는 5kg 센서가 너무 반응을 잘 한다는 거죠.

제가 봉투에서 꺼내면서 다른 센서와 바꿔버렸는지, 아니면 처음부터 잘못 들어가 있는지... 확신이 없습니다.


이걸 토대로, 실제 사용시는 기준 실측값을 가지고 사용해야겠습니다.




FIN


슬슬 뭔가 실생활에 도움되는 것을 만들어야 하는데,

센서 종류만 탐구하고 앉아 있네요.



And

Hardware | ATtiny85 를 사용해 보자 - 2

|

1. 준비물


ATtiny85 에 구동 program 를 업로드 하기 전에, 구성품 준비가 필요합니다.

관련해서는 다음에 링크된 이전글을 참고해 주세요.


* Hardware | ATtiny85 를 사용해 보자 - 1

http://chocoball.tistory.com/entry/Hardware-ATtiny85-1



참고로 ATtiny85 의 datasheet 는 다음과 같습니다.

Atmel-2586-AVR-8-bit-Microcontroller-ATtiny25-ATtiny45-ATtiny85_Datasheet.pdf





2. 참조 사이트


ATtiny85 에 프로그램 업로드를 위해서는 몇가지 방법이 있지만,

저는 다음 사이트를 기준으로 참고하였습니다.


* Breathing life into the DigiSpark clone with ATtiny MCU

https://makbit.com/web/firmware/breathing-life-into-digispark-clone-with-attiny-mcu/




3. Arduino - ArduinoISP


자, 이제 준비가 완료 되었으니 이제 시작을 해 볼까요?


ATtiny85 에 프로그램을 심으려면,

바로 PC 와 USB를 통해 연결하면 안되고 "PC -- USB -- Arduino -- ATtiny85" 식으로 연결하여 프로그래밍 할 수 있습니다.


중간에 위치한 Arduino 를 브릿지 형식으로 사용하는 것입니다. 이름하야  In-circuit Serial Programmer (ISP) 라는군요.

이를 위해, Arduino 가 ISP 로 동작할 수 있도록 Arduino 에 ISP 프로그램을 업로드 해줍니다.


File > Examples > 11.ArduinoISP > ArduinoISP 



이걸로 Arduino 쪽의 준비는 끝났습니다.




4. Arduino IDE - Perferences


다음으로 IDE의 Preferences 메뉴로 이동하여 ATtiny85 보드를 Arduino 에서 인식시킬 수 있도록 관련된 library 를 인스톨 합니다.

이를 위하여, 다음 URL 중 하나를 Preferences 의 Boards Manager URLs 에 다음 중 하나를 선택하여 입력해 줍니다.


* ATtinyCore

- http://drazzy.com/package_drazzy.com_index.json

* Digispark

- http://digistump.com/package_digistump_index.json


File > Preferences > Additional Boards Manager URLs



보통은 Digispark 용을 사용해도 되나,

Spence Konde 라는 사람이 만든 ATTinyCore 는 좀더 정밀하게 설정할 수 있고, 문제 없이 동작한다고 합니다.


* Spence Konde

https://github.com/SpenceKonde/ATTinyCore


저는 Spence Konde 를 선택했습니다.




5. Arduino IDE - Board Manager


다음으로 ATtinyCore 라이브러리를 Board Manager 를 통해 설치합니다.


Tools > Board > Board Manager > search "ATtinyCore"



위의 과정까지 거치면, 아래처럼 Board 에서 ATtiny85 를 선택할 수 있습니다.





6. Arduino IDE - Programmer


이제 마지막으로 운용할 Programmer 를 선택합니다.

이미 우리는 Arduino 를 ISP 로 사용할 것을 알기에, "Arduino as ISP" 를 선택하면 됩니다.


ATtinyCore 라이브러리가 설치되어 있으므로, "Arduino as ISP (ATtinyCore)" 를 선택해도 됩니다만,

왠지 default 로 제공되는 것을 사용하고 싶어서 "Arduino as ISP" 를 선택했습니다.


어느쪽을 선택해도 문제없을것 같아요.



이제 Arduino IDE 에서의 준비는 끝났습니다.




7. Layout


ATtiny85 의 Pin 배열은 다음과 같습니다.



위의 그림을 참조하여 Arduino 와 ATtiny85 를 다음과 같이 연결합니다.


  ATtiny85  | Arduino Nano
---------------------------
    VCC     |     5V
    GND     |     GND
    Reset   |     D10
    Pin 0   |     D11
    Pin 1   |     D12
    Pin 2   |     D13
---------------------------


추가로 Arduino 의 GND/RESET 에 10uF 캐패시터를 연결해 줍니다.

이유는 Arduino 가 ATtiny85 에 업로드 할 때, auto reset 을 방지하기 위함이라 합니다.



실제 모양은 다음과 같아요.

그간 고생해서 얻은 "DIP to SOIC converter" 가 빛을 발하는 순간입니다.



이제 물리적인 구성은 완료 되었습니다.




8. sketch


소스는 아래 link 를 참조하였습니다.

깜빡이 간격이 좀 짧은것 같아 increment / decrement 를 5에서 1로 변경했습니다.


* Attiny85 blink fade for loop 3 LED

https://codebender.cc/sketch:354605


해당 소스는 단순히 LED 를 깜빡이게 하는것 외에도,

PWM (Pulse With Modulation) 기법을 이용하여 LED 점등을 fade 효과를 낸 것입니다.


/*
This code will allow you to mix fading and blinking on 3 LEDs
Jill Dawson
*/

int Pin0 = 0;	// LED connected to pwm pin 0, which can blink or fade
int Pin1 = 1;	// LED connected to pwm pin 1, which can blink or fade
int Pin2 = 2;	// LED connected to digital pin 2, which can only blink

void setup() {
	// nothing happens in setup
	// declares pins as outputs
	
	pinMode (0, OUTPUT);
	pinMode (1, OUTPUT);
	pinMode (2, OUTPUT);
} 

//Loop repeats
void loop() {
	// fades pin 0 in from min to max in increments of 5 points
	for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=1) {
		// sets the value (range from 0 to 255):
		analogWrite(Pin0, fadeValue);
		// wait for 30 milliseconds to see the dimming effect
		delay(30);
	}
	
	// fades pin 0 out from max to min in increments of 5 points
	for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=1) {
		// sets the value (range from 0 to 255):
		analogWrite(Pin0, fadeValue);
		// wait for 30 milliseconds to see the dimming effect
		delay(30);
	}
	
	// blinks LED 1 three times
	{
		digitalWrite (1, HIGH);	//turns pin 1 on
		delay (1000);			//waits for 1 second
		digitalWrite (1, LOW);	//turns pin 1 off
		delay (1000);			//waits for 1 second
		digitalWrite (1, HIGH);	//turns pin 1 on
		delay (1000);			//waits for 1 second
		digitalWrite (1, LOW);	//turns pin 1 off
		delay (1000);			//waits for 1 second
		digitalWrite (1, HIGH);	//turns pin 1 on
		delay (1000);			//waits for 1 second
		digitalWrite (1, LOW);	//turns pin 1 off
	}
	
	// blinks LED 2 three times
	{
		digitalWrite (2, HIGH);	//turns pin 2 on
		delay (1000);			//wait for 1 second
		digitalWrite (2, LOW);	//turns pin 2 off
		delay (1000);			//waits for 1 second
		digitalWrite (2, HIGH);	//turns pin 2 on
		delay (1000);			//wait for 1 second
		digitalWrite (2, LOW);	//turns pin 2 off
		delay (1000);			//waits for 1 second
		digitalWrite (2, HIGH);	//turns pin 2 on
		delay (1000);			//wait for 1 second
		digitalWrite (2, LOW);	//turns pin 2 off
		delay (1000);			//waits for 1 second
	}
	
	// fades pin 1 out from max to min in increments of 5 points
	for(int fadeValue = 0 ; fadeValue <= 255; fadeValue +=1) {
		// sets the value (range from 0 to 255):
		analogWrite(Pin1, fadeValue);
		// wait for 30 milliseconds to see the dimming effect
		delay(30);
	}
	
	// fades out from max to min in increments of 5 points:
	for(int fadeValue = 255 ; fadeValue >= 0; fadeValue -=1) {
		// sets the value (range from 0 to 255):
		analogWrite(Pin1, fadeValue);
		// wait for 30 milliseconds to see the dimming effect
		delay(30);
	}
}


Arduino IDE 에서 업로드 합니다.



AVR Part 항목을 보면 ATtiny85 로 정확히 인식합니다.



ATtiny85 에 FLUSH 가 성공하면 위와 같이 문제없이 완료가 됩니다.




9. 결과


짜잔~!





FIN


이제 ATtiny85 에 프로그램을 업로드 하여 standalone 으로 동작하는 것까지 확인할 수 있었습니다.


"ATtiny85 + DIP to SOIC adapter + USB board" 를 USB 에 직접 연결하여,

Arduino ISP 없이도 Digispark 처럼 프로그램을 업로드 할 수 있는게 목표므로, 다음 글에서 구성해 보도록 하겠습니다.


And

Hardware | ATtiny85 를 사용해 보자 - 1

|

1. 시작


Arduino Nano 를 사용하고 있지만, 실제 프로젝트 구성시 이렇게 많은 핀들이 필요할지 의문이 드는 때가 있습니다.

인터넷을 돌아다니다 보면, Arduino 본체는 아니지만 소스코드는 거의 동일하지만, chip 은 조그마한 것이 사용된 것을 볼 수 있습니다.


그 이름하야 ATtiny85.


Arduino Nano 에 들어가는 chip 이 Atmel 사의 MEGA328P 인데,

이 ATtiny85 의 생산회사도 Atmel 사 입니다.



이 ATtiny85 는 두가지 package 가 존재합니다.

하나는, 아래 보이느 DIP8 형태 (다리가 8개 벌레같은 칩) 의 ATtiny85.


'

다른 하나는, SOIC 형태 (납착한 보드 납땝식) 의 ATtiny85 입니다.



다리는 8개밖에 없는지라, power / ground 빼면 6개 이고, chip control 하는 1번을 빼면,

실제 가용할 수 있는 pin 수는 5개가 되겠군요.



실제 project 상에서 사용되는 Pin 수는 그리 많지 않기때문에,

간단한 sensor 를 이용하여 기능 구현할 때에는 Arduino 보단, 이런 ATtiny85 를 사용하는 것이 훨씬 경제적으로 보입니다.


- 장소 차지가 적다

- Power가 더 적게 먹을 것이다

- 기판 적층시 component 처럼 실장할 수 있다




2. 최종 모양


ATtiny85 에 프로그램을 upload 하기 위해서는, FTDI 나 Arduino ISP 모드를 이용하여 8k 자체 메모리에 업로드 해야 합니다.


위의 방법이 일반적이지만, 아래 그림의 처럼

직접 Arduino IDE 에서 프로그래밍 하여 USB를 통해 upload 할 수 있는, Digispark 모양으로 만들고 싶었습니다.


* Digispark

http://digistump.com/products/1



클라우드펀딩인 Kickstarter 에서도 큰 방향을 일으킨 제품입니다.


* Digispark - The tiny, Arduino enabled, usb dev board!

https://www.kickstarter.com/projects/digistump/digispark-the-tiny-arduino-enabled-usb-dev-board



지금까지 내용을 정리하면 최종 모습은 아래와 같은 모양이 됩니다.


- SOIC 형태

- Digispark 처럼 USB 를 통한 개발 보드 형태


알리에서 검색해 보면, DIP 소켓 을 사용하여 Digispark 처럼 사용할 수 있게 해주는 보드가 있습니다.

그럼 위의 DIP 소켓을 SOIC 로 변환해주는 adapter 를 이용하면, 최종적으로 SOIC를 사용할 수 있겠군요.



이제 구상이 끝났으니 AliExpress 에서 구입을 진행해 봅니다.




2. 구입 - ATtiny85


먼저 SOIC 타입의 ATtiny85 를 구매합니다.


* Free Shipping 5PCS Original Integrated circuit parts ATTINY85 ATTINY85-20SU

https://www.aliexpress.com/item/Free-Shipping-5PCS-Original-Integrated-circuit-parts-ATTINY85-ATTINY85-20SU/32318325945.html



5개에 1만원 정도이니, 여타 다른 chip 들에 비하면 비싼 편 입니다.



릴 package 를 끊어서 보내줬군요.



확대해서 보면 Atmel 사의 TINY85 라고 쓰여 있습니다.



여기서 잠깐, 구매한 ATtiny85 는 20SU 라는 코드가 달려 있습니다.

제품사양을 보면 20SH 는 좀더 비싸고, 20SU 는 조금 더 쌉니다. 기호의 의미는 다음과 같다고 하네요.


– H: NiPdAu lead finish

– U: matte tin


U는 주석이고, H 는 NiPdAu (Nickel-Palladium-Gold) 로 납땜시, 더 확고하고 쉽게 접합된다고 합니다.



이렇게까지 전문적으로 아직 필요가 없으므로, 무난하게 20SU 버전으로 구입합니다.




3. 구입 - USB board


ATtiny85 chip 을 엊고 USB 를 연결하게 할 수 있는 보드를 구매합니다.


물론 ATtiny85 가 DIP 소켓에 꽂혀 있는 일체형이나 SOIC chip 이 납땜되어 있는 버전도 팔지만,

SOIC 를 바꿔 끼울 수 있도록 adapter 를 사용할 것이기에 깡통 USB 보드를 선택합니다.


* ATtiny13A/ATtiny25 /ATtiny45/ATtiny85 Pluggable Development Programming Bare Board

https://www.aliexpress.com/item/Free-Shipping-ATtiny13A-ATtiny25-ATtiny45-ATtiny85-Pluggable-Development-Programming-Bare-Board/32706943203.html



배송 포함 1천원정도니 부담없습니다.



잘 도착해서 보니, 기판 찌꺼기가 같이 붙어 있네요.

뭐 이 가격이니 이해할 수 있습니다.



뒷면입니다.



기판 찌꺼기는 펜치로 잡고 구부리면 쉽게 제거됩니다.



제거되면 기분이 뭔가 좋아집니다. 이런 즐거움도 선사해 주는군요.



나중에 adapter 가 도착하여 ATtiny85 와 채결할 때, 호기심으로 1번 핀을 거꾸로 채결해 봤더니 연기가 나더군요.

(나중에 안 사실이지만, 이 연기는 솔더링 잘되라고 도포된 약품이 레귤레이터 열로 증발한 것)


USB 연결시에 PC 에서 인식 못하는 문제가, 이 태워먹은 결과라고 잘못 생각하고 바로 2개를 추가로 주문했습니다.

(USB 를 연결하여 Digispark 처럼 사용하려면, 필요한 과정이 더 있슴)



총 3개가 되었군요.




4. 구입 - DIP to SOIC converter


USB 의 DIP 소켓을 SOIC 를 엊을 수 있게 하는 adapter / converter 를 주문합니다.


* SOIC8 SOP8 to DIP8 EZ Socket Converter Module Programmer Output Power Adapter With 150mil Connector SOIC 8 SOP 8 To DIP 8

https://www.aliexpress.com/item/SOIC8-SOP8-to-DIP8-EZ-Socket-Converter-Module-Programmer-Output-Power-Adapter-With-150mil-Connector-SOIC/32613388551.html



잘 도착했습니다.



포장도 잘 되어 있네요.



정전기 방지 포장까지 되어 있습니다.



위에서 누르면 가운데 금속 다리가 벌어져 SOIC chip 을 끼울 수 있는 구조 입니다.


음?

그렇습니다. USB 의 DIP socket 과 맞지 않습니다. (이런 고추장....)
또한 SOIC chip 을 끼우는 가운데 공간도 좁아, ATtiny85 도 들어가지 않습니다.

알고보니 150mil 규격이 아니라 200mil 을 구매해야 했던 것이였습니다.
ATtiny85 의 스펙을 살펴보면, chip 몸채가 5.18 mm 인걸 알수 있습니다. (아래그림 E1)


이것에 대응하는 것이 200mil SOIC 소켓 입니다.


Chip 규격이 다양한 만큼 알아야 할것도 많네요.

AliExpress 의 무료배송 마약때문에, 새로 구입한 converter 가 도착하려면 최소 2주 이상을 또 기다려야 합니다.

이거 하나 하는데 도대체 얼마나 기다려야 하는겨.


가끔 AliExpress 를 통한 놀이는 기다림이 대부분인것 같습니다.

기다리다가 열정이 식어버려, 다시 끌어올리는데 시간이 많이 걸리는 경우가 있어요.




5. 구입 - 또다른 DIP to SOIC converter


이제 정확한 제품 규격을 알게 되었으니 제대로 구입합니다.

제품명에 "Universal" 이라는 문구가 왠지 신뢰갑니다.


* Universal Adapter Sockets SOP8 SOP 8 to DIP8 DIP 8 for all Programmer 200 208 mil

https://www.aliexpress.com/item/Universal-Adapter-Sockets-SOP8-SOP-8-to-DIP8-DIP-8-for-all-Programmer-200-208-mil/32680997921.html



드.디.어! 정확한 converter 가 도착 했습니다.



대충 포장되어 있더라도 상관 없습니다.



아아아아아! 이거 얼마나 걸린거야.




6. 최종 모습


겨우 최종 결과 모습이 되었습니다.

별것도 아닌것 같은데 너무 오래 걸렸네요.



USB 보드 + DIP to SOIC adapter + ATtiny85 구성 입니다.



모두 합체하면 이렇게 되죠.




FIN


여기까지 오는데 너무 힘을 빼서, 실제 Arduino IDE 를 이용한 program uploading 은 다음 편에서 다루도록 하겠습니다.


And

Hardware | TCS230/TCS3200 color sensor 를 사용해 보자

|

1. Color Sensor


색을 인식하는 센서가 있다고 해서 주문해 봤습니다.


* Color sensor TCS230 TCS3200 Color Recognition Sensor Detector Module DC 3-5V Input

https://ko.aliexpress.com/item/Free-Shipping-Color-sensor-TCS230-TCS3200-Color-Recognition-Sensor-Detector-Module-DC-3-5V-Input/32630370831.html





2. 도착


한 2주 걸렸습니다.

잘 쌓여서 왔습니다.



뒷면입니다.



저 가운데 있는 센서가 컬러 센서 인듯 하군요.



디지털 현미경으로 한번 확인해 봤습니다.



RGB 소자가 격자로 자리잡고 있네요.

소자 연결 부분은 금선으로 연결되어 있는 것이 보입니다.


센서의 스팩은 다음과 같습니다.


* TCS230

tcs230-e33.pdf





3. Pinout


Arduino 와의 pin 연결은 다음과 같습니다.

   TCS230   | Arduino Nano
---------------------------
     GND    |     GND
      OE    |      -
      S1    |     D4
      S0    |     D3
            |
      S3    |     D6
      S2    |     D5
     OUT    |     D2
     VCC    |     5V
---------------------------

Layout 은 다음과 같습니다.






4. Sketch


* Arduino Color Sensing Tutorial – TCS230 TCS3200 Color Sensor

https://howtomechatronics.com/tutorials/arduino/arduino-color-sensing-tutorial-tcs230-tcs3200-color-sensor/


아래는 color 센서에서 가장 기초가 되는 sketch 입니다.

소스를 보면 S2 / S3 를 high / low 를 가지고 RGB 를 구분하여 입력을 받는 구조 입니다.




/*     Arduino Color Sensing Tutorial
 *      
 *  by Dejan Nedelkovski, www.HowToMechatronics.com
 *  
 */
 
#define S0 3
#define S1 4
#define S2 5
#define S3 6
#define sensorOut 2
int frequency = 0;

void setup() {
  pinMode(S0, OUTPUT);
  pinMode(S1, OUTPUT);
  pinMode(S2, OUTPUT);
  pinMode(S3, OUTPUT);
  pinMode(sensorOut, INPUT);
  
  // Setting frequency-scaling to 20%
  digitalWrite(S0,HIGH);
  digitalWrite(S1,LOW);
  
  Serial.begin(9600);
}

void loop() {
  // Setting red filtered photodiodes to be read
  digitalWrite(S2,LOW);
  digitalWrite(S3,LOW);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  // Printing the value on the serial monitor
  Serial.print("R= ");//printing name
  Serial.print(frequency);//printing RED color frequency
  Serial.print("  ");
  delay(100);

  // Setting Green filtered photodiodes to be read
  digitalWrite(S2,HIGH);
  digitalWrite(S3,HIGH);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  // Printing the value on the serial monitor
  Serial.print("G= ");//printing name
  Serial.print(frequency);//printing RED color frequency
  Serial.print("  ");
  delay(100);

  // Setting Blue filtered photodiodes to be read
  digitalWrite(S2,LOW);
  digitalWrite(S3,HIGH);
  // Reading the output frequency
  frequency = pulseIn(sensorOut, LOW);
  // Printing the value on the serial monitor
  Serial.print("B= ");//printing name
  Serial.print(frequency);//printing RED color frequency
  Serial.println("  ");
  delay(100);
}


위의 소스는 센서의 주파수 특성을 그대로 표현해 줄 것입니다.






5. 결과


아래 무지개 색을 빨강부터 차례대로 비추어본 결과 입니다.



값이 주르륵 변하는게 보이네요.



값의 변화를 그래프로 표시해보니 다음과 같습니다.

빨간색일 경우는 빨간색이 가장 높고, 파란색일 경우는 파란색 파장이 가장 높습니다.



위의 결과는 단순히 frequency - 주파수의 값을 나타내므로, 0~255 까지를 보여주는 color decimal value 는 아닙니다.




6. color code 형식으로 표시


color code 방식으로 표시를 하기 위해선, 아래 사이트에서 소개된 TCS3200 sample 을 사용하면 됩니다.


* ARDUINO COLOR SENSOR / COLOR RECOGNITION SENSOR TCS230

http://www.instructables.com/id/Arduino-COLOR-Sensor-Color-Recognition-Sensor-TCS2/


* Sample library

TCS3200.zip


Library 에 중요한 코드가 들어가 있어서 sample sketch 는 너무 간단합니다.

심심한 부분도 있고 해서 color OLED 를 함께 사용한 code 를 짜 봅니다.


목표는 color OLED 에 현재 인식되는 color 도 표시하고 RGP decimal value 도 표시해 주는 것입니다.


#include "TCS3200.h"
uint8_t RGBvalue[3];
TCS3200 colSens;

// for color OLED
#define sclk 13
#define mosi 11
#define cs   10
#define rst  9
#define dc   8

#include "Adafruit_GFX.h"
#include "Adafruit_SSD1331.h"
#include "SPI.h"

// Option 1: use any pins but a little slower
Adafruit_SSD1331 display = Adafruit_SSD1331(cs, dc, mosi, sclk, rst); 

// Color definitions
#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0 
#define WHITE           0xFFFF

void setup() {
	Serial.begin(115200);
	Serial.println("BEGIN");
	colSens.begin();
	
	display.begin();
	display.fillScreen(BLACK);
}

void loop() {
	colSens.loop();
	colSens.getRGB (RGBvalue);
	//colSens.getRGBtoMaxCorrection (RGBvalue);
	
	// clear previous text
	display.fillRect(2, 2*(display.height())/12, (2.5*(display.width()))/6-1, 9*(display.height())/12, BLACK);
	
	
	display.setCursor(2, 2*(display.height())/12);
	display.setTextColor(RED);
	display.print("R "); //printing name
	display.print(RGBvalue[0]);
	
	display.setCursor(2, 5.5*(display.height())/12);
	display.setTextColor(GREEN);
	display.print("G "); //printing name
	display.print(RGBvalue[1]); //printing RED color frequency
	
	display.setCursor(2, 9*(display.height())/12);
	display.setTextColor(BLUE);
	display.print("B "); //printing name
	display.print(RGBvalue[2]); //printing RED color frequency
	
	// check what color is sensing
	if (RGBvalue[0] == 255 && (70 < RGBvalue[1] && RGBvalue[1] < 80) && (80 < RGBvalue[2] && RGBvalue[2] < 90))
		display.fillRect(2.5*(display.width())/6, (display.height())/12, 5*(display.width())/6, 11*(display.height())/12, RED);
	else if (RGBvalue[0] == 255 && RGBvalue[1] == 255 && (60 < RGBvalue[2] && RGBvalue[2] < 70))
		display.fillRect(2.5*(display.width())/6, (display.height())/12, 5*(display.width())/6, 11*(display.height())/12, YELLOW);
	else if ((110 < RGBvalue[0] && RGBvalue[0] < 120) && (160 < RGBvalue[1] && RGBvalue[1] < 170) && (100 < RGBvalue[2] && RGBvalue[2] < 110))
		display.fillRect(2.5*(display.width())/6, (display.height())/12, 5*(display.width())/6, 11*(display.height())/12, GREEN);
	else if ((70 < RGBvalue[0] && RGBvalue[0] < 80) && (98 < RGBvalue[1] && RGBvalue[1] < 108) && (200 < RGBvalue[2] && RGBvalue[2] < 210))
		display.fillRect(2.5*(display.width())/6, (display.height())/12, 5*(display.width())/6, 11*(display.height())/12, BLUE);
}


if 문이을 간결하게 하거나 변수화 시킬 수 있는 부분은 많으나, 그냥 발로 짰습니다.

또한, text update 를 하는 방법을 몰라 그냥 fillRect() 함수로 문대 버리다 보니, 인터럽트가 걸려서 색 인식 update 가 늦습니다.


판별 루틴에서 프린트된 빨간색과 센서가 인식되는 값이 달라서, 센서 인식 값 기준으로 +5/-5 로 값의 범위를 맞췄습니다.

그냥 보여주기식 꼼수...



이하 동영상 입니다.



동영상에서는 노란색 인식이 똥망이네요.





FIN


색을 인식하는 모듈을 어디에 쓸꺼냐고 물어보면... 딱히 적절한 대답이 생각나지 않습니다 만...

언젠가는 한번 있을지도... (아니면 없을지도...)

And

Hardware | Arduino 의 AREF pin 에 대해 알아보자

|

1. 시작


일전에 여러 photoresistor 의 수치적인 차이를 확인해 보았습니다.


* Hardware | Arduino 로 Photoresister 가지고 놀기 - 2

http://chocoball.tistory.com/entry/Hardware-Arduino-Photoresister-2


여기서 사용했던 arduino 의 또다른 기능.

그것은 AREF 였습니다.



위의 글에서는 참고한 사이트를 단순히 따라하다 보니 진정 AREF 의 기능을 모르고 사용했더랬습니다.

오늘은 이 AREF 에 대해 좀더 알아보도록 하죠.




2. What is the AREF?


왜 욕하냐구요?

아닙니다. Arduino 는 영어하는 형들이 만들었으므로, 기본 영어로 모든 문서가 되어 있습니다.


AREF 는 Analog REFerence 의 약자 입니다.


가장 명확한 설명은 당연 arduino 제조사 사이트겠지요.


* analogReference()

https://www.arduino.cc/reference/en/language/functions/analog-io/analogreference/


다만 뭔가 와닿지 않습니다.

다른 사이트를 살펴 보지요.


* Arduino Tutorials – Chapter 22 – the AREF pin

http://tronixstuff.com/2013/12/12/arduino-tutorials-chapter-22-aref-pin/


설명이 자세하게 잘 나와 있습니다.

요는, analogRead() 를 통해서 입력받은 voltage 값이 작거나 차이가 적을 때, digital 화 시켜서 leveling 을 해준다는 것 입니다.


실제로 photoresistor 를 가지고 놀았을 때, 소자간의 차이가 거의 없는 경우는,

단순히 voltage 값만 안다고 해서 그 차이를 느낄 수가 없었습니다.




3. ADC


이런 analog 값을 digital 로 바꿔주는 기능이 ADC 입니다.

그럼 ADC가 뭐야? 라고 할 수 있습니다. (욕 아니예요)


* Analog to Digital Conversion

https://learn.sparkfun.com/tutorials/analog-to-digital-conversion



위의 그림처럼 5V 기준으로 4가지로 레벨링 한다고 합시다 (0, 1, 2, 3),

입력값이 1V라고 한다면 1.25V ~ 0V 사이이므로 0값을 리턴하고, 3V 라고 한다면 2값을 리턴하게 됩니다.

위의 경우는 2의 2승인 2-bit 해상도의 ADC 입니다.


Arduino 는 10-bit ADC 가 내장되어 있어서, 2의 10승인 1024 leveling 이 가능합니다.

실제 output 값은 0~1023 까지가 되지요.



아래는 실제 photoresistor 를 측정했을 시의 표시 값들입니다.

실제 voltage 값이 아니라 0~1023 으로 leveling 한 값이 측정되게 됩니다.






4. Sketch


그럼 어떻게 사용하는 것일까요?

아래 소스처럼 선언해주면 됩니다.


void setup() {
  ...

  analogReference(EXTERNAL);

  ...
}


옵션의 의미는 다음과 같습니다.


* DEFAULT

  - 5V 전압이 기본인 arduino 에서는 5V,

    3.3V 전압을 사용하는 arduino 에서는 3.3V 를 기준 전압으로 사용합니다.


* INTERNAL

  - 내장 기준 전압을 사용한다는 의미이며, ATmega168/ATmega328 를 사용한 arduino 에서는 1.1V,

    ATmega8 를 사용한 보드에서는 2.56V 가 기준 전압이 됩니다.

    Arudino MEGA 는 아래 두가지 (1V1 / 2V56) 기준이 사용됩니다.


* INTERNAL1V1 (only for Arduino MEGA)

  - 내장 1.1V 를 기준 전압으로 사용합니다.


* INTERAL2V56 (only for Arduino MEGA)

  - 내장 2.56V 를 기준 전압으로 사용합니다.


* EXTERNAL

  - AREF 핀에 외부 전원 (0~5V)을 연결하여, 이를 기준 전압으로 사용합니다.

  - 이것을 우리가 사용한 것이죠.





FIN


이제 analogRead() 를 사용할때면 analogReference() 를 사용하여 쉽게 leveling 할 수 있을것 같습니다.


And

Hardware | HC-SR501 PIR motion sensor - 2

|

1. 시작


HC-SR501 을 가지고 움직임이 있을 시 반응하는 센서를 가지고 놀아 봤더랬습니다.


* Hardware | HC-SR501 PIR motion sensor

http://chocoball.tistory.com/entry/Hardware-HCSR501-PIR-motion-sensor


그러던 중, Photoresistor 단자를 발견합니다.



아래는 HC-SR501 회로도 입니다.



제조사의 사이트에 올라와 있는 회로도와 실제 기판을 봐도 이미 R3 (1MΩ) 이 실장되어 있어서,

제대로 된 값의 photoresistor 만 달면 기능하게 되어 있네요.


좀더 찾아 보니, 아예 세트로 파는 업자도 있습니다.



요는 photoresistor 를 이용하여, 항상 모션 탐지를 하는 것이 아니라,

어두워졌을 때에만 작동하도록 하는 것 입니다.


흠흠, 그럼 photoresistor 를 구입해야 겠죠?





2. Photoresistor 가지고 놀기


HC-SR501 에 photoresistor 를 붙여서 구동하기 위해, 우선 photoresistor 를 가지고 놀아봅니다.


* Hardware | Arduino 로 Photoresister 가지고 놀기 - 1

http://chocoball.tistory.com/entry/Hardware-Arduino-Photoresister-1


이때 구입한 제품이 GL5528.

간단한 동작을 확인 했으니, 본격적으로 HC-SR501 에 붙여 봅니다.





3. HC-SR501 에 납땜하기


Photoresistor 는 RL 이라는 자리에 납땜하면 됩니다.

+/- 전극 구분이 없어서 그냥 두 다리 고정하고 납땜하면 됩니다.



높이 잘 계산해서 올려주고요.



장착되면 위와 같은 모습이 됩니다.



다리를 옆으로 벌려서 흔들리지 않게 하고 납땜합니다.



짜잔 !!!




4. Layout 및 Sketch


구성은 예전 글에서 사용했던 구성과 sketch 와 완벽히 동일합니다.


HC-SR501 PIR sensor | Arduino Nano
----------------------------------
         S          |     D8
         +          |     5V
         -          |     GND
----------------------------------
 
    Piezo busser    | Arduino Nano
----------------------------------
         S          |     D11
         +          |     5V
         -          |     GND
----------------------------------


회로 구성입니다.



Sketch 입니다.


/*******************************************************
 
Uses a PIR sensor to detect movement, sounds a buzzer
 
*******************************************************/
//the time we give the sensor to calibrate (10-60 secs according to the datasheet)
int calibrationTime = 30;
 
int ledPin = 13; // choose the pin for the LED
int inputPin = 8; // choose the input pin (for PIR sensor)
int pirState = LOW; // we start, assuming no motion detected
int val = 0; // variable for reading the pin status
int pinSpeaker = 11; //Set up a speaker on a PWM pin (digital 9, 10, or 11)
 
void setup() {
pinMode(ledPin, OUTPUT); // declare LED as output
pinMode(inputPin, INPUT); // declare sensor as input
pinMode(pinSpeaker, OUTPUT);
 
//give the sensor some time to calibrate
Serial.begin(9600);
Serial.print("Calibrating sensor ");
  for(int i = 0; i < calibrationTime; i++) {
    Serial.print(".");
    delay(1000);
  }
  Serial.println(" Done!");
  Serial.println("SENSOR is ACTIVE now");
  delay(50);
}
 
void loop() {
  val = digitalRead(inputPin); // read input value
  if (val == HIGH) { // check if the input is HIGH
    blinky(); // blink LED when motion haas been detected
    // digitalWrite(ledPin, HIGH); // turn LED ON
    playTone(300, 160);
    delay(150);
     
    if (pirState == LOW) {
    // we have just turned on
      Serial.println("Motion detected!");
      // We only want to print on the output change, not state
      pirState = HIGH;
    }
  } else {
    digitalWrite(ledPin, LOW); // turn LED OFF
    playTone(0, 0);
    delay(300);
 
    if (pirState == HIGH){
    // we have just turned off
      Serial.println("Motion ended!");
      // We only want to print on the output change, not state
      pirState = LOW;
    }
  }
}
 
void playTone(long duration, int freq) {
  // duration in mSecs, frequency in hertz
  duration *= 1000;
  int period = (1.0 / freq) * 1000000;
  long elapsed_time = 0;
 
  while (elapsed_time < duration) {
    digitalWrite(pinSpeaker,HIGH);
    delayMicroseconds(period / 2);
    digitalWrite(pinSpeaker, LOW);
    delayMicroseconds(period / 2);
    elapsed_time += (period);
  }
}
 
void blinky() {
  for(int i=0; i<3; i++) {
    digitalWrite(13, HIGH);
    delay(200);
    digitalWrite(13, LOW);
    delay(200);
  }
}





5. 흠...


손으로 photoresistor 를 가리면 동작은 하는데, 기민하게 동작하지 않았습니다.


원래 회로는 short 된 회로인데,

photoresistor 를 연결하면 광원이 있는 곳에서 close 상태로 만들어 주어 모션 감지를 하지 않게 (disable) 됩니다.


주위가 어두워 지면 photoresistor 의 dark resistance 가 올라가

원래 회로가 가지고 있던 short 상태를 만들어 주는 것인데,

어정쩡하게 저항이 발생하면 제대로 short 된 상태로 넘어가지 못하는 것이었습니다.


뭔가 Photoresistor 가 망가졌나? 생각하고 다른 GL5528 센서로 교환하다, 옆에 있던 캐패시터 옆구리를 지져버렸습니다.

아놔...


다행히 기존에 구입해 놨던 capacitor 가 있어서 교체합니다.


* Hardware | AliExpress 에서 condenser 를 구입해 보자

http://chocoball.tistory.com/entry/Hardware-AliExpress-condenser-buy



기존의 capacitor 보다는 굵은 소자라 뭔가 신뢰가 가네요.






6. 다른 Photoresistor


Capacitor 를 교환했고, photoresistor 도 교환했음에도 불구하고 여전히 기민하게 동작하지 않습니다.

Photoresistor 를 가리고 한참 기다리고 있어도 운 좋으면 detecting 하고, 그렇지 않으면 아무 반응이 오지 않았습니다.


결국 구입한 photoresistor 의 수치적인 한계라고 확신하고, 다른 photoresistor 를 구입해서 테스트 해보기로 합니다.


처음 구입할때는 보이지 않았던, 5가지 묶음 세트가 있네요.

바로 구입합니다. (아니 왜 저 세트로 처음부터 안파냐고...)


* Photoresistor Kit 5Kindsx10pcs 5506 5516 5528 5537 5539 Light Dependent Resistor LDR Pack Photoresistor Package for Arduino

- https://ko.aliexpress.com/item/Photoresistor-Kit-5Kindsx10pcs-5506-5516-5528-5537-5539-Light-Dependent-Resistor-LDR-Pack-Photoresistor-Package-for/32812625860.html



각 소자 번호에 따라 어떤 값을 보이는지 테스트 해봤습니다.


* Hardware | Arduino 로 Photoresister 가지고 놀기 - 2

http://chocoball.tistory.com/entry/Hardware-Arduino-Photoresister-2


수치를 그래프화 해본 결과, 처음 구입한 GL5528 (녹색) 은 가장 어둡게 해도

dark resistance 가 조금 높게 나옵니다. (스펙상으로는 1MΩ 이긴 한데...)



확인 결과 새로 구입한 세트에 있는 5539 (하늘색) 이 더 높은 dark resistance 를 보여 줬습니다.

어둡게 하면 거의 short 상태를 만들어 줄 수 있을 것 같습니다.



수치적으로도 5MΩ 정도면 short 상황을 만들 수 있겠네요. 





7. 구동 확인


기존 GL5528을 제거하고 새로 구입한 5539 를 납땜해 주었습니다.

이제 대망의 마지막 확인 입니다.



5539 photoresistor 는 센서의 구불구불이 더 촘촘하네요.



어둡게 하면 의도대로 잘 동작합니다.



Photoresistor 에 샤프심 캡을 씌워, 어두운 상황을 만들어 동작 시키니 예상대로 반응합니다.




FIN


작년 7월에 처음 photoresistor 를 구매하여 실패의 실패를 거듭하여 겨우 확인 했습니다.

HC-SR501 센서는 이제 서랍으로 들어갈 수 있게 되었습니다.


Photoresistor 는 종류와 가용 범위가 많아서 잘 선택하고 사용해야겠습니다.


이제야 마음 편하게 다른 센서들 공부를 할 수 있겠네요.


And

Hardware | Arduino 로 Photoresister 가지고 놀기 - 2

|

1. 시작


Photoresistor 를 가지고 놀아 봤더랬습니다. (아래 글)


* Hardware | Arduino 로 Photoresister 가지고 놀기 - 1

http://chocoball.tistory.com/entry/Hardware-Arduino-Photoresister-1



다만, 위의 사진에서 보이듯 광원을 받는 센서부의 홈 갯수가 적어 보이는 것 같았습니다.

밑의 사진처럼 촘촘하면, 뭔가 더 예민하게 반응할 것 같았습니다.



이미 PIR motion sensor 에도 GL5528 을 가지고 적용해 봤으나 (아래 글),

완벽한 어둠이 있지 않으면 동작하지 않아, 적당한 어둠에도 동작하도록 하기 위해 위와 같이 촘촘한 센서를 찾아보게 됩니다.


* Hardware | HC-SR501 PIR motion sensor

http://chocoball.tistory.com/entry/Hardware-HCSR501-PIR-motion-sensor





2. 주문


AliExpress 를 뒤져 봅니다.

제가 GL5528을 구입할 때만 해도 다양한 센서를 한묶음으로 파는 경우를 못본것 같은데, 이제는 팔고 있네요.


* Photoresistor Kit 5Kindsx10pcs 5506 5516 5528 5537 5539 Light Dependent Resistor LDR Pack Photoresistor Package for Arduino

https://ko.aliexpress.com/item/Photoresistor-Kit-5Kindsx10pcs-5506-5516-5528-5537-5539-Light-Dependent-Resistor-LDR-Pack-Photoresistor-Package-for/32812625860.html




미리 이런게 있었더라면...

하면서 바로 주문을 넣습니다.


다양한 센서라 그런지, 다른 부품들보다는 다소 비싼 편 입니다. 한, 500원 정도 ?! :-)





3. 도착


한 2주 걸려서 도착했습니다. 알리에서 주문한 것 치곤 빠른 편 입니다.



스폰지 형태로 잘 포장되어 왔구요.



한뭉텅이로 왔구요.



각 부품이 10개씩 포장되어 들어 있구요.



네 그렇습니다.

이렇게 촘촘한 photoresistor 센서를 얻기 위해, 첫번째 시행착오를 거쳐 두번째 구매를 하게 된 것이죠.


다만, 각 센서의 감도 차이를 알고 싶어졌습니다.

물론 spec. 문서를 보면 나와 있습니다만, 주변의 빛의 세기에 따라 어떤 형태의 값들로 움직이는지 보고 싶었습니다.


또한 예전에 구입한 GL5528 이 다른 센서들과 비교하여,

PIR 센서에 적합한 센서를 찾기 위해 값을 비교해 보기로 합니다.





4. Layout


입력은 5V 이지만, 0~1023 레벨로 결과값을 받을 수 있게, 3.3V 를 AREF pin 에 연결합니다.

저도 이번에 AREF를 사용하면서 AREF 의 용도를 알게 되었습니다.


AREF 에 대해서는 따로 정리해 봤습니다.


* Hardware | Arduino 의 AREF pin 에 대해 알아보자

http://chocoball.tistory.com/entry/Hardware-Arduino-AREF-pin



아래는 구성도 입니다.



아래는 실제 배선 샷 입니다.



사진에는 마지막에 추가한 GL5528 이 없습니다.

이 테스트를 하기 전에 사진을 찍은 후, 자고 일어났더니 예전 GL5528 이 생각이 나, 추가하여 결과값을 추출하였습니다.



저항은 10k ohm 입니다.

이는 아래 사양서에서 볼 수 있듯이, 일반적인 낮의 100 lux 에서 대략 10k ohm 의 값을 가지기 때문입니다.






5. Sketch


원리는 다음과 같습니다.


V = IR


* case 1 : 10KΩ

  - 10KΩ + 10KΩ = 20KΩ

  - I = 5V / 20KΩ = 0.25mA

  - 0.25mA * 10KΩ = 2.5V

  - 5V - 2.5V = 2.5V --> analog input


* case 2 : 30KΩ

  - 30KΩ + 10KΩ = 40KΩ

  - I = 5V / 40KΩ = 0.125mA

  - 0.125mA * 30KΩ = 3.75V

  - 5V - 3.75V = 1.25V --> analog input


* case 3 : 100KΩ

  - 100KΩ + 10KΩ = 110KΩ

  - I = 5V / 110KΩ = 0.045mA

  - 0.045mA * 100KΩ = 4.54V

  - 5V - 4.54V = 0.54V --> analog input


less light --> more resistance --> less analog input

more light --> less resistance --> more analog input


결론은,

많은 광량일 경우는 높은 치수를, 즉 낮은 저항 수치를 가지고,

적은 광량일 경우는 낮은 치수를, 즉 높은 저항 수치를 가지고 서로의 성능을 비교하는 과정입니다.


지금까지의 과정과 아래 소스는 다음 blog 를 참조하였습니다.


* Photo resistors, in depth

https://piandmore.wordpress.com/2016/10/14/photo-resistors-in-depth/


예전에 구입한 GL5528 를 A5 에 추가 연결하였으므로, 소스에서도 입력과 출력에 대해 A5 를 추가하였습니다.


////////////////////////////////////////////////////////////////////////////////////
//
//                               PI and more
//                      Photo resistors in depth
//
// https://piandmore.wordpress.com/2016/10/14/photo-resistors-in-depth/
//
////////////////////////////////////////////////////////////////////////////////////
//
// The number of steps after which the header is repeated
//
#define STEPCOUNT 10
//
// The current step count
//
byte step = STEPCOUNT;

void setup() {
  //
  // Setup serial
  //
  Serial.begin(115200);
  Serial.println("Ready");
  //
  // Set the reference for measuring the analog signals
  // For some reason I got incorrect readings without connecting
  // the 3.3v (on my Arduino Nano) to AREF and setting this
  // reference
  analogReference(EXTERNAL);
  //
  // Setup all analog inputs. We are using 5 which is the maximum
  // for the Nano on which I tested.
  //
  pinMode(A0,INPUT);
  pinMode(A1,INPUT);
  pinMode(A2,INPUT);
  pinMode(A3,INPUT);
  pinMode(A4,INPUT);
  pinMode(A5,INPUT);
}

void loop() {
  //
  // Increase our counter
  //
  step++;
  //
  // If we are over our STEPCOUNT then we repeat the header
  //
  if (step>STEPCOUNT) {
    //
    // The reference to the different photo resistors
    // GL5506, GL5516, GL5528, GL5537 and GL 5539
    //
    Serial.println("* 5506  5516  5528  5537  5539  GL5528");
    step = 0;
  }
  //
  // Print all analog values to serial
  //
  Serial.print("  ");
  Serial.print(analogRead(A0));
  Serial.print("   ");
  Serial.print(analogRead(A1));
  Serial.print("   ");
  Serial.print(analogRead(A2));
  Serial.print("   ");
  Serial.print(analogRead(A3));
  Serial.print("   ");
  Serial.print(analogRead(A4));
  Serial.print("   ");
  Serial.print(analogRead(A5));
  Serial.println();
  delay(250);
}


위의 sketch 를 실행시키면 다음과 같이 "Serial Monitor" 를 통해서 값을 확인할 수 있습니다.







6. 결과


제조사의 사양서는 찾을 수 없었지만, 5506 부터 나와있는 사양 테이블은 아래와 같습니다.

그래프를 보면 결과값과 비슷하게 나온것 같습니다.



강한 불빛인 휴대폰 플레쉬부터, 거실 불 하나만의 광량, 손으로 그늘을 만들고,

마지막에 손으로 가리는 순간들의 값을 EXCEL 정리해 봤습니다.


* EXCEL

photoresistor_record_20180225.xlsx


숫자로만 보면 들쑥날쑥 하여 알아보기 힘듭니다.

아래의 그래프로 그려봤습니다.



EXCEL 숫자만 보면, 과연 순서대로 나열해서 했나 싶을 정도로 들쑥날쑥 합니다만,

그래프로 그리면 확실히 그 경향을 알 수 있습니다.




FIN


예전에 구입한 GL5528 (녹색) 은, 이번에 구입한 5528 (회색) 과 확연한 값의 차이를 나타냅니다.

오히려 5537 (노랑) 과 더 비슷해 보이는군요.


위의 결과를 가지고 생각해 보면, photoresistor 를 직접 사용하기 전에는 측정을 통하여 사용처에 맞는 센서를 골라야 하겠군요.


And

Hardware | Digitial Compass - HMC5883L 사용기 - 1

|

1. 시작하기


지구의 자력을 측정할 수 있는 digital compass 센서가 있다는 소문을 들었습니다.


센서 내부에 코일을 감은 자석에 +/- 극을 지속적으로 변화시켜,

자기장의 변화에 따른 저항을 측정하는 방식으로 방위를 파악한다고 합니다.



* Magnetoresistance

https://en.wikipedia.org/wiki/Magnetoresistance



지표를 기준으로 기울기까지 파악할 수 있습니다.

X/Y 로만 측정하면 방위를 측정할 수 있겠죠.



지구는 위의 그림처럼 자기작을 가지고 있습니다.

위의 그림의 출처는 다음에 있는 블로그를 참조하였습니다.


* Arduino: simple compass with HMC5883L + Library

http://bluelemonlabs.blogspot.kr/2013/08/arduino-simple-compass-with-hmc5883l.html


정확히는 "Anisotropic Magnetoresistance" 현상을 이용한 것이라고 합니다.

더 자세히 알고싶으시면 구글링~.





2. 센서 구입


이런 현상을 이용하여 digital compass 를 쉽게 만들 수 있는 센서를 구입하지 않는 이유를 찾을 수 없었습니다.


* GY-273 3V-5V HMC5883L Triple Axis Compass Magnetometer Sensor Module Three Axis Magnetic Field Module For Arduino

https://ko.aliexpress.com/item/GY-273-3V-5V-HMC5883L-Triple-Axis-Compass-Magnetometer-Sensor-Module-Three-Axis-Magnetic-Field-Module/32826264150.html



센서류 치고는 좀 비싸지만 그렇게 많이는 아니여서 망설임 없이 구입합니다.

(이게 나중에 화근이 됩니다)





3. 도착


무난하게 도착하였습니다.



뽁뽁이 봉지에 잘 넣어서 왔으며, 전자파 방지 비닐에 싸아서 왔습니다.



Header pin 은 납땜되지 않은 채로 왔습니다.

아무래도 운송시 휠수도 있고, 튀어나온 곳으로 힘을 받을 수 있으니까요.



중국 제조사의 이름은 GY-273 인듯 합니다.





4. Layout


Pinout 정보는 다음과 같습니다.


  HMC5883L  | Arduino Nano
---------------------------
    VCC     |     3.3V
    GND     |     GND
    SCL     |     A5
    SDA     |     A4
---------------------------


회로 배선은 다음과 같습니다.



실제 배선은 다음과 같습니다.






5. WTF


순서상으론 이 부분에서 소스를 보여줘야 하나, 다음과 같이 정상적으로 구동이 되지 않는 화면을 먼저 보여드립니다.



Arduino 자체가 망가졌나 해서, 가지고 있던 다른 Arduino Nano 클론 및 Arduino Micro 도 사용해 봤습니다.



가능한 모든 방법을 동원해 봤습니다.

그래도 안되더군요.


정말 가끔 있는 breakout 보드가 망가졌나 했습니다.


한가지 의심스러운 것은 HMC5883L breakout 보드의 I2C address 가, 보통 sample sketch 에서는 "0x1E" 으로 표현되어 있는데,

제가 구입한 보드는 "0x0D" 라고 표시되는 것이였습니다.


뭐, 중국 카피품일 경우, 이 address 가 다르게 나오는 경우가 있어, sketch 에서 변경만 하고 실행했더랬습니다.



위에서 3c 는 OLED 를 같이 접속시켜 확인한 결과 입니다.

문제 없이 "0d" 부분에 연결이 되어 있다고 뜹니다.


인터넷에서 가능한 다른 sample sketch 를 구해서 해봤으나 실패했습니다.





6. i2c scanner


혹여 i2c scanner 의 문제인가 하고, 다른 i2c scanner 도 구해서 해봤으나, 결과는 같았습니다.


// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not known.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// 
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include "Wire.h"

void setup() {
	Wire.begin();
	
	Serial.begin(9600);
	Serial.println("\nI2C Scanner");
}

void loop() {
	byte error, address;
	int nDevices;
	
	Serial.println("Scanning...");
	
	nDevices = 0;
	
	for(address = 1; address < 127; address++ ) {
		// The i2c_scanner uses the return value of
		// the Write.endTransmisstion to see if
		// a device did acknowledge to the address.
		
		Wire.beginTransmission(address);
		error = Wire.endTransmission();
		
		if (error == 0) {
			Serial.print("I2C device found at address 0x");
			if (address<16) Serial.print("0");
			Serial.print(address,HEX);
			Serial.println("  !");
			
			nDevices++;
		} else if (error==4) {
			Serial.print("Unknow error at address 0x");
			if (address<16) Serial.print("0");
			Serial.println(address,HEX);
		}
	}
	
	if (nDevices == 0) Serial.println("No I2C devices found\n");
	else Serial.println("done\n");
	
	delay(5000);           // wait 5 seconds for next scan
}


결과는 다음과 같이 동일하게 "0x0D" 라고 명확하게 표시됩니다.



참고로 앞으론 이 i2c scanner 도 사용해봐야겠네요.
연결된 I2C 부품을 깔끔하게 HEX address 를 표현해 줍니다.





7.  QMC5883L


진심으로 보드가 고장난 것이라 생각하고 재구매를 생각하고 있었습니다.


그러다가 다음과 같은 블로그 글을 읽게 됩니다.

결론은 HMC5883L 이 모두 동일한게 아니라 중국발 QMC5883L 이라는 제품이 있고, 전혀 동일하지 않다는 내용입니다.

허거걱 !!!


* Problem with HMC5883L magnetometer

https://www.reddit.com/r/AskElectronics/comments/5xo3md/problem_with_hmc5883l_magnetometer/



* PROBLEMS WITH GY-271 MAGNETOMETER (HMC5883L != QMC5883L)

http://www.esp8266.com/viewtopic.php?f=13&t=15445


Chip 자체가 다르고 identical 하지 않다고 하니, 한번 살펴 봅니다.



사진으로는 잘 모르겠으나, 일반적인 HMC5883L 과는 다른 마킹임에는 틀림 없어 보입니다.

구매 사이트에서 사진을 퍼와 봤습니다.



완전히 다르네요. "DA 5883 6014" 라고 되어 있습니다.

Sparkfun 에서의 HMC5883L 의 제품은 다음 그림과 같습니다. "L883 2105" 라고 되어 있습니다.


* Sparkfun

https://www.sparkfun.com/products/retired/10494



AliExpress 의 구매 사이트를 더 뒤져 보니 다음과 같은 문구를 발견했습니다.

"Note: It is Domestic Chip HMC5883, the program is not compatible ...."



아놔...


어떤 사이트에는 "Bad Sensor" 라고도 올려져 있습니다.



위의 사진을 보면 정말 main chip 만 다를 뿐, 완벽하게 동일한 구성품과 회로도 입니다.


* HMC5883L(Or QMC5883L) Electronic Compass

http://wiki.epalsite.com/index.php?title=HMC5883L(Or_QMC5883L)_Electronic_Compass


QMC5883L 의 Datasheet 는 다음과 같습니다.

QMC5883L-Datasheet-1.0.pdf





8. Sketch


cpp 및 h 파일은 다음 사이트에서 가져 왔습니다.

arduino/library/ 디렉토리에 "QMC5883L" 이라고 만들고, 그 안에 cpp 와 h 파일을 넣었습니다.


* HMC5883L Compass Module Comunicating but all zero's for x,y,z

https://forum.arduino.cc/index.php?topic=482179.0


Library 소스를 보면 address 가 이미 "0x0D" 라고 박혀 있네요.


QMC5883L 의 sample sketch 를 옮겨 봅니다.


/*
QMC5883L_Example.ino - Example sketch for integration with an QMC5883L triple axis magnetometer.
Copyright (C) 2017 Andy Barnard based on an original for the QMC5883L by Love Electronics (C) 2011

This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

See .

*/

// Reference the I2C Library
#include "Wire.h"
// Reference the QMC5883L Compass Library
#include "QMC5883L.h"

// configure the compass as reqiured
#define OSR 0b00               // over sampling rate set to 512. 0b01 is 256, 0b10 is 128 and 0b11 is 64
#define RNG 0b00               // Full Scale set to +/- 2 Gauss, 0b01 is +/- 8.
#define ODR 0b00               // output data rate set to 10Hz, 0b01 is 50Hz, 0b10 is 100Hz, 0b11 is 200Hz
#define MODE 0b01              // continuous measurement mode, 0b00 is standby
#define CR2 0b00000000          // control register 2: disable soft reset and pointer rollover, interrupt pin not enabled
#define RESETPERIOD 0b00000001  // datasheet recommends this be 1, not sure why!

// Store our compass as a variable.
QMC5883L compass;
// Record any errors that may occur in the compass.
int error = 0;

// Out setup routine, here we will configure the microcontroller and compass.
void setup() {
	// Initialize the serial port.
	Serial.begin(9600);
	
	Serial.println("Starting the I2C interface.");
	Wire.begin(); // Start the I2C interface.
	TWBR = 12;    //Set the I2C clock speed to 400kHz - only works with Arduino UNO
	
	Serial.println("Constructing new QMC5883L");
	compass = QMC5883L(); // Construct a new HMC5883 compass.
	
	// Check that a device responds at the compass address - don't continue if it doesn't - 
	do {
		delay(100);
		Wire.beginTransmission(QMC5883L_Address);
		error = Wire.endTransmission();
		if (error) Serial.println("Can't find compass - is it connected and powered up?");
	} while (error);
	
	// configure the control registers using static settings above
	// compass autoranges, but starts in the mode given
	compass.dataRegister.OSR_RNG_ODR_MODE = (OSR << 6) |(RNG << 4)  | (ODR <<2) |  MODE;
	compass.dataRegister.CR2_INT_ENABLE = CR2;
	compass.dataRegister.SET_RESET_PERIOD = RESETPERIOD;
	
	Serial.println("Configuring QMC5883L - OSR 512, range +/-2 Gauss, ODR 10, Continuous");
	error = compass.Configure(compass.dataRegister); // use static settings from above - can access register data directly if required..
	if (error != 0) // If there is an error, print it out, although no way to get error with this sensor....
	Serial.println(compass.GetErrorText(error));
}

// Our main program loop.
void loop() {
	// Retrive the raw values from the compass (not scaled).
	MagnetometerRaw raw = compass.ReadRawAxis(&compass.dataRegister);
	// Retrived the scaled values from the compass (scaled to the configured scale).
	MagnetometerScaled scaled = compass.ReadScaledAxis(&compass.dataRegister);
	
	// Values are accessed like so:
	int MilliGauss_OnThe_XAxis = scaled.XAxis;     // (or YAxis, or ZAxis)
	
	// Calculate heading when the magnetometer is level, then correct for signs of axis.
	// heading (degrees): 0 = +X, 90 = +Y, 180 = -X, 270 = -Y
	float heading = atan2(scaled.YAxis, scaled.XAxis);
	
	// Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
	// Find yours here: http://www.magnetic-declination.com/
	// Example is: 2� 37' W, which is 2.617 Degrees, or (which we need) 0.0456752665 radians, I will use 0.0457
	// If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
	// float declinationAngle = 0.0457;
	
	float declinationAngle = 0;
	heading += declinationAngle;
	
	// Correct for when signs are reversed.
	if (heading < 0)
		heading += 2*PI;
	
	// Check for wrap due to addition of declination.
	if (heading > 2*PI)
		heading -= 2*PI;
	
	// Convert radians to degrees for readability.
	float headingDegrees = heading * 180/M_PI;
	
	// Output the data via the serial port.
	Output(raw, scaled, heading, headingDegrees);
	
	// Normally we would either:
	// 1. delay the application by 100ms to allow the loop to run at 10Hz (default bandwidth for the QMC5883L)
	// 2. poll the dataready flag in the dataRegister.OVL_DRDY register
	// 3. set the interrupt flat and set a hardware interrupt on the DRDY pin 
	// The first of these options is the easiest.
	delay(100);
}

// Output the data down the serial port.
void Output(MagnetometerRaw raw, MagnetometerScaled scaled, float heading, float headingDegrees)
{
   Serial.print("Raw (X,Y,Z): (");
   Serial.print(raw.XAxis);
   Serial.print(", ");   
   Serial.print(raw.YAxis);
   Serial.print(", ");   
   Serial.print(raw.ZAxis);
   
   Serial.print(")\tScaled (X,Y,Z): (");
   Serial.print(scaled.XAxis, 4);
   Serial.print(", ");   
   Serial.print(scaled.YAxis, 4);
   Serial.print(", ");   
   Serial.print(scaled.ZAxis, 4);
   Serial.println(")");

 
   Serial.print("Magnitude (0.25 to 0.6 on Earth surface): ");
   Serial.print(sqrt(scaled.XAxis * scaled.XAxis + scaled.YAxis * scaled.YAxis + scaled.ZAxis * scaled.ZAxis));
   Serial.print(" Heading: ");
   Serial.print(headingDegrees);
   Serial.print(" Bearing: ");
   Serial.print(bearingDegrees(headingDegrees));
   Serial.println(" (Degrees)");
}

  // Cacluate bearing from heading.
  // bearing 0 = Y pointing North, 90 = Y pointing E, 180 = Y pointing S, 270 = Y pointing W
  float bearingDegrees(float headingDegrees) {
     
     float bearing = 450 - headingDegrees;
     if (bearing >= 360)
     {
      bearing -= 360;
     }
     return bearing;
  }





9. 결과


QMC5883L 이라고 안 이상, 그 뒤는 문제 없이 구동까지 확인할 수 있었습니다.






FIN


여기까지 걸린 시간은 대략 이틀.

구매 사이트에 처음부터 QMC5883L 이라고 표기했으면 이렇게까지 고민하지 않았을 터인데.

역시 알아서 쓰라는 AliExpress 와 대륙의 기상이 느껴집니다.


인터넷을 보면 QMC5883L 에 대해서는 꽤나 여러가지 시도가 있습니다.

사실 접근 address 및 쓰고 읽는 부분만 다를 뿐, 구동 방식은 같다고 합니다.


* QMC5883L Electronic Compass

http://wiki.epalsite.com/index.php?title=QMC5883L_Electronic_Compass



Mecha 라는 ID 를 사용하시는 분이 만든 library 도 있습니다.


* Arduino lib for QMC5883

https://github.com/mechasolution/Mecha_QMC5883L


QMC5883L 임을 안 이상, 다음에는 좀더 철저하게 사용해 보도록 하겠습니다.

And

Hardware | MAX4466 마이크 앰프 breakout board 사용해 보기

|

1. 시작


아두이노와 친해지면서 다음 센서는 뭐할까 하다가,

스피커처럼 생겼지만 사실은 마이크인 "Electret Microphone Amplifier" 를 알게 되었습니다.



특이하게 Electret 이라는 단어가 눈에 띕니다.

의미는 Electricity 와 Magnet 의 합성어라고 하네요.


* 일렉트릿

http://100.daum.net/encyclopedia/view/b18a1451a


전계를 가했을 때 생긴유전 분극이 전계를 없앤 다음까지 잔류하는 물질로 만든 하전체.

자기에서의 영구 자석에 대응하는 것이다. 폴리프로필렌이나 마일러 등의 플라스틱으로 만들며, 소형 마이크로폰 등에 이용된다.


소형 마이크로폰에 사용된다고 하네요. 외관 모양 그대로의 기능을 가지고 있습니다.

Wikipedia 에서 설명은 다음에서 하고 있습니다.


* Electret

https://en.wikipedia.org/wiki/Electret





2. 구매


용돈 생활인의 안식처, 알리에서 찾아 봅니다.

adafruit 에서는 6.95 USD 입니다만, 알리는 1.66 USD 입니다.


* Electret Microphone Amplifier MAX4466 Adjustable Gain Breakout Board For Arduino MAX4466 Module

https://ko.aliexpress.com/item/Electret-Microphone-Amplifier-MAX4466-Adjustable-Gain-Breakout-Board-For-Arduino/32786459312.html



제품 설명에서는 홈페이지에서는 스펙에 대해 잘 설명되어 있습니다.


- 20 ~ 20KHz

- DC 2.4 ~ 5V


Add an ear to your project with this well-designed electret microphone amplifier. This fully assembled and tested board comes with a 20-20KHz electret microphone soldered on. This breakout is best used for projects such as voice changers, audio recordingmpling,

and audio-reactive projects that use FFT.

On the back, we include a small trimmer pot to adjust the gain.

Using it is simple: connect GND to ground, VCC to 2.4-5VDC. The output pin is not designed to drive speakers or anything but the smallest in-ear headphones you'll need an audio amplifier (such as our 3.7W stereo amp) if you want to connect the amp directly to speakers. [Specification] For the amplification, we use the Maxim MAX4466, an op-amp specifically designed for this delicate task! The amplifier has excellent power supply noise rejection, so this amplifier sounds really good and isn't nearly as noisy or scratchy as other mic amp breakouts we've tried! You can set the gain from 25x to 125x. That's down to be about 200mVpp (for normal speaking volume about 6" away) which is good for attaching to something that expects 'line level' input without clipping, or up to about 1Vpp, ideal for reading from a microcontroller ADC. The output is rail-to-rail so if the sounds gets loud, the output can go up to 5Vpp! For the best performance, use the "quietest" supply available (on an For Arduino, this would be the 3.3V supply). The audio waveform will come out of the OUT pin. The output will have a DC bias of VCC/2 so when its perfectly quiet, the voltage will be a steady VCC/2 volts (it is DC coupled).


If the audio equipment you're using requires AC coupled audio,

place a 100uF capacitor between the output pin and the input of your device.

If you're connecting to an audio amplifier that has differential inputs or includes decoupling capacitors,

the 100uF cap is not required.





3. adafruit 과의 비교


원본은 adafruit 의 MAX4466 breakout 로 보입니다.

이래는 비교 입니다.


* Electret Microphone Amplifier - MAX4466 with Adjustable Gain

https://learn.adafruit.com/adafruit-microphone-amplifier-breakout/assembly-and-wiring




마이크 부분을 제외하고 뒷면을 보면, 숫자 표기는 달라도 저항의 값은 모두 같은 것을 사용한 것으로 보입니다.



앞부분은 평범합니다.



처음 도착시 동봉되어 있던, male pin 이 어디로 가버려 

따로 구매한 핀 중에서 이쁜 색으로 나온 노란색 male pin 을 사용합니다.


Male pin 구매기는 아래를 참고하세요.


* Hardware | 2.54mm pin header 구매하기

http://chocoball.tistory.com/entry/Hardware-254mm-pin-header






4. Layout


회로 구성은 다음과 같습니다.


   MAX4466  | Arduino Nano
---------------------------
    VCC     |     3.3V
    GND     |     GND
    OUT     |     A0
---------------------------


  SSD1306   | Arduino Nano
---------------------------
    GND     |     GND
    VDD     |     3.3V
    SCK     |     A5
    SDA     |     A4
---------------------------


VU meter 를 같이 이용하기 위해 SSD1306 도 같이 연결하였습니다.






5. Sketch


아래 보이는 sketch 는 adafruit 가 제공하는 기본 소스 입니다.


/****************************************
Example Sound Level Sketch for the 
Adafruit Microphone Amplifier
****************************************/

const int sampleWindow = 50; // Sample window width in mS (50 mS = 20Hz)
unsigned int sample;

void setup() 
{
   Serial.begin(9600);
}


void loop() 
{
   unsigned long startMillis= millis();  // Start of sample window
   unsigned int peakToPeak = 0;   // peak-to-peak level

   unsigned int signalMax = 0;
   unsigned int signalMin = 1024;

   // collect data for 50 mS
   while (millis() - startMillis < sampleWindow)
   {
      sample = analogRead(0);
      if (sample < 1024)  // toss out spurious readings
      {
         if (sample > signalMax)
         {
            signalMax = sample;  // save just the max levels
         }
         else if (sample < signalMin)
         {
            signalMin = sample;  // save just the min levels
         }
      }
   }
   peakToPeak = signalMax - signalMin;  // max - min = peak-peak amplitude
   double volts = (peakToPeak * 5.0) / 1024;  // convert to volts

   Serial.println(volts);
}


이 소스를 이용하면, 입력된 voltage 값을 Serial Monitor 를 통해 확인할 수 있습니다.



그래프로 그려보면 다음과 같습니다.



그래프가 튀는 부분은 "아~" 라고 소리를 질러 변화를 준 부분입니다.




6. VU meter 와 연동하기


 아래 링크는 SSD1306 OLED 를 이용한 VU meter 연동 글입니다.


* Hardware | SSD1306 monochrome OLED 를 가지고 VU meter 를 만들어보자

http://chocoball.tistory.com/entry/Hardware-VU-meter-using-SSD1306-monochrome-OLED


Pin 연결은 동일하기 때문에 그대로 사용했습니다.


/*  OLEDMeter was written to utilize any 128x64 display. I have only seen marginal attempts to
 *  animate meters and I hope this one will set a standard. Please feel free to modify and share
 *  this code for any 128x64 LCD or OLED. OLEDMeter sketch was written for use with I2C SH1106.
 *  This code must be modified to work with other display devices.
 * 
 *  Working portion of code was taken from Adafruit Example Sound Level Sketch for the
 *  Adafruit Microphone Amplifier
 *  https://learn.adafruit.com/adafruit-microphone-amplifier-breakout/measuring-sound-levels
 * 
 *  Remaining code was written by Greg Stievenart with no claim to or any images or information
 *  provided in this code. Freely published May 26, 2016.
 * 
 *  Software to convert background mask to 128x64 at: http://www.ablab.in/image2glcd-software/
 * 
 *  IMPORTANT: Sound source must be grounded to the Arduino or other MCU's to work. Usually the
 *  base sleeve contact on TRS or TRRS connector is the ground.
 */
 
#include "Wire.h"						// requried to run I2C SH1106
#include "SPI.h"						// requried to run I2C SH1106
#include "Adafruit_GFX.h"				// https://github.com/adafruit/Adafruit-GFX-Library
#include "Adafruit_SSD1306.h"			// https://github.com/wonho-maker/Adafruit_SH1106
 
#define OLED_RESET 4					// reset required for SH1106
 
Adafruit_SSD1306 display(OLED_RESET);	// reset required for SH1106
 
int analogInput = A0;					// analog input for outside audio source
int hMeter = 65;						// horizontal center for needle animation
int vMeter = 85;						// vertical center for needle animation (outside of dislay limits)
int rMeter = 80;						// length of needle animation or arch of needle travel
 
const int sampleWindow = 50;			// sample window width in mS (50 mS = 20Hz)
unsigned int sample;
 
// VU meter background mask image
static const unsigned char PROGMEM VUMeter[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x03, 0x00, 0x60, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x09, 0x04, 0x80, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x01, 0x98, 0x08, 0x06, 0x03, 0x80, 0x21, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x09, 0x00, 0x80, 0x21, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0xA4, 0x10, 0x06, 0x03, 0x00, 0x20, 0xC0, 0x00, 0x80, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x71, 0x80, 0xA4, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x0A, 0x40, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3C, 0x00, 0x00,
  0x00, 0x00, 0x3A, 0x40, 0x00, 0x00, 0x02, 0x01, 0x00, 0x40, 0x80, 0x07, 0x00, 0x20, 0x00, 0x00,
  0x00, 0x00, 0x42, 0x40, 0x00, 0x08, 0x02, 0x01, 0x08, 0x40, 0x80, 0x00, 0x00, 0x38, 0x00, 0x00,
  0x00, 0x00, 0x79, 0x80, 0x04, 0x08, 0x02, 0x01, 0x08, 0x81, 0x10, 0x00, 0x00, 0x04, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0x02, 0x01, 0x08, 0x81, 0x11, 0x04, 0x00, 0x38, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x02, 0x01, 0x08, 0x81, 0x21, 0x04, 0x00, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x00, 0x84, 0x02, 0x04, 0x0F, 0xFF, 0xFF, 0xC3, 0xE2, 0x04, 0x00, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x00, 0xC2, 0x01, 0x07, 0xF0, 0x00, 0x00, 0x3B, 0xFE, 0x08, 0x40, 0x40, 0x08, 0x00,
  0x00, 0xFE, 0x00, 0x62, 0x01, 0xF8, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xE8, 0x40, 0x80, 0x7F, 0x00,
  0x00, 0x00, 0x00, 0x21, 0x1E, 0x00, 0x04, 0x00, 0x80, 0x00, 0x7F, 0xFE, 0x80, 0x80, 0x08, 0x00,
  0x00, 0x00, 0x03, 0x31, 0xE0, 0x00, 0x04, 0x00, 0x80, 0x04, 0x01, 0xFF, 0xC1, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x07, 0x1E, 0x00, 0x40, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1F, 0xFA, 0x00, 0x08, 0x00,
  0x00, 0x00, 0x07, 0xF0, 0x00, 0x40, 0x3B, 0x07, 0x60, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x34, 0x81, 0x90, 0xCC, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00,
  0x00, 0x00, 0x0C, 0x00, 0x03, 0x30, 0x0C, 0x82, 0x90, 0x53, 0x20, 0x00, 0x07, 0xF8, 0x00, 0x00,
  0x00, 0x00, 0x70, 0x40, 0x00, 0xC8, 0x3B, 0x02, 0x60, 0x53, 0x20, 0x00, 0x00, 0xFE, 0x00, 0x00,
  0x00, 0x01, 0x80, 0x20, 0x01, 0xC8, 0x00, 0x00, 0x00, 0x4C, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00,
  0x00, 0x06, 0x00, 0x00, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00,
  0x00, 0x08, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00,
  0x00, 0x30, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00,
  0x00, 0x00, 0x40, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
  0x00, 0x00, 0xA0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x02, 0x02, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x03, 0x06, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x8C, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x30, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x70, 0x19, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x20, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
 
void setup() {
	pinMode(analogInput, INPUT);					// analog input for outside audio source
	display.begin(SSD1306_SWITCHCAPVCC, 0x3C);		// needed for SH1106 display
	display.clearDisplay();							// clears display from any library info displayed
	Serial.begin(9600);
}
 
void loop() {
 
/***********************************************************************
 Start of code taken from Adafruit Example Sound Level Sketch for the
 Adafruit Microphone Amplifier
************************************************************************/
	
	unsigned long startMillis= millis();	// Start of sample window
	unsigned int peakToPeak = 0;			// peak-to-peak level
	
	unsigned int signalMax = 0;
	unsigned int signalMin = 1024;
	
	// collect data for 50 mS
	while (millis() - startMillis < sampleWindow) {
		sample = analogRead(0);
		if (sample < 1024) {			// toss out spurious readings
			if (sample > signalMax) {
				signalMax = sample;		// save just the max levels
			} else if (sample < signalMin) {
				signalMin = sample;		// save just the min levels
			}
		}
	}
	
	peakToPeak = signalMax - signalMin;	// max - min = peak-peak amplitude
	float MeterValue = peakToPeak * 330 / 1024;		// convert volts to arrow information
	double volts = (peakToPeak * 5.0) / 1024;		// convert to volts

/****************************************************
 End of code taken from Adafruit Sound Level Sketch
*****************************************************/
	
	MeterValue = MeterValue - 34;								// shifts needle to zero position
	display.clearDisplay();										// refresh display for next step
	display.drawBitmap(0, 0, VUMeter, 128, 64, WHITE);			// draws background
	int a1 = (hMeter + (sin(MeterValue / 57.296) * rMeter));	// meter needle horizontal coordinate
	int a2 = (vMeter - (cos(MeterValue / 57.296) * rMeter));	// meter needle vertical coordinate
	display.drawLine(a1, a2, hMeter, vMeter, WHITE);			// draws needle
	display.display();
	Serial.println(volts);
}


연결되어 VU meter 가 잘 표시되네요.



구동 동영상 입니다.






7. VCC 와 GND


처음에 VU meter 의 바늘이 널띄면서 도저희 측정할 수 있는 상태가 아니였습니다.



Pin 들의 접점이 문제인가 여러번 빼고 꼽고 했지만 개선이 이루어지지 않았습니다.

최종적으로 생각한 것은 예민한 센서이다 보니, 잡음이 원인이 아닌가 하는 것이였습니다.


위의 사진처럼 SSD1306 과 동일하게 사용하는 공통 VCC/GND 에 연결한 것을,

아래처럼 각각 arduino 의 VCC/GND 에 연결하니 해결되었습니다.



예민한 센서류는 공통 VCC/GND 에 연결하면 안되는 거군요.

이렇게 하나 배워 봅니다.




FIN


소형 마이크에는 Electret 소자가 사용된다 합니다.

Arduino 를 위한 소리 감지용 breakout 보드도 나와 줘서 필요시 잘 사용할 것 같습니다.


And
prev | 1 | ··· | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ··· | 11 | next