· 

9.LED7セグメント表示プロジェクトーRaspberry Pi Pico WindowsC言語入門

11.セグメントLEDプロジェクト

11.1.7セグメントLED(Sparkfun)表示ー時刻、温度表示

プロジェクト名:Led7segment

プロジェクト概要

LCDは表示が見にくい他、デザイン的に物足りない場合があります。このような場合、7セグメントLEDが使用できます。本プロジェクトはSparkfunのセグメント4桁LED(青)を使用したプロジェクトです。接続はシリアル、SPI、I2Cから選択できます。当初I2Cで接続していましたが、動作が不安定でシリアル接続に切り替えました。色は赤、白、青から選択できます。Picoではシリアル出力が3Vロジックで、LEDへの電源も3Vになっています。この場合、5V電源を与えた場合に比べてLEDの輝度が多少落ちます。このため、シリアル接続にレベル変換モジュールBSS138を使用しています。シリアル接続のボーレイトは初期状態で9600です。UART1の初期化処理は以下となります。

 

#define UART_ID uart1

#define BAUD_RATE 9600

#define UART_TX_PIN 4

uart_init(UART_ID, BAUD_RATE);

uart_set_translate_crlf(UART_ID, false);

gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);

 

本プロジェクトでは、UARTライブラリの他にオンボード温度の読み込みに必要なADC、時刻処理に必要なRTCライブラリを使用します。以下のincludeが必要です。

 

#include "hardware/adc.h"

#include "hardware/rtc.h"

#include "hardware/uart.h"

同時にCMakelists.txtにも以下、追加します。

target_link_libraries(Led7segment hardware_adc hardware_rtc hardware_uart)

 

LEDの場合、消費電流が問題になると思います。

Parameter Min Typ. Max

Supply voltage 2.4V 3.3-5V 5.5V

Supply current (Vcc=3.3V) 3.8mA 7.9mA

Supply current (Vcc=5V) 6.9mA 14.1mA

上記仕様ではPicoの最大出力電流が50mAですので、範囲内です。

 

部品リスト

Sparkfunシリアル接続7セグメント4桁LED(青) 1 スイッチサイエンス

タクトスイッチ 1

 

配線図

 

ソースリスト

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include "pico/stdlib.h"

#include "hardware/adc.h"

#include "hardware/rtc.h"

#include "hardware/uart.h"

 

//#define PICO_DEFAULT_LED_PIN 25

#define LED_PIN  PICO_DEFAULT_LED_PIN

#define BUTTON_PIN 10

 

#define UART_ID uart1

#define BAUD_RATE 9600

#define UART_TX_PIN 4

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

int WaitTerminalStartup()

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

 

void InitAdc() {

    adc_init();

    adc_set_temp_sensor_enabled(true);

    adc_select_input(4);

}

float ReadAdcTemperature() {

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

 

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

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

    return tempC;

}

 

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);

}

 

//Sseg control --------

void sseg_reset()

{

    uint8_t buf[8];

    buf[0] = 0x81;

    uart_write_blocking(UART_ID, buf, 1);

    sleep_ms(10);

}

bool sseg_set_i2c_addr(int addr)

{

    if((addr < 1) || (126 < addr)){

        return false;

    }

    uint8_t buf[8];

    buf[0] = 0x80;

    buf[1] = addr;

    uart_write_blocking(UART_ID, buf, 2);

    sleep_ms(10);

   

    return true;

}

bool sseg_set_baudrate(int baudrate)

{

    if((baudrate < 0) || (11 < baudrate)){

        return false;

    }

    uint8_t buf[8];

    buf[0] = 0x7F;

    buf[1] = baudrate;

    uart_write_blocking(UART_ID, buf, 2);

    sleep_ms(10);

 

    return true;

}

bool sseg_segment_control(int digit, int segment)

{

    if((digit < 0) || (3 < digit)){

        return false;

    }

    if((segment < 0) || (127 < segment)){

        return false;

    }

    uint8_t buf[8];

    uint8_t dbuf[4] = {0x7B,0x7C,0x7D,0x7E};

    buf[0] = dbuf[digit];

    buf[1] = segment;

    uart_write_blocking(UART_ID, buf, 2);

    sleep_ms(10);

 

    return true;

}

bool sseg_set_brightness(int value)

{

    if((value < 0) || (100 < value)){

        return false;

    }

    uint8_t buf[8];

    buf[0] = 0x7A;

    buf[1] = value;

    uart_write_blocking(UART_ID, buf, 2);

    sleep_ms(10);

 

    return true;

}

bool sseg_set_cursor(int value)

{

    if((value < 0) || (3 < value)){

        return false;

    }

    uint8_t buf[8];

    buf[0] = 0x79;

    buf[1] = value;

    uart_write_blocking(UART_ID, buf, 2);

    sleep_ms(10);

 

    return true;

}

void sseg_set_decimal(bool dec0,bool dec1,bool dec2,bool dec3, bool colon, bool apostrophe)

{

    uint8_t buf[8];

    buf[0] = 0x77;

    buf[1] = (uint8_t)apostrophe  << 5;

    buf[1] |= (uint8_t)colon << 4;

    buf[1] |= (uint8_t)dec3 << 3;

    buf[1] |= (uint8_t)dec2 << 2;

    buf[1] |= (uint8_t)dec1 << 1;

    buf[1] |= (uint8_t)dec0;

    uart_write_blocking(UART_ID, buf, 2);

    sleep_ms(10);

}

void sseg_clear_display()

{

    uint8_t buf[8];

    buf[0] = 0x76;

    uart_write_blocking(UART_ID, buf, 1);

    sleep_ms(10);

}

void sseg_display_data(char *data, int len)

{

    uart_write_blocking(UART_ID, data, len);

    sleep_ms(10);

}

 

int main()

{

    stdio_init_all();

 

    gpio_init(LED_PIN);

    gpio_set_dir(LED_PIN, GPIO_OUT);

    gpio_init(BUTTON_PIN);

    gpio_set_dir(BUTTON_PIN, GPIO_IN);

    gpio_pull_down(BUTTON_PIN);

   

    gpio_put(PICO_DEFAULT_LED_PIN, 0);

    gpio_put(LED_PIN, 0);

 

    uart_init(UART_ID, BAUD_RATE);

    uart_set_translate_crlf(UART_ID, false);

    gpio_set_function(UART_TX_PIN, GPIO_FUNC_UART);

 

    WaitTerminalStartup();

    printf("\nTerminal connected\n");

 

    InitAdc();

    InitRtc();

    sseg_clear_display();

    sseg_set_brightness(100);

 

    datetime_t nowdt;

    int presec = -1;

    char buf[128];

    int i = 0;

    bool colonOn = false;

    int valueMode = 1; //0:time 1:temperature

 

    while(true) {

        uint8_t ret = gpio_get(BUTTON_PIN);

        if(ret == 1) {

            if(valueMode == 0){

                valueMode = 1;

            } else {

                valueMode = 0;

            }

        }

        rtc_get_datetime(&nowdt);

        if(presec != nowdt.sec)

        {

            float temp = ReadAdcTemperature();

            sprintf(buf, "%5.2f", temp);

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

 nowdt.year, nowdt.month, nowdt.day,nowdt.hour,nowdt.min, nowdt.sec, temp);

            if(valueMode == 0) {

                sseg_set_cursor(0);

                sprintf(buf, "%02d%02d", nowdt.hour,nowdt.min);

                sseg_display_data(buf, 4);

                if(colonOn){

                    colonOn = false;

                } else {

                    colonOn = true;

                }

                sseg_set_decimal(false,false,false,false, colonOn, false);

            } else {

                sseg_set_cursor(0);

                sprintf(buf, " %3.0f", temp*10.0f);

                sseg_display_data(buf, 4);

                sseg_set_decimal(false,false,true,false, false, false);

            }

        }

        presec = nowdt.sec;

        sleep_ms(200);

    }

    return 0;-

}

 

タクトスイッチを押す毎に、時刻表示とオンボード温度表示が切り替わります。