DIPマイコンLPC1114FNでmbed入門 Ledマトリックス ~ その6 環境センサ~
DIPマイコンLPC1114FNでmbed入門
Ledマトリックスで遊びましょう ~その6 環境センサのデータを2枚でスクロール~
mbed LPC1114FN(以後、1114FN)は安価に購入できて、mbedクラウド開発環境を使ってプログラムを開発することができるマイコンです。1114FNを使って、8×8ドット=64個のLEDを使ったLEDマトリックスに文字を表示します。
LEDマトリックスユニットを2枚に増やし、数字の0~9を右から左へスクロールし、流れるように表示することはできましたか。
今回は、I2C気圧・気温・湿度センサBME280(以後、BME280)を搭載し、気圧・気温・湿度をスクロール表示しましょう。
注)
mbed LPC1114FNは発売からずいぶん経過しており、
Arm社が提供する「Mbed OS」および「Mbedプラットフォーム」は、2026年7月をもって完全にサポートを終了します。期間終了後はウェブサイトがアーカイブされ、オンラインでのプロジェクトビルドやコンパイルは一切できなくなります。回路図やプログラムは参考資料として公表します。
○回路図
BME280はI2Cバス規格のセンサなので、SCLとSDAの2本だけで、1114FNと接続することができます。I2Cバスはどこでもいいので、10kΩ程度の抵抗でプルアップするのを忘れないようにしましょう。後は回路図通りに電源接続とGND接続を行います。
BME280ユニット:ストロベリーリナックスにて購入
○ハードウェアの完成
BME280を組み込んだLEDマトリックスボードが完成しました。
単3乾電池4本で動作可能です。
ストロベリーリナックスにて購入したI2C気圧・気温・湿度センサBME280です。このタイプはDIN8ピンと配列が同じタイプです。
○プログラミング
■BME80イニシャライズ
BME280を使用するための関数は、mbedサイトにて公開されているものを使用しています。PublishされているBME280のライブラリごと取り込んでください。
#include "mbed.h"
#include "BME280.h" //BME280のヘッダファイル
DigitalOut led(dp28);
BME280 sensor1(dp5,dp27,0x76 << 1);//使用宣言
■BME280データ取り込み関数
次の関数によりBME280より気圧・気温・湿度データを取り込みます。
BME280により取り込む気圧は現在の標高の気圧です。通常、天気予報どで使われている気圧は海面0メートルの気圧で表現されています。よって、補正式により補正する必要があります。気温も使う本格的な補正式もありますが、今回は次に示す簡易補正式を使っています。
気圧の標高簡易補正式:標高/7
プログラム中の700は筆者の住居の標高です。お住まいの標高に合わせて書き換えてください。
void get_sensor1(void){
t1=sensor1.getTemperature();// 気温
if(t1 > 85.0){ // 気温補正
t1=t1-409.0-1;
}
h1=sensor1.getHumidity(); // 湿度
pp1=sensor1.getPressure(); // 気圧
pp1=pp1+int(700/9);// 簡易標高補正 ここの700をお住まいの標高に書き換える。
}
■BME280取得データの加工
BME280より取得したデータをLEDマトリックスに表示できるように加工します。各データはlongに変換します。気温は10倍することで、小数点以下を含んだデータを整数値に変換します。その後に各桁毎に分解し、配列に代入します。
get_sensor1();
hpascal=long(pp1); // 気圧long変換
ttemp=long(t1*10); // 温度整数値変換
sitemp=long(h1); //湿度long変換
//気圧4桁をhpketa[0]~hpketa[3]に取り込む
hpketa[0]=int(hpascal/1000);hpascal=hpascal-hpketa[0]*1000;
hpketa[1]=int(hpascal/100); hpascal=hpascal-hpketa[1]*100;
hpketa[2]=int(hpascal/10); hpascal=hpascal-hpketa[2]*10;
hpketa[3]=hpascal;
//温度3桁をtpketa[0]~tpketa[2]に取り込む
tpketa[0]=int(ttemp/100);ttemp=ttemp-tpketa[0]*100;// jyuu noketa
tpketa[1]=int(ttemp/10);ttemp=ttemp-tpketa[1]*10;// ichi no keta
tpketa[2]=int(ttemp); // shousuutenika no keta
//湿度3桁をsiketa[0]~siketa[2]に取り込む
siketa[0]=int(sitemp/100);sitemp=sitemp-siketa[0]*100;
siketa[1]=int(sitemp/10);sitemp=sitemp-siketa[1]*10;
siketa[2]=int(sitemp);
■桁データの変換
桁毎に分解した配列データを数字フォントに対応させ、表示用配列load_image[ ]に順次格納します。
■■気圧データ
気圧3桁の処理部です。hpketa[ ]に入っている数値とマッチした数字フォントをload_image[ ]に入れます。
for(i=3;i<=6;i++){// kiatu 4keta suuji [3 ~ 6]
for(j=0;j<=9;j++){
if(hpketa[i-3] == j){
load_image[i]=moji_font[j];
}
}
}
■■気温データ
気温は、(+)(-)と小数点以下一桁の表示があるので、順次処理します。
if(t1 >=0){//(+)の場合
load_image[9]=moji_font[15];//+
}
else { //(-)の場合
load_image[9]=moji_font[16];// -
}
//整数部の処理
for(i=0;i<=1;i++){// kion seisuuketa
for(j=0;j<=9;j++){
if(tpketa[i] == j){
load_image[i+10]=moji_font[j];
}
}
}
load_image[12]=moji_font[12];// . //小数点の処理
for(j=0;j<=9;j++){// kion shousuu keta //小数点以下一桁の処理
if(tpketa[2] == j){
load_image[13]=moji_font[j];
}
}
■■湿度の処理
湿度3桁の処理部です。
for(i=0;i<=2;i++){ // situdo 3 keta
for(j=0;j<=9;j++){
if(siketa[i] == j){
load_image[i+16]=moji_font[j];
}
}
}
load_image[19]=moji_font[20]; // %のデータ
■LEDマトリックス表示部
全部で23文字ある表示データはload_image[0~22]に入っているので、順次LEDマトリックスに表示します。この部分は前回までのプログラムと同じです。
○プログラム全体
プログラム全体を示します。
// LedMatrix 2mai Ondo,Situdo,Kiatu
#include "mbed.h"
#include "BME280.h"
DigitalOut led(dp28);
BME280 sensor1(dp5,dp27,0x76 << 1);
// spi(mosi,miso,sck)
SPI max72_spi(dp2, NC, dp6);
DigitalOut load(dp14);//spi load
// CPU MT7219
// dp1 mosi(Master In Salve Out) => DIN
// dp2 miso(Master OutSlave) => nc
// dp6 sck (Serial Clock) => clk
// dp14 =>(Slave Select) load
int maxInUse = 2; //change this variable to set how many MAX7219's you'll use
// define max7219 registers
#define max7219_reg_noop 0x00
#define max7219_reg_digit0 0x01
#define max7219_reg_digit1 0x02
#define max7219_reg_digit2 0x03
#define max7219_reg_digit3 0x04
#define max7219_reg_digit4 0x05
#define max7219_reg_digit5 0x06
#define max7219_reg_digit6 0x07
#define max7219_reg_digit7 0x08
#define max7219_reg_decodeMode 0x09
#define max7219_reg_intensity 0x0a
#define max7219_reg_scanLimit 0x0b
#define max7219_reg_shutdown 0x0c
#define max7219_reg_displayTest 0x0f
#define LOW 0
#define HIGH 1
#define MHZ 1000000
#define ON 1
#define OFF 0
double p1,t1,h1,pp1;
double hight,hosei;
void maxSingle( int reg, int col) {
//maxSingle is the "easy" function to use for a
//single max7219
load = LOW; // begin
max72_spi.write(reg); // specify register
max72_spi.write(col); // put data
load = HIGH; // make sure data is loaded (on rising edge of LOAD/CS)
}
void maxAll (int reg, int col) { // initialize all MAX7219's in the system
load = LOW; // begin
for ( int c=1; c<= maxInUse; c++) {
max72_spi.write(reg); // specify register
max72_spi.write(col); // put data
}
load = HIGH;
}
void maxOne(int maxNr, int reg, int col) {
//maxOne is for adressing different MAX7219's,
//while having a couple of them cascaded
int c = 0;
load = LOW;
for ( c = maxInUse; c >= maxNr; c--) {
max72_spi.write(0); // no-op
max72_spi.write(0); // no-op
}
max72_spi.write(reg); // specify register
max72_spi.write(col); // put data
for ( c=maxNr-1; c >= 1; c--) {
max72_spi.write(0); // no-op
max72_spi.write(0); // no-op
}
load = HIGH;
}
void setup () {
// initiation of the max 7219
// SPI setup: 8 bits, mode 0
max72_spi.format(8, 0);
// going by the datasheet, min clk is 100ns so theoretically 10MHz should work...
// max72_spi.frequency(10*MHZ);
maxAll(max7219_reg_scanLimit, 0x07);
maxAll(max7219_reg_decodeMode, 0x00); // using an led matrix (not digits)
maxAll(max7219_reg_shutdown, 0x01); // not in shutdown mode
maxAll(max7219_reg_displayTest, 0x00); // no display test
for (int e=1; e<=8; e++) { // empty registers, turn all LEDs off
maxAll(e,0);
}
maxAll(max7219_reg_intensity, 0x0f & 0x0f); // the first 0x0f is the value you can set
// range: 0x00 to 0x0f
}
void get_sensor1(void){
t1=sensor1.getTemperature();
if(t1 > 85.0){
t1=t1-409.0-1;
}
h1=sensor1.getHumidity();
pp1=sensor1.getPressure();
pp1=pp1+int(700/9);
}
int main(void) {
const uint64_t moji_font[] = {// bold font , kagami moji font
0x3c66666e76663c00,//0~9
0x7e1818181c181800,
0x7e060c3060663c00,
0x3c66603860663c00,
0x30307e3234383000,
0x3c6660603e067e00,
0x3c66663e06663c00,
0x1818183030667e00,
0x3c66663c66663c00,
0x3c66607c66663c00,
0x6666663e06060600,// 10 h
0x06063e66663e0000,// 11 p
0x1818000000000000,// 12 .
0x30480848340a0a04, // 13 dc
0x1010157555770101,// 14 hp
0x18187e7e18180000,// 15 +
0x00007e7e00000000,// 16 -
0x082a1c771c2a0800, //17 asuta1
0x007e424a52427e00, // 18 sikaku2
0x0000000000000000, // 19 blank
0x60660c1830660600, // 20 %
0x4242665a5a7e1800, // 21 uchi
0x220424692e2a2c00 // 22 soto
};
/*
const uint64_t moji_font[]={
0x006e333e301e0000,//a
0x003b66663e060607,//b
0x001e3303331e0000,//c
0x006e33333e303038,//d
0x001e033f331e0000,//e
0x000f06060f06361c,//f
0x1f303e33336e0000,//g
0x006766666e360607,//h
0x001e0c0c0c0e000c,//i
0x1e33333030300030,//j
0x0067361e36660607,//k
0x001e0c0c0c0c0c0e,//l
0x00636b7f7f330000,//m
0x00333333331f0000,//n
0x001e3333331e0000,//o
0x0f063e66663b0000,//p
0x78303e33336e0000,//q
0x000f06666e3b0000,//r
0x001f301e033e0000,//s
0x00182c0c0c3e0c08,//t
0x006e333333330000,//u
0x000c1e3333330000,//v
0x00367f7f6b630000,//w
0x0063361c36630000,//x
0x1f303e3333330000,//y
0x003f260c193f0000 //z
};
*/
// // Jissainiha konoyouni mieru
// maxSingle(1,1); |-| -------+
// maxSingle(2,2); |-| ------+-
// maxSingle(3,4); |-| -----+--
// maxSingle(4,8); |-| ----+---
// maxSingle(5,16); |-| ---+----
// maxSingle(6,32); |-| --+-----
// maxSingle(7,64); |-| -+------
// maxSingle(8,128); |-| +-------
int i,j,k;
uint8_t bitsum[22][9],bit1gyou,bitline[250];
uint64_t moji1,load_image[22];
long hpascal,ttemp,sitemp;
int hpketa[4],tpketa[3],siketa[3];
int gdot[]={128,64,32,16,8,4,2,1};
int gbit[16],gbit_s[32];
long wtime=0;
long hpdata[16],hprange,hpmax,hpmin;
long hpcenter;
int dotdata,fstloop,fshuuki;
double hpscope;
double gctrim=0.0;
setup();
wait(0.1);
get_sensor1();
hpascal=long(pp1);
hpmin=hpascal;
hpmax=hpascal;
hpscope=1;
hprange=0;
for(i=0;i<16;i++){
hpdata[i]=hpascal-3;
}
while(1){
get_sensor1();
hpascal=long(pp1);
ttemp=long(t1*10); // seisuuchi henkan
sitemp=long(h1);
hpketa[0]=int(hpascal/1000);hpascal=hpascal-hpketa[0]*1000;
hpketa[1]=int(hpascal/100); hpascal=hpascal-hpketa[1]*100;
hpketa[2]=int(hpascal/10); hpascal=hpascal-hpketa[2]*10;
hpketa[3]=hpascal;
tpketa[0]=int(ttemp/100);ttemp=ttemp-tpketa[0]*100;// jyuu noketa
tpketa[1]=int(ttemp/10);ttemp=ttemp-tpketa[1]*10;// ichi no keta
tpketa[2]=int(ttemp); // shousuutenika no keta
siketa[0]=int(sitemp/100);sitemp=sitemp-siketa[0]*100;
siketa[1]=int(sitemp/10);sitemp=sitemp-siketa[1]*10;
siketa[2]=int(sitemp);
load_image[0]=moji_font[19]; //blank
load_image[1]=moji_font[19]; //blank
load_image[2]=moji_font[17]; //asuta
for(i=3;i<=6;i++){// kiatu 4keta suuji [3 ~ 6]
for(j=0;j<=9;j++){
if(hpketa[i-3] == j){
load_image[i]=moji_font[j];
}
}
}
load_image[7]=moji_font[14];//hp
load_image[8]=moji_font[19]; //blank
if(t1 >=0){
load_image[9]=moji_font[15];//+
}
else {
load_image[9]=moji_font[16];// -
}
for(i=0;i<=1;i++){// kion seisuuketa
for(j=0;j<=9;j++){
if(tpketa[i] == j){
load_image[i+10]=moji_font[j];
}
}
}
load_image[12]=moji_font[12];// .
for(j=0;j<=9;j++){// kion shousuu keta
if(tpketa[2] == j){
load_image[13]=moji_font[j];
}
}
load_image[14]=moji_font[13]; //dc
load_image[15]=moji_font[19];//blank
for(i=0;i<=2;i++){ // situdo 3 keta
for(j=0;j<=9;j++){
if(siketa[i] == j){
load_image[i+16]=moji_font[j];
}
}
}
load_image[19]=moji_font[20]; // %
load_image[20]=moji_font[19];//blank
load_image[21]=moji_font[19];//blank
for(i=0;i<22;i++){ // 0~21 22 moji
moji1=load_image[i];
for(j=0;j<8;j++){// bitsum[1]
bitsum[i][j]=0;
}//j
for(j=0;j<8;j++){
bit1gyou=moji1 & 0xff;
for(k=0;k<8;k++){// kagami moji no font
//for(k=8;k>=1;k--){ // futuu no font
bitsum[i][k]=bitsum[i][k]+(bit1gyou & 0x01)*pow((double)2,(double)(j));
bit1gyou=bit1gyou >> 1;
}//k
moji1=moji1 >> 8;
}//j
}// i
k=0;
for(i=0;i<22;i++){
for(j=0;j<8;j++){
bitline[k]=bitsum[i][j];
k++;
}
}
for(i=0;i<=(22*8-1-16);i++){// bitline hyouji
maxOne(1,1,bitline[i]);
maxOne(1,2,bitline[i+1]);
maxOne(1,3,bitline[i+2]);
maxOne(1,4,bitline[i+3]);
maxOne(1,5,bitline[i+4]);
maxOne(1,6,bitline[i+5]);
maxOne(1,7,bitline[i+6]);
maxOne(1,8,bitline[i+7]);
maxOne(2,1,bitline[i+8]);
maxOne(2,2,bitline[i+9]);
maxOne(2,3,bitline[i+10]);
maxOne(2,4,bitline[i+11]);
maxOne(2,5,bitline[i+12]);
maxOne(2,6,bitline[i+13]);
maxOne(2,7,bitline[i+14]);
maxOne(2,8,bitline[i+15]);
wait(0.1);
}
wait(0.1);
}//while
}//main
○Publish
次のURLでPublishしています。
https://developer.mbed.org/users/takeuchi/code/20160510_V22_1s_LedMatrix/
○完成!
電源ON後に、BME280よりデータを取得し、LEDマトリックスに表示表示します。
気圧の表示です。
単位としてhpを表示します。必要な単位のフォントは筆者が作成しました。
気温の表示です。最初に(+)か(-)を表示します。整数部は2桁です。
小数部を一桁表示し、単位として℃を表示します。
湿度の表示です。
単位として%を表示します。百の位は1か0しかないので、0の場合は表示しないプログラムは各自で考えてみてください。
身近にスクロール表示方式の温湿圧計があるととてもいい感じで便利です。ぜひ、製作に挑戦してください。
投稿者の人気記事

-
taketea2018
さんが
前の月曜日の19:10
に
編集
をしました。
(メッセージ: 初版)
ログインしてコメントを投稿する