분명 고3일 때 하라는 공부는 안 하고 블로그에 글을 쓰고 있었는데, 정신차려보니 어느덧 군 복무도 끝나가고 있습니다.
    새로운 마음으로 공부하고 작업한 내용을 기록하고자 새 Jekyll 블로그를 만들었습니다.

    댓글을 쓰셔도 보기가 어려우니, 불편하시더라도 궁금한 점은 옮긴 새 블로그에 댓글로 달아 주시면 성심성의껏 답변해 드리겠습니다. 감사합니다.
    2021년 2월 14일

    새 블로그 주소는 https://luftaquila.io입니다.
     

    LUFT - AQUILA

    A sky sailing Electron.

    luftaquila.io




    블로그를 이전하면서 글도 같이 옮기고 있습니다.

    블로그 이전 공지 : https://luftaquila.tistory.com/56

     

    이 글은

     

    https://luftaquila.io/blog/diy/usb-wattmeter-diy/

     

    아두이노 USB 파워미터 DIY

    당신의 전기료는 안녕하십니까

    luftaquila.io

    로 이동되었습니다!


    댓글을 쓰셔도 보기가 어려우니, 불편하시더라도 궁금한 점은 옮긴 새 블로그에 댓글로 달아 주시면 성심성의껏 답변해 드리겠습니다.

     

     

    원래 글을 보려면 더 보기를 누르세요

    더보기

    이전 글 아두이노 USB 파워미터 프로젝트 - 하드웨어 제작 편에서 때깔 좋게 하드웨어를 만들고 왔습니다.

     

     

    이제 여기에 코드를 올릴 차례군요.

     

    USB_PowerMeter.ino
    다운로드
    USB_PowerMeter_Separated.zip
    다운로드

     

    일단 소스코드 파일을 업로드해 뒀습니다.

    ino파일과 zip파일 모두 같은 파일입니다만, zip파일은 코드가 분할되어 있습니다.

     

    아두이노 소스코드 분할, 새 탭  기능에 관해서는 아래 포스팅을 참고해 주세요.

    아두이노 코드 분할 - 새 탭 기능 사용하기

     

    소스 컴파일에 라이브러리가 몇 개 필요합니다.

    LCD와 INA219 라이브러리인데요, 이미 사용하신 적이 있으신 분들은 건너뛰셔도 됩니다.

     

    처음 사용하시는 분들께서는

    https://playground.arduino.cc/Main/LiquidCrystal

    https://github.com/adafruit/Adafruit_INA219

    에서 라이브러리를 각각 다운받아 적용해 주세요.

     

    라이브러리 적용 방법을 모르는 분들께서는 아래 포스팅을 참고하셔서 적용하신 후에 진행해 주시기 바랍니다.

    아두이노 라이브러리 컴파일 에러 때려잡기

     

     

     

    라이브러리 작업이 끝났으면, 본격적인 코딩에 들어가 보겠습니다.

     

     

     

    /* Coded by Luft Aquila, v1.1.2 at 2017.07.22 01:39 AM Contact : http://luftaquila.tistory.com / luftaquila@protonmail.ch */ #include <Wire.h> #include <LiquidCrystal.h> #include <Adafruit_INA219.h> Adafruit_INA219 sensor219; LiquidCrystal lcd(12, 11, 10, 9, 8, 7); //LCD 통신 핀을 설정합니다. //LCD의 4, 6, 11, 12, 13, 14번 핀과 연결된 디지털 핀 순서대로 적어 주세요. int sw = 5; float v = 0.0; //측정값을 저장할 변수들을 선언합니다. float mAh_total = 0; float current = 0; unsigned long int timer = 0; //경과시간 측정 등에 사용될 타이머 변수들을 선언합니다. unsigned long int time0; unsigned long int last_time; void Measurement() //센서 측정값을 읽어온 후 계산, 저장을 담당하는 함수입니다. { // INA219 Variables float busVoltage = 0; float power = 0; // Voltmeter Variables int analogInput = A7; float vout = 0.0; float vin = 0.0; float R1 = 30000.0; float R2 = 7500.0; int value = 0; // INA219 Measurements - INA219의 측정값을 받아옵니다. busVoltage = sensor219.getBusVoltage_V(); current = sensor219.getCurrent_mA(); if(current <= 0.2) //전류값이 튀는 경우가 있어서 0.2mA보다 작은 전류는 무시 처리합니다. current = 0; power = busVoltage * (current/1000); //mW 단위의 전력을 계산합니다.(W = P * I) // Voltmeter Measurements - 전압 센서의 측정값을 받아옵니다. value = analogRead(analogInput); vout = (value * 5.0) / 1024.0; vin = vout / (R2 / (R1 + R2)); v = vin-0.2; if(v<0) v=0; // mAh Calculation - 밀리암페어시(전류 * 시간)값을 계산합니다. float mAh; mAh = current * 1/7200; //측정 순간의 mA단위 전류값에 측정 간격인 0.5초 만큼의 시간을 곱해줍니다. mAh_total = mAh + mAh_total; //이전 mAh값에 방금 측정한 mAh값을 더해 총량을 계산해 줍니다. // Passed Time Calculation - 전원이 켜진 후 경과한 시간을 측정합니다. timer = millis() / 1000; Output(); //측정을 완료했으니 값을 LCD에 출력하는 함수를 호출합니다. } void Output() //측정값을 LCD에 출력하는 역할을 담당하는 함수입니다. { // Print Passed Time - 전원이 켜진 후 경과한 시간을 출력합니다. lcd.setCursor(1, 1); if(timer >= 0 && timer < 10) //자릿수에 따라 출력 위치를 옮겨줍니다. { lcd.print(" "); lcd.print(timer); } else if(timer >= 10 && timer < 100) { lcd.print(" "); lcd.print(timer); } else if(timer >= 100 && timer < 1000) { lcd.print(" "); lcd.print(timer); } else if(timer >= 1000 && timer < 10000) lcd.print(timer); else lcd.print("Err."); // Print Voltage - 전압 값을 출력합니다. USB 포트로는 5V내외만 들어오니 자릿수 변경은 필요없습니다. lcd.setCursor(1, 0); lcd.print(v, 2); // Print Current - mA 단위의 전류값을 출력합니다. 자릿수에 따라 출력 위치를 옮겨줍니다. lcd.setCursor(8, 0); if(current >= 0 && current < 10) { lcd.print(" "); lcd.print(current, 1); } else if(current >= 10 && current < 100) { lcd.print(" "); lcd.print(current, 1); } else if(current >= 100 && current < 1000) { lcd.print(" "); lcd.print(current, 1); } else if(current >= 1000 && current < 10000) lcd.print(current, 1); else lcd.print(" Err."); // Print mAh - mAh 값을 출력합니다. 마찬가지로 자릿수를 따라 옮겨줍니다. lcd.setCursor(7, 1); if(mAh_total >= 0.0 && mAh_total < 10.0) { lcd.print(" "); lcd.print(mAh_total, 1); } else if(mAh_total >= 10.0 && mAh_total < 100.0) { lcd.print(" "); lcd.print(mAh_total, 1); } else if(mAh_total >= 100.0 && mAh_total < 1000.0) { lcd.print(" "); lcd.print(mAh_total, 1); } else if(mAh_total >= 1000.0 && mAh_total < 10000.0) { lcd.print(" "); lcd.print(mAh_total, 0); } else if(mAh_total >= 10000.0 && mAh_total < 100000.0) { lcd.print(" "); lcd.print(mAh_total, 0); } else if(mAh_total >= 100000.0 && mAh_total < 1000000.0) lcd.print(mAh_total, 0); else lcd.print(" Err."); } void setup() //위에 정의한 함수들은 호출됐을 경우에만 실행됩니다. //전원이 들어오면 setup()함수가 가장 먼저 최초 1회만 실행됩니다. { sensor219.begin(); //INA219와의 통신을 시작합니다. lcd.begin(16, 2); //LCD와의 통신을 시작합니다. pinMode(5, INPUT_PULLUP); // 5번 핀을 풀업저항 모드 스위치 핀으로 지정합니다. // Setting LCD Layout - LCD에 측정값들의 단위를 표시해줍니다. lcd.setCursor(5, 0); lcd.print("V"); lcd.setCursor(14, 0); lcd.print("mA"); lcd.setCursor(13, 1); lcd.print("mAh"); lcd.setCursor(5, 1); lcd.print("s"); last_time = millis(); //측정 간격을 0.5초로 유지하기 위한 변수입니다. Measurement(); //최초 1회 측정을 실행하고, 이어 호출되는 Output() 함수로 측정값을 출력합니다. } void loop() { // Print to LCD every 0.5 sec - 매 0.5초마다 측정 후 값을 출력합니다. time0 = millis(); if(time0 - last_time >= 500) { Measurement(); last_time = time0; } if(digitalRead(sw)==LOW) // 스위치가 눌린 경우 mAh 값을 초기화해 처음부터 다시 적산합니다. mAh_total = 0; }

    이게 코드의 전부입니다! 주석 중에 이해가 안 가거나 궁금한 부분은 언제든지 댓글 달아 주세요!

     

     

    계산 과정이 꽤 되고, 출력값도 많다 보니 코드가 상당히 복잡해졌습니다. 무려 200줄이나 되는군요.

    여기에는 기능 구현 부분만 편집해서 넣어놨지만, 원래 제가 작성해서 업로드한 코드는 500줄 분량입니다(...)

    기능을 이것저것 닥치는 대로 집어넣다 보니...

     

    몇백 줄 분량 코드를 한 파일에 몰아넣으면 가독성이 상당히 떨어집니다.

    이럴 때 가독성 확보를 위해 필요한 조치가 바로 코드 분할 기능입니다.

     

    위에서도 링크를 한 번 걸었지만, 잘 쓰면 가독성 확보에 아주 유용한 기능이라 다시 한 번 걸어놓겠습니다.

    라고 쓰고 포스팅 반복 홍보라고 읽습니다.

    아두이노 코드 분할 - 새 탭 기능 사용하기

     

     

    작동 영상입니다. 영상에 나오는 건 잡다하게 추가한 기능이 많아서 블로그에 올라간 소스랑은 좀 달라요.

     

     

    --------------------------------------------------------------------------------
    +내용추가 : 하드웨어 편에 추가해 놨지만 혹시 몰라 소프트웨어 편에도 적어놓습니다.사용한 전압 센서 자체 저항이 37.5kΩ 정도로, 전압계 치고는 저항이 아주 낮은 편입니다.보통 디지털 멀티미터 전압계가 최소 수십 메가옴은 나오거든요.
    그렇게 크지 않은 저항을 도선에 병렬 연결한 셈이라 USB 전력이 오가는 메인 도선 전류가 좀 깎여나갑니다.이게 신경쓰이시는 분들은 코드의 47~53번 내용을 생략하시고, 그 위에 전력 계산할 때 사용한busVoltage = sensor219.getBusVoltage_V();를 그대로 변수 v에 넣어서 쓰시면 됩니다.
    다만 버스 전압은 전압 센서가 재는 전압보다는 값이 조금 흔들리는 편이에요.

     

    Posted by LUFT - AQUILA
    • djksaldca
      2018.10.16 12:50

      안녕하세요! 혹시 코드중에 // Print Passed Time 부분은 LCD에 어떤영향을 미치는지 알 수있을까요?
      영상을 보니 시간은 나오지 않고 전압/전류/전력값만 나오는것 같더라구요!