반응형

아두이노와 지문 인식 센서를 사용해 보자.

 

AS608 칩을 사용한 지문 인식 센서다.

 

핀맵은 왼쪽부터 아래와 같다. (D- D+는 USB 연결 시 사용한다)

D- D+ UA TCH GND RX TX VCC(3.3V)

제품마다 다를 수 있다.

 

아래와 같이 연결한다.

VCC - 3.3V

TX - D2

RX - D3

GND - GND

 

Arduino IDE - Library Manager - fingerprint를 검색하고 Adafruit Fingerprint Sensor Library를 설치한다.

 

 

File - Examples - Adafruit Fingerprint Sensor Library - enroll 을 선택한다.

 

컴파일하고 아두이노에 업로드한다.

 

시리얼 모니터를 확인하면 지문인식 센서가 인식되고 ID 입력을 기다린다.

 

127개의 지문을 인식할 수 있다. 처음 이므로 1을 입력하면 첫 번째 지문 등록 대기상태로 들어간다.

 

 

손가락을 대면 지문이 인식되고 뗐다 다시 대면 첫 번째 지문이 등록 된다. 2를 입력하고 동일한 방법으로 두 번째 지문을 등록한다.

 

이번엔 fingerprint 예제를 불러온다.

 

컴파일하고 업로드한다.

 

지문인식 센서가 인식되고 대기상태에 들어간다. 센서에 2개의 지문(템플릿)이 있다고 표시된다.

 

 

첫 번째 등록한 손가락을 대면 ID 1과 매치된다.

 

두 번째 손가락을 대면 ID 2와 매칭된다.

 

반응형
Posted by J-sean
:
반응형

이북(eBook)에 쓰이는 전자잉크를 아두이노와 함께 사용해 보자.

 

MH-ET LIVE 2.13 Inch E-paper Module

 

3.3V와 5.0V 모두 사용 가능하다. 딥스위치는 L(4-Line)로 옮겨준다.

전자잉크와 아두이노는 아래와 같이 연결한다.

 

E-Paper Arduino
Busy D7
Reset D9
D/C D8
CS D10
SCLK D13
SDI D11
GND GND
VCC 5V

 

Arduino IDE를 실행한다.

 

 

Library Manager에서 e-paper를 검색하고 GxEPD2를 설치한다.

 

필요한 라이브러리 모두 함께 설치한다.

 

File - Examples - GxEPD2 - GxEPD2_HelloWorld를 선택한다.

 

HelloWorld 예제가 열린다.

 

 

GxEPD2_display_selection_new_style.h 파일을 선택하고 #define GxEPD2_DISPLAY_CLASS GxEPD2_3C의 주석을 해제한다

그리고 기본적으로 #define GxEPD2_DISPLAY_CLASS GxEPD2_BW의 주석이 해제되어 있다. 주석 처리하자.

 

#define GxEPD2_DRIVER_CLASS GxEPD2_213_Z98c의 주석을 해제한다

 

컴파일하고 업로드한다.

 

화면이 몇 번 깜빡이고 Hello World!가 출력된다.

 

 

전원이 공급되지 않아도 출력상태가 유지된다.

 

반응형
Posted by J-sean
:
반응형

L293D는 다이오드가 내장된 DC모터 드라이버다.


L293D DC Motor Driver


L293D Pin Map

Enable 1, 2와 Enable 3, 4는 PWM(0~255)으로 모터 속도를 제어한다.

모터가 높은 전압을 사용한다면 Vcc 2에 외부 전원을(4.5~36V) 연결한다. (Vcc 1은 내부 로직용 전압이다)


Peak output current(nonrepetitive, t ≤ 100 µs): 1.2A

Continuous output current: 600mA

l293d.pdf


드라이버 내부에는 모터에서 발생하는 역기전력으로 인한 MCU 손상 방지용 다이오드가 내장되어 있다.

GND(4, 5, 12, 13)는 모두 연결되어 있어서 하나만 외부 GND에 연결하면 된다.



위 다이어그램과 같이 연결한다.


L293D - Arduino

Enable 1, 2 - D8

Input 1 - D9

Output 1 - Motor +

GND - GND

Output 2 - Motor -

Input 2 - D10

Vcc 2 - 5V

Vcc 1 - 5V




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#define EN1 8
#define IN1 9
#define IN2 10
 
void setup() {
  pinMode(EN1, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
}
 
void loop() {
  digitalWrite(EN1, HIGH);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  delay(1000);
 
  digitalWrite(EN1, LOW);
  delay(1000);
 
  digitalWrite(EN1, HIGH);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  delay(1000);
 
  digitalWrite(EN1, LOW);
  delay(1000);
}


위 코드를 컴파일하고 아두이노에 업로드한다. 'CW 회전 - 1초 대기 - CCW 회전 - 1초 대기'가 반복된다.


반응형
Posted by J-sean
:
반응형

RFID-RC522 모듈과 아두이노를 이용해 RFID카드를 읽고 쓸 수 있다.


RFID-RC522


RFID Cards


위 다이어그램과 같이 연결한다.


ARDUINO - RFID-RC522

3.3V - 3.3V

D9 - RST

GND - GND

N/A - IRQ

D12 - MISO

D11 - MOSI

D13 - SCK

D10 - SDA



Library Manager에서 MFRC522을 검색하고 설치한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <SPI.h>
#include <MFRC522.h>
 
#define SS_PIN 10
#define RST_PIN 9
 
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
 
// Array for new NUID 
byte nuidPICC[4= {0};
 
void setup() {
  Serial.begin(9600);
  SPI.begin(); // Init SPI bus
  rfid.PCD_Init(); // Init MFRC522
}
 
void loop() {
  // Reset the loop if no new card present on the sensor/reader. This saves the entire process when idle.
  if (!rfid.PICC_IsNewCardPresent()) {
    delay(500);
    
    return;
  }
 
  // Verify if the NUID has been read.
  if (!rfid.PICC_ReadCardSerial()) {
    delay(500);
    
    return;
  }
 
  if (rfid.uid.uidByte[0!= nuidPICC[0||
    rfid.uid.uidByte[1!= nuidPICC[1||
    rfid.uid.uidByte[2!= nuidPICC[2||
    rfid.uid.uidByte[3!= nuidPICC[3] ) {
    Serial.println("A new card has been detected.");
 
    // Store NUID into nuidPICC array
    for (byte i = 0; i < 4; i++) {
      nuidPICC[i] = rfid.uid.uidByte[i];
    }
  } else {
    delay(500);
 
    return;
  }
 
  Serial.print("PICC type: ");
  MFRC522::PICC_Type piccType = rfid.PICC_GetType(rfid.uid.sak);
  Serial.println(rfid.PICC_GetTypeName(piccType));
 
  // Check if classic MIFARE type
  if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
    piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
    piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
    Serial.println("Your tag is not MIFARE Classic type.");
    
    return;
  }
 
  Serial.print("Card UID: ");
  for (byte i = 0; i < 4; i++) {
    Serial.print(rfid.uid.uidByte[i]);
    if (i < 3)
      Serial.print("-");
  }
  Serial.println();
}


RFID 카드 읽기 소스를 컴파일 하고 아두이노에 업로드한다. 


RFID-RC522 모듈에 카드를 가까이 대면 카드 타입과 ID가 표시된다.


반응형
Posted by J-sean
:
반응형

아두이노로 간단히 RF433MHz 통신이 가능하다.


왼쪽이 리시버, 오른쪽이 트랜스미터다.


송신기와 수신기를 아두이노에 연결해 준다. RadioHead Packet Radio library를 다운받고 아래와 같이 아두이노 라이브러리에 복사한다.


특별한 설치 과정은 없다. 그냥 복사한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// ask_transmitter.pde
// -*- mode: C++ -*-
// Simple example of how to use RadioHead to transmit messages
// with a simple ASK transmitter in a very simple way.
// Implements a simplex (one-way) transmitter with an TX-C1 module
// Tested on Arduino Mega, Duemilanova, Uno, Due, Teensy, ESP-12
 
#include <RH_ASK.h>
#ifdef RH_HAVE_HARDWARE_SPI
#include <SPI.h> // Not actually used but needed to compile
#endif
 
RH_ASK driver;
// RH_ASK driver(2000, 4, 5, 0); // ESP8266 or ESP32: do not use pin 11 or 2
// RH_ASK driver(2000, 3, 4, 0); // ATTiny, RX on D3 (pin 2 on attiny85) TX on D4 (pin 3 on attiny85), 
// RH_ASK driver(2000, PD14, PD13, 0); STM32F4 Discovery: see tx and rx on Orange and Red LEDS
 
void setup()
{
  #ifdef RH_HAVE_SERIAL
    Serial.begin(9600);    // Debugging only
  #endif
    if (!driver.init())
  #ifdef RH_HAVE_SERIAL
      Serial.println("init failed");
  #else
      ;
  #endif
    else
      Serial.println("init succeeded");
}
 
void loop()
{
  const char *msg = "Hello Wireless World!";
 
  driver.send((uint8_t *)msg, strlen(msg));
  driver.waitPacketSent();
  #ifdef RH_HAVE_SERIAL
      Serial.println("Message sent.");
  #endif
  
  delay(200);
}


Transmitter 소스를 컴파일하고 아두이노에 업로드한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// ask_receiver.pde
// -*- mode: C++ -*-
// Simple example of how to use RadioHead to receive messages
// with a simple ASK transmitter in a very simple way.
// Implements a simplex (one-way) receiver with an Rx-B1 module
// Tested on Arduino Mega, Duemilanova, Uno, Due, Teensy, ESP-12
 
#include <RH_ASK.h>
#ifdef RH_HAVE_HARDWARE_SPI
#include <SPI.h> // Not actually used but needed to compile
#endif
 
RH_ASK driver;
// RH_ASK driver(2000, 4, 5, 0); // ESP8266 or ESP32: do not use pin 11 or 2
// RH_ASK driver(2000, 3, 4, 0); // ATTiny, RX on D3 (pin 2 on attiny85) TX on D4 (pin 3 on attiny85), 
// RH_ASK driver(2000, PD14, PD13, 0); STM32F4 Discovery: see tx and rx on Orange and Red LEDS
 
void setup()
{
  #ifdef RH_HAVE_SERIAL
    Serial.begin(9600);    // Debugging only
  #endif
    if (!driver.init())
      
  #ifdef RH_HAVE_SERIAL
      Serial.println("init failed");
  #else
      ;
  #endif
    else
      Serial.println("init succeeded");
}
 
void loop()
{
  uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
  memset(buf, 0, RH_ASK_MAX_MESSAGE_LEN);
  uint8_t buflen = sizeof(buf);
 
  if (driver.recv(buf, &buflen)) // Non-blocking
  {
    // Message with a good checksum received, dump it.
    driver.printBuffer("Got:", buf, buflen);
    #ifdef RH_HAVE_SERIAL
      String message = (char*)buf;
      Serial.print("Message: ");
      Serial.println(message);
    #endif
  }
 
  delay(200);
}


Receiver 소스를 컴파일하고 아두이노에 업로드한다.


송신기에서는 계속 메세지를 보낸다.


송신기에서 보낸 메세지를 수신기에서 받는다. printBuffer()로 출력한 메세지는 각 문자의 아스키 코드값이다.


void RHGenericDriver::printBuffer(const char* prompt, const uint8_t* buf, uint8_t len)

Parameters

[in] prompt string to preface the print

[in] buf Location of the buffer to print

[in] len Length of the buffer in octets.


Prints a data buffer in HEX. For diagnostic use


※ 참고: RH_ASK Class Reference


반응형
Posted by J-sean
:
반응형

MX1508 모터 드라이버로 2개의 DC모터나 1개의 스텝 모터를 컨트롤 할 수 있다.

- Supply voltage: 2~10V.

- Signal input voltage 1.8~7V.


MX1508 모터 드라이버


MX1508 드라이버 다이어그램은 아니지만 위와 같은 방식으로 연결한다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const int IN1 = 5;
const int IN2 = 6;
const int IN3 = 9;
const int IN4 = 10;
 
void setup() {
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
}
 
void loop() {
  CWRotation(100);
  delay(1000);
 
  CCWRotation(200);
  delay(1000);
}
 
void CWRotation(int speed)
{
  analogWrite(IN1, speed);
  digitalWrite(IN2, LOW);
  analogWrite(IN3, speed);
  digitalWrite(IN4, LOW);
}
 
void CCWRotation(int speed)
{
  digitalWrite(IN1, LOW);
  analogWrite(IN2,speed );
  digitalWrite(IN3, LOW);
  analogWrite(IN4, speed);
}


소스를 컴파일 하고 아두이노에 업로드한다. 모터가 다른 속도로 정회전, 역회전을 반복한다.


반응형
Posted by J-sean
:
반응형

Windows API(CreateFile)을 이용해 간단히 아두이노와 시리얼 통신을 할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
char state;
 
void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  Serial.println("Arduino ready.");
}
 
void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available())
  {
    state = Serial.read();
    while (Serial.available())
    {
      Serial.read();  // 첫 번째 문자만 입력받고 나머지는 버린다.
    }
    
    if (state == '0')
    {
      digitalWrite(LED_BUILTIN, LOW);
      Serial.println("LED OFF");
    } else
    {
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.println("LED ON");
    }
  }
 
  delay(100);
}


위 소스를 컴파일 하고 아두이노에 업로드 한다. 시리얼 모니터를 통해서도 Builtin LED를 제어할 수 있다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#ifndef SERIALCLASS_H_INCLUDED
#define SERIALCLASS_H_INCLUDED
 
#define ARDUINO_WAIT_TIME 2000
 
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
 
class Serial
{
private:
    //Serial comm handler
    HANDLE hSerial;
    //Connection status
    bool connected;
    //Get various information about the connection
    COMSTAT status;
    //Keep track of last error
    DWORD errors;
 
public:
    //Initialize Serial communication with the given COM port
    Serial(const char* portName);
    //Close the connection
    ~Serial();
    //Read data in a buffer, if nbChar is greater than the
    //maximum number of bytes available, it will return only the
    //bytes available. The function return -1 when nothing could
    //be read, the number of bytes actually read.
    int ReadData(char* buffer, unsigned int nbChar);
    //Writes data from a buffer through the Serial connection
    //return true on success.
    bool WriteData(const char* buffer, unsigned int nbChar);
    //Check if we are actually connected
    bool IsConnected();
 
 
};
 
#endif // SERIALCLASS_H_INCLUDED


Serial class header.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "SerialHeader.h"
 
Serial::Serial(const char* portName)
{
    //We're not yet connected
    this->connected = false;
 
    //Try to connect to the given port throuh CreateFile
    //CreateFile may need to be replaced with CreateFileA or...
    //Project - XXX Properties - Configuration Properties - Advanced - Character Set - Use Multi-Byte Character Set
    this->hSerial = CreateFileA(portName,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
 
    //Check if the connection was successfull
    if (this->hSerial == INVALID_HANDLE_VALUE)
    {
        //If not success full display an Error
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
 
            //Print Error if neccessary
            printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
 
        }
        else
        {
            printf("ERROR!!!");
        }
    }
    else
    {
        //If connected we try to set the comm parameters
        DCB dcbSerialParams = { 0 };
 
        //Try to get the current
        if (!GetCommState(this->hSerial, &dcbSerialParams))
        {
            //If impossible, show an error
            printf("failed to get current serial parameters!");
        }
        else
        {
            //Define serial connection parameters for the arduino board
            dcbSerialParams.BaudRate = CBR_9600;
            dcbSerialParams.ByteSize = 8;
            dcbSerialParams.StopBits = ONESTOPBIT;
            dcbSerialParams.Parity = NOPARITY;
            //Setting the DTR to Control_Enable ensures that the Arduino is properly
            //reset upon establishing a connection
            dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
 
            //Set the parameters and check for their proper application
            if (!SetCommState(hSerial, &dcbSerialParams))
            {
                printf("ALERT: Could not set Serial Port parameters");
            }
            else
            {
                //If everything went fine we're connected
                this->connected = true;
                //Flush any remaining characters in the buffers 
                PurgeComm(this->hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
                //We wait 2s as the arduino board will be reseting
                Sleep(ARDUINO_WAIT_TIME);
            }
        }
    }
 
}
 
Serial::~Serial()
{
    //Check if we are connected before trying to disconnect
    if (this->connected)
    {
        //We're no longer connected
        this->connected = false;
        //Close the serial handler
        CloseHandle(this->hSerial);
    }
}
 
int Serial::ReadData(char* buffer, unsigned int nbChar)
{
    //Number of bytes we'll have read
    DWORD bytesRead;
    //Number of bytes we'll really ask to read
    unsigned int toRead;
 
    //Use the ClearCommError function to get status info on the Serial port
    ClearCommError(this->hSerial, &this->errors, &this->status);
 
    //Check if there is something to read
    if (this->status.cbInQue > 0)
    {
        //If there is we check if there is enough data to read the required number
        //of characters, if not we'll read only the available characters to prevent
        //locking of the application.
        if (this->status.cbInQue > nbChar)
        {
            toRead = nbChar;
        }
        else
        {
            toRead = this->status.cbInQue;
        }
 
        //Try to read the require number of chars, and return the number of read bytes on success
        memset(buffer, 0, nbChar);
        if (ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL))
        {
            return bytesRead;
        }
 
    }
 
    //If nothing has been read, or that an error was detected return 0
    return 0;
 
}
 
 
bool Serial::WriteData(const char* buffer, unsigned int nbChar)
{
    DWORD bytesSend;
 
    //Try to write the buffer on the Serial port
    if (!WriteFile(this->hSerial, (void*)buffer, nbChar, &bytesSend, 0))
    {
        //In case it don't work get comm error and return false
        ClearCommError(this->hSerial, &this->errors, &this->status);
 
        return false;
    }
    else
        return true;
}
 
bool Serial::IsConnected()
{
    //Simply return the connection status
    return this->connected;
}


Serial class source.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include "SerialHeader.h"
 
using namespace std;
 
int main()
{
    Serial* ser = new Serial("\\\\.\\COM3");
    char message[255];    
 
    if (ser->IsConnected()) {
        cout << "Serial Communication Connected." << endl;
        // memset(message, 0, sizeof(message));
        // Serial::ReadData() 내부에서 memset이 실행된다.
        ser->ReadData(message, sizeof(message));
        cout << "Message from Arduino: " << message << endl;
    } else {
        cout << "Device can not be found or can not be configured." << endl;
 
        return 0;
    }
    
    while (true) {
        cout << "0: Off, 1 : On, q(Q) : Quit" << endl << "Choose : ";        
        cin >> message;
 
        if (!strcmp(message, "q"|| !strcmp(message, "Q")) {
            break;
        } else if (!strcmp(message, "0")) {            
            ser->WriteData("0"1);
            Sleep(200); // 아두이노와의 시리얼 통신을 위한 대기 시간.            
            ser->ReadData(message, sizeof(message));
            cout << "Message from Arduino: " << message << endl;
        } else {
            ser->WriteData("1"1);
            Sleep(200); // 아두이노와의 시리얼 통신을 위한 대기 시간.            
            ser->ReadData(message, sizeof(message));
            cout << "Message from Arduino: " << message << endl;
        }
    }
 
    return 0;
}


Windows에서 위 소스를 실행하면 연결된 아두이노의 Builtin LED를 제어할 수 있다.


※ 참고: Arduino and C++ (for Windows)



반응형
Posted by J-sean
:
반응형

Note(Banknote) Acceptor, Bill Acceptor 등으로 불리는 지폐 인식기는 보통 자판기, 동전 교환기, 오락실등에서 사용된다. 여러가가지 모델이 있지만 작동 원리는 대부분 비슷하다.

 

SAMDUCKSA의 SN401PK라는 모델의 지폐인식기다.

 

오른쪽 측면에 8개의 dip switch가 있다. 2번(천원당 pulse 2회), 7번(pulse length = 50ms) switch가 on 되어 있다.

 

왼쪽 측면에는 입력(Vcc, GND), 출력(Pulse)등을 위한 10개의 터미널(Molex Microblade Connector)이 있다. 보통 2, 8(9), 10번 터미널을 사용한다.

 

위에도 6개의 터미널은 있는데 설명이 없다. 제조사에서 사용하는 터미널이 아닐까 싶다.

 

 

 

 

지폐 투입구. 지폐를 밀어 넣으면 자동으로 인식 된다.

 

지폐 투입구를 열어보면 LED, 센서, 타이밍 밸트, 롤러등이 있다.

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const int NOTEPIN = 4;
unsigned long duration;
int count = 0;
 
void setup() {
  pinMode(NOTEPIN , INPUT_PULLUP);
  // 플로팅 방지 풀업 저항.
  Serial.begin(9600);
  Serial.println("Counter Ready");
}
 
void loop() {
  duration = pulseIn(NOTEPIN, LOW, 200000); // microsecond  
  // NOTEPIN은 풀업 저항을 사용하므로 LOW 펄스를 읽어야한다.
  // 0.2초 대기. 0.1초는 너무 짧아 Pulse signal을 제대로 받지 못한다.
  // 빠른 지폐인식을 위해 최소한의 대기시간을 지정.
  
  //Serial.println(duration); // 약 50ms의 펄스가 발생한다.
  
  // Condition: Pulse = 50 ms(millisecond), 1 time/1,000 won
  // 지폐 인식기의 Pulse 신뢰도가 100%가 아니면 1,000원당 1회의 Pulse로 세팅시
  // 1,000원짜리는 인식 하지 못하거나 다른 지폐도 잘못 인식하는 경우가 발생한다.
  // 그런 경우 1,000원당 2회 이상의 Pulse로 세팅하고 코드를 적절히 수정하면 오류에
  // 대응할 수 있다. 하지만 지폐 인식 속도는 느려진다.
  if (duration > 40000// 40 millisecond = 40000 microsecond
                        // SN401PK는 약50ms의 시그널을 발생한다.
  {
    count++;
  } else if (count > 0 && duration < 10000) {
    Serial.print("Signal count: ");
    Serial.println(count);
    
    if (count == 1) {
      Serial.println("1천원");
    } else if (count == 5) {
      Serial.println("5천원");
    } else if (count == 10) {
      Serial.println("1만원");
    } else {
      Serial.println("Error");
    }
    
    count = 0;
  }
 
  delay(10);
}
 

 

소스 코드

 

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
const int NOTEPIN = 4;
const int COINPIN = 2;
const int RELAYPIN = 6;
 
unsigned long duration = 0;
int billCount = 0;
int coinCount = 0;
 
int pulse=0,temp,target=0,index=0;
char sen;
unsigned long int timer;
 
 
void setup() {
    pinMode(NOTEPIN, INPUT_PULLUP);
 
    pinMode(COINPIN, INPUT_PULLUP);
    sen=digitalRead(COINPIN);
 
    pinMode(RELAYPIN, OUTPUT);
    digitalWrite(RELAYPIN, HIGH);
 
    Serial.begin(9600);
    Serial.println("Counter Ready");
}
 
void SpitCoin(int target) {
 
    index=0;
    timer=millis();
    temp=target;
    if((temp>0)&(temp<=100)){
      pulse=0;
      target=temp;
      Serial.println("Give me "+String(target)+" coins");
      digitalWrite(RELAYPIN,LOW);
    }
  while(true)
  {
    sen=(sen<<1)|digitalRead(COINPIN);
    sen&=0x03;
    if(sen==1&(digitalRead(RELAYPIN)==LOW))
    {
      timer=millis();
      pulse++;
      Serial.println("Count "+String(pulse));
      if(pulse>=target)
      {
        digitalWrite(RELAYPIN,HIGH);
        Serial.println("You get "+String(pulse)+"/"+String(target)+" coins");
        pulse=0;
        target=0;
 
        break;
      }
    }
 
    if((digitalRead(RELAYPIN)==LOW)&(millis()-timer>2000))
    {
      digitalWrite(RELAYPIN,HIGH);
      Serial.println("Out of coin. You get "+String(pulse)+"/"+String(target)+" coins");
      pulse=0;
      target=0;
 
      break;
    }
  }
}
 
void loop() {
    duration = pulseIn(NOTEPIN, LOW, 200000); // microsecond
    if (duration > 40000// microsecond (40 millisecond = 40000 microsecond)
    {
        billCount++;
    }
    else if (billCount > 0 && duration < 10000) {
        Serial.print("Signal count: ");
        Serial.println(billCount);
        
        if (billCount < 5) {            
            Serial.println("1,000 won");
            SpitCoin(2);
        }
        else if (billCount < 15) {
            Serial.println("5,000 won");
            SpitCoin(10);
        }
        else if (billCount < 25) {
            Serial.println("10,000 won");
            SpitCoin(20);
        }
        else {
            Serial.println("Error");
        }
 
        billCount = 0;
    }
 
  delay(10);
}
 

 

소스 코드

 

반응형
Posted by J-sean
: