製作モジュール一覧

2017年11月29日水曜日

Nucleo(mbed)で電圧を監視する

MAU106±5V電源でDigital+5Vの出力を1/2に分圧して取り出せるようにしているので、Nucleoでその電圧を測定して電圧監視するClassを作ってみた。

Class内でTickerを使うには、attach()を
t.attach(this, &VoltageMonitor::blinkLed, 0.5);
と、第一引数に自分自身を指定する必要がある。(参考:「https://os.mbed.com/forum/mbed/topic/1964/」)
Warning: Function "mbed::Ticker::attach(T *, M, float) [with T=VoltageMonitor, M=void (VoltageMonitor::*)()]" (declared at <a href="#" onmousedown="mbed_doc_goto('/VoltageMonitor_Test//extras/mbed_e7ca05fa8600/drivers/Ticker.h', '102'); return false;">/extras/mbed_e7ca05fa8600/drivers/Ticker.h:102</a>) was declared "deprecated" in "VoltageMonitor/VoltageMonitor.h", Line: 67, Col: 24
というWarningが出るが、mbed-srcのdirvers/Ticker.hに
    template<typename T, typename M>
    MBED_DEPRECATED_SINCE("mbed-os-5.1",
        "The attach function does not support cv-qualifiers. Replaced by "
        "attach(callback(obj, method), t).")
    void attach(T *obj, M method, float t) {
        attach(callback(obj, method), t);
    }
と宣言されていて、cv-qualifiers(constやvolatileの修飾子)をサポートしていないので(mbed-os-5.1以降?)非推奨というような事が書いてある。

mbed OS 5はなんだかイマイチこなれていない感があるので今回はmbed 2で使うことにして、
void attach(T *obj, M method, float t)
をそのまま使うことにした。そもそも
attach(callback(obj, method), t);
の「callback()」が何なのかよくわからない。←そのうち調べるかも?

ブレッドボード配線図

Test Program
https://os.mbed.com/users/ryood/code/VoltageMonitor_Test/ Revision:1

VoltageMonitor Class
https://os.mbed.com/users/ryood/code/VoltageMonitor/ Revision:1

VoltageMonitor Classのコンストラクタで
    // パラメータ
    // _ain: 電圧監視用ADC
    // _vdd: VDDの電圧値(実測値を指定)
    // _loThreshold: 電圧低下閾値
    // _hiThreshold: 過電圧閾値
    // _pLed: 警告用LED (NULL: LEDを使用しない)
VoltageMonitor(AnalogIn* _pAin, float _vdd, float _loThreshold, float _hiThreshold, DigitalOut* _pLed=NULL)
とパラメータを指定し、check()を呼び出す。
    // 返り値
    // -1: 電圧低下
    //  0: 正常
    //  1: 過電圧
    int check()
Nucleo自体には内部レファレンスがあるが、3.3VのVDDを実際にテスタ等で測定して基準電圧として使うことにした。

動作としては電圧が低下した場合はLEDがゆっくり点滅、過電圧の場合ははやく点滅、正常時は常時点灯としている。

内蔵基準電圧


Nucleoをmbedで使って内蔵基準電圧を使いたい場合は
AnalogIn   vrefint(ADC_VREF);
と指定すれば使えるようだ。

参考「https://os.mbed.com/questions/75910/How-to-get-the-value-of-inbuilt-vref-int/」

内蔵基準電圧は1.21Vなので今回は使用していない。(入力が0V~2.7V以上を想定)

2017年11月26日日曜日

Raspberry Pi 3とCortex-M7のNucleo F767ZIの浮動小数点演算を比較

Nucleo用にmbedで書いたプログラムとほぼおなじものをRaspberry Pi3用にC++で書いて比較してみた。

Nucleo用プログラム (mbed)
https://os.mbed.com/users/ryood/code/FloatingPointTest/ Revison:1

Raspberry Pi 3用プログラム <floating_point_test.cc>

#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdint.h>

#define LOOP_N  (10000)

float buffer[LOOP_N];

clock_t start;

void floatTest()
{
    // divf
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = (float)i / LOOP_N;
    }
    int elapse = clock() - start;
    printf("divf\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);
    
    // sinf
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = sinf((float)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("sinf\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);

    // cosf
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = cosf((float)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("cosf\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);

    // expf
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = expf((float)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("expf\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);
    
    // logf
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = logf((float)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("logf\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);
    
    // sqrtf
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = sqrtf((float)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("sqrtf\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);      
}

void doubleTest()
{
    // div
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = (double)i / LOOP_N;
    }
    int elapse = clock() - start;
    printf("div\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);
    
    // sin
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = sin((double)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("sin\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);

    // cos
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = cos((double)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("cos\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);

    // exp
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = exp((double)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("exp\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);
    
    // log
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = log((double)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("log\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);
    
    // sqrt
    start = clock();
    for (int i = 0; i < LOOP_N; i++) {
        buffer[i] = sqrt((double)i / LOOP_N);
    }
    elapse = clock() - start;
    printf("sqrt\t%d\t%f\r\n", elapse, (float)elapse / LOOP_N);      
}

int main()
{
    printf("\nFloating Point Test\n");
    printf("CLOCKS_PER_SEC: %ld\n", CLOCKS_PER_SEC); 
    
    // 単精度浮動小数点演算
    printf("\nFloating Point Test\n");
    printf("float\n");
    printf("op\ttotal\t1-op\n");
    printf("-------------------------------\n");
    floatTest();
    
    // 倍精度浮動小数点演算
    printf("double\n");
    printf("op\ttotal\t1-op\n");
    printf("-------------------------------\n");
    doubleTest();
}


pi@raspberrypi:~ $ gcc -o floating_point_test -lm floating_point_test.cc

pi@raspberrypi:~ $ cat /etc/debian_version
8.0

Raspberry PiのプログラムはLinux上で実行しているのでNucleoの方が有利ですが、Raspberry PiをOSなし(ベアメタルと言うそうです)で動かすのはかなり難しいので、実用的な性能比較ということになると思います。

実行結果

Floating Point Test
CLOCKS_PER_SEC: 1000000

Floating Point Test
float
op      total   1-op
-------------------------------
divf    629     0.062900
sinf    2124    0.212400
cosf    2163    0.216300
expf    3632    0.363200
logf    2659    0.265900
sqrtf   3630    0.363000
double
op      total   1-op
-------------------------------
div     753     0.075300
sin     4805    0.480500
cos     4829    0.482900
exp     5356    0.535600
log     4408    0.440800
sqrt    4871    0.487100

※Raspberry Pi上では実行ごとに結果が異なる。



float型ではsqrtf()以外ではNucleo F767はRasPi3の約0.6倍の性能。なぜだかsqrtf()だけはNucleo F767の方が速い。

double型ではsqrt()以外はNucleo F767はRasPi3の約0.2倍~0.5倍の性能。これもsqrt()はNucleo F767の方が速い。

駆動クロックは

Nucleo F767ZI: 216MHz
Raspberry Pi 3: 1.2GHz

で約6倍差があるので、Cortex-M7のNucleo F767ZIは、まあまあ健闘していると思う。

Nucleo F767ZIの消費電流は98mAで(ボード上のJP5 IDDで測定)、Raspberry Pi 3よりかなり少ない。

2017年11月24日金曜日

KIK01 作戦検討その5

現状の配線を記録しておきます。


リズムマシンとのカラミ



まずはSync線1本を使ってKICKパートとしてリズムマシンと同期させてみる予定。

KIK01の筐体の構想




本体を操作子系とを二段積みしてスペースを節約しようと思う。

KIK01を(むりくり)二段積みして、リズムマシンとベースマシンといっしょに並べてみた


台座に使ってるラックの一面だけでは面積的につらくなってきました。

ラックに使っているホーム・エレクタは丈夫で使いやすいんですが、いかんせん値段が高いから増設はきっついが・・・

そうか!ラックの2段めのガラクタをどっかにやって有効利用する手もあるか?!