oracleメモ。Export/Import/DIRECTORY指定

 

なんか急遽データベースであるOracleのお仕事来そうなので、日曜返上でお勉強です。

 

http://www.ac.cyberhome.ne.jp/~coloration-style/Oracle/Oracle19c_Install.html
とかに従ってインストール。

 

C:¥DB¥WINDOWS.X64_193000_db_homeに展開したファイルを配置して


 setup.exeを実行

 

 

 

完了!!

 

 

でsqlplusが動かなくて試行錯誤

 

・・・


結果、


 C:¥DB¥WINDOWS.X64_193000_db_home¥network¥admin
 ORACLEHOMEの中のadminの中のファイル
 sqlnet.oraの1行変更すれば治る。


変更前

 

 NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)

 

変更後

 

 NAMES.DIRECTORY_PATH= (TNSNAMES)

 

と変更すること。


自分の場合は試行錯誤の中でorclで作ってからorcl2を作っているのでsqlplusのコマンドは
 sqlplus sys@orcl2 as sysdba

 pass=Mxxxxx1

となった。この後また変更することになるが。

上記のセットアップをした場合に

 oracleにDBは作られているっぽいので、create tableを実施。

 

 CREATE TABLE t1  ( k1 VARCHAR2(10) NOT NULL, k2 VARCHAR2(50), k3 NUMBER(1,0) ) ;

 INSERT INTO t1 (        k1, k2, k3) VALUES (        'tokyo', 'sibuya', 1) ;
 commit work;
 select * from t1;

 

ここでまた試行錯誤・・・

 

expdpのテストをしたいんですけど。
 expdpすると、sysではログインできないとか、
  ユーザー追加すると、ユーザー登録できなかったりで、

 

試行錯誤。

 

・・・

 

調べた結果

 

 pdb=プラガブル・データベースというキーワードにたどり着きまして。
  google先生によると
   上でインストールしたときにプラガブルデータベース使うとしたらしく。

    不要な新機能に振り回される。

 

 

sqlplusの起動もプラガブル

 

 sqlplus sys@orclpdb as sysdba

 

startupでプラガブルを起動

 

 startup

 

それでやっと、

 ユーザ追加成功

 

 CREATE USER miha identified by Mxxxxx1

 

権限追加

 

 grant connect to miha;
 grant ALL PRIVILEGES TO miha;
 GRANT READ ON DIRECTORY DIR1 TO miha; DIR1は後で出てくる。このタイミングではエラーになるかも
 GRANT WRITE ON DIRECTORY DIR1 TO miha; DIR1後で出てくる。このタイミングではエラーになるかも

 

作ったユーザーで再接続

 

 sqlplus miha/Mxxxxx1@orclpdb

 

テーブル作って

 

 CREATE TABLE t1  ( k1 VARCHAR2(10) NOT NULL, k2 VARCHAR2(50), k3 NUMBER(1,0) ) ;
 CREATE TABLE t2  ( k1 VARCHAR2(10) NOT NULL, k2 VARCHAR2(50), k3 NUMBER(1,0) ) ;


データインサート

 

 INSERT INTO t1 (        k1, k2, k3) VALUES (        'tokyo', 'sibuya', 1) ;
 INSERT INTO t1 (        k1, k2, k3) VALUES (        'aomori', 'hirosaki', 1) ;
 INSERT INTO t2 (        k1, k2, k3) VALUES (        'hokkaido', 'hakodate', 1) ;
 INSERT INTO t2 (        k1, k2, k3) VALUES (        'iwate', 'morioka', 1) ;
 commit work;

 

そんでセレクトしてみておく。
 SELECT
  select * from t1;

 

□ここから先が元々やりたかったexport


 exp miha/Mxxxxx1@orclpdb file=tableexp.dmp rows=y tables=(users.t1)

 

□export先のDIRECTORY指定


 CREATE DIRECTORY DIR1 as 'C:¥tmp';    ←深い場所にしてしまうとエラーになるぞなんで?
 DROP DIRECTORY DIR1;
 SELECT * FROM ALL_DIRECTORIES;

 

□DIRECTORYを使ってexport

 

 expdp miha/Mxxxxx1@orclpdb tables=t1,t2 directory=DIR1 dumpfile=data.dmp logfile=data.log

 

□表は削除しておく(表があるとエラーになるので)

 

 drop table t1;
 drop table t2;

 

□DIRECTORYを使ってimport

 

 impdp miha/Mxxxxx1@orclpdb tables=t1,t2 directory=DIR1 table_exists_action=replace dumpfile=data.dmp   logfile=dataimp.log

 

これで一通りexportからimportまで出来るようになった。


JUGEMテーマ:電子工作

 

ESP32のmicropythonでマジックパケット

 

パソコンの電源を遠隔操作するやつ。
 遠隔操作でPCの電源をON/OFF/RESETする回路とか。
  https://ameblo.jp/fc2miha/entry-12833773018.html

 

前に作って、今でも重宝して使っておりましたが、
 マザーボードの電源スイッチの所に直接細工する方式のため、
  ノートPCでは使用できなかったり、

  工作が敷居が高かったりすることもあったりしました。

  ただし、こちらの方法は長押しやリセットも出来るので、それはそれで優れている部分もありますが。

 

少し汎用的なものをMagicPacket方式で作れるかなーと思い調べてみたので記事にします。

 

マジックパケットとは、LANに接続しているPCの電源をONにするために
 活用可能なもので、パソコンが対応している必要があります。

 

こちらに細かく解説しておられますので参考にしてください。
参考
 https://atmarkit.itmedia.co.jp/ait/articles/2004/20/news021.html

 

要約すると、
 完全にシャットダウン:パソコンのBIOSで設定が必要
  うちのパナソニックの場合は
   Biosの詳細→Power On by LAN機能 → 許可
 スリープの場合:Windows10で設定が必要
  うちのパナソニックの場合は
   デバイスマネージャー→ネットワークアダプター
    →Intel(R)EthernetConnectionI218-LM
     →電源管理
      →「このデバイスでコンピューターのスタンバイ状態を解除できる

        ようにする」をチェックする
       →「MagickPacketでのみ、コンピューターのスタンバイ状態を解除できる

        ようにする」をチェックする
です。

 

ご自身のパソコン(Windows)が対応可能かを確認するには
 コマンドを入れてみて
  powercfg.exe /devicequery wake_programmable
 以下の感じの文字が出るか確認します。
  Realtek RTL8723B Wireless LAN 802.11n USB 2.0 Network Adapter
  Realtek PCIe GBE Family Controller
  Mitsumi WiMAX Network Adapter
  Intel(R) Ethernet Connection I218-LM ← 上の例はこれでWindows10を設定
  Intel(R) Dual Band Wireless-AC 7260
 WakeOnに対応しているデバイスが出てきます。

 

マジックパケットの構成
 WIKIによると、
  「マジックパケットは、FF:FF:FF:FF:FF:FFに続けて起動したい装置の
   MACアドレスを16回繰り返したデータパターン(AMD Magic Packet Format) が
   ペイロードのどこかに含まれているようなパケットである。」
 となっております。


パケットを組み立てて送信先のアドレスはブロードキャストアドレスである
 255.255.255.255宛に投げてみたところ
うまく動きましたので、それで良しとしております。

 

参考
 https://kapibara-sos.net/archives/853

 

■プログラム

 

ESP32のmicropython用プログラムです。


上記参考ページを参考にして、FFを6回、とMACアドレス6バイトを繰り返し16回続くパケット
 (全部で6バイト+6×16バイト=102バイト)
を組み立てたらUDPでブロードキャストアドレスに送信します。

 

import usocket
import ussl
import network
import utime
import struct
import sys

 

print("MagicPacket 0.1")

ssid = wifi_ssid
passkey = wifi_password

 

def send_magic_packet(addr):
    # 
    s = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM)
    #
    mac_ = addr.upper().replace("-", "").replace(":", "")
    if len(mac_) != 12:
        print("MAC address error: {}".format(addr))
        sys.exit(0)


    print("addr="+addr)
    #
    buf = 'F' * 12 + (mac_ * 16)
    print("buf="+str(buf))
    #
    magicp = b''
    for i in range(0, len(buf), 2):
        magicp += struct.pack('B', int(buf[i:i + 2], 16))
    #
    debug_str=""
    for i in range(0, len(magicp)):
        debug_str = debug_str + '{:02X}'.format(magicp[i])
    print("magicp="+debug_str)
    #
    sockaddr = usocket.getaddrinfo('255.255.255.255', 7)[0][-1]
    
    # マジックパケット送信
    print("s.sendto : {}".format(addr))
    s.sendto(magicp, sockaddr)
    s.close()

 

timeout=60
wifi= network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(ssid, passkey)
while not wifi.isconnected() and timeout > 0:
    print('.')
    utime.sleep(1)
    timeout -= 1
#
mac_addr = "8C:C1:21:53:61:4F"
send_magic_packet(mac_addr)


JUGEMテーマ:電子工作

 

ARDUINO+MCP2515+MCP2561でCAN通信してみた。の巻

 

最近CANの通信とRS485の通信とかいろいと記事を書いております。

過去記事
 ESP32+MCP2561-EPでCAN
  https://ameblo.jp/fc2miha/entry-12833773103.html

 ESP32+LTC485CN8でRS485  

 ESP32+MCP2562でCAN
  https://ameblo.jp/fc2miha/entry-12833773100.html

 ARDUINO+LTC485CN8でRS485
  https://ameblo.jp/fc2miha/entry-12833773099.html

 

これを見ると、ARDUINOでCANが無かったので、
今回はarduino+MCP2515+MCP2561の組み合わせでCAN通信するやり方を整理しておきたいと思います。

 

調べていてわかったことですが、
 CAN通信するときに必要なものとして3つあることが判明しておりまして、
  1.マイコン
  2.CANコントローラー
  3.CANトランシーバー
です。他にも通信ケーブルとか、マイコン用の電源とかありますがそこは共通なので、省略して考えます。

 

で、
 1のマイコンに2のコントローラーを内蔵しているものがあり、
  それがESP32だったりとかします。
   なので、ESP32から直接MCP2561とかMCP2562を繋げばCAN通信可能なんです。
でも、
 ARDUINOにはCANコントローラー内蔵していないのでCANコントローラーであるMCP2515の出番となります。

 

参考記事
 https://siroyantech.hatenablog.com/entry/2021/01/31/150751
 https://github.com/sandeepmistry/arduino-CAN/blob/master/examples/CANReceiver/CANReceiver.ino
 https://qiita.com/Yu-Tomo/items/9bb85145c9aebb2385e8

 

今回使用するのは
 MCP2515です。あと、MCP2561です。
 データシート
  https://akizukidenshi.com/download/ds/microchip/mcp2515_j.pdf
 全部5V動作なので、MAKERUNOを使っていきます。

 

写真

 

 

 


左下がESP32で、これがマスターです。
左上がMAKERUNOで、これがスレーブです。

 

CANのアーキテクチャ的にはマスタースレーブの概念が無いと思いますが、
前の記事と比べ易くする為にそんなプログラムになっています。


なお、ESP32の中のプログラムは前と同じです。
 https://ameblo.jp/fc2miha/entry-12833773100.html

 

 

間にあるLAN線の長さは前の記事と同じ7メートルになっております。

 

■回路図

 

 

ARDUINO(ATMEGA328)→MCP2515→MCP2561→LAN線 今回のスレーブ側ですが、マスター側も同じです。
ただし、今回、水晶発振(セラロックでもOK)の手持ち一つしかなかったのと、
マスター側はESP32の方が実用的と思い、ESP32は前のまま利用しています。

 

間の接続はCANHはCANHにCANLはCANLに接続します。

 

■プログラム

 

Arduino用に書かなきゃならないのかと思っていたのですが、
ESP32と同じライブラリが使えることからほぼ同じでよく
 先頭にある#defineを追加。
 setupのCAN.setPins(26, 27);をコメントアウトしているのみです。


□マスター側プログラム

 

プログラムは前と同じです。
 ESP32です。
 https://ameblo.jp/fc2miha/entry-12833773100.html

 

 

□スレーブ側プログラム

 

 ARDUINOです。

 

#define CAN_CS 6
#define CAN_INT 2

#include <CAN.h>
#include <string.h>

void setup() {
  Serial.begin(115200);
  while (!Serial);

  Serial.println("CAN Receiver");

  //CAN.setPins(26, 27);
  // start the CAN bus at 500 kbps
  if (!CAN.begin(500E3)) {
    Serial.println("Starting CAN failed!");
    while (1);
  }
}

int receive(char *buf)
{
  // try to parse packet
  int packetSize = CAN.parsePacket();

  if (packetSize || CAN.packetId() != -1) {
    // received a packet
    //Serial.print("Received ");

    if (CAN.packetExtended()) {
      Serial.print("extended ");
    }

    if (CAN.packetRtr()) {
      // Remote transmission request, packet contains no data
      Serial.print("RTR ");
    }

    //Serial.print("packet with id 0x");
    //Serial.print(CAN.packetId(), HEX);

    if (CAN.packetRtr()) {
      //Serial.print(" and requested length ");
      //Serial.println(CAN.packetDlc());
    } else {
      //Serial.print(" and length ");
      //Serial.println(packetSize);

      // only print packet data for non-RTR packets
      if(CAN.available()){
        int size = 0;
        while (CAN.available()) {
          //Serial.print((char)CAN.read());
          buf[size] = CAN.read();
          size++;
        }
        //Serial.println();
        return size;
      }
    }

    //Serial.println();
  }
  return 0;
}

int nCount = 0;
void loop() 
{
  char buf[256];
  memset(buf, '¥0', sizeof(buf));
  int size = receive(buf);
  if(size>0){
    Serial.println(buf);
    //
    //ack
    //
    CAN.beginPacket(0x12);
    //char buf[256];
    sprintf(buf, "A:%d", nCount);
    CAN.write((uint8_t*)buf, strlen(buf));
    CAN.endPacket();
    nCount++;
  }
}


■実験結果

 

通信速度ですが、
CANで設定上の通信速度は500Kbpsです。
しかし、ざっと10秒で1000往復になりました。
ESP32同士でやると3000往復なので、このあたりでCPUの性能差出てしまうようです。
1往復あたりは10ミリ秒ですね。

 

でもまぁ価格差など考慮すると十分高速で実用的と言えると思います。

 

あと、時々止まるのは調整で何とかなる認識です。

 → この問題はARDUINOだからの問題ではなくて単に作者がサポっているだけです。


マスター側をリセットすると同じ調子で送信始めるので、
一定期間受信できなかったときは再送するなど、何か仕掛けが必要になります。
 あとは、通信速度を意図的に下げておくとかかなと思います。


JUGEMテーマ:電子工作

 

MAKERUNOを初めて使う。

 

arduinoそのまま買うと高いから、とか、
UNOがあるのに3.3Vのarduino買いたくないとか
そんなセコイ理由で
ずっと前
 https://ameblo.jp/fc2miha/entry-12833772800.html

 

こんなのを作って遊んでたりしましたが、


秋月さんのページでMAKERUNOなるものを見つけたので
買ってきました。

 

とりあえず、いつも通りにマニュアル読まないでパソコンに繋ぐと、
昔懐かしのマリオのオープニング1小節分ぐらいが流れてきます。
そんで、横にくっついているLEDに光が流れるという演出。
さらに、内蔵スイッチを押すとピロ、って音がする。

 

https://www.youtube.com/shorts/mNu2tmZOQP8


かっこいいー
というわけで、感動したので記事に書かねばならんというわけで
今パソコンに向かっております。

 

しかし、パソコン側のCOMポートが増えないので、ドライバーが合ってないのね。
と判断し、調べると秋月のページにUSB-シリアル変換IC:CH340Gと書いてあるので、
そのドライバー検索しをダウンロードしましたとさ。

 

この、MAKERUNO、なかなか良くできているというか遊び心を掻き立ててくれます。

本家との違いは、
 ブザーがついていて音楽の演奏が可能
 各デジタルピンにLEDが接続されていて、光る
 RESET以外にタクトスイッチが付いていて簡単な外部入力がパーツの追加無しで出来る

といった所です。しかも、安い。

 

消すのもったいなかったけど、

Lチカ書き込んでいつも通りLEDぴかぴかを確認。

 

説明書を見るとhttp://bit.ly/makerUNOstartに何か書いてありそうなので見てみると
『このサイトにアクセスできません』

 

 

しかし、ここでくじけてはいけない。


目的は

  どのピンがタクトスイッチに接続されているのか?
  ピンがブザーに接続されているのか?
の2点。LEDがくっついている以外はその他は本家と同じはず。


あったあった。
 https://docs.google.com/document/d/1gJIF-tssdoxk8qAq2aHBmPwVHulFL_lSElOhA17Du64/edit
 ・On board programmable push button (pin 2, need to configure as INPUT_PULLUP).
 ・On board piezo buzzer (pin 8).
→2番にタクトスイッチ(プルアップ)
→8番にブザー

2番のタクトスイッチはプルアップなので押されたらLOWになる

 

■プログラム

 MakerUNOに最初から入っているプログラムを再現してみました。
 なんか、ピロが少し音が違うけどこのぐらいで許して。

 

参考
 http://nyazak-ele.blog.jp/archives/8823582.html

 

int Do = 261;
int Re = 294;
int Mi = 329;
int Fa = 349;
int So = 392;
int La = 440;
int Si = 493;
int Do2 = 523;
int Re2 = 587;
int Mi2 = 659;
int Fa2 = 698;
int So2 = 784;
int La2 = 880;
int Si2 = 988;
int Do3 = 1047;
int Re3 = 1175;
int Mi3 = 1319;
int Fa3 = 1397;
int So3 = 1568;

int LED1[5]={13, 12, 11, 10, 9};
int LED2[5]={7, 6, 5, 4, 3};

int mario[13] = {Mi2, Mi2, 0, Mi2, 0, Do2, Mi2, 0, So2, 0, 0, 0, So};
 
void setup() {
 
    pinMode(8, INPUT);

    for(int i=0;i<5;i++){
      digitalWrite(LED1[i], HIGH);
      digitalWrite(LED2[i], HIGH);
    }
 
    for (int i = 0; i < 13; i++) {
      tone(8, mario[i], 50);
      delay(130);
    }
    digitalWrite(2, HIGH);
}
int nMode = 0;
int nCount = 0;
int nOldCount = 5;
int oldVal = -1;
void loop() {
  
  digitalWrite(LED1[nCount], HIGH);
  digitalWrite(LED2[nCount], HIGH);
  digitalWrite(LED1[nOldCount], LOW);
  digitalWrite(LED2[nOldCount], LOW);

  int val = digitalRead(2);
  if(oldVal!=val){
    if(val==LOW){
      if(nMode==0){
        nMode = 1;
        //
        tone(8, So2, 90);
        delay(130);
        tone(8, Do2, 90);
        delay(130);
      }
      else{
        nMode = 0;
        //
        tone(8, Do2, 90);
        delay(130);
        tone(8, So2, 90);
        delay(130);
      }
    }
    oldVal=val;
  }

  if(nMode == 0){
    nOldCount = nCount;
    nCount++;
    if(nCount>=5){
      nCount = 0;
    }
  }
  else{
    nOldCount = nCount;
    nCount--;
    if(nCount<0){
      nCount = 5;
    }
  }
  delay(100);
}


JUGEMテーマ:電子工作

ESP32でCAN通信してみた。MCP2561-EPの記事

 

実はですね。ESP32でCANの記事を前に書いたんですが、
 その前に間違えてMCP2561を買っちゃっおりまして、
 それがパーツ箱に未使用のまま残っていたので、気になっておりましたが、
 5V→3v3Vへの信号の入れ方が前の記事で判ったりとか
  https://ameblo.jp/fc2miha/entry-12833773102.html


 下の参考記事によると、MCP2561をESP32にそのまま直結でも難なく動いていたりする様なんですよね。
  参考記事
   https://404background.com/circuit/mcp2561-can/

 

それで、ですね。
前の記事で
 https://ameblo.jp/fc2miha/entry-12833773100.html


MCP2562FDとESP32で通信させる記事を書いてたんですが、
MCP2561とESP32で通信させる記事を実験をしてみたところ成功しましたので
まとめておきます。

 

今回使用するのは
 MCP2561-EPです。
 上でも書きましたがMCP2562FDと間違って買ったんですが。
 データシート
  https://akizukidenshi.com/download/ds/microchip/mcp2561_mcp2562_j.pdf

 

  


  SPLIT端子でコモンモード安定化が特徴のようですが、今回これは使いません。

 

写真

 


左下がESP32で、これがマスターです。
左上がESP32で、これがスレーブです。

 

間にあるLAN線の長さは前の記事と同じ7メートルになっております。

 

■回路図

 


ESP32→MCP2561→LAN線 が2セットになるので、
片方だけ書きましたが、
間の接続はCANHはCANHにCANLはCANLに接続します。

 

今回のポイント
 回路図の「これ」の部分がESP側の信号を受ける所RXでここに抵抗4.7KΩ入れています。

 これでESP32側が3.3Vで動作していてもポートが壊れず、さらに正常に信号が読み取れます。

 ほかの信号線としてはTXがありますが、こちらはESPから出力する3.3Vを

 5V側でHIGHとして読み取れればいいので5V側からの信号が来ない限りは大丈夫なはずです。

 

■プログラム


□マスター側プログラム

 前と同じ
 https://ameblo.jp/fc2miha/entry-12833773100.html

 

 

□スレーブ側プログラム

 前と同じ
 https://ameblo.jp/fc2miha/entry-12833773100.html


■実験結果


ざっと10秒で1000往復出来てますので、
1往復あたりは10ミリ秒ですね。

プログラムをよく見ると、delay(10)があるので、
 delayだけで10㍉秒なので、処理自体はものすごく速いですね。
 

 

LTC485CN8を使用したRS485通信ESP32+micropython版

 

ARDUINO版の記事を先に参照してください。
 https://ameblo.jp/fc2miha/entry-12833773099.html

 

この記事のESP32+micropython版です

 

マスター側をESP32に置き換えて、スレーブ側をArduinoを使う場合です。

 

LTC485CN8を使うわけですが、
データシート 
 https://www.mouser.jp/datasheet/2/609/485fm-2955265.pdf
 電源電圧は5Vで動く。

 

前にも書きましたが、ARDUINOの5V版で作るのが簡単そうだったので、
前の記事はARDUINOで作りました。

でも、やっぱり、3.3Vから制御したい!!というわけで、
色々調べました。

 

変換アダプタ使うのが簡単ですが、なんかつまらないじゃないですか?
 という訳で、UARTの5Vと3.3Vを接続できる回路を間にかましてみました。
参考
 https://www.cepstrum.co.jp/hobby/5v33v/5v33v.html

 

写真

 


左下がESP32ーDEVKITで、これがマスターです。
左上がUNO互換機で、これがスレーブです。
赤で書いたブレッドボードが3.3Vと5Vの変換です。

UARTの5Vと3.3Vを接続できる回路は上の写真の「これ」の部分です。
間にあるLAN線の長さが7メートルになっております。

 

■回路図

 

 

上の回路はESP32で作ったマスター側です。

スレーブ側は前の記事と同じです。
 https://ameblo.jp/fc2miha/entry-12833773099.html

 

間の接続はAはAにBはBに接続します。

 

今回のポイントはESP32のRX端子に4.7KΩの抵抗を付けている所です。
これがあると、単純に5V→3.3Vの信号が正常に受けられるって事ですね。
TX端子は電圧がかかる事は想定していないので、問題あるかもですが、
 ま、大丈夫って事で、こんな回路になりました。


詳しくは上の参考のURLを参照でおねがいしたい。


■プログラム


□マスター側プログラム

 

import time
from machine import UART, Pin

print("start")

txden = Pin(13,Pin.OUT)

uart2 = UART(2, 9600, rx=18, tx=19)
uart2.init(9600, bits=8, parity=None, stop=1, timeout = 10, timeout_char =5)
count = 0
while True:
    print("point "+str(count))
    txden.value(1)
    #
    uart2.write("write"+str(count)+'¥r¥n')
    time.sleep_ms(20)
    txden.value(0)
    count=count+1
    #
    #
    #
    print("point : 200")
    #
    time.sleep_ms(50)
    for i in range(10):
      buf = uart2.read()
      if buf is None :
        #size =uart2.any()
        #print("none")
        time.sleep_ms(10)
        continue
      else:
        break
    #
    try :
      buf = buf.decode('utf-8')
    except :
      print("")
    print(buf)
    
    time.sleep_ms(10)


□スレーブ側プログラム

 

前の記事と同じです
 https://ameblo.jp/fc2miha/entry-12833773099.html

 

■実験結果

 

スレーブは前の記事のままでプログラムもそのまま。

ESP32のマスター側は上記通りで、安定して通信できているようです。

間の回線はLAN線のツイストペア7メートルです。

終端抵抗は無し。

 

通信速度ですが、
電文が100回往復する時間を測定したところ、15秒かかっておりますので、
1回あたりだと、0.15秒です。

 

タイミングによってはマスター側への到着が遅れる場合があるみたいで、
次のReadで2回分読み込む事が有ったので、uart2.read()の中身がNoneの場合に
リトライする様にしました。


JUGEMテーマ:電子工作
 

ESP32のmicropythonでSSL(https)通信を行う。

 

ずっと前に書いた記事ですが、
 https://ameblo.jp/fc2miha/entry-12833772838.html

 raspberryPIでSSL通信をする記事を書いておりました。もう7年も前ですね。

 

C言語でSSL(htpps)通信でhtmlのページのデータを持ってくるプログラムでした。
今日はESP32のmycropythonで同じことをします。

 

■プログラム

 

import usocket
import ussl
import network
import utime

ssid = wifi_ssid
passkey = wifi_password

timeout=60
wifi= network.WLAN(network.STA_IF)
wifi.active(True)
wifi.connect(ssid, passkey)
while not wifi.isconnected() and timeout > 0:
    print('.')
    utime.sleep(1)
    timeout -= 1

s = usocket.socket()
addr = usocket.getaddrinfo("google.com", 443)[0][-1]
s.connect(addr)
s = ussl.wrap_socket(s)
print(s)
s.write("GET /?hl=ja HTTP/1.0¥n¥n")
result = s.read(4096)
print(result)


JUGEMテーマ:電子工作

 

ESP32でCAN通信してみた。MCP2562FDの記事

 

久々にESP32をC言語で使ってみました。
いつもはESP32はMycropythonだったので、arduinoIDEでESP32は懐かしい香りがします。

それで、ですね。


前の記事で
 https://ameblo.jp/fc2miha/entry-12833773099.html

 


RS485でarduinoで通信させる記事を書いてたんですが、
調べると、似たような規格のCANもあるよ。ってなっていて、
ESP32でも対応できるって事でしたので。参考記事を頼りにしながら
いろいろやってみました。

 

参考記事
 https://siroyantech.hatenablog.com/entry/2021/01/31/150751
 https://github.com/sandeepmistry/arduino-CAN/blob/master/examples/CANReceiver/CANReceiver.ino

 

今回使用するのは
 MCP2562FDです。
 ひと月ぐらい前かなー店舗では在庫切れになるぐらい人気になっていた商品。
 データシート

 


  https://akizukidenshi.com/download/ds/microchip/MCP2562FD.pdf

CANのデータラインは5V動作、ESP32とのやり取りは3.3Vで動作できる優れ物ですね。

 

写真

 

 

 

 

左下がESP32で、これがマスターです。
左上がESP32で、これがスレーブです。

CANのアーキテクチャ的にはマスタースレーブの概念が無いと思いますが、
今回は前の記事と比べ易くする為にそんなプログラムにしました。

間にあるLAN線の長さは前の記事と同じ7メートルになっております。

 

■回路図

 

 

 

ESP32→MCP2562FD→LAN線 が2セットになるので、
片方だけ書きましたが、
間の接続はCANHはCANHにCANLはCANLに接続します。

 

■プログラム

 

参考記事にあるプログラムと使用しているライブラリを参考にしながら、
プログラム書きました。

送信時にCAN.writeするんですが、8バイトまでしか送信できなく、
いろいろ悩みましたが、
有名なInterfaceの記事を見つけたので。
 https://interface.cqpub.co.jp/wp-content/uploads/if2112_062.pdf
 後ろにFDってついているのだと、64バイトまで送れるって書いてある。
つまり、ライブラリが対応していれば、64バイトまで行けるのかなー?
と参考ページのライブラリのページ眺めてみましたが、FDって書いていないので
たぶん、8バイトまでって事で
たくさん送る場合は8バイトで分割するのかなーって事で納得する事にしました。

 

□マスター側プログラム

 

#include <Arduino.h>
#include <CAN.h>

void setup() {
  Serial.begin(115200); //com13
  while (!Serial);

  Serial.println("CAN Sender");

  CAN.setPins(26, 27);
  if (!CAN.begin(500E3)) {
    Serial.println("Starting CAN failed!");
    while (1);
  }
}

int nCount = 0;

void loop() {
  //Serial.print("Sending packet ... ");
  Serial.print("start:");
  Serial.println(nCount);

  CAN.beginPacket(0x12);
  char buf[256];
  sprintf(buf, "w:%d", nCount);
  CAN.write((uint8_t*)buf, strlen(buf));
  CAN.endPacket();
  //Serial.println("done");
  nCount++;

//
//read
//
  //char buf[256];
  memset(buf, '¥0', sizeof(buf));
  int size = receive(buf);
  if(size>0){
    Serial.println(buf);
  }
  
  delay(10);
}

int receive(char *buf)
{
  // try to parse packet
  int packetSize = CAN.parsePacket();

  if (packetSize || CAN.packetId() != -1) {
    // received a packet
    //Serial.print("Received");

    if (CAN.packetExtended()) {
      Serial.println("extended ");
    }

    if (CAN.packetRtr()) {
      // Remote transmission request, packet contains no data
      Serial.println("RTR ");
    }

    //Serial.print("packet with id 0x");
    //Serial.print(CAN.packetId(), HEX);

    if (CAN.packetRtr()) {
      //Serial.print(" and requested length ");
      //Serial.println(CAN.packetDlc());
    } else {
      //Serial.print(" and length ");
      //Serial.println(packetSize);

      // only print packet data for non-RTR packets
      if(CAN.available()){
        int size = 0;
        while (CAN.available()) {
          //Serial.print((char)CAN.read());
          buf[size] = CAN.read();
          size++;
        }
        Serial.println();
        return size;
      }
    }

    //Serial.println();
  }
  return 0;
}

 

□スレーブ側プログラム

 

#include <CAN.h>

void setup() {
  Serial.begin(115200); //com16
  while (!Serial);

  Serial.println("CAN Receiver");

  CAN.setPins(26, 27);
  // start the CAN bus at 500 kbps
  if (!CAN.begin(500E3)) {
    Serial.println("Starting CAN failed!");
    while (1);
  }
}

int receive(char *buf)
{
  // try to parse packet
  int packetSize = CAN.parsePacket();

  if (packetSize || CAN.packetId() != -1) {
    // received a packet
    //Serial.print("Received ");

    if (CAN.packetExtended()) {
      Serial.print("extended ");
    }

    if (CAN.packetRtr()) {
      // Remote transmission request, packet contains no data
      Serial.print("RTR ");
    }

    //Serial.print("packet with id 0x");
    //Serial.print(CAN.packetId(), HEX);

    if (CAN.packetRtr()) {
      //Serial.print(" and requested length ");
      //Serial.println(CAN.packetDlc());
    } else {
      //Serial.print(" and length ");
      //Serial.println(packetSize);

      // only print packet data for non-RTR packets
      if(CAN.available()){
        int size = 0;
        while (CAN.available()) {
          //Serial.print((char)CAN.read());
          buf[size] = CAN.read();
          size++;
        }
        //Serial.println();
        return size;
      }
    }

    //Serial.println();
  }
  return 0;
}

int nCount = 0;
void loop() 
{
  char buf[256];
  memset(buf, '¥0', sizeof(buf));
  int size = receive(buf);
  if(size>0){
    Serial.println(buf);
    //
    //ack
    //
    CAN.beginPacket(0x12);
    //char buf[256];
    sprintf(buf, "A:%d", nCount);
    CAN.write((uint8_t*)buf, strlen(buf));
    CAN.endPacket();
    nCount++;
  }
}

 

■実験結果

 


思ったように動いているみたいですね。
 CANHとCANLで±逆側に信号が出ています。

通信速度ですが、
CANで500Kbpsなんで、目にもとまらぬ速さです。
もうね、測定しなくても良いかな思うぐらいです。

ざっと10秒で1000往復出来てますので、
すげーです。
1往復あたりは10ミリ秒ですね。

uartとか、シリアルから拡張しているRS485よりも高速化可能な様です。

ただ、
手軽さで言うと、uartを応用できるRS485も捨て難いですから、
適材適所っていう事になるとは思います。


 

 

JUGEMテーマ:電子工作

有線のリモコンとかで使えそうな技術の検証です。
1対1の通信で大丈夫なので、RS485はオーバースペックなんですが、
RS485で実現しておけば、他にも1対多とか多対多とかでも
応用効きそうなので、実験しておきました。
 


今回使用するのはLTC485CN8です。
データシート 
 https://www.mouser.jp/datasheet/2/609/485fm-2955265.pdf

 

 電源電圧は5Vで動く。
 +14V~-14Vまでバスに電圧かかってもOK
 出力はVCCが基準になるって事ですね。
 あと、RS485らしく、終端抵抗の事とか書いてるなー
 
という訳で、ARDUINOとARDUINO互換機の5V版で試験をする。
 
写真
 

 
 
左下がARDUINO-UNOで、これがマスターです。
左上がUNO互換機で、これがスレーブです。
 
で、マスターから送信するときの伝送経路
 UNO→LTC485→LAN線→LTC485→UNO互換機
 
で、マスターが受信するときの伝送経路
 UNO互換機→LTC485→LAN線→LTC485→UNO
 
となり、
シーケンス図を書くとこんな感じです。

 
間にあるLAN線の長さが7メートルになっております。
 
■回路図
 

 
 
UNO→LTC485→LAN線 が2セットになるので、
片方だけ書きましたが、
間の接続はAはAにBはBに接続します。
 
■プログラム
 
プログラムはD13を使ってLTC485のREとDEに接続してあるので、
送信時にHIGHにします。
あとは、普通にSoftSerialですので、
比較的手軽に通信できるみたいです。
 
1対多に対応する場合はマスターを一つ置いておいて、
マスターさんがスレーブさんの送信権管理して、
1本しかない物理ケーブルの時間割をしてあげればいいと思います。
 
多対多に対応する場合はスレーブ同士での通信が必要になると思いますが、
この場合でもやっぱマスターさんがうまく
1本しかない物理ケーブルの時間割をしてあげればいいと思います。
 

□マスター側プログラム


#include <SoftwareSerial.h>
 SoftwareSerial mySerial(2, 3);    // RX,TX
 
 int txden = 13;
 
 void setup(){
   pinMode( txden, OUTPUT );
  
   Serial.begin(115200);
   mySerial.begin(9600);
   digitalWrite(txden, LOW);

   Serial.println("start:");
 
}

int count = 0;

void loop(){
  char buf[256];
  digitalWrite(txden, HIGH);
  sprintf(buf, "com4 write %d¥r¥n", count);
  mySerial.print(buf);
  Serial.println("point : A000");
  delay(10);//送信が終わるまで待つ
  digitalWrite(txden, LOW);
  count++;
  //
  unsigned long t1 = millis();
  while(1){
    unsigned long t2 = millis();
    if((t2-t1)>3000){
      t1 = t2;
      break;
    }
    if(mySerial.available()>0){
      Serial.println("point : A100");
      memset(buf, '¥0', sizeof(buf));
      int i = 0;
      while(mySerial.available()>0){
        char val = mySerial.read();       // 受信したデータを読み込む
        buf[i]=val;
        i=i+1;
        if(val=='¥n'){
          break;
        }
        delay(10);
      }
      Serial.println(buf);
      break;
    }
 }


□スレーブ側プログラム

 

#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3);    // RX,TX
 
int txden = 13;
 
void setup(){
   pinMode( txden, OUTPUT );
  
   Serial.begin(115200);
   mySerial.begin(9600);            
   digitalWrite(txden, LOW);

   Serial.println("start:");
 
}

 int count = 0;
 unsigned long t1 = 0;
 void loop(){
  int nDataExist = 0;
  if(mySerial.available()>0){
    while(mySerial.available()>0){
     int val = mySerial.read();       // 受信したデータを読み込む
     Serial.write(val);
     nDataExist = 1;
     delay(10);
    }
  }
  //
  if(nDataExist == 1){
    Serial.println("point : 100");
    char buf[256];
    digitalWrite(txden, HIGH);
    sprintf(buf, "ack %d¥r¥n", count);
    mySerial.print(buf);
    delay(10);//送信が終わるまで待つ
    digitalWrite(txden, LOW);
    count++;
  }
}

 

■実験結果
 
オシロで取得した差動信号の模様
 

 
思うようにできているみたいですね。
AとBで±逆側に信号が出ています。
試しに7メートルのケーブルはそのままで、
UARTで直結したところ、まったく通信できませんでしたので、
こんな時はRS485が役に立ってくれそうです。
通信速度ですが、今回9600bps設定にして上のサンプルのままで、
電文が100回往復する時間を測定したところ、24秒かかっておりますので、
1回あたりだと、0.24秒です。
電気のリモコンならボタンを押して電気がつくまで0.24秒かかる事になりますが、
ま、こんなもんなのかな?
通信速度9600bpsを早くしていけばそれなりに速度は上がるとも思いますし、
応用次第ですね。
 
ちなみに、終端抵抗は無しでやってます。
 

 

 


JUGEMテーマ:Arduino


 

 

JUGEMテーマ:電子工作
 

ラジオRDA5807のソフトを改良

 

先々月に作成したラジオ。
  https://ameblo.jp/fc2miha/entry-12833773073.html

 

RDA5807ではソフトでボリューム調整が出来るんだけど、
一度設定したらあまり変更しないかなーと思い、
アンプ側のボリュームにまかせればいいと思っておりました。
値を1に設定していたんですが、
機器の組み合わせによっては余りにも小さかったりして、やっぱボリューム調整機能を追加することにしました。

 

今まではロータリーエンコーダーで周波数
 プッシュスイッチでステレオモノラル切り替えにしておりましたが、

 

プッシュスイッチを押すごとにモード切替。
 周波数→周波数(0.1単位)→ステレオモノラル切り替え→ボリューム→元に戻る
という事にして
 それぞれの中での値の調整はロータリーエンコーダーにする事にしました。

 

 

■LCD表示はこんな感じで

 通常 周波数を0.1MHz単位で変更

 

 周波数微調整 周波数を0.01MHz単位で変更

 

 ステレオモノラル調整

 

 ボリューム調整

 

■回路
 再掲

 

■プログラム

 

#include "EEPROM.h" 
#include "ST7032_asukiaaa.h"
#include "radio.h"
#include "RDA5807M.h"

ST7032_asukiaaa lcd;

int old2=1;
int old4=0;
float fHz = 79.7;   //FM泉
//float fHz = 77.1; ///FM仙台
//float fHz = 93.5; ///TBC
//float fHz = 82.5; ///NHK宮城
//float fHz = 76.2; ///仙台シティーFM
//float fHz = 78.1; ///BAY WAVE石巻 NG
//float fHz = 76.4; ///ラジオ石巻 NG
//float fHz = 77.9; ///エフエムいわぬま NG
float oldHz = 0;
long lastTm;
int modeMONO=false;
int nMode = 0;  //0=周波数1MHz
                //1=周波数0.1MHz
                //2=ST/Mono
                //3=Volume

#define FIX_BAND     RADIO_BAND_FMWORLD
int nVolume = 1;

RDA5807M radio;

//
// address  0=周波数
//          1=ボリューム
void save_EEPROM(int address, int v)
{
  int address_h = address*2;
  int address_l = address*2+1;
  EEPROM.write(address_h, v/256);
  EEPROM.write(address_l, v%256);
  
  Serial.println("save");
  Serial.println(address_h);
  Serial.println(address_l);
  Serial.println(v/256);
  Serial.println(v%256);
}

int load_EEPROM(int address)
{
  int address_h = address*2;
  int address_l = address*2+1;
  int h = EEPROM.read(address_h);
  int l = EEPROM.read(address_l);

  int r = h * 256 + l;
  Serial.println(r);
  return r;
}
void displaySet()
{
    lcd.setCursor(0, 0);
    if(nMode==0){
      lcd.print("FM Radio!    ");
    }
    if(nMode==1){
      lcd.print("FM Radio! *1 ");
    }
    if(nMode==2){
      lcd.print("FM Radio! S/M");
    }
    if(nMode==3){
      lcd.print("FM Radio! VOL");
    }
    if(nMode==0 || nMode==1 || nMode==2){
      prtHz();
      lcd.setCursor(12, 1);
      if(modeMONO==true){
        lcd.print("MONO");
      }else{
        lcd.print("ST  ");
      }
    }
    if(nMode==3){
      char buf[16];
      lcd.setCursor(0, 1);
      lcd.print("                ");
      
      lcd.setCursor(2, 1);
      sprintf(buf, "%02d", nVolume);
      lcd.print(buf);
    }
}

void prtHz()
{
  char buf[21];
  memset(buf, '¥0', sizeof(buf));
  dtostrf((float)fHz,6,2,buf);
  strcat(buf, "MHz");

  lcd.setCursor(1, 1);
  lcd.print(buf);

}
void setup(){
  Serial.begin(115200);

  Serial.println("start BuildNo 0.05-1");

  //save_EEPROM(771);
  int hz = load_EEPROM(0);
  Serial.println("setup 100");
  if(hz<0){
    hz=0;
  }
  fHz = (float)hz / (float)100.0;

  nVolume = load_EEPROM(1);
  Serial.print("volume=");
  Serial.println(nVolume);
  if(nVolume < 0 || 15 < nVolume){
    nVolume = 5;
  }
  
  Serial.println("setup 110");
  oldHz = fHz;
 
  delay(200);
  
  Serial.println("setup 120");
  
  radio.init();

  Serial.println("setup 200");
  
  //radio.debugEnable();
  radio.setBandFrequency(FIX_BAND, fHz*100);
  radio.setVolume(nVolume);
  radio.setMono(false);
  radio.setMute(false);

  //lcd 初期化
  lcd.begin(16, 2);
  lcd.setContrast(10);
  //
  displaySet();
//  lcd.print("FM Radio! ");
//  prtHz();
//  lcd.setCursor(11, 1);
//  lcd.print("ST  ");

  //
  pinMode(2, INPUT);
  pinMode(3, INPUT);


  lastTm = millis();

}

void loop() {
//  lcd.setCursor(0, 1);
//  lcd.print(millis()/1000);

  //
  int nDisplayFlag = 0;
  int val4Flag=0;
  int val2 = digitalRead(2);  //くるぐる
  int val3 = digitalRead(3);  //ぐるぐる
  int val4 = digitalRead(4);  //ModeSW
  if(old4!=val4){
    if(val4==1){
      if(val2==1){
        nMode = nMode + 1;
        if(nMode > 3){
          nMode = 0;
        }
        Serial.println(nMode);
        nDisplayFlag = 1;
      }
    }
    old4=val4;
  }
  if(old2!=val2){
    if(val2==1){
      if(nMode==0 || nMode==1){
        if(val3==0){
          if(nMode==1){
            fHz = fHz + 0.01; 
            val4Flag=1;
          }
          else{
            fHz = fHz + 0.1;
          }
        }
        else{
            if(nMode==1){
              fHz = fHz - 0.01;
              val4Flag=1;
            }
            else{
              fHz = fHz - 0.1;
            }
        }
        //Serial.println(fHz);
        Serial.println(fHz);
        nDisplayFlag = 1;
        prtHz();
        lastTm=millis();
      }
      if(nMode==2){
        if(modeMONO==false){
          modeMONO=true;
          Serial.println("modeMONO=true"); 
          //lcd.setCursor(11, 1);
          //lcd.print("MONO");
          nDisplayFlag = 1;
        }
        else{
          modeMONO=false;
          Serial.println("modeMONO=false"); 
          //lcd.setCursor(11, 1);
          //lcd.print("ST  ");
          nDisplayFlag = 1;
        }
        //Serial.println(fHz);
        Serial.println(fHz);
        nDisplayFlag = 1;
        prtHz();
        lastTm=millis();
      }
      if(nMode==3){
        if(val3==0){
          nVolume = nVolume + 1;
          if(nVolume>15){
            nVolume = 15;
          }
          radio.setVolume(nVolume);
        }
        else{
          nVolume = nVolume -1;
          if(nVolume<0){
            nVolume = 0;
          }
          radio.setVolume(nVolume);
        }
        //Serial.println(fHz);
        Serial.println(nVolume);
        nDisplayFlag = 1;
        save_EEPROM(1, nVolume);
      }
    }
    old2=val2;
  }
  long now = millis();
  if((now-lastTm)>1000){
    if(oldHz!=fHz){
      Serial.print("set:");
      Serial.print(fHz);
      Serial.println("MHz");
      radio.setMute(true);
      //radio.init();
      radio.setBandFrequency(FIX_BAND, fHz*100);
      //radio.setVolume(nVolume);
      //radio.setMono(false);
      radio.setMute(false);

      save_EEPROM(0, fHz*100);
      oldHz = fHz;
    }
  }
  //
  if(nDisplayFlag == 1){
    displaySet();
  }
}

 
JUGEMテーマ:Arduino