以前の記事でNUCLEOボードにはEVALUATION BOARD LICENSEが適用されているらしいと言っていたが,その内容がmbed.orgのquestionsに並ぶようになった.
その回答の一つ目が非常に難易度が高い(コスト的に).
以前の記事でNUCLEOボードにはEVALUATION BOARD LICENSEが適用されているらしいと言っていたが,その内容がmbed.orgのquestionsに並ぶようになった.
その回答の一つ目が非常に難易度が高い(コスト的に).
ST Nucleo L152REを購入した。
このマイコンボードは Evaluation products licenseなので
そのままボードの商用利用はできないが、このタイプのマイコンのプロトタイプには使用できる。
また信号処理の練習には使用できる。
それがDACを2つ持っているということでPA_4とPA_5の2つを使用。
ところが、このボードはPA_5とLED1が同じポートにつながっているのでLEDを使用したいなら一つしか使用できない。
Arduino UNOでは,そのままHIDとして振る舞い,キーボードにしてしまうことも可能らしいが,まだそこまでできないので...
シリアルポートからデータを受け取り,キー入力のイベントを発生させることにした...
private: System::Void serialPort_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e) {
String^ line;
int countUp = 0;
Generic::List<System::Int32>^ time = gcnew Generic::List<System::Int32>();
do {
try {
line = this->serialPort->ReadLine();
if (countUp == 0 && !line->StartsWith("START")) {
return;
}
if (!line->StartsWith("START") && !line->StartsWith("END")) {
time->Add(Convert::ToInt32(line));
}
countUp++;
} catch (TimeoutException^ /*e*/) {
}
} while (!line->StartsWith("END"));
while (this->keep);
this->OnOffList.Clear();
this->keep = true;
for (int i = 0; i < time->Count; i++) {
this->OnOffList.Add(time[i] < 1000 ? 1 : 0);
}
this->Invoke(gcnew OnRecievedDelegate(this, &remokeyboard::Form1::OnRecieved));
}
delegate System::Void OnRecievedDelegate();
private:
System::DateTime oldTime;
public: System::Void OnRecieved() {
array<System::Boolean>^ stop
= {true,true,true,false,false,false,true,true,false,true,false,false,false,true,true,false,true,true,false,true,false};
array<System::Boolean>^ play
= {true,false,true,true,false,false,true,true,false,true,false,false,false,true,true,false,true,true,false,true,false};
this->textBox1->Text = "";
for (int i = 0; i < this->OnOffList.Count; i++) {
if (i == 0)
this->textBox1->Text = String::Format("{0}", this->OnOffList[i].ToString()->ToLower());
else
this->textBox1->Text = String::Format("{0},{1}", this->textBox1->Text, this->OnOffList[i].ToString()->ToLower());
}
System::Int32 check = 1;
if (stop->Length == this->OnOffList.Count) {
for (int i = 0; i < stop->Length; i++) {
check *= (this->OnOffList[i] == stop[i] ? 1:0);
}
if (check) {
System::Int64 test = (DateTime::Now.ToBinary() - oldTime.ToBinary());
System::Int64 test2 = DateTime(2000000).ToBinary();
if (test > test2) {
keybd_event(0xb2, 0, 0, (System::IntPtr)0);
keybd_event(0xb2, 0, 2, (System::IntPtr)0);
oldTime = DateTime::Now;
}
}
}
check = 1;
if (play->Length == this->OnOffList.Count) {
for (int i = 0; i < play->Length; i++) {
check *= (this->OnOffList[i] == play[i] ? 1:0);
}
if (check) {
System::Int64 test = (DateTime::Now.ToBinary() - oldTime.ToBinary());
System::Int64 test2 = DateTime(2000000).ToBinary();
if (test > test2) {
keybd_event(0xb3, 0, 0, (System::IntPtr)0);
keybd_event(0xb3, 0, 2, (System::IntPtr)0);
oldTime = DateTime::Now;
}
}
}
this->keep = false;
}
SONYのリモコンに対応しつつ,それ以外の物にも対応するコード.
#define NUM_LIMIT 80
const int pin = 8; // 赤外線リモコン受信モジュール
const int led = 13; // 表示器
unsigned long dura[NUM_LIMIT];
void setup () {
pinMode(pin, INPUT);
pinMode(led, OUTPUT);
Serial.begin(115200*2); // 115200*34までは問題なさそう
digitalWrite(led, LOW);
}
void loop () {
int mode;
int anti_mode;
char str[64];
unsigned long duration;
int time0 = 0;
int time1 = 0;
int sonyMode = 1;
// 格納場所を0で埋めておく
for (int i = 0; i < NUM_LIMIT; i++)
dura[i] = 0;
mode = HIGH; // 使用モジュールに合わせて設定(負論理: HIGH)
anti_mode = LOW;
int i = 0;
// pinがLOWになるまで待機する.
while(digitalRead(pin) == mode);
time0 = micros();
// pinがHIGHになるまで待機する.
while(digitalRead(pin) == anti_mode);
time1 = micros();
dura[i] = time1 - time0;
if (dura[i] < 2750) {
sonyMode = 1;
do {
// 次にくるLOWのパルスの幅を測る(?s)
duration = pulseIn(pin, anti_mode, 4200);
// duration = 0: タイムアウト
if (duration == 0) {
// とりあえず何か値を入れる
dura[i] = 4200;
} else {
// 測った時間を格納する
dura[i] = duration;
}
// カウントアップ
i++;
} while (duration != 0 && i < NUM_LIMIT);
} else {
// pinがLOWになるまで待機する.
while(digitalRead(pin) == mode);
dura[i] = micros() - time1;
i++;
sonyMode = 0;
do {
// 次にくるHIGHのパルス幅を測る(?s)
duration = pulseIn(pin, mode, 18500);
// duration = 0: タイムアウト
if (duration == 0) {
// とりあえず何か値を入れる
dura[i] = 20000;
} else {
// 測った時間を格納する
dura[i] = duration;
}
// カウントアップ
i++;
} while (duration != 0 && i < NUM_LIMIT);
}
// どこまで値を埋めたのかを確認する.
int count = 0;
for (count = 0; i < NUM_LIMIT && dura[count] != 0; count++);
// データ送信開始の合図の内容作成
if (sonyMode == 1)
sprintf(str, "START: %03d", count);
else
sprintf(str, "START: %03d NOT_SONY", count);
// データ送信開始の合図送信
Serial.println(str);
// データ送信
for (int i = 0; i < count; i++) {
sprintf(str, "%05d", dura[i]);
Serial.println(str);
}
// データ送信終了の合図送信
Serial.println("END");
}
先のサンプルは,SONYのリモコンでは使えなかった.
SONYの聞きについて来るリモコンについては,次のようにすると良いらしい.
#define NUM_LIMIT 80
const int pin = 8; // 赤外線リモコン受信モジュール
const int led = 13; // 表示器
unsigned long dura[NUM_LIMIT];
void setup () {
pinMode(pin, INPUT);
pinMode(led, OUTPUT);
Serial.begin(115200*2); // 115200*34までは問題なさそう
digitalWrite(led, LOW);
}
void loop () {
int mode;
int anti_mode;
char str[64];
unsigned long duration;
// 格納場所を0で埋めておく
for (int i = 0; i < NUM_LIMIT; i++)
dura[i] = 0;
mode = HIGH; // 使用モジュールに合わせて設定(負論理: HIGH)
anti_mode = LOW;
int i = 0;
// pinが最初にLOWになるで待機する.
while(digitalRead(pin) == mode);
do {
// 次にHIGHLOWになるまで測る(?s)
duration = pulseIn(pin, anti_mode, 4200);
// duration = 0: タイムアウト
if (duration == 0) {
// とりあえず何か値を入れる
dura[i] = 4200;
} else {
// 測った時間を格納する
dura[i] = duration;
}
// カウントアップ
i++;
} while (duration != 0 && i < NUM_LIMIT);
// どこまで値を埋めたのかを確認する.
int count = 0;
for (count = 0; i < NUM_LIMIT && dura[count] != 0; count++);
// データ送信開始の合図の内容作成
sprintf(str, "START: %03d", count);
// データ送信開始の合図送信
Serial.println(str);
// データ送信
for (int i = 0; i < count; i++) {
sprintf(str, "%05d", dura[i]);
Serial.println(str);
}
// データ送信終了の合図送信
Serial.println("END");
}