'battery'에 해당되는 글 8건

  1. 2021.01.06 Hardware | bGeigie Nano 충전을 wireless 로 바꿔보자
  2. 2020.10.25 Hardware | 아이폰 8 액정 수리기
  3. 2020.05.29 Life | iPhone 8 Plus 밧데리 교환 DIY
  4. 2019.04.17 Hardware | iPhone SE 밧데리 교환 DIY
  5. 2019.04.15 Hardware | iPhone 6 Plus 밧데리 교환 DIY
  6. 2018.11.20 Hardware | RTC DS3231 부품 사용기 - 2
  7. 2018.05.19 Life | iPhone 6S Plus 밧데리 교환 DIY
  8. 2017.11.22 Hardware | bGeigie Nano 의 battery 를 업그레이드 해보자

Hardware | bGeigie Nano 충전을 wireless 로 바꿔보자

|

가지고 있던 방사능 측정기를 사용하고 있습니다. 지금까지의 관련 글은 다음과 같아요.


* Hardware | Safecast bGeigie Nano 를 조립해 보자 - 1

http://chocoball.tistory.com/entry/Hardware-Safecast-bGeigie-Nano-1


* Hardware | Safecast bGeigie Nano 를 조립해 보자 - 2

http://chocoball.tistory.com/entry/Hardware-Safecast-bGeigie-Nano-2


* Hardware | bGeigie Nano 의 battery 를 업그레이드 해보자

http://chocoball.tistory.com/entry/Hardware-bGeigie-Nano-battery-upgrade


* Hardware | bGeigie Nano 를 이용하여 방사능을 측정해 보자

http://chocoball.tistory.com/entry/Hardware-bGeigie-Nano-checking-radiation


* Hardware | Safecast bGeigi nano firmware upgrade

https://chocoball.tistory.com/entry/Hardware-Safecast-bGeigi-nano-firmware-upgrade


Mini USB B type 으로 충전 합니다만, 뚜껑을 까고 USB 에 연결하는 것이 귀찮아 무선충전 개조를 생각하게 됩니다.




1. 무선 충전 리시버


무선 충전용 리시버를 연결해 주면 될 것 같아, 집안에 굴러다니는 무선 충전용 리시버를 사용해 봅니다.

예전에 사부작 사부작 하려고 구매해 놨던 Charger Module 을 테스트 해 봅니다.


* dc 12V Wireless Charging Charger Module 5V 2A Power Supply Coil for DIY Cell Phone Transmitter Module + Receiver Module

https://www.aliexpress.com/item/32717511392.html



Transmitter Module 입니다.



Receiver Module 입니다.



한 set 인 Transmitter 와 Receiver 와는 사용이 가능하나, 요츰의 Qi 시리즈와는 컨트롤 통신의 싱크가 맞지 않아 사용이 불가 하더군요.

아래 처럼, 무선 충전기에 다른 기기를 충전하다 사용하면 5V 를 뽑아 줍니다.



다만, 선 무선 충전이 이루어 지지 않고 있는 상태에서 Receiver 를 올려 놓으면 전원이 널을 뜁니다.

이걸 사용하긴 힘들겠군요. 



일전에 Transistor Tester 를 무선 충전으로 개조했을 때, 사용했던 Charging Coil Receiver Module 을 또다시 구입합니다.


* Hardware | Transistor Tester 무선충전 upgrade

https://chocoball.tistory.com/entry/Hardware-Transistor-Tester-wireless-charging-upgrade


가격이 완벽히 동일하군요.


* DIY Qi Standard Wireless Charging Coil Receiver Module Circuit Board DIY Coil For Phone For Battery 5V 1A Fast Quick Charger

https://www.aliexpress.com/item/32995630744.html



잘 도착.



완성도가 나쁘지 않은 모습.



Qi 형식에 맞는 통신 및 전원 컨트롤을 위해, 회로가 복잡합니다.





2. Mini USB type B 어뎁터


충전으로 사용되는 Mini USB type B 의 숫놈 변환 어뎁터를 구입합니다.

무선 충전 Receiver 와 USB 어뎁터 전원선과 연결하면, Receiver Module > Mini USB Type B (Male) > 본체 구조가 됩니다.


* Left & Right & UP & Down Mini USB male to Micro USB B feMale data charger cable adapter converter charger data cable 0.1M -1M

https://www.aliexpress.com/item/4001170882838.html



USB 어뎁터 도착.



이처럼 Type B > Universal USB 로 변환 어뎁터 이지만, 중간을 잘라 전원의 +/- 선을 무선 충전 코일의 output 과 연결하려 했습니다.



꽂힐 USB Female 부분.



꽂아 봤습니다... 아... 튀어 나오네요.



언뜻 문제 없이 보이지만, 생각보다 많이 튀어나와, 펠리컨 케이스의 뚜껑이 닫히지 않습니다.



선을 밑으로 뺄 수 있도록 되어 있어, 구조적으로 완벽하지만, 뚜껑 문제로 단념.





3. 무선 Receiver Module 장착


USB 단자를 사용하지 못하지만, 본체 부분을 살펴 보면 CHG 5V/- 가 보입니다. 당연 Charging 5V +/- 겠네요.

무선 Receiver Module 에서 나오는 +/- 를 직접 연결하면 될 듯 합니다.



장착될 위치를 대략 맞춰 봅니다. 위치는 대략 이렇게 하면 간섭이 없을 듯.



PCB 부분은 코일 끝단을 구부려서 아크릴 밑 부분에 위치하게 합니다.



아크릴을 다시 본체에 장착하면 다음과 같은 모습이 됩니다. 선을 바깥 쪽으로 빼야 해서, 세번 째 작업에서 성공했습니다.



선을 아래 그림처러 빼고, 중간의 틈새를 이용하여 올리면 됩니다.



끝단을 아래처럼 납땜하면 작업이 완료 됩니다.





4. 테스트


훗, 한방에 잘 되네요. USB 단자를 이용하지 않더라도 충전이 잘 됩니다.

다만, 고주파음이 좀 들리는 것이 흠.



그리고 가장 큰 문제는, 케이스를 씌우고 충전하면 충전 되지 않습니다.

그 이유로는, 케이스를 씌우면서 충전 기기의 Transmitter 와의 거리가 1cm 이상 벌어져, 전자기가 도달하지 못하는 문제가 있습니다.


좀더 강력한 Transmitter 를 사용하지 않는다면, 불가능 할 듯. 나중에 적당한 Transmitter 를 찾아 봐야겠습니다.



당분간는 예전처럼 그냥 USB 를 사용할 수 밖에.... ㅠㅠ

무선 충전 Receiver Module 이 연결되어 있더라도, USB 를 충전도 문제가 없었습니다.




FIN


And

Hardware | 아이폰 8 액정 수리기

|

그 동안 iPhone 간단 자가수리로 아래처럼 포스트를 뽑아 먹었네요.


* Life | iPhone 8 Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/Life-iPhone-8-Plus-battery-replacement-DIY


* Hardware | iPhone SE 스크린 교환기

https://chocoball.tistory.com/entry/Hardware-iPhone-SE-screen-replacement


* Hardware | iPhone 6s Plus 오리지널 배터리 교환기

https://chocoball.tistory.com/entry/Hardware-iPhone-6s-Plus-original-battery-replacement


* Hardware | iPhone SE 밧데리 교환 DIY

https://chocoball.tistory.com/entry/Hardware-iPhone-SE-battery-replacement-DIY


* Hardware | iPhone 6 Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/iPhone-6-Plus-battery-replacement-DIY


* Hardware | iPhone 6s plus earpiece 자가 수리

https://chocoball.tistory.com/entry/Hardware-iPhone-6s-plus-earpiece-replacement-diy


* Life | iPhone 6S Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/Life-iPhone-6S-Plus-battery-replacement-DIY


오늘은, 직장 동료의 iPhone 8 액정 수리기 입니다.




1. 상태


전면 낙하 한 번, 측면 낙하 두 번 정도의 상태 입니다.



왼쪽 모서리 부분은 아주 박살이 났습니다.



밑부분부터 측면까지 금도 나가 있고, 화면에 불은 들어 오는데, 인지할 정도가 아니여서 수리를 하게 되었습니다.



뒷면에 생활 스크레치 정도는 있지만, 교체할 정도는 아니라서 전명 액정만 갈기로 합니다.





2. 분해


교환용 액정에 들어있던 드라이버들 입니다.



나사를 빼려 하니, 생활 오염이 심하여 세척을 먼저 합니다.



나의 만능 액체... 아소프로폴 99% 입니다.



쓱싹쓱싹 하니, 나사 머리 뿐만 아니라 스피커/마이크 부분도 깨끗해 졌습니다.



별나사 드라이버로 살살 제거해 줍니다.



잊어먹지 않도록 어디엔가 잘 보관해 줍니다.



빨판은 하나만 동봉되어 있는데, 저는 여러개를 가지고 있으니, 위아래로 붙여서 땡겨 줍니다.



살짝 벌어지는 틈을 타서 얼른 헤라를 꽂아 넣습니다. 여기까지 오면 거의 다 한거나 마찬가지.



헤라로 한바퀴 돌려, 발라져 있는 접착제를 끊어 주면 액정이 쉽게 들어 올려집니다.

주의할 것은, 정면에서 봤을 때 오른쪽 / 사진에서 윗부분에 flex cable 로 연결되어 있으니, 끊어먹거나 힘이 들어가지 않도록 합니다.



얼마나 세게 깨졌으면, 액정 잔해가 돌아다니고 있습니다.



십자 드라이버로 나사 제거 후, 금속판을 들어내면 connector 들이 노출 됩니다. 액정과 연결되어 있는 커넉터 두 개를 분리합니다.



윗쪽에 추가로 연결되어 있는 부분이 있으니, 마찬가지로 나사 풀고 금속판 제거 후, 커넥터를 뽑아 줍니다.



짜잔~ 해체 완료.





3. 액정 비교


깨진 오리지널 액정은 구멍이 났네요.



대체 액정은 아래 링크에서 구입했다고 합니다.

카메라 / 스피커는 일체형이고, 홈버튼만 이식하면 됩니다.


물론 저가형으로, 카메라 스피커 이식형도 있습니다만, 작업 시간이 훨씬 많이 들고 실패 확률이 낮아집니다.


* No.1 Full Set LCD Screen For iPhone 7 8 Plus LCD Assembly Complete Touch Digitizer Screen Replacement AAA Display Front Camera

https://www.aliexpress.com/item/4000248534609.html



포장은 플라스틱으로 잘 고정되어 있습니다.



대체 액정이지만 나쁘지 않습니다.



뒷면 입니다. 먼가 조잡해 보이지만 그건 느낌일 뿐 입니다.



오리지널과 같이 찍어 봤습니다. 당연하게도 거의 동일합니다.



대체형 액정은 한자 "팔" 이 각인되어 있네요.



원래는 바코드가 새겨져 있습니다.



오리지널 액정 윗쪽 flex cable 에는 애플 로고가 새겨져 있습니다.



대체 액정에는 숫자는 따라 했는데 로고는 뺐군요.



중간쯤 보이는 케이블 두 개 입니다.



대체 액정은 잘 휘고 더 얇습니다. 내구성은 떨어지겠지만, 조립하면 안쪽에 들어가니 별 문제는 없습니다.



오리지널 액정의 홈버튼 뒷쪽 입니다. 저 홈버튼 뭉치를 대체 액정에 이식해 줘야 합니다.



대체 액정에는 홈버튼 뭉치가 들어갈 자리는 비어 있습니다.



대체 액정의 공기가 들어간 부분은 애교.





4. 홈버튼 이식


오리지널 액정에서 홈버튼을 분리합니다.

주의점은 3각 나사로 고정되어 있으니, 드라이버 선택을 맞게 해야 합니다.



액정과 연결되어 있는 커넥터도 살살 분리 합니다.



양면 테이프로 고정되어 있으니, 헤라를 밑부분에 조금씩 쑤셔 넣으면서 분리하면 됩니다. 짠~.



조립은 분해의 역순.




5. 작업 완료


전원을 넣으니, 문제 없이 잘 동작 되네요.



다만, True Tone 은 활성화 되어 있지 않습니다.



원래 True Tone 도 활성화 시키고 싶었으나, 이걸 하려면 원본 액정에서 고유코드를 뽑아서 대체 액정에 밀어 줘야 가능합니다.

이 작업을 위해서는 아래같은 장비가 있어야 합니다.


* QIANLI iCopy Plus with Battery Board for iPhone 7 8 X XR XS MAX 11 Pro Max LCD/Vibrator Transfer Display/Touch EPROM Repair

https://www.aliexpress.com/item/4000207236545.html



이 장비는 여러가지 코드 복사에 사용될 수 있습니다. 대응 가능한 iPhone 은 7 부터 XS max 까지 입니다.



추가로 방수를 위해서 씰링 테이프도 구매해서 조립할 때 넣어주어야 하나, 이 부분은 이번에 빠졌네요.


* 2Pcs Screen Waterproof Adhesive Seal Sticker For for IPhone 6s 6s plus 7 7 plus 8 8 plus XR X XS Phone Repair Part

https://www.aliexpress.com/item/4000036443357.html



부품중에 카드모양의 빨간 플라스틱.



아마도 스텐드 인 듯 하여 대충 조립해서 세워 봤는데, 저는 반대 방향으로 사용했군요. 어쩐지 자꾸 미끄러 지더니만...

다음에 또 사용할 일이 있으면, 아래 사진의 반대방향으로 사용하면, 액정이 잘 고정되고 편할 듯 합니다.



FIN


And

Life | iPhone 8 Plus 밧데리 교환 DIY

|
Life | iPhone 6S Plus 밧데리 교환 DIY

출처: https://chocoball.tistory.com/entry/Hardware-iPhone-6s-Plus-original-battery-replacement [초코볼의 inside Tech]i
Life | iPhone 6S Plus 밧데리 교환 DIY

출처: https://chocoball.tistory.com/entry/Hardware-iPhone-6s-Plus-original-battery-replacement [초코볼의 inside Tech]

오늘은 iPhone 8 Plus 배터리 자가 교체기 입니다.

지금까지 iPhone 배터리 자가 교체는 4번 해봤습니다. 관련된 글은 아래 참조.


* Hardware | iPhone 6s Plus 오리지널 배터리 교환기

https://chocoball.tistory.com/entry/Hardware-iPhone-6s-Plus-original-battery-replacement


* Hardware | iPhone SE 밧데리 교환 DIY

https://chocoball.tistory.com/entry/Hardware-iPhone-SE-battery-replacement-DIY


* Hardware | iPhone 6 Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/iPhone-6-Plus-battery-replacement-DIY


* Life | iPhone 6S Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/Life-iPhone-6S-Plus-battery-replacement-DIY




1. 배터리 구매


인터넷을 뒤지다 보면 몇 가지 브랜드 들이 보이는데, DEJI 제품을 한번도 사용해 본적이 없는 것 같아, 아래 제품을 구입했습니다.

보통은 AliExpress 에서 구매하는데, 가격 비교를 해 보니, 한국에서 직접 구매하는 것이 배송이나 가격적으로 더 메리트가 있었습니다.

왠만하면 이제 한국에서 온라인 쇼핑하는 것이 나은 듯.


* DEJI 아이폰 6 6s 7 8 X 아이폰6플러스 아이폰6s플러스 아이폰7플러스 아이폰8플러스 아이폰X 아이폰6s 배터리 뎃지 아이폰 배터리 자가 교체 수리

https://smartstore.naver.com/it2000/products/4435333557



비용은 19,500 원 + 배송비 2,500 원. 하루만에 도착.



중국 회사 제품이지만, 한국의 총판이 있는 듯.



메뉴얼은 버리고 구성품에 빠진 것이 없나 확인해 봅니다.



배터리 스펙은 다음과 같습니다. 2691mAh 용량이면 정품과 동일 용량.



배송 중의 충격에 영향받지 않도록 플라스틱 구조물이 보호하 모양으로 포장되어 있습니다.



단자 끝이 대충 접혀져 있군요. 지금까지 경험상 대충 손으로 구부리는 듯 합니다.

보드와 결합 후, 텐션이 생길 수 있으니, 필요하면 다시 구부려야 합니다. 일단은 그냥 놔두고 작업 하면서 확인해 보면 됩니다.



동봉되어 있던 드라이버 구성 입니다. 삼각형 드라이버가 필요 할까? 했는데 iPhone 8 부터는 필요 하더군요.





2. 방수 씰링 테이프


아마 iPhone 6s 부터, 방수 성능을 높이기 위해 본체 케이스와 액정 화면 사이에 실링이 되어 있습니다.

배터리 교체를 위해 분해하면서 방수 실링을 벗겨 내야 하므로, 조립시 다시 실링 할 수 있게 방수 스티커를 구입합니다.


* 1pcs High quality Waterproof Sticker For iPhone X XS MAX XR 6 6s 7 8 plus LCD Screen Tape 3M Adhesive Glue Repair Parts

https://www.aliexpress.com/item/32868448515.html



한 장에 1천원 꼴. 구입하는 김에 2장을 구입합니다. 잊어버리고 있으면 배달되는 알리 쇼핑.



조립시 편하게 접착할 수 있도록 두 겹으로 쌓여 있습니다.





3. 작업 시작


교체 작업 전에 가능한 방전을 시켜 놓습니다.

성능 최대치가 86% 이군요. 그냥 저냥 사용할 정도는 되지만, 사용 도중 갑짜기 다운 될 수도 있습니다.

올 초 추울 때, 산에 가서 사진 찍으려 하니, 조금 있다가 꺼지더군요. 이미 징조가 왔습니다. 교체가 수순입니다.



우선, 별나사를 풀어줍니다.

다음 작업이 뚜껑을 따기 위해 가열하는 것 인데, 가열 후에 나사 풀고 있으면 식어버리므로 먼저 나사를 제거합니다.



나사산이 뭉개지지 않도록 조심조심 작업합니다.



나사에서도 방수를 위한 고무가 붙어 있습니다. 확실히 방수에 많이 신경 썼군요.



실링 테이프로 강하게 접착되어 있으니, 드라이어로 녹여 주는 겁니다. 한 2분 정도 가열해 줄 필요가 있습니다.

작업 할 때, 사진 찍는 것을 잊어버려 아래는 설정샷.



빨판을 이용하여 살짝 들어주고, 조그마한 틈이 보이면 바로 헤라를 밀어 넣습니다.

상판을 빨판으로 들어 올릴 때 조금 힘이 필요하니 조심해야 합니다. 무리하게 하다가 본체가 날라가거나 추가 파손이 있을 수 있으니까요.



본체 가장자리를 빙 둘러 가면서 헤라를 전진 시킵니다. 아래 화살표 방향으로 진행합니다.

이유는 케이블 들이 아래 화살표 방향과 반대쪽에 모여 있기 때문입니다. 얇은 리본 케이블에 최대한 힘이 가해지지 않는 방법.



지지직... 하면서 방수 접착 테이프가 떨어지면서 아래와 같이 상판이 분해 됩니다.

중요한건 액정을 완전히 젖히지 않는 것. 그러다간 가느다란 리본 케이블 파손으로 이어져 액정도 교체해야 하는 상황이 발생 할 수 있습니다.


액정을 옆에 뭔가로 괴어 놓고 작업 합니다. 저는 배송된 배터리 박스를 활용.



아래 사진에서 가리키는 나사 들을 분리합니다.



나사를 제거하고, 판때기를 분리하면 액정과 연결 된 커넥터에 접근할 수 있습니다.



제일 먼저 배터리 커넥터 분리.



그 다음으로 액정과 연결된 커넥터 두 개를 분리.



윗쪽의 커넥터를 분리하기 위해 아래 사진의 나사들을 제거. 이 쪽 나사는 삼각 나사 입니다. 삼각 드라이버가 여기에 쓰이는군요.



나사와 커버를 제거하면 커넥터가 보입니다.



커넥터를 제거. 뿅~ 하고 올라옵니다.



이로써 액정과 본체가 분리 되었습니다.



여기까지 오면 전체 작업의 1/3 정도 완료.




4. 본체쪽 구성품 분리 작업


액정과 본체에 남아 있는 방수 스티커를 제거해 줍니다. 이 작업은 조립 전에 해도 상관은 없슴.



이제 본체의 부품들을 분리할 차례.

아래 사진의 나사를 제거합니다. 그 밑에는 안테나가 숨어 있습니다.



양면 테이프로 붙어 있는 부부분을 살살 달래 주면서 분리합니다.



그 다음 안테나 커넥터 부분을 분리합니다. 워낙 작은 커넥터로 연결되어 있으면서 꽉 고정되어 있는 부분이므로 살짝만 힘 줄 필요가 있슴.

절대 무리해서 분리하면 안됩니다. 지렛대처럼 뭔가를 밑에 대고 살살 들어 올려 줍니다. 어느 순간 툭 하고 올라옵니다.


사진은 없지만, 윗쪽에 본체와 연결된 커넥터도 분리해 주면 됩니다.



헵틱 엔진은 그냥 나사 분리하고 커넥터 분리하면 쉽게 제거 가능.





5. 배터리 분리


드디어 배터리를 분리할 차례. 밑바닥에 붙어 있는 양면 테이프를 살살 노출시켜 일정한 힘으로 당겨 줍니다.



이거 끊어 먹으면, 지렛대 헤라로 휘저어서 배터리를 분리해야 하므로, 숨도 쉬지 말고 일정한 힘으로 땡겨 줍니다.



저는 동봉된 드라이버에 말아서 살살 땡기면서 분리했습니다. 힘을 과하게 주지 않으면서 "일정하게" 당기는게 포인트.



이번 작업은 큰 문제 없이 깔끔하게 분리 되었네요.



본체 중앙에 무선 충전 코일이 자리잡고 있어서, 배터리 테이프는 그 부분을 피해간 모양으로 붙어 있었습니다.





6. 배터리 장착


본체와 연결할 커넥터 비교. 역시 대충 구부려진 모양입니다.



시험삼아 장착해 보니 케이블 텐션에 문제는 없어서 손대지 않고 그냥 그대로 사용.



인터넷에 나와있는 사진을 참고로 배터리 고정용 테이프의 방향을 확인해 봅니다.



요렇게 붙이면 되는군요. 배터리와 닿는 부분을 벗기고 배터리에 붙여 줍니다.



테이프 끝부분은 아래처럼 말아서 정리해 주면 됨.



그 다음, 본체와 접촉할 부분의 테이프 커버를 제거하고 본체에 안착시키면 끝.

위치를 잘 잡아야 문제가 없는데, 신경써서 작업하느라 그 부분의 사진은 없네요.



마무리 순서는, 헵틱 엔진과 안테나를 결합하고, 방수용 실링 테이프를 가장자리 모양대로 붙여준 후, 분해의 역순.




FIN


교체 후, 모든 기능 정상. 배터리의 성능도 100%.



사진 찍으며 천천히 하느라, 작업 시간은 2시간 반 걸렸네요.

iPhone 최근것 일수록 배터리 교환 작업의 난위도가 조금씩 올라가는 것이 느껴집니다. 그 만큼 기능이 추가되면서 내부가 복잡해 진 듯.


'Life' 카테고리의 다른 글

Life | 헌혈 일상기  (2) 2020.10.19
Life | 코로나19 입국자 추적 프로그램  (0) 2020.06.30
Life | 양변기 DIY 교체기  (0) 2020.05.09
Life | 항공무선통신사 도전기 - 3  (6) 2019.11.22
Life | 삼성 micro SD 카드 AS 후기  (0) 2019.11.10
And

Hardware | iPhone SE 밧데리 교환 DIY

|

1. 이번엔 iPhone SE 다~~~!!!


지금까지 iPhone 6 Plus, 6S Plus 의 배터리를 교환해 왔습니다.


* Life | iPhone 6S Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/Life-iPhone-6S-Plus-battery-replacement-DIY


* Hardware | iPhone 6 Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/iPhone-6-Plus-battery-replacement-DIY


가족이 쓰고 있는 iPhone SE 도 4년째가 되어가니 배터리 상태가 매롱합니다.

교환해 줘야겠죠?





2. 구입


기계적으로 AliExpress 에서 구입했습니다.

나중에 알게된 사실이지만, 한국 업체에서 구입하면 1만원 미만으로 구입이 가능합니다.


iPhone 6 Plus 도 그랬지만, 이번 SE 도 한국에서 직접 구입했으면 저렴하게 구할 수 있었는데, 괜히 AliExpress 만을 믿었네요.

그치만 신뢰가 높은 NOHON 제품이니 괜찮다고 자위해 봅니다.


거의 2배 가격인 2만원 정도에 구입했습니다.


* NOHON Battery For Apple iPhone SE 4S 5S 6 7 Replacement Bateria For iPhone4S iPhone6 iPhone7 Mobile Phone Batteries + Free Tools

https://www.aliexpress.com/item/NOHON-Battery-For-Apple-iPhone-SE-1624mAh-Original-Li-polymer-Battery-Internal-Battery-Free-Repair-Tools/32803100048.html







3. 도착


문제 없이 도착했습니다.

포장 딱지 붙여진 것을 보니 세관에서 한번 뜯어본것 같습니다. 아무래도 배터리류는 검사가 필요하겠죠.



반갑다 NOHON.



다른 iPhone 들과는 다르게, 대용량 버전이 없습니다.

기존 오리지날과 같은 1624 mAh 입니다.



리튬 폴리머 배터리였군요.

加强版 이라고 써 있지만, 사실 오리지날과 같은 용량입니다. (어디서 약을...)



더이상 필요 없지만, 빨판, 헤라 및 도구들 입니다.

SE 배터리는 폭이 좁아서, 양면테이프가 2줄입니다.






4. 분해


분해의 시작은, 전원 커넥터 밑부분의 별나사 두 개부터 입니다.



별나사를 제거하면, 빨판으로 상판을 끌어 당겨서 살짝 공간을 만든 뒤, 헤라로 쭉 밀고 나가면 됩니다.



다른 iPhone 버전들과는 다르게, 홈버튼과 연결된 커넥터가 밑부분에 하나 존재합니다.

그러니, 상판을 들어 올릴 때, 이 연결 부분을 해제하기 전까지는 조심해서 들어 올려야 합니다.



특이하게 홈버튼 커넥터와 본체 사이에는 아래 사진처럼 철판 쉴드가 하나 존재합니다.

핀셋같은 것으로 살짝 들어올리면, 뽕 하고 빠집니다. 어디 도망가지 못하도록 잘 보관해 놓습니다.



홈버튼 커넥터의 쉴드를 제거하고 커넥터를 제거하면, 상판 밑부분을 들어 올릴 수 있습니다.



상부 부분은 카메라 부터 여러 센서가 연결된 뭉치들이 있습니다.

이 부분도 철판 커버 벗겨내고 커넥터를 분리해 주면 됩니다.


단, 이 부분은 커넥터가 짧은지, 상판을 확 제끼면 끊어질 염려가 있으니, 되도록 최대한 낮게 상판을 들어 올려서 작업해야 합니다.

선에 힘이 걸릴까봐, 드라이버를 거의 45도 눞혀서 작업 했네요.



상판을 분리하기 위한 커넥터는 아래와 같이 3개 입니다.



짜잔~ 상하판이 분리가 되었습니다.



상판에 붙어있는 홈버튼이나 어어피스, 카메라도 나중에 문제 생기면 따로 교체할 수 있겠네요.






5. 배터리 분리


이제 배터리를 분리하기 위해, 배터리 커넥터 커버를 벗겨 냅니다.



다른 iPhone 과 조금 다르게, 접착 테이프를 제거하기 위해, 아래 사진처럼 둥그란 부분을 들어 올려서 테이프가 노출되게 해야 합니다.



요렇게요.



두 줄이 하나로 연결되어 있으니, 들어올린 부분 중간을 자르고, 잘 돌돌 말면서 제거해 줍니다.



한 쪽은 성공 했는데, 다른 쪽은 실패네요. 아놔.

힘을 줘서 배터리를 조금 구부러 뜨려야 합니다.

그러면 나머지 접착 테이프가 살짝 보이니, 보이는 부분을 땡겨서 제거하면 됩니다.



짜잔~ 분리가 되었습니다.






6. 문제 발생


새로 구입한 배터리는 오리지날과 다르게, 90도 꺾이는 부분을 일찍 꺾어 놔서 커넥터까지의 길이가 길어져버렸습니다.



무리하게 연결하면 연결은 되지만, 계속 힘을 받아 나중이 되면 문제가 자연스럽게 생기겠죠?

구부러진 부분 전체를 모두 펴고, 높이와 길이가 오리지날과 동일하게 구부려 줍니다.



작업을 하다 보면, 항상 이런 예기치 못한 사소한 문제점과 맞닥뜨리는 것 같아요.

임기응변이 필요한 부분입니다.



접착 테이프도 잘 발랐고, 잘 안착시킨 다음 조립을 해주면 됩니다.

조립은 분해의 역순입니다.





7. 완료


작업하기 전, 확인했던 배터리 성능 상태 입니다.



조금만 쓰면 금방 50% 가 되어 버렸고, 쉽게 꺼지기 일쑤였죠.



배터리 교체 후, 최고의 성능으로 다시 되돌아 왔습니다.

배터리는 소모품 맞습니다.





FIN


역시 NOHON 의 사용자 메뉴얼은 정말 친절합니다.




이런 완성도 높은 메뉴얼 같으니라구.


And

Hardware | iPhone 6 Plus 밧데리 교환 DIY

|

이번에 iPhone 6 Plus 의 밧데리를 교환할 기회가 생겨서 기록으로 남깁니다.

iPhone 6S Plus 도 한번 갈아 봤었는데, 그 이전 버전의 iPhone 을 해볼 기회가 생겼네요.


* Life | iPhone 6S Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/Life-iPhone-6S-Plus-battery-replacement-DIY





1. 밧데리 구매


처음에 AliExpress 를 뒤졌습니다.

가장 많이 구매된 제품이 아래 링크 입니다.


* Baseus Original Mobile Phone Battery For iPhone 6 6s s Plus Replacement Batterie High Capacity Internal Bateria For iPhone 6plus

https://www.aliexpress.com/item/Baseus-Original-Mobile-Phone-Battery-For-iPhone-6-6s-s-Plus-Replacement-Batterie-High-Capacity-Internal/32856181487.html



23 USD 정도군요.

혹시나 하는 마음으로 한국 사이트를 뒤져 봤습니다.


* 아이폰 5s 6 6s 7 아이폰6plus 6s plus 7plus 배터리 자가교체 아이폰6s+ 아이폰7+

https://smartstore.naver.com/sega4216/products/218691174?NaPm=ct%3Dju832v9s%7Cci%3D3848926b594dbfcca956711cb07d9f3ddea122d9%7Ctr%3Dslsl%7Csn%3D209333%7Cic%3D%7Chk%3D6818a9a50eeab8a82232280351059b2a5e40f8d4



* iPhone 6 Plus 용 대용량 베터리 : 18,000 원

* 테입 : 1,000 원

* 배송료 : 2,500 원

-------------------------------------------------

* 총 : 21,500 원


거기다 다음날 배송... 바로 주문합니다.





2. 디스플레이 접착제


iPhone 6S Plus 를 작업할 때에는 adhesive = 접착제를 따로 주문해야 했습니다.

그러나 iPhone 6 Plus, 즉 6S 이전의 제품들에는 이게 필요없다고 하네요.


* iPhone Display Adhesive Replacement

https://www.ifixit.com/Guide/iPhone+Display+Adhesive+Replacement/93983




IPX 를 올리기 위해 실링용 접착제를 사용하기 시작한 듯 합니다.

여튼 iPhone 6 Plus 는 필요 없으니 패~스.





3. 배송


저녁에 주문 넣었는데 다음날 오후에 도착했네요.

빨라서 좋지만, 택배 기사님들에게 그 댓가가 돌아가야 할 터인데요.



박스는 심플.



음? 공구는 선택하지 않았는데?

판매자님 감사합니다.



모든 구성품이 들어 있습니다. 스티커도 3줄이라서, 알리에서 파는 것보다 한가닥 더 많습니다.

이번에는 AliExpress 를 사용하지 않는게 정답이었네요.

항상 알리가 옳지는 않은것 같습니다.



대용량을 시켰더니만, 3400 mAh 짜리가 왔습니다.

예전 iPhone 6S Plus 의 대용량이 3250 mAh 인것을 상기해 보면, 그 사이에 용량을 꾸겨 넣는 기술이 더 는것 같네요.





3. 수술 집도


물건이 왔으니 수술 들어갑니다.



iPhone 6 Plus 입니다.



전원 커넥터 부분에 있는 별나사 2개를 빼면 상판을 쉽게 분리할 수 있습니다.

상판은 빨판을 이용해서 당기면 살짝 올라옵니다.


그 부분을 헤라를 집어넣고 벌리면 쉽게 분리가 되요.

수술에 집중하느라 사진은 없습니다.



상판과 연결된 커넥터들을 모두 분리하면 상하판이 완벽히 분리됩니다.



iPhone 6S Plus 와 거의 비슷하군요.



기존 밧데리가 모습을 들어 냅니다.

3.82V 로 동작하는 11.1Wh 용량입니다.

P=VI 이니, 11.1Wh / 3.82V = 2905mAh 입니다. 표기된것과 거의 비슷한 2915mAh 용량입니다.



밧데리 연결 커버를 분리합니다.



커버를 벗기면, 왼쪽 부분이 밧데리 커넥터 입니다. 이부분을 분리합니다.



하판과 밧데리를 붙여주는 접착 테이브를 벗겨 냅니다.

벗겨내는 작업은 iPhone 6S Plus 에서 했던 작업과 동일합니다.

작업하느라 사진을 못찍었는데, 내용은 같으니 아래 포스트를 참조하세요.


* Life | iPhone 6S Plus 밧데리 교환 DIY

https://chocoball.tistory.com/entry/Life-iPhone-6S-Plus-battery-replacement-DIY


두번째 했더니만, 접착제 제거시 끊어지지 않고 깔끔하게 제거했습니다.



대용량과 비교샷.

크기는 아~주 살짝 큰것 같습니다만 거의 차이나지 않습니다.

두깨도 아~주 살짝 두껍지만 전혀 간섭을 일으킬 만한 정도는 아닙니다.



교환할 새로운 밧데리에 접착 테이프를 이쁘게 바릅니다.



숨죽이며 새로운 밧데리를 본체에 잘 붙입니다.

기회는 한번 뿐이기에 미리 자리를 잘 잡아 보고, 한번에 위치시킵니다.


후훗, 두번째 교환기는 특별히 문제 없이 성공했습니다.


항상 그렇듯, 조립은 분해의 역순.

오늘도 이렇게 하루가 평화롭게 저물어 갑니다.


And

Hardware | RTC DS3231 부품 사용기 - 2

|

이 포스트는 앞전에 DS3231 을 사용해 보면서, 못다한 이야기를 하기 위해 구성했습니다.


* Hardware | RTC DS3231 부품 사용기 - 1

http://chocoball.tistory.com/entry/Hardware-RTC-usning-DS3231-1



1. AT24C32 (EEPROM) I2C address


DS3231 에 붙어있는 EEPROM 은 ATMEL 사의 AT24C32 라는 칩 입니다.

32bit = 4kByte EEPROM 의 I2C 기본 주소값은 0x57 입니다.


 

 A0

A1

A2 

0x57

0

0

0

0x56

1

0

0

0x55

0

1

0

0x54

1

1

0

0x53

0

0

1

0x52

1

0

1

0x51

0

1

1

0x50

1

1

1

* 0 = open, 1 = short


참고로 0x57 은 16진수 이므로, 10진수로 표시하고자 할 때에는 87 이라고 입력해도 됩니다.


* Hex to Decimal converter

https://www.rapidtables.com/convert/number/hex-to-decimal.html






2. 유령 I2C address - 0x5f


제가 사용한 fake DS3231 은, 사용되지 않는 "0x5f" 라는 I2C 주소가 존재합니다.



모르고 지나가기엔 너무 궁금합니다.

여러 방법으로 찾아 봤는데, 가장 신뢰성 있는 설명은 다음 LINK 인 듯 합니다.


* I2C response to "Ghost Address" 0x5F

https://electronics.stackexchange.com/questions/397569/i2c-response-to-ghost-address-0x5f



즉, 정품에 포함되어 있는 32k EEPROM 은 ATMEL 문자로 시작하는데,

이 fake 제품에 다른 chip 이 있는 것이 아니라, ATMLH745 는 address 가 두개 있는 듯 합니다.


왜냐하면, 위의 첫번째 댓글에 A2 단자를 short 시켰을때 EEPROM 주소가 바뀌는데,

이 ghost address 도 연동해서 바뀐다는 테스트 결과가 나왔거든요.


A0, A1, A2 all open (default)
--------------------------------------------
|   chip  |    DIGIT   |   HEX  |  DECIMAL |
--------------------------------------------
| AT24C32 | 0b01010111 |  0x57  |    87    |
--------------------------------------------
|  ghost  | 0b01011111 |  0x5f  |    95    |
--------------------------------------------

A0, A1 open, A2 short
--------------------------------------------
|   chip  |    DIGIT   |   HEX  |  DECIMAL |
--------------------------------------------
| AT24C32 | 0b01010011 |  0x53  |    83    |
--------------------------------------------
|  ghost  | 0b01011011 |  0x5b  |    91    |
--------------------------------------------


그럼 AT24C32 주소를 0x5f 로 해보면 어떨까요?

아래처럼 소스를 조금 바꿔 봤습니다.


#include "Wire.h"
#define AT24C32_I2C_ADDRESS 0x5f //I2C address of AT24C32

byte seconds, minutes, hours, day, date, month, year;

void setup() {
	Serial.begin(9600);
	delay(1000);
	
	Wire.begin();
}

void loop() {
	getAT24C32Data();
	
	Serial.print("seconds : "); Serial.println(seconds, BIN);
	Serial.print("minutes : "); Serial.println(minutes, BIN);
	Serial.print("hours   : "); Serial.println(hours, BIN);
	Serial.print("day     : "); Serial.println(day, BIN);
	Serial.print("date    : "); Serial.println(date, BIN);
	Serial.print("month   : "); Serial.println(month, BIN);
	Serial.print("year    : "); Serial.println(year, BIN); 
	Serial.println("");
	
	delay(1000);
}

void getAT24C32Data() {
	// send request to receive data starting at register 0
	Wire.beginTransmission(AT24C32_I2C_ADDRESS);
	Wire.write(0x00); // start at register 0
	Wire.endTransmission();
	Wire.requestFrom(AT24C32_I2C_ADDRESS, 7); // request seven bytes
	
	if(Wire.available()) {
		seconds = Wire.read(); // get seconds
		minutes = Wire.read(); // get minutes
		hours   = Wire.read(); // get hours
		day     = Wire.read();
		date    = Wire.read();
		month   = Wire.read(); //temp month
		year    = Wire.read();
	} else {
		//oh noes, no data!
	}
}


원래 AT24C32 의 주소인 0x57 를 넣으면 아래처럼 나옵니다만,

0x5f 로 하면 data 는 오는데, 전부 255 값을 갖습니다.


0x57 로 할 때



0x5f 로 할 때



엄한 어드레스인 0x83 로 할 때



값이 동일하지 않아서, 완벽히 동일한 값에 접근하는것 같지는 않습니다.

그래도 뭔가 있기는 한것 같네요.


소설을 써 보자면, 중국에서 fake 칩을 만들면서 다른 기능도 넣지 않았을까...

혹시 어떤 다른 정보와 관여하는 기능이 있는것이 아닌지?





3. Battery 의 종류


밧데리는 지금 CR2032 을 끼워서 사용하고 있습니다.

시간 유지만으로 사용되면 1uA 정도 사용되므로, 200mAh 라고 한다면 약 20년은 사용 가능하다고 하네요.


* RTCモジュール DS3231+AT24C32 ZS-042

https://blogs.yahoo.co.jp/dascomp21/68145713.html



다만, 사양적으로는 충방전이 되는 LIR2032 을 사용하라고 하네요.



실제로 약 1년정도 사용하다가 베터리가 터진 케이스가 인터넷에 보고되었습니다.


회로 구성도를 봐도, 충전이 되게끔 만들어진 회로라서 rechargeable battery 를 사용하지 않으면,

지속적으로 건전지에 부담이 가게끔 되어 있다고 합니다.



굳이 CR2025 을 장기간 사용하려 한다면, 위의 그림처럼 방충전 회로와 연결되는 패턴을 끊어주면 된다 합니다.


잠깐 쓰고 빼 놓거나, 잔량이 거의 없는거라면 괜찮겠죠?

저는 체중계에서 다 쓴 건전지를 사용하고 있어서 그냥 낑궈 놓으려고 합니다.


이 정보는 아래 사이트를 참고하였습니다.


* RTC DS3231/DS1302を調べて見ました

https://blogs.yahoo.co.jp/hobbyele/64900109.html





4. BCD


EEPROM 에 집어 넣고 빼는 값의 포맷은 decimal 이지만, 실제로 저장되는 값은 binary 나열값 입니다.


더 나아가, 이는 아래 그림처럼 EEPROM 에 저장되는 방식이 얼핏 보기에는 실제의 값을 단순히 binary 로 바꾼 값처럼 보이지만,

이 binary 값은 기능적으로 입력되어 있을 뿐, 실존하는 값과는 다른 값 입니다.


결국, 입출력은 decimal, 저장된 것은 binary, 더욱이 이 decimal / binary 가 실제의 값을 표현하지는 않다는 것이죠.


그래서 값 치환이 3번 일어나게 됩니다.

- decimal 실제 값을 EEPROM 에 저장될 binary 를 상정하여 변경 (변경 1)

- 이를 decimal 로 치환하여 EERPOM 에 전송 (변경 2)

- EEPROM 에 보내면 알아서 다시 binary 의 나열로 저장 (변경 3)


값의 format 변경은, decimal --> binary --> decimal --> binary 로 되겠죠.


왜이리 복잡하게 하는가를 생각해 보면,

EEPROM 의 address 는 직접 접근 가능하지만, 각 address 의 bit 값은 따로따로 접근을 못하며,

거기에 각 bit 가 기능적으로 정의되어 있어서, "저장된 값 = 실존하는 값" 공식이 성립하지 않기 때문 입니다.



그럼 실제 source code 에서 10의 자리와 1의 자리의 연산식이 이떻게 이루어 지는지를 확인해 보죠.

초 단위의 식은 아래와 같습니다.


seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); // convert BCD to decimal


상위 bit 부분 - 10의 자리 수 - "((seconds & B11110000)>>4)*10" 부분만을 띄어서 보면 다음과 같은 항목이 됩니다.

왼쪽부터,

- EEPROM 에서 읽어온 값 (decimal) 인 seconds

- seconds 값을 AND 연산 하면서 자동으로 binary 로 변환

- 4 bit 를 왼쪽으로 shift (날림) 를 통해 10의 자리만을 건짐

- 10 을 곱하면서 decimal 로 변경


위의 과정의 경과를 살펴보면 아래와 같겠죠.


| seconds | (BIN)seconds | seconds & B11110000 | (BIN)(seconds & B11110000) | (seconds & B11110000)>>4 | *10 |


0 | 0 | 0 | 0 | 0 | 0
1 | 1 | 0 | 0 | 0 | 0
2 | 10 | 0 | 0 | 0 | 0
3 | 11 | 0 | 0 | 0 | 0
4 | 100 | 0 | 0 | 0 | 0
5 | 101 | 0 | 0 | 0 | 0
6 | 110 | 0 | 0 | 0 | 0
7 | 111 | 0 | 0 | 0 | 0
8 | 1000 | 0 | 0 | 0 | 0
9 | 1001 | 0 | 0 | 0 | 0
16 | 10000 | 16 | 10000 | 1 | 10
17 | 10001 | 16 | 10000 | 1 | 10
18 | 10010 | 16 | 10000 | 1 | 10
19 | 10011 | 16 | 10000 | 1 | 10
21 | 10101 | 16 | 10000 | 1 | 10
22 | 10110 | 16 | 10000 | 1 | 10
23 | 10111 | 16 | 10000 | 1 | 10
24 | 11000 | 16 | 10000 | 1 | 10
25 | 11001 | 16 | 10000 | 1 | 10
32 | 100000 | 32 | 100000 | 2 | 20
33 | 100001 | 32 | 100000 | 2 | 20
34 | 100010 | 32 | 100000 | 2 | 20
35 | 100011 | 32 | 100000 | 2 | 20
36 | 100100 | 32 | 100000 | 2 | 20
37 | 100101 | 32 | 100000 | 2 | 20
38 | 100110 | 32 | 100000 | 2 | 20
39 | 100111 | 32 | 100000 | 2 | 20
40 | 101000 | 32 | 100000 | 2 | 20
41 | 101001 | 32 | 100000 | 2 | 20
48 | 110000 | 48 | 110000 | 3 | 30
49 | 110001 | 48 | 110000 | 3 | 30
50 | 110010 | 48 | 110000 | 3 | 30
51 | 110011 | 48 | 110000 | 3 | 30
52 | 110100 | 48 | 110000 | 3 | 30
53 | 110101 | 48 | 110000 | 3 | 30
54 | 110110 | 48 | 110000 | 3 | 30
55 | 110111 | 48 | 110000 | 3 | 30
56 | 111000 | 48 | 110000 | 3 | 30
57 | 111001 | 48 | 110000 | 3 | 30
64 | 1000000 | 64 | 1000000 | 4 | 40
65 | 1000001 | 64 | 1000000 | 4 | 40
66 | 1000010 | 64 | 1000000 | 4 | 40
67 | 1000011 | 64 | 1000000 | 4 | 40
68 | 1000100 | 64 | 1000000 | 4 | 40
69 | 1000101 | 64 | 1000000 | 4 | 40
71 | 1000111 | 64 | 1000000 | 4 | 40
72 | 1001000 | 64 | 1000000 | 4 | 40
73 | 1001001 | 64 | 1000000 | 4 | 40
80 | 1010000 | 80 | 1010000 | 5 | 50
81 | 1010001 | 80 | 1010000 | 5 | 50
82 | 1010010 | 80 | 1010000 | 5 | 50
83 | 1010011 | 80 | 1010000 | 5 | 50
84 | 1010100 | 80 | 1010000 | 5 | 50
85 | 1010101 | 80 | 1010000 | 5 | 50
86 | 1010110 | 80 | 1010000 | 5 | 50
87 | 1010111 | 80 | 1010000 | 5 | 50
88 | 1011000 | 80 | 1010000 | 5 | 50
89 | 1011001 | 80 | 1010000 | 5 | 50


결과적으로 10 --> 20 --> 30 --> 40 --> 50 순으로 값을 변경한다는 것을 알 수 있습니다.

보고 있으면 오묘하죠? 숫자놀이의 향연이라고 할 수 있겠습니다.






5. 알람 설정


아래는 EEPROM 에 저장된 기능별 주소록 입니다.


- datasheet : DS3231.pdf



저 위의 표를 염두에 두면서 DS3231.h 파일을 열어보면 알람의 설정방법에 대해 기술되어 있습니다.


/* Retrieves everything you could want to know about alarm
 * one. 
 * A1Dy true makes the alarm go on A1Day = Day of Week,
 * A1Dy false makes the alarm go on A1Day = Date of month.
 *
 * byte AlarmBits sets the behavior of the alarms:
 *	Dy	A1M4	A1M3	A1M2	A1M1	Rate
 *	X	1		1		1		1		Once per second
 *	X	1		1		1		0		Alarm when seconds match
 *	X	1		1		0		0		Alarm when min, sec match
 *	X	1		0		0		0		Alarm when hour, min, sec match
 *	0	0		0		0		0		Alarm when date, h, m, s match
 *	1	0		0		0		0		Alarm when DoW, h, m, s match
 *
 *	Dy	A2M4	A2M3	A2M2	Rate
 *	X	1		1		1		Once per minute (at seconds = 00)
 *	X	1		1		0		Alarm when minutes match
 *	X	1		0		0		Alarm when hours and minutes match
 *	0	0		0		0		Alarm when date, hour, min match
 *	1	0		0		0		Alarm when DoW, hour, min match
 */


자세히 보면, Alarm 1 이 초단위까지 자세하게 설정할 수 있으며,

Alarm 2 는 최소단위가 분단위임을 알 수 있습니다.

이 차이는 Alarm 1에 5개의 address 가 할당되어 있고, Alarm 2 에 4개의 address 가 할당되어 있는게 그 차이 입니다.


"DS3231.h" 에는 setA1Time, setA2TimeturnOnAlarm() 펑션이 있습니다.


File > Examples > DS3231 > DS3231_set 의 일부분이 다음과 같습니다.


		// Test of alarm functions
		// set A1 to one minute past the time we just set the clock
		// on current day of week.
		Clock.setA1Time(DoW, Hour, Minute+1, Second, 0x0, true, false, false);
		// set A2 to two minutes past, on current day of month.
		Clock.setA2Time(Date, Hour, Minute+2, 0x0, false, false, false);
		// Turn on both alarms, with external interrupt
		Clock.turnOnAlarm(1);
		Clock.turnOnAlarm(2);


이걸 이용하여 알람을 설정할 수 있습니다.

위의 source 는 특정 시간 설정 후, 1분과 2분 경과 후에 알람이 뜨도록 되어 있네요.


알람 확인은 기본으로 제공되는 다음 소스에서 확인할 수 있습니다.


File > Examples > DS3231 > DS3231_test


print 부분의 소스가 좀 부실해서 아주 쬐끔 수정 후, 표시된 내용이 아래 입니다.


2018 11 19 2 15 56 58 24h T=24.25 O+
Alarm 1: 2 DoW 15 57 0 enabled
Alarm_1 bits: 0
Alarm 2: 19 Date 15 58 enabled
Alarm_2 bits: 0

2018 11 19 2 15 56 59 24h T=24.25 O+
Alarm 1: 2 DoW 15 57 0 enabled
Alarm_1 bits: 0
Alarm 2: 19 Date 15 58 enabled
Alarm_2 bits: 0

2018 11 19 2 15 57 0 24h T=24.25 O+ A1!
Alarm 1: 2 DoW 15 57 0 enabled
Alarm_1 bits: 0
Alarm 2: 19 Date 15 58 enabled
Alarm_2 bits: 0

2018 11 19 2 15 57 2 24h T=24.25 O+
Alarm 1: 2 DoW 15 57 0 enabled
Alarm_1 bits: 0
Alarm 2: 19 Date 15 58 enabled
Alarm_2 bits: 0

......

2018 11 19 2 15 57 59 24h T=24.25 O+
Alarm 1: 2 DoW 15 57 0 enabled
Alarm_1 bits: 0
Alarm 2: 19 Date 15 58 enabled
Alarm_2 bits: 0

2018 11 19 2 15 58 0 24h T=24.25 O+ A2!
Alarm 1: 2 DoW 15 57 0 enabled
Alarm_1 bits: 0
Alarm 2: 19 Date 15 58 enabled
Alarm_2 bits: 0

2018 11 19 2 15 58 1 24h T=24.25 O+
Alarm 1: 2 DoW 15 57 0 enabled
Alarm_1 bits: 0
Alarm 2: 19 Date 15 58 enabled
Alarm_2 bits: 0


시간 설정 1분 후와 2분 후에 A1 과 A2 알람이 표시된 것을 확인할 수 있습니다.


알람 설정은, 시간 설정/표시 보다 훨씬 복잡합니다.

BCD 및 EEPROM 값에 대한 완벽한 이해가 있어야 하더군요.


소스를 새로 짤 수 있으나 너무 힘을 들이는 듯 해서,

지금까지 본것 중에 최고의 source 를 만들어 놓은 분의 website를 대신해서 기록해 봅니다.


* Arduino real time clock with alarm and temperature monitor using DS3231

https://simple-circuit.com/arduino-ds3231-real-time-clock-alarm-temperature/


이걸 만든 양반은 실제 상용으로 사용해도 될만큼 시간설정 및 알람 설정이 가능하도록 만들었습니다.

EEPROM 의 각 값들이 어떻게 사용되는지에 대한 완벽한 code 가 포함되어 있습니다.


또한 편한 library 를 사용하지 않고, 오로지 Wire.h 라이브러리만을 이용하여 직접 모든 것을 컨트롤 했습니다.


/* Arduino real time clock and calendar with 2 alarm functions and temperature monitor using DS3231
   Read DS3231 RTC datasheet to understand the code
   Time & date parameters can be set using two push buttons connected to pins 9 (B1) & 10 (B2).
   Alarm1 and alarm2 can be set using two push buttons connected to 11 (B3) & 10 (B2).
   Pin 12 becomes high when alarm occurred and button B2 returns it to low and
   turns the occurred alarm OFF.
   DS3231 interrupt pin is connected to Arduino external interrupt pin 2.
*/

// include LCD library code
#include "LiquidCrystal.h"
// include Wire library code (needed for I2C protocol devices)
#include "Wire.h"

// LCD module connections (RS, E, D4, D5, D6, D7)
LiquidCrystal lcd(3, 4, 5, 6, 7, 8);

const int button1   =  9;                   // button1 pin number
const int button2   = 10;                   // button1 pin number
const int button3   = 11;                   // button1 pin number
const int alarm_pin = 12;                   // Alarms pin number

void setup() {
  pinMode(9,  INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);
  pinMode(11, INPUT_PULLUP);
  pinMode(12, OUTPUT);
  digitalWrite(alarm_pin, LOW);
  // set up the LCD's number of columns and rows
  lcd.begin(20, 4);
  Wire.begin();                                 // Join i2c bus
  attachInterrupt(digitalPinToInterrupt(2), Alarm, FALLING);
}

// Variables declaration
bool alarm1_status, alarm2_status;
char Time[]     = "  :  :  ",
     calendar[] = "      /  /20  ",
     alarm1[]   = "A1:   :  :00", alarm2[]   = "A2:   :  :00",
     temperature[] = "T:   .   C";
byte  i, second, minute, hour, day, date, month, year,
      alarm1_minute, alarm1_hour, alarm2_minute, alarm2_hour,
      status_reg;

void Alarm(){
  digitalWrite(alarm_pin, HIGH);
}
void DS3231_read(){                             // Function to read time & calendar data
  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address
  Wire.write(0);                                // Send register address
  Wire.endTransmission(false);                  // I2C restart
  Wire.requestFrom(0x68, 7);                    // Request 7 bytes from DS3231 and release I2C bus at end of reading
  second = Wire.read();                         // Read seconds from register 0
  minute = Wire.read();                         // Read minuts from register 1
  hour   = Wire.read();                         // Read hour from register 2
  day    = Wire.read();                         // Read day from register 3
  date   = Wire.read();                         // Read date from register 4
  month  = Wire.read();                         // Read month from register 5
  year   = Wire.read();                         // Read year from register 6
}
void alarms_read_display(){                     // Function to read and display alarm1, alarm2 and temperature data
  byte control_reg, temperature_lsb;
  char temperature_msb;
  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address
  Wire.write(0x08);                             // Send register address
  Wire.endTransmission(false);                  // I2C restart
  Wire.requestFrom(0x68, 11);                   // Request 11 bytes from DS3231 and release I2C bus at end of reading
  alarm1_minute = Wire.read();                  // Read alarm1 minutes
  alarm1_hour   = Wire.read();                  // Read alarm1 hours
  Wire.read();                                  // Skip alarm1 day/date register
  alarm2_minute = Wire.read();                  // Read alarm2 minutes
  alarm2_hour   = Wire.read();                  // Read alarm2 hours
  Wire.read();                                  // Skip alarm2 day/date register
  control_reg = Wire.read();                    // Read the DS3231 control register
  status_reg  = Wire.read();                    // Read the DS3231 status register
  Wire.read();                                  // Skip aging offset register
  temperature_msb = Wire.read();                // Read temperature MSB
  temperature_lsb = Wire.read();                // Read temperature LSB
    // Convert BCD to decimal
  alarm1_minute = (alarm1_minute >> 4) * 10 + (alarm1_minute & 0x0F);
  alarm1_hour   = (alarm1_hour   >> 4) * 10 + (alarm1_hour & 0x0F);
  alarm2_minute = (alarm2_minute >> 4) * 10 + (alarm2_minute & 0x0F);
  alarm2_hour   = (alarm2_hour   >> 4) * 10 + (alarm2_hour & 0x0F);
    // End conversion
  alarm1[8]     = alarm1_minute % 10  + 48;
  alarm1[7]     = alarm1_minute / 10  + 48;
  alarm1[5]     = alarm1_hour   % 10  + 48;
  alarm1[4]     = alarm1_hour   / 10  + 48;
  alarm2[8]     = alarm2_minute % 10  + 48;
  alarm2[7]     = alarm2_minute / 10  + 48;
  alarm2[5]     = alarm2_hour   % 10  + 48;
  alarm2[4]     = alarm2_hour   / 10  + 48;
  alarm1_status = bitRead(control_reg, 0);      // Read alarm1 interrupt enable bit (A1IE) from DS3231 control register
  alarm2_status = bitRead(control_reg, 1);      // Read alarm2 interrupt enable bit (A2IE) from DS3231 control register
  if(temperature_msb < 0){
    temperature_msb = abs(temperature_msb);
    temperature[2] = '-';
  }
  else
    temperature[2] = ' ';
  temperature_lsb >>= 6;
  temperature[4] = temperature_msb % 10  + 48;
  temperature[3] = temperature_msb / 10  + 48;
  if(temperature_lsb == 0 || temperature_lsb == 2){
    temperature[7] = '0';
    if(temperature_lsb == 0) temperature[6] = '0';
    else                     temperature[6] = '5';
  }
  if(temperature_lsb == 1 || temperature_lsb == 3){
    temperature[7] = '5';
    if(temperature_lsb == 1) temperature[6] = '2';
    else                     temperature[6] = '7';
  }
  temperature[8]  = 223;                        // Put the degree symbol
  lcd.setCursor(10, 0);
  lcd.print(temperature);                       // Display temperature
  lcd.setCursor(0, 2);
  lcd.print(alarm1);                            // Display alarm1
  lcd.setCursor(17, 2);
  if(alarm1_status)  lcd.print("ON ");          // If A1IE = 1 print 'ON'
  else               lcd.print("OFF");          // If A1IE = 0 print 'OFF'
  lcd.setCursor(0, 3);
  lcd.print(alarm2);                            // Display alarm2
  lcd.setCursor(17, 3);
  if(alarm2_status)  lcd.print("ON ");          // If A2IE = 1 print 'ON'
  else               lcd.print("OFF");          // If A2IE = 0 print 'OFF'
}
void calendar_display(){                        // Function to display calendar
  switch(day){
    case 1:  strcpy(calendar, "Sun   /  /20  "); break;
    case 2:  strcpy(calendar, "Mon   /  /20  "); break;
    case 3:  strcpy(calendar, "Tue   /  /20  "); break;
    case 4:  strcpy(calendar, "Wed   /  /20  "); break;
    case 5:  strcpy(calendar, "Thu   /  /20  "); break;
    case 6:  strcpy(calendar, "Fri   /  /20  "); break;
    case 7:  strcpy(calendar, "Sat   /  /20  "); break;
    default: strcpy(calendar, "Sat   /  /20  ");
  }
  calendar[13] = year  % 10 + 48;
  calendar[12] = year  / 10 + 48;
  calendar[8]  = month % 10 + 48;
  calendar[7]  = month / 10 + 48;
  calendar[5]  = date  % 10 + 48;
  calendar[4]  = date  / 10 + 48;
  lcd.setCursor(0, 1);
  lcd.print(calendar);                          // Display calendar
}
void DS3231_display(){
  // Convert BCD to decimal
  second = (second >> 4) * 10 + (second & 0x0F);
  minute = (minute >> 4) * 10 + (minute & 0x0F);
  hour = (hour >> 4) * 10 + (hour & 0x0F);
  date = (date >> 4) * 10 + (date & 0x0F);
  month = (month >> 4) * 10 + (month & 0x0F);
  year = (year >> 4) * 10 + (year & 0x0F);
  // End conversion
  Time[7]     = second % 10  + 48;
  Time[6]     = second / 10  + 48;
  Time[4]     = minute % 10  + 48;
  Time[3]     = minute / 10  + 48;
  Time[1]     = hour   % 10  + 48;
  Time[0]     = hour   / 10  + 48;
  calendar_display();                           // Call calendar display function
  lcd.setCursor(0, 0);
  lcd.print(Time);                              // Display time
}
void Blink(){
  byte j = 0;
  while(j < 10 && (digitalRead(button1) || i >= 5) && digitalRead(button2) && (digitalRead(button3) || i < 5)){
    j++;
    delay(25);
  }
}
byte edit(byte x, byte y, byte parameter){
  char text[3];
  while(!digitalRead(button1) || !digitalRead(button3));    // Wait until button B1 is released
  while(true){
    while(!digitalRead(button2)){                           // If button B2 is pressed
      parameter++;
      if(((i == 0) || (i == 5)) && parameter > 23)          // If hours > 23 ==> hours = 0
        parameter = 0;
      if(((i == 1) || (i == 6)) && parameter > 59)          // If minutes > 59 ==> minutes = 0
        parameter = 0;
      if(i == 2 && parameter > 31)                          // If date > 31 ==> date = 1
        parameter = 1;
      if(i == 3 && parameter > 12)                          // If month > 12 ==> month = 1
        parameter = 1;
      if(i == 4 && parameter > 99)                          // If year > 99 ==> year = 0
        parameter = 0;
      if(i == 7 && parameter > 1)                           // For alarms ON or OFF (1: alarm ON, 0: alarm OFF)
        parameter = 0;
      lcd.setCursor(x, y);
      if(i == 7){                                           // For alarms ON & OFF
        if(parameter == 1)  lcd.print("ON ");
        else                lcd.print("OFF");
      }
      else{
        sprintf(text,"%02u", parameter);
        lcd.print(text);
      }
      if(i >= 5){
        DS3231_read();                          // Read data from DS3231
        DS3231_display();                       // Display DS3231 time and calendar
      }
      delay(200);                               // Wait 200ms
    }
    lcd.setCursor(x, y);
    lcd.print("  ");                            // Print two spaces
    if(i == 7) lcd.print(" ");                  // Print space (for alarms ON & OFF)
    Blink();                                    // Call Blink function
    lcd.setCursor(x, y);
    if(i == 7){                                 // For alarms ON & OFF
      if(parameter == 1)  lcd.print("ON ");
      else                lcd.print("OFF");
    }
    else{
      sprintf(text,"%02u", parameter);
      lcd.print(text);
    }
    Blink();
    if(i >= 5){
      DS3231_read();
      DS3231_display();}
    if((!digitalRead(button1) && i < 5) || (!digitalRead(button3) && i >= 5)){
      i++;                                      // Increment 'i' for the next parameter
      return parameter;                         // Return parameter value and exit
    }
  }
}

void loop() {
  if(!digitalRead(button1)){                    // If B1 button is pressed
      i = 0;
      hour   = edit(0, 0, hour);
      minute = edit(3, 0, minute);
      while(!digitalRead(button1));             // Wait until button B1 released
      while(true){
        while(!digitalRead(button2)){           // If button B2 button is pressed
          day++;                                // Increment day
          if(day > 7) day = 1;
          calendar_display();                   // Call display_calendar function
          lcd.setCursor(0, 1);
          lcd.print(calendar);                  // Display calendar
          delay(200);
        }
        lcd.setCursor(0, 1);
        lcd.print("   ");                       // Print 3 spaces
        Blink();
        lcd.setCursor(0, 1);
        lcd.print(calendar);                    // Print calendar
        Blink();                                // Call Blink function
        if(!digitalRead(button1))               // If button B1 is pressed
          break;
      }
      date = edit(4, 1, date);                  // Edit date
      month = edit(7, 1, month);                // Edit month
      year = edit(12, 1, year);                 // Edit year
      // Convert decimal to BCD
      minute = ((minute / 10) << 4) + (minute % 10);
      hour = ((hour / 10) << 4) + (hour % 10);
      date = ((date / 10) << 4) + (date % 10);
      month = ((month / 10) << 4) + (month % 10);
      year = ((year / 10) << 4) + (year % 10);
      // End conversion
      // Write time & calendar data to DS3231 RTC
      Wire.beginTransmission(0x68);             // Start I2C protocol with DS3231 address
      Wire.write(0);                            // Send register address
      Wire.write(0);                            // Reset sesonds and start oscillator
      Wire.write(minute);                       // Write minute
      Wire.write(hour);                         // Write hour
      Wire.write(day);                          // Write day
      Wire.write(date);                         // Write date
      Wire.write(month);                        // Write month
      Wire.write(year);                         // Write year
      Wire.endTransmission();                   // Stop transmission and release the I2C bus
      delay(200);
    }
    if(!digitalRead(button3)){                  // If B3 button is pressed
      while(!digitalRead(button3));             // Wait until button B3 released
      i = 5;
      alarm1_hour   = edit(4,  2, alarm1_hour);
      alarm1_minute = edit(7,  2, alarm1_minute);
      alarm1_status = edit(17, 2, alarm1_status);
      i = 5;
      alarm2_hour   = edit(4,  3, alarm2_hour);
      alarm2_minute = edit(7,  3, alarm2_minute);
      alarm2_status = edit(17, 3, alarm2_status);
      alarm1_minute = ((alarm1_minute / 10) << 4) + (alarm1_minute % 10);
      alarm1_hour   = ((alarm1_hour   / 10) << 4) + (alarm1_hour % 10);
      alarm2_minute = ((alarm2_minute / 10) << 4) + (alarm2_minute % 10);
      alarm2_hour   = ((alarm2_hour   / 10) << 4) + (alarm2_hour % 10);
      // Write alarms data to DS3231
      Wire.beginTransmission(0x68);               // Start I2C protocol with DS3231 address
      Wire.write(7);                              // Send register address (alarm1 seconds)
      Wire.write(0);                              // Write 0 to alarm1 seconds
      Wire.write(alarm1_minute);                  // Write alarm1 minutes value to DS3231
      Wire.write(alarm1_hour);                    // Write alarm1 hours value to DS3231
      Wire.write(0x80);                           // Alarm1 when hours, minutes, and seconds match
      Wire.write(alarm2_minute);                  // Write alarm2 minutes value to DS3231
      Wire.write(alarm2_hour);                    // Write alarm2 hours value to DS3231
      Wire.write(0x80);                           // Alarm2 when hours and minutes match
      Wire.write(4 | alarm1_status | (alarm2_status << 1));      // Write data to DS3231 control register (enable interrupt when alarm)
      Wire.write(0);                              // Clear alarm flag bits
      Wire.endTransmission();                     // Stop transmission and release the I2C bus
      delay(200);                                 // Wait 200ms
    }
    if(!digitalRead(button2) && digitalRead(alarm_pin)){         // When button B2 pressed with alarm (Reset and turn OFF the alarm)
      digitalWrite(alarm_pin, LOW);               // Turn OFF the alarm indicator
      Wire.beginTransmission(0x68);               // Start I2C protocol with DS3231 address
      Wire.write(0x0E);                           // Send register address (control register)
      // Write data to control register (Turn OFF the occurred alarm and keep the other as it is)
      Wire.write(4 | (!bitRead(status_reg, 0) & alarm1_status) | ((!bitRead(status_reg, 1) & alarm2_status) << 1));
      Wire.write(0);                              // Clear alarm flag bits
      Wire.endTransmission();                     // Stop transmission and release the I2C bus
    }
    DS3231_read();                                // Read time and calendar parameters from DS3231 RTC
    alarms_read_display();                        // Read and display alarms parameters
    DS3231_display();                             // Display time & calendar
    delay(50);                                    // Wait 50ms
}
// End of code


이렇게 긴 source 는 붙여넣기 하면 이쁘지 않지만, 너무 잘 짠 코드라 여기에 남깁니다.





6. Square Wave - 정현파 만들기


RTC에 왠 정현파 재조기 인가 하는데, 시간은 정확한 oscillator 를 사용하므로,

square wave 를 정확하게 만들 수 있는 기능이 있습니다.


만들 수 있는 주파수는 다음과 같습니다.

- 1.024kHz

- 4.096kHz

- 8.192kHz

- 32.768kHz


source 는 Example 에 올라와 있는 내용을 그대로 사용해 봤습니다.


File > Examples > DS3231 > DS3231_oscillator_test


		// Oscillator functions

		void enableOscillator(bool TF, bool battery, byte frequency); 
			// turns oscillator on or off. True is on, false is off.
			// if battery is true, turns on even for battery-only operation,
			// otherwise turns off if Vcc is off.
			// frequency must be 0, 1, 2, or 3.
			// 0 = 1 Hz
			// 1 = 1.024 kHz
			// 2 = 4.096 kHz
			// 3 = 8.192 kHz (Default if frequency byte is out of range);
		void enable32kHz(bool TF); 
			// Turns the 32kHz output pin on (true); or off (false).
		bool oscillatorCheck();;
			// Checks the status of the OSF (Oscillator Stop Flag);.
			// If this returns false, then the clock is probably not
			// giving you the correct time.
			// The OSF is cleared by function setSecond();.


마침 DSO150 이라는 DIY oscilloscope 를 만들어 놓은 것이 있네요.


* Hardware | DSO150 Oscilloscope

http://chocoball.tistory.com/entry/HardwareDSO150Oscilloscope


SQW 에 DSO150 을 연결해서 확인해 봅니다.

신기하게도 정현파가 잘 뜨네요.



단, 32kHz 는 높은 주파수라서 그런지 32K 단자에서 따로 검출할 수 있습니다.






7. 시간 표시를 2 digit 로 바꾸기


시간, 분, 초의 표시가 10자리 밑이면 한자리 값으로만 나옵니다.

6초면 "06"이 아니라 "6" 으로 표시되면서 자리 위치가 자꾸 바뀌는게 마음에 들지 않습니다.



값을 EEPROM 에서 리턴 받으면 10 이하일 경우 "0" 을 삽입해 주는 코드를 추가하여 아래와 같이 수정했습니다.


#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
 
Adafruit_SSD1306 display = Adafruit_SSD1306();
  
#define DS3231_I2C_ADDRESS 104
 
// SCL - pin A5
// SDA - pin A4
// To set the clock, run the sketch and use the serial monitor.
// Enter T1124154091014; the code will read this and set the clock. See the code for full details.
 
byte seconds, minutes, hours, day, date, month, year;
char weekDay[4];
 
byte tMSB, tLSB;
float temp3231;

String T_seconds, T_minutes, T_hours, D_date, D_month, D_year;
 
void setup() {
  Serial.begin(9600);
   
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);  // initialize with the I2C addr 0x3C (for the 128x32)
  display.clearDisplay();
  display.display();
  delay(1000);
 
  Wire.begin();
}
 
void loop() {
  watchConsole();
   
  get3231Date();
   
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.setTextSize(1);

  if (seconds < 10) { T_seconds = "0" + String(seconds, DEC);} else {T_seconds = String(seconds, DEC);}
  if (minutes < 10) { T_minutes = "0" + String(minutes, DEC);} else {T_minutes = String(minutes, DEC);}
  if (hours < 10) { T_hours = "0" + String(hours, DEC);} else {T_hours = String(hours, DEC);}
  if (date < 10) { D_date = "0" + String(date, DEC);} else {D_date = String(date, DEC);}
  if (month < 10) { D_month = "0" + String(month, DEC);} else {D_month = String(month, DEC);}
  if (year < 10) { D_year = "0" + String(year, DEC);} else {D_year = String(year, DEC);}
  
  display.print("DATE : "); display.print(weekDay); display.print(", "); display.print(D_date); display.print("/"); display.print(D_month); display.print("/"); display.println(D_year);
  display.print("TIME : "); display.print(T_hours); display.print(":"); display.print(T_minutes); display.print(":"); display.println(T_seconds);
  display.print("TEMP : "); display.println(get3231Temp());
  display.display();
   
  delay(1000);
}
 
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val) {
  return ( (val/10*16) + (val%10) );
}
 
void watchConsole() {
   
  if (Serial.available()) { // Look for char in serial queue and process if found
    if (Serial.read() == 84) { //If command = "T" Set Date
      set3231Date();
      get3231Date();
      Serial.println(" ");
    }
  }
}
  
void set3231Date() {
  //T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year)
  //T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99)
  //Example: 02-Feb-09 @ 19:57:11 for the 3rd day of the week -> T1157193020209
  // T1124154091014
  seconds = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
  minutes = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hours   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  day     = (byte) (Serial.read() - 48); // set day of week (1=Sunday, 7=Saturday)
  date    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  year    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
   
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x00);
  Wire.write(decToBcd(seconds));
  Wire.write(decToBcd(minutes));
  Wire.write(decToBcd(hours));
  Wire.write(decToBcd(day));
  Wire.write(decToBcd(date));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}
 
void get3231Date() {
  // send request to receive data starting at register 0
  Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
  Wire.write(0x00); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes
   
  if(Wire.available()) {
    seconds = Wire.read(); // get seconds
    minutes = Wire.read(); // get minutes
    hours   = Wire.read(); // get hours
    day     = Wire.read();
    date    = Wire.read();
    month   = Wire.read(); //temp month
    year    = Wire.read();

    seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); // convert BCD to decimal
    minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); // convert BCD to decimal
    hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111)); // convert BCD to decimal (assume 24 hour mode)
    day     = (day & B00000111); // 1-7
    date    = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31
    month   = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
    year    = (((year & B11110000)>>4)*10 + (year & B00001111));
  } else {
    //oh noes, no data!
  }
   
  switch (day) {
    case 1:
      strcpy(weekDay, "Sun");
      break;
    case 2:
      strcpy(weekDay, "Mon");
      break;
    case 3:
      strcpy(weekDay, "Tue");
      break;
    case 4:
      strcpy(weekDay, "Wed");
      break;
    case 5:
      strcpy(weekDay, "Thu");
      break;
    case 6:
      strcpy(weekDay, "Fri");
      break;
    case 7:
      strcpy(weekDay, "Sat");
      break;
  }
}
 
float get3231Temp() {
  //temp registers (11h-12h) get updated automatically every 64s
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
   
  if(Wire.available()) {
    tMSB = Wire.read(); //2's complement int portion
    tLSB = Wire.read(); //fraction portion
     
    temp3231 = (tMSB & B01111111); //do 2's math on Tmsb
    temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
  } else {
    //oh noes, no data!
  }
  return temp3231;
}


10보다 작은 수가 오면 자동으로 "0" 을 붙여주게 되었습니다.



요일 값을 year / month / date 값을 이용하여 자동으로 연산하여 넣어줄 수 있도록 할 수도 있습니다만,

너무 복잡해 지므로 관련해서 코드를 짠 분의 site 를 링크해 놓습니다.


* Day of the Week calculator

https://www.hackster.io/erikuchama/day-of-the-week-calculator-cde704






8. DS3231 내부 온도 센서와 BME280 센서와 비교


예전에 온도 전용 센서인 BME280 을 이용하여 측정해 본 경험이 있습니다.


* Hardware | BME280 sensor

http://chocoball.tistory.com/entry/HardwareBME280


DS3231 내부 온도센서의 정확성 비교를 위해 하룻저녁 두개를 같이 측정해 봤습니다.



꽤나 근접하네요.


DS3231 의 결과값에 일괄적으로 +0.25 를 했더니만 이제 좀 비슷해 진것 같습니다.

그 결과 그래프가 아래 그림입니다. 최종적으로는 +0.3 정도가 가장 적당해 보이네요.



DS3231 내부 온도센서의 정확성을 위해,

추출한 값을 100 곱한 다음, 마지막에 100 으로 나누는 방식을 채용하여 측정하였습니다.


* How to read DS3231 Internal temperature sensor, example code

http://forum.arduino.cc/index.php?topic=262986.15


아래 참고한 사이트를 보면 DS3231 을 가지고 온갖 할 수 있는 일을 다하는 사람의 글 입니다.


* Using a $1 DS3231 Real-time Clock Module with Arduino

https://thecavepearlproject.org/2014/05/21/using-a-cheap-3-ds3231-rtc-at24c32-eeprom-from-ebay/


최종 비교를 위해 사용된 sketch 는 다음과 같습니다.


#include "Wire.h"
#include "SPI.h"
#include "Adafruit_Sensor.h"
#include "Adafruit_BME280.h"

#define BME_SCK 13
#define BME_MISO 12
#define BME_MOSI 11
#define BME_CS 10

Adafruit_BME280 BME;
   
const int DS3231_RTC_ADDR = 0x68;
const int DS3231_TEMP_MSB = 0x11;
union int16_byte {
  int i;
  byte b[2];
} rtcTemp;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  BME.begin();
}

void loop() {
   Wire.beginTransmission(DS3231_RTC_ADDR);
   Wire.write(DS3231_TEMP_MSB);
   Wire.endTransmission();
   Wire.requestFrom(DS3231_RTC_ADDR, 2);
   rtcTemp.b[1] = Wire.read(); 
   rtcTemp.b[0] = Wire.read();
   long tempC100 = (rtcTemp.i >> 6) * 25;    //degrees celsius times 100
   Serial.print( tempC100 / 100 );
   Serial.print( '.' );
   Serial.print( abs(tempC100 % 100) );
   
   Serial.print("\t");
   Serial.println(BME.readTemperature());

   delay(1000);
}





FIN


이번에 DS3231 을 가지고 놀면서 대학때 배운 BCD 도 다시 해보고,

EEPROM 에 대한 address 방식 등에 대해서도 배울 수 있어서 좋았습니다....

만, 배울게 너무 많아서 힘들었습니다.


당연히 지금껏 사용해본 sensor 중에는 활용도와 배울 점으로는 단연 top 입니다.

관련해서 전문가들도 온갖 기술을 구현해 놨고... 정말 변태같은 sensor 인듯 합니다.

(datasheet 를 보면 뭔가 더 많은데, 여기서 그만 하려구요.)


And

Life | iPhone 6S Plus 밧데리 교환 DIY

|

1. 내가 조루라니


그렇습니다. iPhone 6S Plus 를 2년 이상 사용하다 보니,

밧데리 충전 가능 용량이 2750mAh --> 1800mAh 로 확연히 떨어졌습니다.


매번 기회 있을 때마다 충전을 해야 하고, 반나절도 못가는 상태가 되었습니다.



밧데리 대란으로 정식 AS 센터에서 3만 7천원이라고 합니다.




2. 밧데리


알리익스프레스에서 검색해 봅니다.

원래 정품은 2750mAh 지만, 3250mAh 짜리 고용량이 있네요.


상품평이 괜찮아서 조금 가격이 있지만, 3250mAh 로 결정했습니다.


* Original NOHON Battery For iPhone 6S Plus 6SPlus Li-ion Replacement Batteries 3250mAh High Capacity Retail Package

https://www.aliexpress.com/item/NEW-Arrival-Original-NOHON-Battery-For-iPhone-6S-Plus-6SPlus-Li-ion-Replacement-Batteries-3250mAh-High/32809041799.html



배달은 한 2주 된것 같습니다.

포장은 특별히 문제 없이 뽁뽁이 봉투에 넣어서 배달되었습니다.



구성품은 헤라, 빨판, 드라이버, 소켓 분리 툴, 접착 테이프, 그리고 밧데리 입니다.



밧데리 샷 입니다.



보증기한이 6개월인데, 이게 고장나면 아예 폰이 타버리겠죠?

용량이 3250mAh 라고 쓰여 있습니다.



그냥 뒷면샷 입니다.



자세히 보면, 테이핑 마무리 등은 정품이 좀더 깔끔한것 같습니다.




2. 방수 점착제


밧데리 동영상 등을 보면, 상판을 뜻을 때, 방수용 점착제가 같이 뜯어져 나오는 장면들이 많습니다.


일반적인 동영상을 보면 이 부분을 다시 보충해 주는 정보가 없지만,

확실히 다시 보충해 줘야 하는 부분이라고 생각하고 따로 구입했습니다.


* 2x original Waterproof Adhesive Glue Tape Sticker For iPhone 6S 6SP 7 7P plus Front Housing LCD Touch Screen Frame tracking code

https://www.aliexpress.com/item/2x-original-Waterproof-Adhesive-Glue-Tape-Sticker-For-iPhone-6S-6SP-7-7P-plus-Front-Housing/32801683330.html



2장이 한세트이니, 한번 실패해도 안심입니다.



포장은 얇은 박스로 왔네요.

전혀 구겨질 수 없도록 일반 포장지가 아니고 박스로 오는게 믿음이 갑니다.



이렇게 두장 들어 있습니다.




3. 교환 방법 공부


iPhone 6S Plus 의 밧데리 교환방법이 가장 잘 설명된 Youtube 동영상 입니다.


* Tutorial: Detailed step by step Battery Replacement Guide for iPhone 6S (Plus)

https://www.youtube.com/watch?v=doubGxWEUtw


어느부분을 주의해야 하는지라던가, 접착 테이브 붙이는 방법, 점검법, 그리고 실링 점착제 붙이는 방법 등,

가장 잘 설명해 주는 동영상인듯 합니다.


밑에는 AliExpress 사이트의 제품 설명 화면들 입니다.

실링 점착제 붙이는 부분은 빠져 있지만, 전반적으로 잘 설명되어 있습니다. 




흠흠.... 이렇게 하면 되는군요.




4. 분해 - 상판


이제 본격적으로 분해를 시작해 봅니다.


우선, 헤어드라이어기로 iPhone 의 가상자리를 달구어 줍니다.

한 2분정도면 충분할것 같습니다.


충분히 달구지 않으면 상하판을 잡고 있는 점착제가 딱딱한 상태라서 힘을 많이 주게 되므로 파손의 위험이 있습니다.

점착제가 유들유들하게 만드는게 포인트 입니다.



충분히 달구며 바로 온도가 떨어지지 않습니다.



동그라미 부분의 별나사를 살폿이 풀어줍니다.



위의 사진처럼 빨판을 살짝 윗쪽에 붙여서 들어 올립니다.

들어 올리는 부분에 간격이 생기면 거기에 헤라를 집어 넣어서 점점 더 벌여주기 시작합니다.



빨판 위치를 다시 살짝 옮겨, 그 부분을 들어 올리면서 벌려 줍니다.

이렇게 하면, "지지직" 하면서 점착제로부터 상하판이 분리되면서 벌어집니다.



너무 힘을 많이 주지 않고, 벌리는게 뽀인트 입니다.

90도 각도를 유지합니다. 확 꺾어버리면, 커넥터가 손상되므로 특별히 주의해야 합니다.



위의 사각진 부분의 상판에서 나사 5개를 풀고 커넥터를 분리합니다.



이로써 상판 분리가 끝났습니다.



분리 후의 모습입니다. 깔끔하게 잘 만들었네요.

6S Plus 라서 그런지 공간이 조금 넉넉해 보입니다.



상판 뒷면입니다.




5. 분해 - 밧데리


이제 밧데리를 분리할 차례 입니다.



드라이기로 또한 충분히 달구워 줍니다.



위 사진의 동그라미 2개 나사를 분리하여, 밧데리 커넥터가 있는 커버를 제거합니다.

이제 밧데리 커넥터를 분리할 수 있습니다.



작업하느라 사진 찍는걸 잊어버렸습니다.

밧데리 밑부분에 접착 테이프를 당겨서 빼내는 부분이 있습니다.


3개 중, 가장 오른쪽 부분은 이쁘게 분리했지만, 다른 두 부분이 아직 붙어 있어서,

분리된 부분의 밧데리를 꺾고, 드라이버를 집어 넣어서 접착 테이프를 돌돌 말아서 제거해 줍니다.






6. 새 밧데리 장착


접착 테이프는 윗부분에 살짝 먼저 붙여 놓고... 



뒤로 꺽어서 실링을 제거하고 붙입니다.



마무리 부분에서 실링 커버가 조금 튀었더니 끝부분에 붙어서 절대 떨어지지 않더군요.



할 수 없이 저 부분은 잘라 냈습니다. 강력한 접착제네요.



잘 장착 되었습니다.

밧데리 커넥터를 채결하고 커버를 드라이버로 고정 하면, 이제 상판을 붙일 차례 입니다.



상판 붙이기 전에 방수 점착제를 먼저 정렬해서 붙여 놓습니다.



밑에부터 붙인 다음, 양 옆을 태두리를 신경쓰면서 위에까지 덮어 줍니다.

손톱으로 잘 접착되도록 눌러줍니다.


이제 분리의 역순으로 상판을 채결해 줍니다. (사진 無)





7. 결과


특별한 문제 없이 잘 교체 되었습니다.



3250mAh 를 구매했지만, 인식은 3300mAh 네요.

한가지 더, 실제 전압이 3.80V --> 4.28V 로 바뀌었습니다.


이제 한번 충전으로 하루정도는 버티겠네요. 뭔가 기분이 개운해졌습니다.


총 비용은, 23.65 + 3.06 USD = 26.71 USD = 28,800 원 정도 합니다.

서비스 비용인 3만 7천원보다는 1만원 싸게 하면서 대용량으로 바꿀 수 있었네요.


다만, 기다림, 작업 시간, 준비, 실패할 확률 등을 감안하면, 3만 7천원이 비싼게 아니라는 것을 알 수 있습니다.




FIN


NOHON 제품 사용 설명서 사진입니다.



각종 그림과 자세한 설명으로 많은 도움이 되었습니다.



이렇게 친절한 설명서는 처음인듯 해요...


And

Hardware | bGeigie Nano 의 battery 를 업그레이드 해보자

|

1. 시작


bGeigie Nano 가 무엇인지, 어떻게 조립했는지는 아래 link 들을 참조하세요.


* Safecast bGeigie Nano 를 조립해 보자 - 1

http://chocoball.tistory.com/entry/Hardware-Safecast-bGeigie-Nano-1


* Safecast bGeigie Nano 를 조립해 보자 - 2

http://chocoball.tistory.com/entry/Hardware-Safecast-bGeigie-Nano-2


bGeigie Nano 를 조립하면서 설명서를 보면, battery 가 기존 2000mAh 에서 1200mAh 로 바뀐 것을 알게 됩니다.


https://github.com/Safecast/bGeigieNanoKit/wiki/Assembly-Manual



제작자에게 문의한 결과 battery 수급 문제와 두께로 인한 문제를 언급하고 있습니다.


https://groups.google.com/forum/#!searchin/safecast-devices/battery|sort:date/safecast-devices/DSUfd7i8IUQ/G6Hjsrn-BwAJ


이게 충전을 하고 가지고 다니는 것이라, 가능하면 큰 용량의 battery 를 사용하는게 좋을것 같았습니다.

아래는 기존 battery 사진입니다.



두꺼운 전선과 Li-Ion 충방전에 필요한 보호회로가 붙어 있습니다.

이 대용품을 찾아야 합니다.




2. 고용량 제품 찾기


한국내에서 제품을 찾기도 쉽지 않을 뿐더러, battery 제품은 가격이 비쌉니다.

AliExpress 에서 폭풍검색 합니다.


몇몇 제품이 물망에 올랐지만, bGeigie Nano 에 잘 수납되어야 하고, 용량이 2000mAh 이상인 것을 계속해서 찾던 중,

아래 제품을 알게 됩니다.


* 3.7V 2500mAh polymer lithium ion battery


https://ko.aliexpress.com/item/3-7V-2500mAh-645455-polymer-lithium-ion-Li-ion-battery-for-mp3-mp4-tablet-pc-DVD/32797293075.html



크기가 확신할 수는 없었지만, 기존의 battery 의 폭과 두께가 크게 차이나지 않을것 같았습니다.

7.14 USD 는 정말 매력적인 가격이 아닐 수 없습니다.




3. 도착


배송 완료까지 거의 1달 걸렸습니다.

Battery 라서 좀 까다로왔는지 모르겠습니다.

배송 추적을 해 보면, Turkey 에 보내졌다고 나왔는데, 어느샌가 저의 주소로 배달되었습니다.



예상했던 그대로 배송이 되었습니다.



막상 upgrade 를 할 수 있다는 마음에 매우 흥분되었습니다.

오오오~~~!!! 대용량 battery 다!



bGeigie Nano 보드에 올려 봅니다.

크기가 정말 딱 맞습니다. 거의 여유공간은 없이 들어갑니다.


제작자가 이야기 했듯, 날카롭게 쏫아 오른 납땜 부분이 battery 를 찔러서 터질 수 있으니,

동봉되어 있던 쿠션용 스폰지를 붙여 놓은 플라스틱 보드지가 두껍고 딱 크기가 좋아서 바로 뒷에 덧대어 줍니다.



이렇게 맞춤일수가.



두께도 적당합니다. 쿠션 테이프까지 붙이고 나사를 조이면, 확실하게 고정이 됩니다.

완벽하게 고정되는 순간입니다.





4. Connector


여기서 문제가 생깁니다.

위의 사진에서도 알 수 있듯이 선만 달랑 있고, 기판과 연결되는 connector 가 없습니다.


Connector 의 사양 확인해야 하는데, 베니어 켈리퍼로 칫수를 측정해도 아주 미묘한 차이인지라 어떤것을 주문해야 할지 난감했습니다.



AliExpress 의 여러 판매자 제품들을 보니, 대략 위의 규격중에 하나라는 것을 알게 되었습니다.

처음에는 XH 2.54mm 가 아닐까 했습니다만, 확신할 수 없었습니다.


그래서 처음부터 동봉되어 있는 battery의 connector 를 뚤어져라 보았죠. 뭔가 있을것 같았습니다.



그렇습니다. 뭔가 적혀있었어요. "H JS" !!!


또한, 이 bGeigie Nano 에 들어가는 부품들은 OLED 모니터부터 Bluetooth 모듈까지 SparkFun 회사꺼를 많이 사용합니다.

그럼 혹시...?


SparkFun 에서 취급하는 Connector 를 찾아봅니다. Bingo!

SparkFun 은 JST 규격의 2.0mm 제품을 선호한다고 나와 있습니다.

그리고 친절하게도 JST 2.0mm 는 PH 두개의 극을 가지는 것과 같다는 것도 나와 있었습니다.


* Power Connectors

https://learn.sparkfun.com/tutorials/connector-basics/power-connectors




정리하자면, JST 2.0mm = PH 2-pin connector 라는 것이였습니다.

한달 기다렸는데 좀더 기다리죠 뭐. Connector 도 주문을 합니다.



* JST 2.0 PH 2-Pin Connector


https://ko.aliexpress.com/item/50-SETS-Mini-Micro-JST-2-0-PH-2-Pin-Connector-Plug-with-Wires-Cables-120MM/32824363436.html



한 3주 걸려서 도착했습니다.

도대체 이거 하나 upgrade 하는데 얼마나 걸리는지 모르겠습니다. (거의 2달)



커넥터의 모양을 요리조리 살펴 봅니다.



흠흠 맞는것 같네요.



Female connector 에 고정되는 돌기도 잘 구현되어 있습니다.



실제로 bGeigie Nano 에 연결해 봅니다.



딱 맞군요!



분리시, 손톱을 거는 돌기가 정품보다 작습니다.



모양의 거의 동일합니다.




5. Upgrade 효과


아래 사이트를 보면, 계산적으로 2500mAh 면 3일정도 가는 것으로 되어 있습니다.


https://github.com/Safecast/bGeigieNanoKit



실제로 upgrade 하고 full 충전 후, 한번도 끄지않고 사용해 보면, 딱 48 시간 = 이틀 정도 갑니다.


1300mAh 정도면 하루+12시간이라고 표현 되어 있으니, 계산상으로만 보면 12시간 늘어난 것인데,

위성 통신이랑, Bluetooth 통신도 있으므로, 실제로는 1일이 2일 정도로 늘지 않았나 생각해 봅니다.



Battery low 가 뜨면 로깅이 중지됩니다.

그냥 측정만 하는것 같아요.



Battery low 가 뜨는 타이밍은 약 10% 정도인것 같습니다.




FIN


좋은 점

당연히 오래 간다는 점이죠!


아쉬운 점

Connector 의 선이 한가닥으로 되어 있어서 전류량적으로 아쉽다.

Connector 의 고깔 부분을 손톱으로 잡고 뽑을 수 있게 되어 있는데, 이 부분의 크기가 작아서 아쉽다.

2500mAh 면 대략 3일인데, full 2일이면 끝난다. 혹시... 용량표기의 오류?

And
prev | 1 | next