SSブログ
English Version
前の5件 | -

CH32V203で遊ぶ(その1)SPIでLCD [CH32V]

 円安の影響もあり、従来から愛用してきた PIC24 は値上がりしたままです。「最近遊んだMPU」の記事で書いたように秋月電子通商さんで安価(執筆時点で120円)で入手できるようになった CH32V203K8T6 のソフトウェアを統合開発環境である MounRiver Studio の環境を準備済みなので少し遊んでみました。


1.今回の目標
 目標として部品箱で見つけた少し古いLCDである NOKIA 5110(84x48ドット)を制御してみることにしました。


2.SPI通信
★変更 2024/07/13 全体的に誤記修正(I2C ⇒ SPI)
 CH32V203K8T6 のデータシートは読み易くはないですが、サンプルコードがそれなりにあるので助かります。
 SPIインターフェースを使ってLCDを制御する場合、多くのLCDではコマンドとデータを識別する信号入力があり、この識別信号をSPI通信と同期して切り替える必要があります。このためネット上で見かけるほとんどのコードはSPIの送信レジスタに書き込み後に送信が完了するまで待つようになっています。
 このため連続してSPIで送信する際に送信データ間の隙間が大きくなってしまいます。下図から送信データ間に 11us の隙間が発生していることが判りますが、CPU が 144MHz 動作の割には大きいように感じます。SPIのクロックは 2MHz です。
 因みにネット上をざっくり探しましたがSPIでLCD制御する場合の実測波形は見つかりませんでした。

SPIでの連続した送信例(対処前)


 この送信データ間の隙間時間を短くするために次の対処をやってみました。
  • SPI送信後に送信完了を待たない
  • SPI送信前に送信対象データのコマンド/データの種別が前回の送信と異なる場合はSPI送信完了までウェイトした後にコマンド/データ識別信号を変更する

 変更後のデジアナ波形が下図になります。隙間時間が 11us から 4.5us に短縮されました。

SPIでの連続した送信例(対処後)



3.LCD(NOKIA5110) の制御
 LCDの接続は下表に示す通りでLIGHT信号は100Ωの抵抗を介して接続しました。また、消費電流は 5mA 程度でしたが電源の ON/OFF がし易いように CH32V203 への電源は WCH-LinkE からではなく、安定化電源から給電しています。

CH32V203K8Y6NOKIA 5110WCH-LinkE
1:3.3V6:VCC
5:3.3V6:VCC
7:RA17:LIGHT
8:RA21:RST
9:RA3>2:CE
10:RA43:DC
11:SPI_CK5:CLK
12:SPI_MISO
13:SPI_MOSI4:DIN
16:GND8:GND8:GND
17:3.3V6:VCC
19:TX1:RX
23:SWDIOSWDIO
24:SWCLKSWCLK
32:GND8:GND8:GND


 主な実装機能は下記の通りです。
  1. フォントは「ポケコン(G850)用拡張基板(その7)仮想画面でCP/M」の記事で書いた自作の縮小フォント(4x5)を使用

  2. LCD 内部の RAM の読み出し機能が無いのでアプリ内に VRAM を実装し、テキストとグラフィックの重ね合わせ表示に対応

  3. 画面サイズが 84 x 48 と小さいのでグラフィック機能は凝らずにドット描画、ライン描画、円描画のみに対応


 ライン描画処理は過去にも何回か作成していて今回はケース分けが少なくなるように考えて実装しました。LCDに実際に描画したサンプルが下の写真です。

NOKIA5110での表示例



4.まとめ
 MounRiver Studio を使ってSPIでのLCD(NOKIA 5110)を制御してみました。Arduino 環境であれば割合簡単に動かせるようになると思いますが、Arduino はソースを探す作業がメインになりがちで内部の仕掛けが見えにくいのであまり好きではありません。最初はおそらく10倍以上の手間がかかりますが一度作った機能は次回からは自分ですぐに使えようになるのでその後の作業が楽になるはずです。

★追記 2024/07/14 {
 MounRiver Studio でのディバッグ時の画面キャプチャを貼っておきます。

MounRiver Studio でのディバッグ画面例
}

★追記 2024/07/15 {
 機能追加時に必要となるデータシートから抜粋した CH32V203K8T6 のピンアサイン図と機能対応表を追記します。

ピンアサイン(CH32V203KxT6)


機能対応表(その1)

機能対応表(その2)
}





 まだあまり整理していませんがLCD関連のヘッダと処理コードを貼っておきます。

LCD関連ヘッダファイル
/************************************* LCD drive headder(Nokia 5110) Ver 0.01 2024/06/12 by skyriver *************************************/ #ifndef CONCAT #define TOSTRING(x) #x #define CONCAT(x,y) x##y #define CONCATM(x,y) CONCAT(x,y) #endif #define LCD_MAX_X 84 // max x + 1 #define LCD_MAX_Y 48 // max y + 1 #define LCD_MAX_LN (LCD_MAX_Y / 8 ) #define LCD_CONTRAST 64 // contrast initial value /**** I/O definition ****/ #define LCD_PORT GPIOA // SPI port for LCD #define LCD_SPI SPI1 // SPI number for LCD RA5:SCK,RA6:MISO,RA7:MOSI #define LCD_SPICK GPIO_Pin_5 #define LCD_SPIMISO GPIO_Pin_6 #define LCD_SPIMOSI GPIO_Pin_7 #define LCD_LED GPIO_Pin_1 // LCD LED 0:on #define LCD_RST GPIO_Pin_2 // LCD RST #define LCD_CS GPIO_Pin_3 // SPI_CS #define LCD_CMD GPIO_Pin_4 // LCD CMD/PAR #define LCD_BSET( bits ) GPIO_SetBits( LCD_PORT, bits ) #define LCD_BRESET( bits ) GPIO_ResetBits( LCD_PORT, bits ) #define LCD_SPIWR( dat ) SPI_I2S_SendData( LCD_SPI, dat ) #define LCD_SPIRD() SPI_I2S_ReceiveData( LCD_SPI ) #define LCD_SPIWRSTS() SPI_I2S_GetFlagStatus( LCD_SPI, SPI_I2S_FLAG_TXE ) #define LCD_SPIRDSTS() SPI_I2S_GetFlagStatus( LCD_SPI, SPI_I2S_FLAG_RXNE ) #define LCD_SPIWRBSY() SPI_I2S_GetFlagStatus( LCD_SPI, SPI_I2S_FLAG_BSY ) void LcdCsOn( void ); void LcdCsOff( void ); uint16_t LcdWrCmd( uint8_t dat ); uint16_t LcdWrData( uint8_t dat ); void InitLcd( void ); void LcdLocate( uint8_t x, uint8_t y ); void LcdWrDatas( uint8_t *dpnt, uint16_t len ); void LcdWrFill( uint8_t data, uint16_t len ); void LcdCls( void ); void LcdSetLed( uint8_t led ); void LcdSetCont( uint8_t val ); void LcdPutc( uint8_t data ); void LcdSetPoint( uint8_t x, uint8_t y ); void LcdCircle( uint8_t cx, uint8_t cy, uint8_t r ); void LcdLine( uint8_t xst, uint8_t xen, uint8_t yst, uint8_t yen ); #define FONTSIZX 4 //font width #define FONTSIZY 5 // font hight extern uint8_t Font4x5[]; // font data


LCD関連処理コード
/************************************* LCD driveer(Nokia 5110) Ver 0.02 2024/06/14 by skyriver *************************************/ #include "debug.h" #include <stdint.h> #include "stdlib.h" #include "LcdNokia.h" #define LCDTIMER 1000 // write SPI timer counter typedef enum { DATA, CMD } SpiSortTyp; static SpiSortTyp PrevSort; // spi send previous mode(cmd or data) static uint8_t LcdVram[ LCD_MAX_X * LCD_MAX_LN ]; // LCD VRAM image static uint16_t LcdXPos, LcdYPos; // text write point static uint16_t LcdTxtX, LcdTxtY; // graphic write point // initialize GPIO and SPI void InitLcdSpi( void ) { GPIO_InitTypeDef GPIO_InitStructure={0}; SPI_InitTypeDef SPI_InitStructure={0}; RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_SPI1, ENABLE ); // RCC_APB2PeriphClockCmd( CONCATM(RCC_APB2Periph_, LCD_PORT) | RCC_APB2Periph_SPI1, ENABLE ); GPIO_InitStructure.GPIO_Pin = LCD_SPICK | LCD_SPIMOSI; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( LCD_PORT, &GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = LCD_RST | LCD_CS | LCD_CMD | LCD_LED; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( LCD_PORT, &GPIO_InitStructure ); GPIO_InitStructure.GPIO_Pin = LCD_SPIMISO; // not use GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( LCD_PORT, &GPIO_InitStructure ); GPIO_SetBits(LCD_PORT, LCD_CS ); GPIO_ResetBits(LCD_PORT, LCD_RST| LCD_LED ); SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_Direction = SPI_Direction_1Line_Tx; // SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;//8bit mode0 msbfirst SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; // SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 16:500kHz SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; // SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init( LCD_SPI, &SPI_InitStructure ); SPI_Cmd( LCD_SPI, ENABLE ); } // set LCD's SPI CS after send complete void LcdCsOn( void ) { while( LCD_SPIWRBSY() == SET ) {} LCD_BRESET( LCD_CS ); } // reset LCD's SPI CS after send complete void LcdCsOff( void ) { while( LCD_SPIWRBSY() == SET ) {} LCD_BSET( LCD_CS ); } // write cmd to LCD // dat <- write data // return -> nonzero:OK, else timeover uint16_t LcdWrCmd( uint8_t dat ) { uint16_t cnt = LCDTIMER; while( --cnt ) { if( LCD_SPIWRSTS() == SET ) { // can write if( PrevSort != CMD ) { PrevSort = CMD; while( LCD_SPIWRBSY() == SET ) {} LCD_BRESET( LCD_CMD ); } LCD_SPIWR( dat ); break; } } if( cnt == 0 ) { printf( "\nLcd timeover" ); } return( cnt ); } // write data to LCD // dat <- write data // return -> nonzero:OK, else timeover uint16_t LcdWrData( uint8_t dat ) { uint16_t cnt = LCDTIMER; while( --cnt ) { if( LCD_SPIWRSTS() == SET ) { // can write if( PrevSort != DATA ) { PrevSort = DATA; while( LCD_SPIWRBSY() == SET ) {} LCD_BSET( LCD_CMD ); } LCD_SPIWR( dat ); break; } } if( cnt == 0 ) { printf( "\nLcd timeover" ); } return( cnt ); } void InitLcd( void ) { InitLcdSpi(); Delay_Ms(100); // LCD_BRESET( LCD_RST ); LCD_BSET( LCD_RST ); LcdCsOn(); LcdWrCmd(0b00100000 | 1 ); // Function set : H = 1 LcdWrCmd(0b00000100 | 1 ); // Temparature control : TC=1(0-3) LcdWrCmd(0b00010000 | 3 ); // Bias system : Bais=3(0-7) LcdWrCmd(0b10000000 | LCD_CONTRAST ); // Set Vop : contrast(0-127) LcdWrCmd(0b00100000 | 0 ); // Function set : H=0 LcdWrCmd(0b00001000 | 4 ); // Display control : normal(D:1,E:0) LcdWrCmd(0b01000000 | 0 ); // Set Y addr : 0(0..5)( x 8 dot) LcdWrCmd(0b10000000 | 0 ); // Set X addr : 0(0..83) LcdCsOff(); } // set write point // x,y <- point addr x:0..83, y:0..5 void LcdLocate( uint8_t x, uint8_t y ) { LcdTxtX = x; LcdTxtY = y; LcdCsOn(); LcdWrCmd(0b01000000 | y ); LcdWrCmd(0b10000000 | x ); LcdCsOff(); } // write datas // dpnt <- data addr // leng <- how many data void LcdWrDatas( uint8_t *dpnt, uint16_t len ) { uint8_t *vpnt = LcdVram + LcdTxtY * LCD_MAX_X + LcdTxtX; LcdTxtX += len; if( LcdTxtX >= LCD_MAX_X ) { LcdTxtY += LcdTxtX / LCD_MAX_X; LcdTxtX = LcdTxtX % LCD_MAX_X; } LcdCsOn(); while( len-- ) { *vpnt |= *dpnt++; LcdWrData( *vpnt++ ); } LcdCsOff(); } // write same data // data <- write data // leng <- how many data void LcdWrFill( uint8_t data, uint16_t len ) { uint8_t *vpnt = LcdVram + LcdTxtY * LCD_MAX_X + LcdTxtX; LcdTxtX += len; if( LcdTxtX >= LCD_MAX_X ) { LcdTxtY += LcdTxtX / LCD_MAX_X; LcdTxtX = LcdTxtX % LCD_MAX_X; } LcdCsOn(); while( len-- ) { LcdWrData( *vpnt++ = data ); } LcdCsOff(); } void LcdCls( void ) { LcdLocate( 0, 0 ); LcdWrFill( 0, LCD_MAX_X * LCD_MAX_LN ); } void LcdSetLed( uint8_t led ) { if( led ) { LCD_BRESET( LCD_LED ); } else { LCD_BSET( LCD_LED ); } } void LcdSetCont( uint8_t val ) { LcdCsOn(); LcdWrCmd(0b10000000 | val ); // contrast(0-127) LcdCsOff(); } // write font data // data <- char code void LcdPutc( uint8_t data ) { LcdWrDatas( &Font4x5[ (data - 0x20) * FONTSIZX ], FONTSIZX ); } // set point // (x,y) <- position void LcdSetPoint( uint8_t x, uint8_t y ) { if( (x < LCD_MAX_X) && (y < LCD_MAX_Y ) ) { uint8_t lin = y >> 3; uint8_t *vpnt = LcdVram + lin * LCD_MAX_X + x; *vpnt |= 1 << (y % 8); LcdLocate( x, lin ); LcdWrDatas( vpnt, 1 ); } } // draw circle void LcdCircle( uint8_t cx, uint8_t cy, uint8_t r ) { uint8_t x = r; uint8_t y = 0; int8_t d = -2 * r + 3; while(x >= y) { LcdSetPoint( cx + x, cy + y ); LcdSetPoint( cx - x, cy + y ); LcdSetPoint( cx + x, cy - y ); LcdSetPoint( cx - x, cy - y ); LcdSetPoint( cx + y, cy + x ); LcdSetPoint( cx - y, cy + x ); LcdSetPoint( cx + y, cy - x ); LcdSetPoint( cx - y, cy - x ); if(d >= 0) { d -= 4 * --x; } y++; d += 4 * y + 2; } } // draw line void LcdLine( uint8_t xst, uint8_t yst, uint8_t xen, uint8_t yen ) { int8_t x,y,difx,dify; int8_t err, xtail, ytail; LcdXPos = xen; LcdYPos = yen; difx = abs( xen - xst ); dify = abs( yen - yst ); if( ( (difx >= dify) && (xen > xst) ) || ( (difx < dify) && (yen > yst) ) ) { x = xst; y = yst; xtail = xen; ytail = yen; } else { x = xen; y = yen; xtail = xst; ytail = yst; } if( difx >= dify ) { int8_t dy; dy = ytail > y ? 1 : -1; err = difx / 2; for( ; x < xtail; x++, xtail-- ) { LcdSetPoint( x, y ); LcdSetPoint( xtail, ytail ); err += dify; if( err >= difx ) { err -= difx; y += dy; ytail -= dy; LcdSetPoint( x, y ); LcdSetPoint( xtail, ytail ); } } if( x == xtail ) { LcdSetPoint( x, y ); } } else { int8_t dx; dx = xtail > x ? 1 : -1; err = dify / 2; for( ; y < ytail; y++, ytail-- ) { LcdSetPoint( x, y ); LcdSetPoint( xtail, ytail ); err += difx; if( err >= dify ) { err -= dify; x += dx; xtail -= dx; LcdSetPoint( x, y ); LcdSetPoint( xtail, ytail ); } } if( y == ytail ) { LcdSetPoint( x, y ); } } }
※Ver0.02 2024/07/14 LcdLine()を両端からの描画方式にして高速化



★追記 2024/07/15
 秋月さんから購入した ILI9341搭載2.8インチTFT液晶 MSP2807(320 x 240 dot)に対応してみました。CH32V203 の内蔵 RAM では AP 内に VRAM 領域を確保できないので文字描画後にグラフィック描画した場合は混在表示できますが、グラフィック描画部に文字を表示した場合は重なった部分のグラフィックは消去されます。

MSP2807 での表示例


 X(旧Twitter)に投稿したメッセージに添付した動画を貼っておきます。本来なら画面クリアしてから描画ONすべきなのですが、書き込み速度が判リ易いように消去処理も表示状態で行っています。




[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

GreenPAKで遊ぶ(その8)導通チェッカ(その2) [GreenPAK]

 前回の記事で SLG46826 単独で何か有用なツールを作りたいということで GreenPAK Designer て導通チェッカを設計してみました。中々実用的なものができたのでプリント基板化して実際に作ってみましたので記録に残しておきたいと思います。自分のためのメモも兼ねて後日参照し易いようにパターン図や部品実装後の写真も掲載します。


1.導通チェッカの仕様
 今回作成した導通チェッカを Conchecker と命名しました。主な仕様は次のとおりです。
  1. 電源として3Vのボタン電池(CR2032)を1個使用
  2. 被測定側への印加電圧は約 0.5V
  3. スリープ時の消費電流は約 0.3uA
  4. スリープ状態時にプローブをショートすることでウェイク状態に移行する
  5. ウェイクから30秒後にスリープ状態に移行する
  6. 被測定の抵抗が80Ωより小さい場合、ブザーを鳴らし(500Hz)、更に38Ω以下でブザーの音色を変える(1kHz)
    ※スリープ状態でもプローブに80オーム以下の被測定物が接続されるとウェイクします
  7. 電池の電圧が低下した場合はウェイク時に基板上の LED が1秒間隔で点滅する


2.回路設計
 下図が GreenPAK Designer で設計した回路です。被測定物が接続された状態の電圧をコンパレータ2個で判別しています。CMP2L は電源電圧監視用です。

GreenPAK Designer で設計した回路


 プリント基板作成のために書いた回路図が下図です。

プリント基板作成用回路図


3.プリント基板のパターン設計
 回路的にはシンプルなのでパターン設計は楽です。グランドベタ化前の両面のパターンが下図になります。

プリント基板の両面パターン(グランドベタ化前)


 下図はグランドベタ化後のトップ面のパターンです。SLG46826 を含め、主要な表面実装部品はトップ面に配置しました。

トップ面のパターン


 下図はボトム面のパターンです。ボタン電池ホルダと電源用コンデンサをボトム面に配置しています。中央にあるのは逆さになっていますがいつも使っているロゴです

ボトム面のパターン


 下図は3D表示したプリント基板のトップ面です。

3D表示(トップ面)


 ボトム面の3D表示が下図になります。

3D表示(ボトム面)


4.部品実装
 今回も JLCPCB さんに製造依頼しました。10cm x 10cm 以内のサイズのプリント基板を5枚製造するのが2ドルででき、送料(0.96ドル)とPayPal Fee(0.5ドル)の合計で3.46ドルでプリント基板が作れるので円安ではありますが、いい時代になったものです。CNCで切削するより奇麗なので最近はCNCが稼働していません。

 下図が部品実装後のトップ面です。

部品実装後のトップ面


 下図が部品実装後のボトム面です。上記の3D表示ではコネクタをトップ面に実装するようになっていましたが、電池ホルダが結構厚いのでコネクタ(丸ピンヘッダを流用)はボトム面に実装することにしました。左上のコンデンサと電池ホルダが少し緩衝したのでホルダを若干削りました。

部品実装後のボトム面


 部品実装後の動作チェックで次の問題が発生し、対処しました。前回の記事で追記したように後追いで電池の電圧低下を検出する機能を追加しましたが、ブレッドボードで動作確認していませんでした^^;

[問題]
 スリープ時の電流が 70uA 程度発生している(目標値は 0.3uA )
  • 原因1
     スリープ時に圧電素子に3V印加され電流が増大していた
    ⇒対処としてスリープ時は圧電素子に電圧が掛からないようにした。この対処でスリープ時の電流は 10uA 程度になった。

  • 原因2
     電池電圧低下警告LEDの点灯用デジタル出力ピンをスリープ時に Digital in の状態にしていたが入力が浮いている状態で電流が増加していた。
    ⇒対処としてスリープ時は Analog input の状態にすることでスリープ時の電流値が想定値である 0.3uA になった。


5.ケース設計
 ケースは本体部とキャップ部の2ピース構成とし、ネジなどは使わずはめ込み式にしました。圧電素子とテスタのプローブには半田付け作業時に発生する抵抗などのリードを半田付け後、ホットボンドで固め、基板上の丸ピンヘッダに接続するようにしました。プローブはタイラップで縛り、抜けを防止しています。

ケース設計時のCAD画面


 完成した状態の写真が下図になります。電池切れ警告の LED を基板上に実装した関係で透明の PETG フィラメントでケースを造形しました。透明フィラメントなのでロゴはほとんど見えませんね。


導通チェッカの完成写真


6.まとめ
 SLG46826 を単独で使用して何か有用なツールを作ろうということで導通チェッカを作成してみました。導通チェック時は今までテスタを使っていましたが、今回の物は抵抗値により2種類の音で反応する等、実用的なものができたのではないかと思います。
 また、従来マイコン関連のボードを開発する際、IC 数削減のため GAL を使う場合がありました(例えばこれ等)が GAL は消費電流が大きいことが難点でした。SLG46826 は低消費電流なので今後活用できるケースが多いのではないかと思います。



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]
nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

半田吸取り線カッターの製作 [3D_printer]

 2024/06/10 に HAKKO から WICKカッター FT-630 なるものが発売されました。業界初となる半田吸取り線の自動カッターです。

 今まで半田吸取り線をニッパーでカットしていましたが、自動カッターがあれば確かに作業効率が改善されそうです。しかし、価格が1万円以上なので「電動こて先クリーナーの製作」の時のように自作してみたいものです。
 HAKKO の製品では吸取り線をカット後に吸取り線を保持することで手で引っ張り出す手間も無くなると謳っていますが、吸取り線の引き出しは片手で十分出来るので保持機能に関してはあまりメリットを感じません。
 今回は電動での自動動作にはせずに極めて原始的な、しかしそれなりに作業効率を改善できるものにしたいと思います。題して半田吸取りたカッター(仮称)です。


1.構成部品
 使用するメインの部品はローソン100円ストアで163円で購入した爪切りです。桃色でコスメティック ツールと書かれていて同じツールでも別領域の物ですねw

未開封の100均の爪切り


 中身は下の写真のようにツートンカラーの爪切りです。

100均の爪切り



 爪切り単独では半田吸取り線カッターとしては使い辛いので爪切りの柄に付ける下図のアタッチメントを作りました。簡単な部品ですがパチっと固定できるようにするために何回か試行錯誤しました。

半田吸取り線カッター用の爪切りアタッチメントのCAD設計画面


 PETGフィラメントで出力したものが下の写真です。

半田吸取り線カッター用のアタッチメント



2.完成物
 下の写真は完成した半田吸取り線カッターです。笑っちゃうくらい単純な構造ですね。自動動作ではないので冒頭で紹介した HAKKO の商品よりは使い辛そうですが、慣れればほぼ同等の作業効率になるのではないかと期待しています。

半田吸取り線カッター(完成写真)


 X(旧Twitter)に投稿したメッセージに付けた動画を貼っておきます。



nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

半田ケースホルダの製作 [3D_printer]

 X(旧Twitter)のタイムラインで半田ごてを持つ手の人差し指に装着する半田を供給する治具を見かけました。半田の押し出し部分はFDM方式の3Dプリンタのエクストルーダーのようですね。



 ピストル型で半田供給機能ある半田ごても市販されていますが、確かに便利そうです。
 半田付けをしている際に腕の本数が足りなくなり、半田ケースをくわえることもたま~にありますw
 半田の押し出し機能までは無くてもいいのでもっと簡易的なものということで愛用の半田ケースを指でホールドできる治具を作ってみました。

半田ケースホルダのCAD設計画面


 半田ごてを持つ右手の人差し指に付けるより、左手の人差し指に装着する方が(ある程度の慣れは必要そうですが)便利そうです。シンプルな構造ではありますが利便性はそれなりにありそうです。

半田ケースホルダの使用例


nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー

GreenPAKで遊ぶ(その7)導通チェッカ [GreenPAK]

 SLG46826 単独で有用なツールを作るとしたら何がいいか考えてみると動作の柔軟性からしてマイコンにはかなわないと思ってしまいます。マイコンはソフト制御なので動作に柔軟性がありますが、ソフト作成の手間がかかる(でもソフト作りは楽しい)し、電池駆動の場合、スリープ時の省電力化にも気を使います。逆に SLG46826 であれば、回路作成は必要ですがソフトが不要であり、省電力化もあまり気を使わなくてもよさそうです。
 試しに簡単な回路でコンパレータ等の使用コンポーネントをパワーダウン状態にして消費電力を測定してみました。テスタの uA レンジで測定したので精度は高くないと思いますが待機時の消費電流は 0.2uA 程度でした。最初、簡単に 0.2uA とは中々凄いと思いましたが、I2C 接続を外したら 10uA 以上だったのであぁ I2C ピンから給電されていたのかと一旦落胆し、その後 I2C ピンをプルアップすることで 0.2uA に戻ったので電池駆動の導通チェッカを設計してみることにしました。


1.導通チェッカの仕様
 回路チェック用導通チェッカと言えば ChaN さんの回路内導通チェッカが有名ですが、これを参考にして次の仕様にしました。
  • 電源は3Vのボタン電池(CR2032)を使用する。
  • 被測定側への印加電圧は 0.5V 程度とする。
  • 60秒間程度操作が無い場合、自動的にスリープ状態に移行する。
  • スリープ状態時にプローブをショートすることでウェイク状態になる。
  • 80Ωより小さい場合、ブザーを鳴らし(500Hz)、更に40Ω以下でブザーの音色を変える(1kHz)。

 上記の感度はもう少し低い抵抗値にしたかったのですが、コンパレータのリファレンスの最小値が 32mV であることから上記の値にしました。コンパレータはリファレンスを 32mV のものと 64mV の二つ使用することにしました。
 また、ウェイクアップ用の専用のスイッチを設けずにウェイクアップするために、プローブへ給電する分圧抵抗のグランド側をデジタル出力で駆動し、スリープ時は入力に切り替えることで、プローブ短絡時の立下りエッジでウェイクアップするようにしました。これによりウェイクアップのスイッチを省略しています。


2.回路設計
 設計した回路を下図に示します。OSC0 で 1kHz と 500Hz のブザー用の矩形波を作り、LUT0 でコンパレータの出力により音を切り替えています。CNT1 を one shot モードで動かし、アクティブ(ウェイク状態)で二つのコンパレータと OSC0 をパワーオン状態にしています。

導通チェッカ回路


 外部回路である被測定部分では V3 の矩形波出力で 50 Ωの抵抗をオン/オフ制御することでチェック対象の抵抗値の変動をシミュレーションしています。FET を使いたかったのですが想定通り動かすには色々パラメータの設定が必要そうだったのでトランジスタに変更しました。

 下図がシミュレーション結果です。被測側が 50 Ωパラ接続の状態でブザー用の PIN 19 に 1KHz が出力され、50 Ω単独では 500Hz が出力されていて想定通りの動作になっています。

導通チェッカのシミュレーション結果


★追記 2024/06/24 {
 回路図を追記します。右端の部品はボタン電池(CR2032)のホルダです。

導通チェッカ回路図
}


3.まとめ
 SLG46826 を使ってスリープ機能付き、かつプローブ操作でウェイクアップする導通チェッカが割合簡単に設計できました。テスタで実測した結果、スリープ時の消費電流は 0.2uA 程度でした。今回の作業で感じた SLG46826 の長所と短所を列挙すると
  • 長所
    1. uA 以下の小電流での待機状態を容易に実現できる。
    2. ソフトの作成無しにある程度の動作を実現できる。
    3. 簡単な外部回路もシミュレートできるので動作確認が容易である。
  • 短所
    1. ソフトウェアのような柔軟な動作の作りこみが困難である。
    2. one shot をリトリガラブルにできない(未発見の実現方法がある?)。
    3. 再書き込み可能なチップの選択肢が少ない(今回の用途ならもっとピン数の少ないチップを使いたい)。

 上記の短所 ii のため、導通チェック中に one shot が終了した場合、一瞬ではありますがプローブに 3V が印加される可能性があります。これによりチェック対象の回路が破壊されることはまず無いとは思いますがこの点については未解決のままです。
 尚、コンパレータのリファレンス電圧を 32mV と 64mV に設定しているので計算上は下記のように 80 Ω以下でブザーが鳴り、38 Ω以下でブザー音が高くなるはずです。

 64mV:80 Ω = 0.064/((3-0.064)/3.3-0.064/0.68)
 32mV:38 Ω = 0.032/((3-0.032)/3.3-0.032/0.68)


★追記 2024/06/24
 SLG46826 の機能が余っているので、ボタン電池の電圧が 2.56V 以下になった際に2秒周期で点滅する電池切れ表示用LEDを追加しました。

電池切れLED付き導通チェッカの設計回路 Ver0.02


電池切れLED付き導通チェッカ回路図 Ver0.02


★追記 2024/06/25
 この導通チェッカを手配線で作成しようと思いましたが、ピッチが狭いのでプリント基板化することにしました。背面に背負っているのはボタン電池ホルダです。

電池切れLED付き導通チェッカ基板の3D表示 Ver0.02



[TOP] [ 前へ ] 連載記事一覧 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー
前の5件 | -