프로그래밍/C, C++, Java, Python

[Python] IEEE754 부동 소수점 <-> 비트 변환 예제

포도알77 2019. 7. 14. 13:06

1. 서론

 현재  태양광 모니터링 프로젝트 진행하고 있다. 특히 RTU와 인버터간의 데이터 통신을 통해서 값을 얻어야 하는데, 인버터 제작 회사마다 통신 프로토콜이 다르다.

 게다가 일반적으로 소수점을 표현할 때 고정 소숫점을 주로 사용하는 것과 달리 ABB사의 TRIO-50-TL-OUTD 인버터는 부동 소수점을 사용한다.

 따라서 IEEE754 32비트 단정도를 헥사로 받아서 이를 변환하여야 한다. C나 C++ 같은 경우 직관적으로 memcpy로 처리하면 될것 같은데 파이썬은 사실 이번 프로젝트에서 처음 사용하는 것이라 구글링이 필요했다.

 

2. ABB 사의 IEEE754 32비트 부동소수점 표현 방식

 ABB사에서 제공하는 TRIO-50-TL-OUTD 인버터 통신 프로토콜 문서 9 페이지를 를 보면 Word Swapped Floating Point 32-bit(SF32)로 정의된 데이터 타입이 있으며, Modebus PDU register 형태를 보면 아래의 사진과 같이 Low word부터 표현되어 있다. 

  이 말은 일반적인 MSB-LSB 형태의 데이터 4byte 순서가 [0, 1, 2, 3]일 때, 위의 SF32는 [2, 3, 0, 1] 형태로 표현하고 있는 것이다. 

 즉, IEEE754로 표현하기 위해서는 값의 순서를 바꿔야 한다는 말이 된다.

 

 

3. Python으로 코딩하기

사실 더 깔끔하게 코딩할 수 있겠지만, 급한 내 상황상 이 정도만 해도 충분해 보인다. 

def toFloat32(data, order=[2,3,0,1]):
    ndata = [0, 0, 0, 0]
    for i in range(0, 4):
        ndata[order[i]] = data[i]
    hstr = bytes(x for x in ndata)
    return struct.unpack(">f",hstr)[0]

 

 위의 코드는 정말 별 내용이 없다. hex 배열을 받아서 이를 IEEE754로 변환해서 float 형태의 값으로 반환한다. 향후 표현 방식이 또 다른 인버터를 대응하기 위해서 order를 매개 변수로 처리했다. 

 for 루프는 헥사 값 순서 변경을 위함이고 이후 byte 타입으로 변경 후에 struct.unpack을 수행하여 값을 변경한다. 당연히 struct 모듈을 import해야 한다.

페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사