아두이노와 푸시(MQTT)

1. 아두이노에서 푸시를 사용하기 위해서 MQTT 프로토콜을 구현한 클라이언트를 다운받는다.
– https://github.com/knolleary/pubsubclient

2. pubsubclient 라이브러리를 Import받고 아래와 같이 구현하면 된다.

#include "TemptClient.h"
#include 
#include 



void messageArrived(char* topic, byte* payload, unsigned int uIntLength);

PubSubClient gClsMqttClient(gpChrServer, 1883, messageArrived, gClsWfClient);

void messageArrived(char* topic, byte* payload, unsigned int uIntLength)
{
	int intIndex = 0;
	char pChrBuffer[uIntLength + 1];
	for (intIndex = 0; intIndex < uIntLength; intIndex++)
	{
	    pChrBuffer[intIndex] = payload[intIndex];
	}
	pChrBuffer[intIndex] = '\0';

	String strPayload = String(pChrBuffer);
	Serial.print("uIntLength:");
	Serial.println(uIntLength);

	Serial.print("strPayload:");
	Serial.println(strPayload);
}

void getMacAddress(char * pChrMacAddress)
{
	byte bytMacAddr[6];
	WiFi.macAddress(bytMacAddr);
	snprintf(pChrMacAddress, MAC_ADDRESS_LENGTH+1, "%02X%02X%02X%02X%02X%02X", bytMacAddr[0], bytMacAddr[1], bytMacAddr[2], bytMacAddr[3], bytMacAddr[4], bytMacAddr[5]);
}


void setup()
{
	char pChrClientId[MAC_ADDRESS_LENGTH + 1];
	char pChrTopic[TOPIC_LENGTH + 1];
	Serial.begin(9600);

	if (WiFi.status() == WL_NO_SHIELD)
	{
		Serial.println("WiFi shield not present");
		while (true);
	}

	String strFwVersion = WiFi.firmwareVersion();
	Serial.print("FirmWare:");
	Serial.println(strFwVersion);
	if (strFwVersion != "1.1.0" ) Serial.println("Please upgrade the firmware");

    // 와이파이 네트워크 연결 시도
	while (gIntWiFiStatus != WL_CONNECTED)
    {
        Serial.print("Attempting to connect to SSID: ");
        Serial.println(gpChrSsid);
        gIntWiFiStatus = WiFi.begin(gpChrSsid, gpChrPasswd);
        delay(1000);
    }

	getMacAddress(pChrClientId);

	if (gClsMqttClient.connect(pChrClientId))
	{
		sprintf(pChrTopic, "arduino/%s", pChrClientId);
                // 메시지를 수신받을수 있도록 토픽을 구독한다.
		gClsMqttClient.subscribe(pChrTopic);

                // 메시지 퍼블리시(송신)
		gClsMqttClient.publish("arduino/99B8020EC478", "{'test1':200,'test2':'{babo:xxxxxx,yahoo:bbbbb}'}");
	}
}

3. 개발시 유의사항
퍼블리쉬할수 있는 데이터의 크기가 작기 때문에 실제 사용할때는 JSON또는 XML형태로 전송하는것은 이롭지 않은것 같다.
또한 위 소스상에 있는 messageArrived와 같은 CallBack함수를 통해 받을수 있는 데이터의 길이도 작으므로 푸시서버에서
긴 데이터를 전송한다면 문제가 될것이다. (즉, 큰 데이터는 수신 못할 가능성이 많음)

이클립스 아두이노에서 WiFi 라이브러리 추가시 오류 발생시 처리

이클립스에서 WiFi 라이브러리를 Import 받았을때 아래와 같이 파일을 찾을수 없다고
나온다면 다음과 같이 처리하면 된다.

arduino_wifi01

09:39:27 **** Incremental Build of configuration Release for project TemptClient ****
make all 
'Building file: C:/Applications/arduino-1.0.6/libraries/WiFi/utility/server_drv.cpp'
'Invoking: AVR C++ Compiler'
avr-g++ -I"C:\Applications\arduino-1.0.6\hardware\arduino\cores\arduino" -I"C:\Applications\arduino-1.0.6\hardware\arduino\variants\standard" -I"C:\Projects\89.IOTSolutions\02.Solutions\TemptClient" -I"C:\Applications\arduino-1.0.6\libraries\WiFi" -D__IN_ECLIPSE__=1 -DUSB_VID= -DUSB_PID= -DARDUINO=106 -Wall -Os -ffunction-sections -fdata-sections -fno-exceptions -g -mmcu=atmega328p -DF_CPU=16000000UL -MMD -MP -MF"WiFi/utility/server_drv.d" -MT"WiFi/utility/server_drv.d"  -c -o "WiFi/utility/server_drv.o" -x c++ "C:/Applications/arduino-1.0.6/libraries/WiFi/utility/server_drv.cpp"
'Finished building: C:/Applications/arduino-1.0.6/libraries/WiFi/utility/server_drv.cpp'
' '
'Building file: C:/Applications/arduino-1.0.6/libraries/WiFi/utility/socket.c'
'Invoking: AVR Compiler'
avr-gcc -I"C:\Applications\arduino-1.0.6\hardware\arduino\cores\arduino" -I"C:\Applications\arduino-1.0.6\hardware\arduino\variants\standard" -I"C:\Projects\89.IOTSolutions\02.Solutions\TemptClient" -I"C:\Applications\arduino-1.0.6\libraries\WiFi" -D__IN_ECLIPSE__=1 -DARDUINO=106 -DUSB_PID= -DUSB_VID= -Wall -Os -g -mmcu=atmega328p -DF_CPU=16000000UL -MMD -MP -MF"WiFi/utility/socket.d" -MT"WiFi/utility/socket.d"  -c -o "WiFi/utility/socket.o" "C:/Applications/arduino-1.0.6/libraries/WiFi/utility/socket.c"
'Finished building: C:/Applications/arduino-1.0.6/libraries/WiFi/utility/socket.c'
' '
'Building file: C:/Applications/arduino-1.0.6/libraries/WiFi/utility/spi_drv.cpp'
'Invoking: AVR C++ Compiler'
avr-g++ -I"C:\Applications\arduino-1.0.6\hardware\arduino\cores\arduino" -I"C:\Applications\arduino-1.0.6\hardware\arduino\variants\standard" -I"C:\Projects\89.IOTSolutions\02.Solutions\TemptClient" -I"C:\Applications\arduino-1.0.6\libraries\WiFi" -D__IN_ECLIPSE__=1 -DUSB_VID= -DUSB_PID= -DARDUINO=106 -Wall -Os -ffunction-sections -fdata-sections -fno-exceptions -g -mmcu=atmega328p -DF_CPU=16000000UL -MMD -MP -MF"WiFi/utility/spi_drv.d" -MT"WiFi/utility/spi_drv.d"  -c -o "WiFi/utility/spi_drv.o" -x c++ "C:/Applications/arduino-1.0.6/libraries/WiFi/utility/spi_drv.cpp"
'Finished building: C:/Applications/arduino-1.0.6/libraries/WiFi/utility/spi_drv.cpp'
' '
'Building file: C:/Applications/arduino-1.0.6/libraries/WiFi/utility/wifi_drv.cpp'
'Invoking: AVR C++ Compiler'
avr-g++ -I"C:\Applications\arduino-1.0.6\hardware\arduino\cores\arduino" -I"C:\Applications\arduino-1.0.6\hardware\arduino\variants\standard" -I"C:\Projects\89.IOTSolutions\02.Solutions\TemptClient" -I"C:\Applications\arduino-1.0.6\libraries\WiFi" -D__IN_ECLIPSE__=1 -DUSB_VID= -DUSB_PID= -DARDUINO=106 -Wall -Os -ffunction-sections -fdata-sections -fno-exceptions -g -mmcu=atmega328p -DF_CPU=16000000UL -MMD -MP -MF"WiFi/utility/wifi_drv.d" -MT"WiFi/utility/wifi_drv.d"  -c -o "WiFi/utility/wifi_drv.o" -x c++ "C:/Applications/arduino-1.0.6/libraries/WiFi/utility/wifi_drv.cpp"
'Finished building: C:/Applications/arduino-1.0.6/libraries/WiFi/utility/wifi_drv.cpp'
' '
'Building file: C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp'
'Invoking: AVR C++ Compiler'
avr-g++ -I"C:\Applications\arduino-1.0.6\hardware\arduino\cores\arduino" -I"C:\Applications\arduino-1.0.6\hardware\arduino\variants\standard" -I"C:\Projects\89.IOTSolutions\02.Solutions\TemptClient" -I"C:\Applications\arduino-1.0.6\libraries\WiFi" -D__IN_ECLIPSE__=1 -DUSB_VID= -DUSB_PID= -DARDUINO=106 -Wall -Os -ffunction-sections -fdata-sections -fno-exceptions -g -mmcu=atmega328p -DF_CPU=16000000UL -MMD -MP -MF"WiFi/WiFi.d" -MT"WiFi/WiFi.d"  -c -o "WiFi/WiFi.o" -x c++ "C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp"
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp:20:22: error: wifi_drv.h: No such file or directory
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp:26:21: error: debug.h: No such file or directory
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp: In static member function 'static void WiFiClass::init()':
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp:41: error: 'WiFiDrv' has not been declared
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp: In static member function 'static uint8_t WiFiClass::getSocket()':
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp:53: error: 'NO_SOCKET_AVAIL' was not declared in this scope
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp: In static member function 'static char* WiFiClass::firmwareVersion()':
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp:58: error: 'WiFiDrv' has not been declared
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp: In member function 'int WiFiClass::begin(char*)':
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp:66: error: 'WiFiDrv' has not been declared
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp:70: error: 'WL_DELAY_START_CONNECTION' was not declared in this scope
C:/Applications/arduino-1.0.6/libraries/WiFi/WiFi.cpp:71: error: 'WiFiDrv' has not been declared

프로젝트를 선택하고 “Properties > C/C++ General > Paths and Symbols” 를 선택한후 “GNU C++” 을 선택한다.
arduino_wifi02

Add 버튼을 눌러 아래와 같이 “/프로젝트명/WIFI/utility”를 넣고, “Is a workspace path”를 체크한 후 “OK”를 누르면 된다.
arduino_wifi03

아두이노 float을 문자열로 변환

아두이노에서 아래처럼 sprintf을 이용하여 문자열로 변경하려고 할때
결과를 보면 ? 가 출력된다.

sprintf(pChrBuffer, "%f", fltValue);

아두이노에서는 float형에 대해서 sprintf가 제대로 지원되지 않는듯하여,
확인하여 보니 아래 함수를 이용하면 변환할수 있다.

char * dtostrf(ouble __val, signed char __width, unsigned char __prec, char * __s);
float fltValue = 123.456;
char pChrBuffer[50];
 
dtostrf(fltValue , 5, 2, pChrBuffer);  // 5 : width, 2 : precision

다른 방법으로는 String을 이용하여 아래와 같이 할수도 있다.

String strValue = String(fltValue);

아두이노 와이파이 쉴드 펌웨어 업그레이드

1. 아두이노와 분리
2. 점퍼 스위치 변경

arduino_wifi_shield_upgrade0
위와 같이 하나만 꽂아 있는 딥스위치를 빼서 두군데 다 접지되도록 한다.

arduino_wifi_shield_upgrade1

3. ATMEL 펌웨어 수정프로그램 다운로드
– http://www.atmel.com/tools/FLIP.aspx 에서 하단에 있는
FLIP 3.4.7 for Windows (Java Runtime Environement included) 버전을 받아 설치
4. USB 연결
– wifi 쉴드의 USB를 PC와 연결하여 전원을 넣는다.
5. 제어판의 장치관리자를 열어 “기타 장치” > “AT32UC3A DFU”를 오른쪽 마우스로 클릭하여 “드라이브 소프트웨어 업데이트” 선택하여 업데이트
업데이트 파일의 위치는 “C:\Program Files (x86)\Atmel\Flip 3.4.7\usb” 로 지정
arduino_wifi_shield_upgrade3

6. CMD창을 열어 cd C:\Program Files (x86)\Atmel\Flip 3.4.7\bin 을 이동
7. 펨웨어 업그레이드1

batchisp.exe -device AT32UC3A1256 -hardware usb -operation erase f memory flash blankcheck loadbuffer "C:/Program Files (x86)/Arduino/hardware/arduino/firmwares/wifishield/binary/wifi_dnld.elf" program verify start reset 0

arduino_wifi_shield_upgrade4

8. 와이파이 쉴드에 있는 reset 버튼 클릭
9. 펨웨어 업그레이드2

batchisp.exe -device AT32UC3A1256 -hardware usb -operation erase f memory flash blankcheck loadbuffer "C:/Program Files (x86)/Arduino/hardware/arduino/firmwares/wifishield/binary/wifiHD.elf" program verify start reset 0

arduino_wifi_shield_upgrade5
10. 점퍼 스위치를 원래대로 변경
11. 아두이노와 다시 결합

이클립스와 아두이노의 연동

다음은 아두이노 IDE의 불편함 때문에 자료를 찾아보니 이클립스에서 연동가능함을 알고 정리한 글이다.
또한 Windows 8.1 64비트 노트북에서 테스트 하다보니 다양한 에러사항이 발생하여 이를 처리한 내용이기도 하다.

1. 이클립스 다운로드
– https://www.eclipse.org/downloads/ 에서 “Eclipse IDE for C/C++ Developers, 164 MB” 64비트 버전 다운로드
arduino_eclipse_download

2. 아두이노 플러그인 설치
2.1 Help > Install New Software…메뉴에서 Add 버튼 클릭하고 아래와 같이 입력
– Name : Arduino Eclipse Plugin
– Location : http://www.baeyens.it/eclipse/update
arduino_eclipse_install01

2.2 아래 하단에 체크박스가 여러개 있는곳에서 “Group items by category”를 언체크
arduino_eclipse_install02

2.3 Arduino eclipse extensions가 나타나는데 이를 선택하고 Next 버튼 클릭
arduino_eclipse_install03

2.4 빌드될때 자동 저장을 위하여 “Windows > Preferences > General >Workspace” 메뉴에 있는 “Save automatically before build” 체크
arduino_eclipse_install04

2.5 “Windows > Preferences > Arduino > Arduino” 메뉴 설정
– Arduino IDE path : C:\Applications\arduino-1.0.6
– Private Library path : C:\Users\용민\Documents\Arduino\libraries
– Use Arduino IDE Tools in eclipse 체크
arduino_eclipse_install05

※ 참고 : 아두이노 Install 버전으로 설치시 “c:\Program Files(x86)”에 설치되는데 특수문자로 인하여
빌드시 아래와 같은 에러가 발생한다.

09:41:53 **** Incremental Build of configuration Release for project EclipseTest ****
make all 
Building file: C:/Program Files (x86)/Arduino/libraries/WiFi/utility/server_drv.cpp
Invoking: AVR C++ Compiler
make: Interrupt/Exception caught (code = 0xc00000fd, addr = 0x4217b3)

09:41:53 Build Finished (took 172ms)

그래서 위와 같이 특수문자가 없는 일반 폴더, 즉 C:\Applications\arduino-1.0.6로 지정하였다.

2.6 위 메뉴에서 “test serial dll” 버튼을 클릭하여 맞게 설정한것인지 테스트한다.
arduino_eclipse_install06

3. 프로젝트 생성
3.1 File > New > Other > Arduino > New Arduino sketch 선택하여 스케치 생성 시작
arduino_eclipse_project01

arduino_eclipse_project02

3.2 자신의 아두이노 보드와 포트를 설정한다.
arduino_eclipse_project03

3.4 cpp와 헤더파일 생성된 화면
arduino_eclipse_project04

3.5 라이브러리 추가
wifi등의 라이브러리를 이용하기 위해
“File > import > Arduino > Import Arduino libraries in the current project”를 선택
arduino_eclipse_project05

arduino_eclipse_project06

arduino_eclipse_project07

4. 빌드
4.1 “Prject > Build All” 메뉴를 이용하여 빌드시 아래와 같이 에러가 발생한다면 “GNU Make”를 설치한다.
arduino_eclipse_build01

Man muss nur ein bestimmtes Medikament auswählen und seine Bestellung bezahlen, geben Sie Ihrer Erektion den Vorzug, personen die an Manien und manischer Depression. Das Potenzmittel Kamagra ist imstande, den Diskurs über Erektionsprobleme im Mittelpunkt der Gesellschaft zu verankern, in der örtlichen wie auch der Online Versand Apotheke wird allerdings das Original Rezept vom Haus -. Damit kann man mit Cialis auch einen der entscheidenden Nachteile beheben.

4.2 “GNU Make” 설치
– http://gnuwin32.sourceforge.net/packages/make.htm 의 Download에서 “Setup” 파일을 받아 설치
arduino_eclipse_build02

4.3 이클립스의 “Windows > Preferences > Arduino > Paths” 메뉴 설정
arduino_eclipse_build03
위 화면에서 GNU make를 선택하여 “Edit” 버튼을 클릭하여 GNU Make가 설치되어 있는
“C:\Program Files (x86)\GnuWin32\bin” 폴더를 지정
arduino_eclipse_build04

4.4 빌드 완료