Wireless 바코드 스캔 피드백
왕허접하지만 실제 업무용.
2016-04-10
개요 : 창고의 물건을 특정 지역에 넣을때 Wireless Scanner는 전 창고를 커버하지만 문제는 스캔한 데이타가 중앙 자료 데이다베이스에 잘 들어 갔는지, 무슨 문제가 없는지를 알 방법이 없기에 이 피드백장비를 만들게 되었음. 자체 데이타 관리 프로그램에서 신호를 보내서 현재 상황을 알려줌.
문제 : 왜 간단하게 안드로이드로 셀폰용 앱을 만들어 처리하지, 귀찮게 저런걸 만들어야 하나? 답은 직원들이 일하다 고가의 셀폰을 떨어뜨려 망가지면 최소 칠십만원짜리 셀폰을 사주기는 무리. 창고에서 일하는 남미계열 직원들은 어려서 그런지 셀폰은 최고제품들을 사용함. 막 쓰는 용이 필요함.
해법 : 아주 싸게 LCD (2줄/16자) 와, NodeMCU V.1.0과 싸구려 셀폰 배터리 파워 뱅크만을 사용해서 전체 가격은 $18 (2만원) 이내로 만들었음. (비고 : 사실상 가격은 대량생산용이 아니라 중요한 요소가 아니었지만 그냥 재미삼아 가장 간단하게 만들었음.)
기술 : 컴과 장비(NodeMCU)는 무선 UDP 통신으로 함.
NodeMCU는 I2C로 LCD에 메세지를 보냄.
참고 : 우리나라에서 이런 장비를 만들어 팔려면 통신관련인증이나 허가를 받아야 하는데 비용이 기본이 수천만원이니깐 일반 상업용 제품을 만드는 시도도 하지 마실길(지랄맞은 망국규제). 나는 미국에서 내가 소프트웨어 일봐주는 회사의 창고용으로 만든것임. 우리나라의 innovation은 거의 중견기업 내지는 대기업 전용인것 같슴. 안타깝게도 대한민국은 IoT의 후진국이 될 수 밖에 없는 운명.. 판매용을 만들때는 문제지만 본인 소유의 농장이나 공장을 자동화하는 용도로는 문제가 없을듯. 아님 회사내 사용을 목적으로 만든다면, 그래도 법에 걸릴라나? 그건 잘 모름.
회로 :
LCD는 5V 전압을 사용함.
사진 :
(장비의 최종 조립 전)
(밧데리 붙이기 전 - 초 강력 양면 테입 사용)
(조립후 뒷 모습 : 세워놓을수 있음)
(조립후 윗 모습)
완성된 앞모습.
동영상 :
코드 : (NodeMCU의 코드만) - 공개용. 라이브러리는 각자 알아서 설치할것.
/* THIS IS WRITTEN FOR NodeMCU ESP-12E Development Board V.1.0 */
/* Author: Hyun Ja. License for this code is set to public domain(free) */
/* License of each library is as specified by each library authors. */
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
WiFiUDP port;
LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display
char packetBuffer[30];
unsigned int localPort = 6767;
const int ThisMachine = 2;
/* Set these to your desired credentials. */
const char* ssid = "****"; // 당신의 와이파이 명칭
const char* password = "**********"; // 당신의 와이파이 패스워드
char botresp[30] = "002-WB: Scan Box First!";
int P2B_NEWLINE = 11; // < -- Beginning of Command to BOT (ESP-BOT)
int P2B_COM_TYPE = 12; // 0..int p2b_pin = 0;9 -- First 2 letters after "<"
// Total Command Types : 10 x 10 = 100
int P2B_DATA = 12; // Data section
int P2B_ENDING = 13; // > -- End of Message Signal
int P2B_STAT_NONE = 1; // Do nothing until '<' has received
int P2B_STAT_CMD = 2; // Accepting Command
int P2B_STAT_DATA = 3; // Accepting Command data
int P2B_STAT_END = 4; // '>' has receieve, it is the end of command;
char p2b_mach[4]; // always needed + 1
char p2b_command[3]; // always needed + 1
char p2b_data[17]; // always needed + 1
int p2b_machno = 0;
int p2b_status = 0;
int iD0 = 16; // GPIO 16;
int iD1 = 5; // GPIO 5;
int iD2 = 4; // GPIO 4;
int iD3 = 0; // GPIO 0;
int iD4 = 2; // GPIO 2;
int iD5 = 14; // GPIO 14;
int iD6 = 12; // GPIO 12;
int iD7 = 13; // GPIO 13;
int iD8 = 15; // GPIO 15;
int iD9 = 3; // GPIO 3;
int iD10 = 1; // GPIO 1;
int iD11 = 9; // GPIO 9;
int iD12 = 10; // GPIO 10;
// Head Light using relay
int HeadLight = iD0; // using GPIO = 16 to turn on/off relay
int i = 0; // dumb int
int j = 0; // dumb int
int k = 0; // dumb int
int n = 0;
int lp =0; // dumb last position ofinput command string
char inputString[30]; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
char inChar;
String tempStr;
String BoxLine;
String ItemLine;
char buffer[12]; // buffer used for itoa (int to string conversion)
int inlen = 0; // Length of inputString
void ClearP2BCommand()
{
p2b_mach[0] = 0; // null
p2b_mach[1] = 0; // null
p2b_mach[2] = 0; // null
p2b_mach[3] = 0; // null
p2b_command[0] = 0; // null
p2b_command[1] = 0; // null
p2b_command[2] = 0; // null
for (int i=0; i <= 16; i++){
p2b_data[i] = 0; // null
}
p2b_machno = 0;
BoxLine = " ";
ItemLine = " ";
}
void setup(){
lcd.init(); // initialize the lcd
lcd.backlight();
// clear the screen
lcd.clear();
lcd.print("Scan Box First!");
pinMode(HeadLight, OUTPUT); // iD0
WiFi.begin("****", "********"); // 각자의 와이파이 연결 코드
port.begin(localPort);
BoxLine = "Configuring AP..";
WriteBox();
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
};
ItemLine = "SSID : ";
ItemLine += ssid;
WriteItem();
digitalWrite(HeadLight, HIGH);
delay(1000);
BoxLine = "Scan Box First!";
WriteBox();
delay(1000);
ItemLine = " ";
WriteItem();
digitalWrite(HeadLight, LOW); // Off for Begining (HIGH = off, LOW = on
}
void uPrint(char* msg){
port.beginPacket(port.remoteIP(),port.remotePort());
port.write(p2b_mach);
port.write("-");
port.write(msg); // Getting Command Works
port.write(": ");
port.write(p2b_data);
port.endPacket();
}
void WriteBox(){
lcd.clear();
lcd.setCursor(0,0);
lcd.print(BoxLine);
}
void WriteItem(){
lcd.setCursor(0,1);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(ItemLine);
}
// Test Sample send-out from PC
// #002-IT:Item: 125412-25>
// #002-WB:BOX : 1A-293>
void ExecuteLogicalCommand()
{
// Write to the top row
if (((char)p2b_command[0] == 'W') and ((char)p2b_command[1] == 'B')) {
BoxLine = p2b_data;
WriteBox();
};
// Write to the second row
if (((char)p2b_command[0] == 'I') and ((char)p2b_command[1] == 'T')) {
ItemLine = p2b_data;
WriteItem();
};
uPrint(p2b_command); // print to UDP Port
}
void ClearParamsAndInputstring(){
// clear the string:
for (i=0;i<=29;i++) {
inputString[i] = 0;
};
i = 0;
j = 0;
stringComplete = false;
}
void loop(){
int packetSize = port.parsePacket();
if (packetSize) {
int len = port.read(packetBuffer, 30); // here, len = packetSize
if (len > 0) {
packetBuffer[len] = 0;
if (len < 26) {
for (i=1;i<26;i++)
botresp[i+3] = packetBuffer[i];
}
};
i = 0;
while ((packetSize) >= i){
inChar = packetBuffer[i]; // get the new byte:
inputString[i] = inChar;
i++;
// if the incoming character is a newline, set a flag
if ((inChar == '#') or (inChar == '<')) {
p2b_status = P2B_STAT_CMD;
ClearP2BCommand();
j = i-1;
} else if (inChar == '>') {
p2b_machno = 0;
if (inputString[j+1] != '0') {
p2b_machno = (int(inputString[j+1])-48) * 100;
}
if (inputString[j+2] != '0') {
p2b_machno = p2b_machno + (int(inputString[j+2])-48) * 10;
}
if (inputString[j+3] != '0') {
p2b_machno = p2b_machno + (int(inputString[j+3])-48);
}
// If this command is for ME (This machine)
if (ThisMachine == p2b_machno){
p2b_mach[0] = inputString[j+1];
p2b_mach[1] = inputString[j+2];
p2b_mach[2] = inputString[j+3];
p2b_command[0] = inputString[j+5];
p2b_command[1] = inputString[j+6];
j = j + 8;
k = 0;
for (n=j;n<=packetSize;n++){
// end of param
if (inputString[n] == '>'){
} else {
p2b_data[k] += inputString[n];
k++;
}
}
ExecuteLogicalCommand();
}
stringComplete = true;
p2b_status = P2B_STAT_NONE;
} else {
lp = i-1; // set last position on each entry;
}
}
}
if (stringComplete) {
ClearParamsAndInputstring();
};
}
'NodeMCU' 카테고리의 다른 글
GY-88을 NodeMCU (ESP-12E) 모듈과 I2C로 연결해서 사용하기 (0) | 2016.03.10 |
---|---|
NodeMCU w/ Motor Sheild 예문의 실제 실험 사진들 (0) | 2015.11.09 |
NodeMCU V.1.0 을 Motor Shield 와 함께 사용한 프로그램 예) (0) | 2015.11.09 |