Blog移動 (Blog change) [その他]
Arduino DDS_VFO Ver.1 Ver.2 Ver.3 [Aruduino]
いつもお世話になっているKさんが、ArduinoVFO2.2inchTFTを1.8inchTFTにスケールダウンしてくれた。これで1.44,1.8,2.2と3サイズがそろった。製作機器、ケースに合わせて選択できる。Kさん有難う。
左から1.44inchTFT 1.8inchTFT 2.2inchTFT (クリックで拡大)
Arduino DDS_VFO(2) [Aruduino]
早々 ルーマニアの yo6qcm Nicさんが、追試してくれました。
私の作ったものがルーマニアで動いていることは本当に嬉しいことです。
Nicさん有難う。
YO6QCM Nic in Romania tested in a hurry.
The VFO controller I made is that I'm really happy to be moving in Romania.
Thank you very much for Mr. Nic.
Arduino DDS_VFO Ver.2 2.2inchLCD [Aruduino]
Arduino DDS_VFO(3) DDS周波数ずれ対策 [Aruduino]
arduinoによるDDS-VFOは、一応完成したが周波数ずれの対応が出来ていない。特に中華DDSの基準発振器は怪しい。今回製作したもので数百hzのずれがあった。
以前作ったBASCOM版DDS-VFOでは、その調整が出来るようプログラミング出来たが、今回採用している<EF-AD9850.h>ライブラリーでは、スケッチ側から基準周波数を指定せず、ライブラリーの内部で設定されている。<AD9850.h>というライブラリーでは、スケッチ側から基準周波数を指定しているので、これならばスケッチ側で変更可能である。こちらのほうが便利かもしれない。
取敢えず今回<EF-AD9850.h>ライブラリーを変更して修正を行った。
修正箇所はライブラリーディレクトリー内部のEF-AD9850.cppというファイル名のファイルをテキストエディタなどで開く。
76行目
x=4294967295/125;//Suitable for 125M Crystal
この行の125を変更することにより出力周波数が変わる。勿論DDSを十分エージングしてから行うこと。
また、125Mhz基準発振器を別の周波数に変更したときも、ここで変更すればOK
今回は以下のように変更した。少々根気がいる作業である。
x=4294967295/124.99705;//Suitable for 125M Crystal
これで気持ちよく使えるようになった。
こんどは<AD9850.h>を使ってスケッチ側で変更できるようにしてみるつもりである。
Arduino DDS_VFO(2) [Aruduino]
前回に続いてVFO製作。今回はスイッチ関係とSメータ表示を付け加え完成としたい。
回路は前回掲載しているのでそちらを参照願いたい。説明のためスケッチの一部を以下に記載。これだけでは動作しないのでご注意。別途スケッチをダウンロード願います。
最初にスイッチの取り込みや出力、アナログ取り込み等の設定をする。
ポートを分かりやすい名称に設定(将来ポート変更があってもここで変更すれば簡単に修正できる)
const byte s_meter=A0; // Sメータ値アナログ入力
const byte modesw=A1; // モード切替スイッチ(入力)
const byte modeout=A2; // モード切替情報出力(出力)
const byte stepsw=A3; // 周波数ステップ切替スイッチ(入力)
const byte ritsw=A4; // RIT on/offスイッチ(入力)
const byte txsw=A5; // 送信情報取り込み(入力)
読み替えたI/Oをvoid setup()内で入出力プルアップ設定する
void setup() {
pinMode(modesw,INPUT_PULLUP); // モード設定INPUTTプルアップ付き
pinMode(modeout,OUTPUT); // モード情報を外部キャリア切替に出力(LSB,Low CW High)
pinMode (stepsw,INPUT_PULLUP); // ステップ切替設定INPUTTプルアップ付き
pinMode (ritsw,INPUT_PULLUP); // リットON/OFF設定INPUTTプルアップ付き
pinMode(txsw,INPUT_PULLUP); // 送信情報(Low)INPUTTプルアップ付き
:
:
メインプログラムのloop()内でスイッチ変化を読み取る
void loop(){
if (digitalRead(modesw)==LOW){modeset();} //modeスイッチを押したときmodeset()サブルーチンに飛ぶ
if (digitalRead(stepsw)==LOW){setstep();} // STEPスイッチを押したときsetstep()サブルーチンに飛ぶ
if (digitalRead(ritsw)==LOW){setrit();} // ritスイッチを押したときsetrit()サブルーチンに飛ぶ
if (digitalRead(txsw)==LOW){txset();} //送信情報が入力されたらtxset()サブルーチンに飛ぶ
smeter(); //条件無しで毎回smeter()サブルーチンに飛ぶ
:
:
loop()内でスイッチ変化が検出されたときに各サブルーチンにジャンプしてそれぞれのプログラムを実行する。
全部の内容を記載するのは大変なので代表的にmode変更サブルーチンを掲載します。その他スケッチ全体で何かご質問でもあれば、コメント欄やメールでも頂ければ幸いです。
modeスイッチが押されたときに実行されるサブルーチン
void modeset(){ // サブルーチン宣言
if (flagmode==0){ // モードフラグが「0」なら以下を実行
flagmode=1; // モードフラグを「1」に変更
ifshift=ifshiftCW; // IFshift周波数をCW用に設定
digitalWrite(modeout,HIGH); // A2pinをHighにする。外部キャリア切替用信号
}
else{ // モードフラグが「0」で無ければ
flagmode=0; // モードフラグを「0」に変更
ifshift=ifshiftLSB; // IFshift周波数をLSBに変更
digitalWrite(modeout,LOW); // A2pinをLowにする。外部キャリア切替信号
}
tft.fillRect(5,41,36,14,BLACK); // 画面のモード表示部分を黒で塗りつぶし
tft.setCursor(5,41); // カーソル位置設定
tft.setTextSize(2); // 文字サイズを「2」に設定
tft.setTextColor(MAGENTA); // 文字色をマゼンタに設定
if (flagmode==0){tft.print("LSB");} // modeフラグが「0」ならばLSBと表示
if (flagmode==1){tft.print("CW");} // modeフラグが「1」ならばCWと表示
ddswrite(); // シフト周波数が変更となるのでDDSに書き込む while(digitalRead(modesw) == LOW); // モードスイッチがOFFになるのを待つ
}
このサブルーチンの中でmodeフラグというものが出てきている。これは現状の状態を記憶させるためのもので、色々な場面でこれを参照することにより、設定状態が判定できる。要するに旗を立てて目印とするものである。これを使うことによりすっきりとしたスケッチとなり、ミスも減る。これ以外にもritフラグ等を使用している。
最後の行while文であるが、JA2GQPさんのスケッチから流用させていただいた。チャタリング防止に有効。これが無いとスイッチを押して離す間に何回も切替が実行されてしまう。
その他のサブルーチンもこんな具合で作っている。
Sメータであるが、思ったより旨く動いている。受信機AGCから0~5V位の電圧をA0pinからアナログ取り込み命令で受け取る。電圧は0~1023の数値に変換され変数に入る。このままでは旨くないので、これを50で割る。4V位をMAXとすればこれで0~15位の数値になる。これを15個の文字でSを表現している。丁度良い文字が無かったのでちょっと凝った書き方をしている。スケッチで見てください。さらに9以上は赤字にしてオーバーを示している。
以上簡単であるが、解説とする。Arduino DDS-VFOの1号機完成である。更にプログラミングを勉強しメモリ等機能UPしたいと思う。
スケッチ ダウンロード先
http://yahoo.jp/box/FzCR1P
実動作ビデオ
https://www.youtube.com/watch?v=1dGlrlca9_I&t=14s
Arduino DDS_VFO(1) [Aruduino]
arduinoによるcolor_LCDとDDS、ロータリーエンコーダーを動かすことが出来たので、いよいよVFOを目指していく。
最初に仕様を決める。とはいっても初心者であるのであまり複雑なことは出来ない。基本的な機能とした。
【仕様】
・7Mhzシングルバンド
・周波数可変STEP(10,100,1K,10KHz)
・RIT(±10KHz)
・モード(LSB,CW)
・Sメータ表示
【ハードウェア】
仕様を決めたら、其れに合わせてハードウェアを決定する必要がある。前回のものに、STEP変更スイッチ、RITスイッチ、モード変更スイッチの3つのスイッチが追加される。さらに送信状態の取り込みとモード(LSB,CW)の情報を出力ピンが必要となる。
送信情報の取り込みは(A5)で、これをLOWにすることで送信状態となる。
モードはモードスイッチ(A1)でCWに変更されると、モード出力(A2)がHigh(5V)となる。これをデジトラに入力し、オープンコレクタで外部(キャリアOSC切替)に出力する。
【画面構成】
画面はイメージを作り上げるためにグラフィック的に描いただけで機能はまだ無い。ここまでは前回までのコマンドで作成できる。
やはり実際に作ってみたほうがイメージが作りやすいと思う。
ここで今までのコマンドでは描けないものが1つある。それは周波数表示の白枠や、STEP,RIT表示の角が丸くなった長方形である。
コマンドは、
さてここまで決定したらいよいよプログラミングである。今回は周波数表示の改善である。というのは、前回のスケッチによる表示は、周波数を変更するたびに全体がチカチカして見にくい。そこでこれを改善する。とは言うもののこれは結構ハードなプログラミングとなってしまった。処理スピード等の懸念はあるが、取敢えずチャレンジしてみた。
そもそもこの原因は、グラフィック表示ならではのものである。キャラクタLCDであれば上書きすれば書き換わるが、グラフィックLCDでは、一度前の表示を背景色で塗りつぶす必要がある。このため全体がチカチカしてしまう。
ならばどうする。毎回書き直さず周波数変化があった時だけ書き換える。さらに変化のあった桁だけ修正することとした。
Arduino DDS contorol [Aruduino]
前回に続きいよいよDDSを動かすことに挑戦
ハードウェアとしては、前回のLCDの時が基本であるが、DDSとロタリーエンコーダを付加している。さらにLCDの接続部分で、前回は5Vと3.3VのレベルコンバーターにCD4010(CD4050)を使用していたが、今回は秋月で便利なコンバータモジュールを見つけたのでこれに変更した。このコンバータはフェアチャイルドのFXMA108という8bitの双方向通信が可能なものである。基板はDIPの変換基板についているのでユニバーサル基板やブレッドボードに簡単に取り付けられる。また信号が左右で対になっているので配線の引き回しが非常に楽になるという物だ。 注意としてはI2Cには使えない。SPI通信はOK。I2CはFXMA2102というモジュールが別途用意されているので、そちらを使用されたい。FXMA108は以下のリンク参照
http://akizukidenshi.com/catalog/g/gM-04522
DDSは、おなじみAD9850の中華DDS基板である。これについては多くの情報がNETで見られるのでそちらを参照されたい。
ロータリーエンコーダは、サトー電気の特価コーナーにある100STEP/1回転のものを使用した。100STEPのものでお値打ちなものはなかなか入手できないが、これはお買い得である。ノンステップである。詳細は以下HPにあります。
http://www.maroon.dti.ne.jp/satodenki/bargain00.html
今回の目標は、DDSを動作させロータリーエンコーダで周波数を変更し、LCDに周波数を表示することである。基礎技術としているので、周波数STEP変更は行っていない。また表示もただ表示するだけとなっている。これがクリアできれば、次の段階でより高度な制御を行っていくつもりである。
Arduinoのスケッチを以下に載せるが、ライブラリーについて注意点がある。似て非なるものが存在している場合がある。スケッチを公開する場合は極力ライブラリー情報も載せるべきと思う。
● LCD
<TFT_ILI9163C.h> https://github.com/sumotoy/TFT_ILI9163C
● SPI通信
<SPI.h> arduino標準
● フォント
< Adafruit_GFX.h> https://github.com/adafruit/Adafruit-GFX-Library
● エンコーダー
<Rotaly.h> https://github.com/brianlow/Rotary
エンコーダは<rotaly.h>というライブラリーもある。内容は同じであるが、「R」「r」と大文字小文字の違いである。arduinoでは大文字小文字の認識がしっかりしているのでこれを間違えるとコンパイルエラーとなる。今回大文字のものを使用しているのでスケッチも大文字で書いている。
● DDS
<EF_AD9850.h> http://elecfreaks.com/store/download/datasheet/breakout/DDS/EF_AD9850_library.zip
DDS用AD9850用ライブラリーはこれ以外に<AD9850.h>という物も公開されている。制御方法は異なるので注意が必要である。それぞれ特徴があり一長一短である。今回はEF-AD9850を使用した。
スケッチにつては極力コメントを入れてあるが、初心者なので間違いがあるかもしれない。もしお気づきのことがあればお知らせください。
Arduino IDE はVer.1.6.5を使用
スケッチ
/*
Arduino DDS(AD9850) Rotary Encoder TEST
2016.06.10 JA2NKD
*/
#include <SPI.h> // LCDで使われるSPI通信用ライブラリ
#include <Adafruit_GFX.h> // グラフィックや文字フォント用ライブラリ
#include <TFT_ILI9163C.h> // LCDを使うためのライブラリ
#include <Rotary.h> // エンコーダを使うためのライブラリ
#include <EF_AD9850.h> // AD9850を使うためのライブラリ
// Color definitions カラー設定(16bit)
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
// 1.44inch Color LCD Pin assign
#define __CS 10
#define __DC 9
#define __RST 8
int val; // 入力した文字のASCIIコード
long freq = 30000000; //DDSに送る周波数データ(初期設定値)
long freqold = 0; //周波数データの変化前のデータ
// AD9850 assign DDSモジュールとArduinnoの接続
int ddsreset = 4;//RESET
int fqup = 6;//FQ_UP
int clock = 7;//W_CLK
int data = 5;//DATA
// 各ライブラリにpin設定情報をを送る
TFT_ILI9163C tft = TFT_ILI9163C(__CS, __DC, __RST);
EF_AD9850 AD9850(clock, fqup, ddsreset, data);
Rotary r = Rotary(2, 3);
void setup() // 初期設定立ち上がり時1回だけ処理される
{
tft.begin(); // LCDと通信開始
tft.setRotation(1); // 画面を90度時計回りに回転
tft.fillScreen(BLACK); // 画面を黒で塗りつぶし
PCICR |= (1 << PCIE2); // エンコー割り込み設定
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19); // エンコーダー割り込み設定
sei(); // 割り込み開始
AD9850.init();// AD9850の初期化
AD9850.reset();// AD9850リセット
AD9850.wr_serial(0x00, freq); // 周波数データを送る
}
void loop() { //メインプログラムを書く
writeTextdds();
}
ISR(PCINT2_vect){ //エンコーダ割り込み処理
unsigned char result = r.process(); // ライブラリからの戻り値格納
if (result) {
if (result == DIR_CW) { // 戻り値がDIR_CWと同じなら以下を処理
freq = freq + 100000; // 右回りの時 周波数を100K UP
}
else { // 戻り値がDIR_CWと同じでなければ以下を処理
freq = freq - 100000; // 左回りの時 周波数を100K DOW
}
}
}
unsigned long writeTextdds(){ // 周波数をLCDに表示、DDSにデータを送る
if (freq != freqold){ // 周波数に変化があれば以下を処理
tft.fillRect(10, 10, 100, 30, BLACK); // 表示か所を黒で塗りつぶし
tft.setCursor(10, 10); // 周波数表示位置にカーソル移動
tft.setTextColor(YELLOW); // 文字色設定
tft.setTextSize(2); // 文字サイズ設定
tft.println(freq); // 文字表示(改行あり)
AD9850.wr_serial(0x00, freq); // DDSに周波数データを送る
freqold = freq; // 新しい周波数をoldに格納
}
}
おわり
Aruduino & Color LCD No.2 [Aruduino]
前のBlog記事で説明しきれていない内容で、幾つかの注意点があるので、追記することとした。
1) Aruduino
今回使用しているAruduino nano は純正品でなく中華製互換品である。Aruduino IDEは、純正品であれば、AruduinoとのUSB接続のためのドライバーがあるので問題なく接続できる。しかし中華製Aruduinoは、物によりシリアル-USB接続用インターフェースICの種類が違うものが多い。たいていは購入するときにそのドライバー情報が記載されているので、指示されたドライバーをインストールする必要がある。
今回使用しているものには、CH340GというICが使用されている。これ用のドライバーは以下のページから取得できる。
2) LCDライブラリー
今回使用している1.44inchカラーLCDは、ILI9163Cと言うものが使用されている。「ILI9163C Library」で検索すれば見つけられる。
TFT-ILI9163C-master.ZIPという名前で ダウンロードされるので、適当なフォルダーで解凍する。解凍するとTFT-ILI9163C-masterというフォルダーが作られる。実はこの名前では旨く動かない。フォルダー名を「TFT-ILI9163C」と変更してAruduinoプログラムフォルダーに有るLibraryフォルダーに移動する。AruduinoIDEからも取り込みが出来るが、このフォルダーではなく、ドキュメントフォルダーのAruduinoフォルダーにあるLibraryに収納される。しかしこのフォルダー内部にて階層管理が出来ないようである。そのため本体内のLibraryに入れたほうが管理しやすい気がする。ここに入れればIDEメニューに自動的にLibrary名が表示されるはずである。
次にこのLibraryであるが、そのままでは、旨く動かない。下の写真のように表示がずれる。
これはLCDサイズが128x160に設定されているようで、何故かオフセット数値が記載されている。なのでこれを「0」に変更すれば旨く表示されるようになる。
グラフィックLCDはキャラクタLCDと違い文字フォントを持っていない。そこでこのフォントLibraryが必要となる。
以上今回Aruduinoを使ってみて少し躓いた部分を備忘録的にUPした。参考にしていただければ幸いである。
Aruduino & Color LCD [Aruduino]
前のブログ記事にお世話になっているKさんから提供していただいたN6QW PETEさんが開発したカラーLCD-VFOに魅せれてしまった。お世話になっているJH8SSTさんからもLCD等を提供していただいた。そうなるとこれを使いこなしたいという欲望がわきあがってくる。
普段BASCOM-AVRを使っているのでなんとかこれで制御できないかとNETで調べてみたが、該当のLCDの使用例は見つからなかった。そこで Aruduinoで調べてみたところ非常に多くの使用例や豊富なライブラリーがあることが分かった。
これはいよいよAruduinoを使ってみるしかないということになった。もともとBASICスパゲッティープログラムでやっていたので、Cライクなプログラムはなじみがない。しかし覚えるしかないようだ。Aruduinoの世界ではプログラムと言わずスケッチということが分かった。
最初にプログラム(以下スケッチ)をコンパイルして機械語にするソフトが必要である。これは無償でダウンロードできる。
Aruduino-IDEと言われるソフトである。インストール方法等はNETに沢山あるのでそちらを参照されたい。ただバージョンは色々あり、最新版がいいとは思うが不具合を起こす場合もあるようだ。私はKさんのアドバイスにより1.6.5バージョンをインストールすることにした。
当然Aruduinoに書き込む必要があるわけであるが、USBケーブルを使ってPCとAruduinoを接続すれば書き込める。
これはAruduinoの中にブートローダーというPCと接続して書き込むためソフトがインストールされているためである。このことは、BASCOM-AVR等書込器が必要なものに比べてきわめて簡単でハードルが低い。
また特に凄いのは、非常に多くの製作例、ライブラリー、スケッチの公開シェアがされていることである。今回のような携帯電話に使われていたLCD等の多くもライブラリーが発表されている。無線関連でもSi5351PLLやDDSのAD9850などのライブラリーもある。実に豊富な情報がUPされている。特に海外の情報は凄いものがある。日本でも製作例はあるもののスケッチの公開等は少ない。 どんどんシェアしてより良いものを作っていければと思うのだが。
さて、今回使用しているLCDはノキア携帯用のものらしいが、よく判らない。中華では数百円で入手できる。Aruduinoとの接続はSPI(Serial Peripheral Interface)通信で行っている。SPI通信はIDEの標準ライブラリーに用意されている。
LCD自体の表示関連制御にはILI9163CというドライバーICが使われておりこのライブラリーは公表されている。フォント等にはAdafruit_GFX.hというライブラリー(定番らしい)が公開されている。
いよいよプログラミングである。ここで少し困ったことがあった。スケッチに書く命令語(コマンド)が分からない。リストなどないのかと探してみたが見つからなかった。そこで既に発表されている他のスケッチ等を見て調べることとした。
当面必要なコマンドはどうにか分かったので備忘録も兼ねてここにUPしていくこととした。
スケッチ例(1)
文字表示の例。
----------------------------------------------------------------------
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <TFT_ILI9163C.h>
// Color definitions 色の設定
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFF
/* 以下コメント SPI通信の接続ピン等MEMO
Teensy3.x and Arduino's
You are using 4 wire SPI here, so:
MOSI: 11//Teensy3.x/Arduino UNO (for MEGA/DUE refere to arduino site)
MISO: 12//Teensy3.x/Arduino UNO (for MEGA/DUE refere to arduino site)
SCK: 13//Teensy3.x/Arduino UNO (for MEGA/DUE refere to arduino site)
the rest of pin below:
*/
#define __CS 10 //LCDとの接続ポート指定
#define __DC 9 // 〃
#define __RST 8 // 〃
TFT_ILI9163C tft = TFT_ILI9163C(__CS, __DC, __RST); //ライブラリにーLCD制御ポートを送る
void setup() {
tft.begin(); //LCDとの通信開始
}
void loop() {
testText(); //サブルーチン(関数)にジャンプしコマンドを実行し戻る
}
//以下サブルーチン
unsigned long testText() {
tft.setCursor(0, 0); //書き始める位置をX,Yで指定
tft.setTextColor(WHITE); //文字色指定
tft.setTextSize(1); //文字サイズを指定
tft.println("Hello World!"); //文字を書く 以下同様
tft.setCursor(0,20);
tft.setTextColor(YELLOW);
tft.setTextSize(2);
tft.println("JA2NKD");
tft.setCursor(0,50);
tft.setTextColor(RED);
tft.setTextSize(3);
tft.println("JH8SST");
tft.setCursor(0,90);
tft.setTextColor(GREEN);
tft.setTextSize(4);
tft.println("Hello");
}
スケッチ例(2)
図形表示
前半は上記スケッチと同じなので、サブルーチン以下のみを示す。
----------------------------------------------------------------------- --
unsigned long testText() {
tft.setRotation(1); //画面全体を回転(1-3)90度毎時計方向
tft.drawLine(0,0,128,128,WHITE); //ライン X1,Y1からX2,Y2
tft.drawRect(50,10,30,30,RED); //四角形ライン X,Yから横縦の長さを指定
tft.fillRect(90,10,30,30, BLUE); //四角形塗りつぶし
tft.drawTriangle(30,50,10,70,50,70, YELLOW); //三角形ライン 3頂点座標
tft.fillTriangle(30,80,10,100,50,100,CYAN); //三角形塗潰し
tft.drawCircle(80,105,15,MAGENTA); //円ライン 中心座標と半径
tft.fillCircle(90,60,15,GREEN); //円塗潰し
}