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

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

新規登録して質問してみよう
ただいま回答率
85.45%
VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

Arduino

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

Q&A

0回答

658閲覧

エンコーダー付きサーボモーターを接続したArduinoとc++の通信について

SHIN_gen

総合スコア2

VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

Arduino

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

0グッド

0クリップ

投稿2022/12/23 06:37

編集2022/12/23 07:20

前提

Visual Studio C++を用いてArduinoと通信を行いArduinoからデータを取りたいが取れない

実現したいこと

Arduinoに接続したエンコーダー付きサーボモーターから角度を取りコンソールに表示したい。

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

通信は出来ているようだがArduinoからのデータを受け取ることができていないと思われる。

該当のソースコード

c++

1/* 2c++ <=> Arduino HSCフライトコントローラーを基にしたシリアル通信 3*/ 4 5#define _USE_MATH_DEFINES 6#define _WINSOCK_DEPRECATED_NO_WARNINGS 7#define ReadData 24 //受信バイト数 8#define BUFFER_SIZE 256 //送信最大バイト数 9 10#include <iostream> 11#include <winsock2.h> 12#include <windows.h> 13//#include <ws2tcpip.h> 14//#include <time.h> 15//#include <math.h> 16//#include <cmath> 17//#include <fstream> 18#include <thread> 19 20 21 22#pragma comment(lib, "WS2_32.LIB") 23 24using namespace std; 25 26bool trg = false; 27 28HANDLE arduino; 29boolean Ret; 30 31void send_ard(float* s0, float* s1); //送信 32void receive_ard(float* In); //受信 33 34class joystick { 35public: 36 float x; 37 float y; 38}; 39 40 41int main(int argc, char* argv[]) { 42 //ジョイスティック角度 43 joystick joy; 44 joystick delta; 45 46 WSADATA data; 47 WSAStartup(MAKEWORD(2, 0), &data); 48 49 /************************************************************/ 50 /*シリアル通信設定(Arduino用)*/ 51 /************************************************************/ 52 53 ///////////////////1.受信ポートをオープン///////////////////// 54 cout << "1step" << endl; 55 arduino = CreateFile(L"COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,//COM をaruduinoに合わせて書き換え 56 FILE_ATTRIBUTE_NORMAL, NULL); //ポート設定 57 if (arduino == INVALID_HANDLE_VALUE) { 58 cout << "PORT COULD NOT OPEN error" << endl; 59 system("PAUSE"); //一時停止(コンソール画面が消えないように) 60 exit(0); 61 } 62 63 ////////////////2.送受信バッファ初期化///////////////// 64 cout << "2step" << endl; 65 Ret = SetupComm(arduino, 1024, 1024); //(通信デバイスのハンドル,受信バッファサイズ, 送信バッファサイズ) 66 67 if (!Ret) { 68 cout << "SET UP FAILED" << endl; 69 CloseHandle(arduino); 70 system("PAUSE"); 71 exit(0); 72 } 73 cout << "2.5 step" << endl; 74 Ret = PurgeComm(arduino, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | 75 PURGE_RXCLEAR); //未処理の読み書きの中止及び送受信バッファのクリア 76 if (!Ret) { 77 cout << "CLEAR FAILED" << endl; 78 CloseHandle(arduino); 79 system("PAUSE"); 80 exit(0); 81 } 82 83 //////////////////3.基本通信条件の設定//////////////////// 84 cout << "3step" << endl; 85 DCB dcb; //DCB(デバイス制御ブロック)構造体の変数 86 GetCommState(arduino, &dcb); //通信デバイスの制御設定をDCBに格納 87 dcb.DCBlength = sizeof(DCB); //DCBサイズ 88 dcb.BaudRate = 115200; //伝送速度 89 dcb.fBinary = TRUE; //バイナリモード 90 dcb.ByteSize = 8;//ReadData; //データサイズ 91 dcb.fParity = NOPARITY; //パリティ有無種類 92 dcb.StopBits = ONESTOPBIT; //ストップビットの数(今回は1bit) 93 Ret = SetCommState(arduino, &dcb); //DCBに従って通信デバイスを構成 94 if (!Ret) { 95 cout << "SetCommState FAILED" << endl; 96 CloseHandle(arduino); 97 system("PAUSE"); 98 exit(0); 99 } 100 float In[ReadData / 4] = { '\0' }; 101 102 //ジョイスティック初期化 103 cout << "4step" << endl; 104 float s0 = 0;// 90;//70~110 105 float s1 = 0;// 90;//70~110 106 float s0_pre; 107 float s1_pre; 108 float j0 = 0, j1 = 0; 109 send_ard(&s0, &s1); 110 111 cout << "start!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << endl; 112 113 int n = 0; 114 int m = 60; 115 116 while (n <= 10) { 117 cout << "test1" << endl; 118 119 receive_ard(In); 120 121 cout << "test2" << endl; 122 123 124 //joystick角度計算 125 joy.y = (In[0] + 1146.25) / 18.375; 126 joy.x = (In[1] + 1140) / 18; 127 delta.y = joy.y - (In[3] + 1146.25) / 18.375; 128 delta.x = joy.x - (In[4] + 1140) / 18; 129 130 s0 = n; 131 s1 = m; 132 cout << s0 << "\n"; 133 send_ard(&s0, &s1); 134 135 n++; 136 m--; 137 138 std::cout << "joy.y" << std::endl; 139 std::cout << "joy.x" << std::endl; 140 std::cout << "delta.y" << std::endl; 141 std::cout << "delta.x" << std::endl; 142 143 std::this_thread::sleep_for(std::chrono::milliseconds(500));//0.5秒停止 144 } 145 return 0; 146} 147 148void send_ard(float* s0, float* s1) { 149 150 //通信に必要な変数定義 151 DWORD dwSendSize; 152 char Out[16] = { '\0' }; 153 154 //制御に必要な変数定義 155 //float a0 = *s0;//18.375*(*s0) - 1146.25;//140~875 156 //float a1 = *s1;//18 * (*s1) - 1140;//120~840 157 int delx = 10, dely = 10; 158 159 /*snprintf(Out, sizeof(Out), "A%dB%dC%dD%d#", (int)a0, (int)a1, delx, dely); *///送るデータ 160 snprintf(Out, sizeof(Out), "A%dB%dC%dD%d#", (int)*s0, (int)*s1, delx, dely);//送るデータ 161 162 ///////////////////送信///////////////////// 163 Ret = WriteFile(arduino, &Out, sizeof(Out), &dwSendSize, NULL);//データの送信 164 165 //WriteFile(通信デバイスのハンドル,送信データのポインタ,送信するバイト数,送信されたバイト数,通信と関係ない引数) 166 if (!Ret) { 167 cout << "SEND FAILED" << endl; 168 CloseHandle(arduino); 169 system("PAUSE"); 170 exit(0); 171 } 172 cout << "sendArd" << endl; 173 174} 175 176void receive_ard(float* In) { 177 //通信に必要な変数定義 178 DWORD lRead = 0; 179 char Check[1] = { '\0' }; 180 //////////////////受信//////////////////////////// 181 /************************************************************/ 182 /*通信開始文字(#)を読み取ってから8byte受け取り*/ 183 /************************************************************/ 184 while (1) { 185 Ret = ReadFile(arduino, Check, 1, &lRead, NULL); 186 if (!Ret) { 187 cout << "Check FAILED" << endl; 188 CloseHandle(arduino); 189 system("PAUSE"); 190 exit(0); 191 } 192 193 if (Check[0] == '#')break; 194 } 195 196 Ret = ReadFile(arduino, In, ReadData, &lRead, NULL); //データの受信 197 198 //ReadFile(通信デバイスのハンドル,受信バッファのポインタ,受信するバイト数,実際に受信したバイト数が格納されるポインタ,通信とは関係ない引数) 199 200 if (!Ret) { 201 cout << "READ FAILED" << endl; 202 CloseHandle(arduino); 203 system("PAUSE"); 204 exit(0); 205 } 206}

Arduino

1//エンコーダ動作テストその3 2//https://okasho-engineer.com/rotoryencoder-calculate-angle/ 3//use Seeeduino 4 5byte value = B00000000; 6float degree = 0.00; 7 8void setup() { 9 Serial.begin(115200); 10 pinMode(2, INPUT); //conect C2(Encoder A Phase) 11 pinMode(3, INPUT); //conect C1(Encoder B Phase) 12} 13 14void loop() { 15 value = (value<<2)+(digitalRead(2)<<1)+digitalRead(3); 16 value = value & B00001111; 17 if(value==B00000001||value==B00000111||value==B00001110||value==B00001000) 18 { 19 degree = degree+0.18; 20 } 21 else if(value==B00000010||value==B00001011||value==B00001101||value==B00000100) 22 { 23 degree = degree-0.18; 24 } 25// if(degree>180) 26// { 27// degree = degree-360; 28 // } 29 // else if(degree<=-180) 30 // { 31 // degree = degree+360; 32 // } 33 Serial.print("degree: "); 34 Seeial.print("#"); 35 Serial.println(degree); 36 37 38 39 }

試したこと

 Arduinoだけで動かしたときはシリアルモニタに角度は表示されているのでc++の方にデータが送れていないと思います。
visual studioで動かすとコンソールは開きます。しかし、c++のプログラムの117行目の「cout << "test1" << endl;」部分の”test1”は表示されることからこの部分までは実行出来ているものと思われます。この後の「receive_ard(In)」がArduinoからの受信部分のつもりですがコンソールに表示されないことからデータを受け取ることができていないと思われます。

 

補足情報(FW/ツールのバージョン)

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

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

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

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

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

thkana

2022/12/23 12:39

まだあまりちゃんと見ていませんが、 > シリアルモニタに角度は表示されている のだったら「文字」を送っているわけで、それを float* In に対し ReadFile(arduino, In, ReadData, &lRead, NULL); で意味のあるデータを拾おうというのはかなり無理がある気がします。しかもReadDataは24ってのはどこからでてくるのかしら? UARTの線に乗っかっているのはどういうデータか確認してみては...
matukeso

2022/12/23 13:24

受信できない、というのであれば 、dcdのハンドシェイク系設定を無効にする必要があるじゃないかな。 受信できても中身がおかしい、って話になりそうだけど。
SHIN_gen

2022/12/26 05:23

>>thkanaさん すみません、c++を始めたばかりでよくわかっていないのですが 「float* In に対し ReadFile(arduino, In, ReadData, &lRead, NULL); で意味のあるデータを拾おうというのはかなり無理がある」 というのはなぜでしょうか? >>matukesoさん dcdというと通信関係の部分だったと思うのですが通信の以下のURLを参考にしただけで 細かい部分はわかっておりません。 dcdのハンドシェイクを無効にするにはどうすればよいですか? 「RS232C シリアル通信」 http://www.ys-labo.com/BCB/2007/070512%20RS232C%20zenpan.html
SHIN_gen

2022/12/26 05:46

>>thkana PC側は文字を取ろうとしているがArduino側は数字を送っているのでPCは表示できないということでしょうか?
thkana

2022/12/26 10:02

コンピュータは、本質的には「数値」しか扱えません。が、それでは不便なので「あるお約束の条件下では、数値に対して文字を割り当てて、文字として扱う」という処理をします。 そのお約束に基づいて、Serial.printlnは'0'という文字に48, '1'には49,...'A'には65, 'B'には66...を割り当てて、その数値を送信しています。例えば、12.34というデータは数字に分解して順次48,49,46,40,51というデータを順次送信します。 一方、ReadFileは文字かどうかは関係なく、データを指定されたメモリに詰め込みます。Inがfloat型であれば、浮動小数点型のデータ(WindowsであればIEEE754形式単精度: https://ja.wikipedia.org/wiki/IEEE_754 などを参照してください)の各バイトに48,49,46,50,51...が詰め込まれたものを数値として解釈しようとします。そこには12.34という"意味"はカケラもありません。 さらに言えば、float型の変数は4byteを専有しますが、あなたはそこに24バイトのデータを受信せよ、と命令しました。当然データは溢れて、他の変数や動作に必要なデータを破壊するかも知れません。(バッファオーバーフローとか言う言葉、聞いたことありますよね?) Arduno側は文字列を送っているのに、PC側はそうではないデータ形式を期待しているので、通信として意味をなさない、ということになっています。通信は、送る側と受け取る側でデータ内容について合意がないと通信として成り立ちません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

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

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

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

ただいまの回答率
85.45%

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

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

質問する

関連した質問