SSブログ

Arduino DDS_VFO Ver.1 Ver.2 Ver.3 [Aruduino]

 いつもお世話になっているKさんが、ArduinoVFO2.2inchTFTを1.8inchTFTにスケールダウンしてくれた。これで1.44,1.8,2.2と3サイズがそろった。製作機器、ケースに合わせて選択できる。Kさん有難う。

DSCN3578.JPG  1.8TFT.JPG  DSCN3600.JPG

 左から1.44inchTFT 1.8inchTFT 2.2inchTFT (クリックで拡大)

 

 

 

 

 

 

 

 


nice!(0)  コメント(0) 

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.

 WS000007.JPG


nice!(0)  コメント(2) 

Arduino DDS_VFO Ver.2 2.2inchLCD [Aruduino]

 前回のVFO Ver.1では、LCDに1.44inchTFTを採用したが、やはり老眼が必須の身としては小さい。
そこでさらに大きな表示を検討していた。そこでいつもお世話になっているJH8SST/7さんからご提供いただいた2.2inchTFTを採用することにした。
 折しもJA2GQPさんがツイッターで紹介されていたLCDが非常にきれいなフォント表示になっているのを見つけた。調べてみるとこのフォントは手持ちの2.2inchTFTにも適応していることが分かった。早々プログラミングを開始した。
DSCN3600.JPG
 
 基本的には前作1.44inchLCD-VFOのものを周到している。
従ってグラフィック関係だけ弄ればすんなり完成すると踏んだのであるが、そうは問屋がおろさなかった。
 考えてみれば当然かもしれないが、フォントがきれいな分抽画量が増える、さらに画面が大きい分抽画が増える。その結果、ただ置き換えただけではエンコーダーを回したときにカウントミスが出るようになってしまった。結局この部分に対する修正に苦労をしてしまった。
 また画面が大きくなったため、前回のデザインでは、間の抜けた感じとなってしまったので、いくつか新しい機能を追加した。

arduino_2.2VFOV2.jpg
【変更点】
・2.2inchLCD(ILI9341)
・arduino nano(unoは対応不可)
・RFインジケータ追加
・ModeをLSB,USB,CW,AMと4タイプ対応
 
 
【スケッチ】
・Library(ライブラリー)
 今回の目玉であるフォントであるが、<Ucglib.h>というものである。AdafulitGFXに比べると格段の美しさでギザギザ感がない。サイズも豊富である。ライブラリーは
からダウンロードできる。
 
注意
 <EF-AD9850.h>ライブラリーはそのままではエラーが出る。ライブラリー内のEF_AD9850.hをテキストエディター等で開き以下のように修正する必要がある。
27行目
  #include "WProgra.h" →#include "Arduino.h" 
 
・Ucgフォント
 このフォントの使い方は、ライブラリーの中にマニュアルがあり詳細に説明されている、またフォントもリストがあり、そのなかで気に入ったフォントを指定して使うことができる。
簡単にグラフィックのスケッチ例を示すと

-------------------------------------------------------------------
#include<Ucglib.h>

/*
* Hardware SPI Pins:
* Arduino nano sclk=13pin data=11pin
* 今回ハードウェアSPIを使ったので11,13pinは自動的に選択されるので
* 特にpin設定の必要はない。ソフトウェアSPIを使用する場合は、
* すべてのpin設定が必要となる。
*/

const byte __CS=10; // CS,DC,RSTは任意なのでpin指定の為ここで指定
const byte __DC=9;  // 下のUcgの命令でライブラリーに送る
const byte __RST=8; // サンプルスケッチに各種対応の命令が載っている。

Ucglib_ILI9341_18x240x320_HWSPI ucg(__DC,__CS,__RST);

void setup(){
ucg.begin(UCG_FONT_MODE_TRANSPARENT); //フォント使用開始宣言
ucg.clearScreen(); //画面初期化
ucg.setRotate90(); //画面を90度回転(使い勝手で決める)
}

void loop{

ucg.setFont(ucg_font_fub35_tr);  // フォントを指定
ucg.setPrintPos(100,100);        // 位置を指定
ucg.setColor(255,255,255);       // 色を指定(白)
ucg.print("JA2NKD");             // 文字を書く

}

--------------------------------------------------------------------
色はRGBの3色の数値指定。18bitなので各6bitで(0~63)であるが、どうも
(0~255)で指定するようである。(0,0,0)黒 (255,255,255)白
(255,0,0)赤 (0,255,0)緑 (0,0,255)青となる。
あとはマニュアルを参考にして下さい。

・RFレベル計
 arduino nanoは、A6,A7とunoよりアナログ入力が2つ多い。そこで、今回この2つをSメータとRFレベル系とした。スケッチとしてはRFレベル系もSメータと同様であるが、送信状態の時だけ動作するようになっている。

・モード
 アナログ入力をA6,A7としたことによりA0が別用途に使えるようになったことからモードを4種類(前回2種類)とし、A0,A1をキャリア切り換え用情報出力(2bit)とした。それに合わせて画面も4種類を表示するようにした。選択されているのが黄色、その他はグレーとした。

・周波数表示、Sメータ表示
 前回のスケッチをそのまま置き換えた場合、エンコーダを回すと表示がついて行かず不一致が発生した。取りこぼしである。それだけグラフィック表示が重たくなったということだ。そのため周波数表示は100KHz以下のみ変更されるようにしている。MHzは直接書いており変更しない。このためこのVFOの変更範囲は999KHz以下となる。HFにおいては問題ない。28MHzでも通常28MHz台の1MHzでOKと思われる。
 MHz台の表示を変更する(例えば7→21)場合はスケッチ内に以下のような部分があるので、必要なところの//を消して有効にし希望の数値をいれれば変更できるようにした。これで最大999MHzまで表示することが出来る。
538行
   ucg.setFont(ucg_font_fub35_tr);
    ucg.setColor(0,255,0);
//    ucg.setPrintPos(19,45);  //100Mhz台
//    ucg.print("4");
//    ucg.setPrintPos(47,45);  //10MHz台
//    ucg.print("3");
    ucg.setPrintPos(75,45);
    ucg.print("7");     // 1Mhz台
    ucg.setPrintPos(103,45);
    ucg.print(".");
    ucg.setPrintPos(273,45);
    ucg.print("0");  // 1Hz台
 
  また、Sメータも周波数切り替え時には止めている。なのでエンコーダを回したとき少々違和感があるかもしれないが、致し方ない。
 DSCN3604.JPG
   
以上簡単な説明でご容赦
動作ビデオとスケッチのリンクを載せておきます。
 
VIDEO
 
Sketch

まだarduino初心者(6月から始めた)であるが、何とかできるものである。そういった意味でもarduinoの人気が高いのは良くわかる。


nice!(2)  コメント(2) 

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>を使ってスケッチ側で変更できるようにしてみるつもりである。


nice!(3)  コメント(1) 

Arduino DDS_VFO(2) [Aruduino]

DSCN3569.JPG

 前回に続いて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

DSCN3577.JPG  DSCN3578.JPG


nice!(0)  コメント(0) 

Arduino DDS_VFO(1) [Aruduino]

 arduinoによるcolor_LCDとDDS、ロータリーエンコーダーを動かすことが出来たので、いよいよVFOを目指していく。
最初に仕様を決める。とはいっても初心者であるのであまり複雑なことは出来ない。基本的な機能とした。
【仕様】
 ・7Mhzシングルバンド
 ・周波数可変STEP(10,100,1K,10KHz)
 ・RIT(±10KHz)
 ・モード(LSB,CW)
 ・Sメータ表示

【ハードウェア】
arduino_VFO1.jpg 仕様を決めたら、其れに合わせてハードウェアを決定する必要がある。前回のものに、STEP変更スイッチ、RITスイッチ、モード変更スイッチの3つのスイッチが追加される。さらに送信状態の取り込みとモード(LSB,CW)の情報を出力ピンが必要となる。
 送信情報の取り込みは(A5)で、これをLOWにすることで送信状態となる。
モードはモードスイッチ(A1)でCWに変更されると、モード出力(A2)がHigh(5V)となる。これをデジトラに入力し、オープンコレクタで外部(キャリアOSC切替)に出力する。


【画面構成】

DSCN3569.JPG
 画面構成は大事であると思う。気に入った画面出なければ長く使う気にはなれない。しかしこれは個人のセンスによるものなので各人好みで製作されたい。今回以下の画面とした。どうもN6QWの影響が大きいため似たものとなってしまった。

 画面はイメージを作り上げるためにグラフィック的に描いただけで機能はまだ無い。ここまでは前回までのコマンドで作成できる。
 やはり実際に作ってみたほうがイメージが作りやすいと思う。

 ここで今までのコマンドでは描けないものが1つある。それは周波数表示の白枠や、STEP,RIT表示の角が丸くなった長方形である。
コマンドは、
tft.drawRoundRect(x1,y1,x2,y2,r,color) 塗りつぶし無し
tft.fillRoundRect(x1,y1,x2,y2,r,color)塗りつぶし有り
の2つ。実際の使用はスケッチを参考に。

 さてここまで決定したらいよいよプログラミングである。今回は周波数表示の改善である。というのは、前回のスケッチによる表示は、周波数を変更するたびに全体がチカチカして見にくい。そこでこれを改善する。とは言うもののこれは結構ハードなプログラミングとなってしまった。処理スピード等の懸念はあるが、取敢えずチャレンジしてみた。
 そもそもこの原因は、グラフィック表示ならではのものである。キャラクタLCDであれば上書きすれば書き換わるが、グラフィックLCDでは、一度前の表示を背景色で塗りつぶす必要がある。このため全体がチカチカしてしまう。
 ならばどうする。毎回書き直さず周波数変化があった時だけ書き換える。さらに変化のあった桁だけ修正することとした。
とはいうもののこれが大変な作業である。どうするかであるが、周波数数値をstring()というコマンドで文字に変換し、その文字で周波数の変化前と比較し変更になった文字部分のみ塗りつぶしと表示を行うという面倒な方法とした。面倒ではあるが、これによりドットを任意に追加できるようになった。詳細はスケッチを参考にしてください。特に苦心したのは1桁少なくなるときの消去(いわゆるゼロサプレッス) であった。このルーチンが出来たことにより999MHz~0Hzまでチカチカせず綺麗に表示出来るようになった。
 
DSCN3585.JPG
 尚、今回の修正に当たって数の読替宣言(#define)という命令を(const)命令に変更している。これは(const)命令のほうが厳密に管理されるとのことで、バグ等の原因 にならないようである。詳しくはリファレンス等を参照してください。色々な数値についても変数はいいのですが、定数(プログラム上で変更されない数値)は(const)命令としている。
 
 今回は周波数表示のみであり、表示は左の写真のようになる。
 チカチカせずきわめて綺麗に表示変更される(自画自賛)
 気になった処理スピードも問題なくエンコーダーに追随している。キャラクタLCDに比べてもきわめて処理が早いようだ。 
 
 
 
 
 
 
【スケッチ】
 
// Library include
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <TFT_ILI9163C.h>
#include <Rotary.h>
#include <EF_AD9850.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   0xFFFF

/* 1.44inch color LCD using 4 wire SPI here, so:
 MOSI:  11//Teensy3.x/Arduino UNO
 MISO:  12//Teensy3.x/Arduino UNO
 SCK:   13//Teensy3.x/Arduino UNO
 */

// I/O setting 
  const byte __CS=10;
  const byte __DC=9;
  const byte __RST=8;
  const byte ddreset=4;
  const byte dddata=5;
  const byte ddfqup=6;
  const byte ddclock=7;
  const byte s_meter=A0;
  const byte modesw=A1;
  const byte modeout=A2;
  const byte stepsw=A3;
  const byte ritsw=A4; 
  const byte txsw=A5;
  const byte RE_A=2;
  const byte RE_B=3;
  
  TFT_ILI9163C tft=TFT_ILI9163C(__CS,__DC,__RST);  
  EF_AD9850 AD9850(ddclock,ddfqup,ddreset,dddata);
  Rotary r=Rotary(RE_A,RE_B);

// Variable setting
  long int freq =7100000; // 立上時の周波数
  long int freqold=0; // 変更前の周波数格納用変数
  String freqt=String(freq); // 周波数を文字変数に変換
  long int ddsfreq = 0; // DDSへ送る周波数(後にIFシフトを加味するため)
  char f100m,f10m,fmega,f100k,f10k,f1k,f100,f10,f1; //文字に変換された数値を桁毎に格納する変数
  int fstep=100; // 周波数変更ステップの初期値
  
//  初期設定
void setup() {
  tft.begin();
  tft.setRotation(1);
  PCICR |=(1<<PCIE2);
  PCMSK2 |=(1 << PCINT18) | (1 << PCINT19);
  sei();
  AD9850.init();
  AD9850.reset();
  screen01(); //基本画面の抽画
}

//Main Routine
void loop() {
    if (freq != freqold){ //周波数が変更されたか判定し異なれば以下を実行
      ddsfreq=freq; //変更後周波数を設定
      AD9850.wr_serial(0x00,ddsfreq); //DDSに命令を送る
      freqt=String(freq);  //周波数を文字に変換
      freqlcd(); //周波数表示ルーチンに飛びLCDに表示
      freqold=freq;  //旧周波数に現周波数を代入
    }
}

// Encoder Interrupt
ISR(PCINT2_vect) {
  unsigned char result = r.process();
     if(result) {
      if(result == DIR_CW){  
        freq=freq+fstep; // 周波数をSTEP分プラス
      }
      else{
        freq=freq-fstep; // 周波数をSTEP分マイナス
      }
    } 
}

//Main frequency screen 周波数表示ルーチン
void freqlcd(){
  int mojisuu=(freqt.length()); // 文字数を調べる
  tft.setTextSize(2); // 文字サイズを(2)に設定
  tft.setTextColor(GREEN); // 文字色を緑に設定
  if(freq>=100000000){ // 周波数が100MHz以上の時以下を処理
    if(f100m !=(freqt.charAt(0))){ // 100Mhz台が前回(f100m)と違うか判定し以下を処理
      tft.fillRect(4,13,12,14,BLACK); // 100Mhz台を黒で塗りつぶす
      tft .setCursor(4,13); // カーソルを100Mhzの位置にセット
      tft.print(freqt.charAt(0)); // 100MHz台を表示
      f100m = (freqt.charAt(0)); // 100Mhz台をf100mに格納 
    }
  } // 以下各桁同じような処理のためコメント省略
  if(freq<100000000){tft.fillRect(4,13,12,14,BLACK);}
  if (f10m !=(freqt.charAt(mojisuu-8))){
   tft.fillRect(16,13,12,14,BLACK);
   tft .setCursor(16,13);
   tft.print(freqt.charAt(mojisuu-8));
   f10m = (freqt.charAt(mojisuu-8));
  }

   if(freq<10000000){tft.fillRect(16,13,12,14,BLACK);}
   if(fmega !=(freqt.charAt(mojisuu-7))){
    tft.fillRect(28,13,12,14,BLACK);
    tft.setCursor(28,13);
    tft.print(freqt.charAt(mojisuu-7));
    fmega  = (freqt.charAt(mojisuu-7));
   }

  if(freq>=1000000){ //ドット表示(MHz台)
    tft.setTextSize(1);
    tft.setCursor(39,20); 
    tft.print(".");
    tft.setTextSize(2);
  }

  if(freq<1000000){tft.fillRect(28,13,18,14,BLACK);}
  if(f100k !=(freqt.charAt(mojisuu-6))){
    tft.fillRect(46,13,12,14,BLACK);
    tft.setCursor(46,13);
    tft.print(freqt.charAt(mojisuu-6));
    f100k = (freqt.charAt(mojisuu-6));
  }
    
  if(freq<100000){tft.fillRect(46,13,12,14,BLACK);}
  if(f10k !=(freqt.charAt(mojisuu-5))){
    tft.fillRect(58,13,12,14,BLACK);
    tft.setCursor(58,13);
    tft.print(freqt.charAt(mojisuu-5));
    f10k = (freqt.charAt(mojisuu-5));
  }
   
  if(freq<10000){tft.fillRect(58,13,12,14,BLACK);}
  if(f1k !=(freqt.charAt(mojisuu-4))){
    tft.fillRect(70,13,12,14,BLACK);
    tft.setCursor(70,13);
    tft.print(freqt.charAt(mojisuu-4));
    f1k  = (freqt.charAt(mojisuu-4));
  }
  
  if(freq>=1000){
    tft.setTextSize(1);
    tft.setCursor(81,20); 
    tft.print(".");
    tft.setTextSize(2);
  }
   
  if(freq<1000){tft.fillRect(70,13,18,14,BLACK);}
  if(f100 !=(freqt.charAt(mojisuu-3))){
    tft.fillRect(88,13,12,14,BLACK);
    tft.setCursor(88,13);
    tft.print(freqt.charAt(mojisuu-3));
    f100 = (freqt.charAt(mojisuu-3));
  }

  if(freq<100){tft.fillRect(88,13,12,14,BLACK);}
  if(f10 !=(freqt.charAt(mojisuu-2))){
    tft.fillRect(100,13,12,14,BLACK);
    tft.setCursor(100,13);
    tft.print(freqt.charAt(mojisuu-2));
    f10 = (freqt.charAt(mojisuu-2));
  }
   
  if(freq<10){tft.fillRect(100,13,12,14,BLACK);}
  if(f1 !=(freqt.charAt(mojisuu-1))){
    tft.fillRect(112,13,12,14,BLACK);
    tft.setCursor(112,13);
    tft.print(freqt.charAt(mojisuu-1));
    f1  = (freqt.charAt(mojisuu-1));   
  }
}

//Basic Screen
void screen01(){
  tft.drawRoundRect(0,5,128,30,4,WHITE);
  tft.setCursor(2,120);
  tft.setTextColor(YELLOW);
  tft.print(" Homeblew VFO JA2NKD");
}
 
次回はスイッチ関係の予定
 


nice!(1)  コメント(0) 

Arduino DDS contorol [Aruduino]

arduino_AD9850.jpg

 前回に続きいよいよ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

arduinoTESTbench.JPG

  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に格納
    }
  }

おわり 


nice!(2)  コメント(0) 

Aruduino & Color LCD No.2 [Aruduino]

 前のBlog記事で説明しきれていない内容で、幾つかの注意点があるので、追記することとした。

1) Aruduino
 今回使用しているAruduino nano は純正品でなく中華製互換品である。Aruduino IDEは、純正品であれば、AruduinoとのUSB接続のためのドライバーがあるので問題なく接続できる。しかし中華製Aruduinoは、物によりシリアル-USB接続用インターフェースICの種類が違うものが多い。たいていは購入するときにそのドライバー情報が記載されているので、指示されたドライバーをインストールする必要がある。
 今回使用しているものには、CH340GというICが使用されている。これ用のドライバーは以下のページから取得できる。

CH340G用ドライバー   江苏沁恒股份有限公司
 これをインストールしaruduinoを接続すれば認識する。その後IDEのツール内にあるポート設定で該当のポートを選択することにより書き込みが出来るようになる。

 

aruduino.jpg


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であるが、そのままでは、旨く動かない。下の写真のように表示がずれる。
 

DSCN3560.JPG 
 これを修正するには、TFT-ILI9163CLibrary内の「-settings」フォルダー内の「TFT_ILI9163C_settings.h」ファイルをワードパット等TEXTエディタで開き下記の部分を修正する。

 

#define _TFTWIDTH   128//the REAL W resolution of the TFT
#define _TFTHEIGHT 128//the REAL H resolution of the TFT
#define _GRAMWIDTH      128
#define _GRAMHEIGH      160//160
#define _GRAMSIZE _GRAMWIDTH * _GRAMHEIGH//*see note 1
#define __COLORSPC 1// 1:GBR - 0:RGB
#define __GAMMASET3 //uncomment for another gamma
#define __OFFSET 32//*see note 2   //32を0にする
 これはLCDサイズが128x160に設定されているようで、何故かオフセット数値が記載されている。なのでこれを「0」に変更すれば旨く表示されるようになる。
 
3) フォントドライバー
 グラフィックLCDはキャラクタLCDと違い文字フォントを持っていない。そこでこのフォントLibraryが必要となる。
「adafruit-GFX-Library」というLibraryで、定番Libraryのようだ。これも検索すれば直ぐ見つかる。
このファイルも 「adafruit-GFX-Library-master」となっているのでILI9163Cと同様に名前変更でmasterの部分を消す必要がある。あとはILI9163C同様Libraryフォルダーに保存する。

以上今回Aruduinoを使ってみて少し躓いた部分を備忘録的にUPした。参考にしていただければ幸いである。
 

 


nice!(0)  コメント(0) 

Aruduino & Color LCD [Aruduino]

144LCDschematic.jpg

 前のブログ記事にお世話になっている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");

DSCN3552.JPG

スケッチ例(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); //円塗潰し
 }

 DSCN3556.JPG

まだ他にもあるかもしれないが、現状調べたものです。

nice!(0)  コメント(2) 

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。