モグラ叩きの動きをいろいろと試しているうち,RCサーボの動きが「ひょっこり」に見えてきました(^^;;。

そこで,急ごしらえではあるのですがRCサーボ4台で動く「ひょっこりモグラタワー」なるものを作ってみました。


[外観]
PCの梱包用ダンボールで組んでみたタワーと「元祖モグラ叩きゲーム」から外したモグラ4匹です。左右にひょっこり出てきます(^^)。





[機材]
Arduino で動くRaspberry Pi PicoとI2C接続のサーボコントローラです。

MPU : Raspberry Pi Pico
Servo Controller : PCA9685 (16ch)
RC Servo : SG-90 (超廉価版)

モグラはサーボアームにホットボンドで直結です。





[動画]

簡単なプログラムで動かしてみました。一斉に動くと結構揺れます(^^;;;;;.

じわっと動く動作の後にランダムな動きを試してみましたが,,イマイチですかね,,。






[プログラム]
 つたない例ですが,ま,動いていますのでメモしておきます(^^;;;;。


1)サーボコントローラのPCA9685の設定などは今まで通りです。

16chのRCサーボコントロールモジュール(AE-PCA9685)を使ってモグラを出そうと試作中


/* PCA9685 for 16ch Servo controll OSC:25MHz
MODE1_REG:0x00 PRESCALE__REG:0xFE
LED0_ON_L, ON_H, OFF_L, OFF_H ---> LED15
0x06 0x07 0x08 0x09 ---> 0x42,43,44,45
Raspberr Pi Pico, I2C (SDA:GP4, SCL:GP5) */

#include <Wire.h>
#define PCA9685 0x40

void I2C__write (byte reg, byte val){
Wire.beginTransmission(PCA9685);
Wire.write(reg); Wire.write(val);
Wire.endTransmission();
}

void setup() {
Wire.begin();
// set prescale for 50Hz, OSC:25MHz
// prescale:25000000/(4096*50)-1
I2C__write (0x00, 0b00010001); // MODE1 sleep mode on
I2C__write (0xFE, 121); // set prescale for 50Hz
I2C__write (0x00, 0b00100001); // sleep off and auto inc.
}



2)サーボのポジション設定を角度から行ったりするルーチンです。

16chのRCサーボコントローラー(PCA9685)に角度からのポジション設定ルーチンを追加


void setPos_all(int dv){ // Set all Servo
for (byte i=0; i<4; i++){
setPosition (i, dv);
}
}

void setPos_slow(byte ch, int sdv, int edv){
if (edv > sdv){
for (int i=sdv; i setPosition (ch, i);
delay(20);
}
} else {
for (int i=sdv; i>edv-1 ;i--){
setPosition (ch, i);
delay(20);
}
}
}


/* Set servo position
PCA9685:50Hz, 20ms(4095)
SG-90 Servo Degree Duty cycle Pulse length
0 0.5 ms 102
90 1.45ms 297
180 2.4 ms 491
*/

void setPosition (byte ch, int pos){
if (ch<16 && pos<181){
unsigned int plen=(unsigned int)pos*216/100+102; // pulse length
Wire.beginTransmission(PCA9685);
Wire.write(ch*4+0x06); // set register of servo ch.
Wire.write(0x00); // ON_L
Wire.write(0x00); // ON_H
Wire.write(lowByte(plen)); // OFF_L
Wire.write(highByte(plen)); // OFF_H
Wire.endTransmission();
delay(20);
}
}




3)loop部です。
 長ったらしくいろいろ動きを試していますが,,ま,メモとして(^^;;;;;;。

void loop() {
setPos_all(90);delay(1000);

// ALL L-> M-> R-> M
setPos_all(45);delay(1000);
setPos_all(90);delay(1000);
setPos_all(135);delay(1000);
setPos_all(90);delay(1000);

// One by One, R:0->3, L: 0->3
for (byte i=0; i<4; i++){
setPosition (i, 45);delay(500);
}
for (byte i=0; i<4; i++){
setPosition (i, 135);delay(500);
}
setPos_all(90);delay(1000);

// One by One, R<->L
for (byte i=0; i<3; i=i+2){
setPosition (i, 45);delay(500);
setPosition (i+1,135);delay(500);
}
for (byte i=0; i<3; i=i+2){
setPosition (i, 135);delay(500);
setPosition (i+1,45);delay(500);
}
setPos_all(90);delay(1000);

// One by One, R_step<->L_step
for (byte i=0; i<4; i++){
setPosition (i, 90-11*(i+1));delay(500);
}
for (byte i=4; i>0; i--){
setPosition (i-1, 90+11*i);delay(500);
}
setPos_all(90);delay(1000);

// Move slowly 0:L, 3:R
setPos_slow(0, 90, 45);
setPos_slow(0, 45, 90);
setPos_slow(3, 90,135);
setPos_slow(3,135, 90);

// Move random
long rseed=analogRead(26)*millis();
randomSeed(rseed);
for (byte i=0; i<20; i++){
int rd[]={45,135};
setPosition (random(4), rd[random(2)]);delay(500);
}
}




私の本題のモグラ叩きから横道にそれていますけど,サーボ直結は楽なのにプログラムで色々できてなにか楽しいですね(^^)。

これはこれとして,「ひょっこり」の動きもいろんな場面で使えそうです。