Tanuki_Bayashin’s diary

電子工作を趣味としています。最近はラズベリーパイPicoというマイコンを使って楽しんでいます

ラズパイPico によるUART接続~Pico-SDK C/C++開発環境にて

※なにか気になる点がありましたらコメント欄にご記入ください。

目次

1.はじめに

 以前の記事の続編です。以前書いた記事では、Pico-SDK C/C++ 環境での開発の進め方について述べました。今回は、Raspberr Pi Pico(以下Pico と記述) によるUART接続をするコードを、実際にPico-SDK C/C++ 環境にて開発してみました。

以前書いた記事:pico-sdk C/C++ での開発の進め方 - Tanuki_Bayashin’s diary

開発環境:Windows10 Raspberry Pi Pico(C/C++により記述) ubuntu Visual Studio 2022 cmake など

 PicoにてUART接続するコードは、ubuntu 内のpico-examples の中にあるhello_uart(フォルダuart 内)の中のhello_uart.c というファイルにて既に出来上がっています。しかしこのコードでは、数値は送信できません。
 そこでここでは、数値もUARTにて送信できるようにしたuart2.c というコードを作ってみました。(開発の進め方は以前書いた記事に示してあります)

※ここでは自分なりに考えた処理を紹介していますが、後日、以下のやり方を他の方のブログにて見つけました。こちらの方がPC側に送信した後でもデータの扱いがしやすいことから、コードに書くには適していると思われます。(2022/08/11追記)

        snprintf(s, sizeof(s), "%f", angle);
        uart_puts(UART_ID, s);

解説:1行目により、angleというfloatの変数をsという文字列に変換したのち、uart_puts()にてデータを送信しています。

2.コードの内容

2.1 1桁の数値を送信するには

 1桁の数値(整数型とします)を送信するときの関数を、自分なりに考えてみました。何のことはない、if 文で各数値ごとに、それに見合う文字を送信しているだけです。

 ※uart_putc( ) は文字(変数の場合、const を付ける必要がある)を1つ送信する関数です。
 (Pico‐SDK内で定義されている模様)

リスト1 1桁の数値を送信する関数 uart_integer_to_string()

void uart_integer_to_string(int16_t a) {

    if (a == 0) {
        uart_putc(UART_ID, '0');
    }
    else if (a == 1) {
        uart_putc(UART_ID, '1');
    }
    else if (a == 2) {
        uart_putc(UART_ID, '2');
    }
    else if (a == 3) {
        uart_putc(UART_ID, '3');
    }
    else if (a == 4) {
        uart_putc(UART_ID, '4');
    }
    else if (a == 5) {
        uart_putc(UART_ID, '5');
    }
    else if (a == 6) {
        uart_putc(UART_ID, '6');
    }
    else if (a == 7) {
        uart_putc(UART_ID, '7');
    }
    else if (a == 8) {
        uart_putc(UART_ID, '8');
    }
    else if (a == 9) {
        uart_putc(UART_ID, '9');
    }
    else {
        uart_putc(UART_ID, 'X');
    }

}

 特に説明はいらないかと思います。else では'X' を送信するようにしました。ある種のデバッグ用の処理です。

2.2 複数の桁を送信する場合

 複数の桁の数値を送信したいときは、数値を1桁ずつに区切ってやればいいと考えました。10進の場合だと、常用対数で何桁かを求め、最上位の数値を切り取ります。それを1の位まで繰り返したのが、リスト2に示す関数です。(数値は符号付き整数としました。この後用いる予定のセンサーが扱うデータが、16ビットの符号付整数だからです)

 少し詳しく説明します。数値として’12345’ を用います。
 ⅰ)常用対数を求めます
  \log_{10} 12345 = 4.091491\cdot \cdot \cdot
 ⅱ)この値の小数点以下を切り捨てます(floor関数を用います)
   \mathrm {floor}(4.091491\cdot \cdot \cdot) = 4
 ⅲ)今度はこの値4を用いて10の4乗(pow関数を使用)で数値’12345’ を割ると、
   12345 \div \mathrm {pow} (10, 4) = 1.2345
 ⅳ)さらに小数点以下を切り捨てると、最上位の値、’1’を求めることができます。
   \mathrm {floor}(1.2345) = 1
  この値をUARTにて送信します。
 ⅴ)これを10の位まで行い、for 文の外で1の位の値をUARTにて送信しています。
  (1つ下の桁での計算をする前に、
   12345‐10000 = 2345
   のように、最上位の値を引き算しています)

 ※uart_puts( ) は文字列を1つ送信する関数です。
 (Pico‐SDK内で定義されている模様)

スト2 複数の桁を送信する関数 sendDataByUART() (負の数の場合にも対応しています)

void sendDataByUART(int16_t x) {
    int16_t digit, a;

    if (x < 0) {
        x = -1 * x;
        uart_putc(UART_ID, '-');
    }
    
    digit = floor(log10((double)x));
    for (int j = digit; j > 0; j--) {
        a = floor(x / pow(10.0, j));
        x = x - a * pow(10.0, j);

        uart_integer_to_string(a);
    }
    uart_integer_to_string(x);

    uart_puts(UART_ID, "\n\r");
    sleep_ms(100);

}

この関数により、データ1つ分を送信可能です。

※この方式だと、データの型の問題がクリアされていれば、小数や2進数(小数含む)の場合にも、1桁ずつ送信できるのではと、思っています。(時間のある時に検証したいです)

2.3 main() 内での処理

 リスト3にmain() 内での処理を示します。送信したいデータを配列に収めました。

リスト3 無限ループの部分を中心に示します

    int16_t data[6] = { 1, 0, -200, 32767, -900, -32767 };
    int16_t x;
    while (1) {
        for (int i = 0; i < 6; i++) {
            x = data[i];
            sendDataByUART(x);
        }

        sleep_ms(250);
    }

3.PicoからPCにデータを送信する(動画)

 実際にデータを送信する様子を動画にて示します。

youtu.be

 動画の前半部分は、実際にコードをビルドする様子を示しました。データを送信する様子では、負の値も’-’ の符号付きで表示されています。センサーの値を送信するには十分なようです。(符号付16ビット整数)

4.まとめ

 Pico-SDK C/C++ 環境にて、ラズパイPicoからPCにUARTにて、データを送信するコードを製作しました。(もっと分かりやすく、簡潔な手順があるかも知れないです)

※コードのその他の部分はラズベリーパイ財団の著作物なので、ここでは示すことを控えました。誰でもダウンロードできるファイルなので、ご自身で調べて頂ければと思います。