mbed を使ったロボット作成 第3回

【LCDに何か出してみる】
はじめに
皆さんが接している殆どのデジタル機器には、ユーザに何かを使てるインターフェースが提供されています。
簡単なものだとLEDです。LEDの点灯している色や点滅している感覚なので、そのデバイスが検知している状態をユーザーに伝えています。
また、スマホなどのハイスペックな機器では、グラフィカルな表示で画面があったり、タッチ操作により、機器の制御を行うことができます。
現在作成しているロボットでは、LEDの点滅くらいしかしていないので、何か表示を試みようと色々探してみたところ、16文字×2行に対応したLCDモジュールがあったので、これを制御してみようと思います。
LCDモジュールについて
今回使用するLCDモジュールはデータ転送が8ビットと4ビットのいずれかを選択できます。マイコン側の空きポートの関係上、4ビットのデータ転送方式を選択しました。
また、可変抵抗を接続することで、コントラストを制御することができます。
LCDモジュールの詳細は以下のとおり。
| 製品名 | 16文字×2行 超ハイコントラスト大文字LCDモジュール |
| メーカー | Sunlike Display Tech. Corp. |
| 型番 | SC1602BS*B(LCDバックライト無) |
| 概要 | 1. 5×7ドット+カーソル表示2. 液晶コントローラ内蔵 3. 5V単一電源(艇消費電流) 4. 1/16デューティサイクル |
| 値段 | 500円(秋月電子通商調べ) |
電力に必要な5V電源とGNDは、マイコンの電圧仕様と同じなのでそこから盗み取って接続します、Vo(コントラスト調整電圧)は電源から可変抵抗(10KΩ)を介して接続します。
R/W信号はWrite固定の為、GNDへ接続。RS(Register Select)及びE(Enable Signal),Data0~Data3をマイコンのポートに接続します。

mbedとの接続は以下のとおり。

ソフトウェアについて
開発環境は、「mbedを使ったロボット作成 第1回」でご紹介した「ARMのオンラインコンパイル環境」を使って作成していきます。
LCDデバイス制御用のドライバクラスを作成し、デバイスに特化した制御はこのクラスに吸収させます。利用する側からはドライバクラスのprintf等の出力機能だけで表示制御できた方が便利なので、Streamクラスを継承させたクラスとさせます。
TextPanel.h
#ifndef _TEXTPANEL_H_
#define _TEXTPANEL_H_
#include "mbed.h"
/*
* Text LCD Panel (SC1602BS*B) Access Driver
*/
class TextPanel : public Stream {
public:
TextPanel(PinName regsel ,PinName enable,PinName data0 ,PinName data1 ,PinName data2 ,PinName data3 );
void clearScreen();
void positionSet(int column, int row);
protected:
DigitalOut _regsel, _enable;
BusOut _data;
int _column;
int _row;
/* Stream implementation functions */
virtual int _putc(int value);
virtual int _getc();
void byteWrite( int value );
void commandWrite( int command );
void dataWrite( int data );
int addressConvert(int column, int row);
void charSend(int column, int row, int c);
};
#endif /* _TEXTPANEL_H_ */
TextPanel.cpp
#include "TextPanel.h"
#include "mbed.h"
/* define */
#define TEXT_LCD_ROW_MAX 2 /* TEXT LCD ROW MAX */
#define TEXT_LCD_COL_MAX 16 /* TEXT LCD COL MAX */
#define REG_SEL_HI 1 /* Register Select High */
#define REG_SEL_LO 0 /* Register Select Low */
#define ENABLE_SIG_HI 1 /* Enable Signal High */
#define ENABLE_SIG_LO 0 /* Enable Signal Low */
/*******************************************/
/* Constructer */
/* param regsel Register Select信号ポート */
/* param enable Enable 信号ポート */
/* param data0-3 :データ信号ポート */
/*******************************************/
TextPanel::TextPanel(PinName regsel , PinName enable , PinName data0 , PinName data1 , PinName data2 ,PinName data3 ):
_regsel(regsel),_enable( enable ),_data( data0, data1, data2, data3 ){
int count = 0;
/* command mode set */
_enable = ENABLE_SIG_HI;
_regsel = REG_SEL_LO;
/* Wait */
wait( 0.016 ); /* 16msec wait for powered up */
/* 10msec */
/* init seq:send 0x3 3times(4bit interface) */
for( count = 0 ; count < 3 ; count++ ){
byteWrite( 0x3 );
wait( 0.00164 ); /* 1.64ms wait */
}
byteWrite( 0x2 ); /* 4-bit mode */
wait( 0.000040f ); /* 40usec wait */
commandWrite( 0x28 ); /* Function Set DL:0(4bit) N:1(2Line) F:5*7dot */
commandWrite( 0x0C ); /* Disable ON/OFF Control */
commandWrite( 0x06 ); /* Entry Mode Set Increment */
clearScreen();
}
/**********************************/
/* スクリーンをクリアする */
/* param:無し */
/* return:無し */
/**********************************/
void TextPanel::clearScreen(){
commandWrite( 0x01 ); /* Clear Display */
wait( 0.00164 );
}
/************************************/
/* デバイスにデータを転送する */
/* param:value 転送するデータ(byte) */
/* return:無し */
/************************************/
void TextPanel::byteWrite( int value ) {
/* Uppwer 4bit Send */
_data = value >> 4;
wait(0.000040f); /* 40us wait */
_enable = ENABLE_SIG_LO;
wait(0.000040f); /* 40us wait */
_enable = ENABLE_SIG_HI;
/* Lower 4bit Send */
_data = value >> 0;
wait(0.000040f); /* 40us wait */
_enable = ENABLE_SIG_LO;
wait(0.000040f); /* 40us wait */
_enable = ENABLE_SIG_HI;
}
/**********************************/
/* コマンドデータ転送処理 */
/* param:command 転送するコマンド */
/* return:無し */
/**********************************/
void TextPanel::commandWrite( int command ) {
_regsel = REG_SEL_LO;
byteWrite( command );
}
/**********************************/
/* データ転送処理 */
/* param:data 転送するデータ */
/* return:無し */
/**********************************/
void TextPanel::dataWrite( int data ){
_regsel = REG_SEL_HI;
byteWrite( data );
}
/**********************************/
/* 行・列情報 コマンド変換 */
/* param:column 出力先:列位置 */
/* param:row 出力先:行位置 */
/* return:転送コマンド */
/**********************************/
int TextPanel::addressConvert(int column, int row) {
return 0x80 + (row * 0x40) + column;
}
/**********************************/
/* 文字データの転送を行う */
/* param:column 出力先:列位置 */
/* param:row 出力先:行位置 */
/* param:c 送信する文字コード*/
/* return:無し */
/**********************************/
void TextPanel::charSend(int column, int row, int c) {
int a = addressConvert( column, row ); /* 表示位置計算コマンドの生成 */
commandWrite( a ); /* 出力先転送 */
dataWrite( c ); /* 表示データ転送 */
}
/**********************************/
/* 1文字分のデータ転送を行う */
/* param:value 送信する文字コード */
/* return:送信した文字コード */
/**********************************/
int TextPanel::_putc(int value) {
/* 改行コード? */
if (value == '\n') {
_column = 0;
_row++;
/* 最終行の場合 */
if (_row >= TEXT_LCD_ROW_MAX ) {
_row = 0;
}
/* 改行コード以外 */
} else {
/* 1文字分データ転送 */
charSend(_column, _row, value);
_column++;
/* 行端に達した場合 */
if (_column >= TEXT_LCD_COL_MAX ) {
_column = 0;
_row++;
/* 最終行の場合 */
if (_row >= TEXT_LCD_ROW_MAX ) {
_row = 0;
}
}
}
return value;
}
/**********************************/
/* 入力文字の取得は行わない */
/* param 無し */
/* return -1(常に) */
/**********************************/
int TextPanel::_getc() {
return -1;
}
/**********************************/
/* 出力位置を変更する */
/* param column 出力位置 列 */
/* param row 出力位置 行 */
/* return 無し */
/**********************************/
void TextPanel::positionSet(int column, int row) {
_column = column;
_row = row;
}
main.cpp
#include "mbed.h"
#include "TextPanel.h"
#if 1
TextPanel lcd(D11, PC_9, D12, D13, D14, D15 ); // rs, e, d4-d7
#else
TextLCD lcd(PA_7, PC_9, PA_6, PA_5, PB_9, PB_8 ); // rs, e, d4-d7
#endif
DigitalOut myled(LED2);
int main() {
wait(0.001);
lcd.clearScreen(); wait(0.001);
lcd.positionSet(0, 0);
lcd.printf( "TESTtestTest\n");
int iCounter = 0;
while(1) {
lcd.positionSet(0, 1);
lcd.printf( "%d",iCounter);
iCounter++;
wait(1.0);
myled = 1; // LED is ON
wait(1.0); // 200 ms
myled = 0; // LED is OFF
wait(1.0); // 1 sec
}
}
実行結果
簡単なプログラムによるポート制御で
マイコンからLCDの表示制御ができることが確認できました。
次回はUSBポートについて制御してみたいと思います。
【参考】
mbedを使ったロボット作成 第1回
mbedを使ったロボット作成 第2回
ホームページ http://www.ois-yokohama.co.jp
facebook https://www.facebook.com/orientalinformationservice/
1 thoughts on “mbed を使ったロボット作成 第3回”
この投稿はコメントできません。