酒と薔薇の日々(その2)

好きなことだけ求めて生きるアスペ気味のINTJ人

Copilotのやつは!

2024年05月15日 23時16分14秒 | マイコン(ESP32・Arduino等)
先日から赤外線リモコンで小型マイコンATtiny85を動かしてるが、うまく理解できない関数があって
それをどう使うのか色々Copilotに聞いたら・・・

論点をずらしたテキトーな答えが返ってきた挙げ句、要求もしていないのに示されたプログラムサンプルは・・・
私が書いているブログ内のソースとその解説だった。
(使ってる変数の命名規則で自身の物と判明 「m_speed」)
参照しているサイトは、トップに私のブログ記事、とGitとArduinoフォーラムの3個所だけ

(゚Д゚)ハァ?
テキトーなヤツだわ。やっぱり
でも世界中でこのライブラリを使ってる人が少ないことだけはわかったよ
もう昨日からの訳わからんバグ&トラブルで死ぬ
===========================


母艦PCでプログラム作成 -> ArduinoUnoで書き込み -> ATtiny85マイコン -> ATtiny85IC外して -> 動作用基盤へ差し替え -> 動作確認 -> NGでやり直し

PC上での開発と違ってデバッガが無いから、現時点ではLED点滅程度で動作を推定するしか無い。
更に効率アップのため作ったはずの書き込み基盤が、途中から意味不明のエラーを出しだして、これにも手を取られた。
Arduino基盤の数が限られてるのでここ数日、何回配線を組み直したのか(panic face)
赤外線通信の沼から抜け出せん。

[ MX1508 ] を使ってみた(TinyIRライブラリ受信とanalogWriteでモータ制御)

2024年04月24日 19時18分51秒 | マイコン(ESP32・Arduino等)
問題解決しました こちら
---------------------
既存のIR制御と接続してみた。
今までの基盤と同じ構成なので、繋ぎ変えただけ。
前よりモーターの勢いが強く感じる。

動くには動いたのだが、最近IRリモコンの命令を無視する挙動が多すぎる。
動き出したら停止や逆転が不可能になることが頻発。困った。
古い基盤ではそれが非常に起きにくいことが更に混乱に拍車をかけた。
結局、IRの受信とanalogWriteが割り込み競合しているのではないかと疑っている。
すべてをdigitalWriteで書いたらちゃんと動いた(ようだ)
(ポンコツリモコンのチャタリングも意味不明にしていたのかもしれない)
これは解決しました(2024/5/16)
TinyIRReceiverData.justWritten = false;
を各場所が間違ってました。


もうぐじゃぐじゃです。ハイ
いつもながら、疲れまくった。

/*  以下はちゃんと動いた修正後のソース
Arduino Unoで1モーター制御 Attiny85へ移行する前準備
IR受信はTinyライブラリ
2024/5/16
*/
//#include "Arduino.h"
//#include "PinDefinitionsAndMore.h"
#include "TinyIRReceiver.hpp"

#define LED_pin 13

const int A1A = A0; // PB0; // Pin5(PWM)
const int A1B = A1; // PB1; // Pin6(PWM)

int m_speed = 255; // モータパワー

void setup() {
Serial.begin(115200);
Serial.println("start IR motor control");
pinMode(LED_pin, OUTPUT);
//------ Motor -----------
pinMode(A1A, OUTPUT);
pinMode(A1B, OUTPUT);
// ------- IR ----------
if (!initPCIInterruptForTinyReceiver()) {
if(true){
// 無限ループ
digitalWrite(LED_pin,HIGH);
delay(200);
digitalWrite(LED_pin,LOW);
delay(200);
}
}else{
Serial.println("start IR read");
}
delay(100);
}

int cmd = 255;

void loop() {
if (TinyIRReceiverData.justWritten) {
Serial.print(F("Address=0x"));
Serial.print(TinyIRReceiverData.Address, HEX);
Serial.print(' ');
cmd = TinyIRReceiverData.Command;
Serial.print(cmd, HEX);
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) {
Serial.print(F(" Repeat"));
}
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
Serial.print(F(" Parity failed"));
}
Serial.println();
}
// Serial.println(cmd,HEX);

//------- my code ---------
if (cmd == 0x00) {
digitalWrite(LED_pin, HIGH);
forward();
} else if (cmd == 0x02) {
digitalWrite(LED_pin, HIGH);
back();
} else {
digitalWrite(LED_pin, LOW);
stop();
}
TinyIRReceiverData.justWritten = false;  // ここに書く 重要!
delay(500);
}

void handleReceivedTinyIRData() {
printTinyReceiverResultMinimal(&Serial);
}

//--------停止----------
void stop() {
analogWrite(A1A, 0);
analogWrite(A1B, 0);
}
//--------後退----------
void back() {
analogWrite(A1A, m_speed);
analogWrite(A1B, 0);
}
//--------前進-----------
void forward() {
analogWrite(A1A, 0);
analogWrite(A1B, m_speed);
}


====== 以下は経過 =========
リモコンコマンドは左から01・02・03で、正転・停止・逆転としている。
良く観察すると
01、02までは一応OK。たまに反応が悪くなる
03が入るとかなりの確率で暴走する。
停止命令その他を送信しても何も受け付けなくなる。
あるいは03が入って回りだすと02が入ってきても03と認識する。
モータにコンデンサ付けても効果なし
意味わからん。
 :
少しわかった。
モーターが回転中だとIRレシーバの命令を上手く受け取れなくなる。
特に03の場合は全然ダメになる。
01,02はまだ受け取れてなんとか止まるんだけど。

ちなみにPWMパワーを下げすぎてモータが回れない電力になった場合は、すべてのIRコマンドを正しく認識している。
これは結局回路内の電力問題ではないのか???

ちゅうことで、元のモータードライバ基盤へ戻してみた。
ちゃんと動くではないか!!!!!!
くっそー、モータドライブ基盤がポンコツなのか???
それともニッケル水素2本でやってるのがマズイのか??
それではと、元のまともに動く基盤上で電池をニッケル水素3本直列の3.6Vにしてみた。
なんと、新基盤と同じ状態、メチャクチャ動作が不安定になる!!
をいをい・・・

風呂に入りながらふと思った。
う~ん、もしかするとPWM機能がIR受信を妨げているのか?
IR受信は割り込みを使って(?)パルスを読んでいるのでは?
PWMもTimer割り込みを使ってやってたかも。
そうするともしかすれば競合が発生するよなぁ

むむむっ 案外そうかもしれん・・・
で、すべてをdigitalWrite命令に置き換えてみた。
なんか上手くいってるっぽいが、リモコンのチャタリングが疑われる。
キーアサインを変えてみた。
いいじゃんか!

相変わらずLink挿入を連続して行うとパーになるGooBlog いい加減いせんか



Arduinoで赤外線リモコン・モーター制御の習作

2024年04月16日 15時26分01秒 | マイコン(ESP32・Arduino等)


ATtiny85へ書き込む前に、Arduino上でプログラムを作ってみた。
・電源は2.4Vのニッケル水素2本
 これ1本ではモタードライブ基盤が動かない。
 プチ電組み込み時はリポ電池にする予定
・2.4->5Vへ昇圧しArduinoのVinへ供給
・2.4Vはモーター制御基板のVinへ
・Arduinoと昇圧装置ともオーター制御基板のGNDは共通とする
・LED点滅はArduinoの基盤上LEDでPin番号は13
・モーター基盤はポートAしか使わない
・モータ制御信号はPWMアナログ値で出力し速度制御する
 PinはA0,A1を使った。
・赤外リモコンはTiny:bitのものを使った
 00h:電源ボタン 02h:ライトボタン
・赤外線検知は "TinyIRReceiver.hpp"を使用する
・「PinDefinitionsAndMore.h」が見つからない場合はライブラリから探し
 ソースと同じ同一フォルダに入れること。
・赤外信号が0なら正転、2なら逆転、それ以外で停止
 運転中はLED(Pin13)を点灯する



これをATtiny85で「目標サイズ」までサイズダウンする。
画面下にある白紙が、プチ電車内に収まる基板サイズ85*28*H:11mm

======================
/*
ArduinoUnoで1モーター制御 Attiny85へ移行する前準備

*/
//#include "Arduino.h"
#include "PinDefinitionsAndMore.h"
#include "TinyIRReceiver.hpp"

#define LED_pin 13

const int A1A = A0; // PB0; // Pin5(PWM)
const int A1B = A1; // PB1; // Pin6(PWM)

int m_speed = 150; // モータパワー

void setup() {
//------ Motor -----------
pinMode(A1A, OUTPUT);
pinMode(A1B, OUTPUT);

//------ Serial -----------
Serial.begin(115200);
Serial.println(F("START " __FILE__ " from " __DATE__ "\r\nUsing library version " VERSION_TINYIR));
if (!initPCIInterruptForTinyReceiver()) {
Serial.println(F("No interrupt available for pin " STR(IR_RECEIVE_PIN)));
}
Serial.println(F("Ready to receive NEC IR signals at pin " STR(IR_RECEIVE_PIN)));
}

int cmd = 255;

void loop() {
if (TinyIRReceiverData.justWritten) {
TinyIRReceiverData.justWritten = false;
Serial.print(F("Address=0x"));
Serial.print(TinyIRReceiverData.Address, HEX);
Serial.print(' ');
Serial.print(F("Command=0x"));
cmd = TinyIRReceiverData.Command;
Serial.print(cmd, HEX);
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_IS_REPEAT) {
Serial.print(F(" Repeat"));
}
if (TinyIRReceiverData.Flags == IRDATA_FLAGS_PARITY_FAILED) {
Serial.print(F(" Parity failed"));
}
Serial.println();
}
//------- my code ---------
if (cmd == 00) {
digitalWrite(LED_pin, HIGH);
forward();
} else if (cmd == 02) {
digitalWrite(LED_pin, HIGH);
back();
} else {
digitalWrite(LED_pin, LOW);
stop();
}
}

void handleReceivedTinyIRData() {
printTinyReceiverResultMinimal(&Serial);
}

//--------停止----------
void stop() {
analogWrite(A1A, 0);
analogWrite(A1B, 0);
}
//--------後退----------
void back() {
analogWrite(A1A, m_speed);
analogWrite(A1B, 0);
}
//--------前進-----------
void forward() {
analogWrite(A1A, 0);
analogWrite(A1B, m_speed);
}