質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

2回答

657閲覧

ArduinoとSeeeduinoのI2C通信によるモーター制御

SHIN_gen

総合スコア2

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

1クリップ

投稿2023/01/28 03:00

ArduinoとSeeeduinoはI2Cでつながっています。

seeduinoとArduinoのI2c通信を行っています。双方向の通信は出来ています。
現在、エンコーダー付きサーボモーターから角度を取る為にseeduinoをエンコーダー付きサーボモーターに接続しセンサー代わりに使っています。
従ってArduinoがmaster、Seeeduino側がslaveとなっております。
Arduinoから値を送りエンコーダー付きサーボモーターを制御する場合どのようにすればよいでしょうか。

・実現したいこと
I2c通信でArduinoから任意の値を送りSeeeduinoはその値を受信、その後受信した値を元にエンコーダー付きサーボモーターを制御する。そしてエンコーダー付きサーボモーターから得た現在の角度をSeeeduinoはarduinoへ送信する。ArduinoはSeeeduinoから受け取った値を表示する。

発生している問題・エラーメッセージ

'requestEvent' was not declared in this scope

該当のソースコード

Arduino(master)

1/*エンコーダー付サーボモーターを制御するArduino側master用 1/28*/ 2 3#include <Wire.h> 4 5void setup() { 6 Wire.begin(); 7 Serial.begin(9600); 8 9} 10 11byte sen1 = 0.0; 12 13void loop() { 14 15 Wire.requestFrom(8, 1); 16 Wire.beginTransmission(8); // transmit to device #8 17 Wire.write(sen1); // sends one byte 18 19 while (Wire.available()){ 20 21 byte a2 = Wire.read(); 22 Serial.println(a2); 23 24 //Wire.write("sen1 is "); // sends five bytes 25 Wire.write(sen1); // sends one byte 26 Wire.endTransmission(); // stop transmitting 27 28 sen1 =10; 29 } 30 delay(50); 31}

Arduino:seeeduino(slave)

1/*エンコーダー付サーボモーターを制御するSeeeduino側slave用*/ 2 3#include <Servo.h> 4#include <Wire.h> 5#define PI 3.141592; 6 7Servo myservo1; // create servo object to control a servo 8 9double pos1 = 90;// variable to store the servo position 10 11volatile long value1 = 0; 12volatile uint8_t prev1 = 0; 13 14unsigned long time; 15 16double t0; 17 18void setup() 19{ 20 /*I2c通信の設定「*/ 21 Wire.begin(8); 22 Wire.onRequest(requestEvent); 23 Wire.onReceive(receiveEvent); // register event 24 /*」*/ 25 26 /*ピン設定「*/ 27 pinMode(2, INPUT); //conect C2(Encoder A Phase) 28 pinMode(3, INPUT); //conect C1(Encoder B Phase) 29 attachInterrupt(2, updateEncoder1, CHANGE); 30 attachInterrupt(3, updateEncoder1, CHANGE); 31 //digitalWrite(7, HIGH); 32 //digitalWrite(8, HIGH); 33 myservo1.attach(10); //conect motor driver 34 /*」*/ 35 36 37 Serial1.begin(9600); //Serial通信 38 39 myservo1.write(90);// stop 40 41 t0 = (double)millis() / 1000.0; 42 43} 44 45void updateEncoder1() 46{ 47 uint8_t a = digitalRead(2); 48 uint8_t b = digitalRead(3); 49 uint8_t ab = (b << 1) | a; 50 uint8_t encoded = (prev1 << 2) | ab; 51 if (encoded == 0b1101 || encoded == 0b0100 || encoded == 0b0010 || encoded == 0b1011) 52 { 53 value1-- ; 54 } 55 else if (encoded == 0b1110 || encoded == 0b0111 || encoded == 0b0001 || encoded == 0b1000) 56 { 57 value1++ ; 58 } 59 prev1 = ab; 60} 61byte b = 0; 62 63int cnt = 0; 64double angle1 = 0; 65double theta1 = 0; 66double u1 = 0; 67double d_angle1 = 0.0; // velocity 68double old_angle1 = 0.0; 69double b1 = 0; 70double old_b1 = 0; 71double a1 = 90.0; 72byte a2 = 90.0; 73double old_a1 = 0; 74double t = 0; 75double old_t = 0; 76double dt = 0.0018; 77double MAXV = 0.0; 78double Kp = Kp; 79double Kv = Kv; 80byte sen1 = 0.0 81 82//ループ部分 83void loop() { 84 //角度の生データ 85 angle1 = ((double)(value1) / 4 / (36)) * 360; //エンコーダーから読み取った値から計算した値 86 //エンコーダー付きサーボモーターはパルスが2000 87 //モーターを変える時はここの値を変える 88 89 //Serial.println(angle1); 90 91 //角速度の計算 92 d_angle1 = (angle1 - old_angle1) / dt; //(測定値-初期値)の時間微分 93 94 old_angle1 = angle1; //エンコーダーからの値を改めて初期値に設定 95 96 //角度のフィルター(ノイズ除去) 97 a1 = 0.7 * old_a1 + 0.3 * angle1; 98 old_a1 = a1; 99 a2 = a1; 100 101 //角速度のフィルター(ノイズ除去) 102 b1 = 0.7 * old_b1 + 0.3 * d_angle1; 103 104 old_b1 = b1; 105 106 /*任意の目標角の入力を行う*/ 107 if(Serial.available()>0){ 108 delay(50); 109 sen1 = Serial.read(); 110 111 if(sen1 >=0 && sen1 <= 360){ 112 sen1 = Serial.parseInt(); 113 } 114 } 115 116 //目標角度 117 theta1 = sen1; //90; //theta1; 118 Kp = 0.3; 119 Kv = 0.05; 120 //PDフィードバック制御 121 u1 = (double)(Kp * (theta1 - a1) - Kv * b1); 122 123 // モータドライバに90を入力すると出力電圧が0Vとなる.90より大小で正転,反転する 124 pos1 = 90 + u1; //指令電圧 125 126 if (pos1 > 145) { //電圧制御 127 pos1 = 145; 128 } 129 if (pos1 < 30) { 130 pos1 = 30; 131 } 132 133 134 //モータドライバへ出力 135 myservo1.write(pos1);// tell servo to go to position in variable 'pos' 136 137 138 139 //Serial.print(" "); 140 //Serial.println(pos1); 141 142 if (cnt % 500 == 0) //500回に1回シリアルボードに出力、変更すると回数が変わる。 143 { 144 145 //Serial.print(b); 146 //Serial.print("#"); 147 //Serial.print(theta1); 148 //Serial.print(", "); 149 //Serial.print("#"); 150 Serial.print(time); 151 Serial.print(" , "); 152 //Serial.print("#"); 153 Serial.print(a1); 154 //Serial.print(u1); 155 Serial.print(" , "); 156 Serial.print(a2); 157 //Serial.print("#"); 158 //Serial.println(pos1); 159 160 161 cnt = 0; 162 } 163 164 time = millis() / 1000; // [ms] 165 t = (double)millis() / 1000.0 - t0; // [s] 166 cnt++; 167} 168 169//送信 170void requestEvent() 171{ 172 //Wire.write(b++); 173 //Wire.write((byte&)theta1); 174 //Wire.write((byte&)time); 175 Wire.write((byte&)a2); 176 //Wire.write((byte&)pos1); 177 178} 179 180//受信 181void receiveEvent(int howMany) 182{ 183 (void)howMany; // avoid compiler warning about unused parameter 184 185 while(1 < Wire.available()) // loop through all but the last 186 { 187 char c = Wire.read(); // receive byte as a character 188 Serial.print(c); // print the character 189 } 190 int sen1 = Wire.read(); // receive byte as an integer 191 Serial.println(sen1); // print the integer 192}

試したこと

今出ているエラーは目標角度theta1にsen1を入れようとしてseeeduino(slave)にてSeriai.availableのところにsen1を入れると発生しました。

補足情報

Arduino同士ではなくArduino-Seeeduinoで通信している理由はArduinoでは周波数のせいかエンコーダー付きサーボモーターの角度が取れなかったためです。Seeeduinoでは角度が取れたのでSeeeduinoでセンサー及び制御用として使うことにしました。
また、Arduinoはシリアル通信でパソコンと繋いでおりパソコン側に現在の角度を送信しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

1T2R3M4

2023/01/28 03:42

エラーメッセージに対して試したことを質問に追記してくださいませんか。
guest

回答2

0

ArduinoやSeeeduinoと言ってもそれぞれ何機種かあるので、今回は関係ないですけれど質問のお約束としては機種名をちゃんと記して欲しいと思います。

で。自分で見つけて欲しい間違いではあるのだけれど、

今回は実は
ArduinoTest\ArduinoTest.ino: In function 'void setup()':
ArduinoTest:21:18: error: 'requestEvent' was not declared in this scope
は他のエラーに誘発されたもので、本当のエラーじゃありません。

Arduinoのビルドシステムは.inoファイルを再構成するので、本来のC++であれば先に関数宣言が必要なシーンでもそのエラーにならないケースが多々あります。他の間違いがなければそれで救済されていたはずなのだけれど...

注目すべきはここ。さぁ、目を皿にして間違いを探してください。

Arduino

1byte sen1 = 0.0 2 3 4//ループ部分 5 6void loop() {

Arduino IDEには自動整形機能があって、ある程度文法に沿ってプログラムを整形してくれるわけだけれど、これを適用していれば

Arduino

1byte sen1 = 0.0 2 3 // ループ部分 4 void 5loop() {

このように妙な結果になるので気づきやすいかも知れません。

実はその他にも
#define PI 3.141592;
なんていう間違いも見つけましたけれど、PIというシンボルを使っていないので発現していません。
それ以前にPIはArduino15\packages\Seeeduino\hardware\samd\1.8.3\cores\arduino/wiring_constants.hで定義されていると文句を言ってきていますけれど。

投稿2023/01/28 05:35

編集2023/01/28 05:45
thkana

総合スコア7639

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

まずはエラーメッセージを読みましょう

'requestEvent' was not declared in this scope

'requestEvent' という名前が存在してないってことなので、まずがこいつがどこでどういうふうに定義されてるのかをチェックしてみよう

投稿2023/01/28 03:55

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問