R/Cサーボはpwm(pulse wave modulation)で制御する,マイコンと相性の良い動力源ですね。

またモーターは別電源で動き,制御信号のロジック回路はインデペンデントに普通にマイコンにつなぐ事ができます。

ArrduinoではたいていのMCU向けにサーボライブラリが用意されていますが,小さなMCUに数台のサーボをつなぐのはなかなかの負担です。

それなら,仕事を分担という事でATtiny1604で小規模なサーボドライバを試してみました。


メインのMCUはSeeed studio XIAO ESP32-C3です。
DCモーター2台はpwmでメインから直接制御する予定です。






メインのMCUとATtiny1604のドライバ,R/Cサーボとの概略の配線図です。

・サーボは5Vの別電源,ロジックは3.3Vです。
 なお,GNDは忘れないようにすべて接続します。

・サーボはpwmが使えるPinに接続する必要があります。
 ATtiny1604ではI2Cを使うと4チャンネルまでです。

・I2CのSCLとSDAのプルアップも他に無ければ忘れずに(^^;;;;;







今のところ動いてくれていますV(^^)。
サーボドライバのチェク用とドライバ内のプログラムをメモしておきます。


チェックプログラムです。
動きが細かすぎたので,,じわっじわっと動きます(^^;;;;;;。

/* I2C Check_send */

// I2C Tarrget Slave Address 6
#include <Wire.h>
#define slave_Address 6

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

void loop() {
 for (int i = 0; i < 4095; i++){
   Wire.beginTransmission(slave_Address);
     Wire.write(1);
     Wire.write((byte)(i & 0x00FF));
     Wire.write((byte)(i >> 8));
   Wire.endTransmission();
   delay(20);
 }
}





ドライバのATtiny1604のプログラムです。

・I2Cデータ入力からのインタラプトを使っています。
 サーボ処理のせいかポーリングでは取りこぼしが発生しました,,。

・サーボ数が増えると結構メモリが必要ですね。
 ピン数が同じATtiny404ではメモリ不足のワーニングが出ました(^^;;;;;。


/** R/C Servo Controll test, ATtiny1604 I2C **/

// I2C : Slave, SCL_Pin PB0, SDA_Pin PB1
// 12bit In (0 - 4095) -- > Servo controll (0 - 180)

// I2C Slave Address 6
#include <Wire.h>
#define slave_Address 6

volatile byte rByte[32];  // data buffer


// R/C Servo 1-4
#include <Servo.h>
Servo myservo1;
Servo myservo2;
Servo myservo3;
Servo myservo4;
#define servo1_Pin 0
#define servo2_Pin 1
#define servo3_Pin 5
#define servo4_Pin 10


void setup() {              /* Set Up */

 // Setting for R/C Servo
 myservo1.attach(servo1_Pin);
 myservo1.write(90);
 myservo2.attach(servo2_Pin);
 myservo2.write(90);
 myservo3.attach(servo3_Pin);
 myservo3.write(90);
 myservo4.attach(servo4_Pin);
 myservo4.write(90);
 delay(1000);

 // Start I2C, Slave_Address=6
 Wire.begin(slave_Address);
 // Interrupt Service Routine
 Wire.onReceive(dataReceive);  

} // setup end


void loop() {                   /* main loop */

 // recieve_Data from I2C
 byte servo_Number =rByte[0]; // Recieve data
 int servo_Lval = (int)rByte[1];
 int servo_Hval =(int)rByte[2];

 // Analog data (12bit)
 int servo_orgVal = servo_Lval + servo_Hval*256;
 //data Convert (0-180 degree)
 int servo_posVal = map(servo_orgVal, 0x0000, 0x0FFF, 0, 180);

 servo_Position(servo_Number, servo_posVal);

 delay(20);

} //loop end


void dataReceive(){
 byte rbyteNumber=0;
 while (Wire.available()>0){     
   rByte[rbyteNumber]=Wire.read();
   rbyteNumber=rbyteNumber+1;
 }
}


void servo_Position(byte servo_num, int servo_pos){

 switch (servo_num-1) {
   case 0:
     myservo1.write(servo_pos);
   break;
   case 1:
     myservo2.write(servo_pos);
   break;
   case 2:
     myservo3.write(servo_pos);
   break;
   case 3:
     myservo4.write(servo_pos);
   break;
 }

 delay(20);  // wait for servo move
}