2022年8月30日火曜日
2022年8月16日火曜日
SCCBバスプロトコル詳解と実装方法
■SCCB紹介
SCCB (Serial Camera Control Bus) は、OmniVision社のシリアル カメラ バス プロトコルです。OV7670 などの OV で始まるカメラ モジュールは、SCCB プロトコルを使用します。I2C プロトコルと類似しているため、SIO_C、SIO_DをSCL、SDAと呼びます。
本文は2線式SCCBプロトコルの内容とプログラム実装を中心に解説します。
■回路図
2線式SCCBに対して、SIO_CとSIO_Dだけを接続すればよいです。
■プロトコルの内容とプログラム実装
2 線式 SCCB バス
プロトコル解析
<1>送信開始フラグ: 送信 (データの読み取りまたは書き込み) ごとに、下図に従って SIO_C と SIO_D に指定されたHIGH-LOWレベルを出力する必要があります。対応するレベルを受け取ると、Slaveは転送開始が判ります。次のように操作します。SIO_CがHIGHのままでSIO_DをHIGHからLOWに変換して、SIO_CをLOWに戻ります。
void SCCB_Start(void) {
SCCB_SDA = 1;
SCCB_SCL = 1;
delay_us(50);
SCCB_SDA = 0;
delay_us(50);
SCCB_SCL = 0;
}
<2>送信完了フラグ:Slaveに送信完了を通知します。次のように操作します。SIO_CがHIGHのままでSIO_DをLOWからHIGHに変換します。
void SCCB_Stop(void) {
SCCB_SDA = 0;
delay_us(50);
SCCB_SCL = 1;
delay_us(50);
SCCB_SDA = 1;
delay_us(50);
}
<3>伝送フェーズ
<4>書き込み
フェーズ1:SCCBプロトコルは複数のSlaveに転送ができるため、Slaveの番号が伝える必要があります。実際のIDアドレスは8bitで、bit7~bit1はSlaveの番号ですが、0~127のトータル128のSlaveに転送が可能です。bit0はSlaveにデータを書き込み(0)か読み取り(1)かを示しています。9bit目はDon't
careビット(上図Xのビット)です。例えば、OV7670の場合、Masterから 8bitのデータを受信した後、SIO_C=1の期間にSlaveはSIO_DピンにLOWをセットします。この間、MasterはSIO_Dのレベル情報を読み取って判断する、LOWレベルを読み取った場合は、Slaveはフェーズ1の最初8bitを正常受信したことを示して、送信は成功します。それ以外の場合、送信は失敗します。
フェーズ2:データが書き込まれるレジスタの番号をスレーブに送信します。レジスタの番号は、OVセンサーのデータシートに記載されています。レジスタの番号も 8bitのデータです。
同様に、フェーズ2の9bit目もDon't careビットであり、このbitの説明はフェーズ1と同じです。
u8 SCCB_WR_Byte(u8 dat) { // 一つフェーズを書き込み
u8 j, res;
for (j = 0; j < 8; j++) {
if (dat&0x80) SCCB_SDA = 1;
else SCCB_SDA = 0;
data<<=1;
delay_us(50);
SCCB_SCL = 1;
delay_us(50);
SCCB_SCL = 0;
}
SCCB_SDA_IN(); // 或いはpinMode(SDA, INPUT); Slaveは値をセット可能
delay_us(50);
SCCB_SCL = 1; // SCLをHIGHにする、Slaveはデータを受信した後、SDAをLOWに
delay_us(50);
if (SCCB_READ_SDA) res = 1; // SDAはHIGHの場合、送信失敗
else res = 0; // 送信成功
SCCB_SCL = 0;
SCCB_SDA_OUT(); // あるいは pinMode(SDA, OUTPUT);
Return res;
}
三つフェーズを書き込みの関数:
u8 SCCB_WR_Reg(u8 reg, u8 data) {
u8 res = 0;
SCCB_Start();
If (SCCB_WR_Byte(SCCB_ID)) res = 1; // OV7670の場合は0x42
delay_us(100);
if (SCCB_WR_Byte(reg)) res = 1;
delay_us(100);
if (SCCB_WR_Byte(data)) res = 1;
SCCB_Stop();
return res;
}
<5>読み取り操作
Slaveのレジスタから 1 バイトのデータを読み取る時、次の 2 つのデータ送信プロセスが必要です。
①2 フェーズ書き込み送信プロセス:MasterからSlaveに2フェーズを送信します。最初のフェーズは、スレーブの ID 番号を示します。 2 番目のフェーズは、スレーブのどのレジスタから読み取るかを示します。
NAを送信するために、MasterはSIO_DをHIGHにセットしたままで、SIO_CをLOWからHIGHに変更してからLOWに戻る必要があります。
void SCCB_No_Ack(void) {
delay_us(50);
SCCB_SDA = 1;
SCCB_SCL = 1;
delay_us(50);
SCCB_SCL = 0;
delay_us(50);
SCCB_SDA = 0;
delay_us(50);
}
2フェーズを読み取り関数
u8 SCCB_RD_Byte(void) {
u8 temp = 0, j;
SCCB_SDA_IN();
for (j = 8; j > 0; j--) {
delay_us(50);
SCCB_SCL = 1;
temp = temp << 1;
if (SCCB_READ_SDA) temp++;
delay_us(50);
SCCB_SCL = 0;
}
SCCB_SDA_OUT();
return temp;
}
レジスタから読み取り関数:
u8 SCCB_RD_Reg(u8 reg) {
u8 val = 0;
SCCB_Start();
SCCB_WR_Byte(SCCB_ID);
delay_us(100);
SCCB_WR_Byte(reg);
delay_us(100);
SCCB_Stop();
SCCB_Start();
SCCB_WR_Byte(SCCB_ID|0x01);
delay_us(100);
val = SCCB_RD_Byte();
SCCB_No_Ack();
SCCB_Stop();
return val;
}
2022年8月11日木曜日
PWMの理解ーーその2:ブザーで音楽
■周波数
PWMとは、Pulse Width Modulationの略で、波長のような制御を行います。
細かい部分で見ると、ONとOFFを一定間隔で繰り返しているだけです。
ここで周波数といった名前が登場しますが、ONの長さの事を指します。
ブザーにとっての周波数とは、ドレミの音階を指定することができることになります。
ESP32では、PWM制御の関数が用意されております。(ledcSetup、ledcAttachPin、ledcWriteTone)
■音階
音階は、「音を高低の順番に並べたもの」あり、音の高低は周波数で表します。
音は、周波数が半分になると1オクターブ低くなり、周波数が倍になると1オクターブ高くなります。
1オクターブには12の音があり(①ド、②ド#(レ♭)、③レ、④レ#(ミ♭)、⑤ミ、⑥ファ、⑦ファ#(ソ♭)、⑧ソ、⑨ソ#(ラ♭)、⑩ラ、⑪ラ#(シ♭)、⑫シ)、
その12の音は、隣り合う半音間での周波数の比率が同じです。(音階に対して等比数列的に増える)
音階と周波数の関係は下記サイトをご参照ください。
■配線図
■プログラム
#define BUZZER_PIN 2 // ブザーのピン番号#define BUZZER_CHANEL 0 // ブザーのチャネル番号#define BEAT 250 // 音の長さ(0.25秒間隔)#define G3 196 // ソ3#define C4 261.6 // ド4 1#define D4 293.665 // レ4 2#define E4 329.63 // ミ4 3#define F4 349.228 // ファ4 4#define G4 391.995 // ソ4 5#define A4 440 // ラ4 6#define B4 493.883 // シ4 7#define C5 523.251 // ド5 ivoid playTone(double tone, int num) {ledcWriteTone(BUZZER_CHANEL, tone);delay(BEAT * num);}void playTone(long tone) {playTone(tone, 2);}void playMusic() {// 1 2 3 1 | 1 2 3 1 | 3 4 5 - | 3 4 5 - |// 56543 1 | 56543 1 | 3 5 1 - | 3 5 1 -playTone(C4);playTone(D4);playTone(E4);playTone(C4);playTone(C4);playTone(D4);playTone(E4);playTone(C4);playTone(E4);playTone(F4);playTone(G4, 4);playTone(E4);playTone(F4);playTone(G4, 4);playTone(G4, 1);playTone(A4, 1);playTone(G4, 1);playTone(F4, 1);playTone(E4);playTone(C4);playTone(G4, 1);playTone(A4, 1);playTone(G4, 1);playTone(F4, 1);playTone(E4);playTone(C4);playTone(E4);playTone(G3);playTone(C4, 4);playTone(E4);playTone(G3);playTone(C4, 4);}void setup() {ledcSetup(BUZZER_CHANEL, 12000, 8);ledcAttachPin(BUZZER_PIN, BUZZER_CHANEL);}void loop() {playMusic();delay(1000);}
2022年8月9日火曜日
ESP32-C3開発ボードに書き込みできない解決方法
■問題
ARDUINO環境で、ESP32-C3の開発ボードに書き込み時、下記エラーが出てます。
A fatal error occurred: Invalid head of packet (0x47)
■原因
新発行のESP32-C3開発ボードに対して、ARDUINOはまたサポートしておりません。
解決方法としては最新のLIBをインストールする
■インストール手順:
・最新版ARDUINOをダウンロード&インストールする
https://www.arduino.cc/en/software
・最新のESP32LIBを切り替える
https://github.com/espressif/arduino-esp32から、ESP32をZIPでダウンロードする
に解凍する
解凍後はこのイメージです
・tools\get.exeを実施するPWMの理解ーーその1:雰囲気ランプ
■ESP32-C3開発ボード
ESP32-C3はLEDコントローラーが持っています。これを使って、簡単に雰囲気ランプ効果ができます。
今回は、ESP-C3-32開発ボードを利用します。下記ようなものです。
上図をみると、IO3、IO4、IO5のいずれもRGB LEDを繋がっています(それぞれはR、G、Bです)から、サンプルとして、今回はIO3(赤色)を利用しましょう。
PWMをコントロールするために、下記設定が必要です:
1、タイマーを配置: のDuty比率を指定する
2、チャネルを配置:PWMデータ出力のGPIO
3、ハードウェアのFadeOn機能を利用し、LEDの明るさを変更する
楽鑫は相応の構造体を提供しました。提供している構造体を利用してやりやすいです。
ledc_timer_config_t ⇒ タイマー配置用
ledc_channel_config_t ⇒ チャネル配置用
■プログラム
ledcはESP32のLED用高精度PWM機能です。通常のPWMだけでなく、ledc_set_fade_with_timeとledc_fade_startを使えば自動的に指定秒数でfadeしてくれて大変便利。
#include <stdio.h>#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "driver/gpio.h"#include "driver/ledc.h"#include "sdkconfig.h"#include "driver/ledc.h"#define BLINK_GPIO_R 3#define BLINK_GPIO_G 4#define BLINK_GPIO_B 5#define LEDC_TEST_DUTY 1000#define LEDC_TEST_FADE_TIME 2000ledc_timer_config_t ledc_timer;ledc_channel_config_t ledc_channel;void setup() {ledc_timer.duty_resolution = LEDC_TIMER_10_BIT; // PWM Dutyledc_timer.freq_hz = 1000; // PWM信号の周波数ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE; // タイマーモード(低速)ledc_timer.timer_num = LEDC_TIMER_0; // タイマー インデックスledc_timer_config(&ledc_timer);ledc_channel.channel = LEDC_CHANNEL_0;ledc_channel.duty = 0;ledc_channel.gpio_num = BLINK_GPIO_R;ledc_channel.speed_mode = LEDC_LOW_SPEED_MODE;ledc_channel.timer_sel = LEDC_TIMER_0;ledc_channel_config(&ledc_channel);ledc_fade_func_install(0);}void loop() {ledc_set_fade_with_time(ledc_channel.speed_mode, ledc_channel.channel, LEDC_TEST_DUTY, LEDC_TEST_FADE_TIME);ledc_fade_start(ledc_channel.speed_mode, ledc_channel.channel, LEDC_FADE_NO_WAIT);vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS);ledc_set_fade_with_time(ledc_channel.speed_mode, ledc_channel.channel, 0, LEDC_TEST_FADE_TIME);ledc_fade_start(ledc_channel.speed_mode, ledc_channel.channel, LEDC_FADE_NO_WAIT);vTaskDelay(LEDC_TEST_FADE_TIME / portTICK_PERIOD_MS);}
■最終結果
■RGBを同時コントロールの場合、構造体はこのような実装する
ledc_channel_config_t ledc_channel[3];ledc_channel[0].channel = LEDC_CHANNEL_0;ledc_channel[0].duty = 0;ledc_channel[0].gpio_num = BLINK_GPIO_R;ledc_channel[0].speed_mode = LEDC_LOW_SPEED_MODE;ledc_channel[0].timer_sel = LEDC_TIMER_0;ledc_channel[1].channel = LEDC_CHANNEL_1;ledc_channel[1].duty = 0;ledc_channel[1].gpio_num = BLINK_GPIO_G;ledc_channel[1].speed_mode = LEDC_LOW_SPEED_MODE;ledc_channel[1].timer_sel = LEDC_TIMER_1;ledc_channel[2].channel = LEDC_CHANNEL_2;ledc_channel[2].duty = 0;ledc_channel[2].gpio_num = BLINK_GPIO_B;ledc_channel[2].speed_mode = LEDC_LOW_SPEED_MODE;ledc_channel[2].timer_sel = LEDC_TIMER_2;ledc_channel_config(&ledc_channel[0]);ledc_channel_config(&ledc_channel[1]);ledc_channel_config(&ledc_channel[2]);
2022年8月6日土曜日
MQTTプロトコル紹介
■MQTTとは
MQTT(Message Queue Telemetry Transport)は、発行/購読型のメッセージ処理を実現するための軽量なプロトコルとして設計されています。
メッセージのサブスクライバー(購読者)は、メッセージのパブリッシャー(発行元)が提供する MQTT トピックをあらかじめ講読しておきます。MQTT トピックに何か変化があると、サブスクライバーは PUBLISH コマンドを受け取ってそれを知ることができます。
ネットワークが不安定な場所や、性能が低いデバイスでも動くように軽量化されているのが特徴で、TCP/IP ネットワークをベースに作られています。
■HTTPとMQTTの比較
| HTTP | MQTT | |
| 同期/非同期 | 同期 | 非同期 |
|---|---|---|
| 送受信対象 | 1対1 | 多対多 |
| データ量 | 大きい(重い) | 小さい(軽い) |
| 通信が不安定 | ×(送受信不可) | ○(再送受信可能) |
シンプルロボットカーセットの使い方
■ マイコン :ESP3266-CH340 シンプルの案として、マイコンは安いESP8266-CH340開発ボードを選びました。該当マイコンもWIFI機能があります。 ドライバーダウンロード場所: https://sparks.gogo.co.nz/ch340.html...
-
本文は気象関連センサーの使い方のまとめ紹介 ■部品リスト: ・ ESP8266開発ボード (必須) ・ブレッドボード (必須) ・ USBケーブル (必須) ・ 温度センサー DS18B20(必須) ・雨滴感知センサー (必須) ・気圧センサーBPM180 (必須) ・3mm ...
-
■ マイコン :ESP3266-CH340 シンプルの案として、マイコンは安いESP8266-CH340開発ボードを選びました。該当マイコンもWIFI機能があります。 ドライバーダウンロード場所: https://sparks.gogo.co.nz/ch340.html...
-
■目的: 携帯などでロボットカーの運転をコントロールために、 ESP8266のAPモードで、コントロール用サイトを構築する。 ソースは下記通り: ■プログラム: #include <ESP8266WiFi.h> #include <ESP8266WebSe...














