OBD-II 자주쓰이는 PID 명령 정리

다음은 OBD-II를 테스트 하면서 자주쓰이는 PID에 대하여 정리한 내용입니다.

– OBD 리셋명령(Reset) : AT Z
– Echo Off 명령(Echo Off) : AT E0
– 라인피드명령(Line Feed) : AT L0

– 차량식별자번호(VIN) 구하는 명령 : 09 02
– 연료통에 남아 있는 연료량 구하는 명령(Feul Level, 단위: %) : 01 2F
– 오작동 표시 등 (MIL)을 켜고 주행 한 거리 구하는 명령 : 01 21
– 코드가 지워진 이후의 거리(KM) 구하는 명령 : 01 31
– 현재 엔진의 RPM(revolutions per minute) 구하는 명령 : 01 0C
– 공기흐름량(MAF, 단위:%) 구하는 명령 : 01 10
– MIL등 점화여부 및 고장코드갯수 구하는 명령 : 01 01
– 속도 구하는 명령 : 01 0D
– 시간당 연료소비율 구하는 명령(Fuel Rate) : 01 5E
– 연료종류 구하는 명형(FuelType) : 01 51

아두이노와 푸시(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함수를 통해 받을수 있는 데이터의 길이도 작으므로 푸시서버에서
긴 데이터를 전송한다면 문제가 될것이다. (즉, 큰 데이터는 수신 못할 가능성이 많음)

아두이노 WiFiClient의 write 함수의 제약

tcp 소켓의 send 함수와 같은 함수인 write(데이터, 데이터 길이) 함수를 이용하여
통신서버로 데이터를 전송하려고 할때

size_t write(const char *buffer, size_t size);

아두이노에서는 데이터 길이가 90 bytes 를 초과하게 되면 에러가 발생하게 된다.
따라서 전송할 용량이 크다면, 버퍼를 여러건으로 나누어 전송할 필요가 있다.

wfClent.write(pCharBuffer1, 90);
wfClent.write(pCharBuffer2, 70);
....

이클립스 아두이노에서 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. 아두이노와 다시 결합