MAX7219の使い方 8×8LCD 無ライブラリー (2)

あれこれやってますが,どのHPを見ても,二個目,三個目,四個目のMAX7219に指令を出す方々が書いてあ
りませんでした。これまでかと思い,取説を確認してみるとありました。ありました。きちんと表記があるじゃないですか。

  ===二つ目以降のチップを操作する===

 4つのMAX7219をカスケード接続する場合,4番目のチップに書き込みを行うには,希望する
 16ビットワードの後に,3つのno-noコード(16進の0xXX0X表2)送信します。
 LOAD/CSがハイになった時点で,すべてのデバイスにデータがラッチられます。最初の3つのチップ
 は,no-noコマンドを受け取り,4番目のチップが目的のデータを受け取ります。

とありました。これで,もうちょっと先に進めそうです。

また,諸兄のHPを参考にarduino風に書き換えていた,SPIのデータ書き込みのスケッチも動きました。

#define CLK 13
#define DIN 11
#define CS  10

void setup(){
  Serial.begin( 9600 );     // シリアル通信を初期化する。通信速度は9600bps
    pinMode(CLK, OUTPUT );
    pinMode(DIN, OUTPUT );
    pinMode(CS, OUTPUT );
}

void wait(int i){
  volatile int j,k;
  for(j=0;j<i;j++){
    for(k=0;k<55;k++);
  }
}

//****************************************************************
//arduino自作関数
//データ書き込み
//****************************************************************
void LED_MAT_SEND(unsigned char SELECT, unsigned char DATA){
  digitalWrite( CS, HIGH );// Load ON
  wait(2);void 
  digitalWrite( CS, LOW );// Load OF

  for(int i=0;i<8;i++){               // Send Register data
        digitalWrite( CLK, LOW );//CLK OFF
        if(((SELECT << i) & 0b10000000)==0){
          digitalWrite( DIN, LOW );
          Serial.print( '-' );
        }
        else{
          digitalWrite( DIN, HIGH );
          Serial.print( '+' );
        }
      wait(1);
      digitalWrite( CLK, HIGH );//CLK ON
      wait(1);
  }

  for(int i=0;i<8;i++){               // Send LED DATA
      digitalWrite( CLK, LOW );//CLK OFF


      if(((DATA << i) & 0b10000000)==0){
        digitalWrite( DIN, LOW );
        Serial.print( '-' );
      }
      else{
        digitalWrite( DIN, HIGH );
        Serial.print( '+' );
      }
      wait(1);
      digitalWrite( CLK, HIGH );//CLK ON
      wait(1);
    }
    digitalWrite( CS, HIGH );// Load ON
    wait(2);
    digitalWrite( CS, LOW );// Load OFF
    Serial.print( "******" );
}

デバッグ用のSerial.printは残してあります。また,この, digitalWrite( CLK, HIGH );は結構クロックをつかうようなので,一括処理のものに後で変更しようと思います。このスケッチもSPIライブラリーを使うと,別な諸兄の書かれた下記のように6行程度ですんでしまいます。

void maxTransferCMD(uint8_t address, uint8_t value) {
  digitalWrite(CS_PIN, LOW);
  SPI.transfer(address); // Send address.
  SPI.transfer(value); // Send the value.
  digitalWrite(CS_PIN, HIGH); // Finish transfer.
}

今日,取説で見つけた記述をもとに,2個目3個目のMAX7219に書き込めるスケッチも考えてみたいと思います。

MAX7219の使い方 8×8LCD 無ライブラリー (1)

何年か前に、8×8の小さ目のLCDマトリックスで、PICを使って流れるサインボードのおもちゃを作成しまし
た。ネットサーフィンをしていると、ちょっと大きめの8×8LCDマトリックスがめにとまりましたので、
思わず、いくつかポチってしまいました。

この一つのものと、4連のもの合計3つをアリでぽちりました。

4連のものは、赤と青を購入しました。

この、LCDは、MAX7219というコントロールIC(ドライバー)が使われていて、比較的たやすく、コント
ロールができるようで、arduinoだと、専用のライプラリーもいくつかあるようです。また、このLCDの
面白いのは、横に連結して使えることです。どのくらい連結できるのかわかりませんが、arduinoの設定
の項目には11個の記載がありましたので、もしかして、電源のこと考えないなら、11個ぐらい連結で
きるのかもしれません。

ライブラリーを使えばいいのでしょうが、MAX7219を直接コントロールしたくて、あれこれしらべました。
幸い詳しく書かれている諸兄のHPが見つかりましたので、ここを参考にいろいろやってみます。

いままで、いろんなもののコントロールに、SPI(シリアル通信)を使う記事も見かけましたが、実際は
どんなふうにするのかいまいち理解がおよびませんでしたが、なんとなく理解することができました。
諸兄のHPによれば、下記のようになるそうです。SPIは3本の線でやり取りします。CLK,Cs,DOUTの3本の
線で下記のようにやり取りをします。

 ・Load端子をLowにセット

  -・CLK端子をLowにセット
  +・15ビット目の値をDINにセット
  +・CLK端子をHighにセット ここでシフトレジスタの0ビット目に①の値がセットされます
  +    つまり 00000000 0000000 がMAX7219のシフトレジスタに入ってま
  +・CLK端子をLowにセット
  +・14ビット目の値をDINにセット
  +・CLK端子をHighにセット ここでシフトレジスタがシフトし②が0ビット目に入ります
  -  つまり 00000000 000000①② が入ってます
      これを繰り返して 16ビットすべて送信したら

  LoadをHighにセットします

  この瞬間シフトレジスタの値が 指定されてたレジスタに反映されます。

この流れを、プログラムに組んでやれば、基本的なデータの送信ができます。この送信の手順は、

のデータシートに記載のあるタイミング図をみればいいみたいですが、いままで、この意味がよく分かり
ませんでした。今となって、やっとその意味が分かりました。

このデータ送信も、arduinoだとSPI(シリアル通信)のライブラリーがあるので、簡単にできてしまうよう
なので、ちょっと、びっくりですね。

Arduino PWM 再び (2)

割り込みを使ったPWMのLチカをやりましたが,機能として備わっているPWMもやってみることにしました。
でもがっかりしました。簡単過ぎるのです。

analogWrite(PIN番号,DUTY)

これだけで,できてしまうのです。ただ,analogWriteでは,周波数とかの細かい設定はできないようです。
DUTYは最高が0~255まで,指定できるようです。PICだと,設定値をビット演算して,レジスターに書き
込むのでちょっと面倒です。周波数とかの細かい設定をするには,やはりレジスタをいじるようです。

昨日作った割り込みのPWMと備え付け機能のPWMを使い,LEDをだんだん明るくして,だんだん暗くする
というスケッチを書いて動かしてみました。

include<avr/io.h>
#include <avr/interrupt.h>


int k=0;
int BLUE_LED_PIN = 11;  // PWM出力させるピン番号を指定
int RED_LED_PIN = 13;   //11は備え付け,13は割り込みj
int DUTY = 0;


void setup() {
  pinMode(RED_LED_PIN, OUTPUT);
  pinMode(BLUE_LED_PIN, OUTPUT);


  TCCR1A  = 0;
  TCCR1B  = 0;
  TCCR1B = bit(WGM12) | bit(CS11) | bit(CS10); // CTCモードで分周率64
  TIMSK1 = bit(OCIE1A); // 割り込みをタイマー1に設定
  //TCCR1B |= (1 << WGM12) | (1 << CS12);  //CTCmode //prescaler to 256
  OCR1A   = 6-1;
  //TIMSK1 |= (1 << OCIE1A);
}


ISR (TIMER1_COMPA_vect) {
 if(k<255){
    k=k+1;
  }
  else{
    k=0;
  }
  if(k==0){
    digitalWrite(RED_LED_PIN, HIGH);
  }
  if(k==DUTY){
    digitalWrite(RED_LED_PIN, LOW);
  }
}


void loop() {
   while(DUTY<255){//だんだん明るくする
    analogWrite(BLUE_LED_PIN, DUTY);
    DUTY=DUTY+1;
    delay(25);
  }
  delay(500);
   while(DUTY>1){//だんだん暗くする
    analogWrite(BLUE_LED_PIN, DUTY);
    DUTY=DUTY-1;
    delay(25);
  }
  delay(500);
}

ほぼ同じような動作をしますが,割り込みを使った方は,あるタイミングでちらつきます。どのタイミングで
ちらつくのか分かりませんが,多分,カウント等余分な動作をしているからかなと推測します。

赤のLEDが割り込みでの点滅で,青のLEDが備え付け機能を使った点滅です。

Arduino PWM 再び

このところ,Arduinoをいじってます。PICに比べると遙かにわかりやすいです。ただ,PICに比べると,細か
な設定等が難しいのが欠点であるといえば欠点ですが。

今回は,ArduinoにもPWMの機能が備わっていますが,この機能を使わずに割り込みで,PWMを簡易的に実現してみました。PWMを実現するには,単純に,端子をLOWとHIGHTに切り替えることができればいいので,通常は,

   端子をHIGHT
   delay(50)
   端子をLOW

みたいにすれば,たやすく実現できます。ただ,このdelay(50)がちょっと気に入らないので,使わないで
実現できないかと考えた訳です。構想としては,TIMER割り込みの回数を数えて,

   0回目の割り込み→→端子をHIGHT
   n回目の割り込み→→端子をLOW
   規定の回数の割り込みで,また,0から数えるLOW

組み込みのPWMでも,レジスターレベルでカウントして,考え方としては,上記のものと同じ考えでやってる
ようです。

arduinoで,やってみました。LEDがだんだん明るくなると次は次第に暗くなるというスケッチを描いてみまし
た。

#include<avr/io.h>
#include <avr/interrupt.h>
int k=0;
int n=0;
void setup() {
  pinMode(13, OUTPUT);


  TCCR1A  = 0;
  TCCR1B  = 0;
  TCCR1B = bit(WGM12) | bit(CS11) | bit(CS10); // CTCモードで分周率64
  TIMSK1 = bit(OCIE1A); // 割り込みをタイマー1に設定
  //TCCR1B |= (1 << WGM12) | (1 << CS12);  //CTCmode //prescaler to 256
  OCR1A   = 11-1;
  //TIMSK1 |= (1 << OCIE1A);
}


ISR (TIMER1_COMPA_vect) {
 if(k<100){
    k=k+1;
  }
  else{
    k=0;
    digitalWrite( 13, HIGH);
  }
  if(k==n){
    digitalWrite( 13, LOW);
  }
}


void loop() {
   while(n<100){//だんだん明るくする
    n=n+1;
    delay(25);
  }
   while(n>1){//だんだん暗くする
    n=n-1;
    delay(25);
  }
 
}

動作している様子です。時々,ちらつきがあります。LEDで動かしていますが,もしかして,これで,モー
ターを制御するとばたついたりするかもしれません。

Arduino—再び(4)–LCD Keypad Shield

あれこれやって、思った動作ができるようになりました。やろうとしてたのは、arduinoで、リニアステージの
ステッピングモーターをパルスを送ることで動かすことでした。今回は、TB6600というドライバーを経由し
て、制御しました。結線等は、例によって、諸兄のHPを参考にしました。
このドライバーには、

     ENA- ⇒⇒デジタル11番ピン
     ENA+ ⇒⇒5V

     DIR- ⇒⇒デジタル12番ピン
     DIR+ ⇒⇒5V

     PUL- ⇒⇒デジタル13番ピン
     PUL+ ⇒⇒5V

の6本の接続が必要ですが、プラス側に接続してもマイナス側に接続しても動くようでしたが、aruduinoで
は、+端子は一律5Vに落として、-の端子の方をそれぞれに結線しました。TB6600の内部配線がどうなって
るのか気になるところです。

動作させているところです。パルスを設定して、SELECTボタンで動かしてます。パルスの数値を+と-の設定にすることで、反対の方向に移動させてます。

今回は、別な面で苦労しました。YouTubeの設定が変わったのが、埋め込みリンクの書いてあるところが分からず、時間ばかりかかりました。分かるとなんのことはない、自分の動画の再生画面で、右クリックをするとその項目があり、分かった時は、がっかりしました。

とりあえず動いたarduinoのスケッチアップします。例によってデバックように入れておいたserial.print等の残ったままのものです。

Arduino—再び(3)–LCD Keypad Shield

ほぼ目的のプログラム(スケッチ--arduinoではこう呼ぶみたいですね。)ができました。難しいものではな
く、入門編によくあるようなLチカ(LEDを点灯させる)のプログラムと大差ありません。ただ、キーの読み取
りをアナログの変化で読み取っているので、安定しない部分があるのか、長押しの判別がどうしても、できま
せんでした。

               押されたキーの判別
                    │
          ┌───────────────────────┐
    UPキーが押された⇒⇒ +1の処理    UPキーが長押しされた⇒⇒+10の処理

のようにしたかったのですが、あきらめて、+10の処理は、RIGHTキーに割り当てました。 スケッチでは、

   キー判別の関数の呼び出し
      
   呼び出されたそれぞれキーの回数をカウントする
      
   カウントが一定以上になったら、キーに応じた処理をする。

という単純なことを、メインのLOOPのなかで、繰り返してるだけです。「回数をカウント」の部分はなくても
いいのですが、一応チャタリングの対策です。
入力した数字をLCDに表示するのに数字の桁数が違ってしまうと、正しい表示がされないので、左詰めで表示
できるように簡単な関数を作りました。文字数を取得する関数が準備されてますが、その書式がどちらかとい
うとエクセルのVBAのような感じで、ちょっと戸惑いました。PICのC言語だと目的の文字を括弧の中にいれる
のですが、ピリオドで連結するようでした。このへんの細かい文法は、その都度調べないとだめですね。

   arduinoの記述  s.length( )  (sが長さを求める文字)
   PICのC言語記述 sterlen(s)   (sが長さを求める文字) 

“Arduino—再び(3)–LCD Keypad Shield” の続きを読む

Arduino—再び(2)–LCD Keypad Shield

LCD Keypad Shield が届いたので、あれこれはじめました。

諸兄のプログラムをお借りして、動かしてみました。すんなりと動きましたが、LCDの表示で、明るさの調整がボリュームで必要でした。
 ただ、KEYの読み取りで、判別条件の調整が必要でした。諸兄の物と届いた物では、抵抗値が違うのだと思いますが、下記赤字部分のように、アナログの読み込みの値の修正をしました。

     int read_LCD_buttons(int adc_key_in){
          if (adc_key_in > 1000) return btnNONE;
          if (adc_key_in < 50) return btnRIGHT;
          if (adc_key_in < 150) return btnUP;
          if (adc_key_in < 300) return btnDOWN;
          if (adc_key_in < 600) return btnLEFT;
          if (adc_key_in < 750) return btnSELECT;
          return ERRORR;
     }

この辺は、メーカーの違い、個体値の違い、等によって調整が必要なようです。このアナログ値の調整をする
にあたっては、諸兄の作成されたプログラムが都合がよかったです。キーごとの電圧が表示されますので、そ
れをみながら、調整ができます。私はそのまま使いましたが、表示が電圧ではなくて、アナログの読み取り値
だともっと楽だと思います。また、標準のライブラリーとは、LCDのピンの配置が多少違うので、下記のよう
に、ピンの表示の部分の変更も必要でした。これは、別の諸兄のHPに記載がありました。

     #include LiquidCrystal
      lcd(8, 9, 4, 5, 6, 7);

LCDの表示用にデジタルの、8,9,4,5,6、7、キーの判別ようにアナログのA0のピンを使用していますので、ユーザーはそれ以外のピンしかつかえません。基盤の裏のパターンをたどってみると、

写真の緑黄色矢印から、

 13,12,11,3,2,1,0

の並びで、デジタルのピンを取り出せるようです。また、アナログは、本体右下のピンヘッダーから、

のように、

 1,2,3,4,5

のアナログのピンを取り出せるようです。

大捜索をするようですが、部品を収納した、ケースにピンヘッダーがあったように記憶してますので、探しだして、取り付けたいと思ってます。

Arduino—再び(1)–LCD Keypad Shield

しばらく前にArduinoを使って、フライス用にDROの表示用のものを作成しました。また、備忘録をかねて、
Arduinoをいじりはじめました。LCDと外部入力(キーパッド)のものがほしかったので、いろいろ調べまし
た。
スイッチサイエンスのLCDシールドは手元にあったのですが、これは、

外部入力ができないので、〇zonで、LCD Keypad Shieldくぐると、600円~5000円のものが引っかかりました。LCD 1602でくぐると、600円から30000円と幅広いものが引っかかります。30000円のもの買う方いるのかなと疑問に思ってしまいますが、もちろん、安い物をポチリました。

ただ、ポチったものには、ピンへダーがついてないので、後付けするようかなと思います。2700円だいのものには、ピンヘッダーが付いていますが、高いですね。

これらのシールドには、5個のkeyが付いていますが、どうやって、判別をしてるのかと思いましたが、
keyの配線図がのってました。

抵抗を介して一つのポートに接続しているようですが、どうやって判別するのか、くぐってみると、どうや
ら、電圧の違いで判別してるようでした。
KeyPad用のライブラリーには、

  iuint8_t LiquidCrystal::readButtons(void) {
    int adc_key_in = analogRead(0);
     // read the value from the sensor
    // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
    // we add approx 50 to those values and check to see if we are close
    if (adc_key_in > 1000) return 0x00;
    if (adc_key_in < 50) return BUTTON_RIGHT;
    if (adc_key_in < 195) return BUTTON_UP;
    if (adc_key_in < 380) return BUTTON_DOWN;
    if (adc_key_in < 555) return BUTTON_LEFT;
    if (adc_key_in < 790) return BUTTON_SELECT;
    return 0x1F; // when all others fail, return this…   }

のように記述があり、アナログで電圧の変化によって、判別してるようでした。使用上の注意に接点経年劣化やチャタリング等の対策がソフトの方で必要だとの記述もありました。

arduino+Android端末+bluetooth で DRO (TouchDRO)

 やっと長い冬眠から目覚めました(笑)
 ちょっと面倒になって,ブログの更新をしていませんでした。
 その間も,いろいろあさってましたが,ある海外のサイトで,
 arduinoを使って,Android端末をDROにする記事がありました。
 いろいろくぐって,オープンソースでプロジェクトを作成してる

 HPにたどりつきました。

 まねしてみようと思い,あれこれもがきました。ブレッドボードで,

 

 写真のような回路で実験しましたが,次の動画のような
 結果がでましたので,また,備忘録がてらまとめておこうと
 思います。

 回路図は,前掲のHPの冒頭にありますので,簡単に作成できる
 はずです。

 

  (HPよりお借りしました。)

 部品は下記の記述がありました。

   R1-R3   Resistor, 10K 3
    R4      Resistor, 330 Ohm 1
    R5      Resistor, 220 Ohm 1
    C1-C3   Capacitor, ceramic, 0.1uF 3

 思うようにいかなかったのは,USBのコネクターもピンアサインで。
 あれこ調べました。

 

 写真と回路図は,VCCとGNDが逆なので,注意が必要でした。
 それと,

    「D+」・・・・・・・・「Z-3」(データ)
    「D-」・・・・・・・・・「Z-2」(クロック)

 ようになってますので,ここも要注意かなと思います。

 写真の「ID」は,無結線です。
 それと,BLUETOOTHのアダプターですが,当初 HM-18 という
 のを使いましたが,Android端末と接続が持続できないので,
 HC-5 という物に交換しました。aruduinoとの接続で,分圧等
 で,電圧落とす必要があるのかなと思いましたが,直結で
 大丈夫でした。

 

 USBのコネクターも,HC-5のBLUETOOTHも●ZONから購入
 しました。

 プログラムは,MSP430LaunchPad用とarduino用があるようで,
 記載されているHPも違うようです。

     MSP430用プログラム
     aruduino用スケッチ
  スケッチは,HPの下の方にあります。

  Android端末用のアプリは,
  Google Play

 から入手できます。
 私は,フライスのZ軸に使ってたDROが調子悪くなり,
 時々数値が飛ぶようになったので,新しい物に交換しましたので,
 調子の悪いものて実験しました。また,Android端末は,家の
 が前に使ってたArrows NX なる古い携帯をつかいました。

 AndroidのエミュレータをPCに入れてやってみましたが,
 BLUETOOTHの設定がうまくいかず,動きませんでした。
 実験で使ったスケールはiGagingの古いものですが,新しいものにも対応し
 ているようで,基盤そのものの販売もあるようです。
 基盤を購入して,つなげばそれでできますので,
 その方がてっとりばやいかもですね。でも高い。
 互換品等使えば,DROが安く設置できるかもですね。

ラインレーザーの作成

 いろいろネットサーフィンをしていたら,前にも目にとまりましたが,
 ラインレーザーの自作
 自作テーブルソー
 のHPが目にとまりました。
 ラインレーザー制作では,◯月のレーザーモジュールを使ってる
 ようでした。レーザーモジュールやアルミ角材は,容易に手に
 はいりますが,ガラス棒が難関でした。
 ネットで検索すると,アロマのお店にあるということで,
 「生活の木」というブランドのアロマのお店で購入しました。

 

 ネットで調べましたが,販売単位が10本とかで,送料を入れると,
 2000円程度になるので,使えるかどうかはわかりませんが,
 160円程度で購入できたので,よかったです。
 残念ながら,◯華製でした。

 

 ガラス棒というと,学校の理科室にたてかけてあった長い
 ものを思いうかべてしたが,両端が処理されているせいか,
 割高のような気がします。