お久しぶりです。今回は電子工作の回です。手元にある部品で何か作れないかな?と思い寄せ集めの部品で回路を作りましたのでレポート兼備忘録を書くことにしました。
筆者は素人みたいなものでして、これよんでこうしたほうがいいよ!とかここどうなってるの?とかそんなことも知らないの?とかアドバイスやコメント、質問等あればTwitteなりコメントお願いいたします!
1. とりあえずの目標
有翼飛行機(ラジコン?)を自作したときに自動でサーボでローイング、ヨーイング、エレベーターを自動制御させてみたいな。というのが頭にあり作ってみることにしました。
まず最初の目標は三軸の(x軸、y軸、z軸)加速度を検知させて3個のサーボの制御をおこなうことです。もし可能なら三軸同時にタイムラグ少なく制御させたいですな。
2.概要
まずはシステムのざっくりな説明です
Arduino unoと三軸加速度センサ間の通信はSPI通信をしています。サーボの通信はPWM通信で動作させています。Arduino unoの電源はPCからUSBで給電しています。三軸加速度センサの電源はArduino unoの3.3Vから給電。サーボの電源は乾電池の6Vから給電しています。以下に使用した部品と制作した回路図、プログラムを記載します。
2.1使用した部品
Arduino uno
3軸加速度センサ LIS331
サーボ×3
乾電池4本(6V)
2.2回路図
手書きの回路図には電源を4Vと記載していますが間違えました。6Vです!
サーボは並列回路を組んで電源供給しています。
2.3使用したプログラム
3軸加速度センサーを動作させるためのプログラムがすでにネット上にあったのでそれをちょちょいと書き加えてサーボをなんとか動作させるようにはできました。
使用したプログラムのダウンロード先がどこだか覚えていません!ごめんなさい!たしかGit Hubにあった気がします。
以下プログラム
#include <SPI.h>
#include <stdlib.h>
#include <stdio.h>
#include <Servo.h>
Servo servo;
#define SS 10
#define MOSI 11
#define MISO 12
#define SCK 13
#define SCALE 0.000183105469;
double xAcc, yAcc, zAcc;
int Xpos = 0;
int Ypos = 0;
int Zpos = 0;
Servo Zservo;
void setup()
{
Serial.begin(9600);
SPI_SETUP();
Accelerometer_Setup();
}
void loop()
{
readVal();
Serial.print(Xpos);
Serial.print(",");
Serial.print(xAcc, 3);
Serial.print(",");
Serial.print(yAcc, 3);
Serial.print(",");
Serial.println(zAcc, 3);
Serial.print(",");
delay(1000);
}
void readVal()
{
byte xAddressByteL = 0x28;
byte readBit = B10000000;
byte incrementBit = B01000000;
byte dataByte = xAddressByteL | readBit | incrementBit;
byte b0 = 0x0;
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(dataByte);
byte xL = SPI.transfer(b0);
byte xH = SPI.transfer(b0);
byte yL = SPI.transfer(b0);
byte yH = SPI.transfer(b0);
byte zL = SPI.transfer(b0);
byte zH = SPI.transfer(b0);
delay(1);
digitalWrite(SS, HIGH);
int xVal = (xL | (xH << 8));
int yVal = (yL | (yH << 8));
int zVal = (zL | (zH << 8));
xAcc = xVal * SCALE;
yAcc = yVal * SCALE;
zAcc = zVal * SCALE;
Xpos = map(xVal,-10922.9929,10922.9929,0,180);
analogWrite(9,Xpos);
if(Xpos >= 0 && Xpos <= 30){
analogWrite(9,15);
delay(200);
servo.detach();
}
if(Xpos >= 30 && Xpos <= 60){
analogWrite(9,45);
delay(200);
servo.detach();
}
if(Xpos >= 60 && Xpos <= 90){
analogWrite(9,75);
delay(200);
servo.detach();
}
if(Xpos >= 90 && Xpos <= 120){
analogWrite(9,105);
delay(2000);
servo.detach();
}
if(Xpos >= 120 && Xpos <=150){
analogWrite(9,135);
delay(200);
servo.detach();
}
if(Xpos >= 150 && Xpos <= 180){
analogWrite(9,165);
delay(200);
servo.detach();
}
Ypos = map(yVal,-10922.9929,10922.9929,0,180);
analogWrite(5,Ypos);
if(Ypos >= 0 && Ypos <= 30){
analogWrite(5,15);
delay(200);
servo.detach();
}
if(Ypos >= 30 && Ypos <= 60){
analogWrite(3,45);
delay(200);
servo.detach();
}
if(Ypos >= 60 && Ypos <= 90){
analogWrite(3,75);
delay(200);
servo.detach();
}
if(Ypos >= 90 && Ypos <= 120){
analogWrite(5,105);
delay(2000);
servo.detach();
}
if(Ypos >= 120 && Ypos <=150){
analogWrite(5,135);
delay(200);
servo.detach();
}
if(Ypos >= 150 && Ypos <= 180){
analogWrite(5,165);
delay(200);
servo.detach();
}
Zpos = map(zVal,-10922.9929,10922.9929,0,180);
analogWrite(3,Zpos);
if(Zpos >= 0 && Zpos <= 30){
analogWrite(3,15);
delay(200);
servo.detach();
}
if(Zpos >= 30 && Zpos <= 60){
analogWrite(3,45);
delay(200);
servo.detach();
}
if(Zpos >= 60 && Zpos <= 90){
analogWrite(3,75);
delay(200);
servo.detach();
}
if(Zpos >= 90 && Zpos <= 120){
analogWrite(3,105);
delay(2000);
servo.detach();
}
if(Zpos >= 120 && Zpos <=150){
analogWrite(3,135);
delay(200);
servo.detach();
}
if(Zpos >= 150 && Zpos <= 180){
analogWrite(3,165);
delay(200);
servo.detach();
}
}
void SPI_SETUP()
{
pinMode(SS, OUTPUT);
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV16);
}
void Accelerometer_Setup()
{
byte addressByte = 0x20;
byte ctrlRegByte = 0x37;
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
delay(100);
addressByte = 0x21;
ctrlRegByte = 0x00;
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
delay(100);
addressByte = 0x23;
ctrlRegByte = 0x00;
digitalWrite(SS, LOW);
delay(1);
SPI.transfer(addressByte);
SPI.transfer(ctrlRegByte);
delay(1);
digitalWrite(SS, HIGH);
}
三軸加速度センサーから値を取得し、サーボの角度0度から180度の間の数値に置き換えています。その置き換えた数値をサーボに送信し動作させています。
3.動作結果
うーん、よくわかんないっす
絶えず細かく変化している加速度の値を読み込んでいます。その値を常時サーボに送っているせいかギシギシ動きまくっています。
電力不足なのかプログラムがよくないのか回路の組み方が悪いのかどれも考えられるので問題の切り離しをひとつづつやってかないと何にもわかんないだろうな・・・
考察は取り合えず後に回して後々追記していこうかと思います。(これじゃぁもらえるアドバイスなんてないだろうな・・・)そもそも勉強不足なのもあるしいろいろ調べてみます