旅を楽しくするArduino端末を作る。その10-Ver2へアップデート-

第10回では前回検証したINA219を、旅Arduinoに組み込みます。
第9回はこちらからどうぞ

旅を楽しくするArduino端末Ver2の構成

今回作成する端末は以下の構成とします。

・arduino nano every(制御用マイコン)
・LCD1602(センサー値表示用LCD)
・USB2.0端子(スマートフォン充電用) + 抵抗(2A給電仕様にする為)
・BME280(温度・湿度・気圧測定用)
・GPSモジュール:GYSFDMAXB(進路方角取得用)
DC-DCコンバータ5V,3A:KIC-053&ポリスイッチ
Adafruit INA219 Current Sensor
・ユニバーサル基盤D基板1枚+C基板1枚(電源部と制御部用)

以上の構成で作成を行います。
前回の改善点を踏まえ電源を5V一本にしています。
また、LCD側(ハンドル装着部)をコンパクトにするため、I2Cで通信できるものは、電源部(シート下)に移動させます。
製作する前に回路図を書き、おおよその部品配置を検討します。

回路

前回の設計図を一部使い、設計図を引き直します。
DC-DCコンバータを変更しているので、その周辺が一番修正がかかっています。

また、実物に関しては、電源部と制御部を分けた作りにしています。
バッテリーから近いシート下に、電源部をまとめ、そこから屋外配線用の4線ケーブルを用い、ハンドル部まで電源&信号を配線しています。
ちなみに4線の内訳は

① +9V
② GND
③ SCL
④ SDA

となっております。

外装設計

ここは変更がありません。
LCD部はコンパクトになるので、時間があれば作り直したいところです。

コード

#include <LiquidCrystal.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <Adafruit_INA219.h>
#include "SparkFunBME280.h"
#include "Wire.h"
#include "SPI.h"

static const int TXPin = 2, RXPin = 3;
static float m_fltCurrentTemperature;
static float m_fltCurrenthumidity;
static float m_fltCurrentPressure;
static float m_fltCurrentVoltage;
static float m_fltCurrentCourse;
static float m_fltCurrentAltitude;

Adafruit_INA219 ina219;

TinyGPSPlus gps;
SoftwareSerial ss(TXPin, RXPin);

BME280 Sensor;
LiquidCrystal lcd( 4, 5, 6, 7, 8, 9 );

void DisplayTmp( float temperature, float humidity, float Pressure, float Voltage, String strDirection, float Altitude )
{
  String strTemperature =  String( temperature ); 
  int inthumidity =  humidity;
  String strhumidity = String( inthumidity );
  int intPressure = Pressure;
  String strPressure =  String( intPressure ); 
  String strVoltage =  String( Voltage );
  int intAltitude = Altitude;
  String strAltitude =  String( intAltitude ); 
  
  String strDisplay = "T";

  strDisplay.concat( strTemperature );
  strDisplay.concat( " H" );
  strDisplay.concat( strhumidity );
  strDisplay.concat( " P" );
  strDisplay.concat( strPressure );
  lcd.setCursor(0, 0);
  lcd.print( strDisplay );

  strDisplay = "V";
  strDisplay.concat( strVoltage );
  strDisplay.concat( " A" );
  strDisplay.concat( strAltitude );
  strDisplay.concat( " " );
  strDisplay.concat( strDirection );
  lcd.setCursor(0, 1);
  lcd.print( strDisplay );  
}

String ConvertDegrees( float intCourseDegrees ){
  String strDirection;
  if ((intCourseDegrees) <= 0) {
     strDirection = "XXX";    
    }
    else if ((intCourseDegrees) > 360) {
     strDirection = "XXX"; 
    } 
    else if ((intCourseDegrees) < 11.3) {
     strDirection = "N";    
     }
    else if ((intCourseDegrees) < 33.8) {
     strDirection = "NNE";
     }
   else if ((intCourseDegrees) < 56.3) {
     strDirection = "NE";
     }
   else if ((intCourseDegrees) < 78.8) {
     strDirection = "ENE";
     }
   else if ((intCourseDegrees) < 101.3) {
     strDirection = "E";
     }
  else if ((intCourseDegrees) < 123.8) {
     strDirection = "ESE";
     }
 else if ((intCourseDegrees) < 146.3) {
     strDirection = "SE";
     }
 else if ((intCourseDegrees) < 168.8) {
     strDirection = "SSE";
     }
 else if ((intCourseDegrees) < 191.3) {
     strDirection = "S"; 
     }
 else if ((intCourseDegrees) < 213.8) {
     strDirection = "SSW"; 
     }
else if ((intCourseDegrees) < 236.3) {
     strDirection = "SW";
     }
else if ((intCourseDegrees) < 258.8) {
     strDirection = "WSW";
     }
else if ((intCourseDegrees) < 281.3) {
     strDirection = "W"; 
      }
else if ((intCourseDegrees) < 303.8) {
     strDirection = "WNW"; 
     }
else if ((intCourseDegrees) < 326.3) {
     strDirection = "NW"; 
     }
else if ((intCourseDegrees) < 348.8) {
     strDirection = "NNW"; 
     }
else {
     strDirection = "N";
     }
     return strDirection;
  }

void setup() {
  Serial.begin(115200);
  while (!Serial) {
      // will pause Zero, Leonardo, etc until serial console opens
      delay(1);
  }
  
  uint32_t currentFrequency;

  if (! ina219.begin()) {
    Serial.println("Failed to find INA219 chip");
  while (1) { delay(10); }
  }

  Serial.println("Measuring voltage and current with INA219 ...");
  
  lcd.begin( 16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("MC Touring ADV!");
  Serial.println("LCD SetUp Ready");

  Sensor.settings.commInterface = I2C_MODE; 
  Sensor.settings.I2CAddress = 0x76;
  Sensor.settings.runMode = 3; 
  Sensor.settings.tStandby = 0;
  Sensor.settings.filter = 0;
  Sensor.settings.tempOverSample = 1 ;
  Sensor.settings.pressOverSample = 1;
  Sensor.settings.humidOverSample = 1;

  Serial.println("Starting BME280... ");
  delay(10);
  Sensor.begin();
  
  ss.begin(9600);
  ss.println("Connect Success");
}

void loop() {
  float temperature;
  int temperatureB;
  float humidity;
  int humidityB;
  float Pressure;
  int PressureB;
  float ShuntVoltage;
  float BusVoltage;
  float Voltage;
  int VoltageB;
  //float Power;
  float Course;
  float Altitude;
  String strDirection;

  for (int i=0; i <= 1000; i++){
    while (ss.available() > 0){
      if (gps.encode(ss.read())){
        if (gps.location.isUpdated()){
          Serial.println(gps.course.deg());
          Serial.println(gps.altitude.meters());
          if ( gps.course.deg() != 0 ){
            m_fltCurrentCourse = gps.course.deg();
          }
          if ( gps.altitude.meters() != 0 ){
            m_fltCurrentAltitude = gps.altitude.meters();
          }
        }
      }
    }
  }
  
  strDirection = ConvertDegrees( m_fltCurrentCourse );
  
  temperature = Sensor.readTempC() * 10;
  temperatureB = temperature;
  temperature = temperatureB;
  temperature = temperature / 10;
  humidity = Sensor.readFloatHumidity();
  humidityB = humidity;
  humidity = humidityB;
  Pressure = Sensor.readFloatPressure() / 100;
  PressureB = Pressure;
  Pressure = PressureB;

  ShuntVoltage = ina219.getShuntVoltage_mV();
  BusVoltage = ina219.getBusVoltage_V();
  Voltage = (BusVoltage + (ShuntVoltage / 1000))* 10;
  VoltageB = Voltage;
  Voltage = VoltageB;
  Voltage = Voltage / 10;
  //  power_mW = ina219.getPower_mW();
  
  if( m_fltCurrentTemperature != temperature or m_fltCurrenthumidity != humidity or m_fltCurrentPressure != Pressure or m_fltCurrentVoltage != Voltage )
  {
    lcd.clear();
    //Serial.println(analogRead(A0));
    DisplayTmp( temperature, humidity, Pressure, Voltage, strDirection, m_fltCurrentAltitude );
    m_fltCurrentTemperature = temperature;
    m_fltCurrenthumidity = humidity;
    m_fltCurrentPressure = Pressure;
    m_fltCurrentVoltage = Voltage;
  }
    delay(1000);
}

前回のコードをもとにして、コードを書き換えます。
※時間があったらリファクタリングします。今はとりあえず動くのでこれで

何も対策をせずにループを設計するとループが1秒おきに置き、LCDをクリアにするため画面ちらつき、非常にみずらくなっています。
なので、ちらつき対策として、センサー値の変動がない場合はLCDをクリアにしないようにしているのですが、BME280の温度センサーが小数点第2位まで測定しているため、小刻みに温度が動き、結果LCDの書き換えが起き、ちらつきが発生するといった問題がありました。

なので、いったん取得した温度の小数点第2位を切り落とす処理を加えています。これで画面のちらつきを抑えています。

またINA219を入れてますので、電圧はアナログではなくI2Cから取得できるようになりました。

結果

写真がごちゃごちゃしてて申し訳ないのですが、動作写真になります。
外気温等を測定できるBME280、電流・電圧が測定できるINA219、高度と進行方向を算出するGPSが動作し、USB充電にも対応している形式にになり、これらの動作電源は、12Vのバイクのバッテリーから引けるようになってます。

回路も以前よりすっきりしていますので、なかなか良いのではないでしょうか!

まとめ

Ver1で起きていた不具合や、改良点をVer2では組み込めたと思います。

ここからの改良案ですが、

1.GPSモジュールを活用し逆Tripメーター(トリップマスター)の作成
2.LCDの有機EL化(広視野角)
3.消費電力やGPSのほかの情報を表示する第2画面の作成(切り替えスイッチ)

を予定しています。
1に関してはまだ試作も終わっていないので、時間がかかると思います。
(情報を集めている段階では何とかなりそうな感じはします)
2に関しては購入さえしてしまえば切り替えできるので、何かのついでに購入します。
3に関しては設置場所が問題ですかね。ハンドル周りにつけるのが、ベストですが操作できるようにケースを作る必要がありますね。

この旅Arduino記事ですが、そこそこいろいろな方に見ていただけるみたいなので、なにか進捗があったらまた記事にする予定です。

旅を楽しくするArduino端末を作る。リンク集

その1-不満点を挙げよう- 
その2-不満点をまとめよう-

その3-電圧測定器を作る-
その4-温湿度計を作る-
その5-気圧計を作る-
その6-方位・高度計をGPSで-
その7-12Vバッテリーから電力供給
その8-Ver1作成-
その9-電圧計の誤差とその代替案-
その10-Ver2へアップデート-
その11-LCDをI2Cで制御しよう-
その12-LCDをI2C化-
その13-Ver3へアップデート-
その14-USB充電の仕様に関して-
その15-Arduino言語を用いながらBluetoothで通信できるESP32-
その16-旅Arduino Ver4 スマホアプリ化-

関連記事一覧

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

PAGE TOP