現在、ESP32とSC16IS740とをI2Cで接続してUARTポートを増設使用と思っています。
http://nopnop2002.webcrow.jp/SC16IS75x/SC16IS750-1.html
こちらのサイトのサンプルプログラムなどを参考にしました。
しかし、コンパイルして書き込んだところ、次のようなシリアル通信が戻ってきます。
start i2cuart
device not found
ESP32がSC16IS750と通信できていないように感じます。
cpp
1ーーーーーー(中略)ーーーーーーーーーーーーーーーーーー 2if (i2cuart.ping()!=1)
ここでデバイスからの応答が戻ってきていないように感じます。
i2cScanner.inoというスケッチを起動したところ、
Scanning...
I2C device found at address 0x48 !
done
このようなシリアル通信の返答があるので、I2Cの接続は問題ないように感じます。
なぜ、下記のプログラムでは応答が受信できないのか、
何か確認した方が良い箇所や修正箇所などご教示頂きますよう、よろしく御願い致します。
cpp
1#include <Wire.h> 2#include <SC16IS750.h> 3#include <string.h> 4#include <SPI.h> 5 6SC16IS750 i2cuart = SC16IS750(SC16IS750_PROTOCOL_I2C,SC16IS750_ADDRESS_AA); 7 8//Connect TX and RX with a wire and run this sketch 9 10#define baudrate 9600 11//#define baudrate 57600 12//#define baudrate 115200 13//#define baudrate 230400 14//#define baudrate 460800 15//#define baudrate 921600 16 17void setup() 18{ 19 Serial.begin(115200); 20 21 //int SDA1=21 ;GPIO21を割当 2020/0528追加 22 //int SCL1=22 ;GPIO22を割当 2020/0528追加 23 Wire.begin(21,22); // wake up I2C bus 2020/0528追加 24 25 26 Serial.println("start i2cuart"); 27 // UART to Serial Bridge Initialization 28 i2cuart.begin(baudrate); //baudrate setting 29 if (i2cuart.ping()!=1) { 30 Serial.println("device not found"); 31 while(1); 32 } else { 33 Serial.println("device found"); 34 } 35 Serial.print("start serial communication. baudrate = "); 36 Serial.println(baudrate); 37} 38 39void loop() 40{ 41 static char buffer[64] = {0}; 42 static int index = 0; 43 44 if (i2cuart.available() > 0){ 45 // read the incoming byte: 46 char c = i2cuart.read(); 47 48#if 0 49 Serial.print("c="); 50 if (c < 0x20) { 51 Serial.print(" "); 52 } else { 53 Serial.print(c); 54 } 55 Serial.print(" 0x"); 56 Serial.println(c,HEX); 57#endif 58 59 if (c == 0x0d) { 60 61 } else if (c == 0x0a) { 62 Serial.print("["); 63 Serial.print(buffer); 64 Serial.println("]"); 65 index = 0; 66 } else { 67 buffer[index++] = c; 68 buffer[index] = 0; 69 } 70 } 71} 72
アドレスのピンによりスレーブアドレスが変えれるようですが、そこらへんの接続はどうなってるでしょうか
回路図を提示しましょう
> ESP32がSC16IS750と通信できていないように感じます。
なら、ライブラリの上からではなく、I2Cで直接通信してみるプログラムを書いてどのレベルで「通信できない」のかを確かめてみればよいのではないのでしょうか?
i2cuart.begin(baudrate);の前後それぞれにdelayで100msとか待ち入れるとどうなります?
回答頂きありがとうございます。
'''
delay(100);
i2cuart.begin(baudrate); //baudrate setting
delay(100);
'''
このように前後に100msecのdelay入れてみたのですが、結果は変わらず、Serial.println("device not found");のルーチンに行ってしまいます。
質問文の中でも書いているのですが、i2cのラインに接続したデバイスとの通信ができているかを確認できるi2cScanner.inoを書き込んで起動させると
Scanning...
I2C device found at address 0x48 !
done
このようにアドレス0x48と表示は出てくるので、i2cラインでの通信は一応できているようなのです。
https://github.com/KenjiMaehara/esp32_ILI9488Ctl/blob/master/exsamples/i2cScanner/i2cScanner.ino
thkanaさんの言う通り、SC16IS750.h使わずにi2c通信して動作させて、ライブラリが悪いのかそれ以前の問題なのか切り分けたほうが良いと思います。
> i2cScanner.inoを書き込んで起動させると
そのレベルでは解決出来ないのならば、中に踏み込んで調べるしかないでしょう。
i2cScannerってのは
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
pingは https://github.com/SandboxElectronics/UART_Bridge/blob/master/SC16IS750.cpp
WriteRegister(SC16IS750_REG_SPR,0x55);
if (ReadRegister(SC16IS750_REG_SPR) !=0x55) {
return 0;
}
WriteRegister(SC16IS750_REG_SPR,0xAA);
if (ReadRegister(SC16IS750_REG_SPR) !=0xAA) {
return 0;
}
writeRegister/readRegisterの定義もページ内にあるから、エラーになる原因を探ってみては。
(そう言えば、M5Stackで一時期I2Cライブラリの問題かなにかで内蔵のIMUが読めなかったことがあったっけか。2年位前?)
回答頂きありがとうございます。
SC16IS740のICは16pinのものを使用しています。2番ピン(A0)、3番ピン(A1)はともにVCCとしています。
今気が付いたのですが、
https://www.nxp.com/docs/en/data-sheet/SC16IS740_750_760.pdf
データシートの10ページ付近の10.3Adressingを読んでいると、A0,A1をVCCに接続した場合のアドレスは0x90とのことですが、i2cScanner.inoでの結果は”0x48”と表示されてしまうのですが、アドレスが一致しないということは何か不具合が起きているということでしょうか?
「I2Cのアドレス」といった場合、
本当にアドレスだけの場合とR/Wビットを含めるかの2つの流儀があって、
今回の場合は1001_000X (X=Write:0 / Read:1)を0x90とデータシートでは表現してますが
W/R部分であるXを抜いた先頭7bitを抜き出すと0x48です
要するにそれであってます。
回答頂きありがとうございます。0bit目はread or writeを表しているのですね。
SC16IS750.cppのpingが通過できない原因を見るために、
WriteRegisterで0x55を書いた後のReadRegisterの値が0xffと出てくることがわかりました。
ちょっとWriteRegister、ReadRegisterなども探っていきたいと思います。
uint8_t SC16IS750::ping()
{
int test=0;
WriteRegister(SC16IS750_REG_SPR,0x55);
test = ReadRegister(SC16IS750_REG_SPR);
Serial.print("0x");
Serial.println(test,HEX);
if (ReadRegister(SC16IS750_REG_SPR) !=0x55) {
return 0;
}
WriteRegister(SC16IS750_REG_SPR,0xAA);
test = ReadRegister(SC16IS750_REG_SPR);
Serial.print("0x");
Serial.println(test,HEX);
if (ReadRegister(SC16IS750_REG_SPR) !=0xAA) {
return 0;
}
return 1;
}
回答頂きありがとうございます。
解決しました!
SC16IS750.cppの29行目あたりの
#ifdef __AVR__
#define WIRE Wire
#else // Arduino Due
#define WIRE Wire1
#define WIRE Wire
#endif
この部分を上記のように#elseのルーチンに”#define WIRE Wire”を追加すればよいことが判りました。
ESP32用にはなってなかったのですね。
#ifdef __AVR__
#define WIRE Wire
#elif ESP32
#define WIRE Wire
#else // Arduino Due
#define WIRE Wire1
#endif
こうやっても同じことのようです。
助かりました。
今更なんですけど、ESP32はハードウェアUARTを3つ積んでるので
ピンが余っているならわざわざSC16IS750で増設しなくても良いんですが
なにか使わないといけない理由あります?
SC16IS750を使う理由なんですが、uart機能を持ったレガシーモジュールを最終的に5~6個接続したいという要望があるんです。なるべくESP32の1台に対して詰め込みたいらしく、また更に詰め込む予定もあるとかで、それでI2Cになるべく移したいという感じなんです(^^; やはりそういうのは難しいのでしょうか?
そういうことでしたか
5個以上となるとそうしたほうが良いですね
回答2件
あなたの回答
tips
プレビュー