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

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

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

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Arduino

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

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

Q&A

解決済

2回答

839閲覧

あるクラスで取得したセンサデータをいくつかの他クラスで使用したいです。

Tatsuya1192

総合スコア9

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Arduino

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

マイコン

マイクロコンピュータの略で、CPUにマイクロプロセッサを用いたコンピュータのこと。家電製品、電磁機器などの制御に用いられています。単体でコンピュータとしての機能を一通り備えています。 現代のパーソナルコンピュータに近く、同時期のメインフレームやミニコンピュータと比べ、小さいことが特徴です。

0グッド

1クリップ

投稿2020/04/22 07:54

編集2020/04/23 02:46

前提・実現したいこと

GetDataクラスで取得したセンサデータをいくつかの他クラスで使用したいです。
具体的にはGetDataクラス → Menu2クラスでCSV保存用途と、PlotCanvasクラスのupdateFigure()でのリアルタイムグラフ表示です。

1周間近く詰まってしまったので以前助けていただけたこちらのサイトの皆様の助言をいただきたいです。

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

ValueError: could not convert string to float: 'None'

該当のソースコード

python3

1# 文字数制限の為省略しています。全文載せられます。 2# 以下に動作段階のコードを記載しております。 3# 動作段階のコードにclass GetData()を作成してMenu2クラスとPlotCanvasクラスで使用しようとしておりました。

試したこと

最初はグローバル変数で出来ないか試したが最初に取得したデータのみがタイマーで出続けるのみ。(失敗)
関数を書いてグローバル変数にタイマーで取得し続けた値を入れようとする。(失敗)
スコープ範囲を広げてみる。 理解出来ていなかった為他の方の記述がいじれない。(失敗)
データ取得用クラス作成(GetData)。数値が入っていない様子。(現在)

本当は1行ずつデバッグしながら組んでいくものなのでしょうが、プログラミング初級者であるため1からの記述が難しかったためいろいろな方のコードを引っ張ってきており、私のレベルでは難しい状況となってしまいました。。

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

Windows10 or macOS Catalina 10.15.4
言語 : Python3 (関係ないはずですがファームウェアはCとMicroPythonの2パターンあります。)
フレーム : PyQt5

PlotCanvasクラスのupdateFigure()内でデータ取得をした場合問題なく動きました。
お恥ずかしながら初歩的なことで躓いており、心折れかけてます。
おわかりになる方の助言を心からおまちしております。。

以下追記です。
動いている段階までもどってみました。最近は動かなくてはこのバックアップにもどってのくりかえしです。。

python

1 2class StartMenu(QWidget): #メインウインドウ用のクラス作成 3 def __init__(self, parent): 4 super().__init__(parent) 5 6 self.master = parent 7 self.button1 = QPushButton('Graph', self) #ボタンの作成(表示名) 8 self.button1.move(260, 100) #ボタンの位置を決定(X,Y) 9 self.button1.clicked.connect(self.Graph) #ボタンを押すと(clicked.connect())Graph関数を呼ぶ(Menu2にアクセス) 10 11 self.button2 = QPushButton('InputData', self) 12 self.button2.move(260, 180) 13 self.button2.clicked.connect(self.InputData) 14 15 self.quitbutton1 = QPushButton('exit', self) 16 self.quitbutton1.move (260, 260) 17 self.quitbutton1.clicked.connect(QCoreApplication.instance().quit) 18 19 def initUI(self): 20 self.setWindowTitle(self.title) 21 self.setGeometry(self.width, self.height) 22 self.show() 23 24 def Graph(self): 25 # 0オリジン 26 self.master.setCurrentIndex(1) #Menu2にアクセス 27 28 def InputData(self): 29 # 0オリジン 30 self.master.setCurrentIndex(2) 31 32class Menu2(QWidget): 33 34 def __init__(self, parent): 35 super().__init__(parent) 36 37 # 実際にグラフを打つPlotCanvasクラスのインスタンスを生成。 38 self.m = PlotCanvas(self, width=5, height=4) 39 self.m.move(15,15) 40 41 self.master = parent 42 self.startButton = QPushButton('保存開始', self) 43 self.startButton.move(530, 300) 44# self.startButton.clicked.connect(self.onStartButton) 45 46 self.master = parent 47 self.stopButton = QPushButton('CSVファイル作成', self) 48 self.stopButton.move(530, 330) 49# self.stopButton.clicked.connect(self.onStopButton) 50 51 self.quitbutton2 = QPushButton('quit', self) 52 self.quitbutton2.move(530, 360) 53 self.quitbutton2.clicked.connect(self.quit) 54 55# def onStartButton(self): 56 57# def onStopButton(self): 58 59 def quit(self): 60 self.master.text("return") 61 self.master.setCurrentIndex(0) 62 63class Menu3(QWidget): 64 65 def __init__(self, parent): 66 super().__init__(parent) 67 self.master = parent 68 69 self.textbox = QLineEdit(self) # テキストボックス作成 70 self.textbox.move(20, 20) 71 self.textbox.resize(200,30) 72 73 self.button = QPushButton("Show text", self) # ボタン作成 74 self.button.move(20,80) 75 self.button.clicked.connect(self.on_click) # ボタン押下時のアクションを指定 76 self.show() 77 78 @pyqtSlot() 79 def on_click(self): 80 textboxValue = self.textbox.text() 81 QMessageBox.question(self, "Message - pythonspot.com", "You typed: " + textboxValue, QMessageBox.Ok, QMessageBox.Ok) 82 self.textbox.setText("") 83 84 self.button4 = QPushButton('登録', self) 85 self.button4.move(530, 100) 86 87 self.button4 = QPushButton('登録', self) 88 self.button4.move(530, 220) 89 90 self.button4 = QPushButton('登録', self) 91 self.button4.move(530, 340) 92 93 self.quitbutton3 = QPushButton('quit', self) 94 self.quitbutton3.move(530, 380) 95 self.quitbutton3.clicked.connect(self.quit) 96 97 def quit(self): 98 self.master.text("return") 99 self.master.setCurrentIndex(0) # StartMenuに移動 100 101 102class App(QTabWidget): 103 def __init__(self): 104 super().__init__() 105 self.setWindowTitle("加速度センシング") 106 107 self.tab1 = StartMenu(self) # 1個1個のタブがメニューに対応 108 self.tab2 = Menu2(self) 109 self.tab3 = Menu3(self) 110 111 self.addTab(self.tab1, "StartMenu") # タブページに追加 112 self.addTab(self.tab2, "Graph") 113 self.addTab(self.tab3, "InputData") 114 115 self.setStyleSheet("QTabWidget::pane { border: 0; }") # タブパネルのボーダーを削除 116 117# self.tabBar().hide() # タブバーを非表示に 118 self.resize(640, 470) # サイズの変更と 119 self.move(150, 20) # 立ち上げ位置の設定 120 121 def text(self, text): 122 print(text) 123 124#グラフ描画クラス 125class PlotCanvas(FigureCanvas): 126 127 def __init__(self, parent=None, width=5, height=5, dpi=100): 128 self.fig = Figure(figsize=(width, height), dpi=dpi) 129 self.axes = self.fig.add_subplot(111) 130 super(PlotCanvas, self).__init__(self.fig) 131 self.setParent(parent) 132 133 FigureCanvas.setSizePolicy( 134 self, 135 QSizePolicy.Expanding, 136 QSizePolicy.Expanding 137 ) 138 FigureCanvas.updateGeometry(self) 139 self.plot() 140 141 def plot(self): 142# self.xser = serial.Serial("COM7") # シリアルポート 143 self.ser = serial.Serial("/dev/tty.usbserial-0001") # Macで作業用シリアルPORT 144 timer = QTimer(self) 145 timer.timeout.connect(self.updateFigure) 146 self.x = np.arange(0,10) 147 self.xlist_x = np.zeros(10).tolist() # B 148 self.xlist_y = np.zeros(10).tolist() # Y 149 self.xlist_z = np.zeros(10).tolist() # G 150 151 self.axes.set_ylim((-1000,1000)) 152 153 self.xlines1, = self.axes.plot(self.x, self.xlist_x) 154 self.xlines2, = self.axes.plot(self.x, self.xlist_y) 155 self.xlines3, = self.axes.plot(self.x, self.xlist_z) 156 157 timer.start(1) 158 159 def updateFigure(self): 160 161 self.x += 1 # plotデータの更新 162 self.data = self.ser.readline().rstrip() # \nまで読み込む(\nは削除) 163 accdata = self.data.decode('utf-8') 164 acc = accdata.split(",") 165 acc_x = float(acc[0])/10 + 155 166 acc_y = float(acc[1])/10 167 acc_z = float(acc[2])/10 - 1665 168 169 self.xlist_x.pop(0) 170 self.xlist_x.append(acc_x) 171 self.xlist_y.pop(0) 172 self.xlist_y.append(acc_y) 173 self.xlist_z.pop(0) 174 self.xlist_z.append(acc_z) 175 176 self.xlines1.set_data(self.x, self.xlist_x) 177 self.xlines2.set_data(self.x, self.xlist_y) 178 self.xlines3.set_data(self.x, self.xlist_z) 179 180 self.axes.set_xlim((self.x.min(), self.x.max())) 181 182 self.draw() 183# plt.pause(1) 184 185def main(): 186 app = QApplication(sys.argv) 187 188 ex1 = App() 189 ex1.show() 190 sys.exit(app.exec_()) 191 192if __name__ == '__main__': 193 main()

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

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

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

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

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

guest

回答2

0

ベストアンサー

GetDataクラスで取得したセンサデータをいくつかの他クラスで使用したいです。

具体的にはGetDataクラス → Menu2クラスでCSV保存用途と、PlotCanvasクラスのupdateFigure()でのリアルタイムグラフ表示です。

PubSub というメッセージ伝搬の方法を使うと良いです。

ライブラリ等もありますが、仕組みは単純なので、
簡単な例で紹介。(エラー処理等は省く、最小限の実装です)

class PubSub: def __init__(self): self.listeners = [] def subscribe(self, func): self.listeners.append(func) def unsubscribe(self, func): self.listeners.remove(func) def sendMessage(self, message): for func in self.listeners: func(message) if __name__ == "__main__": # CSV保存用と def save_to_csv(message): print("Save CSV", message) # リアルタイムグラフ表示に見立てた関数 def plot_update(message): print("Plot", message) pub = PubSub() pub.subscribe(save_to_csv) # 呼び出してほしい関数を登録 pub.subscribe(plot_update) # 双方の関数にメッセージが送られます pub.sendMessage("1,2,3")

Qt のシグナル&スロットも同様の仕組みを備えてます。
(通常のマウス操作等のイベントも同イベントループ内で処理されてるので、
大量のデータのやり取りには向いてませんが)

import sys from PyQt5.QtWidgets import QApplication, QPushButton if __name__ == '__main__': app = QApplication(sys.argv) def func1(): print("func1 was called") def func2(): print("func2 was called") button = QPushButton("Click") button.clicked.connect(func1) # subscribe button.clicked.connect(func2) button.clicked.emit() # sendMessage button.clicked.disconnect(func2) # unsubscribe button.show() app.exec_()

(上のコード例には出してませんが)
データ生成元にシグナルを定義して、
CSV出力とプロットの双方のスロットに繋げる、
といった設計等も出来ます。


PubSubを使ったデモ

イメージ説明

データは適当な乱数生成

  • 右パネル subscribe 購読開始を通知 (この時点では何もデータが流れない)
  • Start ... タイマー開始 (データが流れ始め、グラフ描画が開始)
  • 左パネル subscribe 購読開始を通知 (テキストログが流れる)
  • 左パネル unsubscribe 購読解除 (テキストログが止まる)
  • Stop ... タイマー停止 (データがないのでグラフ描画も止まる)

投稿2020/04/24 06:32

teamikl

総合スコア8760

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

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

Tatsuya1192

2020/04/24 11:31

ご指導頂きまして誠に有難う御座います! 今朝、解決していたのですが一日中別の会議で返信及び評価が遅れてしまい申し訳御座いません。 原因は非常に初歩的な事でGetDataクラスの返り値を指定していなかった事でした。。 ですが、こちらの方法がより分かりやすく、ベストアンサーとさせて頂きました! こちらのパターンでも書いてみたいと思います。 誠に有難う御座います!
guest

0

本当は1行ずつデバッグしていくものなのでしょうが、

違います。最初から動くように考えながらプログラムを作成するものであって、適当に組み立ててしまってから動くように直していく、というのは邪道です。

プログラミング初級者であるため1からの記述が難しかったためいろいろな方のコードを引っ張ってきており

理解していないものをキメラにしても大抵動きません。

初心者がどうしたら出来るかわからないのは仕方ないでしょう。だからといって、メチャクチャをやってもいい、というものではありません。わかるところから、順に歩いて下さい。

正直、GetDataというクラス名はかなり引きます。他のStartMenuとかPlotCanvasとかもですけれど。議論はありますけれど、オブジェクト指向の設計としてクラスの候補はまず「名詞」で抽出しよう、なんていう考え方もあるくらいで、動詞+目的語がクラスの名前になるというのは...クラスについてどのように考えているのでしょうか。


それはそれとして。
エラーの原因はそんなこととは関係なく、
関数の定義の仕方がメチャクチャなのでGetData.updatedata()は返り値を持たず、Noneを返すので、

Python

1 def updateFigure(self): # plotする 2 3 self.x += 1 # plotデータの更新 4 accdata = self.getdata.updatedata() 5#accdataは必ずNone 6 7 acc = str(accdata) 8#accdataがNoneなのでそれを文字列にしてaccは'None' 9 10 acc = acc.split(",") 11#Noneは','を含まないのでaccは'None' 12 13 acc_x = float(acc[0])/10 + 155 14#'None'はfloatに変換不可なのでcould not convert string to float: 'None'になる 15

というのがエラーに至る流れです。

PlotCanvasクラスのupdateFigure()内でデータ取得をした場合問題なく動きました。

おなじ手順でやっていたら同じエラーになっていたはずですが、その時のコードはどうなっていましたか?場所だけでなく手順も変えていませんでしたか?


言ってしまえば、多少の手助けでどうにかなる、というレベルではありません。
同じことをまた言いますが、ちゃんとわかっているところまで立ち戻って、一歩ずつ進んでみて下さい。

関数の作り方
クラスの意味、使い方
プログラムの組み立て方

多少の背伸びはいいですけれど、一気に進みすぎるとにっちもさっちも行かなくなります。

投稿2020/04/22 11:28

thkana

総合スコア7703

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

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

Tatsuya1192

2020/04/23 02:48 編集

ご指導頂きまして誠に有難うございます! 勉強不足でくだらない質問をしてしまった中、このように指摘いただけた事がとても嬉しいです。 動いていて動きがわかるのはGetDataクラスを作る前でPlotCanvasクラスを以下のような記述にしておりました。 class PlotCanvas(FigureCanvas): def __init__(self, parent=None, width=5, height=5, dpi=100): self.fig = Figure(figsize=(width, height), dpi=dpi) self.axes = self.fig.add_subplot(111) super(PlotCanvas, self).__init__(self.fig) self.setParent(parent) FigureCanvas.setSizePolicy( self, QSizePolicy.Expanding, QSizePolicy.Expanding ) FigureCanvas.updateGeometry(self) self.plot() def plot(self): # self.ser = serial.Serial("COM7") # COMポート self.ser = serial.Serial("/dev/tty.usbserial-0001") self.fig, self.axes = plt.subplots(1, 1) # Figureオブジェクトとそれに属する一つのAxesオブジェクトを同時に作成 self.x = np.arange(0,10) # リアルタイムX方向表示 self.list_x = np.zeros(10).tolist() # B self.list_y = np.zeros(10).tolist() # Y self.list_z = np.zeros(10).tolist() # G self.axes.set_ylim((-1000,1000)) # 初期化的に一度plotしなければならない # そのときplotしたオブジェクトをlistで受け取る受け取る必要がある. self.lines1, = self.axes.plot(self.x, self.list_x) self.lines2, = self.axes.plot(self.x, self.list_y) self.lines3, = self.axes.plot(self.x, self.list_z) while True: # ここから無限にplotする self.x += 1 # plotデータの更新 data = self.ser.readline().rstrip() # \nまで読み込む(\nは削除) acc = data.decode('utf-8') acc = acc.split(",") acc_x = float(acc[0])/10 + 155 acc_y = float(acc[1])/10 acc_z = float(acc[2])/10 - 1665 self.list_x.pop(0) self.list_x.append(acc_x) self.list_y.pop(0) self.list_y.append(acc_y) self.list_z.pop(0) self.list_z.append(acc_z) # 描画データを更新するときにplot関数を使うと # lineオブジェクトが都度増えてしまうので,注意. # 一番楽なのは上記で受け取ったlinesに対して # set_data()メソッドで描画データを更新する方法. self.lines1.set_data(self.x, self.list_x) self.lines2.set_data(self.x, self.list_y) self.lines3.set_data(self.x, self.list_z) # set_data()を使うと軸とかは自動設定されないっぽいので, # 今回の例だとあっという間にdataカーブが描画範囲からいなくなるため,x軸の範囲は適宜修正してやる必要がある. self.axes.set_xlim((self.x.min(), self.x.max())) # - plt.show() はブロッキングされてリアルタイム描写できない # - plt.ion() + plt.draw() グラフウ0.インドウが固まってプログラムが止まるから使えない # ----> plt.pause(interval) これを使う!!! 引数はsleep時間 plt.pause(1) def clear(self): self.axes.cla() self.draw() インスタンスを生成して、インスタンス変数名 = クラス名 でインスタンス変数を作って インスタンス変数,関数で中身を呼び出すと捉えてしまっていたのでこのようなことになってしまったと思います。 理解力が全然ありませんね。。 自分の周りにプログラミングが出来る人がいないためここで質問してしまいました。。 お手を煩わせてしまい大変申し訳ございませんでした。。
thkana

2020/04/22 23:10

インストラクタ変数、というのは寡聞にして知りません。Pythonはあまり詳しくないのですが、そういうものがあるのでしょうか。 とりあえず、Pythonのプログラムをインデント無しに解釈しろというのは拷問以外の何者でもないので、プログラムを示すのなら質問への追記でお願いします。質問は随時編集出来ます。履歴も残るので、ガシガシ編集しちゃっても大丈夫です。
Tatsuya1192

2020/04/23 02:58

度々もうしわけないです。。インスタンス変数の間違いです。 javaのコンストラクタ変数とごっちゃになってしまいました。 おっしゃるとおり大変見づらかったため質問の編集を行いました。 現況を報告致しますとpython3の教本をいくつか読み直しています。 こちらのようなGUIなどのアプリケーション制作は趣味なのですが 仕事はハードやファーム専門で他の言語をいじる必要があり、(頭の中ごっちゃになって)まだまだ時間がかかりそうです。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問