DragonBoard 410c(Debian)で日本語音声合成(Open JTalk)のTTSしてみる

DragonBoard 410c(Debian)で日本語音声合成(Open JTalk)のTTSしてみる

前回のエントリで音声の出力ができるようになったDragonBoard。この機能を元にOpen JTalkを用いた音声合成を行ってみたいと思います。

Open JTalk - HMM-based Text-to-Speech System

以下の過去エントリを参考にしていきます。

OpenJTalk関連 uepon.hatenadiary.com

Bluetoothスピーカー関連 uepon.hatenadiary.com

Open JTalkのインストー

Open JTalkMMDAgentをインストールします。

$ sudo apt-get install open-jtalk open-jtalk-mecab-naist-jdic htsengine libhtsengine-dev hts-voice-nitech-jp-atr503-m001
$ wget http://downloads.sourceforge.net/project/mmdagent/MMDAgent_Example/MMDAgent_Example-1.6/MMDAgent_Example-1.6.zip
$ unzip MMDAgent_Example-1.6.zip
$ sudo cp -R MMDAgent_Example-1.6/Voice/mei /usr/share/hts-voice/

一度行っているので迷うことはありませんでした。

TTSを実行するシェルを編集する

Open JTalkのパラメータを設定し実行するシェルスクリプトを編集します。

$ vim jtalk.sh

【jtalk.sh】

#!/bin/bash

# HTSVOICE=/usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice
HTSVOICE=/usr/share/hts-voice/mei/mei_normal.htsvoice

voice=`tempfile`
option="-m $HTSVOICE \
  -s 16000 \
  -p 100 \
  -a 0.03 \
  -u 0.0 \
  -jm 1.0 \
  -jf 1.0 \
  -x /var/lib/mecab/dic/open-jtalk/naist-jdic \
  -ow $voice"

if [ -z "$1" ] ; then
        open_jtalk $option
else
        if [ -f "$1" ] ; then
                open_jtalk $option $1
        else
                echo "$1" | open_jtalk $option
        fi
fi

aplay -q $voice
rm $voice

編集が終わったら実行権限を与えます。

$ chmod 755 jtalk.sh

これで準備完了です。

TTSの実行

ここまで終わったので実際に実行させてみます。 コンソール上から以下の様に話したい文章を引数として与えます。

$ ./jtalk.sh こんにちは、今日は雨が降っているなか、お越しい
ただき、ありがとうございます
$ ./jtalk.sh 最大級のパワフルボディ!ダリラガーン!ダゴズバ
ーン!
$ ./jtalk.sh ドリーミングガール、恋のシミュレーション。乙女
はいつも、ときめきクライシス。

正常に動作できたようです。

【動画】

youtu.be

おわりに

思ったよりすんなりOpen JTalkを導入できました。 これでDragonBoardでも音声でアナウンスするようなものは簡単にできそうですね!

DragonBoard 410c(Debian)でPechatを使用してみる(Bluetooth経由の音声出力)

DragonBoard 410c(Debian)でPechatを使用してみる

DragonBoardの唯一困った点は音声出力のpinがデフォルトではないことかなと思います。 できれば、このあたりもついていると良かったかなと。最近は音声認識や自動音声や音声による操作もあるので、こういう方向もアクセスできるといいなあと思ったり。

ただ、DragonBoardにはBluetoothがついているのでBluetooth用の音声機器は接続できます。以前のエントリでRaspberryPiでBluetoothスピーカーのPechatを使用してみました。 一応無事には接続し使用できたのですが、XからのGUI経由でしか設定できなかったので、微妙な感じでした。そのリベンジも兼ねてDrabgonBoardでも設定をチャレンジしてみます。

uepon.hatenadiary.com

ちなみに結論に急ぎたい方は回答編まですっ飛ばしてください。

DragonBoardでBluetooth-音声デバイス設定を行う

一応、前提とする環境を確認します。OSのディストリビューションを確認します。

$ lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description:    Debian GNU/Linux 9.0 (stretch)
Release:        9.0
Codename:       stretch

もちろん、Debianですが、自分が使用したOSイメージはdragonboard410c_sdcard_install_debian-233.zipです。最新ではなく一つ古いバージョンかなと思います。(特にこだわりがなければ最新イメージのほうがいいかなと思います。)

Documentation - 96Boards

音声デバイスとしての制御はPulseAudioを使用するので、pulseaudio関係のパッケージのインストール状況も確認します。

$ dpkg -l | grep pulse
ii  libpulse-mainloop-glib0:arm64                 10.0-1                            arm64        PulseAudio client libraries (glib support)
ii  libpulse0:arm64                               10.0-1                            arm64        PulseAudio client libraries
ii  libpulsedsp:arm64                             10.0-1                            arm64        PulseAudio OSS pre-load library
ii  pulseaudio                                    10.0-1                            arm64        PulseAudio sound server
ii  pulseaudio-module-bluetooth                   10.0-1                            arm64        Bluetooth module for PulseAudio sound server
ii  pulseaudio-utils                              10.0-1                            arm64        Command line tools for the PulseAudio sound server
ii  xmms2-plugin-pulse                            0.8+dfsg-18 

デフォルトでインストールも完了しています。

Bluetoothの接続を確認する

あとはCLIからBluetoothの接続をおこなってみます。Bluetoothの確認用コマンドはbluetoothctlです。

$ sudo bluetoothctl -a
[NEW] Controller 00:00:00:00:XX:XX linaro-alip [default]
Agent registered
[bluetooth]# scan on
Discovery started
[CHG] Controller 00:00:00:00:XX:XX Discovering: yes
[NEW] Device CC:30:80:00:XX:XX Pechat-00F8A1
[NEW] Device AE:12:42:3B:XX:XX 36bde7-bt
[CHG] Device AE:12:42:3B:FF:12 RSSI: -86
[bluetooth]# pair CC:30:80:00:XX:XX
Attempting to pair with CC:30:80:00:XX:XX
[CHG] Device CC:30:80:00:XX:XX Connected: yes
[CHG] Device CC:30:80:00:XX:XX UUIDs: 00001101-0000-1000-8000-00805f9b34fb
[CHG] Device CC:30:80:00:XX:XX UUIDs: 0000110b-0000-1000-8000-00805f9b34fb
[CHG] Device CC:30:80:00:XX:XX ServicesResolved: yes
[CHG] Device CC:30:80:00:XX:XX Paired: yes
Pairing successful
[CHG] Device CC:30:80:00:XX:XX ServicesResolved: no
[CHG] Device CC:30:80:00:XX:XX Connected: no
[bluetooth]# connect CC:30:80:00:XX:XX
Attempting to connect to CC:30:80:00:XX:XX
[CHG] Device CC:30:80:00:XX:XX Connected: yes
Connection successful
[CHG] Device CC:30:80:00:XX:XX ServicesResolved: yes
[CHG] Device AE:12:42:3B:XX:XX RSSI: -87
[CHG] Device AE:12:42:3B:XX:XX RSSI: -74
[Pechat-00F8A1]# quit
Agent unregistered
[DEL] Controller 00:00:00:00:XX:XX linaro-alip [default]

無事にペアリングもコネクトもできました。あとはServiceの設定などを行うのみです。以下はほとんどRaspberryPiのときのエントリーそのままになります。RaspberryPiでは失敗していたのでかなり不安ではありますが…

/etc/systemd/system/pulseaudio.serviceファイルを作成

$ sudo vim /etc/systemd/system/pulseaudio.service

【/etc/systemd/system/pulseaudio.service】

[Unit]
Description=Pulse Audio

[Service]
Type=simple
ExecStart=/usr/bin/pulseaudio --system --disallow-exit --disable-shm

[Install]
WantedBy=multi-user.target

/etc/dbus-1/system.d/pulseaudio-bluetooth.confファイルを作成

$ sudo vim /etc/dbus-1/system.d/pulseaudio-bluetooth.conf

【/etc/dbus-1/system.d/pulseaudio-bluetooth.conf】

<busconfig>

  <policy user="pulse">
    <allow send_destination="org.bluez"/> 
  </policy>

</busconfig>

以上で設定ファイルの編集は終了となります。

pulseaudioサービスの設定

最後に起動時に自動的に設定をされるようにサービスの開始と有効化を行っておきます。

$ sudo systemctl start pulseaudio.service
$ sudo systemctl enable pulseaudio.service

これで完了です。 あとは先程と同じくBluetoothの状態の確認をしますが、基本無事にコネクトができているので一安心です。

後は音声が正常に再生されればいいのですが…

$ aplay /usr/share/sounds/alsa/Front_Center.wav
Playing WAVE '/usr/share/sounds/alsa/Front_Center.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono

あれ? エラーは出ないが、音がならない…RaspberryPiとは違う状況…

最初はmixserの設定で音量が下がっているのかなと思ったのですが、そんなこともなくさすがに微妙な感じになってしまいました。

仕方ないのでサービスはストップし、起動時は無効にすることにします。

$ sudo systemctl stop pulseaudio.service
$ sudo systemctl disable pulseaudio.service

回答編

結局、コマンドラインからの設定は成功しませんでした。(RaspberryPiでもうまく行っていなかったので、こちらがそのままの方法でうまくいくとは思いませんでしたが。)

最後にXを使用してBluetoothの設定を行ってみます。(事前にPechatの電源は入れておいてください。)

まずは、Xの下部のメニューバーをクリックし【設定】→【KDEシステム設定】を選択します。すると設定のダイアログウインドウが開きます。

f:id:ueponx:20170624101410j:plain

その中から【ネットワーク】→【Bluetooth】を選択します。

f:id:ueponx:20170624101422j:plain

するとBluetoothで接続されたデバイスの一覧が表示されます。 画面上にPechatが表示されているのがわかるかと思います。

f:id:ueponx:20170624101443j:plain

一覧からPechatを選択してみます。

f:id:ueponx:20170624101452j:plain

するとダイアログの右側にヘッドフォンの画像が表示されます。 その画面中のTrustedの部分にマウスでチェックをしてみます。

f:id:ueponx:20170624101502j:plain

その後、ダイアログ右側にある【Connect】をクリックします。 接続がうまくいくとボダンの文字はDisconnectという文字列に変更します。

f:id:ueponx:20170624101511j:plain

一応この時点でもaplayコマンドで音がなりませんでした。さすがに八方塞がりかと思ってしまうのですが、今度は下部のメニューバーをクリックし、【サウンドとビデオ】→【PluseAudio Volume Control】を選択します。

f:id:ueponx:20170624101520j:plain

選択後に開いだダイアログの【Output Device】を確認すると本体側(B410c)の設定とPechat側の設定が存在することがわかります。問題はなさそうでもあったので、この時点でaplayコマンドで再生させるのですが、問題はなさそうでしたが音声はなりませんでした。そのため、今度は本体側の外してみます。【Configure】タブを選択しD410cの【Profile】をOffに変更します。

f:id:ueponx:20170624101529j:plain

特に問題はなさそうですが、以前音声デバイスの優先順位の設定をしていたときに、優先度が異なると音声がならないということがあったことをふと思い出しました。

f:id:ueponx:20170624101537j:plain f:id:ueponx:20170624101544j:plain

ペアリングさせなおすのですが、これで問題はなく設定は完了になりそうです。

音声の再生

$ aplay /usr/share/sounds/alsa/Front_Center.wav
Playing WAVE '/usr/share/sounds/alsa/Front_Center.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Mono

音声が再生されました。やっと正常に動作します。 再起動時などにはペアリングなどは解除されるので起動時に再度Pechatの電源ボタンをOnにしてペアリングさせてあげれば問題はないかなと思います。

おわりに

やっぱり、コマンドラインからの設定はうまく行かず…。Xからの設定でうまくいっているので事実上問題はないのですが…残念です。現在の自分の能力ではそこまでということか。トホホ。

DragonBoard 410c(Debian)でGPIOプログラミング(Python編)

DragonBoard 410c(Debian)でGPIOプログラミング(Python編)

前回まではC言語でGPIOを触っていましたが、流石に最近はpythonとかnode.jsで触りたいですね。

uepon.hatenadiary.com

uepon.hatenadiary.com

折角、pythonのラッパーもインストールしてあるのでpython編となります。 早速サンプルを眺めてみます。

#!/usr/bin/python
import time

from gpio_96boards import GPIO

GPIO_A = GPIO.gpio_id('GPIO_A')
pins = (
    (GPIO_A, 'out'),
)

def blink(gpio):
    for i in range(5):
        gpio.digital_write(GPIO_A, GPIO.HIGH)
        time.sleep(i)
        gpio.digital_write(GPIO_A, GPIO.LOW)
        time.sleep(1)

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(
        description='Blink LED on GPIO A (pin 23)')
    args = parser.parse_args()

    with GPIO(pins) as gpio:
        blink(gpio)

基本はLチカなので実行すればGPIO_A(GPIO 23pin)に接続したLEDが点灯します。

$ sudo python blink.py

サンプルのままなので実行に関しては特に問題はありません。部分を見ていきます。

モジュールの読み込み

from gpio_96boards import GPIO

gpio_96boarsがモジュールになるようです。

GPIOのピンの指定

GPIO_Aを指定します。変数名もGPIO_Aなので少しわかりにくいかも。

GPIO_A = GPIO.gpio_id('GPIO_A')

指定したPINとIN/OUTのディレクションをタプルとして保存します。

pins = (
    (GPIO_A, 'out'),
)

出力

設定したタプルに対して値を書き込む処理となります。

gpio.digital_write(GPIO_A, GPIO.HIGH)

ここでは引数のgpioが先程のタプルであるpinsに相当します。 digital_write()で値を書き込むことになります。最初はなんで引数にGPIO_Aを渡さなければいけないのか謎があったのですが、タプルの中に複数のGPIOの設定を入れればいいのかと思って納得しました。

引数にはタプルので指定したGPIOと値をいれると出力ができます。C言語とは少し違う印象ですが、割りと冗長性も少なくできるのでわかりやすいです。

入力

今度は入力になりますが、出力と同様に

  1. GPIOのピンの指定
  2. GPIOからの入力

というステップになります。

出力と入力の対比をしたほうが理解がし易いかなと思います。

GPIO_A = GPIO.gpio_id('GPIO_A')
GPIO_C = GPIO.gpio_id('GPIO_C')
pins = (
    (GPIO_A, 'out'),
    (GPIO_C, 'in'),
)

ピンの設定はまんま同じですが、ディレクションに関してはタプルの中に書いていくことになります。複数のピンがあると冗長性が少なくなるのがこれでわかるかと思います。

入力に関しては

t = gpio.digital_read(GPIO_C)

こんな感じになると思います。取得した値はGPIO.HIGHとGPIO.LOWとなります。

ということでGPIO_Cのタクトスイッチを押したら、GPIO_Aに接続したLEDが点灯するサンプルをかいてみました。C言語編のソースをpythonに移植しています。

#!/usr/bin/python
import time
from gpio_96boards import GPIO

usleep = lambda x: time.sleep(x/1000000.0)


GPIO_A = GPIO.gpio_id('GPIO_A')
GPIO_C = GPIO.gpio_id('GPIO_C')
pins = (
    (GPIO_A, 'out'),
    (GPIO_C, 'in'),
)

def blink(gpio):
    led_state = GPIO.HIGH
    last_t = GPIO.LOW
    while True:
        t = gpio.digital_read(GPIO_C)
        if (t and (not last_t)) :
            gpio.digital_write(GPIO_A, led_state)
            usleep(100000)
            if led_state == GPIO.HIGH:
                led_state = GPIO.LOW
            else:
                led_state = GPIO.HIGH
        last_t = t
        usleep(1)

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(
        description='Blink LED on GPIO A (pin 23)')
    args = parser.parse_args()

    with GPIO(pins) as gpio:
        blink(gpio)

C言語編同様にタクトスイッチでON/OFFができるようになりました。起動時の引数を付けたときのusageメッセージはめんどくさいかったので直してませんw。

終わりに

これでC言語でもpythonでもGPIOの入力・出力ができるようになりました。C言語でも同じことはできるのですが、やっぱりpythonの方が作りやすいかなと思いました。

もうそろそろ作品ぽいものを作らないと行けないのですが、アイデアがちょっとまだまとまっていないのでどうすれば…。

DragonBoard 410c(Debian)でGPIOプログラミング(C言語編):少し解決

DragonBoard 410c(Debian)でGPIOプログラミング(C言語編):少し解決

前回のエントリではなかなかタクトスイッチを使ったGPIOの入力処理がうまく行かず途中で中断してしまいました。

タクトスイッチの回路をArduinoで動作するか試したり、プログラムを直したりとしていましたが、状況は好転しませんでした。

uepon.hatenadiary.com

ふと思い、GPIO_Bが原因?ではないかと思いGPIO_Cに変更してみました。 あと、タクトスイッチを押したらLEDが点灯する様にソースも編集しました。

【blink.c】

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

#include <gpio.h>

#define LED "GPIO-A"
#define TOUCH "GPIO-C"

int main()
{
        int x;
        int t = 0;
        int last_t = 0;
        int led_state = HIGH;

        if(gpio_open(gpio_id(LED), "out")){
                return (-1);
        }
        if (gpio_open(gpio_id(TOUCH), "in")){
                return(-1);
        }

        while(1){
                t = digitalRead(gpio_id(TOUCH));
                if (t && !last_t){
                        digitalWrite(gpio_id(LED), led_state);
                        usleep(100000);
                        if(led_state == HIGH){
                                led_state = LOW;
                                printf("HIGH\n");
                        } else {
                                led_state = HIGH;
                                printf("LOW\n");
                        }
                }
                last_t = t;
                usleep(1);
        }

        digitalWrite(gpio_id(LED), LOW);
        return EXIT_SUCCESS;
}

入力処理

入力に使用するGPIOのピンをTOUCHとしておき、方向を"in"とすればオープンは完了です。

if (gpio_open(gpio_id(TOUCH), "in")){
                return(-1);
        }

入力値の取得はdigitalRead()となります。引数にピン番号を与えることでOKです。値はintで帰ってきますが、HIGHtおLOWでも判別ができるようになっています。

                t = digitalRead(gpio_id(TOUCH));

ではあらためて、makeして実行してみると…

$ make
gcc -DPACKAGE_NAME=\"96BoardsGPIO\" -DPACKAGE_TARNAME=\"96boardsgpio\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"96BoardsGPIO\ 0.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"96boardsgpio\" -DVERSION=\"0.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -I.    -l96BoardsGPIO -g -O2 -MT blink-blink.o -MD -MP -MF .deps/blink-blink.Tpo -c -o blink-blink.o `test -f 'blink.c' || echo './'`blink.c
mv -f .deps/blink-blink.Tpo .deps/blink-blink.Po
/bin/bash ../libtool  --tag=CC   --mode=link gcc -l96BoardsGPIO -g -O2   -o blink blink-blink.o  -lsoc
libtool: link: gcc -g -O2 -o blink blink-blink.o  -l96BoardsGPIO -lsoc
$ sudo ./blink
HIGH
LOW
HIGH
LOW
HIGH
LOW
^C

あれ?すんなり動きました。

動作中の動画は後日追記します。

動作状況の動画になります。

youtu.be

おわりに

GPIO_Bが動かないのは原因がわかりませんが、一応動いたので今回のエントリーとしては解決とします。GPIOのピンごとの設定ってあるんでしょうかね。

DragonBoard 410c(Debian)でGPIOプログラミング(C言語編):課題あり

DragonBoard 410c(Debian)でGPIOプログラミング(C言語編)

以前のエントリーでは、設定まで行うまででした。そこで今回は動作確認を行ったサンプルのソースを確認していこうと思います。

先日ソースからインストールを行った96BoardsGPIOのexampleディレクトリにサンプルはあります。

ドキュメント関係もこちらがいいかなと思います。

github.com

念のためピンアサインも

https://az835927.vo.msecnd.net/sites/iot/Resources/images/PinMappings/DB_Pinout.png

C言語

exampleディレクトリにあるblink.cファイルを開きます。

このプログラムの処理としては以下のような手順になっています。

  1. GPIOのポート指定(といってもポート番号の設定だけ)
  2. 指定したGPIOポートのオープン(open()のような使い方をする模様)
  3. 指定したGPIOポートへのRead/Write(exampleではLチカなのでwriteのみ)

こんな感じになります。なんとなくの印象ですがシステムコールopen()の引数にPathがないような使い方で良いようです。

ではソースを眺めてみます。

【example/blink.c】

#include <stdio.h>

/* 96BoardsGPIO header file */
#include <gpio.h>

/* Just make the pin numbers easier to remember */

int main(int argc, char * argv[])
{
        int x;
        unsigned int gpio_a = gpio_id("GPIO_A");
        /*
         * GPIO_A can also be looked up with:
         *  gpio_a = gpio_by_letter('A');
         *  gpio_a = gpio_by_pin(23);
         */

        // Open the GPIO for use.  Do so by pin number on the
        // Low Speed Expansion Connector.
        if (!gpio_open(gpio_a, "out")) {
                for (x=0; x<10; x++) {
                        digitalWrite(gpio_a, HIGH);
                        usleep(500000);
                        digitalWrite(gpio_a, LOW);
                        usleep(500000);
                }
        } else {
                fprintf(stderr, "Unable to open GPIO_A\n");
                return -1;
        }

        return 0;
}

include部分

いちばん重要なincludeの部分はgpio用のヘッダファイルをincludeファイルします。 この中ではlibsocのヘッダファイルもincludeされていますのでこれだけでいいようです。

/* 96BoardsGPIO header file */
#include <gpio.h>

GPIOのポート指定

あとは、ほぼ上記の手順そのままですが、GPIOのポート指定では3タイプの指定が可能のようです。

        unsigned int gpio_a = gpio_id("GPIO_A");
        /*
         * GPIO_A can also be looked up with:
         *  gpio_a = gpio_by_letter('A');
         *  gpio_a = gpio_by_pin(23);
         */

GPIO_Aのような指定、ポートに割り当てられている文字の指定、ダイレクトにGPIOのpinナンバーの指定、この3つのうちのどれかを指定することになります。 自分が開発を行うのであれば、ピン番号を直接指定するほうが楽かなと思いますけど、96Boards仕様のボードでのソースの移植を行うのであればサンプルと同じ方がいいのかなと思います。動作は同じようです。

指定したGPIOポートのオープン

if (!gpio_open(gpio_a, "out")) {

使用するGPIOのポートとin/outの方向を指定してgpio_open()を呼び出します。

出力処理

                        digitalWrite(gpio_a, HIGH);
                        //略
                        digitalWrite(gpio_a, LOW);
                        //略

あとは、GPIOのピンに対してHIGH/LOWを指定すれば出力が行われます。

make

そのファイルをmakeしてみると以下のようなWarningが発生しますが、成功します。

$ make
gcc -DPACKAGE_NAME=\"96BoardsGPIO\" -DPACKAGE_TARNAME=\"96boardsgpio\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"96BoardsGPIO\ 0.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"96boardsgpio\" -DVERSION=\"0.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -I.    -l96BoardsGPIO -g -O2 -MT blink-blink.o -MD -MP -MF .deps/blink-blink.Tpo -c -o blink-blink.o `test -f 'blink.c' || echo './'`blink.c
blink.c: In function ‘main’:
blink.c:24:4: warning: implicit declaration of function ‘usleep’ [-Wimplicit-function-declaration]
    usleep(500000);
    ^~~~~~
mv -f .deps/blink-blink.Tpo .deps/blink-blink.Po
/bin/bash ../libtool  --tag=CC   --mode=link gcc -l96BoardsGPIO -g -O2   -o blink blink-blink.o  -lsoc
libtool: link: gcc -g -O2 -o blink blink-blink.o  -l96BoardsGPIO -lsoc

usleep()が明示的に宣言されてないよっていう感じなので宣言をすればWarningはなくなると思います。具体的にはinclude部分で#include <unistd.h>を追加すればOKです。

【修正前】

#include <stdio.h>

/* 96BoardsGPIO header file */
#include <gpio.h>

【修正後】

#include <stdio.h>
#include <unistd.h>

/* 96BoardsGPIO header file */
#include <gpio.h>

変更すると

$ make
gcc -DPACKAGE_NAME=\"96BoardsGPIO\" -DPACKAGE_TARNAME=\"96boardsgpio\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"96BoardsGPIO\ 0.1\" -DPACKAGE_BUGREPORT=\"\" -DPACKAGE_URL=\"\" -DPACKAGE=\"96boardsgpio\" -DVERSION=\"0.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_DLFCN_H=1 -DLT_OBJDIR=\".libs/\" -I.    -l96BoardsGPIO -g -O2 -MT blink-blink.o -MD -MP -MF .deps/blink-blink.Tpo -c -o blink-blink.o `test -f 'blink.c' || echo './'`blink.c
mv -f .deps/blink-blink.Tpo .deps/blink-blink.Po
/bin/bash ../libtool  --tag=CC   --mode=link gcc -l96BoardsGPIO -g -O2   -o blink blink-blink.o  -lsoc
libtool: link: gcc -g -O2 -o blink blink-blink.o  -l96BoardsGPIO -lsoc

Warningはなくなりました。

入力

digitalWrite()でLチカができたので今度は入力もやってみたいなあと思いました。

#include <stdio.h>
#include <unistd.h>

#include <gpio.h>

int main(int argc, char * argv[])
{
        int x;
        int v;
        unsigned int gpio_b = gpio_id("GPIO_B");

        if (!gpio_open(gpio_b, "in")) {
                for (x=0; x<3; x++) {
            v = digitalRead(gpio_b);
                        if (v != -1){
                                if (v == HIGH){
                                        printf("HIGH\n");
                                }
                                else {
                                        printf("LOW\n");
                                }
                        }
                        usleep(500000);
                }
        } else {
                fprintf(stderr, "Unable to open GPIO_B\n");
                return -1;
        }

        return 0;
}

このようなファイルにしてタクトスイッチの状態を調べたのですが、どうしてもうまくいきません。値が固定になっているような気がします。スイッチを押しても離してもHIGHのままで、スイッチ回路を諦めてGNDに直結してもNGでした。

$ make ; sudo ./blink
HIGH
HIGH
HIGH

GPIO_Bを使用していたのでもしかしてGPIOのピン側に問題があるのかなと思い、output側でテストすると問題なくLチカはできました。

その後、同じプログラムを実行すると

$ sudo ./blink
LOW
LOW
LOW

今度は固定的にLOWのままになってしまいました。起動時はHIGHで、変更があった際にはそのあとの値が保持されている様です。

ちょっと自分にはお手上げ感ありです。 inputのサンプル実験している人も見当たらず。うーん。

おわりに

Lチカが終わったので結構安心していたのですが、入力に関してはまだうまく行っていません。もう少し調べたいと思います。

/* -----codeの行番号----- */