🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

2回答

2902閲覧

LCD(SO1602AWWB-UC-WB-U)を使ってRTC(DS1307)を表示させる

DMR

総合スコア6

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2021/01/30 13:48

編集2021/01/31 06:27

LCD(SO1602AWWB-UC-WB-U)」を持っています。これを使ってRTC(DS1307)とシリアル通信でLCDに表示させる方法が分かりません。

int DS1307_ADDRESS=0x68; int val=0; byte command; void setTime(){ byte hour=(Serial.read()<<4); hour=hour+(Serial.read()&0x0F); byte minute=(Serial.read()<<4); minute=minute+(Serial.read()&0x0F); byte sec=(Serial.read()<<4); sec=sec+(Serial.read()&0x0F); Wire.beginTransmission(DS1307_ADDRESS); Wire.write(val); Wire.write(sec); Wire.write(minute); Wire.write(hour); Wire.endTransmission(); } void setDay(){ byte year=(Serial.read()<<4); year=year+(Serial.read()&0x0F); byte month=(Serial.read()<<4); month=month+(Serial.read()&0x0F); byte day=(Serial.read()<<4); day=day+(Serial.read()&0x0F); byte day_of_week=(Serial.read()&0x0F); Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x03); Wire.write(day_of_week); Wire.write(day); Wire.write(month); Wire.write(year); Wire.endTransmission(); } void printTime(){ Wire.beginTransmission(DS1307_ADDRESS); Wire.write(val); Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS,7); byte r_sec=Wire.read(); byte r_minute=Wire.read(); byte r_hour=Wire.read(); byte r_day_of_week=Wire.read(); byte r_date=Wire.read(); byte r_month=Wire.read(); byte r_year=Wire.read(); Serial.print(r_year,HEX); Serial.print("/"); Serial.print(r_month,HEX); Serial.print("/"); Serial.print(r_date,HEX); Serial.print(" "); Serial.print(r_hour,HEX); Serial.print(":"); Serial.print( r_minute,HEX); Serial.print(":"); Serial.print( r_sec,HEX); Serial.print(" smtwtfs= "); Serial.println(r_day_of_week,HEX); } void setup() { Serial.begin(9600); Wire.begin(); Serial.flush(); } void loop() { if(Serial.available()){ command=Serial.read(); if(command==0x74){ setTime(); } Serial.println(command); if(command==0x64){ setDay(); } } printTime(); delay(2000); } ```#include <Wire.h> #define OLED_ADRS 0x3C //SA0=L(SA0=H の場合は 0x3D) int DisplayON = 0x0F, ClearDisplay = 0x01, ReturnHome = 0x02; void setup() { Wire.begin(); //Wire ライブラリを初期化し、I2C マスタとしてバスに接続 init_oled(); } void loop() { char moji[] = "I2C OLED WHITE12345"; for(int i = 0; i < 20; i++) { writeData(moji[i]); } writeCommand(0x20+0x80); //2 行目の先頭 for(int i = 0; i < 20; i++) { writeData(i+0xB1); } contrast_max(); //輝度を最大に設定 while(1){} } //----main end---- void writeData(byte t_data) { Wire.beginTransmission(OLED_ADRS); Wire.write(0x40); Wire.write(t_data); Wire.endTransmission(); delay(1); } void writeCommand(byte t_command) { Wire.beginTransmission(OLED_ADRS); Wire.write(0x00); Wire.write(t_command); Wire.endTransmission(); delay(10); } void contrast_max(){ writeCommand(0x2a);//RE=1 writeCommand(0x79);//SD=1 writeCommand(0x81);//コントラストセット writeCommand(0xFF);//輝度MAX writeCommand(0x78);//SD を0にもどす writeCommand(0x28); //2C=高文字 28=ノーマル delay(100); } void init_oled() { delay(100); writeCommand(ClearDisplay); // Clear Display delay(20); writeCommand(ReturnHome); // ReturnHome delay(2); writeCommand(DisplayON); // Send Display on command delay(2); writeCommand(ClearDisplay); // Clear Display delay(20); } コード

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

y_waiwai

2021/01/30 13:59

で、しつもんはなんでしょうか
DMR

2021/01/31 05:44

LCDのサンプルプログラムがこれで #include <Wire.h> #define OLED_ADRS 0x3C //SA0=L(SA0=H の場合は 0x3D) int DisplayON = 0x0F, ClearDisplay = 0x01, ReturnHome = 0x02; void setup() { Wire.begin(); //Wire ライブラリを初期化し、I2C マスタとしてバスに接続 init_oled(); } void loop() { char moji[] = "I2C OLED WHITE12345"; for(int i = 0; i < 20; i++) { writeData(moji[i]); } writeCommand(0x20+0x80); //2 行目の先頭 for(int i = 0; i < 20; i++) { writeData(i+0xB1); } contrast_max(); //輝度を最大に設定 while(1){} } //----main end---- void writeData(byte t_data) { Wire.beginTransmission(OLED_ADRS); Wire.write(0x40); Wire.write(t_data); Wire.endTransmission(); delay(1); } void writeCommand(byte t_command) { Wire.beginTransmission(OLED_ADRS); Wire.write(0x00); Wire.write(t_command); Wire.endTransmission(); delay(10); } void contrast_max(){ writeCommand(0x2a);//RE=1 writeCommand(0x79);//SD=1 writeCommand(0x81);//コントラストセット writeCommand(0xFF);//輝度MAX writeCommand(0x78);//SD を0にもどす writeCommand(0x28); //2C=高文字 28=ノーマル delay(100); } void init_oled() { delay(100); writeCommand(ClearDisplay); // Clear Display delay(20); writeCommand(ReturnHome); // ReturnHome delay(2); writeCommand(DisplayON); // Send Display on command delay(2); writeCommand(ClearDisplay); // Clear Display delay(20); } RTCのコードがこちらです。 #include <Wire.h> int DS1307_ADDRESS=0x68; int val=0; byte command; void setTime(){ byte hour=(Serial.read()<<4); hour=hour+(Serial.read()&0x0F); byte minute=(Serial.read()<<4); minute=minute+(Serial.read()&0x0F); byte sec=(Serial.read()<<4); sec=sec+(Serial.read()&0x0F); Wire.beginTransmission(DS1307_ADDRESS); Wire.write(val); Wire.write(sec); Wire.write(minute); Wire.write(hour); Wire.endTransmission(); } void setDay(){ byte year=(Serial.read()<<4); year=year+(Serial.read()&0x0F); byte month=(Serial.read()<<4); month=month+(Serial.read()&0x0F); byte day=(Serial.read()<<4); day=day+(Serial.read()&0x0F); byte day_of_week=(Serial.read()&0x0F); Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x03); Wire.write(day_of_week); Wire.write(day); Wire.write(month); Wire.write(year); Wire.endTransmission(); } void printTime(){ Wire.beginTransmission(DS1307_ADDRESS); Wire.write(val); Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS,7); byte r_sec=Wire.read(); byte r_minute=Wire.read(); byte r_hour=Wire.read(); byte r_day_of_week=Wire.read(); byte r_date=Wire.read(); byte r_month=Wire.read(); byte r_year=Wire.read(); Serial.print(r_year,HEX); Serial.print("/"); Serial.print(r_month,HEX); Serial.print("/"); Serial.print(r_date,HEX); Serial.print(" "); Serial.print(r_hour,HEX); Serial.print(":"); Serial.print( r_minute,HEX); Serial.print(":"); Serial.print( r_sec,HEX); Serial.print(" smtwtfs= "); Serial.println(r_day_of_week,HEX); } void setup() { Serial.begin(9600); Wire.begin(); Serial.flush(); } void loop() { if(Serial.available()){ command=Serial.read(); if(command==0x74){ setTime(); } Serial.println(command); if(command==0x64){ setDay(); } } printTime(); delay(2000); } この2つのコードを使ってLCDに日付と時刻を表示したいです。
y_waiwai

2021/01/31 05:56

聞きたいことがあるなら、質問に追記しましょう 編集できますよ。 コードは、質問を編集し、<code>ボタンを押し、出てくる’’’の枠の中にコードを貼り付けてください
nac_tnk

2021/01/31 11:18

逆に質問になりますけど、秋月LCDのサンプルは問題無く動くのでしょうか? また、RTCのそのスケッチも問題なく動くのでしょうか?
DMR

2021/01/31 11:57

はい。各々単独ではちゃんと動きます。
nac_tnk

2021/02/01 05:36

それならミックスにしても不具合は出なさそうですけど。 (勿論Wire.begin();は1回で) 単純に表示の仕方が判らないのでしょうか? それとも更新間隔とか、作り方の問題でしょうか?
DMR

2021/02/01 05:42

表示の仕方と作り方がわかりません。お願いします。
guest

回答2

0

ベストアンサー

作り方といっても、RTCからの取得間隔はどうするのか?という部分ぐらいだと思いますけど、
(勿論、SWを付けて時刻あわせをする、というものもありますけど)
実際は作る人の考え次第です。
1秒以下の情報は取得出来ませんから、そのあたりをどうするか?

よくある手法?は、RTCのOUT端子から1Hzを出して、その信号を割り込みあたりで受けて、時刻取得→LCD更新です。
0.1秒?毎に情報を取得する人もいるでしょうし、そのあたりは好きに作ればいい事だと思っています。

秋月のサンプルのままでも可能でしょうけど、多少、操作用の関数を作った方が良いでしょうね。

例えば、カーソル位置の関数です。
データシートより、
イメージ説明

コマンドで、0x80+DDRAMのアドレス(カーソル位置)を送ります。
カーソル位置は、上段は0から、下段は0x20から始まります。なので

arduino

1 2void lcd_pos(byte x,byte y){ 3 writeCommand(0x80+x+0x20*y); 4} 5 6

とか、数値を表示する関数

Arduino

1 2void lcd_val(word val,byte keta){//数値を○桁で表示 3 while(keta){ 4 if(keta==5)writeData(val/10000+'0'); 5 else if(keta==4)writeData(val%10000/1000+'0'); 6 else if(keta==3)writeData(val%1000/100+'0'); 7 else if(keta==2)writeData(val%100/10+'0'); 8 else if(keta==1)writeData(val%10+'0'); 9 keta--; 10 } 11}

のような感じです。で、
イメージ説明

のように表示させたいのなら、void printTime()の後半(RTCから取得した後)に

lcd_pos(0,0); writeData('2'); writeData('0'); lcd_val(r_year,2); writeData('/'); lcd_val(r_month,2); writeData('/'); lcd_val(r_date,2); lcd_pos(0,1); lcd_val(r_hour,2); writeData(':'); lcd_val(r_minute,2); writeData(':'); lcd_val(r_sec,2);

を追加すれば、表示されると思います。(取得間隔が2秒おきのようですけど)

※このLCDは所有していませんし、当然、動作確認もしていません。

追記

作った関数の性格からいくと

作って関数の性格からいくと

writeData('2');
writeData('0');
lcd_val(r_year,2);

の部分は

lcd_val(2000+r_year,4);

でも良い筈ですし、使いやすくする関数も自分で色々作った方が良いです。
例えば文字列を表示する関数。

void lcd_str(char *str){ while(*str){ writeData(*str); str++; } }

とか。
この作例の限らず、書いていて不便さを感じたら便利な手法を考えて下さい。

投稿2021/02/01 07:35

編集2021/02/01 07:49
nac_tnk

総合スコア494

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

DMR

2021/02/02 16:14

カーソル位置の関数で void lcd_pos(byte x,byte y){ writeCommand(0x80+x+0x20*y); } 0x80+x+0x20*yこれの+、*はどういう意味になるのですか?
DMR

2021/02/02 16:18

後、ググっていたらこんなのがあったのですが Wire.write(0x08 + 0x04 * 0x01 + 0x02 * 0x00 + 0x01);//カーソルセット Wire.write(0x00 + ( 0x01 * 0x20 ) + 0x80);//カーソル移動
nac_tnk

2021/02/03 00:37

> 0x80+x+0x20*yこれの+、*はどういう意味になるのですか? 単に四則演算です。yは0行目と1行目だけです。 if(y==0)return 0x80+x; else if(y==1) return 0xA0+x; でも良いです。 > Wire.write(0x08 + 0x04 * 0x01 + 0x02 * 0x00 + 0x01);//カーソルセット コマンド表を見てください。0x08が1の「Cursor or Display Shift」です。 カーソルをどのように使うか?というものです。どちらにシフトさせるとか。 > Wire.write(0x00 + ( 0x01 * 0x20 ) + 0x80);//カーソル移動 これは0x80ですから、同種の命令です。ただし、アドレスが0x20ですから、下段の一番左に来る命令です。 私の書いたものだとlcd_pos(0,1);です。
nac_tnk

2021/02/03 00:48

ごめんごめん。何言ってるんだ俺。 > if(y==0)return 0x80+x; > else if(y==1) return 0xA0+x; if(y==0)writeCommand(0x80+x); else if(y==1)writeCommand(0xA0+x); です。 いちいち、 > Wire.write(0x00 + ( 0x01 * 0x20 ) + 0x80);//カーソル移動 のように、訳が分からないことをするのを避けるために lcd_posのように簡単に扱える関数を作る、という事です。
DMR

2021/02/03 14:16

理解できました。また分からないところが出てくると思うのでその時はよろしくお願いします。 有難うございました。
guest

0

RTCとLCDが互いに直接シリアル通信をすることはありません。マイコン等を使って制御して下さい。

投稿2021/01/31 00:01

thkana

総合スコア7703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

DMR

2021/01/31 01:53

はい、当然arduinoも繋ぎます。
thkana

2021/01/31 04:35

'1602 1307 i2c #include' あたりをキーワードにGoogleで検索をかけてみるといくつも作例がヒットします。それくらいは調査済と思いますが、そういうのでは解決しないなにかがあったのでしょうか? (ちなみに、#includeはソースコードを引っ掛けるおまじない...)
DMR

2021/01/31 05:45

LCDのサンプルプログラムがこれで #include <Wire.h> #define OLED_ADRS 0x3C //SA0=L(SA0=H の場合は 0x3D) int DisplayON = 0x0F, ClearDisplay = 0x01, ReturnHome = 0x02; void setup() { Wire.begin(); //Wire ライブラリを初期化し、I2C マスタとしてバスに接続 init_oled(); } void loop() { char moji[] = "I2C OLED WHITE12345"; for(int i = 0; i < 20; i++) { writeData(moji[i]); } writeCommand(0x20+0x80); //2 行目の先頭 for(int i = 0; i < 20; i++) { writeData(i+0xB1); } contrast_max(); //輝度を最大に設定 while(1){} } //----main end---- void writeData(byte t_data) { Wire.beginTransmission(OLED_ADRS); Wire.write(0x40); Wire.write(t_data); Wire.endTransmission(); delay(1); } void writeCommand(byte t_command) { Wire.beginTransmission(OLED_ADRS); Wire.write(0x00); Wire.write(t_command); Wire.endTransmission(); delay(10); } void contrast_max(){ writeCommand(0x2a);//RE=1 writeCommand(0x79);//SD=1 writeCommand(0x81);//コントラストセット writeCommand(0xFF);//輝度MAX writeCommand(0x78);//SD を0にもどす writeCommand(0x28); //2C=高文字 28=ノーマル delay(100); } void init_oled() { delay(100); writeCommand(ClearDisplay); // Clear Display delay(20); writeCommand(ReturnHome); // ReturnHome delay(2); writeCommand(DisplayON); // Send Display on command delay(2); writeCommand(ClearDisplay); // Clear Display delay(20); } RTCのコードがこちらです。 #include <Wire.h> int DS1307_ADDRESS=0x68; int val=0; byte command; void setTime(){ byte hour=(Serial.read()<<4); hour=hour+(Serial.read()&0x0F); byte minute=(Serial.read()<<4); minute=minute+(Serial.read()&0x0F); byte sec=(Serial.read()<<4); sec=sec+(Serial.read()&0x0F); Wire.beginTransmission(DS1307_ADDRESS); Wire.write(val); Wire.write(sec); Wire.write(minute); Wire.write(hour); Wire.endTransmission(); } void setDay(){ byte year=(Serial.read()<<4); year=year+(Serial.read()&0x0F); byte month=(Serial.read()<<4); month=month+(Serial.read()&0x0F); byte day=(Serial.read()<<4); day=day+(Serial.read()&0x0F); byte day_of_week=(Serial.read()&0x0F); Wire.beginTransmission(DS1307_ADDRESS); Wire.write(0x03); Wire.write(day_of_week); Wire.write(day); Wire.write(month); Wire.write(year); Wire.endTransmission(); } void printTime(){ Wire.beginTransmission(DS1307_ADDRESS); Wire.write(val); Wire.endTransmission(); Wire.requestFrom(DS1307_ADDRESS,7); byte r_sec=Wire.read(); byte r_minute=Wire.read(); byte r_hour=Wire.read(); byte r_day_of_week=Wire.read(); byte r_date=Wire.read(); byte r_month=Wire.read(); byte r_year=Wire.read(); Serial.print(r_year,HEX); Serial.print("/"); Serial.print(r_month,HEX); Serial.print("/"); Serial.print(r_date,HEX); Serial.print(" "); Serial.print(r_hour,HEX); Serial.print(":"); Serial.print( r_minute,HEX); Serial.print(":"); Serial.print( r_sec,HEX); Serial.print(" smtwtfs= "); Serial.println(r_day_of_week,HEX); } void setup() { Serial.begin(9600); Wire.begin(); Serial.flush(); } void loop() { if(Serial.available()){ command=Serial.read(); if(command==0x74){ setTime(); } Serial.println(command); if(command==0x64){ setDay(); } } printTime(); delay(2000); } この2つのコードを使ってLCDに日付と時刻を表示したいです。
DMR

2021/01/31 15:05

LCDの種類が違うようでうまくいきません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問