製作実習
人様の製作を真似て勉強することしかできないのでwebで気づいた装置を組み立てます。
少しわかってきたので自分で考えたものもここに書きます。2015.07.10
1 LCDの表示 2015.04.16
2 LCD用負電源 2015.05.12
3 パーツとしてのLCD表示回路 2015.05.17
4 周波数カウンター 2015.07.10
5 気圧計BMP180 2016.01.27
6 実験用3.3V電源LCD 2016.02.19
7 中国製LCD(青地に白抜き) 2016.02.19
8 古いLCD(DEC-32V0 SH4-4038 02) 2016.02.22
9 3色LED表示器(カラーサイコロ)2017.02.09
10 LED3色8個の表示2024.04.21
1 LCDの表示
いくつかのサイトを見せていただきましたが、このページの記事がわかりやすかったのでトレースしてみました。inazakiさんのサイトのようです。
H8・R8Cのボタンを押して、「簡易LCDモニター(R8C)」がそれです。
写真左側のスイッチ基板はUSB-シリアル変換器とターゲット基板の間に入って、MODEの切り替えをしています。ブレッドボードが複数になってもMODEスイッチは1つで済ますもくろみです。
ブレッドボードに接している基板は、電源スイッチのためのものです。白い押しボタンスイッチは珍しくトグルスイッチです。プログラム書き込み時にデバイスとつながらない時がありますが、ターゲットの電源を一時切るとうまうゆくようです。どこかの学習基板では書き込みのリセットを押すときは電源を必ず切るように指示したものがありました。
DIPスイッチは他の実験のもので、今回は関係がありません。
LCD表示器はかなり以前にデジットで購入したもので、品番もわかりません。2行×16文字ですが、秋月のものとはVccとGNDが逆で、1番ピンがGNDになっています。
参考サイトには、ソースファイルとhexファイル(.MOT)がありますが、ソースファイルをHEWでビルドして使っています。
端子の勘違いに気づくまで(LCDのDB番号とR8Cのポート番号が逆になっている)少々時間がかかりましたが、正常に起動しました。
プログラムは、PCから(私はTeraTermを使いましたが)、
(行番号1または2)、(カンマ)、(2桁のカラム番号)、(カンマ)、(文字列)
を送るとLCDに表示するものです。
これからはこの方の lcd.h lcd.c を使わせていただこうと思っています。上記のフォーマットで関数を呼び出すと表示されるようになっています。
なお、プログラム時とUART通信時ではデバイスのポート番号が違うので、14番ピンと15番ピンを1.5kの抵抗でつないでいます。
書き込みには、cp2102コンバーターを使いました。これは3.3Vで動いているようで、FDT4.09で書こうとするとつながらないケースが多く出ました。ターゲットはLCDが5Vでないと動かないし、書き込みは3.3Vでないとうまくいかない。当方の電源には5Vと3.3Vがスイッチ切り替えになっているので煩雑に切り替えても手間はないので問題ではないのですが。FT232RLで電圧切替スイッチを付けたコンバーターの方がよいのかもしれません。
プログラム
2 LCD用負電源
電源の主流が3.3Vになり、温度センサーの電源電圧がmax3.7Vのものがありました。ところが手持ちのLCDは3.3Vでは表示できません。以前にも経験があるのですが、負電源を作って回路は3.3Vで、液晶の電圧はそれより高くすることを考えます。
GND−10kVR−マイナス電源
と接続してVRの中点からV0に接続します。
計画通り作ったところ無負荷で3.0V出ましたから「よし」としたのですが、負荷をかけると1V未満になります。そこで、インバーターをパラにしたのですがまだまだ電圧不足です。コンデンサに10μFを付け加えて期待の電圧になりました。-2.5Vが得られてLCDが3.3Vで表示できました。
端切の基板にカッターナイフでパターンを作りICはのりづけしています。
3 パーツとしてのLCD表示回路
上記のLCD回路の作者の方が書いておられましたが、R8C/M12Aは端子の数が少ないのが難点です。LCD表示のために6本の端子を必要とします。そこで、R8C/M12Aを1個追加しておけばUARTの1本の信号線でLCDに表示できます。
実験で使いやすいようにベニヤ板の上にまとめました。上に見える3本の線をブレッドボードにつなげば使えます。
信号線をマイコンのTXDにつないでキャラクタを送ることになります。
「!」で消去、
行番号(1,2) カンマ カラム番号(01〜16) 文字列 で表示
となります。
プログラムはブレッドボードで作り、ソケットで実装しているので reset MODE は実装していません(手抜きです)。
3.3Vで使うようにLCD用の負電源を付けました。上の実験ではインバータICを使いましたが、今回はマイコンに余裕があるのでポートをon,offして矩形波を作り、それを使っています。
タイマー割り込みで作るのが正当ですが、不勉強だったので、入力待ちループにポート反転命令を書いて、約8kHzの信号を取り出しています。
とりあえず基板にカッターで溝を入れて実験しました。使ったショットキバリアダイオードが1608サイズであったので、カソードマークを読むこと、ハンダ付けすることに苦労しました。
実験中でハンダが汚いのですがご辛抱下さい。(作っても時間が経てば端子の位置も忘れるのでここに置いています)
LCD組み込みの装置を作るとき、開発段階で重宝すると思います。プログラム
負電源整流回路の第2作です。
25kHz程度を発振するとコンデンサは0.1μで実用になるようです。
上のものは横幅が14mmでしたが、右は11mmです。
銅箔の全面にハンダを伸ばしてからハンダ付けしました。ハンダが素直に広がってくれます。
第2作 2017.04.27
バックライト付きのLCDが手元にあったので3.3V回路にUART_RXD1本だけでドライブするLCDモジュールを考えました。
あわよくば5VのLCDを3.3Vでドライブできないかと思いましたが、見事期待はずれでした。5VのR8C/M12Aは3.3Vでドライブできません。バックライトのLEDを諦めれば、Voのマイナス電源を用意して3.3V駆動のLCDモジュールができます。結果的に、LEDバックライトなし、3.3V駆動のLCDとしました。
3.3VでIOの少ないデバイスで使うのに便利だと思います。LED照明を有効にするには、LED回路だけを5Vに変更するか、全体を5Vシステムにしてレベルコンバーターを入れるかのどちらかになります。
前回のものよりコンパクトに仕上げました。回路は基本的には変わっていません。入力端子として 電源端子、RXD+GND端子 を用意しています。LCDのコントラスト用電源Voは、負電源が-2.77V出ていて、10kの抵抗をつけると偶然良好なコントラストになりましたのでそのままにしています。可変抵抗は付けていません。
プログラムd04/lcd_rxd01.zip
(2017.05.10追記) ESP8266で実用性テストをしてみました。
@ esp8266のuart通信速度を9600bpsにしました。R8C/M12Aが115200bpsで動くといいのですが試しでは動きませんでした。中間の速度も考えられますが通常は9600で使っていますのでそれに従いました。
A R8C/M12Aのソフトウエアの速度が遅いので、連続した表示命令を出すと正しく伝わりません。表示命令の間に 50ms のdelayを入れると正しく表示されました。
4 周波数カウンター 2015.07.10
カウンターの勉強を兼ねてWEBで周波数カウンターを調べるとこのサイトにたどり着きました。
プログラムを見せていただくと、タイマーカウンターRJ2を使って入力をカウントしています。このタイマーはffffhからのダウンカウンターなのですが ~カウント値(チルダ-カウントレジスタ)でアップカウントと同じ値を得ています。16ビットカウンターですからそれを超える分はアンダーフローフラグをチェクしてアンダーフローの回数を調べて総カウント値を得ています。
カウント時間は水晶発振子でシステムクロックを安定させ、RC2カウンタで0.1秒を作って計測しています。
そのまま真似ようかと思ったのですが、実験中のブレッドボードにはRTCがついていて、1Hzの矩形波を出していますからその1秒でカウントすることにしました。
測定値は文字列の形にしてライター経由でPCに表示するのが最も簡単です。さらに、UART利用のLCD端末も作ってあるので文字列の最初に"1,01,"を書いておくとLCDの1行目第1カラムから書き出してくれるので便利です。
1秒が正確だからシステムクロックは内蔵発振器で良いと考えました。紆余曲折はありましたが、RTCのINT3割り込みでカウントすることができました。
驚いたのは、20MHzのシステムクロックで16MHzをカウントしたことです。AVRで作ったものは1/2がカウントできなかったと思います。
実験回路を次にあげておきます。
連続して表示すると測定値がバラつきます。16MHzでは40カウントほどのばらつきが出ます。限界を過ぎているかと思い、4MHzをカウントするとやはり10カウントほどバラつきます。AVRでは1カウントしかずれませんでした。いろいろ考えるうちにシステムクロックを疑い、20MHzの水晶を探して水晶発振に変えました。
その結果16MHzで概ね10カウントのバラ付きで収まりました。ただ、7〜9回に1回位の割合で20カウントくらい離れた結果が出ます。この理由はわかりません。また、20カウント離れていてもその率は 10-5くらいですからしかたがないのかもしれません。少なくとも私にはそれだけの精度を必要としません。
計測ルーチンをいろいろと変えてみましたが、最終的にはもっとも簡単なルーチンとなりました。
//( main で)
/* --- カウンタ初期設定 ------ */
msttrj = 0; //TRJ2 0=activ 1=standby
//p46sel0 = 1; //p4_6 → input TRJIO
//p46sel1 = 0; //
//p46sel2 = 1; //
p17sel0 = 0; //p1_7 → input TRJIO
p17sel1 = 1; // --
tmod0_trjmr = 0; //ivent count mode
tmod1_trjmr = 1; //--
tmod2_trjmr = 0; //--
tstop_trjcr = 1; //counter stop
tstop_trjcr = 0; //counter stop clear
tundf_trjcr = 0; //under flag 0=non
trjif_trjir = 0; //0=Without request flag 1=request flag, with well
trjie_trjir = 1; // interupt on
ilvlb = 0x03; // interupt level=2 0x01=lebel1 0x00=off
EI(); //割り込み許可
tstart_trjcr = 1; //カウント開始(途中で止めない)
while(1){
if(flag==1){//計測終了
flag=0;
//(計測値計算および表示)
}//if
}//while
#pragma interrupt intINT3(vect=26)/* ---- INT3 割り込み処理 1秒毎に-------- */
void intINT3( void ){
fl=(long)~trj; //計数値を読んで
trj=0xffff; //初期値に戻し
flag=1; //フラグを立てる
}
#pragma interrupt intRJ(vect=22)/* -----TRJ割り込み カウンターアンダーフローで --- */
void intRJ(void){
trjif_trjir = 0; //割り込みフラグを倒す
g++; //アンダーフローの回数をインクリメント
}
1秒毎にカウンタ読み取り、カウンタリセットをして結果を表示します。カウンタのカウントとアンダーフローの回数はすべて割り込み処理ですることになります。
基板に組み替えて周波数カウンタを作るか?−−−思案中です。計測値のばらつきとAVRですでに2台あるためです。タイマーRJ2の勉強にはなりました。 プログラム(.cファイルとインクルードファイルを繋いであります)
2015.07.12
ここのサイトのカウンタを元に研究してきましたが、本来の回路ではどのような値になるのか試してみました。ただ、表示ルーチンはハードの違いで異なっています。
オリジナルでは水晶発振を時間のもとにしています。精密な水晶はないので、通常の20MHzの水晶を使いました。測定時間は0.1秒ですから測定値は10Hz単位になります。
私の方法では15,999,650Hz付近になるものが、15,993,500Hz付近になりました。水晶の精度が足りないの
か10-4程度の誤差があるように思います。
5 気圧計BMP180 2016.01.27
amazonで¥285で購入した中国発の気圧センサーBMP180モジュールはaduinoで動作を試しましたがR8C/M12Aで液晶表示で作ろうとしました。
調べながら作っているときはわかっているつもりですが、しばらく時間が立てばどこをそうすればよいのかまったく忘れています。ここでは思い出しながら、次に自分が読んでわかるような記録をしたいと思っています。
気圧センサーBMP180、リアルタイムクロックDS3231モジュール、2行*16字液晶で構成します。
まず、液晶表示の準備をします。接続は、
11番ピン P3_3 -- R/S 茶
12 P4_5 -- E 黄
17 P1_3 -- DB4 緑
18 P1_2 -- DB5 青
19 P1_1 -- DB6 灰
20 P1_0 -- DB7 白
です。
インクルードファイルは所定の場所において共用するのが本来ですが、変更を加えると以前のファイルがわからなくなりますのでメインファイルと同じ場所にコピーしておくことにしました。インクルードファイル置き場から lcdとi2c_uartの.h、.cをコピーしました。
(追記)今までいくつかのスレーブの読み書きができた自作のI2Cルーチンではこのセンサーの読み出しができませんでした。理由は不明ですが使えないのでこの計画は終了します。
Arduinoでは読み出せたので、Arduinoで完成させました。
6 実験用3.3V電源LCD 2016.02.19
最近のI2Cインターフェイスをもつモジュールは電源電圧が3.3Vで、5Vでは使えないものが多くなったように思います。そのため3.3Vで使えるLCDが欲しくなります。
実験用に負電源を内蔵して、3.3Vで使えるLCDを作りました。
R8C/M12Aを使ったものでは負電源用の矩形波をMCで作ることができるのですが、今回はパーツとしての3.3VLCDですから74HC04で矩形波を作り、整流して負電源を得ています。
74HC04はssopのものが手元にありましたので小さな基板に作り、LCD裏面に両面テープで貼り付けています。
LCDには中国製の安いものを使いました。バックライトのLEDは内蔵の100Ωではなく47Ωを使っています。
負電源回路は以前に作ったこれと同様ですが、発振回路のCとRは手持ちの関係でC=680pF、R=4.7k としています。整流回路のCは0.1μ×2です。約120kHzの方形波で、整流後の負電圧はLCDの負荷をかけて2.3V程度となっています。
これで3.3Vブレッドボードの試作実験が楽になります。
7 中国製LCD(青地に白抜き) 2016.02.19
内容はこちらの下の方を見てください。
8 古いLCD(DEC-32V0 SH4-4038 02) 2016.02.22
ジャンク箱から古いLCDが出てきました。裏面に DEC-32V0 SH4-4038 02 と書かれています。webで調べると販売のページが多くありますが、説明や内容を書いたページはなかなか見つかりません。
探しているとこのサイトに回路図があることがわかりました。
これによるとピン機能は次のようです。
1 GND 2 Vcc 3 Vo(gnd) 4 D7 5 D6 6 D5 7 D4 8 RS 9 E 10 NC
これを信用して、上記の「 1 LCDの表示」の回路とプログラムでテストしたところ正常に表示されました。
ただ、この液晶は1行16文字ではなく、1行の内前半分8文字は1行目扱いで、後半の8文字は2行目の命令で書かれます。
多分古いプリンターから取り出したものと思いますが、そこでは1行に2つの情報が入っていたものと思われます。
液晶のドライバーは統一されているようで、助かります。ほとんどが日立とコンパチになっているのですね。このテストをすることにしたのもドライバーICに HD44780A00 とあったからです。
(2016.03.02追記) chanさんの解説によると日立のドライバICはこの表示形式になっているようです。現在使われている2行以上のものや16字以上のものは後の拡張機能によるものと理解しました。
(2016.03.09追記) VoをGNDに直結すると文字が黒くなりすぎるので、20k-VRの中点に繋ぎコントロールできるようにしました。
9 3色LED表示器(カラーサイコロ)2016.02.09
しばらくR8C/M12AをさわってなかったこととPCシステムを変更したことから、ウオーミングアップを兼ねて作ることにしました。AVRではtiny2313で過去に作ったことがあります。「嫁入り」に使うかもしれないので値上げのされた2313を避けてR8C/M12Aにしたものです。
LEDは秋月で昔にあった部品取り基板のものを使っています。表面実装のLEDチップをピンセットに挟んで持ち上げるようにしながらガスコンロで裏側からあぶるとうまく取れました。
リセットボタンを押すとメニューボタンが有効になり、メニューボタンを押すごとにメニュー番号が変わるとともにLEDの色が変わります。メニュー番号1番から 赤、緑、黄(1+2)、青、マゼンタ(1+4)、シアン(2+4)、白(1+2+4)、消灯(0) となります。
1番の赤メニューは、スタートボタンで6色(RGBCMY)が高速で変わり白色に見えます。ストップボタンでいずれかの色で止まります。赤1、緑2、黄3、青4、マゼンタ5、シアン6 と見立ててサイコロの代わりに使えます。混合で白色になることもわかります。
2番の緑メニューはスタートボタンで 赤、緑、青 を1秒間隔で点灯します。この3色のLEDであることを示します。
3番の黄メニューは 0から7に相当する 消灯、赤、緑、黄、青、マゼンタ、シアン、白 を1秒間隔で点灯します。
4番の青メニューは赤PWM点灯としました。
5番のマゼンタメニューはシアン(緑+青)のPWM点灯としました。明るい色になります。
6番のシアンメニューは白を除く全色のランダム点灯でPWMとしています。rand()関数を使いました。
LEDチップは裏側から0.2mmのUEWをはんだ付けして、強度を得るために台紙にエポキシ接着剤で貼り付けています。
タクトスイッチはアマゾンで購入した中国製です。2本足で小さいので良いのですが動作が固くて指が痛くなります。弱ければ嬉しいのですが残念です。
抵抗は4k7と470だけ1608のチップ型を持っていますのでそれを使いました。
久しぶりのことで「忘れ」が多く、やや困りました。(webにいろいろ書いておいて自分が助かっています)
/***********************************************************************/
/* */
/* FILE :led3.c 3色Ledの点滅 含むPWM */
/* DATE :Wed, Feb 08, 2017- SAT, APR 01,2017 */
/* DESCRIPTION :main program file. */
/* CPU GROUP :M12A */
/* port */
/* led R p3_3 pin11 */
/* led G p3_4 10 */
/* led B p3_5 9 */
/* sw start p1_0 pin20 */
/* sw menu/stop p1_1 pin19 */
/* */
/* */
/* */
/* This file is generated by Renesas Project Generator (Ver.4.19). */
/* NOTE:THIS IS A TYPICAL EXAMPLE. */
/***********************************************************************/
#include "sfr_r8m12a.h"
void main(void);
void delay(volatile unsigned int);
void led(int);
void main(void)
{
unsigned int i,ii,j,k;
unsigned char d[]={0,0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,
23,26,30,33,36,40,43,46,50,55,60,65,70,75,80,85,90,95,
100,100,100,
95,90,85,80,75,70,65,60,55,50,46,43,40,36,33,30,26,23,
20,18,16,14,12,10,9,8,7,6,5,4,3,2,1,0,0}; // n=73
// System clock Int 20MHz
prc0=1; //Protect off
hocoe=1;
for(i=0;i<1000;i++){}
hscksel=1;
scksel=1;
prc0=0; //Protect on
// set port
pd1=0b00000000; //p1_0-7 input
pd3=0b00111000; //p3_3--3_5 output
drr3=0b00111000; //p3_3,4,5 high-current
// get menu number *************************************
i=1;
led(i);
while(p1_0==1){
if(p1_1==0){i++; if(i==8) i=0; led(i); delay(500);}// menu button
}
// menu_n==1 led=RED color dice only 6 colors **********
if(i==1){
while(1){
i++; if(i==7) i=1;
led(i); ;delay(5);
if(p1_1==0){delay(200); while(p1_0==1){};}
}
}
// menu_n==2 led=GREEN RGB ********************************************
if(i==2){
while(1){
led(1); delay(1000);
led(2); delay(1000);
led(4); delay(1000);
}
}
// menu_n==3 led=YELLOW bkRGYBMCW ******************************
if(i==3){
i=0;
while(1){
led(i); delay(1000); // led: 1=R 2=G 3=Y 4=B 5=M 6=C 7=W
i++; if(i==8) i=0;
}
}
// menu_n==4 led=BLUE red PWM ******************************
if(i==4){
i=0;
while(1){
for(ii=0;ii<73;ii++){
for(j=0 ; j<100 ; j++){
for(k=0; k<300; k++){
if(k<d[ii]){ led(1);} else { led(0);} // led: 1=R 2=G 3=Y 4=B 5=M 6=C 7=W
}
}
}
}
}
// menu_n==5 led=M G+B PWM ******************************
if(i==5){
i=0;
while(1){
for(ii=0;ii<73;ii++){
for(j=0 ; j<100 ; j++){
for(k=0; k<100; k++){
if(k<d[ii]){ led(6);} else { led(0);} // led: 1=R 2=G 3=Y 4=B 5=M 6=C 7=W
}
//delay(1);
}
}
}
}
// menu_n==6 led=C rand() PWM ******************************
if(i==6){
int r;
i=0;
while(1){
r=(rand() % 6)+1;
for(ii=0;ii<73;ii++){
for(j=0 ; j<100 ; j++){
for(k=0; k<100; k++){
if(k<d[ii]){led(r);} else {led(0);} // led: 1=R 2=G 3=Y 4=B 5=M 6=C 7=W
}
}
}
}
delay(300);
}
}
/* ********************* end of main ************************ */
//--------------- delay 1 ms -----------------------------------------------
void delay(volatile unsigned int ii){
volatile unsigned int i;
while(ii>0){
for(i=1;i<923;i++);// 実測値
ii--;
}
}
//---------------- led on -----------------------------------
void led(int c){
p3_3=0; p3_4=0; p3_5=0;
switch (c) {
case 0: p3_3=0; p3_4=0; p3_5=0; break;
case 1: p3_3=1; p3_4=0; p3_5=0; break;
case 2: p3_3=0; p3_4=1; p3_5=0; break;
case 3: p3_3=1; p3_4=1; p3_5=0; break;
case 4: p3_3=0; p3_4=0; p3_5=1; break;
case 5: p3_3=1; p3_4=0; p3_5=1; break;
case 6: p3_3=0; p3_4=1; p3_5=1; break;
case 7: p3_3=1; p3_4=1; p3_5=1; break;
default: p3_3=1; p3_4=1; p3_5=1;
}
}
//***************** end of file
10 LED3色8個の表示 2024.04.21
以前に書いた記事を思い出し、Lチカの遊びをしました。RGB3色のLEDを8個並べていろいろな点灯をしようと考えました。
ポートp1_0〜p1_7にRGB共通のカソードをつなぎ、8個のR端子を繋いだものをp3_3に、Gをp3_4に、Bを3_7に繋いでいます。最初はp3_5に繋いでいたのですがトラブルがあって変更したままになっています。
p1ポートで発光するLEDを指定し、同時にp3ポートでRGBを決めています。
トランジスタがついていますがトラブルがあって接続はしていません。p3ポートHでp1ポートLのとき発光します。メニュースイッチの押した回数で点灯の種類を決める予定ですがプログラムは途中です。
書きかけのプログラムをここに置きます。
工事中
1 LCDの表示 2016.01.27