Vol.907 29.Nov.2024

複数条件でデータ集計 OneDrive PICミニBB(17)_I2C接続有機グラフィック表示ユニット

E Excelで複数の条件に合うデータを集計する 〜SUMIFS関数

by fjk

 Excelの「SUMIF」関数と「SUMIFS」関数は、ある範囲の検索条件に合う値の合計を求められる便利な関数である。特に、SUMIFS関数は複数の検索条件で使用できる。

【使い方】
=SUMIFS(合計範囲, 条件範囲 1, 条件 1, [条件範囲 2, 条件 2[, ...]])
SUMIF 関数では「検索条件が1 つしか設定できない」が、SUMIFS関数ではそれぞれ検索範囲と検索条件をカンマ区切りで続けて書くことにより、複数の条件に合うセルが計算される。検索範囲と検索条件の組み合わせについては、最大 127 ペアまで指定できる。
(参考) 関数の詳細     使い方の例 など
 
【使用例】
<SUMIFSの使用例 >

また、似たように複数の検索条件に合う関数として、 AVERAGEIFS 関数、COUNTIFS 関数もある。
  ・AVERAGEIFS 関数 :   複数の検索条件に合う値の平均値を出したい場合
  ・COUNTIFS 関数 :    複数の検索条件に合うデータの数をカウントしたい場合

<AVERAGEIFSの使用例 >


O OneDrive   〜複数のMSアカウントで利用する

by fjk

  OneDriveはMicrosoftが提供しているオンラインストレージサービス(5GBまで無料)で、複数の機器の間で同じファイルを簡単に共有したり、第三者にファイルを公開することもできる。Windows10/11には、標準でOneDriveアプリがプリインストールされていて、Microsoftアカウントでサインインするだけで、すぐに使い始められる。また、iOSやAndroid OSを搭載したスマートフォン/タブレットでは、それぞれのアプリストアからOneDriveアプリを無償でインストールできる。
 OneDriveの詳細は、microsoft.comを参照。


OneDriveの種類

 Microsoftの提供ということで安心感があり、無料なのでよく利用しているが、ディスクPCとノートパソコンで別のMSアカウントを使っているので、この異なるアカウント間での連携ができないか調べて見た。

複数のアカウントでOneDriveを使うには、以下の方法がある

@ 個人アカウントと職場アカウント(One Drive for Business)を使う
1台のPCに、個人向けのOneDriveと職場用OneDrive_for_Businessを別アカウントで登録し利用する。しかし、windows10では個人用アカウントは 1 つだけしか持つことができない。
A 共有フォルダーを使う
OneDriveのHPからサインインし、新しいフォルダを新規作成し、このフォルダーを共有にする。すると、このフォルダーは異なるアカウントでもアクセスできるようになる。しかし、誰でもアクセスできるように設定もできるため、セキュリティが少し心配。
B Webブラウザから別アカウントで使う
動作は少し遅くなるが、2つのパソコンの設定の変更が必要なく、簡単に利用出来る。
 ・onedrive.live.comからサインインし、ユーザーを指定する。これが最も簡単。
 
<onedriveページのサインイン>

サインイン画面

個人アカウント選択

パスワード入力
※「PCに2つのユーザーアカウントを作成し、それぞれに対応したOneDriveを使う」方法もある。


P PICミニBBシリーズ(17)  〜I2C接続有機グラフィック表示ユニット

by fjk

 小型で自発光の「0.96inch_128x64dot有機ELディスプレィ(Organic Light Emitting Diode)ユニット」(秋月電子#112031、@580、I2C接続)を使ってみた。
 このOLEDは制御チップにSSD1306が使われ、その使用例が多く報告されている。しかし、RaspberyPiやArduinoではAdafluitのライブラリで簡単に使えるが、MCCを使ったPICでの使用例は少ない。

<参考にしたHP>
ゆるく楽しむプログラミング&電子工作
有機EL(OLED)をPICマイコンで制御
OLED0.96インチで遊ぶ(5)-PICから表示
ArduinoでOLEDをライブラリ無しで表示してみる
 
【ハードウェア】 ( SSD1306データ資料
PIC-BASE14ボードはI2C通信を使うabc900などと基本的にほぼ同じですが、PIC16F18325と同ボード上に8pinのメモリも搭載できるよう、PICの位置など配線を変更しています。なお、LED用の電流制限抵抗を取り付けるスペースがきつくなったので、4.7KΩの抵抗入りLEDを使いました。また、今回の報告に関係の無い余計な配線もありますが、今後の機能強化・拡張用です。

有機ELディプレイの回路(メモリは予定)

BB配線状況(LEDは抵抗入)

【ソフトウェア】
−−−−−−− MCC設定 −−−−−−−−

System(Osc= HFINTOSC、Clock= 32MHz、Divider= 1)

I2C(Clock=400kHz)

Eusart(B.Rate=115200)
  • I2C接続でOLEDにコマンドやデータを送信するには、以下の順にバイトデータを書き込む
     
       OLEDアドレスコントロール、[コマンド][、データ[、・・・] [、コマンド[、・・]]
     
     例えば、コマンドは、0x3C0x000x21、0x00, 0x3F (コマンド用コントロールは0x00)
         データは、 0x3C0x40、0x00、 ・・・   (データ用コントロールは0x40)
     
    ※コマンド用コントロールは、0x00(複数のコマンドを続けて)または0x80(続けてコマンド1バイトのみ)。
     
  • 今回、初期設定はデフォルトのままで済むところは設定せず、最低限の設定で済ませた。
     (画面の表示向きなどを変える場合は、マニュアルを参考に[コメントを外し]追加で設定すること)
     
  • データの書込みモードには、「水平モード」、「垂直モード」、「ページモード」(default)があり、モードによってカーソルの移動や位置指定方法が異なる。

    水平モード(0x20,0x00)

    垂直モード(0x20,0x01)

    ページモード(0x20,0x02)
    ※水平モードからページモードに変更しても範囲データ(range)が残っている場合があるので注意!
  • テスト用に、以下のターミナルコマンド(大文字)を作成した。
    T:
    デバイステスト用(パターン表示)
    C:
    OLED画面全クリア(クリアパターン指定)
    L:
    途中行クリア(クリアパターン指定)
    E:
    最下行クリア(クリアパターン指定)
    F:
    5x7フォント表示テスト(文字はプロポーショナル)
    S:
    5x7文字列表示テスト
    H:
    8x16半角文字表示テスト
    K:
    16x16全角文字表示テスト
  • なお、ターミナルとの通信に利用するEUSARTのコード追加はリンク先を参照

有機グラフィックユニット表示例
【abc907-18325.cファイル】 abc907-18325.c + myProject.h(zip)

/*****************************(abc907-18325.c)***
 *      OLEDライブラリーテスト            
 *************************************************/
#include "mcc_generated_files/mcc.h"
#include "myProject.h"      // i2C_SSD1306.hの宣言を追加

#define  VBA

char     RBuf[BFSIZE];      // BFSIZEはmyProject.hで宣言
uint8_t  SFlg;

//---- test data -----
char msg0[] = "Test Print!";
const char hk[10][16] ={
   { 0x00,0xF8,0x04,0x02,0xC2,0x24,0xF8,0x00,
     0x00,0x0F,0x14,0x23,0x20,0x10,0x0F,0x00 },  // 0
   { 0x00,0x10,0x08,0xFE,0x00,0x00,0x00,0x00,
     0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00 },  // 1
   { 0x00,0x18,0x04,0x02,0x82,0x44,0x38,0x00,
     0x00,0x38,0x26,0x21,0x20,0x20,0x20,0x00 },  // 2
   { 0x18,0x04,0x82,0x82,0x82,0x44,0x38,0x00,
     0x0C,0x10,0x20,0x20,0x20,0x11,0x0E,0x00 },  // 3
   { 0x00,0xC0,0x30,0x0C,0xFE,0x00,0x00,0x00,
     0x03,0x02,0x02,0x02,0x3F,0x02,0x02,0x00 },  // 4
   { 0xE0,0x5E,0x22,0x22,0x22,0x42,0x80,0x00,
     0x0C,0x10,0x20,0x20,0x20,0x10,0x0F,0x00 },  // 5
   { 0xF0,0x8C,0x42,0x42,0x42,0x84,0x00,0x00,
     0x0F,0x10,0x20,0x20,0x20,0x10,0x0F,0x00 },  // 6
   { 0x02,0x02,0x02,0x02,0xE2,0x1A,0x06,0x00,
     0x00,0x00,0x00,0x7E,0x01,0x00,0x00,0x00 },  // 7
   { 0x38,0x44,0x82,0x82,0x82,0x44,0x38,0x00,
     0x0E,0x11,0x20,0x20,0x20,0x11,0x0E,0x00 },  // 8
   { 0x78,0x84,0x02,0x02,0x02,0x84,0xF8,0x00,
     0x08,0x10,0x21,0x21,0x21,0x10,0x0F,0x00 }   // 9
};
const char kj[2][32]={
   { 0x00,0x10,0x60,0x01,0x06,0x04,0xE4,0x24,
     0x2F,0x24,0xE4,0x24,0x2F,0x24,0xE4,0x04,
     0x00,0xC0,0x30,0x0C,0x03,0x90,0x95,0x55,
     0x55,0x35,0x1F,0x35,0x55,0x55,0x91,0x90 },  // 漢
   { 0x00,0x1C,0x04,0x04,0x24,0x24,0x24,0x24,
     0xA7,0xA4,0x64,0x24,0x04,0x04,0x1C,0x00,
     0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x82,
     0xFF,0x02,0x02,0x02,0x02,0x02,0x02,0x02 },  // 字
};

//---- test program ----
void test_Msg(){
    i2cOLED_posPX(0,68);
    i2cOLED_str(msg0);    
}

void test_HanK(){
    uint8_t i;
    for(i = 0; i <= 9; i++)
        i2cOLED_Ptn(5,i*8,2,8,(char *)hk[i]);
}

void test_Kanj(){
    uint8_t i;
    for(i = 0; i < 2; i++)
        i2cOLED_Ptn(5,90+i*16,2,16,(char *)kj[i]);
}

void test_Ascii(){
    char c;
    i2cOLED_posPX(0,0);
    for(c = 0x30; c <= 0x39; c++)  i2cOLED_chr(c);
    i2cOLED_posPX(2,0);
    for(c = 0x41; c <= 0x50; c++)  i2cOLED_chr(c);
    i2cOLED_posPX(3,0);
    for(c = 0x61; c <= 0x71; c++)  i2cOLED_chr(c);
}

/*--------------------------------------------------
 *       Main application
 *------------------------------------------------*/
void main(void){
    uint8_t cmd;
    SYSTEM_Initialize();
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
    i2cOLED_init();
    puts("ready!\n"); 
    while (1) {
        if(SFlg){
            cmd = RBuf[0];
            #ifndef VBA
                puts("\r");
            #endif
            switch(cmd){
                case 'T': ssd1306_test();           break;
                case 'C': i2cOLED_Clr(0,7,0);       break;
                case 'L': i2cOLED_LnClr(4,0x08);    break;
                case 'E': i2cOLED_LnClr(7,0xD0);    break;
                case 'F': test_Ascii();             break;
                case 'S': test_Msg();               break;
                case 'H': test_HanK();              break;
                case 'K': test_Kanj();              break;
            } 
            SFlg = 0;
        }
        IO_RA4_Toggle();
        __delay_ms(500);
    }
}/
**===  End of File  ===*/
【myProject.hファイル】

/**************************(myProject.h)***
 *   プロジェクト個別条件指定ファイル     *
 *   (main.cと同じフォルダーに作成)     *
 ******************************************/

#include "mcc_generated_files/mcc.h"
#include "i2c_SSD1306.h"
//#include "myStdlib.h"
//#include "i2cLCD_ST7032i.h"
//#include "AQM1248A.h"
//#include "AQM1248A_v5.h"
//#include "ADT7410.h"
//#include "DS1307.h"
//#include "PC_EEPROM.h"

#define  ON    1
#define  OFF   0

/***** PIC電源電圧 ***********************/
//--- VCC宣言無しは5V(VCC=50と同じ)
#define VCC   50                    // 電源電圧は5V
//#define VCC   33                  // 電源電圧は3.3V

/***** EUSARTモジュール *******************/
//#include "../myXC8lib/myEusart.h"
#define BFSIZE  80                 
//--- ECHO宣言無しはエコー有り(ECHO ONと同じ)
#define ECHO  ON                    // エコー有り
//#define ECHO  OFF                 // エコー無し

/***** MSSPモジュール *********************/
#define MASTER 1
#define SRAVE  2
#define I2CMODE MASTER            // マスターとして使用
//#define I2CMODE SRAVE             // スレーブとして使用
//--- MSSPが一つしか無い場合は I2C宣言無し
#define I2C  1                    // I2C1を使用
//#define I2C  2                    // I2C2を使用

#if I2CMODE == MASTER
    #if I2C == 1
        #include "mcc_generated_files/examples/i2c1_master_example.h"
    #elif I2C == 2
        #include "mcc_generated_files/examples/i2c2_master_example.h"
    #else
        #include "mcc_generated_files/examples/i2c_master_example.h"
    #endif
 #endif

//--- SPIが一つしか無い場合は宣言しない
//#define SPIMODE MASTER            // マスターとして使用
//#define SPIMODE SRAVE             // スレーブとして使用

//#define SPI  1                    // SPI1を使用
//#define SPI  2                    // SPI2を使用

/*********** End of File ******************/

 
【i2c_SSD1306.hファイル】 i2c_SSD1306.c/h + Font_5x7.h (zip)

/*********************** (i2c_SSD1306.h) *******
 *      OLED library Headee                    *
 *      use for 0.96OLED  ,....                *
 ************************************************/
//--- 描画エリアの設定 (for Hor/Ver Mode)--------------
/*    p0: ページ開始位置、  p1: ページ終了位置(-7) [バイト単位]
 *    x0: 列(X)開始位置、  x1: 列(X)終了位置(-127)  */
void i2cOLED_RangePX(uint8_t p0,uint8_t p1, uint8_t x0, uint8_t x1);

//--- 描画開始(カーソル)位置 (for Page Mode)---------
/*    pg: ページ位置[バイト単位]、  cX: 列(x)位置  */
void i2cOLED_posPX(uint8_t pg, uint8_t cX);

//--- ページ列消去(カーソルは行先頭に移動) ---------
/*    pg: 消去したいページ[バイト単位]、  dt: 消去データ */
void i2cOLED_LnClr(uint8_t pg, uint8_t dt);

//--- OLED画面消去 (行範囲指定付き)-----------------
/*    P0: 消去開始ページ、 p1: 消去終了ページ[バイト単位]
 *    dt: 消去データ         */ 
void i2cOLED_Clr(uint8_t p0, uint8_t p1, uint8_t dt);

//--- OLEDに5x7文字を1文字表示する ------------------------
/*      (事前にi2cOLED_posPXで位置指定しておくこと)
 *      ch: 表示文字(ASCII)  */
void i2cOLED_chr (char ch);

//--- OLEDに5x7文字列(プロポーショナル)を表示 ----
/*      (事前にi2cOLED_posPXで位置指定しておくこと)
 *      *str: 表示文字列(ASCII)  */
void i2cOLED_str(char *str);

//--- OLEDの初期化 
void i2cOLED_init(void);

//--- OLEDにパターンを表示 -----------
/*      pg: 表示開始ページ位置(0-7)、cx:表示開始列位置(0−127)
 *      pn: ページ数(1-8)、  xn:列数(1-64) pn*xnは64以内
 *      *ptn: 表示パターンデータのポインタ
 *  RTN: (uint8_t)次表示データの表示列(x)位置       */
uint8_t i2cOLED_Ptn(uint8_t pg,uint8_t cx,uint8_t pn, uint8_t xn, char *ptn);

//--- test SSD1306 ------------------
/*   (デバイスの初期動作テスト用です。ライブラリー化時は削除すること) */
void ssd1306_test(void);

【i2c_SSD1306.cファイル】

/**************************(i2c_SSD1306.c) *****
 *      OLED library                           *
 *      use for 0.96-OLED  ,....               *
 ***********************************************/
#include "myProject.h"
#include "Font_5x7.h"

#define I2COLED_ADR   0x3C              // 0x3Dもある
#define TEST_BF_SIZE  64
#define OLED_BF_SIZE  TEST_BF_SIZE + 2
#define HORIZONTAL    0x00              // 水平アドレスモード
#define VERTICAL      0x01              // 垂直アドレスモード
#define PAGE_ADDR     0x02              // ページモード

uint8_t OLED_MODE;
uint8_t gBf[OLED_BF_SIZE];


//----- Set Draw Area (for Hor/Ver Mode)-------
void i2cOLED_RangePX(uint8_t p0,uint8_t p1, uint8_t x0, uint8_t x1){
    gBf[0] = 0x00;                      // 連続コントロール指示
    gBf[1] = 0x20; gBf[2] = 0x00;       // 水平モード指定
    gBf[3] = 0x21; gBf[4] = x0; gBf[5] = x1;    // 水平範囲(x0-x1)
    gBf[6] = 0x22; gBf[7] = p0; gBf[8] = p1;    // 垂直範囲(p0-p1)
    I2C1_WriteNBytes(I2COLED_ADR, gBf,9);
}

//----- Cursor X,Y (for Page Mode)--------------
void i2cOLED_posPX(uint8_t pg, uint8_t cX){
    i2cOLED_RangePX(0,7,0,127);         // Rangeを全画面に
    gBf[0] = 0x00;                      // 連続コントロール指示
    gBf[1] = 0x20; gBf[2] = 0x02;       // Pageモード指定
    gBf[3] = 0xB0 + (pg & 0x07);        // pageアドレス指定 (0xB0-B7)
    gBf[4] = cX & 0x0F;                 // 列(x)位置下位4ビット指定
    gBf[5] = 0x10 + ((cX >> 4) & 0x07); // 列(x)位置上位3ビット指定
    I2C1_WriteNBytes(I2COLED_ADR, gBf,6);
}
/
/-------- clear LINE --------------------------
void i2cOLED_LnClr(uint8_t pg, uint8_t dt){
    uint8_t i;
    i2cOLED_posPX(pg,0);                // ページモードで位置指定
    gBf[0]=0x40;                        // データコントロール指示
    for(i=1;i<=65;i++) gBf[i]=dt;
    I2C1_WriteNBytes(I2COLED_ADR, gBf,65);
    I2C1_WriteNBytes(I2COLED_ADR, gBf,65);
}    

//-------- clear OLED --------------------------
void i2cOLED_Clr(uint8_t p0, uint8_t p1,uint8_t dt){
    uint8_t i;
    for(i = p0; i <= p1; i++)    i2cOLED_LnClr(i,dt);
    i2cOLED_posPX(p0,0);
}

//-------- OLEDに5x7文字を表示する -----------------
void i2cOLED_chr(char dat){
    char i;
    dat -= 0x20;                        // 配列アドレスを計算
    gBf[0] = 0x40;                      // データコントロール指示 
    for(i=0; i<5; i++) {
        gBf[i+1] = Font[dat][i];
        if(gBf[i+1] == 0xFF) break;     // 幅狭文字なら抜ける
    }
    gBf[i+1]=0;                         // 1ドット空ける
    I2C1_WriteNBytes(I2COLED_ADR, gBf,i+2);     
}

//-------- OLEDに5x7文字列(プロポーショナル)を表示 ---
void i2cOLED_str(char *str){
    while(*str)  i2cOLED_chr(*str++);  	//pointer increment
}

//------ OLEDにパターンを表示
uint8_t i2cOLED_Ptn(uint8_t pg,uint8_t cx,uint8_t pn, uint8_t xn, char *ptn){
    uint8_t i; 
    i2cOLED_RangePX(pg,pg+pn-1,cx,cx+xn-1); // 水平モードでエリア指定
    gBf[0] = 0x40;                      // データコントロール指示
    for(i = 1; i <= pn*xn; i++)   gBf[i] = *ptn++;
    I2C1_WriteNBytes(I2COLED_ADR, gBf, pn*xn+1);
    return cx+xn;
}

//-------- OLEDの初期化  ----
void i2cOLED_init(void){
    uint8_t Cmds[]={
                0x00,               // 連続コントロール指示
                0xA8,0x3F,          // 総ライン数 64行
                0xD3,0x00,          // 表示オフセット無し
                0x40,               // 表示開始ライン=0(下位6ビット)
//                0xA0,             // 左右反転 0xA0:→/0xA1:←
//                0xC0,             // 上下反転 0xC0:↓/0xC8:↑(原点=左上)
//                0xDA,0x02,        // 表示モード=Alternative
//                0x81,0x7F,        // コントラスト= 127(/0-255)
//                0xA4,             // 描画の許可?
//                0xA6,             // 白黒反転 A6:無し/A7:反転
//                0xD5,0x80,        // クロック分周比=128
//                0x20,0x00,        // アドレスモード=horizontal
                0x8D,0x14,          // チャージポンプ設定(必須)
                0xAF                // 表示開始
                };
    __delay_ms(20);                 // 20ms wait
    I2C1_WriteNBytes(I2COLED_ADR, Cmds,9); 
}

//-----  Test for SSD1306 (デバイスの動作テスト用です)
void ssd1306_test(){
//    uint8_t startCmd[] = {0x80,0xA5};
    uint8_t areaCmd[] ={
                0x00,               // 連続コントロール指示
                0x20, 0x00,         // 水平モード
                0x21, 96,127,       // Xエリア指定
                0x22, 2, 3          // Yエリア指定(バイト単位)
                };
//    uint8_t endCmd[] = { 0x80,0xA4 };
    gBf[0] = 0x40;                  // データコントロール指示
    for (int i = 1; i < TEST_BF_SIZE; i++){
        gBf[i] = (uint8_t)(i-1);
    }
//    I2C1_WriteNBytes(I2COLED_ADR, startCmd,2);
    I2C1_WriteNBytes(I2COLED_ADR, areaCmd,9);
    I2C1_WriteNBytes(I2COLED_ADR, gBf, TEST_BF_SIZE);
//    I2C1_WriteNBytes(I2COLED_ADR, endCmd,2);
}


※プログラムのリストをハイライト無しのスタイルで見る場合はここをクリック


※ 本レポートの参考・利用は、あくまでも自己責任でお願いします。


複数条件でデータ集計 OneDrive PICミニBB(16)_I2C接続有機グラフィック表示ユニット