ESP32とMicroPythonのADCでジョイスティックの位置をPCのPyQtGraphに表示する

MicroPythonを入れたESP32でAD変換を使ってみるためにジョイスティックの位置を読み取ってみました。シリアル通信でPCに送られてきた文字列をただ表示するだけじゃ面白くないのでPyQtGraphのグラフに表示してみました。



マイコンからの受信データの確認

AD変換した値をシリアル通信で送信するプログラムを作成しました。プログラムはAD変換の設定をした後に値を送り続けるという単純なプログラムです。VS codeのステータスバーのRunをクリックするとデータが送られてきてターミナルに表示されました。このデータを処理してパソコン側でグラフとして表示してみます。

パソコン側でのグラフ表示

以前作成したPyQtGraphを使ったコードを流用して作成しました。受信した値はnumpy配列の最後のインデックスに入れていき、最初のインデックスのデータは削除することで、グラフに軌跡が残るように表示してみました。グラフの描画はPyQtのQTimerで一定間隔で行うようにしています。

self.plot_data['X'] = np.append( self.plot_data['X'][1:], float(splited[1]) )
self.plot_data['Y'] = np.append( self.plot_data['Y'][1:], float(splited[3]) )

所感

マイコン側もパソコン側もPythonでコードを書くことができるのは便利ですね。ロボットの制御とかにも使ってみたいと思います。今回作ったプログラムは表示できればよかっただけなので、PC側のソフトでデータの取りこぼしがあるかもしれません。シリアル通信についてはもう少し調べてみたいと思います。

マイコンのコード

import time
from machine import Pin, ADC

# ADC settings
adc_x = ADC(Pin(34))
adc_y = ADC(Pin(35))
adc_x.atten(ADC.ATTN_11DB)
adc_y.atten(ADC.ATTN_11DB)

while True:
    x = adc_x.read()
    y = adc_y.read()

    print("x", x, "y", y)

    time.sleep_ms(100)

パソコンのコード

# -*- coding: utf-8 -*-
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from pyqtgraph import PlotWidget
import pyqtgraph
import numpy as np
import serial

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        self.plot_data = { 'X':np.full(10, 0), 'Y':np.full(10, 0) }

        self.resize(600, 600)
        self.setStyleSheet("QMainWindow {background: 'white';}")
        self.serial = serial.Serial('COM3', 115200, timeout=None)

        # leyout
        self.centralwidget = QtWidgets.QWidget(self)
        self.setCentralWidget(self.centralwidget)
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout2 = QtWidgets.QHBoxLayout()
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.verticalLayout.addLayout(self.horizontalLayout2)
        
        # pot widget
        self.plotwidget = PlotWidget(self)
        self.plotwidget.setBackground("#FFFFFFFF")
        plotitem = self.plotwidget.plotItem
        plotitem.setLabels(bottom='X', left='Y')
        plotitem.getAxis('bottom').setPen( pyqtgraph.mkPen(color='#000000') )
        plotitem.getAxis('left').setPen( pyqtgraph.mkPen(color='#000000') )
        plotitem.setRange(xRange = (0, 4095), yRange = (0, 4095), padding = 0)
        
        # leyout
        self.horizontalLayout.addWidget(self.plotwidget)

        # timer
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update_data)
        self.timer.start(50)

    def update_data(self):
        # stop timer
        self.timer.stop()

        # clear
        self.plotwidget.clear()

        # get serial
        line = self.serial.readline()
        splited = line.split()
        self.plot_data['X'] = np.append( self.plot_data['X'][1:], float(splited[1]) )
        self.plot_data['Y'] = np.append( self.plot_data['Y'][1:], float(splited[3]) )

        # set data
        self.plotwidget.addItem(
            pyqtgraph.PlotDataItem(
                x=self.plot_data['X'], y=self.plot_data['Y'], 
                pen=pyqtgraph.mkPen(color='#000000', width=10), antialias=True
            )
        )
        
        print(self.plot_data['X'], self.plot_data['Y'])

        # start timer
        self.timer.start(50)

def main():
    app = QtWidgets.QApplication(sys.argv)
    mainwindow = MainWindow(None)
    mainwindow.show()
    app.exec()

if __name__ == '__main__':
    main()

コメント

タイトルとURLをコピーしました