« 2022年3月 | トップページ | 2022年5月 »

2022年4月

2022年4月30日 (土)

ダイソー「LOOPER」(1000mAh) 充放電実験 400サイクル終了

ダイソーのニッ水充電池「LOOPER」単3(1000mAh)、
充放電実験開始が 2月6日
途中経過報告が3月24日。
 ・ダイソー「LOOPER」(1000mAh) 充放電実験 220サイクル目
昨日、400サイクルを終了しました。

50サイクルごとに行う「1.0Vまでの0.2C放電」。
この放電の様子です。
Cap011

「0.2C」ですので、定格で「5時間 = 300分」の放電時間。
300サイクル目までは300分を越えていますんで、
「min 1000mAh」と示された定格容量を満足していると。

JISではこの時間が「60% = 3時間 = 180分」になると
「寿命」と判断します。
「まだまだ行くぞ!」というところでしょうか。

しかし、この0.2C放電カーブより、毎サイクルごとの
0.5C充放電の時間と、充電停止電圧をグラフ化する
ほうが、「劣化の進行」が見えるように思います。

Cap012

充電停止電圧の上昇を見ると、サイクルが進み
内部抵抗が大きくなっている様子が浮かんできます。
「looper」、まだまだ大丈夫そうです。
  ※冬が過ぎて、室温の上昇も「良い方」に
   働きます。
800サイクル目に向け、実験継続です。

 

| | コメント (0)

2022年4月24日 (日)

女房実家から持って帰ってきた「ミニ灯籠」と、雨のツツジ

雨の日曜日、庭のツツジが満開です。
  ※このツツジ、老木で70年は経過しているかと。
土曜日、女房の実家に行って、ちょいとお片付けしてきました。

「ミニ灯籠」があったので、持って帰ってきました。
我が家の庭で、満開のツツジといっしょに記念撮影。
114

全体の感じ。
115

このツツジは出窓のルーツ(昭和26、27年くらい) に植えられたもの。
70年ものかと。
幹の根元が中空になってしまっているんで、そろそろ寿命でしょう。

| | コメント (0)

2022年4月22日 (金)

Arduino UNOのA/D入力:PWMでD/A出力してA/D入力を試す

A/DとD/A(PWMを使って)、同じ基準電圧で出力・入力すると
スケールが同じになります。
ラズパイ・ピコで試したのが
  ・Arduino IDEでRaspberry Pi Pico:PWMでD/A出力してA/D入力を試す
結果・・・
 「こりゃあかんで」
 「まともに使われへんやん」
ということに。
ピコでまともなA/Dしたい時は外付けICを使うのが定石
になるかと思います。

で、同じ考え方をArduino UNOで試してみました。
UNOに乗っているマイコンチップはATmega328P。
過去、いろんなツールに使ってきましたが、ピコの
ようないびつなA/D変換結果には出くわしていません。
外部から与えた電圧(などの信号)で2点校正すれば、
安定した読みが得られるぞ、ということで、回路と
ソフトを作ってきました。

あらためて試してみました。
まずは外部から基準電圧を与えるため、こんな回路で
試します。
A11_20220422130301
使った基準電圧ICはMCP1525とMCP1541。
それぞれの実値は、2.4976Vと4.0777Vでした。

10bitのPWMを0~1023、step=1で可変。
A/Dの平均回数は16回。
その結果。
Cc1_20220422130401

3LSBほどの差が生じましたが、「段」や「飛び」
はありません。
  ※0V付近に不感帯が発生。
   オペアンプによるものは1.0~1.5mVです。

次がチップに内蔵された1.1V基準電圧源。
AREF端子から外に出し、オペアンプU1Bで受けて
D/Aの基準電圧にします。
こんな回路。
A12_20220422130501

AIN0入力に入れるCRフィルタの影響も見てみました。
結果のグラフ。
Cc2_20220422130601
ノイズ除去用として良く用いる「10KΩ + 0.1uF」の
フィルタ。
大きな変換値への影響は無さそうです。

他のArduino UNO基板ではどうかと試しました。
グラフはスムージング処理を加えて描きました。
Cc3_20220422130701

2点校正:線形補間すれば、10bitの分解能を十分に
生かせる特性です。

※関連
線形補間って「LERP」って言うんだ!
Arduino 10bit A/D値をmap関数でスケーリングする例
ミスが広まる 1/1023 vs 1/1024
Arduino なんとかして誤用を正したい:A/Dの1/1023とmap関数
Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMを使おう

/*****  PWM出力とA/D入力のテスト *****/
// Arduino UNOで
// A0でA/D入力
// PWM周波数は1.95kHz, 10bit分解能 D9(PB1) OC1A出力
// Vrefに2.5V基準電圧ICを接続 → 内部1.1Vで ★1
/***** 送信データ *****/
char tx_str[64]; // 送信文字列
/***** シリアル1行入力 *****/
#define RXBF_SIZ 32 // 文字バッファ文字数
char rx_bff[RXBF_SIZ+1]; // 受信文字バッファ (+null)
byte f_rxok; // 受信データありフラグ
/***** シリアル1行受信 *****/
// CRでターミネート f_rxokを1に
// エコーバックなしに
// なし→BSで1文字戻す
void rxbff(void)
{
static byte cnt = 0; // 受信文字数
char c;
if(Serial.available()){ // 受信データあり
if(f_rxok == 0){ // 前データ受信処理した
c = Serial.read(); // 1文字読み出し
if(c == '\r'){ // CR?
rx_bff[cnt] = '\0'; // nullを最後に
// Serial.println(); // 改行
f_rxok = 1; // 受信成功
cnt = 0; // 最初から
}
// else if(c == '\x08'){ // BS? (処理なしに)
// if(cnt > 0){
// cnt--; // 1文字戻す
// Serial.print("\b \b"); // BS,space,BS
// }
// }
else{ // 文字
if((cnt < RXBF_SIZ) && // バッファサイズ内
(isprint(c))){ // 表示可能文字0x20~0x7E
// Serial.write(c); // エコーバック
rx_bff[cnt] = c; // バッファに入れる
cnt++; // 1文字進める
}
}
}
}
}
/***** Break処理付のdelay *****/
// シリアル受信あればdelayを中断
void bkdelay(word dly)
{
word tn, t;
tn = (word)millis(); // now
while(1){
t = (word)millis() - tn; // 経過時間
if(t >= dly) break;
if(Serial.available()) break; // 受信データ
if(f_rxok) break; // CR入力
}
}
/***** 平均処理付A/D入力 *****/
// avr:平均回数
// Raspberry Pi Picoは12bit
// Arduino UNOは10bit
// D2出力は処理タイミングチェック用
// ノイズ減のためコメントアウト
word adavr(word avr)
{
word ad;
word i;
uint32_t add; // 平均加算値
if(avr == 0) avr = 1; // 0なら1回に
add = 0;
for(i = 0; i < avr; i++){
// digitalWrite(2, HIGH); // D2 H
ad = analogRead(A0); // 生A/D値
// digitalWrite(2, LOW); // D2 L
add += (uint32_t)ad; // 加算
}
ad = (word)(add / avr); // 平均値
return ad; // 10bit A/D値
}

/***** D9:PB1:OC1Aへのアナログ出力 *****/
// 10bit値 0~1023
#define PWMTOP 1023 // 10bit max値
void analogWrite9(word d)
{
if(d > PWMTOP) d = PWMTOP;
OCR1A = PWMTOP - d; // PB1設定
}

/***** SETUP *****/
void setup() {
Serial.begin(9600); // 通信
pinMode(2, OUTPUT); // D2
pinMode(9, OUTPUT); // D9 PC1A PWM出力
pinMode(LED_BUILTIN, OUTPUT); // LED
// PWMでD/A出力
// タイマー1 PWM出力 (A:PB1,B:PB2)
TCCR1A = 0b11000010;
// |||| ++---- PWM ICR1 モード
// ||++-------- Port動作
// ++---------- PWM A (Negモード)
TCCR1B = 0b00011010;
// || ||+++---- クロックセレクト 16MHz/8=2MHz
// || ++------- PWM ICR1 モード
// |+---------- ICES1
// +----------- ICNC1
ICR1 = PWMTOP; // 10bit
OCR1A = 0xFFFF; // PWM off 0Vに
// A0入力 Vrefは外部 → 内部に
// analogReference(EXTERNAL); // 外部 ★1
analogReference(INTERNAL); // 内部1.1V
analogRead(A0); // 1回変換しておく
}

// 繰り返しデータ
word ad; // A/D値
word da; // D/A:PWM設定値
char *s; // 入力文字列 最初の
word n; // 文字列番号 5つまで
char *s_in[5]; // 文字列5つ
word d_in[5]; // 入力 start,end,step,avr,wait
byte j_exc; // 実行区分

/***** LOOP *****/
void loop() {
byte f_xLED = 0; // LED点滅用
Serial.println("# A/D test out:PWM D9 in:AD0");
delay(500);
while(1){
f_xLED ^= 1; // LED トグル
digitalWrite(LED_BUILTIN, f_xLED); // LED出力
rxbff(); // 1行受信処理
switch(j_exc){ // 実行区分
case 0: // コマンドプロンプト表示
Serial.print("#Start End Step Avr Wait >");
d_in[2] = 16; // step値を16に
d_in[3] = 1; // 平均回数=1で
d_in[4] = 200; // wait時間を200msに
j_exc = 1;
break;
case 1: // コマンド入力
if(f_rxok){
f_rxok = 0;
Serial.println(); // 改行
n = 0;
s = strtok(rx_bff, " ,"); // 最初の文字分離
while(s != NULL){
s_in[n] = s;
d_in[n] = atoi(s_in[n]); // 数字に
s = strtok(NULL, " ,"); // 次文字分離
n++;
if(n >= 5) break; // 5つまで
}
if(n == 0){ // 数値入力なし
j_exc = 0; // プロンプトから
}
else if(n == 1){ // start一つだけ
da = d_in[0]; // D/A値
analogWrite9(da); // PWM出力して
delay(1000); // wait
j_exc = 2; // A/D入力繰り返しへ
}
else{ // end,step,waitで
j_exc = 3; // PWM繰り返しへ
}
}
break;
case 2: // A/D入力表示続行
ad = analogRead(A0); // A/D値
sprintf(tx_str, "D/A:%4d A/D:%4d",
da, ad);
Serial.println(tx_str);
bkdelay(1000); // 1秒
if(f_rxok){ // break?
f_rxok = 0;
Serial.println("#Break");
j_exc = 0;
}
break;
case 3: // start,end,step,avr,wait
da = d_in[0]; // start値
analogWrite9(da); // PWM出力
Serial.println("#D/A A/D diff");
bkdelay(1000); // 1秒
j_exc = 4; // A/D入力繰り返しへ
break;
case 4: // loop
analogWrite9(da); // PWM出力
bkdelay(d_in[4]); // wait ミリ秒
ad = adavr(d_in[3]); // avr A/D平均処理
sprintf(tx_str, "%4d %4d %5d",
da, ad, (ad - da)); // 差も出力
Serial.println(tx_str);
if(da >= d_in[1]){ // endと比較 おわり?
Serial.println(); // 改行x2
Serial.println();
j_exc = 3; // A/D入力繰り返しへ
}
da += d_in[2]; // +step
if(f_rxok){ // break?
f_rxok = 0;
Serial.println("#Break");
j_exc = 0;
}
break;
}
}
}

PWM出力、8bitしか扱えないanalogWrite()は使っていません。
タイマー1を使ったPWM出力、その初期化手順はsetup()を、
出力方法はanalogWrite9()を見てください。

12_20220422154401
ブレッドボードに2つあるIC、上のほうがオペアンプ。
下側がアナログマルチプレクサ。

| | コメント (0)

タミヤ★★ミニ四駆用充電池「NEO CHAMP」950mAh 800サイクル目

充放電実験を始めたのが2021年11月15日
11_20220422095801
タミヤの「NEO CHAMP」950mAh単3ニッケル水素電池、
JIS C8708:2019での充放電実験800サイクル目が終わりました。

50サイクルごとの0.2C放電グラフ。
Cap107
まだまだ大丈夫そうです。
200サイクル目が2022年2月4日
電池が元気だと、充放電に目一杯の時間がかかります。

毎サイクルの充放電時間と充電終了電圧を記録したのがこのグラフ。
  (充放電電流が異なる50サイクルごとのは除いて)
Cap108
作った充放電装置、連続運転できるのが400サイクル。
内部抵抗を計っておこうと、400サイクル目に電池を
取り外しました。
その時、電池電極と電池ホルダーを清掃(IPAでゴシゴシ)
したのが良かったのか、接触状態が回復したようです。
  ※いつもは、取り外して清掃まではしません。
   電池ホルダーに装着したままクルクル回して
   なんてことはしますが、取り付けっぱなしです。
1200サイクル目に向けて実験続行です。

パナソニック 充電式エボルタお手軽モデル BK-3LLB 1000mAh
のグラフを見ますと、800サイクル目の0.5C放電が95分。
Cap002_20211018105901
NEO CHAMP、頑張っているようです。


| | コメント (0)

2022年4月20日 (水)

Arduino IDEでRaspberry Pi Pico:シリアル受信バッファを増やす

「rp2040・1.13.1」内の「docs」「serial.rst」ファイルを
見ますと、
 Serial1.setFIFOSize(128);
 Serial1.begin(baud);
というサンプルが記されていて、setFIFOSizeでバッファを
増やして、受信時の文字抜けを防げるぞとなっています。

Pi Picoの初期設定ではFIFOの32文字
それを指定しただけ増やせるということなのです。
それを確かめてみました。
  ※Arduino-UNOだと、「HardwareSerial.h」の中で
   送受それぞれに64バイトずつ確保されています。

こんなスケッチを書いてみました。
setFIFOSizeでバッファを128文字に。
・1ms周期で受信文字を取り出す。
・順に文字バッファに保存。
・CRが来たらそれをシリアル出力。
・動作確認のためパルス出力。
   P2:1ms周期の受信文字取り出しタイミング
   P3:シリアル出力タイミング
   P4:loopでパルスをトグル
・Serial1:UART0を115200BPSで
・別のマイコンから1秒周期でシリアルデータ
 (71文字+CR+LF)を送り込んで抜けがないかを
 確認。 (71文字に意味はなし たまたま)

オシロで見るとこんな波形。
F000_20220420163701

まず、ドバッとかたまりで受信データがやってきます。
それをゆっくりと1ms周期で読み出しています。
初期設定のまま(FIFOの32文字だけ)だったり、
割り込み処理がうまく行ってないと、バッファが
あふれて文字抜けが発生します。
タイミングにより「CR」を見つけることができなければ
受信後の処理ができなくなってしまいます。
そんなことなく、うまく処理が進みました。

もう少し波形を拡大すると、受信割り込み処理に
時間が取られて、loopパルスが広がっているところが
見えてきます。

F001

しかし・・・
残念なことにシリアル送信側のバッファ容量は
増えていません。
32文字のFIFOのままです。
F004

ですので、「送出文字数 - 32文字」を出し終わる
までの待ち時間が発生します。
Arduino UNOだと、これが64文字なんですよね。
これ、なんとかしたいなぁ。

//  Raspberry Pi PicoのSerial1.setFIFOSizeを確かめる
// 文字バッファ
#define STRBF_SIZ 256 // 文字バッファサイズ
char str_bff[STRBF_SIZ + 1]; // 文字列(null含む)
word str_cnt; // 受信文字数

/***** SETUP *****/
void setup() {
Serial1.setFIFOSize(128); // FIFO
Serial1.begin(115200); // UART0
pinMode(2, OUTPUT); // P2 受信処理中H
pinMode(3, OUTPUT); // P3 送信タイミングでH
pinMode(4, OUTPUT); // P4 loopでトグル
pinMode(LED_BUILTIN, OUTPUT); // LED
}

/***** LOOP *****/
void loop() {
byte f_xLED = 0; // LED点滅用
char c;
uint32_t t, tn; // us計時
tn = micros(); // 開始時
while(1){
f_xLED ^= 1; // LED トグル
gpio_put(LED_BUILTIN, f_xLED);
gpio_put(4, f_xLED); // P4もトグル
t = micros() - tn; // 経過us
if(t >= 1000){ // 1ms経過
tn = micros(); // 現在時
if(Serial1.available()){ // 受信データあり
gpio_put(2, HIGH); // P2 H
c = Serial1.read(); // 1文字読み出し
if(c == '\r'){ // CR?
str_bff[str_cnt] = '\0'; // nullを最後に
gpio_put(3, HIGH); // P3 H
Serial1.print(str_bff); // 受信文字列1行送信
gpio_put(3, LOW); // P3 L
sprintf(str_bff, " (%3dchr)", str_cnt);
Serial1.println(str_bff); // 受信文字数
str_cnt = 0; // 文字数ゼロに
}
else{ // CR以外の文字
if((str_cnt < STRBF_SIZ) && // バッファサイズ内
(isprint(c))){ // 表示可能文字0x20~0x7E
str_bff[str_cnt] = c; // バッファに保存
str_cnt++; // 1文字進める
}
}
}
gpio_put(2, LOW); // P2 L
}
}
}

 

| | コメント (0)

2022年4月19日 (火)

Arduino IDEでRaspberry Pi Pico:millisをwordで処理した時の異常

2022年4月14日:Arduino IDEでRaspberry Pi Pico:32bitマイコンがバグを生む
この検証用スケッチを書いてみました。

/*****  millisを使った時間待ち  *****/
// uint32_tではなくwordで
word ms_0;
word ms_1;
void delay2(word dly)
{
ms_0 = (word)millis(); // 開始値
while(1){
digitalWrite(2, HIGH); // テスト用パルス出力
ms_1 = (word)millis(); // 現在値
if((ms_1 - ms_0) >= dly) break; // ★1 時間経過
// if((word)(ms_1 - ms_0) >= dly) break; // ★2
digitalWrite(2, LOW);
}
}

/***** SETUP *****/
void setup() {
Serial.begin(9600); // TX
pinMode(2, OUTPUT); // PD2
pinMode(3, OUTPUT); // PD3
pinMode(LED_BUILTIN, OUTPUT); // LED
}

/***** LOOP *****/
void loop() {
byte f_xLED = 0; // LED点滅用
word cnt = 0; // loopカウンタ
char tx_bff[64]; // 送信文字列
while(1){
f_xLED ^= 1; // LED トグル
digitalWrite(LED_BUILTIN, f_xLED);
delay2(1000); // 1000ms wait
sprintf(tx_bff, "#%4d %5u %5u",
cnt, ms_1, ms_0);
Serial.println(tx_bff); // 改行
cnt++;
if(cnt > 9999) cnt = 0;
}
}

★1 と ★2の違いが重要。
★2は引き算結果を(word)でキャストしています。

Arduino UNOで動いていた<★1>の処理、
これをRaspberry Pi Picoに持ってくると、
  cnt ms_1 ms_0
 # 61 62002 61002
 # 62 63002 62002
 # 63 64002 63002
 # 64 65002 64002 ←ここまで動いて停止

数値の比較ができず(32bitのマイナス値になる)、
時間待ち関数から抜け出せません。

これを<★2>のようにすると、Pi PicoでもArduino UNO
でもオーバーフロー発生部分を無事に通過できます。
こんな具合。
  cnt ms_1 ms_0
 # 63 64002 63002
 # 64 65002 64002 ←ここで止まっていたのが、
 # 65   466 65002  (65536+466=66002) 通過
 # 66  1466  466
 # 67  2466 1466
 # 68  3466 2466

符号なし16bit値同士の減算、オーバーフローが起こっても
16bitならうまく「差」が算出されます。
「466 - 65002」は16進だと「01D2 - FDEA」。
「01D2 - FDEA = FFFF・03E8」となり、不要な上位の
「FFFF」は捨てられて下位の16bit値、「03E8」が出てきます。
16進の03E8は10進で1000。
ちゃんと1000ms待ちが動きます。

それが32bitマイコンだと「暗黙の型変換と符号拡張」 が悪さをして、
「01D2 - FDEA = FFFF・03E8 = -64536」とマイナスの値になって
しまいます。
  ※符号なし16bit = word = uint16_t で比較されるつもりが
   符号付の long = int32_t (32bitマイコンでは int だ) で
   比較が行われるのです。
結果、1000msの経過がチェックできません。
今回の例では、減算値ms_0は65002と固定されています。
ms_1が0~65535の間を変化しても、1000を越える値は出てきません
いつまでたってもこのdelayルーチンから抜け出せないのです。

このスカタンの場合、65秒ほど経てば「あれ? なんかおかしい
と気が付くわけですが、もっと複雑な処理で、異常の出現まで
時間がかかるような場合や、条件が重なった時だけ発生する
ものだと、むちゃ怖いバグになってしまいます。

8bitマイコンで正しく動いていたルーチンを32bitマイコンに
持ってくると、転けてしまって動かない。
よく考えておかないと、こんなことが現実に起こります。
「暗黙の型変換と符号拡張」 、昔のルーチンを借用する時は
どうぞ気をつけてください。

| | コメント (0)

2022年4月18日 (月)

Arduino IDEでRaspberry Pi Pico:BSch3V部品ライブラリ

「Raspberry Pi Pico」のBSch3V部品ライブラリ をアップしておきます。
Rr1

ピン番号だけだと面白くないので、USBコネクタなど、
外形を模擬しています。

※21ピンの信号名を修正しました。 (2022-04-27)
P11_20220427104101
「ピコ」の場所は「SPECIAL.LB3」の一番最後。
  ・ダウンロード - special.zip   圧縮しています。

| | コメント (2)

Arduino IDEでRaspberry Pi Pico:ピンヘッダが便利かソケットが便利か

Raspberry Pi Picoへ取り付けるコネクタ、
・ブレッドボードに乗せるのならオスのピンヘッダを下向きにハンダづけ。
 この時使うのは秋月電子の
   細ピンヘッダ 1x40(黒)
 対応するソケットは
   分割ロングピンソケット(細ピン用)1x40(40P)

・Arduino-UNOのように必要な信号線だけをちょこっと
 引き出して使うのなら、メスソケットを上向きにハンダ付け。
 その時はこれ。
   分割ロングピンソケット 1x42(42P)
 対応するピンヘッダはこれ。
   ピンヘッダ 1x40(40P)

手元に2つあるRaspberry Pi Pico、ピンヘッダにした
ものとソケットにしたもの、それぞれを作っています。
Aa11_20220418100901

リセットスイッチ(RUN・GND間)は、
   タクトスイッチ(白)(10個入)
2本足のこれを。
  (通常の4本足のは使いにくいかと)

| | コメント (0)

2022年4月15日 (金)

Arduino IDEでRaspberry Pi Pico:A/D入力が…あれっ?

Arduino IDEでRaspberry Pi Pico:PWMでD/A出力してA/D入力を試す
この続きになるのですが、オペアンプとPicoのA/D入力の間に入れた
CRフィルタ。
これがどうもおかしな挙動をするのです。

Pwm_ad31

まず、コンデンサ無しで抵抗だけで。
抵抗値を変えて様子を見ます。
R12-2

抵抗値を大きくすると電圧ドロップが発生して
読み出したA/D値が低下します。
3.3kΩになると「もうアカンでぇ」という感じ。

そこにコンデンサ(仮に0.1uFの積セラ)を入れてみたの
がこれ。
R12-1
瞬時的なA/Dのサンプル電流をコンデンサが吸収してくれる
のでしょう、ドロップが改善されます。
直列抵抗を100kΩにしても抵抗だけのようなドロップは
生じません。

しかし・・・
「100Ω+0.1uF」だと、100Ωの抵抗だけの時は
直結と変わらなかったのに、入力電圧が上がったところ、
Vrefの1/2を越えたところあたりからおかしなドロップ
が生じます。

この挙動は、いったい何なんでしょうね。


※積セラをフィルムコンに変えてもほぼ同じでした。
  (100Ωだけで試して)
Cap103
直結と100Ωだけは同じグラフが出てきますが、
0.1uFを入れるとアレレに。

| | コメント (1)

2022年4月14日 (木)

Arduino IDEでRaspberry Pi Pico:32bitマイコンがバグを生む

Arduino UNOの「int」は16ビット
それがRaspberry Pi Picoになると「int」は32ビットに

Arduino UNOだとついついRAMをケチりたく
なって、255までの数値でOKなら「byte」でと
「スケッチ」を書いてしまいます。
8ビットで済むところをwordやintにするのは
もったいない・・・ はい。ケチです。

そんな考えで作ったプログラムをPicoに持って
くると思わぬ「バグ」が生じます。
  ・Arduino IDEでRaspberry Pi Pico:PWMでD/A出力してA/D入力を試す

このスケッチ中で使っている時間待ちルーチン。
bkdelay」という名で、1ms単位の時間待ちをしている途中、
シリアル入力があったら時間待ちを中断するという機能を
持たせています。
1秒待ちなんかしてる時に、「もぅエエからはよ終わろうぜ
に対処します。

さて、この時間待ち。
割り込みを使わずに管理するとなると、millisを呼び出して
時間経過をチェックするという処理になります。

millisは32bit値で最大1193時間、50日ほどを計時できます。
「そんな長いこと待たへんのんで16bitでエエやん」と
ケチるわけです。  (16bitだと65秒)
その「ケチな考え」が32bit CPUでバグを生んでしまいます。

今回のルーチン。
/***** Break処理付のdelay *****/
// シリアル受信あればdelayを中断
void bkdelay(word dly)
{
word tn, t;
  tn = (word)millis();    // now
  while(1){
   t = (word)millis();    // 経過
   if((word)(t - tn) >= dly) break;
   if(Serial.available())  break; // 受信データ
  }
}

目標待ち時間dlyと経過時間(t - tn)を比較している
んですが、すべて16bit値で計算していました。
  ※Arduino UNOだから。
  ※UNOの時は(word)を付けてなかった。
  ※(t - tn)、符号無しwordだとtとtnの大小が逆に
   なっても差の値は正しく出てきますんで。
ところが、Picoは32bitで内部処理。
16bitで減算して比較するつもりが、32bit値に型変換され
てから比較されるのです。
  ※「暗黙の型変換と符号拡張」というヤツです。
tとtnの大小が逆になったらマイナスになってしまいます。
tnの値によっては、いつまでたってもdlyを越えることが
できません。

ということで、減算式(t - tn)の前に付けた
キャスト演算子(word)
これを忘れると動かないわけです。

※教訓:32bitマイコンはRAMをケチるな!

ちゃうちゃう。
 「暗黙の型変換と符号拡張」に注意!ということで。


※millis時間判定の異常、検証用スケッチの紹介
Arduino IDEでRaspberry Pi Pico:millisをwordで処理した時の異常


| | コメント (1)

Arduino IDEでRaspberry Pi Pico:PWMでD/A出力してA/D入力を試す

Raspberry Pi Picoの実力試験、まずはA/Dコンバータをば。
RP2040に乗ってるA/Dコンバータの分解能は12bit。
データシートを見ますと、その実力値を示す「ENOB」
(Effective Number of Bits)は「9bit」と記されています。
12bitだとVrefに2.5Vを使うと1bitあたり0.61mVとなります。

A/Dの入力電圧を可変するために、使ったのがPWM出力。
これも12bitに設定できるので、同一のVrefを使うと同じ
スケールにできます。

こんな回路で試しました。
Pwm_ad31
35pinのVrefにシャントレギュレータ「LM4050-2.5」
つないで安定化。
Picoの内部にはシャント抵抗(R7:200Ω)が入っていますので、
図のような接続で安定化できます。

そのVref をPWM周期で駆動するマルチプレクサを通して、
VrefとAGND電圧を切り替えます。
そして、LPFを通して0V~Vrefの直流に。
オペアンプでバッファしてPicoのA/D入力につなぎます。

PWM→LPF→DC電圧という流れのD/A、誤差要因は
オペアンプの特性。
使ったMCP6072、RR-in/RR-outの低オフセット電圧品。
ただ0V付近は1.0~1.5mVほどの不感帯が生じます。

PWM値と読み出したA/D値の差をグラフにしてみました。
PWM値0~4095を32ステップで可変しています。
  ※PWM値を0,32,64,92・・・と増加

まずはA/Dの平均値処理やA/D入力にCRフィルタを付けない
素の状態。(赤色線)
それと、回路図内黄色枠のように、A/D入力にCRフィルタを
装着して試してみます。(緑色線)
Cap082
「CRフィルタ」(1k+0.1uF)を入れた方は、
入力電圧が上がるとA/D値が減少する傾向が見えます。

RP2040のデータシートを見ますと、
ADC  Input Impedance」が「100kΩ」と
出ています。
どうやらこの抵抗で「分圧」されてしまっている
ようです。
ノイズを防ぐために抵抗+コンデンサをいれちゃダメ
というところでしょうか。

次はCRフィルタ無しでA/D値を平均処理してみます。
単純な加算平均です。 16回と64回を試します。
stepは同じで32。
Cap081_20220414152601
さらに。 A/Dの平均回数を64回にして、stepを4に
してみました。
Cap083
数値512,1536,2560,3584の4カ所で「」が
出現しました。

この4カ所の「段」、前後をstep1にして見たのがこれ。
  (平均回数は64回)
Cap084
「差」だと段に見えますが、値の変化で見るとこのように
「上昇が緩やかに」なっているのがわかります。
Cap085
16stepくらいの間、変化が止まっているように
見えます。
A/D変換直線性の性能ということでしょう。

とりあえずラズパイ・ピコのA/Dの実力ということで。

※テストに使ったスケッチ (.inoではなく.txtにしています)
   ・ダウンロード - pwm_ad3.txt

※パラメータ入力
PWMを出力するためのパラメータ設定入力、
手抜きしてますので注意を。
・起動時はEnter入力するとタイトルを出して始まる。
   電源オン、あるいはリセットとUSB通信開始の具合。
   USBがいつつながるのか?
   USB接続でPicoはリセット起動しないのか?
   このあたりがよくわかりません。
・5つのパラメータ入力、「#Start End Step Avr Wait >」
 「strtok」で文字のかたまりを分離して「atoi」で
 文字を数値に変えているだけで、数値範囲のチェックは
 していません。

※追記
実験の様子。 ブレッドボードを使ってます。
P11_20220415094801

※PWMによる12bit D/Aコンバータ、その精度を確か
めてみました。
0.1mVの計測、自動ではできないので手でメモしてます。

「段」の出現、D/A出力をミスっていたらということで、
0V付近、フルスケール付近、そして「512」付近の値を
調べてみました。
Pwm2

PicoのPWM出力、「0V付近を除いて」ほぼ計算どうり
の値が出ています。
  ※0V付近はオペアンプの性能。
フルスーケール値「Vref * 4095 / 4096」もちゃんと
出ています。
Arduino UNOのPWMのように「0は0で合っている」けど
「255で256/256」と、おかしなフルスケールにはなってい
ません。
ちゃんとPWMしています。
これぞ正真正銘の「analogWrite」。
  ※Arduino UNOのは似非のanalogWriteっす。

※参
Arduino、analogWriteは捨てちゃえ。ちゃんとしたPWMを使おう


※次記事:オペアンプ出力とアナログ入力間に入れた
 CRフィルタについて。
Arduino IDEでRaspberry Pi Pico:A/D入力が…あれっ?

※検索
macOSからPi Picoを使う - その11 [Pi Pico]
   似たようなデータが出現しています。


| | コメント (0)

2022年4月13日 (水)

Arduino IDEでRaspberry Pi Pico:Win7でのUSB問題解決です

2022年4月1日:ラズパイ・ピコをArduino IDEで動かそうとしたけど
以来、ピコと遊んでいます・・・

しかし問題が残っていました。
ピコのUSBがCOMポートとして認識してくれなかったのです。
そのせいで、スケッチをアップする時は「BOOTSEL」スイッチと
外付け追加した「RESET/RUN」スイッチの操作が不可欠でした。
   ※ドライブとしては認識してくれていた

その後、その解決方法が判明しました。
  結論は「Zadig.exe」を使えと。
    こちらではCOM34で認識してくれました。

※それまでの経過を簡単に
トランジシタ技術2022年5月号(今月号だ!)が
 「ラズパイPico」の特集。
A01_20220413095401
・第6章 1/fゆらぎUSB扇風機「Pico太郎」の製作
   著者:宮村智也さん
A02_20220413095401
 この記事に、Arduino環境の構築方法が載っています。
  「Earle Philhower版」 を使えと。
・参考文献にはこのpdf。
 https://arduino-pico.readthedocs.io/_/downloads/en/latest/pdf/
・ここに、Windows7でのUSB問題は「Zadig」を使って
 解決できると。

 このように解説されています。
Zad1

こちらでも、これで解決しました。
うまく行ったあとに表示させるとこんな具合に。

Zad2

これで、スケッチのアップロードに「BOOTSEL」、「RESET/RUN」
スイッチの操作が不要になりました。
また「Serial.print」でUSBへのデータ送出もできるようになりました。
めでたし、めでたし・・・

| | コメント (0)

2022年4月12日 (火)

Arduino IDEでラズパイ・ピコ:1msタイマー割り込み

Arduino IDEでラズパイ・ピコ:Earle Philhower版
の導入で、Raspberry Pi Pico C/C++ SDKの関数がちゃんと
動き出したようです。

アラーム割り込みとPWM割り込みの二つで
1msタイマー割り込みを試してみました。
こんなスケッチ。

/*****  1msタイマー割り込みのテスト *****/
// タイマーとPWMで
// GP2 1msタイマー割込処理時間
// GP3 タイマー割込でトグル この周期が2.00598ms
// GP4 loopでトグル 割り込みでパルスが停止
// GP5 1kHz PWM出力
// GP6 PWM割込処理時間
// LED 1Hzで点滅
// millisによル送信データ間隔が1003ms
#include "hardware/pwm.h" // PWM処理に必要
#define nop() asm volatile ("nop\n\t") // nopコード
// ※参考
// https://raspberrypi.github.io/pico-sdk-doxygen/group__hardware__pwm.html
// https://github.com/raspberrypi/pico-examples/blob/master/pwm/led_fade/pwm_led_fade.c
// https://plaza.rakuten.co.jp/sorriman/diary/202103080000/

// データ
volatile word tm_1ms; // 1msダウンカウントタイマー
volatile byte f_1sec; // 1秒フラグ
word cnt_1sec; // 秒カウンタ
char tx_str[64]; // 送信文字列

/***** 1ms割り込み処理 *****/
struct repeating_timer st_tm1ms;
// 割り込み処理
bool tm1ms(struct repeating_timer *t)
{
static word cnt1000 = 0;
static byte f_x3 = 0;
gpio_put(2, HIGH); // GP2 H
f_x3 ^= 1;
gpio_put(3, f_x3); // GP3 トグル
if(tm_1ms) tm_1ms--;
cnt1000 ++;
if(cnt1000 >= 1000){
cnt1000 = 0;
f_1sec = 1;
}
gpio_put(2, LOW); // GP2 L
return true;
}

/***** 1kHz PWM割り込み *****/
word slice_num5; // GP5 PWMスライス番号
// 割り込み処理
void pwm1ms(void){
//static byte f_x6 = 0;
pwm_clear_irq(slice_num5);
gpio_put(6, HIGH); // GP6 H
nop(); nop(); nop(); nop(); // 時間待ち
nop(); nop(); nop(); nop();
gpio_put(6, LOW); // GP6 L
// gpio_put(6, f_x6); // GP6 トグル
// f_x6 ^=1;
}

/***** SETUP *****/
void setup() {
Serial1.begin(115200); // TX0
pinMode(2, OUTPUT); // GP2 1msタイマー割込時間
pinMode(3, OUTPUT); // GP3 1ms割り込みでトグル
pinMode(4, OUTPUT); // GP4 loopでトグル
pinMode(6, OUTPUT); // GP6 PWM割り込み
pinMode(25, OUTPUT); // LED
// GP5 PWM:1kHz 割り込み有効に
gpio_set_function(5, GPIO_FUNC_PWM); // GP5 PWMに
slice_num5 = pwm_gpio_to_slice_num(5); // PWMスライス番号
pwm_clear_irq(slice_num5);
pwm_set_irq_enabled(slice_num5, true);
irq_set_exclusive_handler(PWM_IRQ_WRAP, pwm1ms);
irq_set_enabled(PWM_IRQ_WRAP, true);
pwm_set_clkdiv(slice_num5, 100); // 1.25MHz
pwm_set_wrap(slice_num5, 1250-1); // 1kHz
pwm_set_chan_level(slice_num5, PWM_CHAN_B, 625); // duty50%
pwm_set_enabled(slice_num5, true); // PWMスタート
// 1msサイクルでタイマー割り込み
add_repeating_timer_us(1000, tm1ms, NULL, &st_tm1ms);
}

/***** LOOP *****/
void loop() {
byte f_x4 = 0;
byte f_x25 = 0;
uint32_t ms, t;
ms = millis();
while(1){
if(f_1sec){ // 1秒ごとにシリアル出力
f_1sec = 0;
cnt_1sec++;
if(cnt_1sec > 9999) cnt_1sec = 0;
t = millis() - ms;
ms = millis();
sprintf(tx_str, "%4dsec %4ldms",
cnt_1sec, t);
Serial1.println(tx_str);
}
f_x4 ^= 1; // loopでトグル
gpio_put(4, f_x4); // GP4 トグル
if(tm_1ms == 0){ // 0.5秒経過
tm_1ms = 500;
f_x25 ^= 1;
gpio_put(25, f_x25); // LED トグル
}
}
}

・シリアル出力はTX0に。
・実行の様子はポートにパルスとして出力。
・GP2とGP3がアラーム割り込みによるパルス。
 GP3が500Hzでトグルします。
・GP4は処理loopでトグルパルスを出力。
 割り込みなどが入ると、このパルスが止まります。
・GP5が1kHzのPWM出力。
 50%デューテューに設定。
・GP6がPWM割り込みの処理時間。

問題なのがアラーム割り込み。
2022年4月8日にコメントしましたが、アラーム割り込み
を使うとこの中での処理遅れが加算されるのです。
  ※一定周期の時間が欲しい時はアウトです。

間違いなく一定周期が得られるPWMと比べて、どのくらい
違うかというと・・・
 アラーム割り込み(500Hzでトグル)が
   周期 2.005983ms
 1KHzのPWM出力が
   周期 0.9999975ms

1kHzに換算すると「1.00299倍」。
millisで間隔「1003ms」と出てくるので、
方形波パルスの周波数は正しいようです。
やはりアラーム割り込みによる繰り返しはダメ。

1msアラーム割り込みの処理時間はこんなのです。
Aa1_20220412142701
GP2をH/Lしている割り込み処理の区間は約0.3us。
しかし、loopパルスが途絶えている区間が8usほど
になっています。
これが実際の割り込み処理時間になるわけです。
毎回の1ms割り込みで「3us」が積み重なると、
1秒で3msの遅れとなり、だいたいのつじつまが
合ってきます。

※重要
・一定周期の発生にはアラーム割り込みは適さない。
・利用できるのはPWM割り込み。
・PWM __↑ ̄ パルスエッジの直前で割り込みがかかる。
・PWM割り込み、実質的に一つしか使えない。
    どのPWMチャンネルから割り込みが入ったの
    チェックがむつかしいかと。


| | コメント (0)

Arduino IDEでラズパイ・ピコ:Earle Philhower版で

滴了庵日録 2021-11-27 Raspberry Pi Picoの2つのArduinoサポートを比較
を参考に、「Earle Philhower版」を試してみています。

Pp1_20220412105701
感想
 ・これまでのに比べてコンパイルが速いぞ。

割り込みの記述の検証など、まだまだこれから。

※シリアル出力の処理、バッファリングがどうなっているのかを
見てみたら、やはり32バイトのFIFOを利用しているようで、
送出文字が32バイトを越えると、「待ち」が生じます。

Pp3

そのタイミングをオシロで見ていて
 「これはなに?」
 「前のでは見えなかったぞ」
というのがloopで出しているパルスの抜け。
1ms周期のようです。
loop内で「millis()」を呼んでいるので、そのタイミングかとも
思ったのですが、1秒経過でシリアル出力する手前で▲が出てい
るので、1秒経過の直前の1msカウントとも思えません。
ひょっとすと、バックグランドで「タイマー割り込み」が
走っているのかもしれません。

| | コメント (0)

2022年4月 7日 (木)

Arduino IDEでラズパイ・ピコ:Serial出力がバッファされていないぞ

ラズパイ・ピコをArduino IDEで動かそうとしたけど
ということで、ゴソゴソしております。

なんやかんや分かってきたこと。

・タイマー割り込みについて

(1)「rp2040-datasheet.pdf」の「4.6.4.2. Set an alarm」
  に記されている方法を試したけど、受け付けてもらえ
  ませんでした。
https://github.com/raspberrypi/pico-examples/blob/master/timer/timer_lowlevel/timer_lowlevel.c#L25-L72

(2) Arduinoライブラリを探すと、
https://github.com/khoih-prog/MBED_RPI_PICO_TimerInterrupt
https://github.com/khoih-prog/RPI_PICO_TimerInterrupt
  の二つが出てきます。
Intr_lib1
  この「MBED_RPI_PICO_TimerInterrupt」を使うと
  定周期のタイマー割り込み(RP2040で言うところの
  アラーム割り込み)がうまくいきました。

1ms周期での割り込み例
Cc003_20220407115201
loopでパルスをon/offして割り込みが入った時の処理時間を
確かめました。

・シリアル出力・・・ちょっと問題
  こちらの環境では「Serial.print」がうまく
  行かなかったので「Serial1」を使っています。
   (端子GP0のUART0 TX)
この「Serial1.print」がバッファリングしていないのです。
1文字ずつの送出完了を待って文字列を出すのです。
115200ボーなら16文字で1.4ms。
電文の送出が終わるまで、他のことができません。
Arduino-UNOでさえ、送受とも64バイトのバッファを
持っていて割り込み処理してるのに・・・
  ※Serial1にしてるが悪いのかも?
   要調査案件。

Cc000_20220407115201

RP2040のUART、送受とも32文字のFIFOを持っている
はずなのですが、オシロ波形を見る限り生かされていない
ような感じです。

しかし・・・ 4月1日にテストした9600ボーでの出力は
ちゃんとバッファされているようだし・・・・
タイマー割り込みを使ったのが悪いの?
なんでしょね。

4月1日のスケッチをあらためて走らせてみたら・・・
送信データをバッファしなくなっていました。
  ※異なる波形がオシロに出ました。
4月1日以降、タイマー割り込みを動かすためにArduinoの環境を
あれこれしたので、どこかがおかしくなった可能性が大です。

ラズパイ・ピコ向けの環境、再構築でしょうかね。
困ったぞ!

・試したスケッチ。

/*****  ラズパイ・ピコ RP2040 1msタイマー割り込みのテスト  ****/ 
// TimerInterruptTest.ino
// For MBED RP2040-based boards such as Nano_RP2040_Connect, RASPBERRY_PI_PICO, ADAFRUIT_FEATHER_RP2040 and GENERIC_RP2040.
// Written by Khoi Hoang
// Built by Khoi Hoang https://github.com/khoih-prog/MBED_RPI_PICO_TimerInterrupt
// Licensed under MIT license
// "This code is intended to run on the MBED RASPBERRY_PI_PICO platform!"
// "Please check your Tools->Board setting."
#include "MBED_RPi_Pico_TimerInterrupt.h"

/***** タイマーデータ *****/
volatile byte f_1ms; // 1msフラグ
volatile word tm_1ms; // 1msダウンカウントタイマー
volatile byte f_1sec; // 1秒フラグ
volatile word cnt_1000; // 1秒カウント
/***** シリアル出力 *****/
char tx_bff[64]; // sprintf用

/***** 1ms タイマー割り込み処理 *****/
void TimerHandler0(uint alarm_num)
{
//static byte f_x3 = 0; // GP3トグル用フラグ
TIMER_ISR_START(alarm_num); // ISR前処理
gpio_put(2, HIGH); // GP2 H 割り込み処理時間チェック
// gpio_put(3, f_x3); // GP3 トグル
// f_x3 ^= 1;
f_1ms = 1; // 1ms経過
if(tm_1ms) tm_1ms--; // 1msダウンカウントタイマー
cnt_1000++; // 1秒計時
if(cnt_1000 >= 1000){ // 1000 x 1ms
cnt_1000 = 0;
f_1sec = 1; // 1秒経過フラグをon
}
gpio_put(2, LOW); // GP2 L 割り込み処理時間チェック
TIMER_ISR_END(alarm_num); // ISR後処理
}

// Init MBED_RPI_PICO_Timer, can use any from 0-15 pseudo-hardware timers
MBED_RPI_PICO_Timer ITimer0(0);

/***** セットアップ *****/
void setup(){
pinMode(2, OUTPUT); // タイミングチェック用
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(25, OUTPUT); // LED
Serial1.begin(115200); // シリアル1で出力
ITimer0.attachInterruptInterval(1000, TimerHandler0); // タイマー0:1ms
}

/***** LOOP *****/
void loop(){
byte f_x5 = 0; // GP5トグル用
byte f_x25 = 0; // LEDトグル用
word cnt; // tm_1ms回数
uint32_t t; // micros経過時間
uint32_t us;
us = micros();
cnt = 0;
while(1){
gpio_put(5, f_x5); // GP5トグル
f_x5 ^=1; // loop時間チェック
// 時間経過チェック
if(f_1sec){ // 1秒経過?
f_1sec = 0;
gpio_put(25, f_x25); // LEDトグル
gpio_put(4, f_x25); // GP4も同時に
f_x25 ^=1;
}
if(tm_1ms == 0){ // 1msタイムアップ?
gpio_put(3, HIGH); // GP3 H
tm_1ms = 250; // 0.25秒をセット
t = micros() - us; // 経過時間(us)
us = micros();
sprintf(tx_bff, "%4d %4ld.%03ldms",
cnt, t / 1000, t % 1000);
gpio_put(3, LOW); // GP3 L
Serial1.println(tx_bff);
cnt++; // 回数
if(cnt > 9999) cnt = 0; // max9999
}
}
}


※その後
ボードマネージャーで一つ前のにしたら、バッファリングされる
ようになりました。
Bd300

こんな波形に。
Cd000

シリアルデータの出力が続いていても、
loopを回っているパルスが出ています。
この間は別の処理を動かせます。

しかし・・・
2発目の1ms割り込みでのタイミングのloopパルスを
見ると、割り込みで途切れているのが見えています。
Cd001
ところが・・・
シリアルデータを割り込みでバッファリングしていたら、
1ms割り込み以外の途切れも見えるはずです。
テストスッケッチでの送出文字数は17。
RP2040のFIFOは32文字。
文字数を多くしたらどうなるか、試してみます。
 :
 :

試しました。
32文字より増やしたら、その分だけ待ちが発生。
ということで、バッファリングは送信割り込みではなく
FIFOを使っているということになります。

しかし、ツールの環境を変えてダメになる場合が出る
とは・・・困った困った。




| | コメント (2)

2022年4月 4日 (月)

ラズパイ・ピコのmillisとmicros、なぜか遅い!?

ラズパイ・ピコをArduino IDEで動かそうとしたけど のコメントで、
なんとなくloop時間が長いぞ」っと記しましたが、
millismicros処理時間をテストしてみました。

void setup() {
pinMode(2, OUTPUT); // GP2
pinMode(3, OUTPUT); // GP3
}

uint32_t t;

void loop() {
if(millis() != t){ // 1ms変化?
digitalWrite(2, HIGH); // GP2
t = millis();
digitalWrite(2, LOW);
}
digitalWrite(3, HIGH); // GP3 H/L
digitalWrite(3, LOW); // loopでパルス
}

まずmillis
B000_20220404175301
処理に10us以上かかっています。

microsはちょっと速くなりました。
こんな具合に1ms経過をチェック。
  if((micros() - t) >= 1000){ // 1ms変化
    :
B001_20220404175401

どんな処理をしているのか探してみましたが、探し切れていません。

<common.h>
 unsigned long millis(void);
 unsigned long micros(void);
 void delay(unsigned long);
 void delayMicroseconds(unsigned int us);

<wiring.cpp>
 unsigned long millis(){
  return duration_cast<milliseconds>(lowPowerTimer.elapsed_time()).count();
 }

 unsigned long micros() {
  return timer.elapsed_time().count();
 }

この中の、
 lowPowerTimer.elapsed_time()).count();
 timer.elapsed_time().count();
この処理がどうなっているのか不明っす。


※追記 Arduino-UNOと比較
それじゃっと、16MHzクロックのArduino-UNO(ATmega328p)と
比較してみました。
こんなスケッチ。

//  ポート出力 H/L (digitalWriteだと遅いので)
#define PD2_H (PORTD |= (1 << PD2))
#define PD2_L (PORTD &= ~(1 << PD2))
#define PD3_H (PORTD |= (1 << PD3))
#define PD3_L (PORTD &= ~(1 << PD3))

void setup() {
pinMode(2, OUTPUT); // D2
pinMode(3, OUTPUT); // D3
}

uint32_t t;

void loop() {
if(millis() != t){ // 1ms変化
PD2_H; // PD2 H/L
t = millis(); // millis処理の時間
PD2_L;
}
PD3_H; // PD3 H/L
PD3_L;
}

確認用のパルス出力はdigitalWriteを使わず、ポートの直叩きで
スピードアップします。
結果の波形。
A000_20220405085301

millisの処理が1.3usほど
約2usでloopを回っています。

loopで出しているパルス(PD3)。
それが、いったん止まります。
その原因がタイマー0のオーバーフロー割り込み。
millisはタイマー0のオーバーフロー割り込みでカウントアップ
していますんで、その直後のloopで1ms経過を検知している
様子が見えています。


ラズパイ・ピコの速度、はてさて・・・

※関連
割り込みで処理させるwordデータの扱い
   Arduino-UNOでのmillisの中味を解説しています。


| | コメント (0)

ラズパイ・ピコのポートを高速でH/L

ラズパイ・ピコをArduino IDEで動かそうとしたけど では、
digitalWriteでのパルス出力を試しています。
H/Lして1パルスを出すのに、Hに0.5us、Lに0.5us
1パルスが1usほどでしょうか。

※関連

Arduinoのタイマー処理
Arduino UNOのdigitalWriteだとH/L1パルスが10usほどかかります。

トラ技ARMライタ、初通電
  ↑
 これはさすがに高速です

ラズパイ・ピコでの最高速パルスがこんな感じになりました。

A11_20220404112201

GPIO-2の立ち下がりを拡大。
A12_20220404112201

133MHzクロックで、GPIOのモードが「SIO : Single-cyc I/O」と
いうことで、所持しているデジタルオシロの帯域を越えていてパルスが
方形波に見えません。。

そのスケッチ。 (パルス出力部だけ)

      else{       // 1秒経過しない時
gpio_put(2, HIGH); // 2 H
digitalWrite(3, HIGH); // 3 H/L
digitalWrite(3, LOW);
gpio_put(3, HIGH); // 3 H/L
gpio_put(3, LOW);
gpio_put(3, HIGH); // 3 H/L
gpio_put(3, LOW);
gpio_put(2, LOW); // 2 L
}
}

GPIO-2をHにしてから、GPIO-3に対し、digitalWrite()での
H/L1パルスと、gpio_put()でのパルスを2つ。
そしてGPIO-2をLに。

digitalWrite()だと、HしてLになるのが1usほど。
それがgpio_put()にすると、HしてLで15ns。
さすが、「SIO : Single-cyc I/O」です。

| | コメント (0)

2022年4月 1日 (金)

ラズパイ・ピコをArduino IDEで動かそうとしたけど

ラズパイ・ピコ、PCとつないだらドライブとしては認識
してくれたんで「.uf2」ファイルのアップロードはでき
ました。
普通ならその後、USBがCOMポートとして生きるはず
なんだけれど、それがダメ。
本に書いてあることやネットの情報を試しましたが、
COMポートになりません。
  ※zadig.exeでゴソゴソしてもあきません。

Ab1
  ※インターフェースの記事はArduino IDEで簡便
   にっということじゃなく、本格的ツールで使おう
   という話が中心です。

開発で使っているメインのPCがWin7なもんで、それが
原因なのかと・・・
「USBDeview.exe」で見ると、COM33として認識はされて
いるようなんですが、それが出てきません。
Aa1_20220401173501
「デバマネ」に「!」付で現れたりもしたのですが、
動きません。
Aa2_20220401173601

眠っているUSBを動かすためのツールがあるのかもしれません。

Arduino IDEでコンパイルした結果はピコにアップでき
るので試運転は可能。
USBでのシリアル通信がダメなので、Serila1を使って
みました。

GP0ポートに出ているUART0_TXをPCのターミナルに送り
込んでという手筈です。
書き込み時、BOOTSELスイッチを押しながらいったん
ドライブにしなければならないので、リセットスイッチを
設けました。
  ※ピコはリセットという信号名じゃなく、
   RUNという名のHアクティブ信号です。 
   BOOTとRUNのスイッチを両方押さえて
   先にRUNを離すとドライブになり、
   Arduino IDEでのコンパイルが終わったら
   アップロードしてくれます。
   その後、ドライブが消えて勝手にRUN。

Ab2

テストにこんなスケッチを書いてみました。
millis()で1秒を待つ間、digitalWriteでポート出力を
H/Lして応答速度を確かめます。

void setup() {
Serial1.begin(9600); // UART0:GP0に出力
pinMode(2, OUTPUT); // GP2
pinMode(25, OUTPUT); // LED
}

void loop() {
uint32_t t;
float f;
char msg[20];
byte po = 0;
t = millis() - 1000; // 1秒前にセット
f = 0.00; // 1秒ごとに0.01を加算
while(1){
if((millis() - t) >= 1000){ // 1秒経過?
t = millis();
f += 0.01;
if(f >= 100.00) f = 0.00;
sprintf(msg, "%6s %6.2f", // 浮動小数点変換できる?
"Test", f);
Serial1.println(msg);
digitalWrite(25, po); // LED点滅
po ^= 1;
}
else{ // 1秒経過待ちの時
digitalWrite(2, HIGH); // H/L出力
digitalWrite(2, LOW);
}
}
}

ピコ、さすがにARMマイコン。
printfで浮動小数点の変換が有効です。
  UNO(ATmega328P)とは違うぜっといったところ。

※処理時間の様子
Cc000_20220401175301

Cc001_20220401175301

Cc003

ピコを使いこなすにはまだまだです。
  ※ARMマイコン、STM32F407なんかは仕事で
   使ったんですが。
タイマー割り込みやA/D変換割り込み、外部パルス割り込みを
手懐けなくちゃなりません。


| | コメント (2)

『天体観測に魅せられた人たち』

『天体観測に魅せられた人たち』

原題:THE LAST STARGAZERS
    ※stargazer は天文学者のこと
 エミリー・レヴェック 著
 川添節子 訳

11_20220401120701

12_20220401120701
またまた図書館で。
 そして、一気読み!
  むちゃ面白い!

現代の天文学者さん達が、どうやって観測して
いるのか、勉強になりました。

最初のページ、いきなり「再起動してみました?」・・・
と、話が始まります。

何を再起動するのかというと、ハワイの「すばる望遠鏡」
観測中にアラームが出て止まってしまったんだと。
望遠鏡上部の副鏡が落っこちるかもという状況。
どうすりゃいいのと相談したら、たぶん誤報だから
再起動せよというアドバイスが・・・

一気に本の中に引き込まれました。

絵や図や写真は一切なし。 (表紙と裏表紙の写真だけ)
言葉(文字)だけで状況が浮かんでくる、著者さんと
訳者さんの筆力はたいしたものです。

この本を楽しむには、ある程度、天体のこととか
望遠鏡(光学、電波)の基礎知識は必要でしょう。

※参考 著者さんが出てきます。
https://www.ted.com/talks/emily_levesque_a_stellar_history_of_modern_astronomy

原著:THE LAST STARGAZERS の表紙は写真じゃなくってイラストです。
原著の最初が読めます。
 「再起動した?」がこれ
21_20220401121901
アマゾン(日本)での紹介
にも最初のページが出ています。

| | コメント (2)

« 2022年3月 | トップページ | 2022年5月 »