HDMIマイクロスコープを購入した話

f:id:gsmcustomeffects:20210110013750p:plain
今回はEakinsのHDMIマイクロスコープを購入したのでそれのレビュー
買ったもののリンクはこちら

はじめに

近年部品の小型化により電子工作界隈のはんだ付けツールも進化しています。
マイクロスコープ、ホットエアー、プリヒートマシン、簡易BGAワークステーション、卓上リフロー炉、ステンシルプリンタといったようなものが数万で買える時代になってきました。

そのなかでも今回紹介するHDMIマイクロスコープは、その名の通りHDMI映像出力を備えたカメラです。
モニターに拡大表示しながら作業ができるので狭ピッチICのはんだ付け、はんだブリッジの検証などがスムーズに行えます。
モノによってはストレージ機能がついていて映像の録画、写真の記録ができるもの、PC接続機能があるもの、液晶一体型などがあります。

さてマイクロスコープはAliexpressを探せばかなりの種類があります。
今回購入したものはSonyのイメージセンサIMX385を搭載した品であり比較的高級品に分類されるとおもいます。
レンズのインターフェイスは他のものと変わらずCマウント 、付属レンズはX200,X500を選べます。
セット内容をまとめるとこんな感じです。

  • 1 × 顕微鏡カメラ
  • 1 × 電源アダプタ (eu/au)
  • 1 × hdmi ケーブル
  • 1 × 200X/500X ズーム c マウントレンズ
  • 1 × カメラスタンド
  • 1 × led リングライト
  • 1 × 耐熱シリコンマット

肝心な値段ですがX500のレンズセットで33000円程度でした。
Aliexpressで買えるHDMIマイクロスコープの中では高額??な部類に入ると思います。

開封とレビュー

次に使用感なんかを書いていきます。
まず届いて組み立てたのがこんな感じ


商品紹介ページの写真ではコンパクトに見えますが、届いてみるとびっくり・・・・・かなりでかいです。

マウンタから外すとこんな感じです。

付属レンズをX500にしたのですが想定より巨大だったこともあり選択をミスったなという・・・・

次に実際の使用感みたいなのを書いていきます。
通常使用時HDMIに映すとこんな感じです。

結構くっきり映るのではんだブリッジのチェック、デバッグ時のプロービングにいいと思います。

次にカメラ本体の画像保存機能を使って写真を撮ってみました。

イメージセンサが優秀なのかわかりませんがかなりきれいに取れる感じです。

付属レンズは、X500レンズを選んだんですが最低倍率でも観察物体に寄り過ぎなのでもうちょい低倍率のものでもいいと思います。
Eakinsのストアでは、レンズの単体販売も行っているのでより低倍率なものを持っておくといいかもしれません。
ちなみに購入するときレンズの直径がマウンタに適合するものを選ばないと固定できないので注意が必要です。

最後に総合的な感想ですけど画像もきれいに撮れますし固定アームもしっかりしているので買ってよかったと思います。
万人にお勧めできるか?という話ですが、それなりに金額出せる人にとってはお勧めできます。
それ以外の人なら一式2万程度で購入できるこの辺がお勧めになると思います。

コメント、Q&Aなど

これ以上高額なものだと何があるの?

Sony IMX290というイメージセンサを利用したオートフォーカス対応のカメラモジュールがあったり4K出力に対応したカメラモジュール があったりします。

Eakins以外の選択肢ってあるの?

あります。

液晶一体型だとAndonstarというメーカー?ストア?が有名です。
HDMI出力に対応していないものもあるので注意が必要ですが安価かつ一体型で大型液晶がついているモデルもあるのでおススメではあります。

そのほかだとInsein Li Fung Microscope Storeも多くのカメラモジュールを取り扱っています。

ワークディスタンスを伸ばすには?

対策はいろいろありますが

  • 低倍率な違うレンズを選ぶ
  • Cマウントアダプタの倍率が低いものを選ぶ
  • バローレンズを用いる

バローレンズは、0.5X , 0.35Xなどを用いるとワーキングディスタンスを伸ばすことができます。
逆に視野を広げるならCマウントアダプタの倍率を変える必要があります。

私が買ったカメラのX500のレンズは1.0XのCマウントアダプタがついています。

日本で購入できるものはないの?

企業などでは正規ルートで購入できるものが選ばれる傾向にあるのでこういった意見もあると思います。

工具メーカーのHOZANが出しています。
製品情報 | マイクロスコープ・顕微鏡 【HOZAN】 ホーザン株式会社

各種パーツの単品売りをしてくれているので非常に助かります。

Amazonでも購入できます。

Hantek2D72(2CHオシロ+1CH AWG + DMM)の紹介

お久しぶりです。前回の記事から2か月近くあいてしまいましたがぼちぼち開発とかやっています。
今回は新機材としてHantek2D72というオシロスコープ+ファンクションジェネレータ+DMMが一つになったコンパクト測定器を買ったのでそれを紹介しようと思います。
f:id:gsmcustomeffects:20201213224605p:plain
購入はAliexpressのHantek Official Storeで買いました。
セールをやっていたので30%オフぐらいで155ドルで買えました。
f:id:gsmcustomeffects:20201208141314p:plain

Amazonでも売っていますがいくらか割高ですね。
https://amzn.to/3ordcNY

機能紹介

70MHz帯域のオシロスコープ

f:id:gsmcustomeffects:20201208141959p:plain

ファンクションジェネレータ

f:id:gsmcustomeffects:20201208142131p:plain

マルチメータ

f:id:gsmcustomeffects:20201208142201p:plain

USB充電可能(18650バッテリー交換可能)

f:id:gsmcustomeffects:20201208142245p:plain
※USBコネクタはType-CですがシンクICがついているわけではないので通常のType-C充電器だと充電できません。そのため付属のUSB充電器を使用することになります。
バッテリーに関しては、18650セルが使われているためセルがへたったら自己責任になりますがこういうのを買ってきて交換できます。

まとめ

今回は、Hantekのマルチ機能測定器であるHantek2D72を紹介しました。
サイズは若干でかめですがファンクションとオシロ、テスターが使え充電式で20000円程度となっているのでおススメではあります。
一つ一つの機能はベンチタイプ測定器に及びませんがそこまでのスペックを必要としない用途(例えばエフェクターデバッグなんか)には十分に使えるので据え置き測定器を買うまでもないなという人には良い選択肢になると思います。

 

MXR mini iso-brickの解析

最近アイソレートサプライが標準になってきて値段が落ち着いてきたのでMXR mini iso-brickを購入してみました。
この記事では、使った感想よりも回路側にシフトして解説していけたらと思います。

導入

購入のきっかけを説明するために現在販売されているアイソレートサプライを調査してみました。

  • Strymon Ojai系列、Zuma系列(型番は省略)
  • VITALAUDIO POWER CARRIER系列(一部ノンアイソレートあり)
  • MXR iso-brick系列
  • FIREGLOW PPS-1
  • VOODOO LAB PedalPower
  • TRUETONE 1SPOT PRO CS7

上四つは絶縁DCDCを利用したタイプで、下二つはトロイダルトランスを使用したタイプだったと記憶しています。
StrymonとVITALAUDIOはネットに内部画像があがってたのとFIREGLOWが売り切れだったのでMXRをチョイスしました。
そのほか比較的安価、一番小型である、有名ブランドの設計はどうなっているのかというのも理由の一つです。

MXR mini iso-brick

f:id:gsmcustomeffects:20201017182035j:plain

スペックとしては

  • 9V 300mA x 4
  • 9V/18V 800mA x1

合計2Aまでの出力に対応している。
音を評価する環境がないので早速分解していきます。
f:id:gsmcustomeffects:20201017190504j:plain

内部は基板が二段組になっています。
上側の基板にはDCDC回路及びスイッチングトランス、二次側の整流回路が載っています。
下側の基板にはリニアレギュレータと9V/18VのDCDCコンバータが載っています。

上側の基板

f:id:gsmcustomeffects:20201017200545p:plainf:id:gsmcustomeffects:20201017201223p:plain

上側の基板には以下に示すものが載っています。

  • プッシュプルコンバータ制御IC(ZG1810?)
  • 外部N-ch MOSFET x2(STN4260)
  • プッシュプルトランス(シルクにはEPC25記載)
  • 二次側整流回路

絶縁DCDCの回路方式としてはプッシュプル方式という方式が採用されています。
制御ICにはZG1810というものが使われています。
刻印にはDunlopが入ってるのでおそらくOEM品かと思われます。
MOSFETはSTANSONのSTN4260が使われています。
トランスを返して送られてきた矩形波を整流するために二次側には全波整流回路が出力数分載っています。

そもそもプッシュプルコンバータってなに?

プッシュプルコンバータ基本回路はこのような形です。

f:id:gsmcustomeffects:20201018010639p:plainf:id:gsmcustomeffects:20201018010705p:plain
トランスのセンタータップに電源電圧を印可し上下巻線を交互にスイッチングしながら動作するコンバータです。
コイル両端には2*VINが出てくるので高電圧になる場合は感電などの注意が必要です。
解説としてはEDNさんの資料TDKさんの資料がオススメです。

実機の波形を確認してみる

参考までに実機で一時側のスイッチ波形と二次側の波形をとってみました。

f:id:gsmcustomeffects:20201018012914p:plain

計測箇所は画像に示した通りになりますが①と②は1次側GNDに対する電圧を見ており、③は巻線両端の電圧を見ています。
一時側トランスの巻線が直接はんだされてるのはちょっとびっくりですが気にしないことにしましょう。(2*VIN出てるのでちょっと怖い

次に波形を示します。

f:id:gsmcustomeffects:20201018005822p:plainf:id:gsmcustomeffects:20201018005826p:plain
一枚目はGNDに対する一時側の巻線両端を計測したものです。
Vinとしては18Vが入力されているのでVp-pで36V付近が出てきます。
上側と下側を交互にオンしてトランスを駆動している形です。
二枚目は二次側の巻線間を計測したもので0Vを中心にVp-pで25V付近が出ています。
この波形を全波整流するとダイオードの順方向電圧分降下して11.8Vぐらいになるというわけです。
尚スイッチング周波数は60KHz付近です。

下側の基板

少し脱線しましたが、下側の基板も見ていきましょう

f:id:gsmcustomeffects:20201018003041p:plainf:id:gsmcustomeffects:20201018003048p:plain

下側の基板には

  • 9Vリニアレギュレータ 78M09 x4(HTsemi製)
  • 9/18V用DCDCコンバータIC AAP6034A (SGMICRO製)

が載っています。
上側のMOSもそうですが半導体は中華デバイス主体です。
これのおかげで12000円でこのスペックを実現しているのかーとちょっと感心しました。

次に回路動作を見ていこうと思います。
上の基板から来た11.7Vはリニアレギュレータに送られて9Vを生成します。
上の基板から来た24.5VはDCDC回路に送られて9 or 18Vを出力します。

電圧の切り替えはオンボードのスライドスイッチでFB抵抗を切り替えて実現しています。
二次側回路だけ軽くとったので参考にしてください。
drive.google.com

まとめ

今回はmxr iso brick miniを解析し70%ぐらい理解した。
低背のカスタムトランスとOEM制御IC?を用いてこの大きさにまとめているのは流石MXRといったところでしょう。
機会があればFIREGLOWのアイソレート電源も解析してみたいと思う。

おまけ

LT3439を使ったプッシュプルコンバータ

今回の解析では1次側にOEMチップ?が使われていたので同じようなものを作るとき困る。
そこでLT3439を用いたものを紹介します。

f:id:gsmcustomeffects:20201018015822p:plainf:id:gsmcustomeffects:20201018020607p:plain

トランスさえ作れれば結構お手軽な構成ですね。

フライバック方式

複数のアイソレートOUTを小型で作るにはカスタムトランスを使うしかないのが現状です。
汎用トランスで作れそうな絶縁DCDCとしてはフライバックが有名です。
f:id:gsmcustomeffects:20201018021429p:plain

例えばLM5180だとこのような形になります。

f:id:gsmcustomeffects:20201018021616p:plainf:id:gsmcustomeffects:20201018021600p:plain

ちなみにFlybackもトランス出力を増やすことで複数回路に対応できます。
f:id:gsmcustomeffects:20201018021908p:plain

結局のところ一時側の巻線に多くの電流が流れるのでプッシュプルやハーフブリッジ、フルブリッジのような構成が向いてるのかもしれません・・・・

Strymon Ojaiの内部

https://alfalfasprout69.wixsite.com/ojai/gut-shot-picturesより引用
f:id:gsmcustomeffects:20201011150021p:plain

Strymonはトランスを複数載せているのでフライバック?
ピン数的にプッシュプルかもしれない

VITALAUDIO VA-05の内部

Amazonレビューより引用
f:id:gsmcustomeffects:20201011150239p:plain

VITALはMXRに似ているのでもしかしたらここがOEMで作ってるのかな?

VITALAUDIO VA-R8の内部

アスモ君より拝借(https://twitter.com/aSumoeffects/media

f:id:gsmcustomeffects:20201011150501j:plainf:id:gsmcustomeffects:20201011150457j:plain

Seeed FusionPCBで基板を作った話

タイトル通りの話ですがSeeed FusionPCBで基板を発注した話です。

私自身FusionPCBというサービスを知ってから数年たちますが、最近ではつぎつぎに新しいサービスを展開し非常に勢いのあるメーカーであると感じます。

www.fusionpcb.jp


ブランド紹介も済んだところで早速本題に移りたいと思います。
今回発注した基板は、デジタルエフェクターDSPが載っている基板です。
モノとしては、Baoding Forlinx Embedded Technologyhttp://www.forlinx.net/product/rt1061-44.html)社のFET1061Sを実装するための基板になります。


f:id:gsmcustomeffects:20200807153256p:plain


届いた基板がこれ

f:id:gsmcustomeffects:20200807204013p:plain

捨て基板は折ってしまっていますが特に問題はないです。
基板自体の品質ですが、シルクもレジストもかなりきれいに仕上がっています。

今回は基板+ステンシルも頼んだので13.8$(4.9 + 8.9)
配送は新しくできたJapanDirectLineを利用して12.38$
合計で30$いかないで基板が作れてしまった。
個人的にJapanDirectLineが導入され、送料が17$→12.38$程度まで下がったのが大きいといえる。

配送時間だが、発注からの流れを張っておくので参考までに・・・・・
f:id:gsmcustomeffects:20200807160244p:plain

以上Seeed FusionPCBに基板を発注した話でした。

参考

Seeedのエンジニアが書いているブログは新サービス情報などが手に入るので非常にお勧めである。
FusionPCB-配送データ大披露! | Seeed FusionPCB

KiCadのバスについて

導入

KiCadにはメモリバスなどの同種な信号線をまとめるバス機能がある。
バス機能を使うことで回路図の見栄えが良くなったりするので覚えておいて損はない。
今回はそれのやり方とTipsを紹介しようと思う。

使い方


f:id:gsmcustomeffects:20200725093351p:plain

  1. 画像のようにローカルラベルをD0~D7を配置する。
  2. ワイヤーバスエントリを配置
  3. バスを配置
  4. グローバルラベルにてD[0..7]のように信号線をまとめる

使う際はグローバルラベルが推奨されているが、同階層で結線するならローカルラベルでも問題なさそう。
ちなみにまとめたい配線が離れている場合でも0..7 , 8..15とすれば0..15でまとめたところとつなぐことができる。

f:id:gsmcustomeffects:20200725094018p:plainf:id:gsmcustomeffects:20200725093932p:plain

PySide2でQtQuick(qml)使うメモ3

今回はPySide2とPySerialを組み合わせて使うメモ

やることとしてはQMLで作成したGUI側でイベントを発生させてシリアルで何か送信してマイコンを制御するという感じ
つくったのはこんな感じのやつ

f:id:gsmcustomeffects:20191005005003p:plain

COMの選択をしてオープンをすると5~7のオブジェクトが表示される仕組み クローズすると消えるようになってる

f:id:gsmcustomeffects:20191005010331p:plain

コード全文は下に貼るのでちょい特殊な部分だけ解説していく流れで行きます。

尚基礎に関しては一番下に過去の記事貼っていますのでそちらを参考に環境構築などして下さい

Python側実装説明

class SerialComport(QtCore.QObject):
    def __init__(self, parent=None):
        super(SerialComport, self).__init__(parent)
        self.flag = 0
        self.instance = []

    @QtCore.Slot(result = 'QVariant')
    def comlist(self):
        self.ports = list_ports.comports()
        self.devices = [info.device for info in self.ports]
        self.instance.clear()                                   #clear list
        for i in range(len(self.devices)):
            self.instance.append(serial.Serial(port=self.devices[i],baudrate=9600))#instance packing
            self.instance[i].close()
        return self.devices

self.ports = list_ports.comports()でCOMの取得をしている。
self.instance.appendってのでインスタンスを配列みたいに管理できる。
これのおかげで self.instance[1].closeみたいな感じでアクセス可能になるわけ.
めんどくさかったのでボーレートは9600固定(GUI側でボーレート指定すれば実現は可能)
return self.devicesでQt側にlistで返している('QVariant'なので色々返せる)

Pyserialのほうは殆どAPI使ってるだけなので特にないけど送信はこんな感じで書いてる

    @QtCore.Slot(str,int,int,int)
    def slider_changed(self, arg1,r,g,b):
        for i in range(len(self.devices)):
            if (self.instance[i].port == arg1):
                self.instance[i].write(b.to_bytes(1, 'big'))
                self.instance[i].write(g.to_bytes(1, 'big'))
                self.instance[i].write(r.to_bytes(1, 'big'))

Qt(qml)側の説明

function comupdate(){
        comboBox.model.clear()
        var device = SerialComport.comlist();
        for(var key in device){
            comboBox.model.append({text:device[key]});
        }
        comboBox.currentIndex = 1;
    }

起動時の処理を毎度書くのがめんどかったのでfunctionにした。
あとはcomboBoxのmodelプロパティにアクセスしCOMリストを更新している感じ

function part_visible(){
        radioDelegate.visible = true
        radioDelegate1.visible = true
        radioDelegate2.visible = true
        radioDelegate3.visible = true
        slider.visible = true
        slider1.visible = true
        slider2.visible = true
        rectangle.visible = true
    }

    function part_hide(){
        radioDelegate.visible = false
        radioDelegate1.visible = false
        radioDelegate2.visible = false
        radioDelegate3.visible = false
        slider.visible = false
        slider1.visible = false
        slider2.visible = false
        rectangle.visible = false
    }

これはプロパティ表示/非表示の命令であり、各種コンポーネントのvisibleプロパティにtrue/falseしているだけ。

まとめ

Pyserial + PySide2で簡単なCOMアプリケーションを構成することができた。
結構手抜き実装なのでちゃんとやるならtryとか入れたほうがいいと思う。あとはisOpenのケアをもっとまじめにするとかね。

エンディアンとかあんまし気にしてないので間違ってるかも。なのでそこはPyserialのドキュメントちゃんと読んでください。
最後に動作例の動画でも貼っときます


マイコン側参考コード

ハードはKinetis FRDM-K22FでソフトはMbedを利用して書いてます。

/* mbed Microcontroller Library
 * Copyright (c) 2018 ARM Limited
 * SPDX-License-Identifier: Apache-2.0
 */

#include "mbed.h"
#include "stats_report.h"

PwmOut led1(LED1);//r
PwmOut led2(LED2);//g
PwmOut led3(LED3);//b


#define SLEEP_TIME                  500 // (msec)
#define PRINT_AFTER_N_LOOPS         20
Serial pc(USBTX, USBRX);
// main() runs in its own thread in the OS
int main()
{
    SystemReport sys_state( SLEEP_TIME * PRINT_AFTER_N_LOOPS /* Loop delay time in ms */);

    int count = 0;
    while (true) {
        char b = pc.getc();
        char g = pc.getc();
        char r = pc.getc();
            led1 = 1.0-1.0/255.0f*(float)r;//R
            led2 = 1.0-1.0/255.0f*(float)g;//G
            led3 = 1.0-1.0/255.0f*(float)b; //B   
        
        
    }
}

参考用コード全文(Python側)

import sys
import os
from PySide2 import QtCore, QtWidgets, QtQml
from serial.tools import list_ports
import serial

class SerialComport(QtCore.QObject):
    def __init__(self, parent=None):
        super(SerialComport, self).__init__(parent)
        self.flag = 0
        self.instance = []

    @QtCore.Slot(result = 'QVariant')
    def comlist(self):
        self.ports = list_ports.comports()
        self.devices = [info.device for info in self.ports]
        self.instance.clear()                                   #clear list
        for i in range(len(self.devices)):
            self.instance.append(serial.Serial(port=self.devices[i],baudrate=9600))#instance packing
            self.instance[i].close()
        return self.devices

    @QtCore.Slot(str)
    def comopen(self,arg1):
        for i in range(len(self.devices)):
            if(self.instance[i].port==arg1):
                self.instance[i].open()                         #COM open

    @QtCore.Slot(str)
    def comclose(self, arg1):
        for i in range(len(self.devices)):
            if (self.instance[i].port == arg1):
                self.instance[i].close()                        #COM close

    @QtCore.Slot(str,result='int')
    def comlistchanged(self,arg1):
        for i in range(len(self.devices)):
            if(self.instance[i].port==arg1):                    #checking which COM port is selected.
                if(self.instance[i].isOpen() == True):          #open or close check
                    self.flag = 1                               #if checked COM open, set flag.
                    print(self.instance[i].port + ":open")
                else:
                    self.flag = 0                               #if checked COM close, clear flag.
                    print(self.instance[i].port + ":close")
            else:
                if(self.instance[i].isOpen() == True):
                    print(self.instance[i].port + ":open")
                else:
                    print(self.instance[i].port + ":close")
        return self.flag

    @QtCore.Slot()
    def debug_alert(self):
        print("call!")                                         #QtQuick test function

    @QtCore.Slot(str)
    def ledred(self,arg1):
        for i in range(len(self.devices)):
            if (self.instance[i].port == arg1):
                packet = []
                packet.append(0x00)#b
                packet.append(0x00)#g
                packet.append(0xff)#r
                self.instance[i].write(packet)

    @QtCore.Slot(str)
    def ledblue(self, arg1):
        for i in range(len(self.devices)):
            if (self.instance[i].port == arg1):
                packet = []
                packet.append(0xff)#b
                packet.append(0x00)#g
                packet.append(0x00)#r
                print(packet)
                self.instance[i].write(packet)

    @QtCore.Slot(str)
    def ledgreen(self, arg1):
        for i in range(len(self.devices)):
            if (self.instance[i].port == arg1):
                packet = []
                packet.append(0x00)
                packet.append(0xff)
                packet.append(0x00)
                self.instance[i].write(packet)

    @QtCore.Slot(str)
    def ledorange(self, arg1):
        for i in range(len(self.devices)):
            if (self.instance[i].port == arg1):
                packet = []
                packet.append(0x00)
                packet.append(0x45)
                packet.append(0xff)
                self.instance[i].write(packet)

    @QtCore.Slot(str,int,int,int)
    def slider_changed(self, arg1,r,g,b):
        for i in range(len(self.devices)):
            if (self.instance[i].port == arg1):
                self.instance[i].write(b.to_bytes(1, 'big'))
                self.instance[i].write(g.to_bytes(1, 'big'))
                self.instance[i].write(r.to_bytes(1, 'big'))





if __name__ == "__main__":
    os.environ["QT_QUICK_CONTROLS_STYLE"] = "Material"              #set Material theme(QtQuick)
    app = QtWidgets.QApplication(sys.argv)
    myconnect = SerialComport()                                     #Create instance


    engine = QtQml.QQmlApplicationEngine()                          #GUI
    ctx = engine.rootContext()
    ctx.setContextProperty("SerialComport", myconnect)              #Connect GUi to SerialComport Class
    engine.load('mypyside2.qml')                                    #qml file load.
    if not engine.rootObjects():
        sys.exit(-1)
    sys.exit(app.exec_())

コード全文(qml側)

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.3


Window {

    function init(){
        comupdate();
    }

    function comupdate(){
        comboBox.model.clear()
        var device = SerialComport.comlist();
        for(var key in device){
            comboBox.model.append({text:device[key]});
        }
        comboBox.currentIndex = 1;
    }

    function part_visible(){
        radioDelegate.visible = true
        radioDelegate1.visible = true
        radioDelegate2.visible = true
        radioDelegate3.visible = true
        slider.visible = true
        slider1.visible = true
        slider2.visible = true
        rectangle.visible = true
    }

    function part_hide(){
        radioDelegate.visible = false
        radioDelegate1.visible = false
        radioDelegate2.visible = false
        radioDelegate3.visible = false
        slider.visible = false
        slider1.visible = false
        slider2.visible = false
        rectangle.visible = false
    }

    objectName: "a"
    visible: true
    width: 640
    height: 480
    color: "#e2dde2"
    title: qsTr("Controller")
    Component.onCompleted:{
        init();
    }
    Button {
        id: button
        x: 255
        y: 28
        text: qsTr("COM ")
        font.pointSize: 13
        onClicked:{
            comupdate();
        }
    }

    ComboBox {
        id: comboBox
        x: 25
        y: 28
        width: 198
        height: 40
        visible: true
        editable: false
        model: ListModel {
            id: model
        }
        onCurrentIndexChanged:{
            var flag = SerialComport.comlistchanged(comboBox.model.get(comboBox.currentIndex).text);
            if(flag == 1){
                part_visible();
            }
            else{
                part_hide();
            }

        }
    }

    Button {
        id: button1
        x: 369
        y: 28
        text: qsTr("OPEN")
        font.pointSize: 13
        onClicked:{
            SerialComport.comopen(comboBox.model.get(comboBox.currentIndex).text);
            part_visible();
        }
    }

    Button {
        id: button2
        x: 475
        y: 28
        text: qsTr("CLOSE")
        font.pointSize: 13
        onClicked:{
            SerialComport.comclose(comboBox.model.get(comboBox.currentIndex).text);
            part_hide();
        }
    }

    RadioDelegate {
        id: radioDelegate
        visible:true
        x: 81
        y: 106
        text: qsTr("Red")
        onClicked:{
            SerialComport.ledred(comboBox.model.get(comboBox.currentIndex).text)
        }
    }

    RadioDelegate {
        id: radioDelegate1
        visible:true
        x: 187
        y: 106
        text: qsTr("Blue")
        onClicked:{
            SerialComport.ledblue(comboBox.model.get(comboBox.currentIndex).text)
        }
    }

    RadioDelegate {
        id: radioDelegate2
        visible:true
        x: 293
        y: 106
        text: qsTr("Green")
        onClicked:{
            SerialComport.ledgreen(comboBox.model.get(comboBox.currentIndex).text)
        }
    }

    RadioDelegate {
        id: radioDelegate3
        x: 420
        y: 106
        text: qsTr("Orange")
        visible: true
        onClicked:{
            SerialComport.ledorange(comboBox.model.get(comboBox.currentIndex).text)
        }
    }

    Slider {
        id: slider
        visible:true
        x: 81
        y: 215
        width: 439
        height: 40
        stepSize: 1
        wheelEnabled: true
        to: 255
        font.family: "Courier"
        font.capitalization: Font.AllLowercase
        value: 50
        onValueChanged:{
            SerialComport.slider_changed(comboBox.model.get(comboBox.currentIndex).text,slider.value,slider1.value,slider2.value)
            rectangle.color = Qt.rgba(slider.value/slider.to,slider1.value/slider.to,slider2.value/slider.to,1)
        }
    }

    Slider {
        id: slider1
        visible:true
        x: 81
        y: 261
        width: 439
        height: 40
        stepSize: 1
        wheelEnabled: true
        to: 255
        value: 50
        onValueChanged:{
            SerialComport.slider_changed(comboBox.model.get(comboBox.currentIndex).text,slider.value,slider1.value,slider2.value)
            rectangle.color = Qt.rgba(slider.value/slider.to,slider1.value/slider.to,slider2.value/slider.to,1)
        }
    }

    Slider {
        id: slider2
        visible:true
        x: 81
        y: 307
        width: 439
        height: 40
        stepSize: 1
        wheelEnabled: true
        to: 255
        value: 50
        onValueChanged:{
            SerialComport.slider_changed(comboBox.model.get(comboBox.currentIndex).text,slider.value,slider1.value,slider2.value)
            rectangle.color = Qt.rgba(slider.value/slider.to,slider1.value/slider.to,slider2.value/slider.to,1)
        }
    }

    Rectangle {
        id: rectangle
        visible:true
        x: 541
        y: 261
        width: 56
        height: 46
        color:Qt.rgba(0,0,0,1)
    }
}