目次


◆プチ情報

・Google Code Prettifyのテスト
・docomo d-01G dtab 分解 電源スイッチ修理
・車のOBDⅡ 端子にELM327を繋いでみた
・最新版 及び 旧版 Raspberry Pi OS
・Raspi で alexa に 室温 を喋らせてみた
・Win10 上 の VMware に macOS 10.15 Catalina のインストールを夢見た。
・Windows10で、削除できないフォルダを削除する
・(Raspi)LinuxでDiskを丸ごとコピーするには
・人感センサー SR501 誤検知防止 について
・RASPI で WiFi to 有線 イーサネットコンバータ を作ってみました。
・RASPI でルーター機能付き WiFi中継器 を作ってみた。
・RASPIの ハードウェア情報 を表示する
・Raspbian Lite( DonkeyCar3 )に デスクトップ環境 をインストール
・Raspberry Pi (donkeycar3) に Python3.8.1 をインストール
・RASPI 3B に FFmpeg 4.x.x をインストール
・ESP32 内蔵 ATOM & ATOM lite が届きました。
・TJBot に ダッシュボード を追加し ブラウザ で 制御 してみた
・RASPI の VNC の 解像度 を変更する
・Raspberry Pi 3B/ZERO の カメラ で撮影した動画をブラウザで視る
・ESP32 (M5StickC) で PS3 の コントローラ を使う
・台風19号 気圧変化 ambient データ
・raspi にて PS3controller を UDP で M5StickC へ接続
・ラズベリーパイ 仮想キーボード 文字化けについて
・M5StickC で UIFLOW を 使かってみる。
・PS3コントローラをBluetoothでつなげる
・aitendo の 8x8 LED の pin 番号 を調べてみた
・BeetleC が 届いた
・WiFiアクセスポイント(Archer C6)の増設
・M5StickC/M5stack用のGROVE互換コネクタ
・R634M パームレフトをカッティングシートで補修
・aitendo ★特売品★LEDランプユニット
・卓上冷風機 の 使用報告
・マイクロUSBの半田付けにUSB電子顕微鏡を使ってみた
・Windows10 pro x64 1903 で、amazon alexa アプリ
・VertualBox VM で 解像度 の 変更
・Raspberry Pi Desktop で「ownCloud」を使う
・Dynabook R634/M SDDの換装(128G->512GB)
・ONKYO Nexterm P305 メモリの増設とSSDの換装方法
・Eee Slate EP121分解ファン清掃
・2.4インチ液晶 108 IN 1 レトロ筐体型ゲーム機
・windows10のアップグレードについて
・ビットコインマイニング用機器(antminer u3)
・ラズベリーパイ3B用のケース
・電流容量の多いUSB3.0対応ハブを購入
・dynabook R634/M RAM +8GB 増設
・ダイソーで、乾電池式のモバイルバッテリー

◆電子工作

・M5Stack で トーキングテスター を 作ってみた(その1)
・メカナムホィール 車を PS3コントローラ で遊んでみた。
・HAT18650CでM5StickCへの簡単書き込みコネクタの製作
・M5StickC で 接触確認アプリ (COCOA) の数を数えてみた。
・M5StickC バランスロボットが立ちました。
・M5StickC MLX90615 赤外線温度センサー で 非接触温度計 を作ってみました。
・M5StickC を使って 倒立振子 を作ってみました。
・自動はんだ吸い取り器 GET
・RASPI 3B にて DonkeyCar 3 を作ってみた
・IBM ボール紙ロボット ( TJBot zero )を作ってみた
・Pch パワー MOSFET ( 2SJ334 ) を使って 自動点灯 スイッチ を作ってみた
・I2C Wemos D1 mini Motor Shield を使かってみた
・ESP32 で懐かしい CP/M を動かす。
・ジョイステック (HP3-185-A) を ESP32 の BLE 対応に改造
・BeetleC を BLE 経由で遊ぶ
・ダイソー スマホ用Bluetoothリモートシャッター改造
・BeetleC を PS3 のコントローラで遊んでみました。
・M5StickC 搭載 web 操縦 リモコンカー
・M5StickC にて、i2c を 2チャンネル 使う
・100均のおもちゃ自動車をBlynkでコントロール
・倒立振子 バランスロボット製作
・M5Stack で ニキシー管 時計 を作ってみました。
・水センサーを使って、Ambientへ雨と土壌の湿度を送ってみた。
・ESP-01用自動書き込み器
・HDMI コントローラ基板の活用(RTD2662)
・「BME280」のアドレス変更(0x77)
・wifi中継器(esp_wifi_repeter)
・外部AC電源アダプタ供給USBコネクタ
・勝手に命名しました装置名「Nenaizo」


◆園芸

・ゴーヤ、トマト、キュウリ、クローバ園芸日誌
・イチゴ/チューリップの植え付け

◆M5Stackを使い音声と7セグ表示で測定値を教えてくれる
 「トーキングテスター」を作ってみました。(その1)

S__44556302



◆測定項目は、ボタンBにて、操作し、
 電圧、電流、抵抗、ロジックを切り替え、
 音声出力と7セグ表示させます。
 その1は、電圧測定のみ)

◆測定モードは、ボタンCにて操作し、
 手動測定、自動測定、リピート測定としました。
 ①手動測定・・・・ ボタンAを押したとき測定し出力。
 ②自動測定・・・・ 値の変化があった時、測定し出力。
 ③リピート測定・・ 3,5,7,15,31秒間隔でリピート測定し出力。

◆ハードは、出来る限りシンプルにしました。
 (その1は、抵抗2本とコンデンサ1個、ピンヘッダ)

1.準備
①まず最初に、M5Stackで喋らせるためには、音声合成機能を準備します。
  下記URLを参考に、導入し、
  サンプル発生までが出来ていること前提としています。
 *デモ版の為、ナ、マ行が「ヌ」と発音します。

 ダウンロード:SampleTTS.zip

②トーキングテスターは、上記「SampleTTS.ino」を改造します。

③M5Stackの標準のアナログ入力を使って、(GPIO36,35,26)
  電圧、電流、抵抗測定及びロジックテスター作ります。

④アナログ入力については、色々誤差などが有り大変でした。

⑤詳しくは、下記URLが大変参考になり、ありがとうございました。


①ADコンバータのアッテネータの設定を選びます。
 ブログのの内容と実際試してみて、「ADC_11db」を選びました。

以下ブログより抜粋(先人の方に感謝です。)
***********************************************************
  //  analogSetAttenuation(ADC_0db); //アッテネーターを設定
  //  analogSetAttenuation(ADC_2_5db);
  //  analogSetAttenuation(ADC_6db);
  //  analogSetAttenuation(ADC_11db);
***********************************************************
  データーシートのリンクがすぐに出てこないのですが、
  ADCのキャリブレーション方法について書いてある資料には、
  誤差が少ない範囲として、
  Atten0 (0dB)は、  100-950mV
  Atten1 (-2.5dB)は、100-1250mV
  Atten2 (-6dB)は、  150-1750mV
  Atten3 (-11dB)は、 150-2450mV
  となっていて、下の方もダメと書いてありましたorz
************************************************************

②上記より電圧測定範囲を1.2V~27V未満としました。

③電圧測定の入力部分は、抵抗分圧で10倍としました。
 手持ち部品の関係で2MΩと220KΩとしましたが、
 出来れば割り切れる1.8MΩと200KΩが良いです。

 入 力◎-----2MΩ----+->GPIO36(ADC)
              l
    GND◎-+-220KΩ--+
               l         l
               +-0.1uF----+-->GND

④AD変換後の電圧値の算出に
  「(float)ad*3.3/4096.0*10.0」
  ・最後の10.0は、入力抵抗の分圧の分です。
  の式を使って測定値を出していましたが、
  テスター値との乖離があまりにもあり、使えませんでした。

⑤採用したのは、大まかな実測値と計算にて電圧値を算出しました。
 結果、ほぼテスターと同じ様な値となりました。
 ・実測は、2V~27Vまで、1V間隔でAD変換値を記録し、vtblという
  配列に保存しました。2V以下は0.1V間隔でltblに保存しました。
 ・基本値は、配列の位置とし、1Vの間は、1V間の差分を10で割り、
  加算しました。

    計算式の概略
   ad=analogRead(AD_IN);
           for (i=0;i<28;i++) {
             if ((vtbl[i]<=ad)&&(ad<vtbl[i+1])) break;
           }
           v2=vtbl[i+1];
           v1=vtbl[i];
           v3=((ad-v1)/((v2-v1)/10.0))/10.0;
          adt=i+v3;

  シリアル出力
   ad=1076 i=10 v1=1060 v2=1182 v3=0.131148 adt=10.13 
   10.13ボルト.

   ad :AD変換値
   adt:測定電圧値(計算結果)

  以上により、ほぼテスター値とほぼ同じくらいの制度となりました。

3.電流測定、抵抗測定、ロジック測定について

  その1は、抵抗2本とコンデンサ1個の簡易版とし
  電圧測定のみとします。

4.測定値の7セグ表示について

①LCDの表示は、7セグメント表示が、かっこいいかなと色々検索してみましたら

    M5.Lcd.drawString("V",140,200,4);
    M5.Lcd.drawString(String(dt,2),x,80,7);     <--の最後の数値を「7」にすることで
                     7セグ表示出来ました。隠しコマンドかな

*ライブラリの使用例ではサイズとなっている。
  M5.Lcd.drawString("文字列", X, Y, {size}) 指定位置に文字列を表示

5.スケッチについて
 
**整理中

以上

 

・来年の春を楽しみにイチゴ/チューリップの植え付けた。

・2020/10/5

S__44539912

S__44539914

S__44539915







下記のコードはGoogle code-prettifyを使ってコードを読みやすくしています。

console.log('Hello World')

※CDNから下記ファイルを読み込んでいます。
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>

行番号を表示



//#define LED 13 //Arduino uno
//#define LED 1  //Attiny85
#define LED 2  //ESP32Devkit / ESP8266 LOLIN D1 mini
//#define LED 22  //WEMOS LOLIN32 Lite

void setup() {
  // put your setup code here, to run once:
  pinMode(LED, OUTPUT);
  
  Serial.begin(115200);
  Serial.println("Program Start");
  for(int i=0;i<10 ;i++) {
    digitalWrite(LED,HIGH);
    delay(200); 
    digitalWrite(LED,LOW);
    delay(200); 
  }

}

void loop() {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  Serial.println("LED On");
  delay(1000);               // wait for a second
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  Serial.println("LED Off");
  delay(1000);               // wait for a second
}


メカナムホィール 車 に M5StickC を搭載し PS3コントローラ で操作し遊んでみた。





◆ブログ内参考
・I2C Wemos D1 mini Motor Shield を使かってみた
・ESP32 (M5StickC) で PS3 の コントローラ を使う


◆全体写真

S__44359708

◆メカナムホィールの動きとPS3コントローラの釦割り当て

4carps3
◆配線略図

配線略図

◆アマゾンで購入
Homyl DIY メカナムホイール 4輪 ロボットカーシャーシ キット STEM知育玩具 Arduino用


◆メカナムホィールを取り付けた所

S__44326927

◆モーターシールドのI2Cアドレスを表示させた所

S__44359711


◆PS3コントローラのバッテりー残量表示させた所

S__44359712






◆スケッチ例(あくまでも参考です。自己責任で)
//PS3コントローラ対応
//2020/8/22 メカナムホイール車用に改修
//http://gijin77.blog.jp/archives/26057910.html

#include <Wire.h>
#include <M5StickC.h>
#include <Ps3Controller.h>
#include "WEMOS_Motor.h"
/*
#define _CCW  1
#define _BK   2
#define _STOP 3
#define _STANDBY 4
*/
#define _FD  1
#define _BK  2

#define BTN_A 37
#define BTN_B 39
#define LED 10

// Global Variables

float vBatt, voltAve=3.7;
int bx=10;
int by=80;
int bw=20;
int bh=64;
int stop_flg=0;
int mrx=0;
int mry=0;
int mlx=0;
int mly=0;
int demoflg=0;
int pwr=50;
int xyoff=50;

int ps3bat; //PS3バッテリー残量

//Motor shield default I2C Address: 0x2F,0x30
//PWM frequency: 1000Hz(1kHz)
Motor MFR(0x2F, _MOTOR_A, 1000); //Motor A FR
Motor MFL(0x2F, _MOTOR_B, 1000); //Motor B FL
Motor MBR(0x30, _MOTOR_A, 1000); //Motor A BR
Motor MBL(0x30, _MOTOR_B, 1000); //Motor B BL

void setup() {
  pinMode(BTN_A, INPUT);
  pinMode(BTN_B, INPUT);
  pinMode(LED, OUTPUT);
  digitalWrite(LED,HIGH);
  Serial.begin(115200);
  M5.begin();
  Wire.begin(0, 26); //SDA,SCL

  Serial.println("プログラム 開始");
  Ps3.begin("D8:A0:1D:58:4E:C6");

  for (int i=0;i<3;i++){
    M5.Lcd.fillScreen(GREEN);
    digitalWrite(LED,LOW);delay(250);
    M5.Lcd.fillScreen(BLACK);
    digitalWrite(LED,HIGH);delay(250);
  }

  M5.Lcd.setRotation( 0 ); //Mycar = 0
  M5.Lcd.setTextFont(1);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);
  M5.Lcd.setCursor(5,0);M5.Lcd.print("Manual");
  dispvbatt();
  face();
}

void loop() {
int rx,ry;
int lx,ly;

  M5.update();
  if ( M5.Axp.GetBtnPress() ) {
    // 電源ボタンを押すとパワーオフ
//      M5.Axp.pwrerOff();
  }
  if ( M5.BtnB.wasReleased() ) {
    // Bボタンを押すとリスタート
      esp_restart();
  }
  if ( M5.BtnA.wasReleased() ) {
    // Aボタンを押すとデモスタート
      demo_a();
  }

  if  (Ps3.isConnected()){
    dispvbatt();
    if (Ps3.data.button.l1){
//      Serial.println("l1 ボタン圧下");
      ps3bat=Ps3.data.status.battery;
      disp3batt(ps3bat);
      lcdout(GREEN,"Manual");
      delay(200);demoflg=0;
    } else if (Ps3.data.button.l2){ //バッテリ表示デモ
//      Serial.println("l2 ボタン圧下");
      for (int i=1;i<6;i++){
        disp3batt(i);
      }
      disp3batt(0xee);
      lcdout(GREEN,"Manual");
      delay(200);demoflg=0;
    } else  if (Ps3.data.button.select ){
//      Serial.println("select ボタン圧下");
      i2cck();
    } else if (Ps3.data.button.triangle){
//      Serial.println("triangle ボタン圧下");
      lcdout(WHITE,"DEMO A");delay(200);demoflg=1;
    } else if (Ps3.data.button.circle){
//      Serial.println("circle ボタン圧下");
      lcdout(WHITE,"DEMO B");delay(200);demoflg=2;
    } else if (Ps3.data.button.cross){
//    Serial.println("cross ボタン圧下");
      lcdout(WHITE,"DEMO C");delay(200);demoflg=3;
    } else if (Ps3.data.button.square){
      lcdout(WHITE,"DEMO D");delay(200);demoflg=4;
//      Serial.println("square ボタン圧下");
    } else if (Ps3.data.button.r3){
//      Serial.println("r3 ボタン圧下"); //デモリセット
      lcdout(GREEN,"Manual");
      delay(200);demoflg=0;
    } else if (Ps3.data.button.start){
//      Serial.println("start ボタン圧下"); //デモスタート
      if      (demoflg==1) demo_a();
      else if (demoflg==2) demo_b();
      else if (demoflg==3) demo_c();
      else if (demoflg==4) demo_d();
    } else if (Ps3.data.button.r1){
//      Serial.println("r1 ボタン圧下");
      lcdout(YELLOW,"pwr 50");
      pwr=50;delay(200);
    } else if (Ps3.data.button.r2){
//      Serial.println("r2 ボタン圧下");
      lcdout(YELLOW,"pwr100");
      pwr=100;delay(200);
    }
    rx=Ps3.data.analog.stick.rx;
    ry=Ps3.data.analog.stick.ry;
    lx=Ps3.data.analog.stick.lx;
    ly=Ps3.data.analog.stick.ly;

    if (abs(rx)<xyoff) rx=0;
    if (abs(ry)<xyoff) ry=0;
    if (abs(lx)<xyoff) lx=0;
    if (abs(ly)<xyoff) ly=0;
    
    rx = map(rx,-128,128,100, -100); // R-JOYSTICK X
    ry = map(ry,-128,128,100, -100); // R-JOYSTICK Y
    lx = map(lx,-128,128,100, -100); // L-JOYSTICK X
    ly = map(ly,-128,128,100, -100); // L-JOYSTICK Y

    if ((rx==0)&&(ry==0)&&(lx==0)&&(ly==0)&&(stop_flg==0)) {
        stop_flg=1;
        drvFR(_STOP,0);
        drvBR(_STOP,0);
        drvFL(_STOP,0);
        drvBL(_STOP,0);
        face();
    } else if ((mrx != rx)||(mry != ry)||(mlx != lx)||(mly != ly)){
      Serial.printf("1 RX=%4d RY=%4d LX=%4d LY=%4d pwrer=%d",rx,ry,lx,ly,pwr);
      Serial.println();
      stop_flg=0;
      BLE_4car(rx,ry,lx,ly);
    }
    mrx=rx;mry=ry;mlx=lx;mly=ly;
  }
  delay(100);
}

void i2cck(){
  int address;
  int error;

  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextSize(1);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("I2C scanning");
  Serial.println("I2C address scanning");
  for(address = 1; address < 127; address++ ) 
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if(error==0)
    {
      M5.Lcd.print(address,HEX);M5.Lcd.print(" ");
      Serial.println(address,HEX);
    }
    else {
      M5.Lcd.print(".");
 //     Serial.println(".");
    }

    delay(10);
  }
  Serial.println("End");
  delay(3000); 
  M5.Lcd.setTextSize(2); 
  M5.Lcd.fillScreen(BLACK);
  lcdout(GREEN,"Manual");
}

void BLE_4car(int rx,int ry,int lx,int ly) {
//int pwr=50;
/*
  +Y
+X  -X
  -Y
*/
  if ((ry> xyoff)&&(rx==0)) { ff(pwr);Serial.print("ff");}//前進
  if ((ry<-xyoff)&&(rx==0)) { bb(pwr);Serial.print("bb");}//後進
  if ((rx<-xyoff)&&(ry==0)) { ll(pwr);Serial.print("ll");}//左横移動
  if ((rx> xyoff)&&(ry==0)) { rr(pwr);Serial.print("rr");}//右横移動
  if ((ry> xyoff)&&(rx> xyoff)) { fr(pwr);Serial.print("fr");}//右前斜め
  if ((ry> xyoff)&&(rx<-xyoff)) { fl(pwr);Serial.print("fl");}//左前斜め
  if ((ry<-xyoff)&&(rx> xyoff)) { br(pwr);Serial.print("br");}//右後斜め
  if ((ry<-xyoff)&&(rx<-xyoff)) { bl(pwr);Serial.print("bl");}//左後斜め
 
  if ((ly> xyoff)&&(lx==0)) { ff(pwr);Serial.print("ff");}//前進
  if ((ly<-xyoff)&&(lx==0)) { bb(pwr);Serial.print("bb");}//後進
  if ((lx<-xyoff)&&(ly==0)) { rcir(pwr);Serial.print("rcir"); }//右旋回
  if ((lx> xyoff)&&(ly==0)) { lcir(pwr);Serial.print("lcir"); }//左旋回
  if ((lx<-xyoff)&&(ly> xyoff)) { ftr(pwr);Serial.print("ftr");} //前右折 Turn right
  if ((lx> xyoff)&&(ly> xyoff)) { ftl(pwr);Serial.print("ftl"); }//前左折 Turn left
  if ((lx<-xyoff)&&(ly<-xyoff)) { btr(pwr);Serial.print("btr"); }//後右折
  if ((lx> xyoff)&&(ly<-xyoff)) { btl(pwr);Serial.print("btl"); }//後左折
  Serial.println(" --> end ");
}

void drvFR(int fb,int po){
int h;
  if (po>bh) h=bh; else h=po;
  MFR.setmotor( fb,po);
  M5.Lcd.fillRect(bx+30, by-bh-2, 40, bh, BLACK);
  if (fb== _BK) {
    M5.Lcd.fillRect(bx+50, by-h-2, bw, h, RED);
  } else {
    M5.Lcd.fillRect(bx+50, by-h-2, bw, h, GREEN);
  }
}
void drvFL(int fb,int po){
int h;
  if (po>bh) h=bh; else h=po;
  MFL.setmotor( fb, po);
  M5.Lcd.fillRect(bx-10, by-bh-2, 40, bh, BLACK);
  if (fb==_BK) {
    M5.Lcd.fillRect(bx, by-h-2, bw, h, RED);
  } else {
    M5.Lcd.fillRect(bx, by-h-2, bw, h, GREEN);
  }
}
void drvBR(int fb,int po){
int h;
  if (po>bh) h=bh; else h=po;
  MBR.setmotor( fb,po);
  M5.Lcd.fillRect(bx+30, by+2, 40, bh, BLACK);
  if (fb== _BK) {
    M5.Lcd.fillRect(bx+50, by+2, bw, h, RED);
  } else {
    M5.Lcd.fillRect(bx+50, by+2, bw, h, GREEN);
  }
}
void drvBL(int fb,int po){
int h;
  if (po>bh) h=bh; else h=po;
  MBL.setmotor( fb, po);
  M5.Lcd.fillRect(bx-10, by+2, 40, bh, BLACK);
  if (fb==_BK) {
    M5.Lcd.fillRect(bx, by+2, bw, h, RED);
  } else {
    M5.Lcd.fillRect(bx, by+2, bw, h, GREEN);
  }
}

void ff(int pwr){//前進
  drvFR( _FD, pwr);
  drvFL( _FD, pwr);
  drvBR( _FD, pwr);
  drvBL( _FD, pwr);
}

void bb(int pwr){//後進
  drvFR( _BK, pwr);
  drvFL( _BK, pwr);
  drvBR( _BK, pwr);
  drvBL( _BK, pwr);
}

void rr(int pwr){//右横移動
  drvFR( _BK, pwr);
  drvFL( _FD, pwr);
  drvBR( _FD, pwr);
  drvBL( _BK, pwr);
}

void ll(int pwr){//左横移動
  drvFR( _FD, pwr);
  drvFL( _BK, pwr);
  drvBR( _BK, pwr);
  drvBL( _FD, pwr);
}

void fr(int pwr){//右前斜め
  drvFR(_STOP,0);
  drvFL( _FD, pwr);
  drvBR( _FD, pwr);
  drvBL(_STOP,0);
}

void fl(int pwr){//左前斜め
  drvFR( _FD, pwr);
  drvFL(_STOP,0);
  drvBR(_STOP,0);
  drvBL( _FD, pwr);
}

void br(int pwr){//右後斜め
  drvFR( _BK, pwr);
  drvFL(_STOP,0);
  drvBR(_STOP,0);
  drvBL( _BK, pwr);
}

void bl(int pwr){//左後斜め
  drvFR(_STOP,0);
  drvFL( _BK, pwr);
  drvBR( _BK, pwr);
  drvBL(_STOP,0);
}

void rcir(int pwr){
  drvFR( _BK, pwr);//右旋回
  drvFL( _FD, pwr);
  drvBR( _BK, pwr);
  drvBL( _FD, pwr);
}

void lcir(int pwr){//左旋回
  drvFR( _FD, pwr);
  drvFL( _BK, pwr);
  drvBR( _FD, pwr);
  drvBL( _BK, pwr);
}

void ftr(int pwr){//前右折
  drvFR(_STOP,0);
  drvFL( _FD, pwr);
  drvBR(_STOP,0);
  drvBL( _FD, pwr);
}

void ftl(int pwr){//前左折
  drvFR( _FD, pwr);
  drvFL(_STOP,0);
  drvBR( _FD, pwr);
  drvBL(_STOP,0);
}

void btr(int pwr){//後右折
  drvFR(_STOP,0);
  drvFL( _BK, pwr);
  drvBR(_STOP,0);
  drvBL( _BK, pwr);
}

void btl(int pwr){//後左折
  drvFR( _BK, pwr);
  drvFL(_STOP,0);
  drvBR( _BK, pwr);
  drvBL(_STOP,0);

}

void mstop(){
  drvFR(_STOP,0);
  drvFL(_STOP,0);
  drvBR(_STOP,0);
  drvBL(_STOP,0);
  face();
  delay(1000);
}

void demo_a(){
int pwr=50;
int wt=1000;

  lcdout(GREEN,"DEMO A");
//前進
  ff(pwr);delay(wt/2);mstop();
//後進
  bb(pwr);delay(wt);mstop(); 
//前進
  ff(pwr);delay(wt/2);mstop();

//右横移動
  rr(pwr);delay(wt/2);mstop();  
//左横移動
  ll(pwr);delay(wt);mstop();
//右横移動
  rr(pwr);delay(wt/2);mstop();  

//右旋回
  rcir(pwr);delay(wt*3);mstop();  
//左旋回
  lcir(pwr);delay(wt*3);mstop();

//右前斜め
  fr(pwr);delay(wt/2);mstop();
//左後斜め
  bl(pwr);delay(wt/2);mstop();
//左前斜め
  fl(pwr);delay(wt/2);mstop();
//右後斜め
  br(pwr);delay(wt/2);mstop();
  demoend();
}

void demo_b() {
int pwr=50;
int wt=1000;
  lcdout(GREEN,"DEMO B");
//前進
  ff(pwr);delay(wt/2);mstop();
//右横移動
  rr(pwr);delay(wt/2);mstop();  
//後進
  bb(pwr);delay(wt);mstop(); 
//左横移動
  ll(pwr);delay(wt);mstop();
//前進
  ff(pwr);delay(wt);mstop();
//右横移動
  rr(pwr);delay(wt/2);mstop();  
//後進
  bb(pwr);delay(wt/2);mstop();      
  demoend();
}

void demo_c(){
int pwr=75;
int wt=700;
  lcdout(GREEN,"DEMO C");
//前進
  ff(pwr);delay(wt);
//右横移動
  rr(pwr);delay(wt);  
//後進
  bb(pwr);delay(wt);
//左横移動
  ll(pwr);delay(wt);
//右横移動
  rr(pwr);delay(wt); 
//前進
  ff(pwr);delay(wt);
//左横移動
  ll(pwr);delay(wt);
//後進
  bb(pwr);delay(wt);

//右前斜め
  fr(pwr);delay(wt/2);
//右旋回
  rcir(pwr);delay(wt*3);
//左旋回
  lcir(pwr);delay(wt*3);
//左後斜め
  bl(pwr);delay(wt/2);
  demoend();
}

void demo_d(){
int pwr=75;
int wt=500;
  lcdout(GREEN,"DEMO D");
 //前進
  ff(pwr);delay(wt);
//右横移動
  rr(pwr);delay(wt);  
//後進
  bb(pwr);delay(wt);
//左横移動
  ll(pwr);delay(wt);
//右横移動
  rr(pwr);delay(wt); 
//前進
  ff(pwr);delay(wt);
//左横移動
  ll(pwr);delay(wt);
//後進
  bb(pwr);delay(wt);

//右前斜め
  fr(pwr);delay(wt/2);
//右旋回
  rcir(pwr);delay(wt*3);
//左旋回
  lcir(pwr);delay(wt*3);
//左後斜め
  bl(pwr);delay(wt/2);
  demoend();
}

void demoend(){
  mstop();
  lcdout(GREEN,"Manual");
  demoflg=0;
}

void lcdout(int col,String msg){
  M5.Lcd.fillRect(0,0,79,32, BLACK);
  M5.Lcd.setCursor(5, 0);
  M5.Lcd.setTextColor(col);
  M5.Lcd.print(msg);
}

void face(){
 int x0=10;
 int y0=40;
 int w0=25;
 int h0=10;
 int col=TFT_ORANGE;
 M5.Lcd.fillRect(x0,y0,w0,h0,col);
 M5.Lcd.fillRect(x0+35,y0,w0,h0,col);
 M5.Lcd.fillCircle(x0+12,y0+25, 7,col);
 M5.Lcd.fillCircle(x0+12,y0+25, 5,BLACK);
 M5.Lcd.fillCircle(x0+48,y0+25, 7,col);
 M5.Lcd.fillCircle(x0+48,y0+25, 5,BLACK);
 M5.Lcd.fillTriangle(x0+30,y0+25, 30,90,50,90,col);
 M5.Lcd.fillRect(20,y0+60,40,15,col);
}

void dispvbatt(){
  vBatt= M5.Axp.GetVbatData() * 1.1 / 1000;
  M5.Lcd.fillRect(0,145,79,32, BLACK);
  M5.Lcd.setCursor(10,145);
  if (vBatt > voltAve) {
     M5.Lcd.setTextColor(GREEN);
  } else{
     M5.Lcd.setTextColor(RED);
  }
  M5.Lcd.printf("%4.2fv ", vBatt);
}

void disp3batt(int p3bt){
 int x0=20;
 int y0=30;
 int w0=40;
 int h0=120;
 int y1=22;
 int x1,w1;
 int i;

// M5.Lcd.fillRect(0,y0,79,h0,BLACK);
 M5.Lcd.fillScreen(BLACK);
 dispvbatt();
 lcdout(GREEN,"PS3Bat");

 x1=x0+1;w1=w0-2;
 if (p3bt==0xEE) {
   for(int j=0;j<6;j++){
     M5.Lcd.fillRect(x1,y0,w1,y1*5,GREEN);
     for(i=0;i<5;i++){
       M5.Lcd.drawRect(x0,y0+y1*i,w0,20,WHITE);
     }
     delay(500);
     M5.Lcd.fillRect(x1,y0,w1,y1*5,BLACK);
     for(i=0;i<5;i++){
       M5.Lcd.drawRect(x0,y0+y1*i,w0,20,WHITE);
     }
     delay(500);
   }
   M5.Lcd.fillScreen(BLACK);
   return;
 }
 i=5-p3bt;
 switch(p3bt){
   case 1:
        M5.Lcd.fillRect(x1,y0+y1*i,w1,20,RED);
        break;
   case 2:
        M5.Lcd.fillRect(x1,y0+y1*i,w1,y1*p3bt,YELLOW);
        break;
   case 3:
        M5.Lcd.fillRect(x1,y0+y1*i,w1,y1*p3bt,YELLOW);
        break;
   case 4:
        M5.Lcd.fillRect(x1,y0+y1*i,w1,y1*p3bt,GREEN);
        break;
   case 5:
        M5.Lcd.fillRect(x1,y0+y1*i,w1,y1*p3bt,GREEN);
        break;
 }
 for(i=0;i<5;i++){
   M5.Lcd.drawRect(x0,y0+y1*i,w0,20,WHITE);
 }
 delay(3000);
// M5.Lcd.fillRect(0,y0,79,h0,BLACK);
 M5.Lcd.fillScreen(BLACK);
}


◆HAT18650CでM5StickCにスケッチを書き込みするのにいちいち取り外すのが面等なので
 そのままで書き込めるようUSB Type-C から MicroBへの変換コネクタを作って内蔵してみました。
 Vbus,D-,D+,GNDの4本を接続しました。

HAT18650C-1


HAT18650C-2



・M5StickC で 接触確認アプリ (COCOA) の数を数えてみた。

◆下記参考URLよりAtom から M5StickCに変更。
◆釦Aでリスタート出来るように追加した。
◆バッテリー電圧の表示を追加した。

◆参考URL
M5 Atom Matrixで新型コロナウイルス接触確認アプリが周囲に何個あるか数えてみる


◆下記は、スーパーでのカウント数です。

4900


◆下記は、自宅にて
S__44122132


◆スケッチ例(cocoaM5StickC.ino)

#include <M5StickC.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

#define LED 10
int scanTime = 4; //BLEスキャン間隔
BLEScan* pBLEScan;

// 接触確認アプリのUUID
const char* uuid = "0000fd6f-0000-1000-8000-00805f9b34fb";
int deviceNum = 999;

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
       if(advertisedDevice.haveServiceUUID()){
            if(strncmp(advertisedDevice.getServiceUUID().toString().c_str(),uuid, 36) == 0){
                int rssi = advertisedDevice.getRSSI();
                Serial.print("RSSI: ");
                Serial.println(rssi);
                Serial.print("ADDR: ");
                Serial.println(advertisedDevice.getAddress().toString().c_str());
                Serial.println("Found!");
                deviceNum++;
            }
        }

    }
};

void disp(){    
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(10,20);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);M5.Lcd.print("COCOA");  
  if (deviceNum>9) M5.Lcd.setCursor(5,60); else M5.Lcd.setCursor(25,60);
  if (deviceNum>99) M5.Lcd.setTextSize(4); else M5.Lcd.setTextSize(6);
  M5.Lcd.setTextColor(WHITE);M5.Lcd.printf("%d", deviceNum);
  M5.Lcd.setCursor(0,120);M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(CYAN);M5.Lcd.printf("BtnA=Restart");  
  M5.Lcd.setCursor(0,140);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);M5.Lcd.printf("Bt%3.1fV\n", M5.Axp.GetBatVoltage());
}

void Task1(void *pvParameters) {
  // loop()内に書くとボタン圧下が取れないのでマルチスレッド化してある
  while(1) {
    deviceNum = 0;
    BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
    disp();
    Serial.print("Devices found: ");
    Serial.println(deviceNum);
    Serial.println("Scan done!");
    pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  }
}

void setup() {
  M5.begin();
  Serial.begin(115200);
  Serial.println("Program Start...");
  pinMode(LED, OUTPUT);
  M5.Lcd.setRotation( 0 );
  M5.Lcd.fillScreen(GREEN);
  for(int i=0;i<3;i++) {
    digitalWrite(LED,LOW);delay(500);
    digitalWrite(LED,HIGH);delay(500);
  }
  disp();
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
  xTaskCreatePinnedToCore(Task1,"Task1", 4096, NULL, 3, NULL, 1);
}

void loop() {
  M5.update();
    if ( M5.BtnA.wasReleased() ) {
    // ボタンを押すとリスタート
      esp_restart();
    }
 }

************************************
*4秒周期の数と電源on(リスタート)からの
 トータルの数を表示するように追加修正


cocoa07074995

◆経過時間追加
S__44171275


◆スケッチ例(cocoaM5StickC_2.ino)
次の項目を追加修正した。
①スタートからのトータル表示
 (マックアドレスをチェックして違うものだけカウント)
②ボタンAでリスタート
③ボタンBで電源OFF
④スタートからの経過時間を表示

#include <M5StickC.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

#define LED 10
int scanTime = 4; //BLEスキャン間隔
BLEScan* pBLEScan;

// 接触確認アプリのUUID
const char* uuid = "0000fd6f-0000-1000-8000-00805f9b34fb";
int deviceNum = 0;
int cocoa = 999;
int skip_flg=0;
int hh=0;
int mm=0;
int ss=0;
unsigned long otime;

char  cocoa_buf[500][18] = {"01:23:45:57:89:ab","40:00:31:92:29:5a","01:23:45:57:89:ab","40:00:31:92:29:5a"};
char  c_buf[18] = "01:23:45:57:89:ab";

class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    void onResult(BLEAdvertisedDevice advertisedDevice) {
       if(advertisedDevice.haveServiceUUID()){
            if(strncmp(advertisedDevice.getServiceUUID().toString().c_str(),uuid, 36) == 0){
                int rssi = advertisedDevice.getRSSI();
                Serial.printf("RSSI: %d \n",rssi);
                strcpy(c_buf, advertisedDevice.getAddress().toString().c_str());
                Serial.printf("ADDR: %s \n",c_buf);
                Serial.println("Found!");
                cocoa++;
                skip_flg=0;
                for(int i=0;i<=deviceNum;i++) {
                  if (strcmp(cocoa_buf[i],c_buf)==0) {
                    skip_flg=1;
                    break;  
                  }
                }
                if (skip_flg==0) {
                  strcpy(cocoa_buf[deviceNum], c_buf);
                  deviceNum++;
                }
            }
        }

    }
};
void jikan(){
  otime = millis()/1000;
  ss=int(otime%60);
  mm=int((otime/60)%60);
  hh=int(otime/3600);
}
void disp(){    
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(10,5);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);M5.Lcd.print("COCOA");  
  if (cocoa>9) M5.Lcd.setCursor(5,40); else M5.Lcd.setCursor(25,40);
  if (cocoa>99) M5.Lcd.setTextSize(4); else M5.Lcd.setTextSize(6);
  M5.Lcd.setTextColor(WHITE);M5.Lcd.printf("%d", cocoa);
  M5.Lcd.setCursor(0,90);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(YELLOW);M5.Lcd.printf("T=%d", deviceNum);
  M5.Lcd.setCursor(0,110);M5.Lcd.setTextSize(1);jikan();
  M5.Lcd.setTextColor(GREEN);M5.Lcd.printf("Time=%02d:%02d:%02d",hh,mm,ss);  
  M5.Lcd.setCursor(0,120);M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(CYAN);M5.Lcd.printf("BtnA=Restart");  
  M5.Lcd.setCursor(0,130);M5.Lcd.setTextSize(1);
  M5.Lcd.setTextColor(CYAN);M5.Lcd.printf("BtnB=PowerOff");  
  M5.Lcd.setCursor(0,146);M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(GREEN);M5.Lcd.printf("Bt%3.1fV\n", M5.Axp.GetBatVoltage());
}

void Task1(void *pvParameters) {
  // loop()内に書くとボタン圧下が取れないのでマルチスレッド化してある
  while(1) {
    cocoa=0;
    BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
    disp();
    Serial.printf("Devices found: %d Total: %d \n",cocoa,deviceNum);
    for (int i = 0; i < deviceNum; i++){
      Serial.printf("%03d=%s \n",i+1,cocoa_buf[i]);
    }
    Serial.println("Scan done!");   
    pBLEScan->clearResults();   // delete results fromBLEScan buffer to release memory
  }
}

void setup() {
  M5.begin();
  Serial.begin(115200);
  Serial.println("Program Start...");
  pinMode(LED, OUTPUT);
  M5.Lcd.setRotation( 0 );
  M5.Lcd.fillScreen(GREEN);
  for(int i=0;i<3;i++) {
    digitalWrite(LED,LOW);delay(500);
    digitalWrite(LED,HIGH);delay(500);
  }
  disp();
  BLEDevice::init("");
  pBLEScan = BLEDevice::getScan(); //create new scan
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
  pBLEScan->setInterval(100);
  pBLEScan->setWindow(99);  // less or equal setInterval value
  xTaskCreatePinnedToCore(Task1,"Task1", 4096, NULL, 3, NULL, 1);
}

void loop() {
  M5.update();
  if ( M5.BtnB.wasReleased() ) {
    // ボタンを押すとパワーオフ
      M5.Axp.PowerOff();
  }
  if ( M5.BtnA.wasReleased() ) {
    // ボタンを押すとリスタート
      esp_restart();
  }
}

・docomo d-01G 電源 が 入らない ジャンク品を入手したので 分解 してみた

◆本体

S__44081218

S__44081216


①下側切り込みにヘラを挿しパネルを開ける

S__44081215


②写真の赤丸のビスを外す。

d01g-01


③上側も同様にパネルを外す。
④写真の赤丸のビスを外す。

d01g-02


⑤液晶の側面にヘラ又は小さいマイナスドライバーなど挿し、
 少しずつ抉って全周のツメを外す。

S__44081212


⑥中のフラットケーブルに気を付けて開ける。

S__44081211


⑦内部の写真


S__44081209

S__44081208


S__44081207

S__44081205


◆電源スイッチ部分

S__44081210

S__44081229


d01g-10


◆パネル部分の分解
①コネクタの外し方

d01g-20


②特殊ビスの位置赤丸部のを外す

d01g-21


③押さえを外した所

d01g-22


④液晶とタッチパネルを分解した所

d01g-23

d01g-24



色々やった結果
◆別のジャンクを入手し、電源スイッチ部分だけを交換したが変化なし。
◆一台は、タッチパネルの不具合だったので分解し、交換した。
◆他のも組み立ててみたら、どういうわけか両方とも治った。


・車の OBDⅡ 端子に ELM327 を繋いでみた。 *説明等はネットよりのコピペです。

◆OBD-II とは?

オン・ボード・ダイアグノーシス(On-board diagnostics; OBD)とは、自動車各部に取り付けられたECU(Electrical Controll Unit)にプログラミングされている自己診断機能である。
On-Board Diagnosticsの頭文字を取って、OBDと略称されている。

1996年以降、アメリカで販売する自動車に取り付けを義務付けられた車両診断を行うための通信、コネクタ規格です。

日本では、2002年ごろから OBD-II コネクタが採用され始め、新型車は2008年、販売継続車は2010年から OBD-II の搭載が義務付けられました。

なお、欧州では2001年から搭載義務化。中国では2006年12月から、韓国では2007年1月から、OBDコネクタがついていない車の販売が禁止されています。

ただし、コネクタが OBD-II でも、さまざまな通信プロトコルがあり、メーカーが独自に採用する通信プロトコルもあるため OBD-II コネクタがあっても、 全ての自動車で同じ機器が使えるわけではありません。

◆取得できる情報(参考)
・回転数[rpm]
・速度[km/h]
・瞬間燃費[m/μℓ]
・水温[℃]
・スロットルポジション
・累積走行距離[m]
・累積燃料消費量[ml]
・燃料カット走行距離[m]
・エコドライブ時間[s]
・走行距離[m]
・最高速度[km/h]
・平均速度[km/h]
・最高回転数[rpm]
・アイドリングストップ時間[s]
・アイドリング時間[s]
・エコスタート回数
・発進停止回数
・燃料消費量[ml]
・走行時間[s]
など


◆下記は、コネクタのピンアサインです。

odb2-pin2

odb2-pin3


◆ELM327とは?
ELM327は、ELM Electronicsというカナダの会社が作ったOBD-IIの通信を簡単に行えるICチップです。 このICチップを搭載した機器が様々な所から発売されています。


今回、下記の製品をアマゾンにて入手しました。
https://www.amazon.co.jp/gp/product/B07RNHZS44/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1

odb-01


◆フタを開けた時の写真

odb-02


◆横から見た写真

odb-03


◆電源12Vに繋いだ時の電流

odb-04


◆コネクタに直刺しするとバッテリーに直結状態となり、車を使っていないときでも
 消費し続け、バッテリーが上がる可能性があります。
 これを防ぐため、アクセサリー電源よりの給電となるよう分岐ケーブルをアマゾンで
 入手し改造しました。
 ■オスコネクタ16番からの配線を切断し、メス側にシュガーライタプラグよりの12Vの
  線を接続しました。

https://www.amazon.co.jp/gp/product/B015CCIDRC/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1


odb-05


◆車(マツダ フレアワゴン)
 ダッシュボート ハンドル左下についていたコネクタ部 写真

odb-11


◆仮に接続した時の写真 (実際は分岐ケーブル経由)

odb-12

◆分岐ケーブル経由での最終設置写真

odb-13


◆IOS版は、WiFi版が必要とのことです。
◆アンドロイド版ODBⅡのソフト
◆Bluetooth対応で、Android端末やPCと接続可能ソフト
 Torque、OBD Info-san!、OBD Driver、Car Gauge、Leaf Spy(e-powerはNG)で動作確認されているみたいです。
 この中の下記の三つを試してみました。

1.Torque
詳しくは、下記URLを参照して下さい。
[今話題]無料自動車アプリ「Torque(トルク)」とは?


odb-21


odb-22

◆ここで、ちょっと走行テストの動画を紹介します。(先人の方)
超小型 OBDⅡ ELM327 取り付け&Torque走行テスト(4分15秒)



2.OBD Info-san! トライアル版(8分間しか使えない) 製品版は、580円
詳しくは、下記URLを参照して下さい。
OBD Info-san! for Android


odb-24

3.OBD Driver
詳しくは、下記URLを参照して下さい。
車愛好者向けの追加メーターアプリ、「OBD Driver Free」無料配布開始


odb-25


◆この製品は、技適が通っていないのではと、推測されます。
 よって、下記のURLを参照して、技適に対応改造するのも良いかと思います。


ELM327技適対応

OBD2の車両情報を活用、スマートフォンアプリケーション用SDKを公開|カーメイト

技適未取得機器の申請がこんなにカンタンに! マイナンバーカードさえあればスグに実験OK UDM米国版で試してみた

技適なしの海外無線デバイスが国内で気軽に試せる時代到来


以上



・ゴーヤ、トマト、キュウリ、クローバ園芸日誌

◆5/11(月) ゴーヤ、トマト 植え付け

S__44048542

S__44048543

S__44048544


◆6/3(水) キュウリ 植え付け

◆6/9(火) 四葉のクローバー 種まき

S__44048536


◆ゴーヤ、キュウリ 6/9現在

S__44048538


◆トマト 6/9現在

S__44048539

◆ゴーヤ 6/12現在


S__44056626


◆ゴーヤ 6/26現在

S__44105735


◆クローバ 6/26現在

S__44105737

◆キュウリ 7/25 収穫 結構良いのが出来た。

S__44236805



・最新版 ラズパイOS Raspberry Pi OS 2020/05/27



・Raspberry Pi Imager Toolを使用してSDカードに書き込みます。





・旧バージョンのダウンロードURL

HTTP

こちらでも3種類は場所が異なります。

with desktop and recommended software(いわゆるフルver)
https://downloads.raspberrypi.org/raspbian_full/images/

with desktop(いわゆる通常ver)

https://downloads.raspberrypi.org/raspbian/images/

Lite
https://downloads.raspberrypi.org/raspbian_lite/images/

FTP

FTPは国内にあるミラーサイトだから速いです。中身は同じです。

with desktop and recommended software
http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian_full/images/

with desktop
http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/

Lite
http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian_lite/images/


・Raspi に BME280 温湿度気圧センサーを付けて alexa に 室温 を喋らせてみました。

 2020/5/17現在のものです。
色々とネットで先人の方達のお知恵をお借りしてやっとできました。
ありがとうございます。プログラムなどは、自己責任でお使いください。





参考URL
Raspberry Pi で温湿度気圧センサを使う
https://qiita.com/yukataoka/items/8f9046587c978e91f689

Alexaに部屋の温度と湿度を教えてもらう



P1
スライド1

P2
スライド2

P3
スライド3

P4
スライド4

P5
スライド5


◆I2C(BME280)関係は、下記URLを参照してセットアップします。

Raspberry Pi で温湿度気圧センサを使う
https://qiita.com/yukataoka/items/8f9046587c978e91f689


P6
スライド6

◆簡易HTTPサーバーコード(~/app/alexa/server.py)
#############################################################
import http.server
server_address = ("", 8000)
handler_class = http.server.CGIHTTPRequestHandler #ハンドラを設定
simple_server = http.server.HTTPServer(server_address, handler_class)
simple_server.serve_forever()

◆indexファイル(~/app/alexa/index.html)
#############################################################
<html>
<body>
  Hello Raspi HTTPServer.
</body>
</html>


P7
スライド7

◆Alexaスキルの応答コード (~/app/alexa/cgi-bin/bme280web.py)
#############################################################
#!/usr/bin/python3
# -*- coding: utf-8 -*-

from smbus2 import SMBus
import time
import json

class Bme280:

    def __init__(self, busNumber=1, i2cAddress=0x76):

        self.bus = SMBus(busNumber)
        self.i2cAddress = i2cAddress
        self.digT = []
        self.digP = []
        self.digH = []
        self.timeFine = 0.0
        self.presRaw  = 0.0
        self.tempRaw  = 0.0
        self.humRaw   = 0.0

        osrsT   = 1         #Temperature oversampling x 1
        osrsP   = 1         #Pressure oversampling x 1
        osrsH   = 1         #Humidity oversampling x 1
        mode    = 3         #Normal mode
        tSb     = 5         #Tstandby 1000ms
        filter  = 0         #Filter off
        spi3wEn = 0         #3-wire SPI Disable

        ctrlMeasReg = (osrsT << 5) | (osrsP << 2) | mode
        configReg   = (tSb << 5) | (filter << 2) | spi3wEn
        ctrlHumReg  = osrsH

        self.writeReg(0xF2,ctrlHumReg)
        self.writeReg(0xF4,ctrlMeasReg)
        self.writeReg(0xF5,configReg)
        self.getCalibParam()

        self.readData()

    def writeReg(self, regAddress, data):
        self.bus.write_byte_data(self.i2cAddress, regAddress, data)

    def getCalibParam(self):
        calib = []

        for i in range (0x88,0x88+24):
            calib.append(self.bus.read_byte_data(self.i2cAddress,i))
        calib.append(self.bus.read_byte_data(self.i2cAddress,0xA1))
        for i in range (0xE1,0xE1+7):
            calib.append(self.bus.read_byte_data(self.i2cAddress,i))

        self.digT.append((calib[1] << 8) | calib[0])
        self.digT.append((calib[3] << 8) | calib[2])
        self.digT.append((calib[5] << 8) | calib[4])
        self.digP.append((calib[7] << 8) | calib[6])
        self.digP.append((calib[9] << 8) | calib[8])
        self.digP.append((calib[11]<< 8) | calib[10])
        self.digP.append((calib[13]<< 8) | calib[12])
        self.digP.append((calib[15]<< 8) | calib[14])
        self.digP.append((calib[17]<< 8) | calib[16])
        self.digP.append((calib[19]<< 8) | calib[18])
        self.digP.append((calib[21]<< 8) | calib[20])
        self.digP.append((calib[23]<< 8) | calib[22])
        self.digH.append( calib[24] )
        self.digH.append((calib[26]<< 8) | calib[25])
        self.digH.append( calib[27] )
        self.digH.append((calib[28]<< 4) | (0x0F & calib[29]))
        self.digH.append((calib[30]<< 4) | ((calib[29] >> 4) & 0x0F))
        self.digH.append( calib[31] )

        for i in range(1,2):
            if self.digT[i] & 0x8000:
                self.digT[i] = (-self.digT[i] ^ 0xFFFF) + 1

        for i in range(1,8):
            if self.digP[i] & 0x8000:
                self.digP[i] = (-self.digP[i] ^ 0xFFFF) + 1

        for i in range(0,6):
            if self.digH[i] & 0x8000:
                self.digH[i] = (-self.digH[i] ^ 0xFFFF) + 1  

    def readData(self):
        data = []
        for i in range (0xF7, 0xF7+8):
            data.append(self.bus.read_byte_data(self.i2cAddress,i))
        self.presRaw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4)
        self.tempRaw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4)
        self.humRaw  = (data[6] << 8)  |  data[7]

    def getPressure(self):
        pressure = 0.0

        v1 = (self.timeFine / 2.0) - 64000.0
        v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * self.digP[5]
        v2 = v2 + ((v1 * self.digP[4]) * 2.0)
        v2 = (v2 / 4.0) + (self.digP[3] * 65536.0)
        v1 = (((self.digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8)  + ((self.digP[1] * v1) / 2.0)) / 262144
        v1 = ((32768 + v1) * self.digP[0]) / 32768

        if v1 == 0:
            return 0
        pressure = ((1048576 - self.presRaw) - (v2 / 4096)) * 3125
        if pressure < 0x80000000:
            pressure = (pressure * 2.0) / v1
        else:
            pressure = (pressure / v1) * 2
        v1 = (self.digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096
        v2 = ((pressure / 4.0) * self.digP[7]) / 8192.0
        pressure = pressure + ((v1 + v2 + self.digP[6]) / 16.0)
        return pressure/100

    def getTemperature(self):
        v1 = (self.tempRaw / 16384.0 - self.digT[0] / 1024.0) * self.digT[1]
        v2 = (self.tempRaw / 131072.0 - self.digT[0] / 8192.0) * (self.tempRaw / 131072.0 - self.digT[0] / 8192.0) * self.digT[2]
        self.timeFine = v1 + v2
        temperature = self.timeFine / 5120.0
        return temperature

    def getHumidity(self):
        varH = self.timeFine - 76800.0
        if varH != 0:
            varH = (self.humRaw - (self.digH[3] * 64.0 + self.digH[4]/16384.0 * varH)) * (self.digH[1] / 65536.0 * (1.0 + self.digH[5] / 67108864.0 * varH * (1.0 + self.digH[2] / 67108864.0 * varH)))
        else:
            return 0
        varH = varH * (1.0 - self.digH[0] * varH / 524288.0)
        if varH > 100.0:
            varH = 100.0
        elif varH < 0.0:
            varH = 0.0
        return varH


temp=20
humi=20
pres=1000

sensor = Bme280()
temp=format(sensor.getTemperature(),'.1f')
humi=format(sensor.getHumidity(),'.1f')
pres=sensor.getPressure()

speak = "現在書斎の室温は{0}度。湿度は{1}パーセント。気圧は{2}ヘクトパスカルです。".format(float(temp), float(humi),int(pres))

resp = {
  "version": "1.0",
  "response": {
    "outputSpeech": {
      "ssml": "<speak>" + speak + "</speak>",
      "type": "SSML"
    },
    "speechletResponse": {
      "outputSpeech": {
      "ssml": "<speak>" + speak + "</speak>"
      },
      "shouldEndSession": True
    }
  },
  "sessionAttributes": {}
}

print("Content-type: application/json\n")
print(json.dumps(resp))
#############################################################

P8
スライド8

◆Webサーバーの起動
$ cd /home/pi/app/alexa
$ python3 server.py


◆Linux (ARM)版をインストール
$ wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip
$ unzip ngrok-stable-linux-arm.zip
$ sudo mv ngrok /usr/local/bin/
$ ngrok version
ngrok version 2.2.8

$ ngrok authtoken (自分の認証トークン((authtoken)

◆ngrokで外部に公開します。
$ ngrok http 8000


P9
スライド9

P10

下記URLを参照し、Alexaスキルを作成します。

◆ngrokのダッシュボードで確認して、スキルのエンドポイントに設定する。


Alexaに部屋の温度と湿度を教えてもらう

◆アレクサ スキル開発

◆Alexa公式 動画シリーズ「Alexa道場」


スライド10


P11
スライド11

おしまい


・Windows10Pro X64上 の VMware に macOS 10.15 Catalina のインストールを夢見た。

(注)下記は、すべて夢の中の出来事です。

catalina1015



1.最初に下記URLを参照してMac OS Sierra10.12.4をインストール


2.次に下記URLを参照してSierra10.12.4上でCatalina10.15の
  インストールDISKを作成後、macOS 10.15 Catalinaをインストール
  出来た。


3.2より簡単にインストールする方法

VMWareで「macOS Catalina」 超簡単なインストール手順編



・Windows10で、削除できないフォルダを削除する



◆LinuxでDiskを丸ごとコピーするには
「ddrescue」というコマンドを使う
$ ddrescue -f -d -r1 -v /dev/sda /dev/sdb



◆linuxでSDのボリューム名を変更するには
「e2label」というコマンドを使う
$ sudo e2label /dev/sda1 /boot



◆GUIでのdisk操作
$ sudo apt install gparted gpart


以前作っていた、バランスロボットをついに立たせることが出来ました。




S__43638798

S__43638800

S__43638801


ハードは、下記のサイトを参考にしました。
M5StickC バランスロボ

ソフトは、下記のサイトを参考にしました。
実質500円&100Stepで作る超簡単「 ゆるメカトロ的 M5StickC 倒立振子」

M5StickCはMadgwickフィルタで倒立振子の夢を見るか?


■スケッチ

#include <M5StickC.h>

//PIDパラメータ調整
#define OFFSET             90.0                    // 重心 後方-←90°→+前方
#define COEF_P             35.0                    // Propotional
#define COEF_I             1.5                     // Integral
#define COEF_D             50.0                    // Differential

//Motor
#define LED_PIN            10                      // 内蔵LED

#define MOTOR_R 0x65 //A0=low, A1=open
#define MOTOR_L 0x63 //A0=high, A1=open


//MPU6886 https://github.com/m5stack/M5StickC/blob/master/src/utility/MPU6886.h
#define MPU6886_AFS        M5.MPU6886.AFS_2G       // Ascale [g]      (±2,4,8,16)
#define MPU6886_GFS        M5.MPU6886.GFS_1000DPS  // Gscale [deg/s]  (±250,500,1000,200)
#define DPS                1000                    // Gscale [deg/s]
#define CALIBRATION_COUNT  1000

//Function
#define min(a,b)           ((a) < (b) ? (a) : (b))
#define max(a,b)           ((a) > (b) ? (a) : (b))

//キャリブレ結果
double offsetX;              //Gyro X
float  base_angle;           //Accl X
//ローテーション結果
float dpsX;                  //Gyro X
float angleX;                //Accl X
//積分
double gyro_angle_x = 0;
float  preInterval  = 0;

// I2Cドライバー
void drvMotor(byte adr, int16_t pwr) { //pwr -255 to 255
  byte dir, st;
  if (pwr < 0) dir = 2;
  else dir =1;
  byte ipower=(byte) (abs(pwr)/4); //
  if (ipower == 0) dir=3; //brake

  //constrain(x, a, b) xがa以上b以下のときはxがそのまま返ります。xがaより小さいときはa、bより大きいときはbが返ります。
  ipower = constrain (ipower, 0, 63);
  st = drv8830read(adr);
  if (st & 1) drv8830write(adr, 0, 0);
  drv8830write(adr, ipower, dir);
}

void drv8830write(byte adr, byte pwm, byte ctrl) {
  Wire.beginTransmission(adr);
  Wire.write(0);
  Wire.write(pwm*4+ctrl);
  Wire.endTransmission(true);
}

int drv8830read(byte adr) {
  Wire.beginTransmission(adr);
  Wire.write(1);
  Wire.endTransmission(false);
  Wire.requestFrom((int)adr, (int)1, (int)1);
  return Wire.read();
}


void setup() {
  //初期化
  M5.begin();
  M5.Lcd.setRotation(1);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("<B-Robot v1>");
  //Motor設定
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, HIGH);

// I2C設定
  Wire.begin(0, 26, 400000); //SDA, SCL
//  Wire.setClock(50000);
  drvMotor(MOTOR_R,0);
  drvMotor(MOTOR_L,0);

  //MPU設定
  M5.MPU6886.Init();
  M5.MPU6886.SetGyroFsr(MPU6886_GFS);
  M5.MPU6886.SetAccelFsr(MPU6886_AFS);
  delay(1000);

  //キャリブレーション
  calibration();
//  base_angle-=1.5;
//  offsetX+=0.6;

  M5.Lcd.setRotation(2);
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 140);
  M5.Lcd.printf("BT%3.1fV\n", M5.Axp.GetBatVoltage());
  face();
}

void loop() {
  static  int   Duty;
  float         power, powerP, powerD;
  static float  powerI = 0;
  double        angle;

  //MPUローテーション
  calcRotation();
  //モーター制御
  angle = angleX;
  M5.Lcd.setCursor(0, 0);
  if ((base_angle>=0)&&(base_angle<=1.0)) {
    M5.Lcd.setTextColor(GREEN);
  } else {
    M5.Lcd.setTextColor(RED);
  }
  M5.Lcd.printf(">%3.1f", base_angle);

  if ((angle - OFFSET > -20) && (angle - OFFSET < 20)) {    // 30度以下だけモーター駆動
    powerP = (angle - OFFSET ) / 90;                        // angle=0~180  → -1~1
    powerI += powerP;
    powerD = dpsX / DPS;                                    // 角速度 → -1~1
    power = powerP * COEF_P + powerI * COEF_I + powerD * COEF_D;
    power = max(-1, min(1, power));                         // -1~1
    //モーター駆動
    Duty = (int)(255* power );
    drvMotor(MOTOR_R,Duty);
    drvMotor(MOTOR_L,Duty);
    digitalWrite(LED_PIN, HIGH);
  } else {                                                  // 転倒したら停止
    drvMotor(MOTOR_R,0);
    drvMotor(MOTOR_L,0);
    powerI = 0;
    digitalWrite(LED_PIN, LOW);
  }
  M5.update();
  if (M5.BtnA.wasReleased()) {
    M5.Lcd.fillScreen(GREEN);
    ESP.restart();
    while (true) ;
  }
}

//キャリブレーション関数
void calibration() {
  float raw_gyro_x, raw_gyro_y, raw_gyro_z;
  float raw_acc_x, raw_acc_y, raw_acc_z;
  float acc_x = 0, acc_y = 0, acc_z = 0;
  offsetX = 0;
  for (int i = 0; i < CALIBRATION_COUNT; i++) {
    M5.MPU6886.getGyroData(&raw_gyro_x, &raw_gyro_y, &raw_gyro_z);
    M5.MPU6886.getAccelData(&raw_acc_x, &raw_acc_y, &raw_acc_z);
    //ベースプログラムとM5StickCの組付け位置の違いによる座標系変換含む
    offsetX += -raw_gyro_x;
    acc_x   += -raw_acc_x;
    acc_y   +=  raw_acc_y;
    acc_z   += -raw_acc_z;
  }
  //gyro offset
  offsetX /= CALIBRATION_COUNT;
  //加速度から角度を算出
  acc_x   /= CALIBRATION_COUNT;
  acc_y   /= CALIBRATION_COUNT;
  acc_z   /= CALIBRATION_COUNT;
  base_angle = (atan2(acc_y, acc_z + abs(acc_x)) * 360 / 2.0 / PI) + 180;
}

//MPUローテーション関数
void calcRotation() {
  float raw_acc_x, raw_acc_y, raw_acc_z, raw_t, raw_gyro_x, raw_gyro_y, raw_gyro_z ;
  float acc_angle_x;
  M5.MPU6886.getGyroData(&raw_gyro_x, &raw_gyro_y, &raw_gyro_z);
  M5.MPU6886.getAccelData(&raw_acc_x, &raw_acc_y, &raw_acc_z);
  //ベースプログラムとM5StickCの組付け位置の違いによる座標系変換
  raw_gyro_x *= -1;
  raw_acc_x  *= -1;
  raw_acc_z  *= -1;
  //
  acc_angle_x = (atan2(raw_acc_y, raw_acc_z + abs(raw_acc_x)) * 360 / 2.0 / PI) + 180;
  dpsX = raw_gyro_x - offsetX;
  //積分
  float now_time = millis();
  float interval = now_time - preInterval;  //前回からの経過時間
  preInterval = now_time;
  gyro_angle_x += dpsX * (interval * 0.000999999);
  //相補フィルター
  angleX = (0.996 * gyro_angle_x) + (0.004 * acc_angle_x) + base_angle;
}

void face(){
 int x0=10;
 int y0=40;
 int w0=25;
 int h0=10;
 int col=TFT_ORANGE;
 M5.Lcd.fillRect(x0,y0,w0,h0,col);
 M5.Lcd.fillRect(x0+35,y0,w0,h0,col);
 M5.Lcd.fillCircle(x0+12,y0+25, 7,col);
 M5.Lcd.fillCircle(x0+12,y0+25, 5,BLACK);
 M5.Lcd.fillCircle(x0+48,y0+25, 7,col);
 M5.Lcd.fillCircle(x0+48,y0+25, 5,BLACK);
 M5.Lcd.fillTriangle(x0+30,y0+25, 30,90,50,90,col);
 M5.Lcd.fillRect(20,y0+60,40,15,col);
}


・最近の新型コロナの影響で非接触型の温度計を作ってみました。
 毎日の体温の目安になるのではと思っています。

■画面の説明
上から
①周囲温度
②ターゲット温度
③MIN,MAX温度
④釦Aを押したときのターゲット温度(Hold)

*釦Bを押すとリスタートし、データをクリア出来ます。


S__43614232


S__43614231


mlx90615


■使用部品
①M5StickC
③ピンヘッダ、ピンソケット(手持ちの部品)


■ライブラリは、下記のものを使いましたが、そのままではエラーが発生しましたので
ヘッダーファイルを編集しました。


下記の三つのファイルを同じフォルダに保存してコンパイルしました。
mlx90615.ino
mlx90615.h
mlx90615.cpp

■スケッチ

//mlx90615.ino

// 2020/03/06 Yoshito Hashiguchi

#include <M5StickC.h>
#include <Wire.h>
#include "mlx90615.h"

MLX90615 mlx;

float maxtemp=0.0;
float mintemp=100.0;
float hold=0.0;
float objtemp=0.0;
float ambitemp=0.0;

void setup() {

  Serial.begin(115200);
  M5.begin();
  M5.Lcd.setRotation(0);
  M5.Lcd.fillScreen(BLACK);

  Wire.begin(0, 26, 400000); //SDA, SCL
  Serial.println("Melexis MLX90615 infra-red temperature sensor");
  Serial.print("Sensor ID number = ");
  Serial.println(mlx.get_id(), HEX);
}

int ct=0;

void loop() {

  M5.update();
  if ( M5.BtnA.wasPressed() ) {
    hold=mlx.get_object_temp();
  }
  if ( M5.BtnB.wasPressed() ) {
    esp_restart();
  }
  ct++;
  if (ct>100) {
    ambitemp=mlx.get_ambient_temp();
    objtemp=mlx.get_object_temp();
    if (mintemp>objtemp) mintemp=objtemp;
    if (maxtemp<objtemp) maxtemp=objtemp;
    M5.Lcd.fillScreen(BLACK);
    M5.Lcd.setCursor(0,0);
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(GREEN); 
    M5.Lcd.printf("ambient temp\n");
    M5.Lcd.setTextSize(3);M5.Lcd.setTextColor(WHITE);   
    M5.Lcd.printf("%3.1f\n",ambitemp);
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(GREEN); 
    M5.Lcd.printf("\nterget  temp\n");
    M5.Lcd.setTextSize(3);M5.Lcd.setTextColor(WHITE);   
    M5.Lcd.printf("%3.1f\n",objtemp);
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(CYAN);  
    M5.Lcd.printf("\nBtnB=Restart\n");
    M5.Lcd.setTextColor(GREEN); 
    M5.Lcd.printf("Battery:%3.1fV\n", M5.Axp.GetBatVoltage());

    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(GREEN);  
    M5.Lcd.printf("\n min   max\n"); 
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(WHITE);   
    M5.Lcd.printf(" %3.1f  %3.1f\n",mintemp,maxtemp);
    
    M5.Lcd.setTextSize(1);M5.Lcd.setTextColor(CYAN);   
    M5.Lcd.printf("\nBtnA = hold\n");
    M5.Lcd.setTextSize(3);M5.Lcd.setTextColor(WHITE);     
    M5.Lcd.printf("%3.1f\n",hold);

 
    ct=0;
  }
  delay(10);
}

■ヘッダーファイル

//mlx90615.h

#ifndef __MLX90615_H__
#define __MLX90615_H__

#include "Wire.h"

// default MLX90615 I2C address
#define MLX90615_I2C_ADDR 0x5B

// ROM - ID number
#define MLX90615_REG_ID_LOW 0x1E
#define MLX90615_REG_ID_HIGH 0x1F
// RAM - ambient temperature register
#define MLX90615_REG_TEMP_AMBIENT 0x26
// RAM - object temperature register 
#define MLX90615_REG_TEMP_OBJECT 0x27

class MLX90615 {
 public:
  MLX90615(uint8_t i2c_addr = MLX90615_I2C_ADDR);
  void begin();
  uint32_t get_id();
  float get_object_temp();
  float get_ambient_temp();

 private:
  uint8_t i2c_addr_;
  uint16_t read_word16(uint8_t reg);
};
#endif // __MLX90615_H__

■C++ソースファイル

//mlx90615.cpp

#include "mlx90615.h"

MLX90615::MLX90615(uint8_t i2c_addr) {
  i2c_addr_ = i2c_addr;
}

void MLX90615::begin() {
  Wire.begin();
}

uint32_t MLX90615::get_id() {
uint32_t id;
id = read_word16(MLX90615_REG_ID_LOW);
id |= (uint32_t)read_word16(MLX90615_REG_ID_HIGH) << 16;
return id;
}

float MLX90615::get_ambient_temp() {
  float temp;
  temp = read_word16(MLX90615_REG_TEMP_AMBIENT) * 0.02 - 273.15;
  return temp;
}

float MLX90615::get_object_temp() {
  float temp;
  temp = read_word16(MLX90615_REG_TEMP_OBJECT) * 0.02 - 273.15;
  return temp;
}

uint16_t MLX90615::read_word16(uint8_t reg) {
  uint16_t data;
  Wire.beginTransmission(i2c_addr_);
  Wire.write(reg);
  Wire.endTransmission(false);
  Wire.requestFrom(i2c_addr_, (uint8_t)3);
  data = Wire.read();       // read low byte
  data |= Wire.read() << 8; // read high byte
  Wire.read(); // read and discard PEC (packet error code)
  return data;
}





・M5StickC FM90 BD6211 バッテリー を使って倒立振子を作ってみました。

■最初M5StickCのバッテリーだけで実験していたのですが、直ぐに切れてしまい
 面倒だったので、バッテリーを積んでみました。









br-1


br-2


■使用部品
①M5StickC
②ギヤードモーター FM90(秋月)
③タイヤ FS90R対応用(秋月)
④フルブリッジドライバ 7V BD6211F-D2(秋月)
⑤SOP8P DIP変換基板(秋月)
⑥バッテリー3.7V 1600mAh(中古モバイルバッテリー部品取り)
 ・バッテリーは、HAT端子に接続
⑦3Dプリンタ作成ケース
⑧その他配線部品等


参考は、下記URL


この中のパラーメータ変更
//PIDパラメータ調整
#define OFFSET 86.0  //91.5=>86.0 // 重心 後方-←90°→+前方
#define COEF_D 55.0 //50  ->55   // Differential

  //キャリブレーション
  calibration();
  base_angle-=1.2; //追加調整
  offsetX+=0.6;          //追加調整


●人感センサー SR501 を使って、ambientにESP32でデータを送っている時、
 人がいないのに検知してしまう事がありました。
 ネットで調べたら、WiFiの電波に反応し、誤検知するみたいとの事。

 よって、センサーをビニルテープで、巻いた後、アルミホイルで巻いて
 電波を遮蔽してみたところ、誤検知が無くなりました。

 S__43491385

sr501誤検知


・raspberry Pi Model 3B 最新版OS 2020-02-05-raspbian-buster-full
  で イーサネットコンバータ を作ってみました。


raspicon

今回のイーサネットコンバータ概要
①raspberry Pi Model 3B
②最新版OS 2020-02-05-raspbian-buster-full.img
③内蔵WiFiをwlan0とする。
④wlan0で、上位WiFiを受け、有線eth0に中継する。
⑤eth0のIPアドレスは、192.168.4.1
⑥DHCPの範囲は、192.168.4.100,192.168.4.200,255.255.255.0,24h
⑦Dnsmesq version 2.80 (dnsmesq -v)
⑧dhcpcd 8.1.2 (dhcpcd --version)

1.ソフトウェアのインストール

 sshしたら、必要なソフトウェアをインストールします。
 以下の順でコマンドを実行。

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install dnsmasq

2.dnsmasqとインストールが終わったら、
 これらのサービスを確認し、起動していたら終了させます。

$ service dhcpcd status
$ service dnsmasq status

$ sudo systemctl stop dnsmasq

3.dhcpの設定

 次に設定ファイルを編集していきます。
 まずはdhcpの設定。

$ sudo nano /etc/dhcpcd.conf

「^w」「^v」で最後の行まで飛び、以下を追加します。

denyinterfaces eth0

 eth0をdhcpの対象から除外します。

「^o」で保存し、「^x」で終了します。

 ではdhcpを再起動させます。

$ sudo service dhcpcd restart


4.dnsmasqの設定

 次はdnsmasqの設定です。
 オリジナルの設定ファイルは、コピーしてバックアップを取っておきます。

$ sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.org
$ sudo nano /etc/dnsmasq.conf

「^w」「^v」で最後の行まで飛び、次の3行を追加します。

server=8.8.8.8
interface=eth0
dhcp-range=192.168.4.100,192.168.4.200,255.255.255.0,24h

dhcp-rangeの設定は、dhcpの時に設定したアドレスと照らし合わせて記入してください。

 同じく「^o」で保存し、「^x」で終了します。

 ここまで来たら、dnsmasqを起動します。

$ sudo systemctl start dnsmasq


起動したことを確認してみます。

$ service dhcpcd status
$ service dnsmasq status

*緑色で active (running) と表示されていればOKです。
 違ってたら、設定ファイルを見直してみて下さい。


5.次に、IP転送の設定をします。

$ sudo nano /etc/sysctl.conf

 次の行を探しコメントを外して保存終了します。

#net.ipv4.ip_forward=1

6.IPマスカレードの設定をします。

 下記コマンドを実行してください。

$ sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
$ sudo iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT  
$ sudo iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT

$ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

7.次に、ラズパイが起動後に自動実行するように下記のファイルに追記します。
 *どうしてもeth0に固定IPアドレスを振ることが出来なかったのでここで
  192.168.4.1の固定アドレスを設定しています。
 *他の方法で、設定できた方は、お教えください。

$ sudo nano /etc/rc.local

 一番下にexit 0とあるので、その上に以下の2行を追加します。

sudo ifconfig eth0 192.168.4.1
iptables-restore < /etc/iptables.ipv4.nat

 追加したら保存して終了。

8.これで設定は終わりです。
最後にRaspberryPiを再起動しましょう。

$ sudo reboot

有線LANにケーブルを接続して、インターネットに接続してみましょう。
めでたしめでたし

9.付録 複数の上位WiFiに自動接続させるために
***********************************************************************
WiFi設定ファイル
$ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP

network={
        ssid="AP-1"
        psk="12345678"
        key_mgmt=WPA-PSK
        priority=6
}
network={
        ssid="AP-2"
        psk="12345678"
        key_mgmt=WPA-PSK
        priority=5
}
network={
        ssid="AP-3"
        psk="12345678"
        key_mgmt=WPA-PSK
        priority=4
}
network={
        ssid="test-ap"
        psk="12345678"
        key_mgmt=WPA-PSK
        priority=3
}

・raspberry Pi Model 3B+  最新版OS 2020-02-05-raspbian-buster-full
  で ルーター機能付き WiFi中継器 を作ってみました。

raspiwifirep

S__43483159


今回の中継器概要
⓪raspberry Pi Model 3B+
①最新版OS 2020-02-05-raspbian-buster-full.img
②中華製格安WiFiドングルを挿してwlan1とする。
③内蔵WiFiをwlan0とする。
④wlan1で、上位WiFiを受け、wlan0に中継する。
⑤wlan0のIPアドレスは、192.168.4.1
⑥DHCPの範囲は、192.168.4.100,192.168.4.200,255.255.255.0,24h
⑦hostapd v2.8-devel (hostapd -v)
⑧Dnsmesq version 2.80 (dnsmesq -v)
⑨dhcpcd 8.1.2 (dhcpcd --version)

1.ソフトウェアのインストール

 sshしたら、必要なソフトウェアをインストールします。
 以下の順でコマンドを実行。

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install dnsmasq hostapd

2.dnsmasqとhostapdのインストールが終わったら、
 これらのサービスを確認し、起動していたら終了させます。

$ service dhcpcd status
$ service dnsmasq status
$ service hostapd status

$ sudo systemctl stop dnsmasq
$ sudo systemctl stop hostapd

3.dhcpの設定

 次に設定ファイルを編集していきます。
 まずはdhcpの設定。

$ sudo nano /etc/dhcpcd.conf

「^w」「^v」で最後の行まで飛び、以下を追加します。

denyinterfaces wlan0

 wlan0をdhcpの対象から除外します。

「^o」で保存し、「^x」で終了します。

 ではdhcpを再起動させます。

$ sudo service dhcpcd restart


4.dnsmasqの設定

 次はdnsmasqの設定です。
 オリジナルの設定ファイルは、コピーしてバックアップを取っておきます。

$ sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.org
$ sudo nano /etc/dnsmasq.conf

「^w」「^v」で最後の行まで飛び、次の3行を追加します。

server=8.8.8.8
interface=wlan0
dhcp-range=192.168.4.100,192.168.4.200,255.255.255.0,24h

dhcp-rangeの設定は、適当に設定しています。

 同じく「^o」で保存し、「^x」で終了します。

5.hostapdの設定
 次はhostapdです。ここでアクセスポイントのSSIDやパスワードを設定していきます。

 まずは設定ファイルの例をコピーし開きます。

$ sudo cp /usr/share/doc/hostapd/examples/hostapd.conf /etc/hostapd/hostapd.conf
$ sudo nano /etc/hostapd/hostapd.conf

 開いたら以下を探して確認及び修正。

interface=wlan0
driver=nl80211
ssid=[SSID]
country_code=JP
hw_mode=g
channel=6
auth_algs=1
ieee80211n=1
wpa=2
wpa_passphrase=[PASS]
wpa_key_mgmt=WPA-PSK
rsn_pairwise=CCMP

 同じく「^o」で保存し、「^x」で終了します。
 相当大きいファイルですので、下記コマンドで比較して変更されていることを再確認します。

$ sudo diff /usr/share/doc/hostapd/examples/hostapd.conf /etc/hostapd/hostapd.conf

 保存して終了したら、この設定ファイルを読むようにhostapdの動作ファイルを書き換えます。

$ sudo nano /etc/default/hostapd

#
#DAEMON_CONF=""

ここの#DAEMON_CONF=""をDAEMON_CONF="/etc/hostapd/hostapd.conf"と書き換えます。


 ここまで来たら、dnsmasqとhostapdを起動します。

$ sudo systemctl start hostapd
$ sudo systemctl start dnsmasq

Failed to start hostapd.service: Unit hostapd.service is masked.
もし、hostapdを起動させようとした時、上記エラーが出た場合、以下の手順でコマンドを実行してください。

$ sudo systemctl unmask hostapd
$ sudo systemctl enable hostapd
$ sudo systemctl start hostapd


$ sudo /usr/sbin/hostapd /etc/hostapd/hostapd.conf


起動したことを確認してみます。

$ service dhcpcd status
$ service dnsmasq status
$ service hostapd status

*緑色で active (running) と表示されていればOKです。
 違ってたら、設定ファイルを見直してみて下さい。


6.次に、IP転送の設定をします。

$ sudo nano /etc/sysctl.conf

 次の行を探しコメントを外して保存終了します。

#net.ipv4.ip_forward=1

7.IPマスカレードの設定をします。

 下記コマンドを実行してください。

$ sudo iptables -t nat -A POSTROUTING -o wlan1 -j MASQUERADE
$ sudo iptables -A FORWARD -i wlan1 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT  
$ sudo iptables -A FORWARD -i wlan0 -o wlan1 -j ACCEPT

$ sudo sh -c "iptables-save > /etc/iptables.ipv4.nat"

8.次に、ラズパイが起動後に自動実行するように下記のファイルに追記します。
 *どうしてもwlan0に固定IPアドレスを振ることが出来なかったのでここで
  192.168.4.1の固定アドレスを設定しています。
 *他の方法で、設定できた方は、お教えください。

$ sudo nano /etc/rc.local

 一番下にexit 0とあるので、その上に以下の2行を追加します。

sudo ifconfig wlan0 192.168.4.1
iptables-restore < /etc/iptables.ipv4.nat

 追加したら保存して終了。

9.これでルーター機能付きWiFi中継器の設定は終わりです。
最後にRaspberryPiを再起動しましょう。

$ sudo reboot

しばらくすると、先程hostapdで設定したSSIDが見えるようになってますので、
設定したパスワードで繋いでみましょう。
めでたしめでたし

10.付録 複数の上位WiFiに自動接続させるために
***********************************************************************
WiFi設定ファイル
$ sudo nano /etc/wpa_supplicant/wpa_supplicant.conf

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP

network={
        ssid="AP-1"
        psk="12345678"
        key_mgmt=WPA-PSK
        priority=6
}
network={
        ssid="AP-2"
        psk="12345678"
        key_mgmt=WPA-PSK
        priority=5
}
network={
        ssid="AP-3"
        psk="12345678"
        key_mgmt=WPA-PSK
        priority=4
}
network={
        ssid="test-ap"
        psk="12345678"
        key_mgmt=WPA-PSK
        priority=3
}


*********************************************************
以上 お疲れ様でした。


遂に手に入れました。年と共に目も手も衰えて来ましたので文明の利器に頼ろうと思いました。
非常に楽に取れます。


S__43474953

Raspberry Pi の ハードウェア情報 などを 表示するコマンドを紹介します。

①基板レイアウトの画像とハードウェア情報とリビジョンコードが表示されます。
$pinout


pinout



下記でリビジョンコードが分かります。

②CPU情報が表示されます。
$cat /proc/cpuinfo


③Model名が表示されます。 
$cat /proc/device-tree/model


④Raspbianのカーネルモジュールのバージョンが表示されます。 
$cat /proc/version


*設定済みRaspberryPi3のイメージ(donkey3_1_tf1_13_1.zip)は、Raspbian Liteが元なので
 デスクトップ環境がありませんでした。
 ちょっとしたファイル操作などが不便でした。
 そこで、デスクトップ環境を簡単にインストール方法を調べてみました。

下記コマンドで、PIXEL GUIをインストール出来ました。

$sudo apt-get install --no-install-recommends xserver-xorg
$sudo apt-get install --no-install-recommends xinit
$sudo apt-get install raspberrypi-ui-mods
$sudo reboot 0

但し、日本語フォントやVNC、テキストエデッタが、このままだと出来ないので、追加設定が必要です。

Raspberry Pi (donkeycar3) に Python3.8.1 をインストール
2020年1月28日時点

$ python3 -V
Python 3.7.3
これを3.8.1にしたいと思います。

 

最初にコンパイルに必要になるライブラリをインストールします。

$ sudo apt update
$ sudo apt upgrade
$ sudo apt install libffi-dev libssl-dev openssl

次にソースコードのダウンロード

$ wget https://www.python.org/ftp/python/3.8.1/Python-3.8.1.tgz

コンパイルしていきます。

$ tar zxvf Python-3.8.1.tgz
$ cd Python-3.8.1
$ ./configure
$ make
$ sudo make install
エラー無くインストールできたらバージョンを確認します。

$ python3 -V
Python 3.8.1
 

続いてpipのアップデートを行います。

$ sudo pip3 install --upgrade pip
$ pip3 --version
pip 20.0.2 from /usr/local/lib/python3.8/site-packages/pip (python 3.8)

注)仮想環境では、まだ3.7.3のままでした。後日解明したいと思います。

ドンキーカーで動画を作成するために RASPI 3B に FFmpeg 4.x.x をインストールしました。

①インストール前に、アップデートを実行しておきます。

$ sudo apt update
$ sudo apt upgrade

②FFmpegを入手します。

$ cd ~
$ git clone https://github.com/FFmpeg/FFmpeg.git

③オプション設定を変更します。

$ cd FFmpeg
$ ./configure -–enable-gpl  --enable-nonfree -–enable-omx -–enable-omx-rpi

④コンパイルします。

$ make(非常に時間がかかります)

⑤インストールします。

$ sudo make install


*これでインストール完了です。


自動走行するラジコンカー DonkeyCar 3 を作成途中ですの備忘録を順次残しておきます。

参考URL:FaBo DonkeyCar Docs(1.DonkeyCar3の構築)


1.まずラズパイのイメージを作成します。
 すでにDonkeyCar3の入ったイメージファイルを下記よりダウンロードします。 
  donkey3_1_tf1_13_1.zip 

 ①ダウンロードしたをRaspberry Piのイメージを解凍し、microSDカードに焼き込みます。
 ②焼き込みが、終わったら、一回抜いて、再度挿入し、下記の内容のWiFi設定ファイル 「wpa_supplicant.conf」をテキストエデッタで作成しセーブします。


country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="your network name" <---ここにSSID
    psk="your password"       <---ここにパスワード
    scan_ssid=1
}

 ③出来たら、SDカードをDonkeyCarのRaspPi3に挿入し、電源をOnにします。
 ④PCよりssh pi@donkeypi.localで繋ぎます。IPアドレスが分かれば、IPアドレスでもOK
 ⑤パスワードは、「raspberry」です。

ーーーー次回



*ATOM & ATOM liteが到着しました。重さは、ATOM 7g lite 5gで小さくて軽いです。
 因みにM5StickCは15gでした。
 
atom

 動画は、IDEにてボードは、M5StickCでAdafruit NeoPixelのデモを書き込んでみました。


https://www.facebook.com/yoshito.hashiguchi/videos/pcb.463929294285763/1841414682656515/?type=3&theater&ifg=1




*TJBotに、ダッシュボード パレットを追加して、LEDやサーボモーター
 音声合成に画像認識を制御できるように追加してみました。

1.ブラウザの画面


tjbot01

2.フローの流れ


tjbot020





*VNCで接続するためにRaspberryPiの解像度を変更するには

1.ディスクトップにて
 *いちごマーク-->設定-->Raspberry Pi の設定-->システム-->解像度の設定 

vnc


2.Raspberry Piには従来のBIOSがないため、通常BIOSを使用して保持および
 設定されるさまざまなシステム構成パラメーターは、「config.txt」という名前
 のテキストファイルに保存されます。

 ①解像度の設定(/boot/config.txtの編集)
 $ sudo nano /boot/config.txt

 ②編集内容
 ファイル内に以下の記述があるので修正します。
 hdmi_force_hotplug=1  <-- これの記述も

 hdmi_group=2
 hdmi_mode=51 <---自分の解像度に合わせて修正

 行頭の#はコメント行であるという意味なので、変更するときには#を削除するか、
 別の行でhdmi_groupとhdmi_modeを定義します。

 下記リンク先のhdmi_group=2の解像度一覧で確認できます。
  RPiconfig


・Raspberry Pi 3B/ZERO の カメラ で撮影した動画をブラウザで視る

下記は、node-redのダッシュボードにストリーム配信しています。
mjpgst



簡単に配信することが出来たので備忘録を書いておきます。

1.RASPIでの作業

 ①インストール(下記のコマンドを順次コピペして実行します)
 $ sudo apt-get install -y cmake libv4l-dev libjpeg-dev imagemagick
 $ git clone https://github.com/jacksonliam/mjpg-streamer.git
 $ cd mjpg-streamer/mjpg-streamer-experimental
 $ make

 ②動画の配信
 標準カメラの場合
  $ ./mjpg_streamer -o "./output_http.so -w ./www" -i "./input_raspicam.so -x 640 -y 480 -fps 30 -q 10"

 USBカメラの場合
  $ ./mjpg_streamer -o "./output_http.so -w ./www" -i "./input_uvc.so -r 800x600 -fps 30"

 ③配信を強制的に止める場合
 $ ps ax         <--プロセスIDを確認
 $ kill -9 1234  <-- -9は、強制終了

2.動画の受信
 ①ブラウザで http://[ラズパイのIP]:8080/ を開くだけです。

参考URL:Raspberry Pi 3 の標準カメラで撮影した動画をブラウザに配信する方法まとめ


3.MJPG Streamerが、起動しない時

pi@raspberrypi:~ $ ./msstart.sh
MJPG Streamer Version: git rev: 501f6362c5afddcfb41055f97ae484252c85c912
 i: fps.............: 30
+++++++++
 i: Starting Camera
mmal: mmal_vc_component_create: failed to create component 'vc.ril.camera' (1:ENOMEM)
mmal: mmal_component_create_core: could not create component 'vc.ril.camera' (1)
error create camera

上記エラーで、MJPG Streamerが、起動できないときのチェック方法

①カメラが有効になっているか確認
$ sudo raspi-config
5 Interfacing Options => P1 Camera => Yes

②カメラを認識しているか確認

pi@raspberrypi:~ $ vcgencmd get_camera 
supported=1 detected=0 <-------------カメラを認識していない

pi@raspberrypi:~ $ ls -al /dev/video* <------ /dev/video0が無い
crw-rw----+ 1 root video 81, 0  1月 21 16:07 /dev/video10
crw-rw----+ 1 root video 81, 1  1月 21 16:07 /dev/video11
crw-rw----+ 1 root video 81, 2  1月 21 16:07 /dev/video12

調べた結果、カメラのコネクタが外れかかっていた。再度差し込み

pi@raspberrypi:~ $ vcgencmd get_camera
supported=1 detected=1 <-------------カメラを認識した

pi@raspberrypi:~ $ ls -al /dev/video*
crw-rw----+ 1 root video 81, 3  1月 21 16:27 /dev/video0 <------ /dev/video0が表示
crw-rw----+ 1 root video 81, 0  1月 21 16:27 /dev/video10
crw-rw----+ 1 root video 81, 1  1月 21 16:27 /dev/video11
crw-rw----+ 1 root video 81, 2  1月 21 16:27 /dev/video12

4.mjpg_streamer の起動用と停止用のシェルスクリプトを書いて簡単に実行できるにした。
 
 ①mjpg_streamer の起動シェル 「msstart.shの内容」

pi@raspberrypi:~ $ cat msstart.sh

#!/bin/sh
if pgrep mjpg_streamer > /dev/null
then
    echo "mjpg_streamer already running"
else
    cd mjpg-streamer/mjpg-streamer-experimental/
    ./mjpg_streamer -o "./output_http.so -w ./www" -i "./input_raspicam.so -rot 270 -x 640 -y 480 -fps 30 -q 10"> /dev/null 2>&1&
    echo "mjpg_streamer started"
fi

 ②mjpg_streamer の停止シェル 「msstop.shの内容」

pi@raspberrypi:~ $ cat msstop.sh

#!/bin/sh
if pgrep mjpg_streamer
then
    kill $(pgrep mjpg_streamer) > /dev/null 2>&1
    echo "mjpg_streamer stopped"
else
    echo "mjpg_streamer not running"
fi

5.カメラの取り付け方により回転したいときのオプション 「-rot」
①ラズパイカメラのオプション指定(google 翻訳済み)

$ ./mjpg_streamer -i "input_raspicam.so --help"

 -------------------------------------------------- -------------
 入力プラグインのヘルプ..:raspicam入力プラグイン
 -------------------------------------------------- -------------
 次のパラメーターをこのプラグインに渡すことができます。

 [-fps | --framerate] ...:ビデオフレームレートの設定、デフォルトは5フレーム/秒
 [-x | --width] ........:フレームキャプチャの幅、デフォルトは640
 [-y | --height] ........:フレームキャプチャの高さ、デフォルトは480
 [-quality] .............:JPEG品質を0〜100に設定、デフォルトは85
 [-usestills] ...........:ビデオモードの代わりに静止モードを使用します
 [-preview] .............:全画面プレビューを有効にします
 [-timestamp] ...........:各フレームのタイムスタンプを取得します

 -sh:画像の鮮明度を設定します(-100〜100)
 -co:画像のコントラストを設定します(-100〜100)
 -br:画像の明るさを設定します(0〜100)
 -sa:画像の彩度を設定します(-100〜100)
 -ISO:キャプチャISOを設定します
 -vs:ビデオの安定化をオンにします
 -ev:EV補正を設定します
 -ex:露出モードを設定します(raspistill notesを参照)
 -awb:AWBモードを設定します(raspistill notesを参照)
 -ifx:画像効果を設定します(raspistill notesを参照)
 -cfx:色効果の設定(U:V)
 -mm:メータリングモードを設定します(raspistill notesを参照)
 -rot:画像の回転を設定します(0-359)
 -stats:各画像の画像統計を計算します(-usestillsのノイズを減らします)
 -drc:ダイナミックレンジ補正レベル(raspistill notesを参照)
 -hf:水平反転を設定します
 -vf:垂直フリップを設定します
 -------------------------------------------------- -------------


②WEBカメラのオプション指定(google 翻訳済み)
 
$ ./mjpg_streamer -i "input_uvc.so --help"

 -------------------------------------------------- -------------
 入力プラグインのヘルプ..:UVC webcam grabber
 -------------------------------------------------- -------------
 次のパラメーターをこのプラグインに渡すことができます。

 [-d | --device] .......:開くビデオデバイス(カメラ)
 [-r | --resolution] ...:ビデオデバイスの解像度、
                          次の文字列のいずれかです。
                          QQVGA QCIF CGA QVGA CIF PAL
                          VGA SVGA XGA HD SXGA UXGA
                          FHD
                          または次のようなカスタム値
                          例:640x480
 [-f | --fps] ..........:1秒あたりのフレーム数
                          (カメラは異なる値に強制される場合があります)
 [-q | --quality] .>....:JPEGエンコーディングの品質を設定します
 [-m | --minimum_size]> .:この制限よりも小さいフレームをドロップします。便利です
                          ウェブカメラが小さなサイズのガベージフレームを生成する場合
                          低照度条件下で発生する可能性があります
 [-e | --every_frame] ..:番号付き以外のすべてのフレームをドロップします
 [-n | --no_dynctrl] ...:Linux-UVCドライバーのdynctrlを初期化しません
 [-l | --led] ..........:LEDを「オン」、「オフ」に切り替え、「点滅」または終了させます
                          値「auto」を使用するドライバー次第
 [-t | --tvnorm] ......:TV-Norm pal、ntscまたはsecamを設定します
 [-u | --uyvy] ........:UYVY形式を使用、デフォルト:MJPEG(より多くのCPUパワーを使用)
 [-y | --yuv] ........:YUV形式を使用、デフォルト:MJPEG(より多くのCPUパワーを使用)
 [-fourcc] ............:FOURCCコーデック「argopt」を使用します。
                          現在サポートされているコーデックは次のとおりです。RGBP
 [-timestamp] ..........:フレームタイムスタンプにシステム時間を入力します
 [-softfps] ............:このfpsを試行して達成するためにフレームをドロップします
                          f音を避けるために、カメラを最大fpsに設定します
 [-timeout] ............:デバイスクエリのタイムアウト(秒)
 [-dv_timings] .........:DVタイミングクエリとイベント処理を有効にします
 -------------------------------------------------- -------------

 オプションのパラメーター(すべてのカメラでサポートされているわけではありません):

 [-br] .................:画像の明るさを設定します(自動または整数)
 [-co] .................:画像のコントラストを設定します(整数)
 [-sh] .................:画像の鮮明度を設定します(整数)
 [-sa] .................:画像の彩度を設定します(整数)
 [-cb] .................:カラーバランスの設定(自動または整数)
 [-wb] .................:ホワイトバランスの設定(自動または整数)
 [-ex] .................:露出を設定します(自動、シャッター優先、絞り優先、または整数)
 [-bk] .................:逆光補正の設定(整数)
 [-rot] ................:画像の回転を設定します(0-359)
 [-hf] .................:水平反転を設定(true / false)
 [-vf] .................:垂直フリップの設定(true / false)
 [-pl] .................:電力線フィルターの設定(無効、50hz、60hz、自動)
 [-gain] ...............:ゲインの設定(自動または整数)
 [-cagc] ...............:クロマゲインコントロールの設定(自動または整数)
 -------------------------------------------------- -------------


・IBM Watson が提供するプログラム可能なボール紙ロボット TJBot を作ってみました。

 完成後の写真(左右逆となっている)

S__43261962


S__43261964


・下記URLに作り方が、出ています。

1.まず、厚紙の型を作る必要があったので、型のPDFデータをダウンロードします。
 ①原紙がB4の為、私の持っているA4プリンタで印刷できない事から、A4二枚に半分に
  分け、PDF出力後、A4の紙に印刷しました。
 ②それを写真の工作用紙に貼り付け、カッターでカットしていきました。
 ③カラー用紙の裏面に張り付けたため、完成時、逆の物となりました。

 100均Candoで購入

S__43261968

S__43261967


2.インストールガイドを参照しながらインストールしていきましたが、二年前のガイドだったので所々うまくインストール出来無かったので、ここに現時点でのやり方を書いておきます。
 ①まず、最新版のイメージをダウンロードし、SDカードに書き込みます。
 ②環境を日本語にし、WiFiに接続します。
 ③ガイド「3.4.4 OS と Node-RED の更新」 の手順通りOSをアップデートします。

 $ sudo apt-get update
 $ sudo apt-get upgrade
 $ sudo apt-get dist-upgrade
 $ update-nodejs-and-nodered <---が、うまくいかない。

 ④node-red関係のアップデートが、ガイドのやり方でうまくいかず、
  下記URLを参考に次のコマンドでアップデートしました。

  $ bash <(curl -sL https://raw.githubusercontent.com/node-red/raspbian-deb-
   package/master/resources/update-nodejs-and-nodered)
 
 ■参考URL:Raspberry Pi のNode-REDをアップデートorインストールする方法


 ⑤ガイド「3.5 Node-RED に必要なモジュールを追加する」
  をガイドにそって実行します。

    *コピペ用に記載します。
$sudo npm --unsafe-perm -g install node-red-node-watson node-red-contrib-camerapi
$sudo reboot 

 ⑥ガイド 「3.6 オーディオとカメラの設定」
  をガイドにそって実行します。

    *コピペ用に記載します。
$sudo nano /boot/config.txt
dtoverlay=pwm-2chan,pin=18,func=2,pin2=13,func2=4

$amixer -D hw:1 sset Mic 100% 
$amixer -c0 sset PCM 100% unmute

 *オーディオの再生確認用
$speaker-test -t sine -f 600
$aplay /usr/share/sounds/alsa/Front_Center.wav

 *音が出なかった時など、下記を参考にしました。
   Raspberry Pi で再生と録音を行う


 ⑦ガイド「5. Watson とつないだフローを動かす」
  ここから、ガイドには、「ユーザー名」と「パスワード」を入力するように
  有りますが、IBM Cloud のダッシュボードの中に見つかりませんでした。
  色々試したところ、この二つは、ブランクで、APIKeyの入力が必要でした。
  これで、動くことが分かりました。

注)サンプルの中のvisual.json(画像認識)の顔認識でエラーが出て実行できません。
  原因は、 昨年途中からWatson VRの顔認証機能が廃止されたようです。

3.TJBotを電源ON(起動)した時や、リブートした時、node-redに接続するタイミング
 を把握するために、緑のLEDを点灯させ、IPアドレスをスピーカーから発生してくれ
 るようにしてみました。

 ①まず下記URLを参照して日本語音声合成をインストールする。

 ②次に下記シェルスクリプトを作成する。(コピペする)

pi@raspberrypi:~ $ sudo nano jtalk.sh

#!/bin/sh
TMP=/tmp/jsay.wav
echo "$1" | open_jtalk \
-m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice \
-x /var/lib/mecab/dic/open-jtalk/naist-jdic \
-ow $TMP && \
aplay --quiet $TMP
rm -f $TMP

 ③実行権を設定する。
pi@raspberrypi:~ $ sudo chmod +x jtalk.sh

 ④次にIPアドレスを取得し、音声案内と緑のLEDを点灯させる下記、
  自動実行シェルスクリプトを作成する。

pi@raspberrypi:~ $ sudo nano autorun.sh

#!/bin/sh
ipadd=""
while [ "$ipadd" = "" ]
do
    ipadd=`ip a show wlan0 | grep "inet " | cut -f6 -d ' ' | cut -d '/' -f1`
    wait 1
done
gpio -g mode 23 out
gpio -g write 23 1
rtn=`/home/pi/jtalk.sh IPアドレスは${ipadd}です`


 ⑤実行権を設定する。
pi@raspberrypi:~ $ sudo chmod +x autorun.sh


 ⑥最後に、起動時に自動実行するように「/etc/rc.local」の「exit 0」の前に追記する。

pi@raspberrypi:~ $ sudo nano /etc/rc.local

#!/bin/sh -e
.
.
sh /home/pi/autorun.sh & <---この行を追記する。

exit 0

 以上で起動時にIPアドレスを教えてくれる。


4.これから、色々プログラムして行きたいと思います。

 以上

・Pch パワーMOSFET (2SJ334) を使って 暗くなるとスイッチが入る ハイサイド・スイッチ を作ってみた。

 *一応仕様としては、5V~24V 5A程度と考えています。
 *2SJ334の規格は、60V 30A

①回路図を下記に示します。
mosfetsw
②タッパーの中に組み入れてみました。

mosfet

・I2C Wemos D1 mini Motor Shield 使かってみた

・ESP32 (M5Stack) で 安価な I2C モータードライバ を使ってみました。
 *Wemos D1 mini Motor Shield (i2c interface, TB6612 based) 


msr1


1.安価なのは良いのですが、そのままではM5STACKで認識しない事がわかりました。
 よって、Motor Shieldのファームウェアの再プログラミングが、必要な事が分かりました。

 次からの説明は、Windows10 x64で実行した物です。

2.最初に下記より書き込みツールをダウンロードします。
 STシリアルブートローダーを使用したSTM32用のオープンソースフラッシュプログラム
 (stm32flash.exe)

3.次にバイナリファイルを下記よりダウンロードします。
 *書き換えにより、アドレス設定用のランドは、無効となります。
 標準のものは、I2Cアドレスが、「0x30」に固定の為、複数枚使う場合は、アドレスごと(アドレス0x2d、0x2e、0x2f、0x30)にコンパイルされたファームウェアが、必要です。
 下記は、4つの異なるアドレスのファームウェアファイルを含んだzipファイルです。
https://github.com/pbugalski/wemos_motor_shield/files/1434679/motor_shield_XX_bin.zip

4.2,3のファイルを同じフォルダに解凍、展開しておきます。

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2019/12/19  10:26             3,116 motor_shield.bin
2017/11/02  00:39             3,104 motor_shield_2D.bin
2017/11/02  00:39             3,104 motor_shield_2E.bin
2017/11/02  00:39             3,104 motor_shield_2F.bin
2017/11/02  00:39             3,104 motor_shield_30.bin
2016/02/11  23:44               280 README.txt
2016/02/11  22:04            13,265 stm32flash-manual.pdf
2016/02/10  17:14           252,776 stm32flash.exe
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

5.Motor Shield に書き込むための前準備をします。
 ① Wemos D1 Miniを使う場合

 ①-1  空のスケッチをD1 Miniにアップロードします。これにより、シリアルデータがUSBポートからMotor Shield に、D1 Miniを経由して渡されます。

空のスケッチ:
//------------------------------------------------------------------------
void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}
//------------------------------------------------------------------------

 ①-2 D1 Miniとの結線
 *下記の写真のように結線します。
 *Motor Shield を書き込みモードにするためにRTSは、3vに結線します。

S__43188227


 ② USB-SERIALインターフェースを使う場合
 
 *下記の写真のように結線します。
 *Motor Shield を書き込みモードにするためにRTSは、3vに結線します。

S__43196430


参考:Motor Shield Rev.1.0.0 回路図
motorshieldRev1

 
 ③次のコマンドを実行します。
  重要:COM6を自分のCOMポート番号に置き換えて下さい。 
  *COMポートをデバイスマネージャにて確認


1>C:\motorshield\stm32flash-0.5-win64>stm32flash.exe COM6
*ボードを認識しているか確認します。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
stm32flash 0.5

http://stm32flash.sourceforge.net/

Interface serial_w32: 57600 8E1
Version      : 0x31
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0444 (STM32F03xx4/6)
- RAM        : 4KiB  (2048b reserved by bootloader)
- Flash      : 32KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 3KiB
-------------------------------------------------------------------------------------

2>C:\motorshield\stm32flash-0.5-win64>stm32flash.exe -k COM6
*これにより、シールドのロックが解除されます。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
stm32flash 0.5

http://stm32flash.sourceforge.net/

Interface serial_w32: 57600 8E1
Version      : 0x31
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0444 (STM32F03xx4/6)
- RAM        : 4KiB  (2048b reserved by bootloader)
- Flash      : 32KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 3KiB
Read-UnProtecting flash
Done.
-------------------------------------------------------------------------------------

3>C:\motorshield\stm32flash-0.5-win64>dir
*ファイル名の確認
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ドライブ C のボリューム ラベルは S3SDD00-960 です
 ボリューム シリアル番号は 44C7-1584 です

 C:\motorshield\stm32flash-0.5-win64 のディレクトリ

2020/01/04  13:17    <DIR>          .
2020/01/04  13:17    <DIR>          ..
2019/12/19  10:26             3,116 motor_shield.bin
2017/11/02  00:39             3,104 motor_shield_2D.bin
2017/11/02  00:39             3,104 motor_shield_2E.bin
2017/11/02  00:39             3,104 motor_shield_2F.bin
2017/11/02  00:39             3,104 motor_shield_30.bin
2016/02/11  23:44               280 README.txt
2016/02/11  22:04            13,265 stm32flash-manual.pdf
2016/02/10  17:14           252,776 stm32flash.exe
2020/01/04  13:17                56 wemos_motor_shield.txt
               9 個のファイル             281,909 バイト
               2 個のディレクトリ  492,288,159,744 バイトの空き領域
-------------------------------------------------------------------------------------

4>C:\motorshield\stm32flash-0.5-win64>stm32flash.exe -f -v -w motor_shield_2F.bin COM6
*ここで希望のI2cアドレスのファイルを、書き込みます(例では「0x2F」)。
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
stm32flash 0.5

http://stm32flash.sourceforge.net/

Using Parser : Raw BINARY
Interface serial_w32: 57600 8E1
Version      : 0x31
Option 1     : 0x00
Option 2     : 0x00
Device ID    : 0x0444 (STM32F03xx4/6)
- RAM        : 4KiB  (2048b reserved by bootloader)
- Flash      : 32KiB (size first sector: 4x1024)
- Option RAM : 16b
- System RAM : 3KiB
Write to memory
Erasing memory
Wrote and verified address 0x08000c20 (100.00%) Done.
-------------------------------------------------------------------------------------


6.書き込みが終わったら、配線をM5Stackに繋ぎ変え、I2Cで認識するか確認します。

*「0x2F」「0x30」として、認識しています。

S__43188229

確認用のスケッチ:
//------------------------------------------------------------------------

#include <M5Stack.h>

void setup() 
{
  M5.Lcd.begin();
  M5.Lcd.setRotation(1);
  M5.Lcd.fillScreen( BLACK );
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.setTextColor(YELLOW);  
  M5.Lcd.setTextSize(3);

  M5.Lcd.fillScreen( BLACK );
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("M5Stack I2C Tester");
    
  Wire.begin();

  delay(3000);
  M5.Lcd.fillScreen( BLACK );
}

int textColor=YELLOW;

void loop() 
{
  int address;
  int error;
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.println("scanning Address [HEX]");
  
  for(address = 1; address < 127; address++ ) 
  {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    if(error==0)
    {
      M5.Lcd.print(address,HEX);M5.Lcd.print(" ");
    }
    else M5.Lcd.print(".");

    delay(10);
  }

  if(textColor==YELLOW) textColor=GREEN;
  else textColor=YELLOW;
  M5.Lcd.setTextColor(textColor,BLACK);
  delay(5000);  
}
//------------------------------------------------------------------------

 
7.ライブラリは、下記よりダウンロードします。
 Wemos D1ミニモーターシールド(i2cインターフェイス、TB6612ベース)用のArduinoライブラリ。

参考URL:モーターシールドの再プログラミング


ESP32で懐かしいCP/Mを動かしてみました。

①ESP32でVGA出力が、出来て、PS2のキーボードとマウスが使えました。
 (USB-PS2変換コネクタ経由のUSBマウスは、使えませんでした。)
②CP/Mの中にあったMBASICを久しぶりに動かしてみました。
③インベーダーゲームも懐かしく出来ました。

ライブラリは、下記URLよりダウンロードできます。
https://github.com/fdivitto/fabgl?fbclid=IwAR13n8KkWvauuTyDwfkfc8cty6OnW5jge6WlB1tMEiuNtNm7l6CjAcc_jfg


CP/Mの起動画面

S__43139082


・懐かしのインベーダーゲームも出来ちゃいます。

S__43147266


・修正版回路図
元図の中に、手持ちの抵抗値が無かったので、朱書きの値の物を使いました。
400Ω --> 390Ω
800Ω --> 820Ω
2KΩ ---> 2.2KΩ

ESP32_VGA



・元の回路図


schema





ついに、ArduinoIDE1.8.10 の開発環境にて ESP32(M5STickC)でPS3のコントローラを使う事が出来たので備忘録として残しておく事にしました。

ps3_car


はじめに
PS3のコントローラは、接続先(ESP32)のBluetoothのMac Addressを記憶しなくては、なりません。

1.ESP32のBluetoothのMac Addressを調べるため、下記のスケッチを書き込み、メモしておきます。

BTmacadrs.ino
//*****************************************************
void setup(void) {
  Serial.begin(115200);
  Serial.println("-----------------------------");
  uint8_t btmac[6];
  esp_read_mac(btmac, ESP_MAC_BT);
  Serial.printf("[Bluetooth] Mac Address = %02X:%02X:%02X:%02X:%02X:%02X\r\n", btmac[0], btmac[1], btmac[2], btmac[3], btmac[4], btmac[5]);
}

void loop() {
}
//*****************************************************


*実行例

ps3-01


2.PS3のコントローラに、Mac Addressを記憶させるために下記のソフトを使って記憶させます。
Windows用

SixaxisPairTool
  <-ここでダウンロード出来ます。2020/8/24


①PS3コントローラをMiniUSBケーブルでPCに繋ぎます
②SixaxisPairToolを実行し、<1.>でメモしたMac Addressを入力します。


*実行例

ps3-02


3.次に、PS3コントローラ用のライブラリをArduinoIDE1.8.10に追加します。
下記よりダウンロードして、ライブラリにzipを追加します。

download ps3 arduino library and add zip library

4.次のスケッチで、コントローラのテストを行います。
 *シリアルモニタで、各ボタン、アナログ値を確認できます。
 *シリアルプロッタのグラフで見るとジョイスティックアナログ値がよく分かります。

①PS3コントローラのPS釦を圧下し、ペアリングできる状態にします。
②スケッチを実行し、各ボタン、ジョイスティックを試験します。

ps3test.ino
//*****************************************************
#include <Ps3Controller.h>
void  setup()
{
    Serial.begin(115200);
    Ps3.begin("00:11:22:33:44:55"); //1.でメモしたmac adresに修正
    Serial.println("Ready");
}

void  loop()
{
  if  (Ps3.isConnected()){

    if (Ps3.data.button.select){
      Serial.println("select ボタン圧下");
    }
    if (Ps3.data.button.l3 ){
      Serial.println("l3 ボタン圧下");
    }
    if (Ps3.data.button.r3){
      Serial.println("r3 ボタン圧下");
    }
    if (Ps3.data.button.start){
      Serial.println("start ボタン圧下");
    }

    if (Ps3.data.button.up ){
      Serial.println("up ボタン圧下");
    }
    if (Ps3.data.button.right){
      Serial.println("right ボタン圧下");
    }
    if (Ps3.data.button.down ){
      Serial.println("down ボタン圧下");
    }
    if (Ps3.data.button.left){
      Serial.println("left ボタン圧下");
    }

    if (Ps3.data.button.l2 ){
      Serial.println("l2 ボタン圧下");
    }
    if (Ps3.data.button.r2){
      Serial.println("r2 ボタン圧下");
    }
    if (Ps3.data.button.l1 ){
      Serial.println("l1 ボタン圧下");
    }
    if (Ps3.data.button.r1){
      Serial.println("r1 ボタン圧下");
    }

    if (Ps3.data.button.cross){
      Serial.println("cross ボタン圧下");
    }
    if (Ps3.data.button.square){
      Serial.println("square ボタン圧下");
    }
    if (Ps3.data.button.triangle){
      Serial.println("triangle ボタン圧下");
    }
    if (Ps3.data.button.circle){
      Serial.println("circle ボタン圧下");
    }

    if (Ps3.data.button.ps){
      Serial.println("ps ボタン圧下");
    }
    
    Serial.print("128,-128,LX=,"); //プロッタ用基準線
    Serial.print(Ps3.data.analog.stick.lx);
    Serial.print(",LY=,");
    Serial.print(Ps3.data.analog.stick.ly);
    Serial.print(",RX=,");
    Serial.print(Ps3.data.analog.stick.rx);
    Serial.print(",RY=,");
    Serial.print(Ps3.data.analog.stick.ry);
    Serial.print(",SX=,");
    Serial.print(Ps3.data.sensor.accelerometer.x);
    Serial.print(",SY=,");
    Serial.print(Ps3.data.sensor.accelerometer.y);
    Serial.print(",SZ=,");
    Serial.print(Ps3.data.sensor.accelerometer.z); 
    Serial.println();
  }
  delay(100);
}

//*****************************************************


*シリアルモニタでの実行例

ps3-10


*シリアルプロッタでの実行例

ps3-11

以上

・2019年10月12日 台風19号 接近時 の 気圧変化 を 
 ambient  で 記録していた時のグラフです。


台風19号気圧変化

・リモコンカーをジョイスティック (HP3-185-A) でコントロールするために、
 ESP32 を内蔵させて BLE 対応に改造してみました。


S__42303500



 ・改造前
jt改造前


 ・改造後
jt改造後1

 ・改造後 バッテリーを追加
jt改造後2


FOLYWLIJEOILQ5U.LARGE





・BeetleCをM5StickCにジョイスティックを付けてBLE経由で遊んでみました。
 あと左右の動きが、イマイチでしたので後輪を取り外し、キャスターを取り付てみました。






beetleC改造-2




・ダイソーで売っているスマホ用Bluetoothリモートシャッター(AB Shutter3)改造しました。

改造前
 9ピン・iOSボタン    :VolumeUp キー を押したことと等価
 8ピン・Androidボタン:先に Returnキー(Enterキー)を押す(EnterしてVolumeUp)


この改造で
 9ピン・iOSボタン    :VolumeUp  キー を押したことと等価
10ピン・Androidボタン:VolumeDownキー を押したことと等価
となり、リモートでボリュームのコントロールとカメラのシャッターを操作することが
出来るようになりました。

改造後
ABS3-3


改造前
ABS3-1

ABS3-2


基板上でのパターンは、8ピンがAndroidボタン、9ピンがiOSボタン、10ピンがオープン、
11ピンがGNDといった接続。

ABSt3



中のIC「ST17H26」のピン配置図とピン仕様

ST17H26-1

ST17H26-2


詳しくは、下記サイトで

・M5StickC 搭載 BeetleC に近接センサ「APDS9930」を取付し、
 PS3のコントローラで遊んでみました。
 まだまだ、スピードが出すぎて、コントロールは難しいです。






APDS9930


S__41869344


S__41869343




・raspi にて PS3controller を UDP で M5StickC へ
 接続するためのpythonプログラムです。
プログラムの概要
1. PS3controller をbluetoothで、paspiに接続
2.それをRCWCのフォーマットに変換
3.その後、UDPにてM5StickCに送る


#!/usr/bin/python3
import struct
import socket #UDP送信
import time #待機時間用
from contextlib import closing #with用
host = '192.168.4.1' # IPアドレス(変更する!)
port = 10000 # ポート番号
device_path = "/dev/input/js0"

# unsigned long, short, unsigned char, unsigned char
EVENT_FORMAT = "LhBB";
EVENT_SIZE = struct.calcsize(EVENT_FORMAT)

ps3_RCWC = {0:0x0020,1:0x0040,2:0x0010,3:0x0100,4:0x0200,5:0x0800,6:0x0400,7:0x1000,8:0x000c,9:0x0003,10:0,11:0,12:0,13:0x0001,14:0x0002,15:0x0008,16:0x0004}

data = bytearray([0,0,0,0,0,0,0,0,0,0])

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #ソケットの設定
skip_flg = 0
ct = 0
btime = 0 #前回の時間
bval = 0
ds3_time = 0
ds3_val = 0

with closing(sock): #プログラム終了時にソケットを自動的に閉じる      
 with open(device_path, "rb") as device:
  print("Program Start")
  event = device.read(EVENT_SIZE)
  while event:
    btime=ds3_time
    bval=ds3_val
    (ds3_time, ds3_val, ds3_type, ds3_num) = struct.unpack(EVENT_FORMAT, event)
    print(" ")
    print( "{0}, {1}, {2}, {3}".format( ds3_time, ds3_val, ds3_type, ds3_num ) )
    print("COUNT=",ct)
    ct=ct+1

    if ds3_val == 0:
        ct=0
    if (ds3_type == 2 and ds3_val !=0):
        #if ds3_time-btime < 20:
        if abs(abs(ds3_val)-abs(bval))<1000:
            event = device.read(EVENT_SIZE)
            continue
    
    if (ds3_type == 129 or ds3_type == 130):
         event = device.read(EVENT_SIZE)
         continue        

    if ct > 100:
        event = device.read(EVENT_SIZE)
        continue
    

    val=0
    if ds3_type == 1: #ボタン圧下判定
        skip_flg = 0
        if ds3_num in ps3_RCWC:
          val = ps3_RCWC[ds3_num] #対応ボタンデータ取得
          if ds3_val == 0:
             data[0]=0
             data[1]=0
          else:
             data[0]=int(val // 256)
             data[1]=int(val % 256)
          
    elif ds3_type ==2: #ジョイスティック判定
        skip_flg = 0
        if ds3_val == 0: #中点の時
            val = 128
            data[2]=(val)
            data[3]=(val)
            data[4]=(val)
            data[5]=(val)
        else:
          if ds3_num == 1:  #左側 上下
            if ds3_val < 0: # 上側方向
                val = 128 + abs(int((ds3_val/256)))
            else:           # 下側方向
                val = 128 - int((ds3_val / 256))
            data[3] = (val & 0xff)

          elif ds3_num == 0: #左側 左右
            if ds3_val < 0:  # 左側方向
                val = 128 + int((ds3_val/256))
            else:            # 右側方向
                val = 2 * int((ds3_val / 256))                 
            data[2] = (val & 0xff)

          elif ds3_num == 3: #右側 左右
            if ds3_val < 0:  # 左側方向
                val = 128 + int((ds3_val/256))
            else:            # 右側方向
                val = 2 * int((ds3_val / 256))          
            data[4] = (val & 0xff)
          elif ds3_num == 4: #右側 上下
            if ds3_val < 0:  # 上側方向
                val = 128 + abs(int((ds3_val/256)))
            else:            # 下側方向
                val = 128 - int((ds3_val / 256))
            data[5] = (val & 0xff)
          else:
            skip_flg = 1
            val = 128
            data[2]=(val)
            data[3]=(val)
            data[4]=(val)
            data[5]=(val)
            
        print("analog val=",int(val),ds3_val)
                  
#    elif (ds3_type == 129 or ds3_type == 130):
#        skip_flg=1
    else:
        skip_flg=1    
            
#    print("val=",hex(val),val)   
#    for i in range(10):
#      hex_str = format(data[i],'02x')
#      print(hex_str," ",end="")
#    print(" ")

#UDP send    
    if skip_flg == 0:
        print("send: ", data) #送信した文字列を送信側に表示
        print(" ") 
        sock.sendto(data, (host, port)) #ソケットにUDP送信
#    time.sleep(0.5)
    event = device.read(EVENT_SIZE)

・ラズベリーパイ 仮想キーボード 文字化けについて

下記で、仮想キーボードをインストールする。
$ sudo apt-get install matchbox-keyboard

いざ使うとすると、文字化けで使えません。

下記をインストールして文字化けが直りました。
# sudo apt-get install ttf-kochi-gothic xfonts-intl-japanese xfonts-intl-japanese-big xfonts-kaname
 
以上 めでたしめでたし

・M5StickC で UIFLOW を 使かってみる。


ここに↓ [web uiflow]接続し、[APIKEY]を設定する。
http://flow.m5stack.com/


webuiflow



ここで↓M5Burner をダウンロードして、M5StickCに焼く。
https://m5stack.com/pages/download


下記を参照にセットアップする。

M5stack(M5GO)とM5UI.Flowであそんでみた
https://qiita.com/mashed-p/items/1ba7a3dc54e3b766c2a8

uiflow


以上


PS3コントローラをBluetoothでつなげる

ps3ds


まず、検索デスクをクロームにセットする。
https://www.searchdesk.com/

最近は、apt-getでなくaptを使用するみたい。
$コマンドリストをコピぺしてセットアップする。

◆システムのアップデート
$ sudo apt-get update
$ sudo apt-get dist-upgrade

◆日本語フォントのインストール
$ sudo apt-get install fonts-noto-cjk fonts-ipafont fonts-ipaexfont fonts-takao 

◆UI のフォント変更
デスクトップの何もない所を右クリックし [デスクトップの設定] を選択 (またはアプリケーションメニューから [設定 | Appearance Settings] )。

[System] タブの [Font] を Noto Sans CJK に変更 (フォントの種類は任意です)。

◆一旦再起動しないとフォントが正しく反映されません。
$ sudo reboot

◆Chromium (ブラウザ) の日本語化
$ sudo apt-get install chromium-l10n

◆LibreOffice (Office スイート) の日本語化
$ sudo apt-get install libreoffice-help-ja

◆PS3コントローラをBluetoothでつなげる
$ sudo apt-get -y install libusb-dev joystick python-pygame

$ cd ~
$ wget http://www.pabr.org/sixlinux/sixpair.c
$ gcc -o sixpair sixpair.c -lusb

$ sudo reboot

$ sudo ~/sixpair

GUIにてコントローラーのペアリング

$ jstest /dev/input/js0

***************************************************************

PS3リモートを新しいRaspberry Pi Zero Wに接続する方法
https://www.piborg.org/blog/pi-zero-wifi-ps3

PlayStation 3コントローラーヘルプシート
https://www.piborg.org/blog/rpi-ps3-help

RaspberryPi Zero WとPS3コントローラをBluetoothでつなげる
http://ei0124.blog.fc2.com/blog-entry-43.html

Pythonでdualshock3の入力を読み取る
https://www.usagi1975.com/30jul170722/

Playstation 3コントローラーの構成
https://pythonhosted.org/triangula/sixaxis.html

・M5StickC 搭載 web 操縦 リモコンカーを作ってみました。

前方衝突防止にAPDS9930近接センサーを搭載しました。
約10cmに壁があると停止又はバックするようにしました。
動画は、デモモードで自動で動いています。




wificar2




wificar3

・M5StickC を使って WiFi 操縦 ミニカーを作ってみました。

S__41738280

S__41738281


前面に近接センサーを付け、追突を防止しようと考えました。
そのため、前後で i2c を 2チャンネル 使う方がスマートにできそうです。

最初は、「M5StickC非公式日本語リファレンス」を参照して
下記のスケッチでテストしましたが、ダメでした。
..

M5.begin();
Wire.begin(32, 33); //SDA,SCL
Wire1.begin(0, 26); //SDA,SCL
...

色々テストしていて、理由は、分かりませんが、
一応両方動くようになりました。

Wire1.begin(SDA,SCL)は、使わないで
1.setup()の初期化の時に、それぞれWire.begin(32,33)/(0,26)を設定
2.loop()の中では、近接センサを呼び出す前に都度Wire.begin(32,33);設定
3.終わったらWire.begin(0,26);を再設定する
void setup() {
.......
M5.begin();
Wire.begin(32, 33); //SDA,SCL
// Initialize APDS-9930 (configure I2C and initial values)
if ( apds.init() ) {
Serial.println(F("APDS-9930 initialization complete"));
} else {
Serial.println(F("Something went wrong during APDS-9930 init!"));
}
Wire.begin(0, 26); //SDA,SCL
Wire.setClock(50000);
drvMotorL(0);drvMotorR(0); // STOP
.......
}
void loop(){
.....
Wire.begin(32, 33); //SDA,SCL
if ( !apds.readProximity(proximity_data) ) {
Serial.println("Error reading proximity value");
} else {
Serial.print("Proximity: ");
Serial.println(proximity_data);
}
if (proximity_data>500) {
x=0;y=0;
}
Wire.begin(0, 26); //SDA,SCL
.....
}

・aitendoの8x8LEDのpin番号を調べてみた

COL,ROWの並びとピン番号の並びはめちゃくちゃですね。

1.
S__41689092


2.
LED8x8PinNo


3.
LED8x8


・BeetleC 概要

マイコン:ST32F030 F4P6
DC Stepper Motor Driver:L9110S
Motor:DC3V 1200 rpm ターン DIY ミニモデルモーター
https://www.aliexpress.com/item/32953011103.html?fbclid=IwAR0zsMxg88UmxZWpf7rQym0mGl1fKLqnnqMWVd3zXJpePqvioC9QUPe3O9w

操縦:サンプルスケッチは Motorが速く webでの操縦がしにくい。

1.
BeetleC-1


2.
BeetleC-2


3.
BeetleC-3


4.
Beetlec-4


5.
BeetleC-5


6.
BeetleC-6




















最近、ESP-32やらAlexaやらWiFiの機器が増えてきて推奨接続台数をオーバーして、
時々繋がらないことが頻繁に起こるようになりました。
よって、アクセスポイントを増設しました。
機器は、コストパフォーマンスのよい
「TP-Link WiFi 無線LAN ルーター 11ac MU-MIMO ビームフォーミング
 全ポートギガビット デュアルバンド AC1200 867 + 300Mbps Archer C6」
をアマゾンで購入しました。

これで、接続エラーが減少してくれればと思っています。

https://www.amazon.co.jp/gp/product/B07HMVH73D/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1


TP-LINK

↑このページのトップヘ