JUGEMテーマ:電子工作

 

ATtiny85でクリスマスツリーピカピカ点滅するやつ。

 

12月ぐらいになると、クリスマスツリーにひっかけて電球ピカピカさせるやつが店頭に並ぶ。


2年ぐらい前に買ってこれって点滅した方が良いのにーって思っていたんです。

たしか、500円ぐらいで買った気がするんだけど、
 最近は百均とかでも見かける気がする。

 自分のは星形のやつで、ほかにもいくつかバリエーションあったと思います。

 
 
本日、待望の点滅バージョンに改造されました。

 

■元の回路

 


■改造後の回路

 

 

■ATtiny85のピン配置


■ATtiny85に仕込んだプログラム

 

可変抵抗くっ付けて点滅の時間変えたりとか、PWMでじんわり光らせたりとかも出来るんですけどー
応用バージョンはまた来年かなー

とりあえず、可変抵抗で調整した後の数字を直接プログラムに仕込んであります。

 

ATtiny85への書き込みは

 こちら

  https://ameblo.jp/fc2miha/entry-12833772915.html

 を参考にしてください。

 

void setup() {
  pinMode(4, OUTPUT);

  Serial.begin(9600);
  Serial.println("ver1.2");
  Serial.println("start:");

}

int nCount=0;
void loop() {
  char szStr[30];
  
  sprintf(szStr, "%d¥n", nCount);
  Serial.print(szStr);
  nCount++;
  

//  int v1 = analogRead(A0);
//  sprintf(szStr, "A0 = %d¥n", v1);
//  Serial.print(szStr);
//
//  int v2 = analogRead(A1);
//  sprintf(szStr, "A1 = %d¥n", v2);
//  Serial.print(szStr);

  int v1 =  16;
  int v2 = 320;

  digitalWrite(4, HIGH);
  delay(v1*3+10);
  
  digitalWrite(4, LOW);
  delay(v2*3+10);
}


JUGEMテーマ:電子工作


うちのテスターなんですが、最近、通電チェッカーがメインのお仕事になっていたりする。
その次が抵抗測定で、次が電圧とか、電流とか、です。
テスターって重さの関係なのか知らないですが、ボタン電池を使っていて、
とくにうちのはLR1130っていう電池で、
これを4個も使うので、意外と電池食うなーと思っていたこともあり。
たぶん。通電チェックの場合はピーってなる仕様になっていることもあり。
電池食うよなーみたいな。
 
で、通電チェッカー専用で作ってみました。
 
単3型のEneloop2本仕様で電池長持ちの充電可能がコンセプトです。
 
■回路

 
 
回路に影響を与えないように定電流ダイオードを使ってみました。
 
箱に入れてみました

 
中身
 

 
 
■評価
抵抗を測定してみた。
 10Ω 通電 ピー
 24.8Ω 通電 ピーbibibibi-ri-少し弱くて音が変
 28.1Ω 通電無し
 まー28Ωで通電無しなら合格かなー
 
端子間の電流と電圧を測定してみた。
 8.3mA
 2.6V
ちょっと、高めだけど。8mAぐらいなら、何かを壊す心配は無いだろう。
これで実用的なのかわかんないけど、当分使ってみる。
 


JUGEMテーマ:電子工作
 

ESP32 PWM出力の電圧測定

 

Pin21には10KΩの抵抗を接続してGNDと接続

 

from machine import Pin, PWM
 
pwm0 = PWM(Pin(21))
pwm0.freq(1000)
pwm0.duty(0)    #0V
---------------------------
pwm0.duty(100)    #0.32V
pwm0.duty(200)    #0.64V
pwm0.duty(300)    #0.96V 
---------------------------
pwm0.duty(400)    #1.28V
pwm0.duty(500)    #1.59V
pwm0.duty(600)    #1.91V
---------------------------
pwm0.duty(700)    #2.23V
pwm0.duty(800)    #2.55V
pwm0.duty(900)    #2.87
---------------------------
pwm0.duty(1000)    #3.19
pwm0.duty(1023)    #3.26

 


JUGEMテーマ:電子工作

AQM1602Y-NLW-FBWをESP32のマイクロパイソンから使う

 

小型のキャラクタディスプレーAQM1602シリーズ
I2Cで使えるため非常に便利です。

 

ずっと前やった記事はArduinoで制御する方法でしたが
 https://ameblo.jp/fc2miha/entry-12833772879.html

今回ESP32からMicropythonで制御したので、
記録しておきます。

 

参考
 https://jhalfmoon.com/dbc/2021/05/17/micropython%E7%9A%84%E5%8D%88%E7%9D%A122-%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4pico%E3%80%81aqm1602-lcd%E3%83%91%E3%83%8D%E3%83%AB%E6%8E%A5%E7%B6%9A/


 Raspberry Pi Picoの記述ですが、ESP32のMicropythonでそのままで行けました。

で、それだけでは芸が無いので
 ずっと前にやったオリジナルキャラを追加して、表示してみましたので。参考になる場合はどうぞ。
 
■回路

 

 

■ピン配置

 

■プログラム

上の参考にしたプログラムにオリジナルキャラの作成とカーソル位置の指定、カーソル位置からの文字表示、画面クリアなど追加しています。

 

#
#AQM1602Y-NLW-FBW
#16桁2行 キャラクタディスプレー制御
# 独自キャラクタ追加
#
#接続
# ESP32        AQM
#  22   -----  SCL
#  21   ----   SDA
#


import time
from machine import Pin, I2C
import sys

time.sleep(3.5)
print("AQM1602 Build0.1")

i2c=I2C(0, scl=Pin(22), sda=Pin(21), freq=400000)

display_address = 0x3E
display_data = 0x40
diaplsy_command = 0x00

def writeData(dat):
    i2c.writeto_mem(display_address, display_data, bytes([dat & 0xFF]), addrsize=8)
    time.sleep_ms(1)

def writeCommand(com):
    i2c.writeto_mem(display_address, diaplsy_command, bytes([com & 0xFF]), addrsize=8)
    time.sleep_ms(1)

def initDisplay():
    time.sleep_ms(100)
    writeCommand(0x38)    #FunctionSet
    time.sleep_ms(20)
    writeCommand(0x39)    #FunctionSet 拡張モードへ移行
    time.sleep_ms(20)
    writeCommand(0x14)    #
    time.sleep_ms(20)
    writeCommand(0x73)    #コントラスト下4ビット
    time.sleep_ms(20)
    writeCommand(0x56)    #3.3Vで動かす場合は0x56みたい。
    time.sleep_ms(20)
    writeCommand(0x6C)
    time.sleep_ms(20)
    writeCommand(0x38)    #FunctionSet 拡張モード終了
    time.sleep_ms(20)
    writeCommand(0x01)    #ClearDisplay
    time.sleep_ms(20)
    writeCommand(0x0C)    #DisplayON CursorOFF BlinkOFF
    time.sleep_ms(20)
#参考情報
# flags for display on/off control
# LCD_DISPLAYON 0x04
# LCD_DISPLAYOFF 0x00
# LCD_CURSORON 0x02
# LCD_CURSOROFF 0x00
# LCD_BLINKON 0x01
# LCD_BLINKOFF 0x00


#行出力
def writeLine(nL, lin):
    buf = bytearray(lin)
    if len(buf) <= 0:
        return False
    if len(buf) > 16:
        buf = buf[0, 16]
    if nL == 0:
        writeCommand(0x80)
    else:
        writeCommand(0xC0)
    for idx in range(0, len(buf)):
        writeData(buf[idx])

#カーソル位置に文字列出力
def writeString(lin):
    buf = bytearray(lin)
    if len(buf) <= 0:
        return False
    if len(buf) > 16:
        buf = buf[0, 16]
    for idx in range(0, len(buf)):
        writeData(buf[idx])

#画面消去
def clearDisplay() :
  writeCommand(0x01)
  time.sleep_ms(2)

#オリジナルキャラ作成
def createChar(location, charmap) :
  location = location & 0x07    # 8個のオリジナルキャラが作れる
  
  writeCommand(0x40 | (location << 3));
  for  i in range(0, 8) :
    writeData(charmap[i]);

#カーソル位置指定
def setCursorAQM1602(col, row) :
  if row == 0 :
    offset = 0x00
  else :
    offset = 0x40
  
  writeCommand(0x80 | (col + offset))
  time.sleep_ms(2)

#
#
#

initDisplay()        #初期化

#文字出力
writeLine(0, "Hello, コンバンワ!")
writeLine(1, "1234567890ABCDEF")
time.sleep(3)

#クリア
clearDisplay()

#年
b = bytearray(8)
b[0] = 0b10000
b[1] = 0b11111
b[2] = 0b00100
b[3] = 0b11111
b[4] = 0b10100
b[5] = 0b11111
b[6] = 0b00100
b[7] = 0b00000
createChar(0, b)    #キャラクタ追加

#月
b[0] = 0b01111
b[1] = 0b01001
b[2] = 0b01111
b[3] = 0b01001
b[4] = 0b01111
b[5] = 0b01001
b[6] = 0b10001
b[7] = 0b00000
createChar(1, b)    #キャラクタ追加

#日
b[0] = 0b11111
b[1] = 0b10001
b[2] = 0b10001
b[3] = 0b11111
b[4] = 0b10001
b[5] = 0b10001
b[6] = 0b11111
b[7] = 0b00000
createChar(2, b)    #キャラクタ追加

#
nen=bytearray(1)
nen[0]=0
getu=bytearray(1)
getu[0]=1
hi=bytearray(1)
hi[0]=2
setCursorAQM1602(0, 0)
writeString("2022")
writeString(nen)
writeString("11")
writeString(getu)
writeString("13")
writeString(hi)

setCursorAQM1602(6, 1)    #カーソル位置変更 x=6 y=1
writeString("XYZ")

setCursorAQM1602(12, 0)    #カーソル位置変更 x=12 y=0
kigou=bytearray(2)
kigou[0]=0xfb
kigou[1]=0xfc
writeString(kigou)

time.sleep(3)

#クリア
clearDisplay()


#
c = bytearray(1)
count = 0
while True:
  x = count % 16
  y = int(count / 16) % 2
  setCursorAQM1602(x, y)
  c[0]=count
  writeString(c)
  count = count + 1
  if count > 255  :
    count = 0
    clearDisplay()
  time.sleep_ms(100)
 

■コード表

 


JUGEMテーマ:電子工作


ゲルマラジオの試作
 
アンプとか
https://akizukidenshi.com/catalog/g/gK-02419/
ラジオとか

作ってきましたが、さらに、、
本日の前の記事でオーディオミキサーの実験をしておりました、

 
次はAMラジオでもと思い、AMラジオと言えば懐かしいゲルマラジオ
そういえば、ゲルマダイオードって前になんかセットで20本ぐらい買った記憶があり、
部品庫を探した所、
ありました、それも大量に。
で、ラジオと言えば、バリコン。と思い。
昔の白い四角いやつを思い浮かべながら秋月のページを調べましたが、ないっすね。
代わりに見つかったのが
セラミックトリマコンデンサーとかでした。
 
9pfから60pfまで可変できるって書いてるし。これで良いかなと注文。
で、せっかちなので、届くのを待てずに。手持ちの部品で作り始めてみた。
で、可変のコンデンサーはないけど、
適当な手持ちのコイルと適当なコンデンサーで
AMの周波数に合わせて
コンデンサー15pF
コイル1mH
で計算すると1300KHzぐらいの周波数になるはずなのでこの組み合わせで作ってみた。
 
そうしたら、どうでしょう。891KHzのNHK1が入ってくるんです。
それも、ノイズもなくきれいに聞こえます。
部品点数を考えると感動的なぐらいです。
ちなみに、クリスタルイヤホンとか、セラミックイヤホンとか教科書に書いてありますが、
無視して下の回路図のAMPの所に普通のヘッドホンでも大丈夫です。
 
周波数のずれはコイルとかコンデンサの誤差ですかね。
ま、コイルは測定したとき0.7mHだったし、誤差は普通にあるので、
正確にチャンネル合わせるのはバリコンの代わりの
 セラミックトリマコンデンサー(P-04566)
 ・容量可変範囲:9.8~60pF
が来てからですね。
そんで、回路図です。
 

 
何といっても、ANTから入ってきた信号のみの電力ででラジオが聞けるというのに感動です。
電池は不要です。
 
実際に組んで、Point1の波形
 

負荷を抵抗にして、Point2の波形
 

コンデンサーに付け替えて、Point3の波形
 

いや、Point2はうちの計測機器であれ?って感じですが、
 
ほぼ教科書通りに波形が出てて感動です。
災害時用に一つ持ってた方が安心と思いますので、箱に組んでいこうと思います。
 
 

 
回路

実際に箱に組んでみたら、ANTにGNDを繋ぐとでのあ入らなかったので、注意。
 
あと、バリコン amazonが早かったのでuxcell コンデンサー トリム ラジオ用 調整 3個入り 224pFリニアPCB

 なるものを届けてもらいました。

 

 

 

これ、amazonにもメーカーにも何処にも解説が無く、ピン配置を手探りで探すことになりましたのでそれの記録です。



赤で印付けたところが、224pF出るみたいです。
他にも1ヶ所大丈夫な所あったんですが、印が3か所になるとより判らなくなるので付けておりません。
 

オーディオミキサーの試作
 
アンプとか
 https://akizukidenshi.com/catalog/g/gK-10240/
ラジオとか
 https://ameblo.jp/fc2miha/entry-12833773073.html

 
作って実際に使っておりますが、上のラジオの出力レベルとパソコンの出力レベルが合わなくて、
ラジオに切り替えるたびに音量調整がめんどくさかったり。
このラジオはソフトで音量調整するんだけど、最小にしてももう少し下げたかったり、
3.5のジャックの抜き差しがめんどくさかったり。いろいろ、単発で思い付きで進めてきたせいで
めんどくさい。というわけで、
目標
 1.ピンを抜き差ししなくてもいい。(これで夜中にラジオに切り替えた時にブズッ、ブーンという音に悩まされなくて済む)
 


 2.いちいちボリュームを下げなくてもいい。


を目指してオーディオミキサーを作ってみることにする。
あっちこっちに回路図がころがっているけど、簡単にするため、アンプは内蔵しなくて、
可変抵抗だけで構成してみた。ま、実験実験。
2022.11.12コンデンサー追加。
 
回路図
 

 
 
とりあえず、こんなんでも、うまく聞こえるし大丈夫みたいです。
写真は入力は2系統で試作したもの。上の回路図は入力3系統です。
 

 
回路はこんなのでも良いみたいなので、
早速パーツを注文した。
セレクターとしても使いたいので、オルタネイトの2回路のプッシュスイッチも付けておきたい。
 
JUGEMテーマ:電子工作
 

 

android studio テキストの色とか、画像の指定、背景画像に関して

 

当方androidさんとは昔から縁があり、昔々、androidのnexus7が出たぐらいの時に
NWプリンタに印刷したりとか、客先で使っていたESC-P対応プリンタに
androidから印刷する部分のプログラムとか作ってみたりとか、
しておりましたが、しばらく時が経つこと10年ぐらいかなさっぱりそういう仕事とは
おさらばだと思っていたところにandroidのお仕事が舞い込み。

 

やれると思い込んで、それなりに玉砕覚悟で突っ込んでみたところ、
環境がeclipseからandroidstudioに代わり、
これは使いやすくなっているので問題無いが、老眼にムチ打ち本で勉強してみたり、
その本が古くて役に立たなかったり、わけわかんねー

しかし、それなりに泣きつつ、判ったに変わりつつある今日この頃です。

今日ハマッテイタのは、view沼です。ま、良いんですけど。

 

本日学んだことをまとめていくページです。
あまり、ほかの人には参考にならないかもしれないですね。

まずはいつものように
File→New→NewProjectでBasicActivityを選択する、
で作っていき。

 

リソースをいくつか追加していきます。

android studioの画面です。

 

黄色の所の画像ファイルを追加して。


layoutのfragment_firstを変更していきます。

 

 

■動作確認

 最初の画面です。

 

 ボタンを押した画面です


 
 ボタンをもう一度押した画面です


 
 あとはボタンを押すたびに切り替わります。


■ボタンを押した所のソースプログラム

        binding.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(bFlag==false) {
                    binding.imageView.setImageResource(R.drawable.img4);
                    bFlag = true;
                    //binding.imageView.setVisibility(View.VISIBLE);
                    binding.textView.setTextColor(Color.rgb(0, 100, 0)); //0x006400);
                    binding.textView.setText("123");
                    binding.textView.setTextSize(30);
                    getView().setBackgroundResource(R.drawable.background);
                }
                else{
                    binding.imageView.setImageResource(R.drawable.img3);
                    bFlag = false;
                    //binding.imageView.setVisibility(View.INVISIBLE);
                    binding.textView.setTextColor(Color.rgb(0xff, 0x7f, 0x50));  //xff7f50);
                    binding.textView.setText("456");
                    binding.textView.setTextSize(45);
                    binding.textView.setGravity(Gravity.CENTER);
                    getView().setBackgroundResource(R.drawable.backglound2);
                }
            }
        });

 

■要点解説

 

□用意したImageViewに画像を表示

 

 binding.imageView.setImageResource(R.drawable.img4);

 

□テキストの色、大きさ、文字を指定、そしてセンタリング

 

 binding.textView.setTextColor(Color.rgb(0xff, 0x7f, 0x50));  //xff7f50);
 binding.textView.setTextSize(45);
 binding.textView.setText("456");
 binding.textView.setGravity(Gravity.CENTER);

 

□背景画像を指定

 

 getView().setBackgroundResource(R.drawable.backglound2);

 

□他のViewの例

 ListView listView = getListView();

 listView.setBackgroundResource(background);

 

※Viewの種類が多少違ってもgetすれば行けるっぽい

androidStudioに入れるための透過画像ファイルpngの作成
 
透過pngを使う方法と言い、Windows標準の方法をいろいろ紹介しているみたいですが、
gimpを使うと結構簡単だったのでメモです。
 
drawable-xxhdpiに格納されているのが縦横144ドットなので、
横144ドットのファイルを用意。
 

 
これをgimpで開く。
 
 
■αチャンネルの準備
メニューのレイヤー→透明部分→αチャンネルの追加
 
 
 
■ファジー選択
 

この矢印のところ、を選択して月の背景を選択して
 

こうなったら
delを押す。

 
その状態でファイルを名前を付けて保存
これで、表示してみると背景が透けています。
 

 

AndroidStudio画像表示記事
 
はまりましたぜ。今日もAndroid沼にハマりました。
いやー、だいぶ溺れましたが、何とか沼から生還です。
実はこれを味わいたくてやってる気もしますが。
聞いてください。
 
AndroidStudioについている。基本機能のlayoutを編集するやつで、
ImageViewをドロップして画面に画像を表示する機能あるじゃないですか?
 
で、単純にその流れで、自分の画像をresのdrawbleに入れておけば、
普通に表示されるじゃないですか?
それがですが、Notfoundって言われて実行が止まるんです。
うぎゃー!!
 
 
これが、原因がわからず、本日これで一日沼にハマっていました。
結論から言うと、
画像をresのdrawbleに入れるとき。
 

このフォルダーの後ろの所にv24ってくっついていて、
v24がくっついていると、実行時にエラーになることが判明しました。
これを調べると、うちの開発用のandroidちゃんが
APIレベル低いため、レベルv24の表示で探しに行っていないから
って事みたいだ。
って事でして、判ってみるといとも簡単?に画像が表示できました。
最初からデフォルトで表示する場合は上記のlayoutの機能で普通にresを指定しておけば出るし。
ボタンを押して画像を切り替える場合は以下の感じで
        binding.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if(bFlag==false) {
                    binding.imageView.setImageResource(R.drawable.img4);
                    bFlag = true;
                }
                else{
                    binding.imageView.setImageResource(R.drawable.img3);
                    bFlag = false;
                }
            }
        });
リソースのIDを指定すれば良い。
 
■表示非表示

binding.button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        if(bFlag==false) {
            bFlag = true;
            binding.imageView.setVisibility(View.VISIBLE);
        }
        else{
            bFlag = false;
            binding.imageView.setVisibility(View.INVISIBLE);
        }
    }
});


 
■テキスト属性

binding.textView.setTextColor(Color.rgb(255, 127, 80));  // 文字色
binding.textView.setText("456"); // 文字
binding.textView.setTextSize(45); // 文字大きさ
binding.textView.setGravity(Gravity.CENTER); // センタリング


layoutのTextViewの設定項目でも上記と同じような名前で登場する
変化のないものはそちらで指定してもOK
 
 
 
 
 

androidStudio音を出す。
 
音を出すしたい場合。2種類あって
いや、本当は3種類あるみたいだけど。
 
自分の本に書いてあるのは2種類だったので、こちらで。
 SoundPoolとMediaPlayerがあるんだけど。
 
SoundPoolが連続再生するとそのうち再生されなくなり。
調子悪し。・・・・いろいろ調整したけど無理っぽい。
 
MediaPlayerはうまく動くみたいなのでこれで行く。
といっても、停止→再生を繰り返すと、ぷちっと音が入るのが気に入らないが、
まずはこれで実装しましょう。
 
仕様上は停止しないので問題ないので、連続でイベント発生しない場合は、ほぼ問題ないと思われ。
いつものようにプロジェクト作成はBasicActivityで作っていきました。
 
まず、音源をresに入れていきます。
左上のProjectの所、普段Androidになっている選択をProjectに変更して、
app→src→main→resの配下にrawディレクトリを作って
 音源ファイルをコピーしてください。
今回その名前をbgm.mp3とse.wavにしています。
 

 
 
そして、音源の再生ボタンと停止ボタンを作っていってください。
普通はFirstFragmentの中でボタンを実装しますので、
その手順で行きます。
いつものようにGUIでresのflagment_first修正して
再生用ボタンと停止用ボタンを作ります。
名前をtest_buttonとtest_button2としています。
 
FirstFragmentクラスに以下の様にMediaPlayerの変数を追加します。
    private MediaPlayer mediaPlayer=null;
そしてFirstFlagmentのonViewCreatedの中で以下を追加してボタンの応答を受けられるようにします。
 
binding.testButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Log.d("TAG", "onClick: testButton start bgm");
        //stop
        if(mediaPlayer!=null) {
            mediaPlayer.pause();
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
        //start
        MainActivity activity = (MainActivity) getActivity();
        //mediaPlayer = MediaPlayer.create(activity, R.raw.bgm);
        mediaPlayer = MediaPlayer.create(activity, R.raw.se);
        mediaPlayer.setLooping(false);
        mediaPlayer.seekTo(0);
        mediaPlayer.start();
    }
});
binding.testButton2.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Log.d("TAG", "onClick: testButton2 stop bgm");
        //
        if(mediaPlayer!=null) {
            mediaPlayer.stop();
            mediaPlayer.release();
            mediaPlayer = null;
        }
    }
});
 
上のtestButtonは再生、testButton2が停止。
mediaPlayer.setLooping(false);をtrueにすると再生を繰り返す。
自分のスマホではstopの時にプチッと音が入る。
 
ちなみに、MainActivity activity = (MainActivity) getActivity();とやって、
MediaPlayer.create(activity, R.raw.se);の入力にしています。
こうすると、Fragmentからでも、mediaPlayerのthisの代わりになってくれます。
 
ただし、スマホを回転すると、Fragmenを作り直すようなので、注意です。
もしかしたら、mediaPlayer変数はMainActivityに持っておいて、初期化しておいて、
再生時にFragmentから呼び出すようにした方が良いかもしれませんね。