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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

4回答

2158閲覧

シリアル通信の精度を上げる方法

Merrifield

総合スコア31

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2020/06/24 06:45

編集2020/06/25 02:02

開発環境は、送信側はC#、Visual Studio 2019 windows フォームアプリケーション(.NET Framework)、受信側はc言語でCube Suite+です。マイコンは78K0R、UART-シリアル変換モジュールはFT232RLを使っています。

track barをスクロールするたびに、track barの値をシリアル通信で送信するということをしているのですが、スクロールの動きが速い場合に上手く通信できない部分があるので、通信の精度をより高めたいと思っています。例えば、track barを10から一気に1までスクロールした際に、受信側では1や2といった値で受け取ってしまします。これをより正確に送信するには、どうすればよいでしょうか?

仮想ポートを作り確認してみたところ、例えば10から0に一気に動かしたときに受信側を確認してみると、
R009R007R006R004R002R000
のように途中の値はとびとびになりますが、最後の値はちゃんと送信できているということが分かりました。やはり問題は受信側かなと思います。

送信側のコードを示しておきます。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApp6 { public partial class Form1 : Form { public Form1() { InitializeComponent(); mySerialPort.Open(); } private string StringR, StringG, StringB; private void Form1_Load(object sender, EventArgs e) { //trackBar1の設定 // 最小値、最大値を設定 trackBar1.Minimum = 0; trackBar1.Maximum = 100; // 初期値を設定 trackBar1.Value = 0; // 描画される目盛りの刻みを設定 trackBar1.TickFrequency = 10; // スライダーをキーボードやマウス、 // PageUp,Downキーで動かした場合の移動量設定 trackBar1.SmallChange = 1; trackBar1.LargeChange = 10; // 値が変更された際のイベントハンドラーを追加 trackBar1.ValueChanged += new EventHandler(trackBar1_ValueChanged); //trackBar2の設定 // 最小値、最大値を設定 trackBar2.Minimum = 0; trackBar2.Maximum = 100; // 初期値を設定 trackBar2.Value = 0; // 描画される目盛りの刻みを設定 trackBar2.TickFrequency = 10; // スライダーをキーボードやマウス、 // PageUp,Downキーで動かした場合の移動量設定 trackBar2.SmallChange = 1; trackBar2.LargeChange = 10; // 値が変更された際のイベントハンドラーを追加 trackBar2.ValueChanged += new EventHandler(trackBar2_ValueChanged); //trackBar3の設定 // 最小値、最大値を設定 trackBar3.Minimum = 0; trackBar3.Maximum = 100; // 初期値を設定 trackBar3.Value = 0; // 描画される目盛りの刻みを設定 trackBar3.TickFrequency = 10; // スライダーをキーボードやマウス、 // PageUp,Downキーで動かした場合の移動量設定 trackBar3.SmallChange = 1; trackBar3.LargeChange = 10; // 値が変更された際のイベントハンドラーを追加 trackBar3.ValueChanged += new EventHandler(trackBar3_ValueChanged); } private void trackBar1_ValueChanged(object sender, EventArgs e) { // TrackBar1の値が変更されたらラベルに表示 label1.Text = trackBar1.Value.ToString(); //TrackBarの値を文字列に変換( StringR = "R" + trackBar1.Value.ToString("D3"); //送信 mySerialPort.Write(StringR); } private void trackBar2_ValueChanged(object sender, EventArgs e) { // TrackBar2の値が変更されたらラベルに表示 label2.Text = trackBar2.Value.ToString(); //TrackBarの値を文字列に変換( StringG = "G" + trackBar2.Value.ToString("D3"); //送信 mySerialPort.Write(StringG); } private void trackBar3_ValueChanged(object sender, EventArgs e) { // TrackBar3の値が変更されたらラベルに表示 label3.Text = trackBar3.Value.ToString(); //TrackBarの値を文字列に変換( StringB = "B" + trackBar3.Value.ToString("D3"); //送信 mySerialPort.Write(StringB); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { mySerialPort.Close(); } } }

受信側のコードも一部示しておきます。

__interrupt

1{ 2 /* Start user code. Do not edit comment generated here */ 3 4 //タイマ割り込み(0.1秒ごと)// 5 6 7 UART0_ReceiveData(receive, 4); //文字列でデータ受信 8 9 //numerical = atoi(receive); //文字列を数値に変換 10 11 if(receive[0] == 'R') 12 { 13 14 numericalR = 100 * (receive[1] - '0') + 10 * (receive[2] - '0') + (receive[3] - '0'); //数値に変換 15 TAU0_Channel2_ChangeDuty((unsigned char)numericalR); //デューティー比変更(赤) 16 17 } 18 19 if(receive[0] == 'G') 20 { 21 22 numericalG = 100 * (receive[1] - '0') + 10 * (receive[2] - '0') + (receive[3] - '0'); //数値に変換 23 TAU0_Channel1_ChangeDuty((unsigned char)numericalG); //デューティー比変更(緑) 24 25 } 26 27 28 if(receive[0] == 'B') 29 { 30 31 numericalB = 100 * (receive[1] - '0') + 10 * (receive[2] - '0') + (receive[3] - '0'); //数値に変換 32 TAU0_Channel3_ChangeDuty((unsigned char)numericalB); //デューティー比変更(青) 33 34 } 35コード

受信を行う関数

MD_STATUS

1{ 2 MD_STATUS status = MD_OK; 3 4 if (rxnum < 1U) 5 { 6 status = MD_ARGERROR; 7 } 8 else 9 { 10 gUart0RxCnt = 0U; 11 gUart0RxLen = rxnum; 12 gpUart0RxAddress = rxbuf; 13 } 14 15 return (status); 16} 17コード

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

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

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

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

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

ozwk

2020/06/24 07:43

mySerialPort.Write(...)の前にConsole.Writeline(...)でもなんでも入れて、 送信側で値が飛んでいるのか受信側で読めてないのかを確認してください
ozwk

2020/06/24 07:47 編集

10から一気に1までスクロールした際に, 中間値が飛ぶのか、 最終的に送信される値がトラックバーの値と異なるのか どっちですか?
Merrifield

2020/06/24 08:14

「"console"に"Writeline"の定義がありません」というエラーが出るのですが、どのようにすればよいですか?
ozwk

2020/06/24 08:18

WriteLine
Merrifield

2020/06/24 08:47

実行しても、Console.Writelineがなにをどこに表示してくれるのか分からなかったのですが、デバッグでブレイクポイント設定して確かめてみると、送信は上手くできているようです。
guest

回答4

0

シリアル通信自体は常に正確に通信を行ってます。
問題は、イベントが輻輳した場合に送信内容がおかしくなることでしょうね。
あるいは、PC側の送信が連続した場合に、マイコンの受信がおかしくなることでしょう。

これを確認するには、別のPC(同一PCでもいいですが)に、シリアルターミナルを起動させ、マイコンの代わりに受信させて、トラックバーを操作した場合にどういう送信内容になるかをモニタすることです。

このとき、送信内容がどういう状態でも正常であるなら、マイコン側のプログラムにバグが有る、ということになりますね

投稿2020/06/24 06:56

y_waiwai

総合スコア88042

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

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

episteme

2020/06/24 07:01

せやね。送り損ねなのか 受け損ねなのか その両方か 確認してからですな対処は。
Merrifield

2020/06/24 08:26

送信にポートを使っているので、シリアルターミナルなどが開けないです
y_waiwai

2020/06/24 08:29

だから、別のPCもってきてUSB-シリアル変換器つけて通信内容確認してこようよ 原因もわからないのにあーだこーだやっても無駄ですぜ
iwanote

2020/06/24 11:07

世の中には仮想COMポート作成ソフトもあるのですし…
Merrifield

2020/06/25 02:01 編集

仮想ポートを作るということができたのですね。それでやってみたのですが、受信側を確認してみると、10から0に一気に動かしたとき、 R009R007R006R004R002R000 のように途中の値はとびとびになりますが、最後の値はちゃんと送信できているということが分かりました。
y_waiwai

2020/06/25 04:03

なら、マイコン側の受信がバグってるということですね
guest

0

起こっている現象はやっぱりちゃんと確認していただくとして、

UARTをどういう使い方をしているのかにもよりますけど、
0.1秒毎に覗きに行って4文字ずつ処理では取りこぼしが発生しても当然...というのが第一印象です。
あと、下手に取りこぼすといまの構造では二度と復帰できないかも知れないのもかなり危うい感じがします。

UARTの割り込みで1文字ずつ取り込み、R/G/Bを拾ったらさらに3文字取得する...などの構成にすべきかと思います。

投稿2020/06/24 11:16

thkana

総合スコア7703

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

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

guest

0

自己解決

mouseupのときに送信を行うようにして解決しました。みなさんありがとうございました。

投稿2020/06/25 05:39

Merrifield

総合スコア31

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

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

0

トラックバーの移動に追いつけないんなら、
位置変更のたびに送信するのを諦めて
たとえば一秒に一回、R/G/B値をまとめて送信するとか。

投稿2020/06/24 06:48

編集2020/06/24 06:51
episteme

総合スコア16612

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

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

Merrifield

2020/06/24 08:50

タイマで1ms毎に送信しているのですが、受信側に反映されるのがやけに遅い(数秒かかる)のですが、なぜだかわかります?
episteme

2020/06/24 10:38

いやそれも 送信/受信どっちがモタついてるかはモニタしてみんことには。
Merrifield

2020/06/25 00:36

タイマのときも、送信はしっかりできていたので、受信側に問題があるようです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問