2020年9月24日木曜日

3Dプリンタ直した

■破損箇所■

スクリューの上を上下するアンチバックラッシュナットのネジ山が潰れました。グリースが粉状になってほとんど潤滑されていなかったようです。

■問い合わせ■

FacebookのLonger 3dグループに相談、Amazonでおすすめの部品を教えてもらったりしたのですがピッチが違って使えず。メーカーのサポートに連絡したところ、代替品を送ると連絡をもらいました。スクリューシャフトも傷ついているみたいなので一緒に送ってもらうことに。

■DHLですぐ届いたが……■

スクリューシャフトは別物で長さが合いませんでした。また、分解中にフォトインタラプタを壊してしまったので、そっちは有償で、正しいスクリューシャフトはもう一度無償で送ってもらうことにしました。


■もう一度DHL■

届いたのですが……残念ながらスクリューシャフトは前と同じでOrange 30には長すぎるっちゅーねん。てことで諦めます。幸い、古いスクリューの傷は下の方だけなので上下をひっくり返して使うことにしました。どうせそんなでかいのは出力しないしね。

■修理手順■

すいません、外す順番 / 組み立てる順番ちょっとうろ覚えです……。

  1. 液晶にしっかりカバーをする。
  2. ネジはほとんど同じですが違うのもあるので、どこから外したのかしっかりわかるように皿などを用意しておきます。タワーの根本6本、ビルドプレート4本、スライダー4本でアンチバックラッシュナットは交換できます。フォトインタラプタを交換するにはあと2本外します。なので皿は3つか4つ。
  3. ステッピングモーターのところのカプラーを締め付けているイモネジを緩める
  4. タワーの根本の6本のネジを外す。これ以降、タワーが不用意に倒れたり、タワー下にあるコネクタや配線を痛めないように注意します。
  5. タワーを上に上げるとフォトインタファプタのコネクタがあるので、向きをちゃんと記録しておいてから丁寧に外す。雑に扱って壊したバカは私です。タワーを横倒しにして作業できますが、液晶に傷などつけないように気をつけて。あと、古いグリースのカスがポロポロ落ちてくると思いますが、掃除機でキレイに吸い取ります。
  6. 配線やコネクタに負担がかからないように注意しながら、ビルドプレートをささえるネジのついた板とスライダーをつなぐ4本のネジを外す。ビルドプレートをささえる板が外れる、はず。
  7. アンチバックラッシュナットとスライダーをつないでいる4本のナットを外す。
  8. スクリューをディグリーザーやIPAでよく洗浄します。
  9. 必要があれば、フォトインタラプタを交換します。私は壊したから交換するので普通は不要です。ふははははははははははははははははははは。
  10. アンチバックラッシュナットを3つに分割します。ネジ穴のついているナットをビルドプレート部にネジ止めします。この時スプリングがついたままだとネジが斜めになるので注意。
  11. ビルドプレートにネジ止めされたアンチバックラッシュナットにスクリューをねじ込みます。バネを通し、バネを思いっきり圧縮してアンチバックラッシュナットのもう一つのナットとのかみ合わせを合わせた状態でスクリューをねじ込んで行きます。うまくいくと、両ナットの間に1mmぐらいの隙間が空いた状態でスクリューが通ります。結構回転が渋いのですが、グリースをつければ良くなります。
  12. グリグリ回してアンチバックラッシュナットの下に3-5cmぐらいスクリューが出るようにします。
  13. フォトインタラプタのコネクタを元通り接続します。
  14. スクリューの下部をステッピングモーターのカプラーに差し込みます。イモネジを十分緩めてしっかり奥まで差し込みましょう。
  15. スライダーとビルドプレート部をネジ止めします。スライダーと高さが合わない時にはスクリューを回します。この時、カプラーからスクリューが浮き上がらないように注意します。
  16. タワーの根本の6本のネジを締めます。
  17. カプラーのイモネジをしっかり止めます。
  18. スクリューにグリースを丁寧に塗ります。多すぎてもホコリを吸ってヤスリ状になるだけなので、薄く均一に塗るのがコツです。だそうです。私はできませんが。
  19. 動作テストします。
いやはや……。


PCBWay使ってみた

※この度、PCBWayさんからの無償オファーをいただき、試用させていただきました。利用者としての公平な視点で記述したつもりですが、レビューの前提としてご承知おきください※

■発注感■

中国のPCB屋さん、どこも発注入力ページのデザインがかなり似通っていて、オープンソースがあるのか同じ業者さんがWebつくっているのだろうか。

ということで、他社とあまり変わりなくサクサク入力設定できます。丁度作ろうと思っていた45x40mmの基板があったので、両面、1.6mm、レジスト黒、鉛フリー仕上げ、あとはデフォルトで指定。$18。発注確定9月15日 14:12、完了予定は9月19日。レジスト緑で1.6mm厚だとキレイでない業者でもあんまり外れないので、今度はあえて黒にしてみました。黒はシルクがかすれるとすぐ目立ちます。

なお日本の住所とフォーマットが違うため、郵便番号入力から出てきた市町村名に都道府県名を付記する必要がありました。レポート入れたけど、改善されるかな。

便はDHLを指定しました。

個人的にはOCS/ANA好きなんですが、知っている限りElecrowとFusionしか扱っていないのが残念。

■発送■

そろそろ進捗を確認しようと思っていたらその前にDHLから「荷物届くぞ」の連絡。DHL引き取りが9月17日 23:00。早い。

安心のDHL。と思ったら、配達予定9月24日になっておる……せっかくの連休のお楽しみがDHLによってツブされてしまう……orz 

まぁ届くのは連休明けかな、と思っていたけどさー……。

■受領・結果■

ってことで、9月24日、DHLで届きました。梱包は段ボール箱に入ってDHLのビニール袋。DHLなので中身が潰れている、なんてこともなく。


上の写真は表面の拡大。

パッと見てシルクはズレやカスレなし。非常にクリア。ただし50um程度のズレがある。大きさ指定忘れてた24mil大の文字(「J3」ってやつ)はちょっと潰れ気味。

レジストについてはドリル穴との相対位置誤差はうちのツールでは誤差の範囲で測れません。塗りムラも特になくきれい。

断端は国産並みにツルツルです。こんなにツルツルなのは中華では初めてかも。

ハンダメッキは国産に比べるとちょっとムラがあるけども実用上問題なし。

お試しの機会をありがとうがございました。

2020年9月11日金曜日

老眼への完璧な対策

 

はんだ付け作業はルーペ必須です。

※高齢者の感想です♡

ただ、モニター画面上の回路図を確認しながらはんだ付けをする際には、ルーペを上げたり下げたり上げたり下げたりを無限に繰り返すことになりうざいです。

ってことで、自動化しました。もうオートフォーカス老眼鏡も時代遅れさ(何を根拠に)。



■仕組み■

市販の安い中華ヘッドルーペを改造します。

Nikayoni Stores ヘッドルーペ 拡大鏡 レンズ メガネ タイプ 2灯式 LED ライト 倍率 1.2倍 1.8倍 2.5倍 3.5倍

レンズホルダーとフレームを3Dプリンタで作成し、ホルダーとフレームの間を2個のサーボモーターで駆動します。バイザーの上に加速度センサー(ADXL345)とマイコン(Seeduino XIAO)を搭載し、はんだ付けするのにいい感じに頭を前傾させたらサーボを動かしてレンズを目の前におろします。

このアイディアそのものは最初にヘッドルーペを買った日に思いついたんですが、サーボモーターを固定するいい感じの方法が見つからず、ずっと放置して忘れてました。さらに、3Dプリンタを買って10ヶ月ほど経過したところで、このプロジェクトを思い出し、3Dプリンタの故障や不慣れなFDM機などにも翻弄されながら、ついに日の目をみた次第です。

ご笑覧ください ^ ^

■レンズホルダーとフレーム■

Fusion360で設計し、Snapmaker 2.0のFDMプリンタで出力しました。FDM初めてなので、なかなかキレイにだせず、10回目の試作で何とかきちんと収まりました。

ここからダウンロードできます(github.com/TareObjects/3D-Datas)。



■回路■

XIAOからサーボモーターSG-90を直接駆動しています。よくある中華基板のADXL345も直結です。秋月の45x45mm基板にのせました。サーボとの配線、手持ちのMolex 5051が丁度いい感じで使えたので、使ってます。

XIAOADXL345Servo RServo L
5V5V5V
GNDGNDGNDGND
8SIGNAL
9SIGNAL
3V3VCC
4SDA
5SCL
3V3!CS

あれ罫線が足りない。まぁいいや。



■ソフト■

もうちょっといじりたいけど……とりあえず動くやつ。角度にヒステリシスつけないといけないし、中断モードも必要ですね。

#include <Servo.h>
Servo rServo;
Servo lServo;
//
// ADXL345
//
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);
//
// Setup
//
void setup() {
Serial.begin(115200);
rServo.attach(8);
lServo.attach(9);
if (!accel.begin()) {
Serial.println("Ooops, no ADXL345 detected ... Check your wiring!");
while (1);
}
accel.setRange(ADXL345_RANGE_2_G);
}
const int speed = 15;
const int rOffset = 80;
const int lOffset = 100;
enum {ModeInit = 1, ModeFaceUp, ModeFaceDown};
int mode = ModeInit;
int getCurrentMode() {
sensors_event_t event;
accel.getEvent(&event);
int currentMode;
Serial.print(event.acceleration.y);
Serial.print("--");
if (event.acceleration.y < -3.0) {
currentMode = ModeFaceDown;
Serial.println("Face Down");
} else {
currentMode = ModeFaceUp;
Serial.println("Face Up");
}
return currentMode;
}
void loop() {
int currentMode = getCurrentMode();
if (mode != currentMode) {
delay(100);
currentMode = getCurrentMode();
if (mode != currentMode) {
mode = currentMode;
if (mode == ModeFaceUp) {
faceUp();
} else {
faceDown();
}
}
}
delay(100);
}
void faceUp() {
for (int pos = 0; pos <= 90; pos++) {
rServo.write(pos + rOffset);
lServo.write(lOffset - pos);
delay(speed);
}
}
void faceDown() {
for (int pos = 90; pos > 0; pos--) {
rServo.write(pos + rOffset);
lServo.write(lOffset - pos);
delay(speed);
}
}

2020年9月3日木曜日

補聴器乾燥機の観察

補聴器乾燥機について電気式と乾燥剤式を比較してみました。

この実験は厳密な比較ではありません。ごく簡易的な条件で行いました。何しろ蓋の隙間から電線引っ張り出しているので、当然通常の使用状態とは異なります。あらかじめご了承ください。

■電気式■

シーメンス SIEMENS 補聴器電気乾燥機 パーフェクトドライ クイックエア(4,698円)は電源が必要ですが乾燥剤不要の乾燥機です。最近購入しました。使ってみて思ったのは乾燥機から取り出した時に補聴器が「カサッ」とした手触りなんですよね。相当強力な除湿効果があるのでは、と期待して試してみました。補聴器とセンサーを入れてスイッチをonにします。一定時間(約60分)でスイッチが切れて、徐々に室内と同じ環境に戻ります。

スイッチONから20分ほどで湿度28%まで低下、温度は45分後に45度まで上昇。

乾燥剤式よりも効果があるように感じられるのは、湿度だけでなく温度も上がるからだと思います。



■Panasonic補聴器用乾燥剤■

WIDEXの乾燥ケースを数日開けっ放しにして部屋と同じ湿度にし新品の乾燥剤に補聴器用乾燥剤・1個入りパナソニック製WH-PZ1805Jを入れました。4時間30分ほどで27.8%で落ち着きました。


その後、帰宅して汗びっしょりの補聴器を入れてみたのが11時。15分で28%に到達する電気式ほどではないですが、26分で30%を切っています。


■まとめ■

いかがでしt……じゃなくて。

短時間でさっさと乾かす電気式とじっくり乾燥させる乾燥剤式。電気式は乾燥剤10年分の値段ですが、私のように1日に何度も補聴器を出し入れする使い方には電気式の方が向いているように思います。

■電子工作アカなので■

計測にはM5 ATOM lite + CJMCU-8128を使用しました。CJMCU-8128はCCS-811、BMP280、SI702xを搭載していて、温度(3つ)、湿度、気圧、CO2、TVOC(空気質?)を計測できます。

今回の計測には関係ないんですが……CCS-811ってどのぐらいアテになるんでしょうね。CO2とTVOCの値がほぼ連動してますし、数日使っていると窓をあけてもCO2濃度1200ppmなんて値が出て地球が終わりそうになるんです。


#include "Adafruit_CCS811.h"
#include "Adafruit_Si7021.h"
#include "Adafruit_BMP280.h"
Adafruit_CCS811 ccs;
Adafruit_BMP280 bmp280;
Adafruit_Si7021 SI702x = Adafruit_Si7021();
//
// Wifi, ambient
//
#include <WiFi.h>
#include "Ambient.h"
WiFiClient client;
Ambient ambient;
const char* ssid = "<your wifi ssid>";
const char* password = "<your wifi password>";
unsigned int channelId = <AmbientのチャネルID>;
const char* writeKey = "<Abmientのライトキー>";
//
// Setup
//
void setup() {
Serial.begin(115200);
Wire.begin(32, 26);
WiFi.begin(ssid, password); // Wi-Fi APに接続
Serial.println("CCS811 test");
if (!ccs.begin(0x5A)) {
Serial.println("Failed to start sensor! Please check your wiring.");
while (1);
}
//calibrate temperature sensor
while (!ccs.available());
float temp = ccs.calculateTemperature();
ccs.setTempOffset(temp - 25.0);
Serial.println("BMP280 test"); /* --- SETUP BMP on 0x76 ------ */
if (!bmp280.begin(0x76)) {
Serial.println("Could not find a valid BMP280 sensor, check wiring!");
while (true);
}
Serial.println("Si7021 test!"); /* ---- SETUP SI702x ----- */
if (!SI702x.begin()) {
Serial.println("Did not find Si702x sensor!");
while (true);
}
while (WiFi.status() != WL_CONNECTED) { // Wi-Fi AP接続待ち
delay(100);
Serial.print(".");
}
ambient.begin(channelId, writeKey, &client); // チャネルIDとライトキーを指定してAmbientの初期化
}
float sumTemp = 0;
float sumHumd = 0;
float sumPres = 0;
float sumCo2 = 0;
float sumTVOC = 0;
int cnt811 = 0;
int sumCount = 0;
float period = 1000 * 60;
float prevPeriod = -1;
//
// Loop
//
void loop() {
if (ccs.available()) {
float temp = ccs.calculateTemperature();
if (!ccs.readData()) {
float co2 = ccs.geteCO2();
float tvoc = ccs.getTVOC();
Serial.print("CO2: ");
Serial.print(co2);
Serial.print("ppm, TVOC: ");
Serial.print(tvoc);
Serial.print("ppb Temp:");
Serial.print(temp);
Serial.print(" ");
sumCo2 += co2;
sumTVOC += tvoc;
cnt811 ++;
}
else {
Serial.println("ERROR CCS811");
}
}
float bmpTemp, bmpPressure;
bmpTemp = bmp280.readTemperature();
Serial.print("BMP280 => Temperature = ");
Serial.print(bmpTemp);
Serial.print(" °C, ");
bmpPressure = bmp280.readPressure() / 100;
Serial.print("Pressure = ");
Serial.print(bmpPressure);
Serial.print(" Pa, ");
sumTemp += bmpTemp;
sumPres += bmpPressure;
float siTemp = SI702x.readTemperature();
float siHumidity = SI702x.readHumidity();
Serial.print(" SI702x => Temperature = ");
Serial.print(siTemp, 2);
Serial.print(" °C, ");
Serial.print("Humidity = ");
Serial.println(siHumidity, 2);
sumHumd += siHumidity;
sumCount ++;
int now = millis() / period;
if (now != prevPeriod) {
if (sumCount > 0) {
ambient.set(1, sumTemp / (float)sumCount);
ambient.set(2, sumHumd / (float)sumCount);
ambient.set(3, sumPres / (float)sumCount);
ambient.set(4, sumCo2 / (float)cnt811);
ambient.set(5, sumTVOC / (float)cnt811);
Serial.println("sending");
ambient.send();
}
sumTemp = 0;
sumHumd = 0;
sumPres = 0;
sumCo2 = 0;
sumTVOC = 0;
sumCount = 0;
cnt811 = 0;
prevPeriod = now;
}
}