BME280とBMP280の仕様の違い

f:id:licheng:20190618173924j:plain:w400

BOSCHの気圧・温度センサBME280とBMP280の差は、基本的には湿度センサの有無ですが、configレジスタのt_sbビットの解釈も一部異なっているので要注意。t_sbビットはセンサ測定値の更新周期に影響する tstandby を設定します。

tstandby[msec]の設定

t_sb[2:0] BME280 BMP280
000 0.5 0.5
001 62.5 62.5
010 125 125
011 250 250
100 500 500
101 1000 1000
110 10 2000
111 20 4000

例えば、BME280をBMP280に置き換えたら tstandby=10msecに設定したつもりが2000msecになってしまいます。これはセンサ測定値の更新周期が2秒以上になることを意味します。

PSoC CreaterでVerilogのコンポーネント作成

手順メモ。

ワークスペースにライブラリプロジェクトを追加

  • 左ペインのWorkSpace ExploerでWorkspaceを右クリックして「Add」>「New Project」
  • Select project typeで「Library project」を選択
  • ライブラリの場所と名前を指定。ここではプロジェクト名を「MyLibrary」にしたとする

ライブラリプロジェクトにコンポーネントを追加

  • WorkSpace ExploerのComponentsタブで「MyLibrary」を右クリックして「Add Component Item」
  • 「Symbol Wizard」を選択し、コンポーネント名を指定して「Create New」
  • コンポーネント名には、バージョンを示す「_vX_Y」タグをつける

シンボルウィザードでシンボル作成

  • Symbol Creation Wizardで入出力の端子名と種別(Digital Input, Digital Output, Clock Input)を指定
  • Title colorで緑(Digital)を選択
  • 「OK」でシンボルが作成される
  • コンポーネント.cysymというファイル名でシンボル図のファイルができるので外観を適宜編集

カタログでの分類名を指定

  • シンボル図の空きスペースで右クリックして「Properties」を開く
  • SymbolのDoc.CatalogPlacementで(コレクション)を開く
  • カタログでの分類名を指定する。
  • ここでは「Community/Digital/Logic/コンポーネント (バージョンは付けない)」にしたとする

パラメータを作成

  • シンボル図の空きスペースで右クリックして「Symbol Parameters」を開く
  • パラメータの名前、種別、既定値を設定

Verilogソースを生成

  • シンボル図の空きスペースで右クリックして「Generate Verilog
  • コンポーネント.v というVerilogソースファイルが生成される
  • Verilogソースを編集。「do not edit this line」と書かれた行は編集しないこと
  • 「Build」>「Build All Projects」でビルドする

コンポーネントの使い方

  • 回路図(TopDesign.cysch)を開く
  • 右ペインのComponent Catalogでコンポーネントを探す
  • 上記の例では、「Community」タブの「Digital/Logic/コンポーネント名[バージョン]
  • 回路図にドラッグ&ドロップする

gitのベアリポジトリ、ノンベアリポジトリとは?

  • ベアリポジトリ(bare repository) = 作業コピーを含まないリポジトリ
  • ノンベアリポジトリ(non-bare repository) = 作業コピーを含むリポジトリ
  • ベアリポジトリは集中管理用
  • つまり、リモートリポジトリはベア、ローカルリポジトリがノンベアが基本
  • ノンベアリポジトリからもcloneすることはできる。
  • しかし、ノンベアリポジトリにpushすると通常はエラーになる。
  • 作業コピーとインデックスに不整合が生じるためである。
  • 下記コマンドを実行すればノンベアリポジトリでもpushを受け付けるようになる。
  • SourceTreeの場合、右上の「ターミナル」ボタンでターミナルを開いてコマンドを実行する。
  • ただしこれは非推奨である。一人で開発する分にはまあいいけども。
git config receive.denyCurrentBranch ignore 
  • ベアリポジトリは下記のコマンドで新規作成できる。
  • SourceTreeの場合、GUIからは作成できないのでターミナルでコマンドを実行する。
git init --bare
git clone --bare ノンベアリポジトリの場所

今さらLPCXpressoメモ (2)

割り込み待ち

割り込み待ち命令の組込み関数は、__WFI()

クロック出力

LPC812 Xpressoの場合、P0_1ピンにクロック出力が設定されている。
設定箇所は、lpc_board_nxp_lpcxpresso_812(ボードライブラリのプロジェクト) の board_sysinit.c の Board_SetupMuxing()

I2Cピン

LPC812の場合、I2Cバスが割り当てられているP0_10とP0_11は、GPIOとして使う場合は出力に設定できない。またプルアップも設定できない。

LPC8xxとLPC11xx

どちらもARM Cortex-M0(+)のローエンドマイコンだが、ペリフェラルの仕様がぜんぜん違う。そして、LPCOpenライブラリはその差を吸収してくれない。(API関数が異なる。)

LPC1114 Xpresso用のチップライブラリとボードライブラリ

下記のものを使用する。

  • チップライブラリ : lpc_chip_11cxx_lib
  • ボードライブラリ : nxp_lpcxpresso_11c24_board_lib

Chip_UART_SetBaudFDR関数

lpc_chip_11cxx_lib (LPC11xx用のチップライブラリ) の Chip_UART_SetBaudFDR関数はいい加減な実装で使い物にならない。通常のChip_UART_SetBaud関数で設定できない(誤差が大きくなる)ような高いボーレートを設定したい場合は、LPC111x/LPC11C1x ユーザーマニュアルの「9.6.15 UART 分数分周器レジスタ(U0FDR)」を参照してDL、DIVADDVAL、MULVALの値を設定すること。

固定小数点計算ふたたび

前回の 固定小数点の再発明 - 滴了庵日録 ではROMサイズがかえって増えるという残念な結果になったので、C++でクラス化することはあきらめてC言語で書きなおした。

fixed24.h

#ifndef _FIXED24_H
#define _FIXED24_H

#include<stdint.h>

typedef int32_t fixed24;

#define FIXED24(x, y) (fixed24)(((int64_t)(x) << 24)/(int64_t)(y)) 

fixed24 int_toFixed24(int32_t x, int32_t y);
fixed24 fixed24_mul(fixed24 x, fixed24 y);
fixed24 fixed24_div(fixed24 x, fixed24 y);
int     fixed24_toInt(fixed24 x);
double  fixed24_toDbl(fixed24 x);

#endif

fixed24.c

#include "fixed24.h"

fixed24 int_toFixed24(int32_t x, int32_t y) {
	return (fixed24)(((int64_t)x << 24) / (int64_t)y);
}
fixed24 fixed24_mul(fixed24 x, fixed24 y) {
	return (int32_t)(((int64_t)(x) * (int64_t)(y)) >> 24);
}
fixed24 fixed24_div(fixed24 x, fixed24 y) {
	return (int32_t)((((int64_t)(x) << 32) / (int64_t)(y)) >> 8);
}
int fixed24_toInt(fixed24 x) {
	return (int)((x) >> 24);
}
double fixed24_toDbl(fixed24 x) {
	return (double)x / (double)0x01000000;
}

テスト

#include <stdio.h>
#include <stdlib.h>

#include "fixed24.h"

int main(void)
{
    fixed24 x = FIXED24(10, 1);         // 10/1 = 10
    fixed24 y = int_toFixed24(20, 100); // 20/100 = 0.20
    fixed24 z = 0x01000000 / 2;         // 1/2 = 0.5

    printf("x = %d (%08X)\n", fixed24_toInt(x), x);
    printf("y = %f (%08X)\n", fixed24_toDbl(y), y);
    printf("z = %f (%08X)\n", fixed24_toDbl(z), z);

    z = x + y;
    printf("%f + %f = %f (%08X)\n",
        fixed24_toDbl(x), fixed24_toDbl(y), fixed24_toDbl(z), z);
    z = x - y;
    printf("%f - %f = %f (%08X)\n",
        fixed24_toDbl(x), fixed24_toDbl(y), fixed24_toDbl(z), z);
    z = fixed24_mul(x, y);
    printf("%f * %f = %f (%08X)\n",
        fixed24_toDbl(x), fixed24_toDbl(y), fixed24_toDbl(z), z);
    z = fixed24_div(x, y);
    printf("%f / %f = %f (%08X)\n",
        fixed24_toDbl(x), fixed24_toDbl(y), fixed24_toDbl(z), z);
    z = x * 2;
    printf("%f * 2 = %f (%08X)\n", fixed24_toDbl(x), fixed24_toDbl(z), z);
    z = x / 2;
    printf("%f / 2 = %f (%08X)\n", fixed24_toDbl(x), fixed24_toDbl(z), z);

    x = FIXED24(1, 1);
    y = FIXED24(1, 1);
    printf("%f == %f : %s\n",
        fixed24_toDbl(x), fixed24_toDbl(y), (x == y) ? "TRUE" : "FALSE");
    printf("%f != %f : %s\n",
        fixed24_toDbl(x), fixed24_toDbl(y), (x != y) ? "TRUE" : "FALSE");
    y = FIXED24(2, 1);
    printf("%f == %f : %s\n",
        fixed24_toDbl(x), fixed24_toDbl(y), (x == y) ? "TRUE" : "FALSE");
    printf("%f != %f : %s\n",
        fixed24_toDbl(x), fixed24_toDbl(y), (x != y) ? "TRUE" : "FALSE");

    return 0;
}

今さらLPCXpressoメモ

ひさしぶりにLPCXpresso使ったら、使い方忘れてたのでメモ。

IDEのインストール

  • 最新版のLPCXpresso IDE (今日現在でv8.2.2_650) をダウンロードしてインストールする。
  • Windowsでは、通常は C:\nxp\LPCXpresso_8.2.2_650 にインストールされる。

IDEの起動

  • LPCXpresso IDEを起動するとワークスペースが開く。
  • デフォルトのワークスペースはWindows10では下記のファルダである。
    %USERPROFILE%\Documents\LPCXpresso_8.2.2_650\workspace である。

ライブラリのインポート

  • ここではLPC812-LPCXpressoボードをLPCOpenライブラリで開発するものとして必要なライブラリをインポートする。
  • Quickstart Panelの「Import project(s)」で「Project archive」の「Browse」から下記ファイルを選択する。
    C:\nxp\LPCXpresso_8.2.2_650\lpcxpresso\Examples\LPCOpen\
    lpcopen_2_19_lpcxpresso_nxp_lpcxpresso_812.zip
  • このZIPファイルにはチップライブラリ(lpc_chip_8xx)、ボードライブラリ(lpc_board_nxp_lpcxpresso_812)、およびサンプルコードが含まれるので、とりあえず全てをインポートする。

プロジェクトの作成

  • Quickstart Panelの「New project」からファミリ名「LPC81x」の「LPCOpen - C Project」を選択
  • プロジェクト名を入力
  • ターゲットMCUとして「LPC812」を選択
  • チップライブラリとして「lpc_chip_8xx」、ボードライブラリとして「lpc_board_nxp_lpcxpresso_812」を選択
  • その他のオプションを適宜設定
  • プロジェクトが作成される

プロジェクトのビルド

  • Quickstart Panelの「Build 'プロジェクト名'」でビルドが実行される。

プロジェクトのデバッグ実行

  • Quickstart Panelの「Debug 'プロジェクト名'」でデバッグ実行が開始される。
  • 最初に「Connect to emulator」でデバイスを選択する。
  • main関数の冒頭でブレークするので、Resume(F8)なりStep Into(F5)なりStep Over(F6)なりする。

固定小数点の再発明

Adafruit TrinketのようなROMが数キロバイトしかないマイコンでは、float型を用いると浮動小数点のライブラリがROM容量を圧迫してしまう。そこで固定小数点クラスを作ってみた。

【2019/05/24 追記】
Arduino IDEでビルドしてみたところ、AVRマイコンではfloat使うよりROMサイズが増えてしまった。クラス化はあきらめてCだけで書いたらいちおうfloatよりROM削減にはなったけど、それも思ったほどの効果でもなかった。8ビットマイコンで64ビットの乗算をするためけっこうROMを食うようだ。残念な結果である。
固定小数点計算ふたたび - 滴了庵日録

fixed24クラスの仕様

  • 内部表現は符号1ビット、整数部7ビット、小数部24ビットの全32ビット。
  • 代入(=)、比較(==, != , >, <, >=, <=)、四則演算(+, -, *, /) の演算子が使える。
  • +=のような糖衣な演算子はサポートしない。
  • 生値(32ビットの内部表現) または (分子, 分母) からインスタンス生成する。
  • 整数への変換にはtoInt()メソッドを用いる。(キャスト演算子は暗黙のキャストが危険なため)
  • デバッグ用にdoubleへのキャスト演算子を用意。(通常は無効)
  • 生値(32ビットの内部表現)へのアクセスを許す。(どうせこんなクラス使うのは泥臭い世界)

fixed24.h

#ifndef _FIXED24_H
#define _FIXED24_H

#include<stdint.h>

class fixed24
{
public:
    // constructors
    fixed24(void) {
        value = 0;
    }
    fixed24(int32_t rawval){
        value = rawval;
    }
    fixed24(int32_t numer, int32_t denom){
        int64_t x = ((int64_t)numer << 24) / (int64_t)denom;
        value = (int32_t)x;
    }

    // operators
    void  operator =  (fixed24 x){ value = x.value; }
    bool  operator == (fixed24 x) const { return (value == x.value); }
    bool  operator != (fixed24 x) const { return (value != x.value); }
    bool  operator >  (fixed24 x) const { return (value >  x.value); }
    bool  operator <  (fixed24 x) const { return (value <  x.value); }
    bool  operator >= (fixed24 x) const { return (value >= x.value); }
    bool  operator <= (fixed24 x) const { return (value <= x.value); }
    fixed24 operator + (fixed24 x) const { return fixed24(value + x.value); }
    fixed24 operator - (fixed24 x) const { return fixed24(value - x.value); }
    fixed24 operator * (fixed24 x) const {
        int64_t a = (int64_t)value;
        int64_t b = (int64_t)x.value;
        a *= b;
        a >>= 24;
        return fixed24((int32_t)a);
    }
    fixed24 operator * (int32_t x) const {
        int32_t y = value * x;
        return fixed24((int32_t)y);
    }
    fixed24 operator / (fixed24 x) const {
        int64_t a = (int64_t)value << 32;
        int64_t b = (int64_t)x.value;
        a /= b;
        a >>= 8;
        return fixed24((int32_t)a);
    }
    fixed24 operator / (int32_t x) const {
        int32_t y = value / x;
        return fixed24((int32_t)y);
    }
    
    // convert to integer (-128 to +127)
    // not cast operator because implicit cast is dangerous
    int toInt() const { return (int)(value >> 24); }

#ifdef _DEBUG_FIXED24
    // cast to double (for debug)
    operator double () const {
        double x = (double)value / (double)(1UL << 24);
        return x;
    }
#endif
    
    // raw value
    int32_t    value;
};

#endif

テスト

#include <stdio.h>

#define _DEBUG_FIXED24
#include "fixed24.h"

int main(void)
{
    fixed24 x = fixed24(10, 1);   // 10/1 = 10
    fixed24 y = fixed24(20, 100); // 20/100 = 0.20
    fixed24 z = fixed24(0x01000000 / 2); // 1/2 = 0.5

    printf("x = %d (%08X)\n", x.toInt(), x.value);
    printf("y = %f (%08X)\n", (double)y, y.value);
    printf("z = %f (%08X)\n", (double)z, z.value);

    z = x + y;
    printf("%f + %f = %f (%08X)\n", (double)x, (double)y, (double)z, z.value);
    z = x - y;
    printf("%f - %f = %f (%08X)\n", (double)x, (double)y, (double)z, z.value);
    z = x * y;
    printf("%f * %f = %f (%08X)\n", (double)x, (double)y, (double)z, z.value);
    z = x / y;
    printf("%f / %f = %f (%08X)\n", (double)x, (double)y, (double)z, z.value);
    z = x * 2;
    printf("%f * 2 = %f (%08X)\n", (double)x, (double)z, z.value);
    z = x / 2;
    printf("%f / 2 = %f (%08X)\n", (double)x, (double)z, z.value);

    x = fixed24(1, 1);
    y = fixed24(1, 1);
    printf("%f == %f : %s\n", (double)x, (double)y, (x == y) ? "TRUE" : "FALSE");
    printf("%f != %f : %s\n", (double)x, (double)y, (x != y) ? "TRUE" : "FALSE");
    y = fixed24(2, 1);
    printf("%f == %f : %s\n", (double)x, (double)y, (x == y) ? "TRUE" : "FALSE");
    printf("%f != %f : %s\n", (double)x, (double)y, (x != y) ? "TRUE" : "FALSE");

    return 0;
}