ちょっとTea Time !? Raspberry Pi のPICOを動かしてみる。 2021.8.5

すこし前にこんな情報をいただきました。

RaspberryPiのPICOに搭載されているRP2040というプロセッサがかなり安いようです。



チップでみればかなり安いです。1個100円ちょっとです。ただ、色々と周辺素子もいるので、ボードになったもののほうが使いやすいでしょう。

PICOでも550円です

RP2040だけならかなり安いですが、FLASHメモリーや水晶発振器なども周辺デバイスとしては必要です。
一式が搭載されたPICOは、もちろんRP2040チップ単体に比べると高いですが、それでも秋月電子で550円で買えてしまいます。
ちょうど昼ランチくらいかな?いや、昼ランチ以下でしょう。
 こりゃ、一度遊んでみましょう!


秋月からもPICOが売られています。税込みで550円なので最安じゃないかな?

ちょっと動かしてみる!
 秋月電子で部品を通販するタイミングで、あわせてPICOも買ってみました。
早速ピンを半田付けして動かしてみましょう。実際にはブレッドボードは不要なのですが、
基板が小さくて軽いので固定のためです。
 動作方法については、他のHPで色々と紹介されているのでそちらを参考にしてください。


早速ブレッドボードに差し込んで動かしてみましょう。

どのくらいの速度で動くかな?

PICOで一番気になるのは、どのくらいの速度で動くかです。クロックは最大で133MHzのようです。
実際に搭載されいる水晶は12MHzのようなので11倍のPLLで動いているのかな?それとも8倍程度のPLLかな?
クロックよりかは実際に動作速度が知りたいので、もっとも単純なI/OのON/OFF時間を調べてみました。

 測定結果としては下図のようにON/OFF時間は8ns程度のようです。PIC(PICOではない)を64MHzで動作させたときでも
62.5nsですから約8倍早いことになります。I./O速度だけみると、かなりいいですね。
 ただ、下の波形からわかるようにパルスがLOWになってから次のパルスが出るまでにかなりの間があります。
ループにかかるクロック数はかなり多そうです。

まあ、ループに必要なクロックが多少多くてもPICの比ではなさそうです。それにPICに比べてメモリもROM(FLASH)もはるかに多いですから、
大きなプログラムを組むときは便利なデバイスかもしれません。

int main() {
 const uint LED_PIN = 0;
 gpio_init(LED_PIN);
 gpio_set_dir(LED_PIN, GPIO_OUT);
 while (true) {
  gpio_put(LED_PIN, 1);
  gpio_put(LED_PIN, 0);

 }

}

動作周波数  17.857MHz
動作周期   56ns
int main() {
 const uint LED_PIN = 0;
 gpio_init(LED_PIN);
 gpio_set_dir(LED_PIN, GPIO_OUT);
 while (true) {
  gpio_put(LED_PIN, 1);
  gpio_put(LED_PIN, 1);
  gpio_put(LED_PIN, 0);

 }
}


動作周波数  15.625MHz
動作周期  64ns
I/OのON/OFFにかかる時間は64-56=8ns

PICのプログラムを流用するには

PICのプログラムを移植しようと考えたときに、必須の項目がすこしあります。

1つ目はインターバルタイマー

PICで書いているプログラムの多くは1msのインターバルタイマで割り込みをかけています。
これについてはHPをくぐったら、用法がわかりました。
問題なく使えそうですが、割り込みをOFFにするコマンドはあるのだろうか?
ないはずはないと思いますが、よく探してみないとです。

#include "pico/stdlib.h"
#define GPIO_00 ( 0 )

bool timer_callback( repeating_timer_t *rt )
{
 // ここに割り込みプログラムを書く
 return ( true );
}

void main( void )
{
 static repeating_timer_t timer;
/* GPIO設定 */
 gpio_init( GPIO_00 );
 gpio_set_dir( GPIO_00, GPIO_OUT );
/* インターバルタイマ設定 */
 add_repeating_timer_ms( -1, &timer_callback, NULL, &timer );
 while( true )
 {
  // とりあえずループ
 }
}

2つ目はAD変換器

PICではボリュームや電圧監視に1〜2個のAD変換チャンネルをよくつかいます。
PICOでは外部に3個のAD入力チャンネルがあります。そして変換速度が0.5Ms./sと高速で
さらに12ビットの分解能があります。 これについても、使い方はくぐるとありました。
とりあえず3個あれば足りるでしょう。

#include <stdio.h>
#include <pico/stdlib.h>
#include "hardware/adc.h" // ADC使用

void main(void)
{
unsigned int adcValue;

stdio_init_all();
adc_init();
adc_gpio_init(26);
adc_select_input(0); // ADC0を使用

while(1){
 adcValue = adc_read(); // ADC取得
 printf("adcValue:%d\n", adcValue);
 sleep_ms(500);
 }
}

3つ目は16ビットカウンター

いろいろと調べてみたが、外部クロックを計数するカウンタがみあたりません。
PICではLRCKなどを周波数を計測するために使っています。これがないと少し不便だなあ〜
しかし、PICOの場合は速度が早いので、LRCKなどのパルス幅を計測することで代替できるかもしれません。
カウンタについては、すこし課題がありそうです。

折角なので、何か実用的なものを・・・・

折角PICOを買ってはみたものの、Lチカみたいな使い方では勿体ないです。
なにかI./Oをぶら下げて実用的なものを考えてみましょう!

I/Oをつけてみましょう 2021.8.7

まずは簡単にディスプレとスイッチを取り付けてみることにしました.
回路図は下図の通りです.

まずはこんな形で簡単にI/Oをとりつけました.


実装しました.PICOはソケットを使おうかとおもいましたが、ソケットに挿す力がかなりかかりそうで、
基板がひん曲がりそうなので、直付けしました.


まずは簡単にソフトを作成です. 最初は簡単なLCD2004から動かしましょう.

まずはLCDをつかって動かします.

いままでに作ったPIC用のプログラムが、あまり修正無しでつかえるように
下記のような変換サブルーチンを定義しています.
サブルーチンというよりマクロ変換でもよかったかもです.

void output_low(int pin) { gpio_put(pin,0);}
void output_high(int pin) { gpio_put(pin,1);}
void output_float(int pin) { gpio_set_dir(pin,GPIO_IN);}
void output_drive(int pin) { gpio_set_dir(pin,GPIO_OUT);}
void delay_ms(int n){sleep_ms(n);}
void delay_us(int n){sleep_us(n);}
void delay_cycles(int n) {sleep_us(1);}
int input(int pin){return(gpio_get(pin));}

次は320x240のLCDを動かしてみました。こちらも、比較的簡単な修正でPICのプログラムが移植できました。


手持ちのLCD(320x200 ILI9340)も繋がりました

FLASHのサブルーチンがリンクできない? 2021.8.8

そういえばPICでつかうEEPROMのアクセスも必須の機能です.
PICOにはEEPROMはありませが、広大なエリアをもつFLASHメモリーがあります.そのメモリーの1ページ分(4kB)でも
EEPROMのように扱えばいけるでしょう. FLASHメモリーのアクセアスについてもPICO-SDKを調べてたらありましたが、
なぜかプログラムをコンパイルしてリンクする段階でライブラリが見つからないとエラーがでてきます.
 あれ〜どこにあるのかなあ〜. LINUXってよくわからないからどこを探せばいいかもよくわかりません.

 面倒だからI2Cで動くEEPROMでも載せるかな〜.

ついでにパワーアップ 2021.8.14
 そういえば800x480のLCDが余っていたので、PICOを乗せ換えることにしました.もともとPICでこのLCDを動かそうと
していましたが、キャラクターデータを入れるにはROM容量(32kW=64kB)が少ないので.,すこし挫折していました.しかし、
PICOだとFLASHは2MBあるので気にせずにソフトが組めます.
 ただ、このLCDは8ビットあるいは16ビットでのパラレル転送しかできませんから、結構なI/O数が必要です.
もちろん8ビット転送で行いますが、タッチパネル用のI/Oを含めると18本必要です.PICOのI./Oは全部で26本ですから
残りは8本です.
 AD変換やスイッチ、I2Cを含めるとちょっと足りないかな〜. まあ、足りない場合は最悪I/Oエキスパンダ―でも乗せれば
いいでしょう.


PICOを乗せ換えて800x480LCDを接続するようにしました.


800x480のLCDは8ビットあるいは16ビットのパラレル入力なので結構なI/Oピンを必要としてしまいます.

ターゲットは48素子以上のグライコかなあ〜 20210.8.15

さて、PICOと800x480LCDをどういった用途で使うかを考えて、以前すこし考えていたDIV5142と組み合わせて48素子以上のグラフィックイコライザを考えていましょう。
DIV5142はPICで制御されていましたが、PICOの場合はカウンタ機能がありまん。そこでLRクロックの周波数をPICOで測定するために、クロックの周期を計測することを
考えてみます。
  いくつか試してみましたが、44kHzや48kHzなどの低い周波数ならクロックの半波の周期の計測で、周波数が識別できそうですが192kHzくらいの周波数になると
半波では難しく1波でもすこし辛い感じです。そこで1.5波の周期を調べることで周波数を識別することができそうです。

int measurement_lrck()
{
 int i,j,k;
 i=j=k=0;

if(input(LRCK_PORT)){
 while(input(LRCK_PORT)){i++;if(i>100) return(0);}; // wait
 while(!input(LRCK_PORT)){j++;if(j>100) return(0);};
 k=j+1;
 while(input(LRCK_PORT)){k++;if(k>200) return(0);};
 while(!input(LRCK_PORT)){k++;if(k>300) return(0);};
}
else{
 while(!input(LRCK_PORT)){i++;if(i>100) return(0);}; // wait
 while(input(LRCK_PORT)){j++;if(j>100) return(0);};
 k=j+1;
 while(!input(LRCK_PORT)){k++;if(k>200) return(0);};
 while(input(LRCK_PORT)){k++;if(k>300) return(0);};
}
 if(j>=75 && j<=81) return(44);
 if(j>=69 && j<=74) return(48);
 if(k>=56 && k<=60) return(176);
 if(k>=50 && k<=54) return(192);
 if(k>=114 && k<=119) return(88);
 if(k>=104 && k<=109) return(96);
 return(0);
}

パルスの幅を調べることで周波数を識別するようにしましょう。

ソフト開発用のプラットホーム作成

 構想だけだとなかなか進まないので、ソフト開発用のプラットホームを作成です。
まずはDIV5142の基板に2個のPCM5142を搭載です。ピンポストなどは、あとで増設
するときも考えてあらかじめ実装しておきました。

2CH分のPCM5142を搭載して基板を作成です。


PICは使わないので、基板端子に信号が出るようにダンピング抵抗を取り付けておきます。


(備忘録)ピン配置です。

あわせてのPICO基板(+LCD)にもピンポストを増設です。

PICO搭載基板にもピンポストを実装です。


(備忘録)ピンポストの配置です。



2枚の基板を接続してソフト開発のハードウエアはとりあえず完成です。


こんな感じで接続しています。

ソフト作成にかかりましょう!

とりあえずハードが問題なく動くかどうかの確認が先決なので、I2C通信でPICOとPCM5142とのI/Fを確認です。
800x480のLCDだと、情報量が多いので一気に確認できるので便利です。


PICOとDIV5142でのI2C通信を確認です。PCM5142のレジスターを読み出してみました。

さて、明日からはまた普通の日々がはじまるなあ〜

(つづく?・・・かな?)