ラズピコでArduino IDEの実行速度を見てみるのと改善方法

Arduinoはコンパイル時にcppに落とされてからコンパイルされるので、基本はコンパイラ言語ですが、学習用にかなり冗長な作りになっているようなので、実行速度が問題になるケースも多そうです

というわけで簡単にベンチマーク

元はLEDブリンクのソースに計測用のコードを追加しています

<mainのinoファイル>

ただし時間測定時には、loop1()のwhile処理(loop0()からのメッセージ受信)はコメントアウト

#include "common.h"

// constants won't change. Used here to set a pin number:
const int ledPin = LED_BUILTIN;  // the number of the LED pin

// Variables will change:
int ledState = LOW;  // ledState used to set the LED

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0;  // will store last time LED was updated

// constants won't change:
const long interval = 500;  // interval at which to blink (milliseconds)

uint32_t message_s = 0;
uint32_t message = 999;

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // send message to core1
  rp2040.fifo.push(message_s);
  message_s += 1;

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}

void setup1(){
  pinMode(0, OUTPUT);  
}

void loop1(){
  while (rp2040.fifo.available()>0){
    message = rp2040.fifo.pop();
    message *= 10;
  }
  for (int i = 0; i < 8; i++){
    for (int j = 0; j < 8; j++){ if (disp_data[i][j] > 7){
          dest_data[i][j] = disp_data[i][j];
        }
        else{
          dest_data[i][j] = 0;
        }
    }
  }

  clock_func();
}

<common.hファイル:byte型の二次元配列を2個確保しています>

データの中身に取り立てて意味はありません


// display data
byte disp_data[8][8] = {
   {0,1,1,2,3,5,8,13},
   {13,8,5,3,2,1,1,0},
   {0,1,1,2,3,5,8,13},
   {13,8,5,3,2,1,1,0},
   {0,1,1,2,3,5,8,13},
   {13,8,5,3,2,1,1,0},
   {0,1,1,2,3,5,8,13},
   {13,8,5,3,2,1,1,0}
};

byte dest_data[8][8] = {
};

<clock.inoファイル>

gpioへの書き込みが極端に遅いので、c++の関数を呼び出せるということなので切り替えた(digitalWrite() -> gpio_put())、パルス幅確保のためにハイレベルを5回書き込んでます



void clock_func(){
  //digitalWrite(0, HIGH);
  gpio_put(0, 1);
  gpio_put(0, 1);
  gpio_put(0, 1);
  gpio_put(0, 1);
  gpio_put(0, 1);
  //digitalWrite(0, LOW);
  gpio_put(0, 0);
}

実行速度の測定結果

測定はgpio0のポイントをオシロのプローブであたって時間測定

・digitalWrite()使用時

・gpio_put()使用時

考察

ループの外でGPIO書き込みを行っているのに、全体の処理時間を3割程度長くしてしまうArduinoの標準書き込み関数は時間がクリティカルな場所では使えない、配列の処理に関してはcに比較したら遅いだろうけれども許容範囲か、ただしコードの記述には工夫が必要(配列の要素を一度変数に入れてから処理とかはやめた方が良い

やりたいことはLEDアレイ(HUB75で64*32)の点灯をコア1で行うようにしたいから、16階調処理だと一行のループ処理をおよそ69μs以内(50Hz以下になると人の目に見えるから、1000000/(60*15*16) =69.444μs )ぐらいで実行必要だからターゲットはそこだけど、なんとかなりそうな感触

 

admin

コメントを残す