2018年4月28日土曜日

DigisparkのUSB-Serial通信での奮闘記

世間では、Win7時代に流行ったようですが
マーティーは今頃、Digisparkにハマっています。

Digisparkでは、USBでのSerial通信に標準の「Serial.print」は、使えません。
コンパイルと書き込みはエラーがでないのですが
正規のUSBではなく、V-USBなので、WindowsにCOMポートができないのです。

Digisparkのボードマネージャーをインストールすると
[スケッチの例]-[DigisparkCDC]の[CDC_LED]は、
シリアルモニタから「0」「1」を入力すると
Digispark上のLEDをON/OFFさせるものです。
SerialUSB コマンドが使われています。
*****
#include <DigiCDC.h>
void setup() {                
  // initialize the digital pin as an output.
  SerialUSB.begin(); 
  pinMode(1,OUTPUT);
}

// the loop routine runs over and over again forever:
void loop() {
  
  //turns led on and off based on sending 0 or 1 from serial terminal
  if (SerialUSB.available()) {
    char input = SerialUSB.read();
    if(input == '0')
      digitalWrite(1,LOW);
    else if(input == '1')
      digitalWrite(1,HIGH);
      
  }
  
   SerialUSB.delay(100);               // keep usb alive // can alos use SerialUSB.refresh();
}
*****
で、コンパイルと書き込みはエラーはでず完了します。
が、抜き挿ししても「USBデバイスが認識できません」とでて
デバイスマネージャーには、
「不明なUSBデバイス(無効な構成記述子)」がでてきます。
Baudrateを入れないといけないのかな?
「Serial.begin(9600);」
と、やってみますが、この様にコンパイルエラーになるのです。
「#include <DigiCDC.h>」の下では、Baudrateは指定は、いかんようです。
*****
次のフォルダのライブラリDigisparkCDCを使用中:C:\Users\marty\AppData\Local\Arduino15\packages\digistump\hardware\avr\1.6.7\libraries\DigisparkCDC (legacy)
exit status 1
ボードDigispark (Default - 16.5mhz)に対するコンパイル時にエラーが発生しました。
*****
結局、元の「Serial.begin();」のままにして
何度かやれば認識してくれるだろうと、
また、USBに抜き挿しを繰り返していると
突然!Windows10がブルーバックになり再起動になりました _| ̄|○
Win10でこれがでるとは、かなり致命的です。
再起不能になるのかヒヤヒヤでしたが、幸い無事、再起動しました。
この方も「DigisparkでUSB経由のシリアル通信が出来ない」ということで
同じ様にブルーバックになってしまっています。
DigisparkのFirmwareを更新されたり、色々手を尽くされていますがダメだとのこと。
動いている方もいるので、WinやArduino IDEのバージョンの違いの原因かもですが
「SerialUSB」コマンドは、怖いので使わない方が無難なようです。

.....その後、USBのSerialライブラリに2種類あることがわかりました。
Echo(PCのシリアルモニタの入力と同じものを返す)のサンプルスケッチが
2種類あり、使っているライブラリが違うのです。

[DigisparlCDC]の「Echo」
ここの「CDC_LED」が先のブルーバックになる怖いやつです。
これは、もうやりません。
もうひとつは、[DigisparkUSB]の「Echo」です。
ブルーバックにならないことだけを祈りつつ、これを試してみます。
スケッチは、これです。
#include <DigiUSB.h> と DigiUSB.begin(); が使われています。
*****
#include <DigiUSB.h>

void setup() {
  DigiUSB.begin();
}

void get_input() {
  int lastRead;
  // when there are no characters to read, or the character isn't a newline
  while (true) { // loop forever
    if (DigiUSB.available()) {
      // something to read
      lastRead = DigiUSB.read();
      DigiUSB.write(lastRead);
      
      if (lastRead == '\n') {
        break; // when we get a newline, break out of loop
      }
    }
    
    // refresh the usb port for 10 milliseconds
    DigiUSB.delay(10);
  }
}

void loop() {
  // print output
  DigiUSB.println("Waiting for input...");
  // get input
  get_input();
}
*****
コンパイルと書き込みは、無地終了。
他のUSBを全部外して挿し直すと
おっ!
デバイスマネージャーに「DigiUSB」ってのが出現しています。
いい兆候です。
デバイスマネージャーには、普通のCOMポートはできていないので
Arduino IDEのシリアルモニタでは、何もできません。

探していると、
ここに情報が、引用させていただきますと
やっぱしそうなのか~
*****
 一応DigiCDCを使えばUSBでの仮想シリアルポートも使えるようだけど
 安定性の問題からDigiUSBに取って代わられてるみたい。
*****
*****
 PC側は専用にツールを作らないといけなかったり。
 一応PythonベースでArduinoのシリアルモニタのように使えるツールも
 公開されてるけど…
*****

その言葉を頼りに更に探すと
ここにDigiUSBのお作法とPythonのツールについてのリンクが!m(_ _)m
そのリンクからGitHubのここに飛んでいき
[Clone or download]から
「DigisparkExamplePrograms-master.zip」をDownloadします。
解凍すると配下の「Python\DigiUSB\windows」フォルダに
monitor.exeがあります。
ようやく準備ができました。
[DigisparkUSB]の「Echo」を書き込んだDigisparkを挿して
この「monitor.exe」を実行すると
「Waiting for input...」がでてきました!
受信成功です!
(Pythonは、この時にAnacondaでパッケージをインストールしています)
[Send to device:]の欄に「1」を入力してENTERすると
「1」が返ってきました。
送信も成功です。
ただ、この[DigisparkUSB]の「Echo」だけをコンパイルした結果は、48%
前回の最後のスクリーンショットのスケッチが77%だったので
組み合わせたスケッチは、100%超えになり、どっちにしろダメですね~
ひょっとしたら、できるかもと
スクリーンショットのスケッチにDiGiUSBのSerial通信を合体させてみました。
*****
#include <DigiUSB.h>
#include <CapacitiveSensor.h>
#include <DigiKeyboard.h>

#define KEY_PRINT_SCREEN 0x46

CapacitiveSensor cs_0_2 = CapacitiveSensor(0,2);
     //2pin:センシング  2-0pin:10MΩ
unsigned long csSum;
int LED_State = LOW;

void setup() {
    DigiUSB.begin();
    pinMode(1, OUTPUT);
}

void loop() {
    CSread();
}

void CSread() {
    long cs = cs_0_2.capacitiveSensor(80);
      //a: Calibration時の読取値からの増分をサンプル数80でサンプリングした合計値
    digitalWrite(1, LOW);
 if (cs > 1000) {
      //b: csが1000を超えるとSerialに数値を出力する
   csSum += cs;
      //csがb(1000)を超えている間は、LOOPする毎にcsSumに加算していく

   DigiUSB.print(cs); 
   DigiUSB.print("\t");
   DigiUSB.println(csSum); 

     if (csSum >= 20000)
      //c: csがb(1000)を超え続けて加算されたcsSumがc(20000)を超えるとTriggerと判定する
        {
         DigiUSB.print("Trigger: ");    //Serialに"Trigger"文字を出力
         DigiUSB.println(csSum);        //Triggerした時のcsSum値をSerialに出力

         digitalWrite(1, HIGH);
         DigiKeyboard.update();
         DigiKeyboard.sendKeyStroke(KEY_PRINT_SCREEN, MOD_GUI_LEFT);
         DigiKeyboard.delay(50); 
         digitalWrite(1, LOW);
          if (csSum > 0) { csSum = 0; } //Triggerしたら一旦csSumをClear(Reset)
            cs_0_2.reset_CS_AutoCal();    //読み取り停止してCalibration実行
        }
        } else {
           csSum = 0;
     //パッドから離れてcsがb(1000)を下回るとcsSumをClear
     //又は、抵抗がなかったり、容量が大き過ぎて読み取りがTimeoutした場合
  }
  DigiKeyboard.delay(10);
  DigiUSB.delay(10);   // refresh the usb port for 10 milliseconds
}
*****
コンパイルでエラーがでます。
結局、「#include <DigiKeyboard.h>」だけでエラーがでるのです。
つまり、DigikeyboardとDigiUSBは、同居できないのですね。
V-USBなので、同時にKeyboardとSerialの両方になるDeviceは作れんのかな~?
マーティーにはこの辺は、よくわかりません。

Digikeyboardを全てコメントアウトして書き込んで「monitor.exe」を起動すると
PythonのMonitorが動作しました。
数値が出るのが、ポツン、ポツン、ポツン、とめちゃくちゃ遅いです。
Pythonが重いからなのか、スケッチで何か抜けているのか???
Baudrateの設定は、できないようで
DigiUSB.begin(9600); にするとコンパイルで怒られます。
monitorにもBaudrateを設定する所はないので固定のようです。
一応、DigiUSBとPythonのMonitorを使えば、
何とかSerial通信できることだけは、確認できました。
Arduino UNO R3ならできるのだろうか?
ちょっと調べてみると、そう簡単にはいかんようです。

HID機能は、UNOのATMega328Pだけでは、実現できないのですね。
UNOでも[USB~Serial変換]にATMega16U2を積んだもので
更にATMega16U2のFirmwareを書き換えないとできないということ。
しかも、COMポートを開けるSerial通信と同時使用はできないらしい。
ATMega16U2付のArduino UNO R3ありましたが
送料含めて US$ 6.92! 今の所、興味はわきませんね~

ATMega32U4を積んだLeonardoやMicroであれば普通に動作するらしいのです。
だからArduino Microは、UNOの2倍近くするんですね~
てっきり小さいからだけだと思ってたら正規のUSB内蔵しているのかあ!
ん~ん、これは、試したくなりました!
これが最安値かな?
本体US$ 3.60、送料 US$ 0.26、合計US$ 3.86をポチって
締め括ることにします^^;

0 件のコメント: