BatteCoins 프로젝트

BattleCoins


17.12.26

요 몇 일 전부터 코인 매니저인 송대표가 찾아왔습니다. 그리고 이런저런 이야기를 나누다가 지금 진행중인 Checker를 잠깐 일시정지하고 코인 관련 아이템을 짧게 진행해보기로 했습니다.

그 중 하나가 BattleCoins 이고 안드로이드 앱만 개발기간을 2일로 잡았었는데, Wallet 연동에서 막혀서 4일, 2일이 더 추가 되었습니다.

대략적인 구조는 이렇습니다. 엑티비티 하나로 비교적 간단한 앱입니다.



조금 다른점이라면 텍스트 채팅이아닌 GIF 도장을 남기는 것과 같은 기능을 넣으려고 합니다. 그래서 Glide 라이브러리와 Pinterest 처럼 StaggeredGridLayout을 사용합니다.

Wallet 정보는 CoinmarketCap 과 Bittrex 에서 받아옵니다. 굳이 데이터 수집과 업로드를 하는 봇을 만든 이유는 API SECRET 키를 클라이언트 내부에 둘 수 없어서 필요한 정보만 업로드 해야하기 때문입니다.

우선 포스팅을 쓰는 지금 대부분은 완성을 하였습니다. 세부적인 디자인과 코드 안전성을 높여야 하겠지만요. 공부하는 겸 해서 천천히 내용들을 한번 올려보도록 하겠습니다.

ESP32 AT 커멘드 제어하기

Checker




17.12.18

ESP32 보드를 통해 Wifi, BLE 접속을 테스트 했습니다. 접속은 둘다 잘 되는데, 문제는 기존에 만들었던 코드들은 8266기반이라 대폭 수정이 들어가야 할 것 같습니다...

우선 BLE 연결을 해보는데 디바이스 이름을 바꿔주려 했는데, 기존에 BLE 모듈을 별도로 사용할 때는 SoftwareSerial을 사용해서 AT 커멘드를 제어했는데.. ESP32는 블루투스가 함께 있어서 그게 안 되네요.

초보에다 ESP32는 아직 레퍼런스도 많지 않아서 삽질을 많이 했네요 오늘.. ㅜㅜ..

일단 전체적으로 요약을 하자면

1. ESP32 플래쉬 다운로드 툴 설치
2. 플래쉬 비우기
3. ESP32 펌웨어 다운 설치 (이 때는 UART0 으로 통신합니다)
4. 테스트
( 테스트를 위해 FTDI 모듈이 필요합니다. 기본적으로 보드에 설치되어 있는 usb 단자는 UART0 하고 연결되어 있습니다.  espressif (ESP 개발사) 의 말에 따르면 ESP32 보드는 AT 커맨드를 UART1를 기본으로 한다고 하네요. GPIO16 이 RXD GPIO17 이 TXD 입니다.  그래서 여기와 연결할 때 FTDI 모듈이 필요합니다.)

참조 자료
https://pcbreflux.blogspot.kr/2017/02/esp32-playing-with-esp32-at-commands.html

문서
http://espressif.com/sites/default/files/documentation/esp32_at_instruction_set_and_examples_en.pdf


이런식으로 연결합니다. 사진상에는 잘 안 보이네요.


SSCOM3.2 를 이용해 통신 테스트 합니다. AT를 보내봤습니다. 잘 되네요.
그런데 블루투스 이름 변경이 안되네요. 왜 그런지는 잘 모르겠습니다. 나중에 알게 된 사실입니다만 제공하는 BLE 라이브러리를 통해서 이름 변경이 가능하네요... 젠장... 





샘플용 케이스 인쇄하기



Checker


17.12.17

관리자용 앱과 Firebase 연동을 한 사용자용 앱도 거의 완성을 하였습니다.
사용자용 앱은 나중에 간단하게 글을 올리겠습니다.
 
오늘은 esp32보드를 넣을 케이스를 뽑으려고 합니다. 얼마 전에 도착한 보드가 생각보다 크기가 크네요. 리포 배터리도 더 작은용량을 시켰어야 하는데, 주문 실수입니다. 배송이 워낙 오래 걸리다보니 우선 이 제품들로 제작을 하려고 합니다.







ESP32를 기반으로 한 WEMOS에서 나온 보드입니다. (주문한 제품 중 한개가 고장난 상태로 왔네요. ㅜㅜ..) 배터리 커넥터와 케이블 연결 단자도 함께 있어 이 녀석을 선택했는데, 사이즈가 너무 크네요. 게다가 배터리 커넥터에 연결을 하게 되면 선 때문에 또 사이즈가 커지는 문제가 있어 잘라버렸습니다.



이 보드를 담을 케이스 입니다. (라이노에 사진프레임으로 올렷었는데, 원본파일을 지우니 저렇게 흰색만 뜨네요) 리포 배터리 150mAh를 제일 바닥에 깔고 그 위에 보드, GY-521, RC522를 올릴 예정입니다. 벼락치기로 배운 라이노로 일단 만들었습니다. 곡면 처리를 해서 좀 만들고 싶었는데, 크기가 너무 커져버리고, 프린팅 할 때 깔끔하게 나오지 않아서 그냥 무식하게 진행하고 있습니다..



 
그리고 인쇄 인쇄 인쇄. 오차가 계속 있고 배치를 바꾸느라 아직도 수정 중입니다. 퇴근 전에 한번 더 눌러놓고 가야겠네요.
 




라이노 학습

Checker


17.12.12


ESP32 기반 보드가 도착했습니다. RFID 모듈은 아직 도착하지 않았지만 대략적으로 사이즈를 알아내서 밴드 모델링에 들어가려고 합니다. 조금이라도 그럴싸한 시제품을 위해서는 곡면처리가 필요할 것 같아서 넙스기반 라이노를 학습 중입니다.

다행히 좋은 교재를 발견하여 조금 더 연습한다면 간단한 모델링을 할 수 있지 않을까 합니다.





오늘 만든 와인 거치대입니다. 책 보고 따라해도 쉽지는 않네요 ㅎㅎ. 마지막 사진은 키샷으로 랜더링을 해 보았습니다. 그런데 CNC 데이터를 위해서 표면에 서피스 추출을 하고나서 표면에 저런 무늬가 생기네요.





추가적으로 마우스 작업도 해봤습니다. 엉망이네요 ㅋㅋ 필릿도 잘 안되고 휠 거치대의 높이도 너무 높지만, 라이노라는 녀석을 이런식으로 쓴다는 걸 대강 조금은 알게 되었습니다.
첫 작품들이라 퀄리티는 많이 떨어져도 시간 날 때 마다 차근차근 해 나가야겠습니다~


사무실 이전

2017.12.12
 

사무실에 남아 있는 멀티탭 ㅜㅜ..
우리와나, 그리니, 쿠키크랙의 기증 멀티탭이네요 ㅋㅋ.


사무실을 옮기고 간단한 외주를 하나 진행하느라 한동안 프로젝트를 진행하지 못하였습니다.
 
그나저나 벌써 12월 중순이라니 시간이 너무나 빠르네요. 항상 느끼지만 시간은 빠르고 뒤돌아보면 뭔가 해낸 것은 없는 것 같습니다. 사업 방식이 잘못되었는지도 모르겠다는 생각을 하기도 하고, 역시 뭔가를 해낸다는 것이 쉽지 않다는 생각도 합니다.
 
2년 전 이맘 때 쯤 썼었던 일기를 다시 보고, 1년 전, 6개월 전 일기를 다시 보면 참 발전이 없다는 말만 있네요. 아 그래도 발전은 있는 것 같습니다. 아직 이렇다 할 성과가 없는 것이죠.
 
군고구마 노점부터 소호무역, 쇼핑몰, 플스방 등 그리고 현재하고 있는 사업까지 나름 다양한 것들을 경험했는데, 항상 결과는 그다지 좋지 않았습니다. 도전을 하는 것 까지는 좋은데, 어려움이 닥치면 그만둬서 그런가? 문제 해결능력이 없어서 그런가? 하여튼 진행했던 사업에 모두 깊이가 없었던 것 같네요.

뭔가에 부딪혔을 때, 이 것을 그만둬야 하는지, 아니면 계속해야 하는지 어렵네요.
상황에 따라 다르고 답이 정해져 있는 것이 아니지만, 대표라면 선택을 통해 최고의 결과를 이끌어 낼 수 있어야 하죠.
 
개인적으로는 진행하는 아이템에 대한 흥미가 떨어지거나, 너무나 불투명한 미래가 그려질 때는 그만뒀었는데, 올 연말에도 느끼는 것은 내가 선택을 잘 하고 있는지 다시 생각하게 됩니다.

스스로를 다시 돌아보며 더 성장할 수 있도록 12월을 잘 마무리 해야겠습니다.

Firebase 에서 JsonObject 받기

Checker



17.12.01

Firebase DB에서 JsonObject로 다운받아 정보를 얻어보겠습니다.
DB 구조는 아래와 같이 했습니다.  LEG 를 통해 저 아래 있는 데이터들을 가져올겁니다.

라이브러리는 기존에 사용했었던 FirebaseArduino 를 사용했습니다.
깃 주소와 참조 문서는 아래 링크를 걸어두었습니다~

https://github.com/firebase/firebase-arduino
http://firebase-arduino.readthedocs.io/en/latest/#

우선 해당 라이브러리는 FirebaseObject 라는 놈으로 오브젝트를 가져옵니다.
FirebaseObject  에서 JosnVariant 를 get 할 수 있고 Variant 는 ArduinoJson 라이브러리에서  보니 JsonObject 로 변환이 가능합니다.  (ArduinoJson  라이브러리 링크는 아래 있습니다만, FirebaseArduino 라이브러리의 서드파티 라이브러리로 포함이 되어있습니다)

https://github.com/bblanchon/ArduinoJson

어쨋든 다운을 받고, 원하는 정보를 추출했습니다. DB에 없는 값은 0으로 표시되는지 확인하기 위해 테스트를 했습니다.

// 파이어베이스 JSON 오브젝트 가져오기
FirebaseObject firebaseObject = Firebase.get("LEG");

// JsonObject& 로 변환
JsonObject& jsonObject = firebaseObject.getJsonVariant
maxAcX = jsonObject["maxAcX"];          
minAcX = jsonObject["minAcX"];
maxAcY = jsonObject["maxAcY"];          
minAcY = jsonObject["minAcY"];
maxAcZ = jsonObject["maxAcZ"];          
minAcZ = jsonObject["minAcZ"];
        
maxGyX = jsonObject["maxGyX"];          
minGyX = jsonObject["minGyX"];
maxGyY = jsonObject["maxGyY"];          
minGyY = jsonObject["minGyY"];
maxGyZ = jsonObject["maxGyZ"];          
minGyZ = jsonObject["minGyZ"];

         
Serial.print("maxAcX : "); Serial.print(maxAcX);
Serial.print(" minAcX : "); Serial.println(minAcX);
Serial.print("maxAcY : "); Serial.print(maxAcY);
Serial.print(" minAcY : "); Serial.println(minAcY);
Serial.print("maxGyX : "); Serial.print(maxGyX);
Serial.print(" minGyX : "); Serial.println(minGyX);


결과입니다. maxAcY와 minAcY 는 DB에 없어서 0으로 뜨네요.


RC522 쓰기 읽기 2탄

Checker




17.11.28


요즘은 문서작업 할 것이 많아 바쁘네요. 작업에 진전이 그다지 없었습니다.
시간이 많지 않아서 RC522 쓰기를 이용해 타입을 구분해보는 작업을 하려고 합니다.


우선 모듈을 연결하고 태그를 2개 준비했습니다.


그리고 위의 태그 2개에 시리얼 모니터를 통해 쓰기를 시작합니다.




소스코드는 RC522 라이브러리에서 가져왔습니다.
코드를 대강 분석해보면 RFID TAG의 어느파트에 데이터를 쓰는지 알 수 있습니다.
readBytesUntil 은 해당 문자가 나올때까지 데이터를 읽는 함수인데, 이 녀석을 이용하여 시리얼 통신에서 보낸 ‘#’ 문자를 포함한 데이터를 버퍼에 담고, 그 데이터를 RFID TAG에 쓰는 방식입니다. 저는 RFID 타입 파트를 1번 블럭주소에 입력했고
RFID 옵션 파트를 4번에 입력했습니다.


** 코드를 보면 블럭주소 1에만 입력하는게 아니라 2에도 하는것처럼 보이는데, readBytesUntil() 에서 받는 버퍼는 34바이트 배열이고 write 할때는 16바이트 입니다. 1번 블럭에 16바이트를 쓰고 이후에 2번 블럭에 이어서 쓰는 것이라서 length를 구한 후 빈공간을 공란으로 채워서 1,2에 담는 것입니다.**



#include <SPI.h>
#include <MFRC522.h>

constexpr uint8_t RST_PIN = 9;     // Configurable, see typical pin layout above
constexpr uint8_t SS_PIN = 10;     // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance

void setup() {
 Serial.begin(9600);        // Initialize serial communications with the PC
 SPI.begin();               // Init SPI bus
 mfrc522.PCD_Init();        // Init MFRC522 card
 Serial.println(F("Write personal data on a MIFARE PICC "));
}

void loop() {

 // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
 MFRC522::MIFARE_Key key;
 for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

 // Look for new cards
 if ( ! mfrc522.PICC_IsNewCardPresent()) {
   return;
 }

 // Select one of the cards
 if ( ! mfrc522.PICC_ReadCardSerial()) {
   return;
 }

 Serial.print(F("Card UID:"));    //Dump UID
 for (byte i = 0; i < mfrc522.uid.size; i++) {
   Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
   Serial.print(mfrc522.uid.uidByte[i], HEX);
 }
 Serial.print(F(" PICC type: "));   // Dump PICC type
 MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
 Serial.println(mfrc522.PICC_GetTypeName(piccType));

 byte buffer[34];
 byte block;
 MFRC522::StatusCode status;
 byte len;

 Serial.setTimeout(20000L) ;     // wait until 20 seconds for input from serial
 // Ask personal data: Family name
 Serial.println(F("RFID 타입을 입력하세요. 마지막에 '#'을 붙이세요"));
 len = Serial.readBytesUntil('#', (char *) buffer, 30) ; // read family name from serial
 for (byte i = len; i < 30; i++) buffer[i] = ' ';     // pad with spaces

 block = 1;
 //Serial.println(F("Authenticating using key A..."));
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("PCD_Authenticate() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("PCD_Authenticate() success: "));

 // Write block
 status = mfrc522.MIFARE_Write(block, buffer, 16);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("MIFARE_Write() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("MIFARE_Write() success: "));

 block = 2;
 //Serial.println(F("Authenticating using key A..."));
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("PCD_Authenticate() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 // Write block
 status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("MIFARE_Write() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("MIFARE_Write() success: "));

 Serial.println(F("RIFD 옵션을 입력하세요. 마지막에 '#'을 붙이세요"));
 len = Serial.readBytesUntil('#', (char *) buffer, 20) ; // read first name from serial
 for (byte i = len; i < 20; i++) buffer[i] = ' ';     // pad with spaces

 block = 4;
 //Serial.println(F("Authenticating using key A..."));
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("PCD_Authenticate() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 // Write block
 status = mfrc522.MIFARE_Write(block, buffer, 16);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("MIFARE_Write() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("MIFARE_Write() success: "));

 block = 5;
 //Serial.println(F("Authenticating using key A..."));
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, block, &key, &(mfrc522.uid));
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("PCD_Authenticate() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 // Write block
 status = mfrc522.MIFARE_Write(block, &buffer[16], 16);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("MIFARE_Write() failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }
 else Serial.println(F("MIFARE_Write() success: "));


 Serial.println(" ");
 mfrc522.PICC_HaltA(); // Halt PICC
 mfrc522.PCD_StopCrypto1();  // Stop encryption on PCD

}

위의 코드를 이용하여 두개의 태그를
타입 : A / 옵션 : TAEWOO
타입 : B / 옵션 : EXERCISE
라고 입력했습니다.


아래는 읽기 라이브러리 소스코드 입니다.

#include <SPI.h>
#include <MFRC522.h>

constexpr uint8_t RST_PIN = 9;     // Configurable, see typical pin layout above
constexpr uint8_t SS_PIN = 10;     // Configurable, see typical pin layout above

MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance

//*****************************************************************************************//
void setup() {
 Serial.begin(9600);                                           // Initialize serial communications with the PC
 SPI.begin();                                                  // Init SPI bus
 mfrc522.PCD_Init();                                              // Init MFRC522 card
 Serial.println(F("Read personal data on a MIFARE PICC:"));    //shows in serial that it is ready to read
}

//*****************************************************************************************//
void loop() {

 // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
 MFRC522::MIFARE_Key key;
 for (byte i = 0; i < 6; i++) key.keyByte[i] = 0xFF;

 //some variables we need
 byte block;
 byte len;
 MFRC522::StatusCode status;

 //-------------------------------------------

 // Look for new cards
 if ( ! mfrc522.PICC_IsNewCardPresent()) {
   return;
 }

 // Select one of the cards
 if ( ! mfrc522.PICC_ReadCardSerial()) {
   return;
 }

 Serial.println(F("**Card Detected:**"));

 //-------------------------------------------

 mfrc522.PICC_DumpDetailsToSerial(&(mfrc522.uid)); //dump some details about the card

 //mfrc522.PICC_DumpToSerial(&(mfrc522.uid));      //uncomment this to see all blocks in hex


//---------------------------------------- 타입얻기
 byte buffer1[18];
 block = 1;
 len = 18;

 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 1, &key, &(mfrc522.uid)); //line 834
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("Authentication failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 status = mfrc522.MIFARE_Read(block, buffer1, &len);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("Reading failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 // 타입 프린트 하기
 Serial.print(F("타입 : "));
 for (uint8_t i = 0; i < 16; i++) {
   if (buffer1[i] != 32)  { // 32가  ' ' 공란의 바이트 값
     Serial.write(buffer1[i]);
   }
 }  
 Serial.println();

 
 //-------------------------------------------
 byte buffer2[18];
 block = 4;

 //------------------------------------------- 옵션 얻기
 status = mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(mfrc522.uid)); //line 834 of MFRC522.cpp file
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("Authentication failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 status = mfrc522.MIFARE_Read(block, buffer2, &len);
 if (status != MFRC522::STATUS_OK) {
   Serial.print(F("Reading failed: "));
   Serial.println(mfrc522.GetStatusCodeName(status));
   return;
 }

 //옵션 프린트하기
 Serial.print("옵션 : ");
 for (uint8_t i = 0; i < 16; i++)  {
   if (buffer2[i] != 32)  {
     Serial.write(buffer2[i]);
   }
 }
 
 //----------------------------------------

 Serial.println(F("\n**End Reading**\n"));

 delay(1000); //change value if you want to read cards faster

 mfrc522.PICC_HaltA();
 mfrc522.PCD_StopCrypto1();
}
//***************************************************************************************//





위의 코드로 리딩을 해보니 결과는 이렇습니다. 옵션: 하고 왜 줄 바꿈이 일어나는지는 잘 모르겠습니다. 시리얼 모니터에서 텍스트를 보낼 때, 캐리지 리턴, 라인피드가 입력돼서 그렇네요.

아래와 같이 코드를 마구잡이로 수정해서 태그의 값에 따라서 분기를 줬습니다.

 String buffer1Str;
 Serial.print(F("타입 : "));
 for (uint8_t i = 0; i < 16; i++) {
   if (buffer1[i] != 32)  { // 32가  ' ' 공란의 바이트 값
     Serial.write(buffer1[i]);
   } else {
     buffer1[i] = '\0';
     buffer1Str = String((char*)buffer1);
     break;
   }
 }  
 Serial.println();

 if (buffer1Str.equals("A")) {
   Serial.println(F("타입 A 입니다."));
 } else if (buffer1Str.equals("B")){
   Serial.println(F("타입 B 입니다."));
 }



결과화면입니다. 이제 RC522를 통해 분기를 줄 수 있네요.



BatteCoins 프로젝트

BattleCoins 17.12.26 요 몇 일 전부터 코인 매니저인 송대표가 찾아왔습니다. 그리고 이런저런 이야기를 나누다가 지금 진행중인 Checker를 잠깐 일시정지하고 코인 관련 아이템을 짧게 진행해보기로 했습니다. 그...