F1風G Force Meterのプログラムコードなり

CPUボードはarduino UNO

3軸加速度センサーは秋月製MMA8452Qモジュール

ディスプレモニターはI2C通信のOLED 128×64(SSD1306)
VCCとGNDが逆なものがあるので接続に注意が必要

arduino IDEにてCプログラムコード作成

ブレッドボードでの配線接続方法は以下にゃり?

 

Cプログラムコードは以下にゃり?

/* -------------------------------------------------- *
 *  G Force Meter Program                             *
 * -------------------------------------------------- *
 *        CPU: Arduino UNO CPU Board                  *
 * C Compiler:                                        *
 *  File Name: G_Force_Meter                          *
 *     Author: March                                  *
 *    Created: 2018/07/03                             *
 *        URL: http://ak12-march.is-best.net/         *
 * -------------------------------------------------- */
#include <Wire.h>
#include "U8glib.h"
U8GLIB_SSD1306_128X64 u8g( U8G_I2C_OPT_DEV_0 | U8G_I2C_OPT_NO_ACK | U8G_I2C_OPT_FAST );

/* ----------------------------------------- *
 * Define                                    *
 * ----------------------------------------- */
#define MMA8452_ADRS          0x1D

#define MMA8452_OUT_X_MSB     0x01
#define MMA8452_XYZ_DATA_CFG  0x0E
#define MMA8452_CTRL_REG1     0x2A
#define MMA8452_CTRL_REG1_ACTV_BIT  0x01
#define MMA8452_G_SCALE       2

/* ----------------------------------------- *
 * Variabal                                  *
 * ----------------------------------------- */
volatile char       g_buffer1[ 4 ];
char                *charbuf1 = (char *)&g_buffer1;
volatile char       g_buffer2[ 4 ];
char                *charbuf2 = (char *)&g_buffer2;
volatile char       g_buffer3[ 4 ];
char                *charbuf3 = (char *)&g_buffer3;

/* ------------------------------------------------------ *
 * Program Codes                                          *
 * ------------------------------------------------------ */

/* ----------------------------------------- *
 *  MMA8452 Data Read Byte Program           *
 * ----------------------------------------- */
byte MMA8452_ReadByte( byte adrs )
{
  Wire.beginTransmission( MMA8452_ADRS );
  Wire.write( adrs );
  Wire.endTransmission( false );

  Wire.requestFrom( MMA8452_ADRS, 1 );

  while( !Wire.available( ) );

  return ( Wire.read( ) );
}

/* ----------------------------------------- *
 *  MMA8452 Data Read Byte Array Program     *
 * ----------------------------------------- */
void MMA8452_ReadByteArray( byte adrs, int datlen, byte *dest )
{
  Wire.beginTransmission( MMA8452_ADRS );
  Wire.write( adrs );
  Wire.endTransmission( false );

  Wire.requestFrom( MMA8452_ADRS, datlen );

  while( Wire.available( ) < datlen );

  for( int x = 0; x < datlen; x++ ){
    dest[ x ] = Wire.read( );
  }
}

/* ----------------------------------------- *
 *  MMA8452 Data Read Write Program          *
 * ----------------------------------------- */
void MMA8452_WriteByte( byte adrs, byte dat )
{
  Wire.beginTransmission( MMA8452_ADRS );
  Wire.write( adrs );
  Wire.write( dat );
  Wire.endTransmission( false );
}

/* ----------------------------------------- *
 *  Cpu Init Program                         *
 * ----------------------------------------- */
void setup( )
{
  byte tmp;

  // OLED画面の出力色設定
  u8g.setColorIndex( 1 );
    
  // 3軸加速度センサー初期化
  tmp = MMA8452_ReadByte( MMA8452_CTRL_REG1 );
  MMA8452_WriteByte( MMA8452_CTRL_REG1, tmp & ~(MMA8452_CTRL_REG1_ACTV_BIT) );

  MMA8452_WriteByte( MMA8452_XYZ_DATA_CFG, (MMA8452_G_SCALE >> 2) );
  
  tmp = MMA8452_ReadByte( MMA8452_CTRL_REG1 );
  MMA8452_WriteByte( MMA8452_CTRL_REG1, tmp | MMA8452_CTRL_REG1_ACTV_BIT );
}

/* ----------------------------------------- *
 * Main Loop Program                         *
 * ----------------------------------------- */
void loop( )
{
  byte buf[ 6 ];
  float g_Force[ 3 ];
  float g_Force_AngleXY;
  float g_ForceNonMarkX, g_ForceNonMarkY, g_ForceMax, g_ForceCuff;

  // G Force Data Read
  MMA8452_ReadByteArray( MMA8452_OUT_X_MSB, 6, buf );
  // floatとして変数格納
  // G Force X:g_Force[0] | Y:g_Force[1] | Z:g_Force[3]
  g_Force[ 0 ] = ( float( ( int( buf[ 0 ] << 8) | buf[ 1 ] ) >> 4 ) / ( ( 1 << 11 ) / MMA8452_G_SCALE ) );
  g_Force[ 1 ] = ( float( ( int( buf[ 2 ] << 8) | buf[ 3 ] ) >> 4 ) / ( ( 1 << 11 ) / MMA8452_G_SCALE ) );

  // 小数点2桁以下切捨て 
  g_Force[ 0 ] = (float)((int)(g_Force[ 0 ] * 100)) / 100;
  g_Force[ 1 ] = (float)((int)(g_Force[ 1 ] * 100)) / 100;

  // tan θ > ラジアン値変換
  g_Force_AngleXY = atan( g_Force[ 0 ] / g_Force[ 1 ] );

  // -符号をなくす
  if( g_Force[ 0 ] < 0 ){ g_ForceNonMarkX = (-g_Force[ 0 ]); }
  else{ g_ForceNonMarkX = g_Force[ 0 ]; }
  if( g_Force[ 1 ] < 0 ){ g_ForceNonMarkY = (-g_Force[ 1 ]); }
  else{ g_ForceNonMarkY = g_Force[ 1 ]; }

  // 最大重力値
  g_ForceMax = sqrt( (g_ForceNonMarkX*g_ForceNonMarkX) + (g_ForceNonMarkY*g_ForceNonMarkY));
  // G Forceグラフ 最大スケール値
  #define g_Force_guage_scale   1.0f
  if( g_ForceMax > g_Force_guage_scale ){ g_ForceCuff = g_Force_guage_scale; }
  else{ g_ForceCuff = g_ForceMax; }

  // float > ASCII文字に変換
  dtostrf( g_ForceMax, 3, 1, charbuf1 );
  dtostrf( g_ForceNonMarkX, 3, 1, charbuf2 );
  dtostrf( g_ForceNonMarkY, 3, 1, charbuf3 );

  // OLED Display 出力
  u8g.firstPage( );
  do {
    // G Force graph 枠Lineを描く
    u8g.drawCircle( 96, 32, 30, U8G_DRAW_ALL );
    u8g.drawCircle( 96, 32, 15, U8G_DRAW_ALL );
    u8g.drawLine( 96,  2, 96.0f, 63.0f );
    u8g.drawLine( 66, 32,126.0f, 32.0f );
    u8g.drawFilledEllipse( 96, 32, 1, 1, U8G_DRAW_ALL );
    u8g.drawRFrame( 0, 1, 61, 37, 3);

    // 斜辺c 高さbを求める
    float cosbuff = cos(g_Force_AngleXY);
    float sinbuff = sin(g_Force_AngleXY);

    // G Force Line Pointを描く
    #define GFORCE_BALL_SIZE 3
    if( g_Force[ 0 ] == 0.0 && g_Force[ 1 ] == 0.0f ){
      u8g.drawFilledEllipse( 96.0f, 32.0f, GFORCE_BALL_SIZE, GFORCE_BALL_SIZE, U8G_DRAW_ALL );
    } else if( g_Force[ 1 ] < 0.0f ){
      u8g.drawLine( 96, 32, 96.0f-(((-30.0f) * g_ForceCuff) * cosbuff), 32.0f-(((-30.0f) * g_ForceCuff) * sinbuff) );
      u8g.drawFilledEllipse( 96.0f-(((-30.0f) * g_ForceCuff) * cosbuff), 32.0f-(((-30.0f) * g_ForceCuff) * sinbuff), GFORCE_BALL_SIZE, GFORCE_BALL_SIZE, U8G_DRAW_ALL );
    } else{
      u8g.drawLine( 96, 32, 96.0f-((30.0f * g_ForceCuff) * cosbuff), 32.0f-((30.0f * g_ForceCuff) * sinbuff) );
      u8g.drawFilledEllipse( 96.0f-((30.0f * g_ForceCuff) * cosbuff), 32.0f-((30.0f * g_ForceCuff) * sinbuff), GFORCE_BALL_SIZE, GFORCE_BALL_SIZE, U8G_DRAW_ALL );
    }
    
    // フォント設定
    u8g.setFont( u8g_font_9x15B );
    u8g.drawStrP(  8, 16, PSTR("Max G") );
    u8g.drawStrP( 42, 34, PSTR("G") );
    u8g.drawStrP(  2, 51, PSTR("G Force") );
    
    // フォント設定
    u8g.setFont( u8g_font_10x20r );
    u8g.drawStr(  10, 34, charbuf1 );

    // フォント設定
    u8g.setFont( u8g_font_7x13r );
    u8g.drawStrP( 0, 64, PSTR("X:") ); u8g.drawStrP( 42, 64, PSTR("Y:") );
    u8g.drawStr(  14, 64, charbuf2 );
    u8g.drawStr(  56, 64, charbuf3 );
  } while( u8g.nextPage( ) );

  delay( 50 );
}

u8glibのライブラリーをarduinoにインストールしてからビルドしてなり。

中華製arduino UNOは大体LMS1117の3端子レギュレターが使われています。

LMS1117の絶対定格電圧は15Vと低いので、エンジン始動後14V前後の電圧まであがる自動車などに使うのは危ないです。

そのためおいらは、LMS1117が使われていない絶対低格電圧が20V以上あるarduino UNOを使うようにしてるにゃん。