· 

8.LCDプロジェクト-温度ロガー他PiPicoC言語入門

10.LCDプロジェクト

10.1.16x2LCD表示ーI2Cデバイススキャン

プロジェクト名:ScanI2C

プロジェクトの概要

GROVEの16 x 2 LCDを使用したLCD表示プロジェクトです。Picoに接続されたデバイスを検出し、LCDに表示します。LCD自体のI2Cアドレス は0x27固定で、初期状態ではこのアドレスのみが表示されます。スイッチ1つが接続されており、このスイッチで上位アドレス00-07を切り替えます。スッチを押すごとに、LCDの上位アドレスが切り替わり、現在の上位アドレスはLCD1行目の0-7のカーソルで確認できます。

 

部品リスト

GROVEの16 x 2 LCD  1 スイッチサイエンス

タクトスイッチ    1

 

回路図

 

ソースリスト

 

#include <stdio.h>

#include "pico/stdlib.h"

#include "hardware/i2c.h"

 

//#define PICO_DEFAULT_LED_PIN 25

#define LED_PIN PICO_DEFAULT_LED_PIN

#define BUTTON_PIN 3

#define I2C_PORT i2c0

#define I2C_SDA 8

#define I2C_SCL 9

 

int ScanBuffer[128];

void ScanI2CBus() {

    uint8_t rxdata;

    for (int addr = 0; addr < 128; addr++) {

        ScanBuffer[addr] = i2c_read_blocking(I2C_PORT, addr, &rxdata, 1, false);

        sleep_ms(10); 

    }

}

 

 

//lcd

#define LCD_ADDR 0x27

// commands

const int LCD_CLEARDISPLAY = 0x01;

const int LCD_RETURNHOME = 0x02;

const int LCD_ENTRYMODESET = 0x04;

const int LCD_DISPLAYCONTROL = 0x08;

const int LCD_CURSORSHIFT = 0x10;

const int LCD_FUNCTIONSET = 0x20;

const int LCD_SETCGRAMADDR = 0x40;

const int LCD_SETDDRAMADDR = 0x80;

 

//display entry mode

const int LCD_ENTRYSHIFTINCREMENT = 0x01;

const int LCD_ENTRYLEFT = 0x02;

//display and cursor control

const int LCD_BLINKON = 0x01;

const int LCD_CURSORON = 0x02;

const int LCD_DISPLAYON = 0x04;

 

//display and cursor shift

const int LCD_MOVERIGHT = 0x04;

const int LCD_DISPLAYMOVE = 0x08;

 

//function set

const int LCD_5x10DOTS = 0x04;

const int LCD_2LINE = 0x08;

const int LCD_8BITMODE = 0x10;

 

//backlight control

const int LCD_BACKLIGHT = 0x08;

const int LCD_ENABLE_BIT = 0x04;

 

#define LCD_CHARACTER  1

#define LCD_COMMAND    0

#define MAX_LINES      2

#define MAX_CHARS      16

//#define MAX_LINES      4

//#define MAX_CHARS      20

#define DELAY_US 600

 

//lcd

void i2c_write_byte(uint8_t val) {

    i2c_write_blocking(I2C_PORT, LCD_ADDR, &val, 1, false);

}

 

void lcd_toggle_enable(uint8_t val) {

 

    sleep_us(DELAY_US);

    i2c_write_byte(val | LCD_ENABLE_BIT);

    sleep_us(DELAY_US);

    i2c_write_byte(val & ~LCD_ENABLE_BIT);

    sleep_us(DELAY_US);

}

void lcd_send_byte(uint8_t val, int mode) {

    uint8_t high = mode | (val & 0xF0) | LCD_BACKLIGHT;

    uint8_t low = mode | ((val << 4) & 0xF0) | LCD_BACKLIGHT;

 

    i2c_write_byte(high);

    lcd_toggle_enable(high);

    i2c_write_byte(low);

    lcd_toggle_enable(low);

}

void lcd_clear(void) {

    lcd_send_byte(LCD_CLEARDISPLAY, LCD_COMMAND);

}

void lcd_set_cursor(int line, int position) {

    int val;

    switch (line) {

    case 0:

        val = 0x80 + position;

        break; 

    case 1:

        val = 0xc0 + position;

        break; 

    case 2:

        val = 0x94 + position;

        break; 

    case 3:

        val = 0xd4 + position;

        break; 

    default:

        break;

    }

    lcd_send_byte(val, LCD_COMMAND);

}

 

static void inline lcd_char(char val) {

    lcd_send_byte(val, LCD_CHARACTER);

}

 

void lcd_string(const char *s) {

    while(true) {

        if(*s == 0) {

            break;

        }

        lcd_char(*s);

        s++;

    }

}

 

void lcd_init() {

    lcd_send_byte(0x03, LCD_COMMAND);

    lcd_send_byte(0x03, LCD_COMMAND);

    lcd_send_byte(0x03, LCD_COMMAND);

    lcd_send_byte(0x02, LCD_COMMAND);

 

    lcd_send_byte(LCD_ENTRYMODESET | LCD_ENTRYLEFT, LCD_COMMAND);

    lcd_send_byte(LCD_FUNCTIONSET | LCD_2LINE, LCD_COMMAND);

    lcd_send_byte(LCD_DISPLAYCONTROL | LCD_DISPLAYON, LCD_COMMAND);

    lcd_clear();

}

 

int main()

{

    char buf[128];

 

    stdio_init_all();

 

    gpio_init(LED_PIN);

    gpio_set_dir(LED_PIN, GPIO_OUT);

    gpio_put(LED_PIN, 0);

 

    gpio_init(BUTTON_PIN);

    gpio_set_dir(BUTTON_PIN, GPIO_IN);

    gpio_pull_down(BUTTON_PIN);

 

    i2c_init(I2C_PORT, 400*1000);

    gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);

    gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);

    gpio_pull_up(I2C_SDA);

    gpio_pull_up(I2C_SCL);

 

    ScanI2CBus();    

 

    lcd_init();

 

    lcd_clear();   

    int yaddr = 0;

    lcd_set_cursor(0, 0);

    lcd_string("0123456789ABCDEF");

    lcd_send_byte(LCD_DISPLAYCONTROL | LCD_DISPLAYON | LCD_CURSORON, LCD_COMMAND);

    uint8_t btnStatus = 0;

    while(true) {

        for(int i = 0; i < 16; i++) {

            lcd_set_cursor(1, i);

            if(ScanBuffer[yaddr*16 + i] >= 0) {

                lcd_string("*");

            } else {

                lcd_string("-");

            }

        }

        lcd_set_cursor(0, yaddr);

        while(true) {

            uint8_t ret = gpio_get(BUTTON_PIN);

            if(ret != btnStatus) {

                if((ret == 1) && (btnStatus == 0)) {

                    yaddr++;

                    if(yaddr >= 8){

                        yaddr = 0;

                    }

                    btnStatus = ret;

                    break;

                }

            }

            btnStatus = ret;

            sleep_ms(10);

        }

    }

   

    return 0;

}

 

 

10.2.16x2LCD表示ー3分タイマー

プロジェクト名:Lcd16x2

プロジェクトの概要

GROVEの16 x 2 LCDを使用したLCD表示プロジェクトです。I2CでPicoと通信します。I2Cアドレス は0x27固定です。3分のカウントダウンタイマーを作成しました。3分はプログラムで変更できます。実行されるとまず、オンボードのLEDが点滅、PC側のターミナルソフトの起動待ちとなります。PC側でTera Termが起動すると、次にI2Cデバイスのスキャンが実行され、ターミナルソフトに結果が表示されます。正常であればここで、0x27のLCDデバイスが確認できます。この後3分カウントダウンがスタートします。カウントダウンが完了するとブザーがなります。

 

部品リスト

GROVEの16 x 2 LCD 1 スイッチサイエンス

電子ブザーPKB24SPCH3601 1 秋月電子通商

 

配線図

 

ソースリスト

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "pico/stdlib.h"

#include "pico/binary_info.h"

#include "hardware/i2c.h"

 

//#define PICO_DEFAULT_LED_PIN 25

#define LED_PIN PICO_DEFAULT_LED_PIN

#define BUZZER_PIN 2

 

#define I2C_PORT i2c0

#define I2C_SDA 8

#define I2C_SCL 9

 

// wait stdio start 

int WaitTerminalStartup() {

    int btnin;

    while(true)

    {

        if(stdio_usb_connected())

        {

            return 0;

        }   

        gpio_put(LED_PIN, 1);

        sleep_ms(200);

        gpio_put(LED_PIN, 0);

        sleep_ms(200);

    }

}

 

void ScanI2CBus() {

    printf("\nI2C Bus Scan\n");

    printf("   0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");

    for (int addr = 0; addr < (1 << 7); ++addr) {

        if (addr % 16 == 0) {

            printf("%02x ", addr);

        }

        int ret;

        uint8_t rxdata;

        ret = i2c_read_blocking(I2C_PORT, addr, &rxdata, 1, false);

        sleep_ms(10); 

 

        printf(ret < 0 ? "." : "@");

        printf(addr % 16 == 15 ? "\n" : "  ");

    }

}

 

//lcd

//LCDのソースは10.1.章を参照してください

//---

 

//timer

#define TIMER_MINUTES 3

 

int main()

{

    char buf[128];

 

    stdio_init_all();

 

    gpio_init(PICO_DEFAULT_LED_PIN);

    gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);

    gpio_init(BUZZER_PIN);

    gpio_set_dir(BUZZER_PIN, GPIO_OUT);

    

    gpio_put(PICO_DEFAULT_LED_PIN, 0);

    gpio_put(BUZZER_PIN, 0);

 

    i2c_init(I2C_PORT, 400*1000);

    gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);

    gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);

    gpio_pull_up(I2C_SDA);

    gpio_pull_up(I2C_SCL);

 

    WaitTerminalStartup();

    printf("\nTerminal connected\n");

    ScanI2CBus();    

    printf("I2C Scan completed\n");

    lcd_init();

 

    lcd_clear();   

    lcd_set_cursor(0, 0);

    sprintf(buf, "%1d minutes timer ", TIMER_MINUTES);

    lcd_string(buf);

 

    uint32_t t1 = time_us_32();

    while(true) {

        uint32_t t2 = time_us_32();

        uint32_t span = t2 - t1;

        if(span > TIMER_MINUTES*60*1000*1000 ) {

            lcd_set_cursor(1, 0);

            lcd_string("Time over!      ");

            gpio_put(BUZZER_PIN, 1);

            sleep_ms(3000);

            gpio_put(BUZZER_PIN, 0);

            break;

        }

        span = TIMER_MINUTES*60*1000*1000 - span;

        uint32_t minutes = span/(60*1000*1000);

        uint32_t usec = span%(60*1000*1000);

        sprintf(buf, "    %2d:%6.3f", minutes, (float)(usec/(1000.0f*1000.0f)));

        lcd_set_cursor(1, 0);

        lcd_string(buf);

        sleep_ms(300);

    }

 

    while(true) {

        lcd_set_cursor(1, 0);

        lcd_string("Time over!      ");

        sleep_ms(500);

        lcd_set_cursor(1, 0);

        lcd_string("                ");

        sleep_ms(500);

    }

   

    return 0;

}

 

 

 

10.3.20x4LCD表示ーオンボード温度ロガー

プロジェクト名:Lcd20x4Logger

プロジェクトの概要

GROVEの20 x 4LCDを使用したLCD表示プロジェクトです。I2CでPicoと通信します。I2Cアドレス は0x27固定です。このプロジェクトではPicoの温度センサー12bitADCにより温度を計測し、PicoのRTCリアルタイムクロックによる時刻ともにLCDに表示します。同時にPCターミナルソフトTeraTermに標準出力にします。Tera Termでは、このログをファイル保存できます。ADCは以下の5チャンネルを内蔵しています。

ADC0 GP26

ADC1 GP27

ADC2 GP28

ADC3 Vsys電源電圧

ADC4オンボード温度

ADC、および内蔵RTCを使用する場合、CMakeLists.txtの最後の近くにある以下行に

ADC、およびRTCのライブラリを追加します。

target_link_libraries(Lcd20x4Logger

        hardware_i2c hardware_adc hardware_rtc

        )

を以下に変更。

target_link_libraries(Lcd20x4Logger

        hardware_i2c hardware_adc hardware_rtc

        )

 

Cソースリストヘッダーに以下を追加します。

#include "hardware/adc.h"

#include "hardware/rtc.h"

 

ADC4からの読み込みデータは以下関数

static uint16_t adc_read (void)

で読み込みます。読み込みデータは12bitであるため、0-4095の値がかえってきます。これをまず電圧に変換します。12bitフルスケールがVref 3.3vであるため、

conversionFactor = 3.3f/(1 << 12);

float tempVolt = (float)adc_read() * conversionFactor;

これを温度に変換します。電圧と温度の関係は27℃、0.706Vが原点で、1℃の勾配が0.001721Vです。以下となります。

float tempC = 27.0f - (tempVolt - 0.706f)/0.001721f;

華氏ではtempF = tempC * 9.0f / 5.0f + 32.0f;

 

部品リスト

GROVEの20 x 4 LCD 1 スイッチサイエンス

 

配線図

 

ソースリスト

 

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "pico/stdlib.h"

#include "pico/util/datetime.h"

#include "hardware/i2c.h"

#include "hardware/adc.h"

#include "hardware/rtc.h"

 

//#define PICO_DEFAULT_LED_PIN 25

#define LED_PIN PICO_DEFAULT_LED_PIN

 

#define I2C_PORT i2c0

#define I2C_SDA 8

#define I2C_SCL 9

 

//10.2章参照

int WaitTerminalStartup()

float ReadAdcTemperature() 

//---------------

 

void InitRtc() {

    char datetime_buf[256];

    char *datetime_str = &datetime_buf[0];

 

    //Start on 2023/5/9 Tuesday 10:24:00

    datetime_t t = {

            .year  = 2023,

            .month = 5,

            .day   = 9,

            .dotw  = 2, // 0:Sunday - 5:Friday

            .hour  = 10,

            .min   = 24,

            .sec   = 00

    };

 

    rtc_init();

    rtc_set_datetime(&t);

    sleep_ms(1);

}

 

//10.2章参照

//lcd

//-------------

int main()

{

    char buf[128];

 

    stdio_init_all();

 

    gpio_init(PICO_DEFAULT_LED_PIN);

    gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);

    gpio_put(PICO_DEFAULT_LED_PIN, 0);

 

    i2c_init(I2C_PORT, 400*1000);

    gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);

    gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);

    gpio_pull_up(I2C_SDA);

    gpio_pull_up(I2C_SCL);

 

    WaitTerminalStartup();

    printf("\nTerminal connected\n");

    ScanI2CBus();    

    printf("I2C Scan completed\n");

 

    lcd_init();

    InitAdc();

    InitRtc();

 

    datetime_t nowdt;

    int premin = -1;

    int cury, curx;

    int tempCount;

    float tempBuf[12];

    int i;

    tempCount = 0;

    while(true) {

        rtc_get_datetime(&nowdt);

        sprintf(buf, "%4d/%02d/%02d %02d:%02d:%02d", nowdt.year, nowdt.month, nowdt.day, nowdt.hour,nowdt.min, nowdt.sec);

        lcd_set_cursor(0, 0);

        lcd_string(buf);

        if(premin != nowdt.min)

        {

            float temp = ReadAdcTemperature();

            if(tempCount >= 12) {

                for(i = 1; i < 12; i++) {

                    tempBuf[i -1] = tempBuf[i];  

                } 

                tempBuf[11] = temp;                  

            } else {

                tempBuf[tempCount] = temp;

            }

            tempCount++;

            for(i = 0; i < 12; i++) {

                cury = i/4 + 1;

                curx = (i%4)*5;

                lcd_set_cursor(cury, curx);

                if(i >= tempCount ) {

                    lcd_string("     ");

                } else {

                    sprintf(buf, " %4.1f", tempBuf[i]);

                    lcd_string(buf);

                }

            }

            printf("%4d/%02d/%02d %02d:%02d:%02d  %4.1f C\n",  

nowdt.year, nowdt.month, nowdt.day, 

  nowdt.hour,nowdt.min, nowdt.sec, temp);

        }

        premin = nowdt.min;

        sleep_ms(1000);

    }

    return 0;

}

 

起動されると、まずPCターミナルソフトTera Termの起動待ちとなり、次にI2Cスキャンが実行されます。この後、オンボード計測実行の永久ループにはいります。計測は1分毎に実行され、結果は時刻とともに標準出力TeraTermに出力されます。TeraTerm側では、この出力された計測データをログファイルに保存できます。メニューから”ファイル”>”ログ”でログ設定画面を以下開きます。

保存するファイル名を入力後、"保存"ボタンを押します。以降、PicoからTera Termに出力されたメッセージは保存されます。オプションはこのまま、"追記"、"プレーンテキスト"で問題ありません。

Pico側は1行目は現在時刻を表示します。2-4行は、過去12個の計測温度が表示されます。1分間隔ですので、12分前の温度経過を見ることができます。1分ごとに12個データはシフトします。

 

10.4.20x4LCD(adafruit)表示-時刻アラーム

プロジェクト名:Lcd20x4

プロジェクト概要

Adafruitの20x4キャラクターのLCDのプロジェクトです。このLCD表示器はLCDと制御基板が分離されて、同じ表示制御基板、バックパックで、異なった表示文字数のLCDをコントロールできます。現時点で日本には代理店はないですが、直接購入できます。また今回はUARTでの接続で使用しました。Picoは2つのUART接続は持っています。通通常UART0は標準出力用となっているため、UART1をLCD表示の通信に使用します。LCD表示器のUART接続のロジックレベルは、5Vです。一方、Picoは3.3Vです。このため、レベル変換モジュールBSS138を使用しました。変換なしに直接、接続するとPico側が破損する恐れがあります。PicoのUART接続を検討するときは、相手のロジックレベルに注意してください。このLCD表示器は、バックライトの色をRGBで設定可能で、コントラスト、ブライトネスもソフトで設定できます。接続は以下となります。

LCD 5V Pico 5V 

LCD GND Pico GND 

LCD Rx Pico UART1-TX(GPIO4)

LCDからの送信はないので、PicoのRXの接続は不要です。

部品リスト

RGB-LCD 20x4 1 adafruit

RGB-LCD 20x4対応バックバック 1 adafruit

3.3V>5Vロジックレベル変換モジュールBSS138 1 秋月電子通商

電子ブザーPKB24SPCH3601 1 秋月電子通商

配線図

 

ソースリスト

include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "pico/stdlib.h"

#include "hardware/uart.h"

#include "pico/util/datetime.h"

#include "hardware/rtc.h"

 

//#define PICO_DEFAULT_LED_PIN 25

#define LED_PIN PICO_DEFAULT_LED_PIN

#define BUZZER_PIN 3

 

//10.2章参照  -------

int WaitTerminalStartup()

//---------------------

typedef struct _alarmset{

    int     hour;

    int     min;

    int     sec;

    bool    status;

    int     buzzerCount; 

} alarmset;

 

alarmset Alarm1,Alarm2, Alarm3;

 

void InitRtc() {

    char datetime_buf[256];

    char *datetime_str = &datetime_buf[0];

 

    //Start on 2023/5/9 Tuesday 10:24:00

    datetime_t t = {

            .year  = 2023,

            .month = 5,

            .day   = 9,

            .dotw  = 2, // 0:Sunday - 5:Friday

            .hour  = 10,

            .min   = 24,

            .sec   = 00

    };

 

    Alarm1.hour  = 10;

    Alarm1.min   = 26;

    Alarm1.sec   = 00;

    Alarm1.status = false;

    Alarm1.buzzerCount = 0;

 

    Alarm2.hour  = 12;

    Alarm2.min   = 00;

    Alarm2.sec   = 00;

    Alarm2.status = false;

    Alarm2.buzzerCount = 0;

    

    Alarm3.hour  = 21;

    Alarm3.min   = 00;

    Alarm3.sec   = 00;

    Alarm3.status = false;

    Alarm3.buzzerCount = 0;

 

    rtc_init();

    rtc_set_datetime(&t);

    sleep_ms(1);

}

 

//lcd -----------------------

#define UART_ID uart1

#define BAUD_RATE 9600

#define UART_TX_PIN 4

#define LCD_WIDTH 20

#define LCD_HEIGHT 4

 

// basic commands

#define LCD_DISPLAY_ON 0x42

#define LCD_DISPLAY_OFF 0x46

#define LCD_SET_BRIGHTNESS 0x99

#define LCD_SET_CONTRAST 0x50

#define LCD_AUTOSCROLL_ON 0x51

#define LCD_AUTOSCROLL_OFF 0x52

#define LCD_CLEAR_SCREEN 0x58

#define LCD_SET_SPLASH 0x40

 

// cursor commands

#define LCD_SET_CURSOR_POS 0x47

#define LCD_CURSOR_HOME 0x48

#define LCD_CURSOR_BACK 0x4C

#define LCD_CURSOR_FORWARD 0x4D

#define LCD_UNDERLINE_CURSOR_ON 0x4A

#define LCD_UNDERLINE_CURSOR_OFF 0x4B

#define LCD_BLOCK_CURSOR_ON 0x53

#define LCD_BLOCK_CURSOR_OFF 0x54

 

// rgb commands

#define LCD_SET_BACKLIGHT_COLOR 0xD0

#define LCD_SET_DISPLAY_SIZE 0xD1

 

void lcd_write(uint8_t cmd, uint8_t* buf, uint8_t buflen) {

    // all commands are prefixed with 0xFE

    const uint8_t pre = 0xFE;

    uart_write_blocking(UART_ID, &pre, 1);

    sleep_ms(10); // give the display some time

 

    uart_write_blocking(UART_ID, &cmd, 1);

    sleep_ms(10); // give the display some time

 

    uart_write_blocking(UART_ID, buf, buflen);

    sleep_ms(10); // give the display some time

}

 

void lcd_set_size(uint8_t w, uint8_t h) {

    // sets the dimensions of the display

    uint8_t buf[] = { w, h };

    lcd_write(LCD_SET_DISPLAY_SIZE, buf, 2);

}

 

void lcd_set_contrast(uint8_t contrast) {

    // sets the display contrast

    lcd_write(LCD_SET_CONTRAST, &contrast, 1);

}

 

void lcd_set_brightness(uint8_t brightness) {

    // sets the backlight brightness

    lcd_write(LCD_SET_BRIGHTNESS, &brightness, 1);

}

 

void lcd_set_backlight(bool is_on) {

    // turn the backlight on (true) or off (false)

    if (is_on) {

        lcd_write(LCD_DISPLAY_ON, (uint8_t *) 0, 1);

    } else {

        lcd_write(LCD_DISPLAY_OFF, NULL, 0);

    }

}

 

void lcd_clear() {

    // clear the contents of the display

    lcd_write(LCD_CLEAR_SCREEN, NULL, 0);

}

 

 

void lcd_set_cursor(bool is_on) {

    // set is_on to true if we want the blinking block and underline cursor to show

    if (is_on) {

        lcd_write(LCD_BLOCK_CURSOR_ON, NULL, 0);

        lcd_write(LCD_UNDERLINE_CURSOR_ON, NULL, 0);

    } else {

        lcd_write(LCD_BLOCK_CURSOR_OFF, NULL, 0);

        lcd_write(LCD_UNDERLINE_CURSOR_OFF, NULL, 0);

    }

}

void lcd_cursor_reset() {

    // reset the cursor to (1, 1)

    lcd_write(LCD_CURSOR_HOME, NULL, 0);

}

void lcd_set_cursor_position(uint8_t x, uint8_t y) {

    //index 1 start

    uint8_t buf[] = {x, y };

    lcd_write(LCD_SET_CURSOR_POS, buf, 2);

}

void lcd_set_backlight_color(uint8_t r, uint8_t g, uint8_t b) {

    // only supported on RGB displays!

    uint8_t buf[] = { r, g, b };

    lcd_write(LCD_SET_BACKLIGHT_COLOR, buf, 3);

}

void lcd_set_splash() {

    uint8_t splash_buf[LCD_WIDTH * LCD_HEIGHT];

    for(int i = 0; i < LCD_WIDTH * LCD_HEIGHT; i++) {

        splash_buf[i] = ' ';

    }

    lcd_write(LCD_SET_SPLASH, splash_buf, LCD_WIDTH * LCD_HEIGHT);

}

 

int main() {

    stdio_init_all();

 

    //led buzzer

    gpio_init(LED_PIN);

    gpio_set_dir(LED_PIN, GPIO_OUT);

    gpio_put(LED_PIN, 0);

 

    gpio_init(BUZZER_PIN);

    gpio_set_dir(BUZZER_PIN, GPIO_OUT);

    gpio_put(BUZZER_PIN, 0);

 

    //wait pc terminal start

    //WaitTerminalStartup();

    //printf("\nusb connected\n");

 

    //rtc

    InitRtc();

 

    //lcd 

    uart_init(UART_ID, BAUD_RATE);

    uart_set_translate_crlf(UART_ID, false);

    gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);

 

    lcd_clear();

    lcd_set_size(LCD_WIDTH, LCD_HEIGHT);

    lcd_set_backlight(true);

    lcd_set_backlight_color(0x00, 0x00, 0xFF);

    lcd_set_contrast(220);

    lcd_set_brightness(255);

    lcd_set_cursor(false);

    lcd_cursor_reset();

 

    char buf[128];

    datetime_t nowdt;

    int prsec = -1;

    while(true) {

        rtc_get_datetime(&nowdt);

        if(prsec != nowdt.sec) {

            if((nowdt.hour == 0) && (nowdt.min == 0) && (nowdt.sec == 0)){

                Alarm1.status = false;

                Alarm1.buzzerCount = 0;

                Alarm2.status = false;

                Alarm2.buzzerCount = 0;

                Alarm2.status = false;

                Alarm2.buzzerCount = 0;

            }

 

            if(!Alarm1.status){

                if((Alarm1.hour == nowdt.hour) && (Alarm1.min == nowdt.min) && (Alarm1.sec == nowdt.sec))

                {

                    Alarm1.status = true;

                    Alarm1.buzzerCount = 0;

                    gpio_put(BUZZER_PIN, 1);

                }

            } else {

                if(Alarm1.buzzerCount > 30) {

                    gpio_put(BUZZER_PIN, 0);

                } else {

                    Alarm1.buzzerCount++;

                }

            } 

 

            if(!Alarm2.status){

                if((Alarm2.hour == nowdt.hour) && (Alarm2.min == nowdt.min) && (Alarm2.sec == nowdt.sec))

                {

                    Alarm2.status = true;

                    Alarm2.buzzerCount = 0;

                    gpio_put(BUZZER_PIN, 1);

                }

            } else {

                if(Alarm2.buzzerCount > 30) {

                    gpio_put(BUZZER_PIN, 0);

                } else {

                    Alarm2.buzzerCount++;

                }

            } 

                        

            if(!Alarm3.status){

                if((Alarm3.hour == nowdt.hour) && (Alarm3.min == nowdt.min) && (Alarm3.sec == nowdt.sec))

                {

                    Alarm3.status = true;

                    Alarm3.buzzerCount = 0;

                    gpio_put(BUZZER_PIN, 1);

                }

            } else {

                if(Alarm3.buzzerCount > 30) {

                    gpio_put(BUZZER_PIN, 0);

                } else {

                    Alarm3.buzzerCount++;

                }

            } 

            sprintf(buf, "%4d/%02d/%02d %02d:%02d:%02d", nowdt.year, nowdt.month, nowdt.day, nowdt.hour,nowdt.min, nowdt.sec);

            lcd_set_cursor_position(1, 1);

            uart_puts(UART_ID, buf);

            lcd_set_cursor_position(1, 2);

            if(Alarm1.status){

                uart_puts(UART_ID, "alarm1 on  ");

            } else {

                uart_puts(UART_ID, "alarm1 off ");

            }

            sprintf(buf, "%02d:%02d:%02d", Alarm1.hour,Alarm1.min, Alarm1.sec);

            lcd_set_cursor_position(12, 2);

            uart_puts(UART_ID, buf);

                        

            lcd_set_cursor_position(1, 3);

            if(Alarm2.status){

                uart_puts(UART_ID, "alarm2 on  ");

            } else {

                uart_puts(UART_ID, "alarm2 off ");

            }

            sprintf(buf, "%02d:%02d:%02d", Alarm2.hour,Alarm2.min, Alarm2.sec);

            lcd_set_cursor_position(12, 3);

            uart_puts(UART_ID, buf);

            

            lcd_set_cursor_position(1, 4);

            if(Alarm3.status){

                uart_puts(UART_ID, "alarm3 on  ");

            } else {

                uart_puts(UART_ID, "alarm3 off ");

            }

            sprintf(buf, "%02d:%02d:%02d", Alarm3.hour,Alarm3.min, Alarm3.sec);

            lcd_set_cursor_position(12, 4);

            uart_puts(UART_ID, buf);

        }

        prsec = nowdt.sec;

        sleep_ms(100);

    }

    return 0;

}