製作モジュール一覧

ラベル Graphic LCD の投稿を表示しています。 すべての投稿を表示
ラベル Graphic LCD の投稿を表示しています。 すべての投稿を表示

2017年9月16日土曜日

u8g2のFull BufferとPage Buffer


この間、u8g2で描画テストをしてみてSRAMを消費しすぎていたので原因を考えてみた。
#define RULER_STR "ABCDEFGHI012345678901234567890"
としていて、
u8g2.drawStr(0,10,RULER_STR); // write something to the internal memory
u8g2.drawStr(0,21,RULER_STR);  // write something to the internal memory
u8g2.drawStr(0,32,RULER_STR);  // write something to the internal memory
と、「#define」した文字列を3回も定義していることになるので、これが原因かも?と思って「#define」のところを「const char*」に変更してみた。

「const char*」なら定義は1回なので1/3になるはずだが・・・

Arduinoのスケッチ
<HiLetgo_IIC_OLED_SSD1306_128x32_u8g2_F_FontTest.ino>

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);  // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED

void setup(void) {
  u8g2.begin();
}

const char* RULER_STR = "ABCDEFGHI012345678901234567890";

void loop(void) {
  u8g2.clearBuffer();                   // clear the internal memory
  u8g2.setFont(u8g2_font_8x13_tf);  // choose a suitable font  
  u8g2.drawStr(0,10,RULER_STR); // write something to the internal memory
  u8g2.drawStr(0,21,RULER_STR);  // write something to the internal memory
  u8g2.drawStr(0,32,RULER_STR);  // write something to the internal memory
  u8g2.sendBuffer();                    // transfer internal memory to the display
  delay(1000);

  u8g2.setDrawColor(1);
  u8g2.drawBox(0, 0, 128, 32);
  u8g2.sendBuffer();
  delay(1000);  
}

ビルドの結果は
最大30720バイトのフラッシュメモリのうち、スケッチが9650バイト(31%)を使っています。
最大2048バイトのRAMのうち、グローバル変数が1512バイト(73%)を使っていて、ローカル変数で536バイト使うことができます。
となって、SRAMの消費量は「#define」の時と同じ1512バイト。この程度は最適化されるようだ。

Arduino IDEと言っても中でavr-gccでGCCを使っている。さすがGCCは賢い(^q^!

<追記:2017.09.18>

文字列定数はSRAMではなくフラッシュメモリに格納されると思うので、フラッシュメモリの使用状況も比較。

「#define」時
最大32256バイトのフラッシュメモリのうち、スケッチが9644バイト(29%)を使っています。
最大2048バイトのRAMのうち、グローバル変数が1512バイト(73%)を使っていて、ローカル変数で536バイト使うことができます。

「const char*」時
最大30720バイトのフラッシュメモリのうち、スケッチが9650バイト(31%)を使っています。
最大2048バイトのRAMのうち、グローバル変数が1512バイト(73%)を使っていて、ローカル変数で536バイト使うことができます。

フラッシュメモリの使用量は「const char*」の方が増えている(@@;

</追記>

Page Buffer


ということはFull Bufferだと転送用バッファでメモリ領域を専有しているのでは?と思って、Page単位のクラスを使ってみた。

Arduinoのスケッチ
<HiLetgo_IIC_OLED_SSD1306_128x32_1_FontTest.ino>

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>

U8G2_SSD1306_128X32_UNIVISION_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);  // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED

void setup(void) {
  u8g2.begin();
}

const char* RULER_STR = "ABCDEFGHI012345678901234567890";

void loop(void) {
  u8g2.firstPage();
  do {
    // u8g2.clearBuffer();         // clear the internal memory
    u8g2.setFont(u8g2_font_8x13_tf);  // choose a suitable font
    u8g2.drawStr(0,10,RULER_STR); // write something to the internal memory
    u8g2.drawStr(0,21,RULER_STR);  // write something to the internal memory
    u8g2.drawStr(0,32,RULER_STR);  // write something to the internal memory
    // u8g2.sendBuffer();          // transfer internal memory to the display
  } while (u8g2.nextPage());
  delay(1000);

  u8g2.firstPage();
  do {
    // u8g2.clearBuffer();         // clear the internal memory
    u8g2.setDrawColor(1);
    u8g2.drawBox(0, 0, 128, 32);
    // u8g2.sendBuffer();
  } while (u8g2.nextPage());
  delay(1000);
}


<追記:2017.10.03>

Page Buffer Modeで使う場合、do while()ループ内でu8g2.clearBuffer()、u8g2.sendBuffer()は不要とご指摘いただいたので、スケッチを修正しました。

</追記>

クラス指定を
U8G2_SSD1306_128X32_UNIVISION_1_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);  // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED
に変更した(クラス名の途中のFを1にする)。描画の仕方もPage単位で「do while()」で回すように変更。
最大30720バイトのフラッシュメモリのうち、スケッチが9730バイト(31%)を使っています。
最大2048バイトのRAMのうち、グローバル変数が616バイト(30%)を使っていて、ローカル変数で1432バイト使うことができます。
Full Bufferが1512Bなのに対して、Page Bufferだと616Bで済んでいる。

ただし、ページ単位の書き換えだと書き換えが上から下へとダラダラした描画になる。ベースマシンのシーケンサーのStep表示みたいなリアルタイム書き換えだと見栄えがよくない。

アニメーションさせようと思うと、昔のパソコンの裏VRAMやDirect Drawみたいな感じでFull Bufferを使ったほうがいいと思う。

メモ:


SSD1306はu8glibやu8g2の他にも専用のライブラリが多数公開されています。


2017年9月10日日曜日

HiLetogo 0.9" I2C OLED 128X32をu8g2で使ってみる。

久々にu8glibのWikiページを見たら、「今後開発しないのでu8g2を使うよう」に書いてあったので、試してみた。

u8gとu8g2の違いはhttps://github.com/olikraus/u8g2/wiki/u8gvsu8g2

Improvements
  • Full "RAM" memory buffer without picture loop
  • Arduino SPI and TWI Libraries instead of custom code
  • Support for Unicode and UTF-8
  • Faster compilation
  • High speed text only API (U8x8)
  • Hardware 180 degree rotation for some displays available
  • Tested with AVR, SAM and ESP8266 boards
とある。ページ単位の書き込みをしなくてよくなったようだ。(以前のようにdo while() で描画する方法も残されている)

ライブラリのArduinoへのインストールはhttps://github.com/olikraus/u8g2/wiki/u8g2installにキャプチャ画像入で紹介されているのでその通りにすればインストールできた。

exampleは
  • full_buffer フルバッファで1回で書込み。
  • games おまけ
  • page_buffer ページ単位で書き込み。
  • u8x8 8x8ドットの文字にのみ対応した軽量版
に分かれている。u8x8はHiLetgoのOLEDには小さすぎるかな~

見やすいフォントをさがしてみる。


Arduinoのスケッチ
<HiLetgo_IIC_OLED_SSD1306_128x32_u8g2_F_FontTest.ino>

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);  // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED

void setup(void) {
  u8g2.begin();
}

#define RULER_STR "ABCDEFGHI012345678901234567890"

void loop(void) {
  u8g2.clearBuffer();                   // clear the internal memory
  u8g2.setFont(u8g2_font_8x13_tf);  // choose a suitable font  
  u8g2.drawStr(0,10,RULER_STR); // write something to the internal memory
  u8g2.drawStr(0,21,RULER_STR);  // write something to the internal memory
  u8g2.drawStr(0,32,RULER_STR);  // write something to the internal memory
  u8g2.sendBuffer();                    // transfer internal memory to the display
  delay(1000);

  u8g2.setDrawColor(1);
  u8g2.drawBox(0, 0, 128, 32);
  u8g2.sendBuffer();
  delay(1000);  
}

u8g2のFull Pageバージョンを使ってみた。

クラスは

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);  // Adafruit ESP8266/32u4/ARM Boards + FeatherWing OLED

を指定すれば動作した。「UNIVISON」という名前が何を意味するのかよくわからないですが(^q^;

スケッチはカットアンドトライで見やすいフォントを探したもの。loop()内のdrawBox()は画面のフルサイズで四角を書いて表示領域を確認した。このOLEDの表示域は少し上に偏っているようだ。


「u8g2_font_8x13_tf」を指定すると昔のパソコンっぽい感じのフォントで、16桁3行表示できる。


I2Cの通信状態



ch1:SDA ch2:SCL

デフォルトでFast Mode(400kHz)で動作している。

波形がかなりなまっているので、モジュール上でプルアップされている(おそらく)4.7kΩと並列になるようにブレッドボード上でも4.7kΩのRでプルアップした。

4.7kΩ//4.7kΩ = 2.35kΩ相当のプルアップになる。



ch1:SDA ch2:SCL

波形はきれいになる(←ノイズ等に強くなり誤動作が減る)が、電流が多く流れるのでトレードオフです。

メモ:


exampleのu8g2/page_buffer/Japaneseは、Arduino Uno R3だとメモリが足りなくてコンパイルできなかった。

Arduino:1.8.1 (Windows 10), ボード:"Arduino/Genuino Uno"
最大32256バイトのフラッシュメモリのうち、スケッチが32634バイト(101%)を使っています。
最大2048バイトのRAMのうち、グローバル変数が614バイト(29%)を使っていて、ローカル変数で1434バイト使うことができます。
スケッチが大きすぎます。http://www.arduino.cc/en/Guide/Troubleshooting#size には、小さくするコツが書いてあります。
ボードArduino/Genuino Unoに対するコンパイル時にエラーが発生しました。

フォントデータがでかいのかな?

上記スケッチでも

最大32256バイトのフラッシュメモリのうち、スケッチが9644バイト(29%)を使っています。
最大2048バイトのRAMのうち、グローバル変数が1512バイト(73%)を使っていて、ローカル変数で536バイト使うことができます。

メモリ食いますね(@@;

2017年9月6日水曜日

HiLetogo 0.9" I2C OLED 128X32が届いたのでFast Mode(400kHz)で動作させてみた。


HiLetgoで買ったAD9833モジュールがけっこうちゃんとした製品だったので、OLEDも発注して到着したので試してみた。



8/23に発注して、今日9/6に届いたのでちょうど2週間。

ドライバICのSSD1306は、以前aitendoのOLEDでU8glibで試したことがあるのであっさり動作してくれた。

aitendoのOLEDは3.3V駆動が仕様でSPI接続で使ったので、5V駆動のArduinoから使うために5V→3.3Vのレベル変換をロジックICを使って行ったが、今回購入したOLEDはI2C接続で、駆動電圧3.3V~5Vとなっているのでレベル変換は行っていない。

とは言ってもSSD1306のデータシートを見ると、

• Power supply
o VDD = 1.65V to 3.3V for IC logic

となっているので、3.3V駆動で試してみた。

ブレッドボード配線


配線図は書くまでもなく写真の通り

  • I2C OLEDの電源はArduino Unoから3.3Vを供給
  • I2CのSCL、SDAはモジュール上でプルアップされているので、ArduinoのA5(SCL)とA4(SDA)を直結

Arduinoのスケッチ


U8glibのexampleで試してみた。

使い方は、exampleの

//U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // I2C / TWI

という行のコメントアウトを外して

U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // I2C / TWI

として、SSD1306のI2C接続を指定すれば動作した。

I2CのFast Modeで動作させてみる。


いまだにちゃんと使いこなせないI2Cだが、Slave動作のI2Cデバイスなら細かいところはライブラリまかせにすれば、それほど深みにはまらずに済む。

I2Cでよく参考にしているのはトラ技の2014年10月号の「2線シリアル・インターフェースI2C詳解」という記事。



I2Cには通信速度によってStandard mode、Fast mode、その他より高速なモードがある。

Standard modeはクロックが100kHzでFast modeはクロックが400kHzだ。

SSD1306のデータシートによると、

Symbol Parameter Min Typ Max Unit
tcycle Clock Cycle Time 2.5 - - us

となっていて、2.5nsの逆数は400kHzなのでFast Modeでも動作できそうだ。

U8glibをI2CのFast Modeで動作させるには

U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_FAST); // I2C / TWI

と、コンストラクタのオプションに「U8G_I2C_OPT_FAST」を指定してやればFast Mode(400kHz駆動)で動作する。

Normal ModeとFast Modeの動作速度比較


U8glibには「FPS」という書き換え速度を測定するexampleがあるので比較してみた。

Test Normal Fast Ratio
draw clip test 15.3 34.9 2.281045752
clear screen 9.8 14.0 1.428571429
draw @ 10.7 17.5 1.635514019
draw pixel 7.2 9.8 1.361111111

クロック数の比率の4倍にはならないが、まあまあ高速化できると思う。

I2C通信のようす


Normal Mode (100kHz)

ch1:SDA ch2:SCL

SCLはマス目で読み取って100kHz。

Fast Mode (400kHz)

ch1:SDA ch2:SCL

SCLは400kHz。

Fast Modeでは波形がなまっているので、プルアップ抵抗の抵抗値を下げるとかなんかした方がいいかもしれない。

消費電流


電源のVCC側に10Ω(実測値9.9Ω)のシャント抵抗を入れて電圧をテスタで測定してみると、どちらも

30mV~130mV / 9.9Ω ≒ 3mA~13mA

バックライト付きのLCDよりすこし多いぐらいか。

aitendoのI2C接続のキャラクタLCDとのサイズ比較



いつも使っているaitendoのSPLC792-I2Cと比べると、面積比で1/2ぐらいだと思う。

サイズは小さいが、視認性はかなりよくキャラクタ表示の16桁×2ぐらいならOLEDの方がいいんではと思う。

特にコントラストと、角度をつけて斜めから見た時の視認性はかなりいいと思う。

2016年8月6日土曜日

Nucleo F401REのMorpho HeaderでaitendoのSPI Graphic LCDのCH12864F-SPIを使ってみる。

aitendoのFSTN液晶モジュール(SPI) [CH12864F-SPI]をNucleo F401RE(mbed)で動かす。」でNucleo F401REのAruduino互換ヘッダを使って動作させてみたが、NucleoのMorpho Headerでもやってみた。

Morphoというのはモルフォ蝶という蝶の一種らしい。Arduino Headerの横に蝶の様にハネを広げているということなのだろうか。画像を検索するとなかなか綺麗な蝶だ。

same as Arduino header


NucleoのMorpho Headerの2列のうち内側は基本的にArduino Headerとつながっている。ヘッダのオス/メスが違う。

配線図

ファームウェア
https://developer.mbed.org/users/ryood/code/CH12864F-SPI_Test/


Morpho Headerにつないでも表示できた。

SPI2


Nucleo F401REにはSPIのHWが3個あって、2番目を使ってみた。

配線図

ファームウェア
https://developer.mbed.org/users/ryood/code/CH12864F-SPI2_Test/


こちらは半分ずれて表示されてしまった。オシロで信号を確認するとSPIのSCK、MOSI、CS、LCDコントロール制御用のa0はそれっぽい波形が出ているので制御コマンドがらみかもしれない。

メモ:


SPI1では正常表示されてSPI2ではダメ。

表示バッファが2枚あって順番が逆とかかな。

作成中のベース・マシンでは音源系にSPIを使っているので、シーケンス打ち込み用のLCDはSPI2を使いたい。

2016年5月27日金曜日

aitendoのFSTN液晶モジュール(SPI) [CH12864F-SPI]をNucleo F401RE(mbed)で動かす。

大き目サイズのSPIグラフィックLCDを仕入れてみたのでテスト。

配線図


LEDA(11Pin)は基板上に電流制限抵抗が載っているようだが、一応100Ωの抵抗を入れてVDD(+3.3V)につないだ。

mbedのライブラリはMasato YAMANISHIさんが公開されているst7565LCDクラスを利用した。

main.cpp

#include "mbed.h"
#include "st7565LCD.h"

int main()
{
    //ST7565(PinName mosi, PinName sclk, PinName cs, PinName rst, PinName a0);
    ST7565 gLCD(SPI_MOSI, SPI_SCK, SPI_CS, D9, D8);
    
    gLCD.begin(0x10);
    
    while (true) {
        gLCD.drawstring(0, 0, "Hello World.");
        gLCD.display();
        wait(0.1);
    }
}

ST7565::display()関数を呼び出すことでLCDへの書き込みがおこなわれる。

aitendoのSPI接続のグラフィックLCD



左から、CH12864F-SPI(128x64/SPI)、F12864G25412P1701(128x64/SPI)、Nokia LCD5110(84x48/SPI)。

2016年5月18日水曜日

Nucleo F401RE(mbed)でNokia5110を動かす。

NucleoF401REでNokiaのSPI LCDのLCD5110を動作させてみた。

ブレッドボード図


5V->3.3Vのレベル変換には74HC4050を使った。(参考「ロジックICでSPIの5V->3.3Vレベルシフト Nokia LCD5110を動かす」)

<追記:2016.05.19>

Nucleoは3.3V駆動のようで5V->3.3Vのレベル変換は不要でした。3.3VのLCDに直結して大丈夫です。

</追記>

mbedのオンライン・コンパイラで、「5110_Display」というプログラムを見つけてインポートして使った。

main.cppのN_5110_Displayクラスのコンストラクタで、引数をブレッドボード図の接続の通りNucleoのPin名(Arduino互換名)に変更。

//N_5110_Display Display( p5, p6, p7, p8, p9, p10 );
N_5110_Display Display( D11, NC, D13, D10, D9, D8 );

また、cmsis.hが見つからないというエラーが出たが、mbedライブラリをアップデートしたらコンパイルできた。


プログラムワークスペースで「mbed」の上で右クリック。

メモ:


このN_5110_DisplayクラスはmbedのSPIを使っているようだ。

無償のSTM32用のIDEに「CooCox」意外にも「AC6 SW4STM32」というのがあるようだ。

ARM Cortex-M4でIOピンも多いし安いし(\1,500@秋月)シーケンサーはArduinoからNucleoに移行しようかな…

ToDo:


タイマー割り込み、PSoCとSPI通信、ロータリーエンコーダー、タクトスイッチのチャタリング対策

2016年5月12日木曜日

aitendoのSPI LCD(F12864G25412P1701)をArduinoのUC1701ライブラリで動作させてみる。

aitendoのFSTN液晶モジュール(F12864G25412P1701) のコントローラーの
UC1701専用のライブラリが公開されていたので使ってみた。

ソースは少し雑な感じだが(人のこと言えないですが(^q^;)、U8GLIBよりシンプルなので改変して使うには楽そう(←希望的観測)

このライブラリもAVRのSPIハードウェアは使っていないようだ。

ブレッドボード図


5V→3.3Vの変換にはふたたび74HC4050を使っている(参考:「ロジックICでSPIの5V->3.3Vレベルシフト Nokia LCD5110を動かす」)

Example/HelloWorldをやってみたが、コンストラクタで
//static UC1701 lcd;
static UC1701 lcd(13, 11, 10, 9);
と、接続通りのPinを指定。

RESET線はVCCにつないでも良さそうだが一応Arduino UnoのD8につないで、setup()内で
  // RESET PIN (D8)
  pinMode(8, OUTPUT);
  digitalWrite(8, LOW);
  delay(1);
  digitalWrite(8, HIGH);
として、リセットをかけた。

メモ:


予備のNokia LCD5110をハンダ付けしたらうまく動かなかった。一瞬表示されたけどだめっぽい。原因不明。なのでこのLCDももう少し使ってみることにした。

128x64でサイズが小さいので解像度は高いけど、コントラストが弱くてちょっと見づらい。

U8GLIBで比べるとNokia LCD5110より描画速度は速そう。

2016年5月9日月曜日

Arduino UnoをSPIのMasterにして、複数のSlaveを使う。

PSoC 4 Pioneer KitをSPIのスレーブとして動作させて、SPI LCDのNokia 5110も同じSPIバスを使って動作させてみた。

<追記:2017.08.30>

ArduinoはSPI Slaveにすることができないので、Arduinoのスケッチの中でAVRのレジスタを使って実験しました。

Arduino UnoをSPI Slaveとして使う。

</追記>


※実際の配線では「Arduino Uno」と「Nokia 5110」間のMISOはつながっていません。

SPIはスレーブの切り替えにSS(Slave Select。CS/Chip Select)を使う。信号線はMasterSlaveのMOSIとMasterSlaveのMISOの2本だがスレーブの数だけSSが必要になる。

<追記:2016.06.03>

書き忘れてましたが、SPI通信には信号線以外にクロック線のSCKが必要です(^q^;

</追記>

ブレッドボード図

動作としては、

1) MasterのArduinoが、繋がれているPOTの値を読み取り、SPIでSlaveのPSoC4に送信する。

2) SlaveのPSoC4はArduinoから送られてきたデータを受け取り、繋がれているロータリー・エンコーダーの値を読み取り、MasterのArduinoに送信する。

3) SlaveのPSoC4はArduinoから送られてきたデータの値(RX)と、Arduinoに送ったデータ(TX)をキャラクタLCD(パラレル接続)に表示する。

4) MasterのArduinoは1)で自分が送ったデータ(TX)と、SlaveのPSoC4から送られてきたデータ(RX)をSPI接続のLCDのNokia 5110に表示する。

したがって、POTを回しても、ロータリー・エンコーダーを回してもArduinoのLCDにもPSoC4のLCDにも同じデータが表示される。

Master側のArduinoのスケッチ


// PSoC 4 SPI Slave用のMasterプログラム
// 
// POTでTXデータを設定、NOKIA 5110でTX,RXデータを表示
//
// PSoC 4 Slave
//      SCK    13
//      MISO   12
//      MOSI   11
//      CS      9
//
// LCD5110 
//      SCK  - Pin 13
//      MOSI - Pin 11
//      DC   - Pin 2
//      RST  - Pin 3
//      CS   - Pin 10
//
// POT  A0
//
// 2016.05.09
#include <stdio.h>
#include <SPI.h>
#include <LCD5110_Graph.h>

#define PIN_PSOC_SS  9
#define PIN_POT      A0

#define TX_PACKET_SIZE  3
#define RX_PACKET_SIZE  3

LCD5110 myGLCD(13,11,2,3,10);  // SCK, MOSI, DC, RST, CS

extern uint8_t SmallFont[];

byte txBuffer[TX_PACKET_SIZE];
byte rxBuffer[RX_PACKET_SIZE];

char strBuffer[17];

void setup()
{
  myGLCD.InitLCD();
  myGLCD.setFont(SmallFont);
  
  myGLCD.clrScr();
  myGLCD.print("SPI Master", 0, 0);
  myGLCD.update();
  
  pinMode(PIN_PSOC_SS, OUTPUT);
}

void loop()
{
  int txData;
  int rxData;
  
  txData = analogRead(PIN_POT);
  rxData = sendRecieveData(txData);
  displayData(txData, rxData);
  delay(100);
}

int sendRecieveData(int txData) {
  static byte cnt;

  txBuffer[0] = cnt++;
  txBuffer[1] = txData >> 8;
  txBuffer[2] = txData & 0xff;

  SPI.begin();
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
  digitalWrite(PIN_PSOC_SS, LOW);
  rxBuffer[0] = SPI.transfer(txBuffer[0]);
  rxBuffer[1] = SPI.transfer(txBuffer[1]);
  rxBuffer[2] = SPI.transfer(txBuffer[2]);
  digitalWrite(PIN_PSOC_SS, HIGH);
  SPI.endTransaction();
  SPI.end();

  return ((int)rxBuffer[1] << 8) | (rxBuffer[2]);
}

void displayData(int txData, int rxData) {
  myGLCD.clrScr();
  myGLCD.print("SPI Master", 0, 0);
  
  sprintf(strBuffer, "TXDATA: %d", txData);
  myGLCD.print(strBuffer, 0, 10);
  
  sprintf(strBuffer, "TX:%03d %03d %03d", txBuffer[0], txBuffer[1], txBuffer[2]);
  myGLCD.print(strBuffer, 0, 20);

  sprintf(strBuffer, "RX:%03d %03d %03d", rxBuffer[0], rxBuffer[1], rxBuffer[2]);
  myGLCD.print(strBuffer, 0, 30);

  sprintf(strBuffer, "RXDATA: %d", rxData);
  myGLCD.print(strBuffer, 0, 40);

  myGLCD.update();
}

Nokia 5110の表示には「Nokia5110_Graph」ライブラリを使っている。(参考「ロジックICでSPIの5V->3.3Vレベルシフト Nokia LCD5110を動かす」)。

PSoC4とのSPI通信にはArduinoの「SPI」ライブラリを使った。「NOKIA5110_Graph」はArduinoのSPIライブラリを使用していない(ATMega328pのハードウェアSPIも使っていない)ので、PSoC4との通信の前後でSPIオブジェクトをbegin()、end()させている。こうしないとNokia 5110との通信がうまくいかない。

送受信データは、どちらも3byteにしていて、Masterが生成したカウンターの値(1byte)+POT/RotaryEncoderの16bitの読み取り値(2byte)。

Slave側のPSoC4のプロジェクト


TopDesign

SPISはSCBのSPIコンポーネントでスレーブに設定している。UARTはデバッグ用に使った。PIN_REというPINコンポーネントはロータリー・エンコーダーの読み取り用。

Github:
https://github.com/ryood/PSoC4_SPI_Slave_Test

Master側 (Arduino)
https://github.com/ryood/PSoC4_SPI_Slave_Test/tree/master/Arduino(Master)/SPI_Master_PSOC4_Slave_w_UI

Slave側 (PSoC4)
https://github.com/ryood/PSoC4_SPI_Slave_Test/tree/master/PSoC(Slave)/PSoC4_SPI_Slave_Test

メモ:


SPIは全二重なので送信だけ、受信だけという使い方にするには少し工夫が必要。普通のシリアル通信のようにプログラムを書くと電話でお互いが勝手に喋っべいるみたいな状態(自分の声でかき消されて相手が何を言っているか聞き取れない?)になってしまってハマってしまった。

SlaveからMasterに送信するには、Master側からSlaveに「どうぞ」と声をかけてからSlaveが送信するとか、Master側から制御するR/Wの信号線を追加するとかしないとダメかもしれない。

2016年5月6日金曜日

Arduino UnoでaitendoのSPIグラフィックLCD(F12864G25412P1701)を動かしてみる。

以前、3.3V駆動のArduino Pro Miniで動かしたが、またまた74HC4050を使って5V->3.3V変換してArduino Unoで動かしてみた。

ブレッドボード図

LCDのLEDA(バックライトLEDのアノード)には基板上で電流制限抵抗が入っているのでVDDに直結していいが、


直結するとバックライトが明るすぎたので100Ωの抵抗を入れた。

U8GLIB


U8GLIBのExampleはコンストラクタに
U8GLIB_MINI12864 u8g(10, 9, 8); 
を1行追加するだけで動く。SCK=13, MOSI=11だがこれを省略して、CS=10、A0=9、RESET=8だけパラメータで指定するとハードウェアSPIで動作するようだ。

少しだけ図形を書いてみるテストをしてみたが、

  // picture loop  
  u8g.firstPage();  
  do {
    draw();
  } while( u8g.nextPage() );


と言う風な流儀で描画をしないといけないようだ。(draw()関数内で実際の描画コマンドを発行する)

で、ドキュメントを流し読みしてみると、毎回画面がクリアされて全部書き直さないといけないようで、アニメーション等で前の絵の一部だけ上書きしたい場合速度的に問題がある。

ちゃんとドキュメントやソースを読んでいないので何とも言えないが、PSoC等で使うときにもう少し調べてみる予定。

2016年5月4日水曜日

Nokia LCD5110をU8GLIBで使ってみる。

Nokia LCD5110もAruduinoのU8GLIBで対応しているようなのでやってみた。

一応表示はできた


が、Exampleの「GraphicTest」を動かしてみるとaitendoのOLEDを使った時に比べるとかなり遅いようで表示が乱れてしまう。

初期化はU8GLIB_PCD8544クラスを指定した。

U8GLIB_PCD8544 u8g(13, 11, 10, 9, 8); // SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9, Reset = 8

配線はLCD5110_Basic を使った時と同じように74HC4050を使って5V→3.3V変換して、Aruduinoとの接続はコンストラクタに指定されているPinに変更。

2016年4月27日水曜日

Arduino UnoでaitendoのOLED(VGM12864-3S)を動かす U8GLIB編

74HC4050を使うとSPIならArduino Unoでもあまり気にせず3.3V系を操れそうなので3.3V駆動のOLEDを動作させてみた。

aitendoのOLED VGM12864-3S 



OLEDのグラフィック表示器としては安いほうだが、1,350円なのでヘタして壊したら泣ける。

I2C/SPI/パラレル接続のどれかを選択して使えるようになってるが、I2CはいろいろややこしいのでSPIでやってみた。

I2Cだと上側の7ピンで制御できるが、SPIだと左側のCSとA0ピンも必要になるのでブレッドボードで実験するためにピンソケットを使って上側からケーブルをさせるようにした。

上側の7ピンは


1 2 3 4 5 6 7
VCC GND RESET SCK SDI BS1 BS2

となっていて、VCC、GNDは電源、SCK、SDIはSPIの信号線で、BS1とBS2で通信方法のI2C/SPI/パラレルを選択する。BS1、BS2をL(GND)に落とすとSPI接続になる。

ブレッドボード図


74HC4050はSPIの信号線のロジックレベルを5V->3.3Vに変換するために使っている。ブレッドボードの電源は74HC4050、OLEDともArduino Unoから3.3V供給している。

A0(青)、CS(白)、RESET(緑)は仕様通りHかLに固定すれば動作するので(←未確認)、実質クロックとデータの2線で動かせる。(I2Cの様にデータラインが双方向ではないので、5V->3.3Vに片方向で変換できれば良い)

<追記:2016.09.05>A0とCSはU8GLIBの指定通りに配線しないと動作しません。</追記>

U8GLIB


いろいろな表示器のコントローラーに対応しているライブラリで、CPUはArduino、AVR、ARMに対応している。

Arduino Uno用のライブラリをインストールするとArduino IDEでexampleが使える様になる。

aitendoのOLED(VGM12864-3S)はコントローラーがSSD1306なのでexampleのスケッチの

//U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9); // SW SPI Com: SCK = 13, MOSI = 11, CS = 10, A0 = 9
//U8GLIB_SSD1306_128X64 u8g(4, 5, 6, 7); // SW SPI Com: SCK = 4, MOSI = 5, CS = 6, A0 = 7 (new white HalTec OLED)
U8GLIB_SSD1306_128X64 u8g(10, 9);  // HW SPI Com: CS = 10, A0 = 9 (Hardware Pins are  SCK = 13 and MOSI = 11)


とコメントアウトされているところの「//」を削除してu8gのコンストラクタを指定すれば動く。

U8gLogoや他のスケッチも試してみたが問題なく動作する(^q^/

思ったこと


5V系->3.3V系の変換には74HC4050は結構便利。

マイコンに限ったことではないが、キャラクタLCDと違ってグラフィックLCDは文字を表示するのも一苦労する。U8GLIBはいろいろと関数が用意されているようなので、使うLCDとMPUに合致すれば便利かもしれない。

ARM用のライブラリにPSoC 5LPもあるようだ。

2016年4月24日日曜日

ロジックICでSPIの5V->3.3Vレベルシフト Nokia LCD5110を動かす

aitendoのNokia LCD5110は、3.3V駆動のLCDで、コントローラーのPCD8544のDataSheetを見ると
VIH | MIN 0.7VDD | MAX VDD
となっていて5Vを入力するとほんとはまずい。(動くことは動くが…)

Rの分圧で5V->3.3Vレベルシフト(片方向)続き」で抵抗による分圧をしてみたが、信号波形があまりよくなかったのでもう少し実験してみた。

Arduinoのスケッチは「LCD5110_Basic」ライブラリのArduino(AVR)/LCD5110_Bitmapを使用。

抵抗分圧



↑120Ωと330Ωの抵抗で分圧
バックライトは基板上に電流制限抵抗が入っているので8PINはVDDに直結してよい。

5V * 330Ω / (120Ω + 330Ω) ≒ 3.67V

少し電圧を高めに設定しているのはArduino(今回はaitendoのびんぼうでいいのを使用)のSPI信号の電圧が5V出ていないから。

ArduinoからのSPI信号

ch1:MOSI ch2:SCK

前回は(と言っても1年以上前)10kΩ:20kΩの分圧でうまく動いてくれたが、今回ブレッドボードで実験したところ10kΩオーダーのRではうまく動作せず、1kΩオーダーでもだめだった。

1.2kΩ:3.3kΩで分圧

MOSI(Data)の方は3.3V~GND程度で出力されているがSCK(Clock)のLがGND付近まで落ちていない。LCD5110の入力インピーダンスが低いのかびんぼうでいいのの出力が弱いのかわからないが。液晶にも何も表示されない。

120Ω:330Ωで分圧

抵抗値を下げるとSCKの波形もきれいになり液晶も無事表示された。


ただ120Ω:330Ωの分圧だと1ピン当たり

5V / (120Ω + 330Ω) ≒ 11.1mA

も抵抗だけで電流を流しているのでかなりもったいない。(一応AVRは1ピンあたり20mAまで流せるが)

またマスター側のVCCによってはHの出力電圧が変動してしまうかもしれない。

5VトレラントのバッファICを使う(74HC4050)


5VトレラントのロジックICを使えばロジックレベルの変換ができるので実験してみた。

5VトレラントとはICを3.3V駆動させても5Vの入力を受け付ける。出力は3.3Vになるので5V->3.3Vにレベルシフトできる。(片方向)

74VHCシリーズはすべて5Vトレラントの様だが、HCシリーズでも74HC4050(6回路入りバッファ)が5Vトレラントなのでこれを使った。

74HC4050ピン接続

ブレッドボード図


SPI信号

ch1:MOSI ch2:SCK

SCKも3.3V~GNDできれいな波形が出力されている。

消費電流をテスタで計測してみると6mA程度だった。これはLCD(バックライト含む)と74HC4540の合計。


まとめ


抵抗分圧によるレベルシフトは手軽だが、条件によっては動作しない場合がある。

74HC4050は値段も安いし6回路入っているので5V->3.3Vのレベルシフトにはなかなか使いやすいと思う。

2015年11月7日土曜日

Aruino Pro Mini 328 3.3VでaitendoのSPIグラフィックLCD(F12864G25412P1701)を動かす(メモ)

このLCDは3.3V仕様なので3.3V駆動のArduino Pro Miniで動かしてみた。

UARTの接続は「Aruino Pro Mini 328 3.3Vを秋月のFT232RL USBシリアル変換モジュールで使う



Arduinoのスケッチはラジオペンチさんの「aitendoの小型グラフィック液晶を動かす」のスケッチそのままで動作した。

(Arduino IDEにU8glibは入れていたような気がします)

ピン接続はaitendoの商品説明にあるように設定した。


電圧測定値 

USB VBUS: 5.06V
LCD VDD: 3.31V

キャラLCDとグラフィックLCDのサイズ感


Arduino Pro Mini のPinout表


2015年3月18日水曜日

Rの分圧で5V->3.3Vレベルシフト(片方向)続き

ユニバーサル基板で組んでみた



画像の通りLCDは表示された

SPIのSCKの波形


赤色が3.3V側、黄色が5V側

ブレッドボードで組んだ時と同じくLoが0Vまで落ちていない

カーソルを使ってMin、Maxを測ると960mV~3.28Vだった

LCDのコントローラー(pcd8544)のDATASHEETを見るとLoの上限は0.3VDDとなっているので
3.3V * 0.3 = 990mV
なのでかなりギリギリだ

余裕がないので誤動作しても文句は言えない

抵抗値を変えてみる

あんまり電流を流さないように100kΩと220kΩで分圧する回路をブレッドボードで作成

100kΩ:220kΩで分圧したSCKの波形


悪化してしまった(^q^;

LCDも表示されない

逆に電流を流すようにして1kΩと2kΩで分圧

1kΩ:2kΩで分圧したSCKの波形


カーソルで測ると0V~3.2Vできれいな矩形波で変換できた(^q^/

理論的なことはわからないけど多少電流を流したほうがうまくいくようだ

Arduinoからの出力電流は
5V / (1kΩ + 2kΩ) = だいたい1.67mA
仕様では推奨で20mAまでなので収まっている
トータルで200mAまでなので、1.67mA * 4 = 6.68mAでこちらも基本的にOK

またはんだ付けしたくなったら1kΩ:2kΩバージョンもユニバーサル基板で組もうと思います

<追記:2015.03.19>
10kΩ:20kΩバージョンはブレッドボードで組んでた時は一晩ほっといたら表示が崩れたが
1kΩ:2kΩバージョンはブレッドボードでも一晩たっても平気だった

ということはこれぐらいのR値が適正なのかもしれない

変換後の波形がなまるということは出力先のLCDの入力の容量成分が影響しているような気がします

他にやりたいことがあるのでこの件は保留