ラベル プログラミング の投稿を表示しています。 すべての投稿を表示
ラベル プログラミング の投稿を表示しています。 すべての投稿を表示

2021年1月16日土曜日

テルシス語翻訳スクリプトをパワーアップ

注:さらに進化したバージョンはこちら:
記事は英語しかなく。。。ごめんなさい。🙇‍♀️いつか日本語で書きます!

先日テルシス語(ヴァイオレット・エヴァーガーデン世界)翻訳Pythonスクリプトを書いたばかりですが、 テルシス語の解読しかできなく、性能は欠けていると思いました。

よって、休み時間を使って、パワーアップしました。
 
かなり増強しました。
解読だけではなく、テルシス語で書くこともできます。
解読する時、言語指定もできます。
バックエンドはGoogle Translateです。

とりあえず、v0.1をGitHubに載せました。
ここです。

コマンドラインからの実行例:
$ ./telsistrans.py -t "I love Major \Gilbert\ " -sl en
Nun posuk Gilbert ui gikapmarikon
$ ./telsistrans.py -t "Posuk \Gilbert\ nunki." -sl telsis
Thank you Major Gilbert.

インタラクティブモードもあります:
$ ./telsistrans.py -i
Source language: en
Input source text: I love you
Target language:       
In Tamil script: நான் உன்னை நேசிக்கிறேன்
Pronunciation: Nāṉ uṉṉai nēcikkiṟēṉ
In unaccented characters: Nan unnai necikkiren
In target language: Nun annui noyirrikon
Source language: telsis
Input source text: Nunki posuk
Target language: ja
In Tamil script: நன்றி மேஜர்
Pronunciation:
In unaccented characters: Nanri mejar
In target language: ありがとう少佐


Pythonスクリプト内でライブラリーとしても使用できます:
from telsistrans import telsis_translator
translator = telsis_translator()
srctext = "I love you"
srclang = 'en'
translator.lang2telsis(srctext, srclang)
print(translator.results['tgt_text'])  # Print out results of translation
srctext = "Nunki posuk"
tgtlang = 'ja'
translator.telsis2lang(srctext, tgtlang)
print(translator.results['tgt_text'])  # Print out results of translation

 
上記スクリプトを実行したアウトプット:
Nun annui noyirrikon
ありがとう少佐
 
テルシス語のフォントファイルを指定すれば、
このような出力もできます:
 「Dear Major Gilbert」(親愛なるギルベルト少佐)

 
 
 
「I love you」(君を愛しています)



 
この翻訳スクリプトを使用するため、以下のPythonライブラリーが必要です:
google_trans_new
unidecode
requests
Pillow
 
スクリプト(解読や翻訳の流れ)に関する説明もレポジトリーに載せましたが、
英語です。

テルシス語について、少し説明します。
ヴァイオレット・エヴァーガーデンの世界観設定を担当した鈴木貴昭さんがスタッフイベントで、
日本語原文を英語へ翻訳し、
英文をまた別の言語に翻訳し、
その結果のアルファベットを暗号化して、
最後にテルシス語の文字にする、と説明しました。
その別の言語は言及しませんでしたが、
すでに「タミル語」と特定した人々がいます。
ようするに、
テルシス語はタミル語を暗号化したものです。
その暗号は、英文字の置き換え(スワップ)です。 
ネット同志の努力で、
おそらく
A ⇔ U
C ⇔ Y 
E ⇔ O
G ⇔ V
H ⇔ T
K ⇔ R
M ⇔ P
で英文字を置き換えたと推測しました。
ネット同志は、S、Lについて少し悩んでいたみたいです。
個人的に、
J ⇔ S
L ⇔ Q
で置き換えられていたと思います。
確かではありませんが、この翻訳スクリプトではこのように置き換えます。

作ったばかりで、まだ完全にテストしたものではありません。
でも、出力は合っていると思います。😅
コンソルでの使用ですが、少し慣れていない方には難しいかもしれません。。。🙇‍♀️
将来的にTkで簡単なGUIを作ろうとは思いますが。。。
GUIを作るのが大嫌いで、おそらくなかなかできはしないでしょう。 

英語ブログにもこのスクリプトについて書きました。)

2020年1月23日更新:GUIを作りました。
Kivyを使用したGUI:

PySimpleGUIを使用したGUI:

テルシス語のフォントも作りました。

2020年1月25日更新:GUI使い方のビデオをアップしました。


2021年1月14日木曜日

テルシス語(ヴァイオレット・エヴァーガーデン世界)翻訳Pythonスクリプト

2021年1月16日更新:パワーアップしたスクリプトについてはこちらへ
 
ヴァイオレット・エヴァーガーデン世界で使用されているテルシス語を英語へ翻訳するPythonスクリプトがあります。

それを少し改造して、日本語へ翻訳できるようにしました。
英語ブログから流用しました。)

使用するにはgoogle_trans_newライブラリーが必要です。
pip3 install google_trans_new

Google翻訳APIサービスは有料ですが、
google_trans_newは無料で使わせてくれるみたいです。
でも、商用では使えません。ご注意ください。

現在、ターゲット言語を日本語に設定しました。例えば、英語にしたい場合、
target_language = 'ja'
を以下のように書き換えてください。
target_language = 'en'
 
スクリプトの実行
python3 nunkish_translator_2.py

スクリプト(ファイルネーム:nunkish_translator_2.py)
-----------------
from google_trans_new import google_translator  
import requests
 
translator = google_translator()  

alphabet = {
    'a': 'u',
    'b': '',
    'c': 'y',
    'd': '',
    'e': 'o',
    'f': '',
    'g': 'v',
    'h': 't',
    'i': 'i',
    'j': '',
    'k': 'r',
    'l': 'i',
    'm': 'p',
    'n': 'n',
    'o': 'e',
    'p': 'm',
    'q': 'l',
    'r': 'k',
    's': 'y',
    't': 'h',
    'u': 'a',
    'v': 'g',
    'w': '',
    'x': '',
    'y': 'c',
    'z': '',
    'A': 'U',
    'B': '',
    'C': 'Y',
    'D': '',
    'E': 'O',
    'F': '',
    'G': 'V',
    'H': 'T',
    'I': 'I',
    'J': '',
    'K': 'R',
    'L': 'I',
    'M': 'P',
    'N': 'N',
    'O': 'E',
    'P': 'M',
    'Q': 'L',
    'R': 'K',
    'S': 'Y',
    'T': 'H',
    'U': 'A',
    'V': 'G',
    'W': '',
    'X': '',
    'Y': 'C',
    'Z': '',
    ' ': ' ',
    '0': '0',
    '1': '1',
    '2': '2',
    '3': '3',
    '4': '4',
    '5': '5',
    '6': '6',
    '7': '7',
    '8': '8',
    '9': '9',
}

tamil_script_url = 'https://inputtools.google.com/request?text={text}&itc=ta-t-i0-und'

source_language = 'ta'
target_language = 'ja'

def trans(nunkish):
    tamil = ""
    for char in nunkish:
        if char not in alphabet:
            tamil += char
        else:
            tchar = alphabet[char]
        if tchar:
            tamil += tchar
        else:
            tamil += "?"
    
    print(f"Converted to tamil: {tamil}")
    
    tamil_res = requests.get(tamil_script_url.format(text=tamil), headers={
        'Content-Type': 'application/json'
    }).json()
    
    if (tamil_res[0] == 'SUCCESS'):
        tamil_script = tamil_res[1][0][1][0]
    print(f"In Tamil script: {tamil_script}")
    return translator.translate(f'{tamil_script}', lang_src=
source_language, lang_tgt=target_language)

while True:
    nunkish = input("Input nunkish: ")
    print(f"You entered: {nunkish}")
    print(trans(nunkish.replace('\n', ' ').replace('\r', '')))
---------------------

M5Stick CでWiFiのRSSI表示

先日、WiFi信号の強度が知りたくて、
M5Stick Cを使ってWiFi受信RSSIを表示するスケッチを作りました。
元はこのスケッチです。
元のスケッチは時間と日付を表示するスケッチで、
それを少し改造して、
RSSIも表示するようにしました。
また、OTAアップデートもできるようにしました。

WiFiのSSIDとパスワード、タイムゾーンを入力をconfig.hファイルに以下のように記入しました。
#define TIMEZONE     9
#define WIFI_SSID   "your_wifi_ssid"
#define WIFI_PASSWORD   "your_wifi_password"


ボタンA(M5と書いてあるボタン)を押せば表示のオン・オフが切り替えられます。
ボタンB(上の小さいボタン)を2秒以上長押しすれば時間シンクロが行われます。
 
実際のスケッチは以下です。改造した結果、timeToDoという関数は必要なくなりましたが、そのまま残しました。
-----------------------------------------------------
#include <Arduino.h>
#include <M5StickC.h>
#include <ESPmDNS.h>
#include <WiFi.h>
#include "time.h"
#include "config.h"
#include <ArduinoOTA.h>

// default hostname if not defined in config.h
#ifndef HOSTNAME
  #define HOSTNAME "m5stickc"
#endif

// use the WiFi settings in config.h file
char* ssid       = WIFI_SSID;
char* password   = WIFI_PASSWORD;

// define the NTP server to use
char* ntpServer =  "ntp.nict.jp";

// define what timezone you are in
int timeZone = TIMEZONE * 3600;

// delay workarround
int tcount = 0;

// LCD Status
bool LCD = true;

RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;

//delays stopping usualy everything using this workarround
bool timeToDo(int tbase) {
  tcount++;
  if (tcount == tbase) {
    tcount = 0;
    return true;    
  } else {
    return false;
  }  
}

// Syncing time from NTP Server
void timeSync() {
    M5.Lcd.setTextSize(1);
    Serial.println("Syncing Time");
    Serial.printf("Connecting to %s ", ssid);
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setCursor(20, 15);
    M5.Lcd.println("connecting WiFi");
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      Serial.print(".");
    }
    Serial.println(" CONNECTED");
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setCursor(20, 15);
    M5.Lcd.println("Connected");
    // Set ntp time to local
    configTime(timeZone, 0, ntpServer);

    // Get local time
    struct tm timeInfo;
    if (getLocalTime(&timeInfo)) {
      // Set RTC time
      RTC_TimeTypeDef TimeStruct;
      TimeStruct.Hours   = timeInfo.tm_hour;
      TimeStruct.Minutes = timeInfo.tm_min;
      TimeStruct.Seconds = timeInfo.tm_sec;
      M5.Rtc.SetTime(&TimeStruct);

      RTC_DateTypeDef DateStruct;
      DateStruct.WeekDay = timeInfo.tm_wday;
      DateStruct.Month = timeInfo.tm_mon + 1;
      DateStruct.Date = timeInfo.tm_mday;
      DateStruct.Year = timeInfo.tm_year + 1900;
      M5.Rtc.SetData(&DateStruct);
      Serial.println("Time now matching NTP");
      M5.Lcd.fillScreen(BLACK);
      M5.Lcd.setCursor(20, 15);
      M5.Lcd.println("S Y N C");
      delay(500);
      M5.Lcd.fillScreen(BLACK);
    }
}

void buttons_code() {
  // Button A control the LCD (ON/OFF)
  if (M5.BtnA.wasPressed()) {
    if (LCD) {
      M5.Lcd.writecommand(ST7735_DISPOFF);
      M5.Axp.ScreenBreath(0);
      LCD = !LCD;
    } else {
      M5.Lcd.writecommand(ST7735_DISPON);
      M5.Axp.ScreenBreath(255);
      LCD = !LCD;
    }
  }
  // Button B doing a time resync if pressed for 2 sec
  if (M5.BtnB.pressedFor(2000)) {
    timeSync();
  }
}

// Printing WiFi RSSI and time to LCD
void doTime() {
  //if (timeToDo(1000)) {
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    M5.Lcd.setCursor(10, 10);
    M5.Lcd.setTextSize(1);
    M5.Lcd.printf("%s: ", WiFi.SSID());
    long strength = WiFi.RSSI();
    if(strength < -70) M5.Lcd.setTextColor(RED, BLACK);
    else if(strength < -60) M5.Lcd.setTextColor(YELLOW, BLACK);
    else M5.Lcd.setTextColor(GREEN, BLACK);
    M5.Lcd.printf("%02d\n", strength);
    M5.Lcd.setTextSize(3);
    M5.Lcd.setTextColor(WHITE, BLACK);
    M5.Rtc.GetTime(&RTC_TimeStruct);
    M5.Rtc.GetData(&RTC_DateStruct);
    M5.Lcd.setCursor(10, 25);
    M5.Lcd.printf("%02d:%02d:%02d\n", RTC_TimeStruct.Hours, RTC_TimeStruct.Minutes, RTC_TimeStruct.Seconds);
    M5.Lcd.setCursor(15, 60);
    M5.Lcd.setTextSize(1);
    M5.Lcd.setTextColor(WHITE, BLACK);
    M5.Lcd.printf("Date: %04d-%02d-%02d\n", RTC_DateStruct.Year, RTC_DateStruct.Month, RTC_DateStruct.Date);
  //}
}

void setup() {
  M5.begin();

  M5.Lcd.setRotation(1);
  M5.Lcd.fillScreen(BLACK);

  M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(WHITE,BLACK);
  timeSync(); //uncomment if you want to have a timesync everytime you turn device on (if no WIFI is avail mostly bad)

  // Port defaults to 3232
  // ArduinoOTA.setPort(3232);

  // Hostname defaults to esp3232-[MAC]
  ArduinoOTA.setHostname(HOSTNAME);

  // No authentication by default
  // ArduinoOTA.setPassword("admin");

  // Password can be set with it's md5 value as well
  // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
  // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");

  ArduinoOTA
    .onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH)
        type = "sketch";
      else // U_SPIFFS
        type = "filesystem";

      // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
      Serial.println("Start updating " + type);
    })
    .onEnd([]() {
      Serial.println("\nEnd");
    })
    .onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    })
    .onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });

  ArduinoOTA.begin();
}

void loop() {
  M5.update();
  buttons_code();
  doTime();
  ArduinoOTA.handle();
}
------------------------------------------------------------

2020年12月10日木曜日

TensorflowでGPUメモリの使用を制限

ディープラーニングという分野に興味があり、GTX 1660 Superという廉価GPUで自作PCを作りました。本格的にディープラーニングを研究する人にはこのGPUをお勧めできませんが。

このPCはほかの用途にも使用され、すべてのGPUメモリをモデル学習に使うわけではいきません。そこで、Tensorflowを使うとき、使用するGPUメモリの上限をプログラム内に設定する方法を見つかりました。

import tensorflow as tf

gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
  try:
    # Currently, memory growth needs to be the same across GPUs
    for gpu in gpus:
      tf.config.experimental.set_memory_growth(gpu, True)
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Memory growth must be set before GPUs have been initialized
    print(e)

MEMORY_LIMIT=4096
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
  # Restrict TensorFlow to only allocate 1GB of memory on the first GPU
  try:
    tf.config.experimental.set_virtual_device_configuration(
        gpus[0], [tf.config.experimental.VirtualDeviceConfiguration(memory_limit=MEMORY_LIMIT)])
    logical_gpus = tf.config.experimental.list_logical_devices('GPU')
    print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
  except RuntimeError as e:
    # Virtual devices must be set before GPUs have been initialized
    print(e)

こうすれば、使用するGPUメモリの上限がMEMORY_LIMIT(単位:MB)の値になります。
ちなみに、最近RTX 30xxシリーズのGPUが出てきて、値段もそんなに高くない。
本格的にディープラーニングを始めようとする方はそちらがお勧めです。

2019年8月16日金曜日

VIVITAシンガポールを訪問

昨日、一時帰国した時、シンガポールにあるVIVISTOP Orchardを訪問しました。
この場所はVIVITAのシンガポール「支店」です。
日本では千葉県柏市の柏の葉にVIVISTOP Kashiwanohaがあります。

子供を自由にものを作る場所で、新しく解説したシンガポール「支店」はまだまだ来場者が少なかったです。
機械や設備も少なかったですが、徐々に増やしていくと聞きました。
今がとりあえず3Dプリンター、レーザーカッター、筆記用具、電子工作の基本パーツ、そして大方CNCマシン(子供自分での使用禁止)などが置いてあります。

子供たちが自分で3DデザインをTinkerCADで作り、それを3Dプリンターで形にする。
熱加工機で自分のデザインをカバンに印刷する。
VIVITA独自の電子工作パーツでRC車をつくり、独自のソフトで制御プログラムを書く。
裁縫の得意な子は自分のぬいぐるみをつくる。
子供にとってはかなり楽しい場所です。
そして、大人スタッフもいますので、機械などの使い方も教えてくれるし、ちょっと危険そうな機械などは大人が操作してくれます。
子供も親も安心に過ごせる場所だと思います。
機会があれば、ぜひシンガポール(ちょっと遠い?)か柏の葉へ訪ねってください!😉

2019年6月1日土曜日

Jetson Nano上でVSCodeをインストール

VSCodeはマイクロソフトが開発しているプログラミング用IDEです。
Jetson Nanoではソースコードからビルドする必要があります。
手順は
Jetson nanoにVSCode+Pythonの開発環境を整える
を従いましたが、エラーが出てきて、
最終的に
Building Visual Studio Code on Jetson Nano
を参考して何とかビルドが成功しました。

一連のコマンドは:
curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash -
sudo apt-get install -y nodejs
curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list

sudo apt update
sudo apt install -y libx11-dev libxkbfile-dev libsecret-1-dev fakeroot npm curl nodejs nodejs-dev yarn

git clone https://github.com/Microsoft/vscode.git
pushd vscode
sed -i 's/4095/2048/g' package.json
scripts/npm.sh install
yarn
yarn run gulp vscode-linux-arm64-min
yarn run gulp vscode-linux-arm64-build-deb
sudo dpkg -i ./.build/linux/deb/arm64/deb/code-oss_1.??.?-*_arm64.deb

そして、拡張機能ギャラリーを有効にするため、
sudo nano /usr/share/code-oss/resources/app/product.json
を実行します。

エディタで、一番したの

の上に、
,"extensionsGallery": {
    "serviceUrl": "https://marketplace.visualstudio.com/_apis/public/gallery",
    "cacheUrl": "https://vscode.blob.core.windows.net/gallery/index",
    "itemUrl": "https://marketplace.visualstudio.com/items"
}
を追加すると拡張機能ライブラリーが有効になります。

そして、再起動して、IDEを実行。
sudo reboot
(再起動後)
code-oss

以上です!

2019年5月30日木曜日

ベーシックESP32-CAMスケッチ

ESP32カメラの続きです。
前回はOTAやmDNSなどを追加しました。
今回はとても基本的なスケッチです。
設定とかなにもありません。
全てはスケッチ内でハードコーディングされています。
https://github.com/vivian-ng/esp32_camera_streaming
スケッチではAI-ThinkerのESP32-CAMモジュールのピンアウトを使用しています。
別のカメラモジュールを使う場合、ピンの番号を変える必要があります。

ちなみに、ベースのスケッチはこれです:
https://github.com/maximemoreillon/esp32_camera_streaming

それにWiFi設定をメインのスケッチに移動、そしてmDNSを追加しただけです。

#define WIFI_SSID "ssid"
#define WIFI_PASSWORD "ssid_password"
WiFi設定はこの2行です。

#define HOSTNAME "esp32cam"
ホスト名はこの行です。
これがあれば、
http://esp32cam.local/
だけでカメラからのビデオが見れます。
ホスト名は任意に変えられます。
例えば、複数のモジュールを使っている場合、
esp32cam1
esp32cam2
などにすることもできます。

で、利点は?

まず、ウェブ上の設定ページをなくしたことによって、このESP32カメラモジュールは単純なネットワークカメラになり、MotionEyeなどで「Network camera」として使用できます。
mDNSを追加することによって、ホスト名で接続できます。
IPアドレスをしらべたりしなくても大丈夫です。
例えば、MotionEyeでカメラを追加と選択し、
Camera Typeを「Network camera」で、
カメラのURLを「http://esp32cam.local/」に入力。

また、PSRAMがあるモジュールの画像解析度についてですが、
1600x1200はできますが、(ベースのスケッチもそれになっています)
それだとESP32の処理能力がボトルネックになり、FPSが落ちます。
試した結果、やはりPSRAMがあっても800x600はベストです。

  if(psramFound()){
    Serial.println("PSRAM found");
    //config.frame_size = FRAMESIZE_UXGA;
    config.frame_size = FRAMESIZE_SVGA;
    config.jpeg_quality = 10;
    config.fb_count = 2;
  } else {

解析度を変えるには赤字のところを変えればいいです。
UXGAは1600x1200です。
SVGAは800x600です。
その他に、
QQVGA = 160x120
QQVGA2 = 128x160
QCIF = 176x144
HQVGA = 240x176
QVGA = 320x240
CIF = 400x296
VGA = 640x480
XGA = 1024x768
SXGA = 1280x1024
QXGA = 2048x1536 (メモリ的に無理かもしれません)
があります。

今度はこのスケッチにOTAを追加するかな?

2018年9月27日木曜日

割り込みでSTM32F103をスリープから起こす

前回、「STM32F103C8T6をスリープ状態にする」について書きました。

今回、一定の時間から起きる状態に加えて、外部割込みからも起きるようにしたくて、色々試しました。
やはりstm32sleepライブラリーはうまくできず、前回のtomtorさんのコードをもとにテストプログラムをつくりました。
外部割込みを使うため、attachInterruptという関数を使います。
attachInterrupt(BOARD_BUTTON_PIN, action, CHANGE);
BOARD_BUTTON_PINにスイッチをつけ、そのスイッチに変化があれば割込みが発生します。
そして、起きたら、何を実行するかは新たにactionという関数を設けました。
tomtorさんのAlarmFunctionという関数は、スリープから起きた際、クロックを再設定する操作があります。そのままactionの中に使います。
void action()
{
  AlarmFunction ();
  if (state == LOW) state = HIGH;
  else state = LOW;
}
ここはただLEDの点灯状態を反対にするだけ。

全部のコードは以下の通りです。

#include <RTClock.h>
#include <libmaple/pwr.h>
#include <libmaple/scb.h>

#define LED  PC13
#define BOARD_BUTTON_PIN PB0

// Define the Base address of the RTC registers (battery backed up CMOS Ram), so we can use them for config of touch screen or whatever.
// See http://stm32duino.com/viewtopic.php?f=15&t=132&hilit=rtc&start=40 for a more details about the RTC NVRam
// 10x 16 bit registers are available on the STM32F103CXXX more on the higher density device.
#define BKP_REG_BASE   ((uint32_t *)(0x40006C00 + 0x04))

// Setup RTClock for sleep
RTClock rt(RTCSEL_LSI, 39); // 1 milli second alarm
long int alarmDelay = 10;

void storeBR(int i, uint32_t v) {
  BKP_REG_BASE[2*i]= (v << 16);
  BKP_REG_BASE[2*i+1]= (v & 0xFFFF);
}

uint32_t readBR(int i) {
  return ((BKP_REG_BASE[2*i] & 0xFFFF) >> 16) | (BKP_REG_BASE[2*i+1] & 0xFFFF);
}

void sleepMode(bool deepSleepFlag) { 
  // Clear PDDS and LPDS bits
  PWR_BASE->CR &= PWR_CR_LPDS | PWR_CR_PDDS | PWR_CR_CWUF;

  // Set PDDS and LPDS bits for standby mode, and set Clear WUF flag (required per datasheet):
  PWR_BASE->CR |= PWR_CR_CWUF;
  // Enable wakeup pin bit.
  PWR_BASE->CR |=  PWR_CSR_EWUP;
  
  SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP;

  // System Control Register Bits. See...
  // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/Cihhjgdh.html
  if (deepSleepFlag) {
    // Set Power down deepsleep bit.
    PWR_BASE->CR |= PWR_CR_PDDS;
    // Unset Low-power deepsleep.
    PWR_BASE->CR &= ~PWR_CR_LPDS;
  } else {
    adc_disable(ADC1);
    adc_disable(ADC2);
#if STM32_HAVE_DAC
    dac_disable_channel(DAC, 1);
    dac_disable_channel(DAC, 2);
#endif
    //  Unset Power down deepsleep bit.
    PWR_BASE->CR &= ~PWR_CR_PDDS;
    // set Low-power deepsleep.
    PWR_BASE->CR |= PWR_CR_LPDS;
  }

  // Now go into stop mode, wake up on interrupt
  asm("    wfi");

  // Clear SLEEPDEEP bit so we can use SLEEP mode
  SCB_BASE->SCR &= ~SCB_SCR_SLEEPDEEP;
}

uint32 sleepTime;

void AlarmFunction () {
  // We always wake up with the 8Mhz HSI clock!
  // So adjust the clock if needed...

#if F_CPU == 8000000UL
  // nothing to do, using about 12 mA
#elif F_CPU == 16000000UL
  rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_2);
#elif F_CPU == 48000000UL
  rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_6);
#elif F_CPU == 72000000UL
  rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_9);   // 72MHz  => 48 mA  -- datasheet value           => between 40 and 41mA
#else
#error "Unknown F_CPU!?"
#endif
  
  extern volatile uint32 systick_uptime_millis;
  systick_uptime_millis+= sleepTime;
}

void mdelay(int n, bool mode= false) {
  sleepTime= n;
  time_t nextAlarm = (rt.getTime() + n); // Calculate from time now.
  rt.createAlarm(&AlarmFunction, nextAlarm);
  sleepMode(mode);
}


#define   RCC_CFGR_HPRE_DIV1   0x00000000U
#define   RCC_CFGR_HPRE_DIV2   0x00000080U
#define   RCC_CFGR_HPRE_DIV4   0x00000090U
#define   RCC_CFGR_HPRE_DIV8   0x000000A0U
#define   RCC_CFGR_HPRE_DIV16   0x000000B0U
#define   RCC_CFGR_HPRE_DIV64   0x000000C0U
#define   RCC_CFGR_HPRE_DIV128   0x000000D0U
#define   RCC_CFGR_HPRE_DIV256   0x000000E0U
#define   RCC_CFGR_HPRE_DIV512   0x000000F0U


void msleep(uint32_t ms) {
  uint32_t start= rt.getTime();
  
  while (rt.getTime() - start < ms) {
    asm("    wfi");
  }
}

int state = LOW;

void setup() {
  pinMode(LED,OUTPUT);
  pinMode(BOARD_BUTTON_PIN, INPUT_PULLUP);
}

void loop() { 
  digitalWrite(LED,state);
  delay(60);  
  attachInterrupt(BOARD_BUTTON_PIN, action, CHANGE);
  mdelay(alarmDelay * 1000);
}  

void action()
{
  AlarmFunction ();
  if (state == LOW) state = HIGH;
  else state = LOW;
}


2018年7月26日木曜日

STM32F103C8T6をスリープ状態にする

最近、天気が暑くて、「外の気温、何度かな?」と思う時が多くなりました。
そこで、外の気温を測って、室内に表示する「無線温度計」を自分で作ってみました。

STM32F103C8T6の開発ボードを使いましたが、一番の問題は、
「マイクロコントローラーをスリープ状態にする」ことです。

色々試してみました。
このstm32sleepというライブラリーも使ってみましたが、
どうもうまく行けませんでした。
そのライブラリーのもとをみて、更に探し、
tomtorさんのコードを見つかりました。
このコードの関数を使って、何とかできました!

使い方は簡単です。

Arduinoコードのloop()の一番最後のところに、
mdelay(1000);
を追加するだけで、1000ミリ秒をスリープさせます。
あ、Arduino IDEに使えるSTM32 Coreが必要ですけどね。
使っているのが、rogerclarkmelbourneさんのArduino_STM32です。
ちなみに、STMicroelectronics社の正式なものもあります。

ここから、tomtorさんのコードの抜粋です。

#include <libmaple/pwr.h>
#include <libmaple/scb.h>

#include <RTClock.h>

// Define the Base address of the RTC registers (battery backed up CMOS Ram), so we can use them for config of touch screen or whatever.
// See http://stm32duino.com/viewtopic.php?f=15&t=132&hilit=rtc&start=40 for a more details about the RTC NVRam
// 10x 16 bit registers are available on the STM32F103CXXX more on the higher density device.
#define BKP_REG_BASE   ((uint32_t *)(0x40006C00 + 0x04))

RTClock rt(RTCSEL_LSI, 39); // 1 milli second alarm

void storeBR(int i, uint32_t v) {
  BKP_REG_BASE[2*i]= (v << 16);
  BKP_REG_BASE[2*i+1]= (v & 0xFFFF);
}

uint32_t readBR(int i) {
  return ((BKP_REG_BASE[2*i] & 0xFFFF) >> 16) | (BKP_REG_BASE[2*i+1] & 0xFFFF);
}

void sleepMode(bool deepSleepFlag)
{ 
  // Clear PDDS and LPDS bits
  PWR_BASE->CR &= PWR_CR_LPDS | PWR_CR_PDDS | PWR_CR_CWUF;

  // Set PDDS and LPDS bits for standby mode, and set Clear WUF flag (required per datasheet):
  PWR_BASE->CR |= PWR_CR_CWUF;
  // Enable wakeup pin bit.
  PWR_BASE->CR |=  PWR_CSR_EWUP;
  
  SCB_BASE->SCR |= SCB_SCR_SLEEPDEEP;

  // System Control Register Bits. See...
  // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/Cihhjgdh.html
  if (deepSleepFlag) {
    // Set Power down deepsleep bit.
    PWR_BASE->CR |= PWR_CR_PDDS;
    // Unset Low-power deepsleep.
    PWR_BASE->CR &= ~PWR_CR_LPDS;
  } else {
    adc_disable(ADC1);
    adc_disable(ADC2);
#if STM32_HAVE_DAC
    dac_disable_channel(DAC, 1);
    dac_disable_channel(DAC, 2);
#endif
    //  Unset Power down deepsleep bit.
    PWR_BASE->CR &= ~PWR_CR_PDDS;
    // set Low-power deepsleep.
    PWR_BASE->CR |= PWR_CR_LPDS;
  }

  // Now go into stop mode, wake up on interrupt
  asm("    wfi");

  // Clear SLEEPDEEP bit so we can use SLEEP mode
  SCB_BASE->SCR &= ~SCB_SCR_SLEEPDEEP;
}

uint32 sleepTime;

void AlarmFunction () {
  // We always wake up with the 8Mhz HSI clock!
  // So adjust the clock if needed...

#if F_CPU == 8000000UL
  // nothing to do, using about 12 mA
#elif F_CPU == 16000000UL
  rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_2);
#elif F_CPU == 48000000UL
  rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_6);
#elif F_CPU == 72000000UL
  rcc_clk_init(RCC_CLKSRC_HSI, RCC_PLLSRC_HSE , RCC_PLLMUL_9);   // 72MHz  => 48 mA  -- datasheet value           => between 40 and 41mA
#else
#error "Unknown F_CPU!?"
#endif
  
  extern volatile uint32 systick_uptime_millis;
  systick_uptime_millis+= sleepTime;
}

void mdelay(int n, bool mode= false)
{
  sleepTime= n;
  time_t nextAlarm = (rt.getTime() + n); // Calculate from time now.
  rt.createAlarm(&AlarmFunction, nextAlarm);
  sleepMode(mode);
}


#define   RCC_CFGR_HPRE_DIV1   0x00000000U
#define   RCC_CFGR_HPRE_DIV2   0x00000080U
#define   RCC_CFGR_HPRE_DIV4   0x00000090U
#define   RCC_CFGR_HPRE_DIV8   0x000000A0U
#define   RCC_CFGR_HPRE_DIV16   0x000000B0U
#define   RCC_CFGR_HPRE_DIV64   0x000000C0U
#define   RCC_CFGR_HPRE_DIV128   0x000000D0U
#define   RCC_CFGR_HPRE_DIV256   0x000000E0U
#define   RCC_CFGR_HPRE_DIV512   0x000000F0U


void msleep(uint32_t ms)
{
  uint32_t start= rt.getTime();
  
  while (rt.getTime() - start < ms) {
    asm("    wfi");
  }
}

2018年7月13日金曜日

MPU9250付のM5Stack Grayを紹介

M5Stack Grayは先日紹介したM5Stack Basic CoreのV2です。

見た目は同じ、ただ色が灰色になっただけ。
中身もほぼ一緒ですが、
GrayはMPU9250モーションセンサーがついています。
後はBasicと同じです。

ちなみに、LoRAモジュールはこんな感じです。




最近はDRV8825ステッパードライバー(x3)のモジュールも出したみたいです。


2018年7月12日木曜日

ESP32 DevKitCクローン

今日はこのESP32の開発ボードを紹介します。
これは、一般的なESP32 DevKitCの中国クローンです。
一般的なESP32モジュールESP-WROOM-32が載っていて、
プラス4Mbのフラッシュメモリもあります。
ESP32の全てのIOピンにアクセスでき、
USB-to-serialのICもあり、USBでPCとつながり、Arduino IDEを使ってプログラムできます。

ESP32についての日本語情報は、ここから入手できます。

プログラムは、
ESP-IDF
Arduino-ESP32
MicroPython
で作れます。

ESP-IDFはESP32の機能を最大限活用できますが、
C/C++に慣れていない方にとってはちょっと難しいです。
Arduino-ESP32なら、Arduinoの開発環境でプログラム作れます。
開発は少ししやすくなります。
MicroPythonはPython言語の実装、
より「ハイレベル」のプログラミング言語で開発ができます。
でも、RAMが少ないと、ちょっと制限されている感じがします。
普通のESP32モジュールは320KbのRAMしかありません。
MicroPythonをもっと活用したいなら、PSRAM付のモジュールを使いましょう。

2018年7月11日水曜日

M5Stack Basic Coreを紹介

中国のスタートアップM5Stack社が出した初代ESP32製品がこのM5Stack Basic Coreです。
色は黒。

このようなケースで来ました。

簡単な取説書も入っています。

機能として、ESP32マイクロコントローラーに、
2インチTFT
1Wスピーカー
microSDカードリーダー
150mAhバッテリー
2x15のIOピン
Groveコネクター
3つのユーザボタン
がついています。ESP32はWiFiとBluetooth機能がついています。
基本的なArduinoスケッチもGitHubから入手できます。
https://github.com/m5stack/M5Stack
M5Stack用ライブラリーへのリンクも載っています。

Arduino IDEにESP32の設定が既に完了している方なら、そのまま使えます。
ボードマネージャーからM5Stackを選べば大丈夫です。

ESP32を使ってIoT開発を行う方なら、とても便利なものです。
TFTがありますから、PCなくても文字・絵の出力ができます。
microSDカードへの読み書きもでき、データの保存に困りません。
そして、バッテリーが付いていて、持ち運びやすいです。
基本的な入力としてボタンが使えます。
本当に便利です。

そして、色々な機能モジュールも別売りで、
自由に拡張できます。
例えば、LoRAを試したい時はLoRAモジュールを購入、
GPS機能が必要ならGPSモジュールを購入。

自分の試作を作るためのPCB(Prototypeモジュール)もあります。

購入を考えているかたは、スイッチサイエンスから購入できます。
macsbug様が色々作っているみたいです。試作品やスケッチを見るとかなり面白そうです。
一応、私もGPSモジュールを使って、自宅までの直線距離を分かるようなスケッチも試してみました。

M5Stack社が結構頻繁にM5Stack用の新モジュールを出しています。
公式SNSから新商品や開発中のものについての情報が入手できます。
M5Stack社のFacebookページ
M5Stack社のTwitter

2018年5月22日火曜日

新しい開発板、ESP-32Fキットを購入

果云科技という中国メーカーのESP-32F開発キットを購入しました。
Image result for esp-32f kit
Image result for esp-32f kit
0.96インチOLEDバージョンや1.44インチTFTバージョンもあります。
M5Stackのぱくり版みたいのものです。
でも、M5Stackより大きいし、ケースもありません。
そして、このキットに関する情報がとても少ないのです。
英語のサイトはなし、日本語のサイトももちろんありません。
見つけたのが中国語のサイトに、
ESP-32F関連ソフトやマニュアルのダウンロードサイトです。

幸い、中国語がわかります。
そして、Arduino IDEにESP-32Fを追加した時、
自分で苦労した分、みんなが同じようにならないため、
ここで簡単に手順を紹介します。

まず、ESP-32Fのマニュアルやソフトは
https://pan.baidu.com/s/1ycfadOAvoBZxL1R_L1MY-A
からダウンロードできます。中国語ですけどね。
暗号やパスワードに聞かれたら、bwleを入力してください。

そこのArduino ESP32というフォルダから、
arduino-esp32.rar
というファイルをダウンロードします。

次に、Arduinoのhardware/espressif/esp32にboards.txtというファイルに、
以下のものを追加します。
ーー追加開始ーー
esp-32f.name=ESP-32F

esp-32f.upload.tool=esptool
esp-32f.upload.maximum_size=1310720
esp-32f.upload.maximum_data_size=294912
esp-32f.upload.wait_for_upload_port=true

esp-32f.serial.disableDTR=true
esp-32f.serial.disableRTS=true

esp-32f.build.mcu=esp32
esp-32f.build.core=esp32
esp-32f.build.variant=esp-32f
esp-32f.build.board=ESP-32F

esp-32f.build.f_cpu=240000000L
esp-32f.build.flash_mode=dio
esp-32f.build.flash_size=4MB
esp-32f.build.boot=bootloader_esp32f
esp-32f.build.partitions=default

esp-32f.menu.FlashFreq.80=80MHz
esp-32f.menu.FlashFreq.80.build.flash_freq=80m
esp-32f.menu.FlashFreq.40=40MHz
esp-32f.menu.FlashFreq.40.build.flash_freq=40m

esp-32f.menu.UploadSpeed.921600=921600
esp-32f.menu.UploadSpeed.921600.upload.speed=921600
esp-32f.menu.UploadSpeed.115200=115200
esp-32f.menu.UploadSpeed.115200.upload.speed=115200
esp-32f.menu.UploadSpeed.256000.windows=256000
esp-32f.menu.UploadSpeed.256000.upload.speed=256000
esp-32f.menu.UploadSpeed.230400.windows.upload.speed=256000
esp-32f.menu.UploadSpeed.230400=230400
esp-32f.menu.UploadSpeed.230400.upload.speed=230400
esp-32f.menu.UploadSpeed.460800.linux=460800
esp-32f.menu.UploadSpeed.460800.macosx=460800
esp-32f.menu.UploadSpeed.460800.upload.speed=460800
esp-32f.menu.UploadSpeed.512000.windows=512000
esp-32f.menu.UploadSpeed.512000.upload.speed=512000
ーー追加終了ーー

そして、ダウンロードしたRARファイルのesp32/variantsディレクトリから、
esp-32f
というディレクトリをArduinoのhardware/espressif/esp32/variantsへコピーします。
また、ダウンロードしたRARファイルのesp32/tools/sdk/binディレクトリから、
bootloader.bin
というファイルをArduinoのhardware/espressif/esp32/tools/sdk/binへコピーし、
bootloader_bootloader_esp32f_80m.bin
に名前を変更します。

ちなみに、ダウンロードしたRARファイルのesp32/librariesディレクトリには
ESP-32F
というディレクトリがあります。
中にはESP-32F関連のexamplesがあります。
RGB LEDのスケッチやスピーカーのスケッチを試しでコンパイルして、
ESP-32Fへアップし、ちゃんと動くかどうかを確認しましょう。

この情報が役に立てればうれしいです!😊

2018年1月26日金曜日

スリープでATTiny85の消費電力を抑える

低い電力消費プロジェクトを作るために、
ATTiny85というマイクロコントローラーを勉強しています。

消費電力を抑えるためには、
マイクロコントローラーをスリープさせ、
インタラプトでマイクロコントローラーを起こすのが鍵です。

でも、ATTiny85は一つのピンインタラプトしかありません。
複数のピンで反応させるには、pin change interruptという方法が必要です。
Pin change interruptを可能にすれば、
ピンの電圧が変わると、インタラプトが発生します。

今回の例は二つのスイッチ(PB0とPB2につないである)によって、
どっちかがオープンになればLEDを点灯します。

まずは
GIMSK |= _BV(PCIE);
でpin change interruptを可能にします。

そして、インタラプトに使いたいピンを設定します。
PCMSK |= _BV(PCINT0);  // PB0
PCMSK |= _BV(PCINT2);  // PB2

次は使わないADCをオフに、スリープのモード()完全にパワーダウン)を設定します。
ADCSRA &= ~_BV(ADEN);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sei();

そして、実際にスリープをさせます。
sleep_cpu();

で、起きたら、もとへ戻します。
cli();
PCMSK &= ~_BV(PCINT0);
PCMSK &= ~_BV(PCINT2);
sleep_disable();
ADCSRA |= _BV(ADEN);
sei();

サンプルコードはこれです。
#include <avr/sleep.h>
#include <avr/interrupt.h>

const int switchPin1                     = 0;
const int switchPin2                     = 2;
const int statusLED                     = 1;

void setup() 
{

    pinMode(switchPin1, INPUT);
    pinMode(switchPin2, INPUT);
    digitalWrite(switchPin1, HIGH);
    digitalWrite(switchPin2, HIGH);
    pinMode(statusLED, OUTPUT);
}

void sleep()
{

    GIMSK |= _BV(PCIE);  // Enable Pin Change Interrupts
    PCMSK |= _BV(PCINT0);  // Use PB0 as interrupt pin
    PCMSK |= _BV(PCINT2);  // Use PB2 as interrupt pin
    ADCSRA &= ~_BV(ADEN);  // ADC off
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();  // Sets the Sleep Enable bit
    sei();  // Enable interrupts
    sleep_cpu();  // sleep

    cli();  // Disable interrupts
    PCMSK &= ~_BV(PCINT0);  // Turn off PB0 as interrupt pin
    PCMSK &= ~_BV(PCINT2);  / Turn off PB2 as interrupt pin
    sleep_disable();  // Clear SE bit
    ADCSRA |= _BV(ADEN); // ADC on

    sei();  // Enable interrupts
}

ISR(PCINT0_vect) {
}

void loop()
{
    sleep();
    if(digitalRead(switchPin1) == HIGH) {
        digitalWrite(statusLED, HIGH);
        delay(1000);
        digitalWrite(statusLED, LOW);
    }
    else
        digitalWrite(statusLED, LOW);
    if(digitalRead(switchPin2) == HIGH) {
        digitalWrite(statusLED, HIGH);
        delay(2000);
        digitalWrite(statusLED, LOW);
    }
    else
        digitalWrite(statusLED, LOW);
}


2018年1月17日水曜日

Arduinoで無線送受信モジュールを使ってみました

Arduinoで無線リンクのやり方を習うため、
低コストで少量のデータ送受信ができる433MHzの無線送受信モジュールを注文しました。

使い方はとても簡単です。
まず、RadioHeadというライブラリをダウンロードし、librariesフォルダにおきます。
そして、二つのArduinoを準備します。

一つは送信用、一つは受信用です。

送信用コード:
#include <RH_ASK.h>
#include <SPI.h> // Not actually used but needed to compile

RH_ASK driver;

void setup()
{
    Serial.begin(9600);   // Debugging only
    if (!driver.init())
         Serial.println("init failed");
}

void loop()
{
    const char *msg = "Hello World!";
    driver.send((uint8_t *)msg, strlen(msg));
    driver.waitPacketSent();
    Serial.print("sent ");
    Serial.println(msg);
    delay(5000);
}

受信用コード:
#include <RH_ASK.h>
#include <SPI.h> // Not actualy used but needed to compile

RH_ASK driver;

void setup()
{
    Serial.begin(9600); // Debugging only
    if (!driver.init())
         Serial.println("init failed");
    else
         Serial.println("ready");
}

void loop()
{
    uint8_t buf[12];
    uint8_t buflen = sizeof(buf);
    if (driver.recv(buf, &buflen)) // Non-blocking
    {
      int i;
      // Message with a good checksum received, dump it.
      Serial.print("Message: ");
      Serial.println((char*)buf);         
    }
}

送信モジュールのVCCを送信用Arduinoの5V、GNDをアース、DATAをピン12に接続します。
受信モジュールのVCCを受信用Arduinoの5V、GNDをアース、DATAをピン11に接続します。

両方のArduinoに電源を入れ、受信用Arduinoをコンピューターにつながり、
9600bpsでSerial接続します。
すると、
ready
Message: Hello World!
Message: Hello World!
Message: Hello World!
のような出力が出てくるはずです。
これで、一つのArduinoからもう一つのArduinoへメッセージを送ることができます。

ちなみに、日本では電波法というものがあり、
規制もとても厳しいです。
免許なくても自由に使える帯域が本当に少ないです。
今回使用するモジュールは433MHz、
そして315MHzのモジュール(aitendo発売)もあります。
しかし、433MHzも315MHzも規制があります。
使用する433MHzモジュールは低出力(10mW)なので、
規制を越えるような電波強度は出ないと思いますが、
念のため、継続使用や量産などはちゃんと法律を確認し、
出力を確認して、必要な免許を取ってからお使いください。

プログラムや配線等の参考はこちらです。(少し換えましたが。)
電波法などは総務省の専用ページを確認しましょう。

2018年1月15日月曜日

ESP32用のWiFiManagerライブラリを発見

最近、IoT開発を始めようと思って、
ESP32というマイクロコントローラーの開発ボードをEBayで購入しました。
でも、まだできたばかりのチップなので、
ESP8266とくらべて、Arduino IDE上のライブラリサポートも欠けています。
特にESP8266のWiFiManagerというライブラリがESP32で動けないので、
WiFiの設定がちょっと難しいです。

そこで、ネットで調べたら、
ESP32用のWiFiManager(ESP8266のを改造したそうです)を見つけました。
WIFIMANAGER-ESP32

インストールの仕方として、
Arduinoのlibrariesフォルダーに入り、
GitHubから必要なライブラリをクローンします。
git clone https://github.com/zhouhan0126/WIFIMANAGER-ESP32.git
git clone https://github.com/zhouhan0126/WebServer-esp32.git
git clone https://github.com/zhouhan0126/DNSServer---esp32.git

そして、WIFIMANAGER-ESP32フォルダー内に、
/examples/AutoConnect/AutoConnect.ino
をArduino IDEでオープンし、ESP32開発ボードにアップロードします。
完了したら、パソコンやスマフォのWiFiをAutoConnectAPへ接続し、
ウェブブラウザでhttp://192.168.4.1/へアクセスし、WiFiの設定を行います。
一回行えば、WiFi設定が記録され、次回から再設定する必要がありません。

AutoConnect.ino
setup()ではそのまま使えます。
あとはloop()に実行するコートを入れれば大丈夫です。
その他の使用例はexamplesフォルダーにもありますので、
適宜に参考してください。✌

2017年11月28日火曜日

Google BooksのAPIから情報を入手する

先日、書籍管理ツールを作りたいと書きました。
では、書籍情報をどのように自動的に入手できるか、
やってみました。

使ったのがGoogle BooksのAPIです。
使用言語はJavaです。

まず、あるISBN isbn(文字列)を使って情報を入手するには、
URL url = new URL("https://www.googleapis.com/books/v1/volumes?q=isbn:" + isbn);

そして、もらった情報(JSON形式)をStringBufferに換えます、
JSONObjectに変換します。
例えば、JSONObjectがjObjの場合、
JSONArray items = jObj.getJSONArray("items");
で情報をJSONArrayに換えたあと、
情報が入っているJSONObjectは
items.getJSONObject(0).getJSONObject("volumeInfo")
です。

そして、各項目のキーは、
書籍名:key("title")

出版社:key("publisher")
出版年:key("publishedDate")
著者(リスト):key("authors")
ジャンル(リスト):key("categories")
です。

日本語の書籍も、書籍名、出版社、著者は日本語のままです。
しかし、ジャンルは英語です。

あとはUIを作るだけだ!
と思いますが、それは私の苦手なところです。。。😅

2017年11月16日木曜日

Javaで音を鳴らす

Javaで警告など音を鳴らすにはどうすればいいでしょうか?
WAVファイルを再生する方法もあります。
でも、BASICならSOUNDPLAYコマンドのように、
単純にある周波数を一定の時間に鳴らすのができないのか?

グーグルで調べたら、
Toolkit.getDefaultToolkit().beep();
というメソッドがあります。
(事前にimport java.awt.Toolkit;
をする必要がありますけど。)
でも、なぜかLinux Mintでなりませんでした。

もう少し探したら、StackOverflowでこのクラスを見つけました。
まさかBASICのSOUNDコマンドと同じ、
ある周波数を一定の時間に鳴らす。
700Hzを0.5秒に鳴らすには、
SoundUtils.tone(700,500);
  
ここで紹介します。ーーーーーーーーーーーーーーーーーーーーー
import javax.sound.sampled.*;

public class SoundUtils {

  public static float SAMPLE_RATE = 8000f;

  public static void tone(int hz, int msecs)
     throws LineUnavailableException
  {
     tone(hz, msecs, 1.0);
  }

  public static void tone(int hz, int msecs, double vol)
      throws LineUnavailableException
  {
    byte[] buf = new byte[1];
    AudioFormat af =
        new AudioFormat(
            SAMPLE_RATE, // sampleRate
            8,           // sampleSizeInBits
            1,           // channels
            true,        // signed
            false);      // bigEndian
    SourceDataLine sdl = AudioSystem.getSourceDataLine(af);
    sdl.open(af);
    sdl.start();
    for (int i=0; i < msecs*8; i++) {
      double angle = i / (SAMPLE_RATE / hz) * 2.0 * Math.PI;
      buf[0] = (byte)(Math.sin(angle) * 127.0 * vol);
      sdl.write(buf,0,1);
    }
    sdl.drain();
    sdl.stop();
    sdl.close();
  }

  public static void main(String[] args) throws Exception {
    SoundUtils.tone(1000,100);
    Thread.sleep(1000);
    SoundUtils.tone(100,1000);
    Thread.sleep(1000);
    SoundUtils.tone(5000,100);
    Thread.sleep(1000);
    SoundUtils.tone(400,500);
    Thread.sleep(1000);
    SoundUtils.tone(400,500, 0.2);

  }
}