androidStudioボタン追加メモ
 
File→New→NewProjectでBasicActivityを選択すると、
2枚の画面をボタンで行ったり来たり出来るアプリが作られる。
ここではNameはFirstR5にして進める。
 
左のプロジェクトWindowのapp→res→layout→fragment_first.xml
を選択すると1枚目の画面をビジュアルで編集できるので
PaletteからCommon→Buttonをドラックして画面に配置。
ボタンをクリックし右のAttributesのidをtest_buttonに変更してEnterを押すと
リファクタリングするか?と聞かれるのでする。
同様にAttributesのtextもtest_buttonにしておく。
 

 
次に、
左のプロジェクトのapp→java→FirstFragmentの「ここから」、「ここまで」を追加すると、
ボタンが押されたのを取れるようになります。
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        binding.buttonFirst.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                NavHostFragment.findNavController(FirstFragment.this)
                        .navigate(R.id.action_FirstFragment_to_SecondFragment);
            }
        });
        //ここから
        binding.testButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Log.d("TAG", "onClick: testButton");
            }
        });
        //ここまで
    }
}
デバッガーで動かして
下のDebugで見ながら、TEST_BUTTONをクリックすると
Log.dで出力したメッセージを確認できます。
 

 

AndroidでSQLiteを行う。

 

久々のAndroid開発の仕事が来たので、いろいろ思い出しながら
備忘録としての記事です。

 

今回はSQLiteですね。
結構いろんなプラットフォームに採用されていて
ちょこっとしたといいつつ複雑なこともできるデータの永続化として重宝します。

 

■クラス準備

 

まずは、SQLiteOpenHelperを継承したクラスを準備してonCreateとonUpgradeを継承(Override)して行きます。

Createはcreate分、Upgradeはdrop後にcreateして行きます。
本来ならば、Update側はAlterTableでカラムを追加したり、
するんでしょうけど、備忘録的にはこうしています。

 

package com.miha.firstr2;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;


public class DbHelper extends SQLiteOpenHelper{
    public DbHelper(Context context){
        super(context, "test.db", null, 1);
    }
    @Override
    public void onCreate(SQLiteDatabase db){
        db.execSQL("create table if not exists test( id text primary key, info text)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db,
                          int oldVersion, int newVersion){
        db.execSQL("drop table if exists test");
        onCreate(db);
    }
}

上のテーブル構造としては
  create table test( id text primary key, info text
  なので、
  テーブル名 test
  項目としては2項目で
  id と info 
  があって、それぞれ、テキストが入れられる項目です。
  idがプライマリキーです。

 

■呼び出し方。

 

上記のクラスをnewします。


DbHelper dbHelper=new DbHelper(this);


ちなみに、Contentを渡す関係か?わかりませんが、
MainActivityだとうまく行くけどViewではだめって言われた。

 

dbオブジェクトを取得します。

 

SQLiteDatabase db = dbHelper.getWritableDatabase();

 

データが無いと何もできないのでinsertします

2レコードですね。

 

ContentValues values1 = new ContentValues();
values1.put("id", "0");
values1.put("info", "sapporo");
db.insert("test","", values1);

ContentValues values2 = new ContentValues();
values2.put("id", "1");
values2.put("info", "aomori");
db.insert("test", "", values2);

 

データの中身は
+----------+-------------+
| id       | info        |
+----------+-------------+
| 0        | sapporo     |
+----------+-------------+
| 1        | aomori      |
+----------+-------------+
ですね。

 

検索です。検索条件としてid=1としているので、strに取得できるのはaomoriです。

 

Cursor c = db.query("test", new String[]{"id", "info"},
        "id='1'", null, null, null, null);
c.moveToFirst();
String str=c.getString(1);

 

このgetStringのパラメーターは0から指定出来て1はinfoを取得することになります。
0ならidが取れます。

 

更新です。id=0はsapporoだったのをosakaに書き換えます。

 

ContentValues values3 = new ContentValues();
values3.put("id", "0");
values3.put("info", "osaka");
int num = db.update("test",values3, "id=0", null);

 

この時にnumが0なら更新失敗です。

更新結果を検索します。今度は全検索です。

 

Cursor c = db.query("test", new String[]{"id", "info"},
         null, null, null, null, null);
c.moveToFirst();
while(true){
    String str=c.getString(1);
    if(c.moveToNext()==false){
        break;
    }
}
c.close();

 

この、moveToFirstが先頭、moveToNextが次レコードですね。
  moveToNextがfalseならループ脱出します。

 

 

次に、DBのファイルの中身を見る方法です。


AndroidStudioのメニューからView→ToolWindow→DeviceFileExplorerとして
data/data/com/miha/firstr2/databases/test.dbの位置にDBが保存してあり、
ここで、DB指定して右クリックsave asを選択して保存。
そのファイルをDB-Browser for SQLiteで開くと、DBの中身が見れたりします。

 


JUGEMテーマ:電子工作

RDA5807のラジオ作成

 

いやー結構大変でした。
RDA5807のラジオモジュールを秋月で買ったんですが、
壊れると嫌だなーと思い3つ買いましたが、
モジュールのピンのピッチが2mmピッチだということに到着してから気づいたものの、
2.54の基盤にのっけて配線するって秋月の説明にあり。


真似してみたんですが、いやー難しい。
そんなこんなで一つ破壊。
データシートの図となんか違い。いろいろやって、プラスとマイナス逆につないでもう一つ破壊?(多分)


データシートが怪しいと気づいて一度はうまく動いたんですが、
電源入れたり切ったりしているうちに全部壊してしまいました。


たぶん、突入電流とか、静電気とか、そんなんで壊してしまったと思われます。

で、ですね。


色々調べて、aidendoさん。ラジオモジュールDIP化基板(5枚入) [P20D10A]

 

 

これで、楽々2.54mmに変換できますね。
というわけで、これ。

 

 

5枚入りのセットだったのを間違えて3個注文したら、15枚来ちゃった。
ま、良いんですけど。2mmの10ピンから2.54mmに変換するのに当分困りません。


aitendoさんではRDA5807Pが売っており、こちらも3枚買っておきましたので、
作っていったのですが、
電源入れたり切ったりしているうちに2枚破壊。
またしても、突入電流とか、静電気とか、そんなんで壊してしまったと思われます。
今度は失敗しないよう、5807の電源にコンデンサー470μFと100pFを投入したところ、
壊れないようになったようです。

これで、1台完成。

 


で、もう一台作りたいと思い。
秋月でさらにRDA5807を3つ購入。秋月さんで売っているのはRDA5807Hなんですが。同じように動きました。
首尾よく作り上げ、もう一台完成。

 


って感じで。今回はすごく苦労しました。

 

■回路図

 

■プログラム

 

libは

 http://www.mathertel.de/Arduino/RadioLibrary.aspx

 https://github.com/asukiaaa/ST7032_asukiaaa

を利用しています。

 

https://drive.google.com/file/d/1YMYLGZbwcszczs7nsrwRoNIX2QAAEZpg/view?usp=sharing

 

#include "EEPROM.h" 
#include "ST7032_asukiaaa.h"
#include "radio.h"
#include "RDA5807M.h"

ST7032_asukiaaa lcd;

int old2=1;
int old4=0;
float fHz = 79.7;   //FM泉
//float fHz = 77.1; ///FM仙台
//float fHz = 93.5; ///TBC
//float fHz = 82.5; ///NHK宮城
//float fHz = 76.2; ///仙台シティーFM
//float fHz = 78.1; ///BAY WAVE石巻 NG
//float fHz = 76.4; ///ラジオ石巻 NG
//float fHz = 77.9; ///エフエムいわぬま NG
float oldHz = 0;
long lastTm;
int modeMONO=false;

#define FIX_BAND     RADIO_BAND_FMWORLD
#define FIX_VOLUME   1

RDA5807M radio;

void save_EEPROM(int v)
{
  EEPROM.write(0, v/256);
  EEPROM.write(1, v%256);
}

int load_EEPROM()
{
  int h = EEPROM.read(0);
  int l = EEPROM.read(1);

  int r = h * 256 + l;
  Serial.println(r);
  return r;
}

void prtHz()
{
  char buf[21];
  memset(buf, '¥0', sizeof(buf));
  dtostrf((float)fHz,6,2,buf);
  strcat(buf, "MHz");

  lcd.setCursor(2, 1);
  lcd.print(buf);

}
void setup(){
  Serial.begin(115200);

  //save_EEPROM(771);
  int hz = load_EEPROM();
  fHz = (float)hz / (float)100.0;
  oldHz = fHz;
 
  delay(200);
  radio.init();
  //radio.debugEnable();
  radio.setBandFrequency(FIX_BAND, fHz*100);
  radio.setVolume(FIX_VOLUME);
  radio.setMono(false);
  radio.setMute(false);

  //lcd 初期化
  lcd.begin(16, 2);
  lcd.setContrast(10);
  //
  lcd.print("FM Radio! ");
  prtHz();
  lcd.setCursor(11, 1);
  lcd.print("ST  ");

  //
  pinMode(2, INPUT);
  pinMode(3, INPUT);

  Serial.println("start BuildNo 0.04");

  lastTm = millis();

}

void loop() {
//  lcd.setCursor(0, 1);
//  lcd.print(millis()/1000);

  //
  int val4Flag=0;
  int val2 = digitalRead(2);
  int val3 = digitalRead(3);
  int val4 = digitalRead(4);
  if(old2!=val2){
    if(val2==1){
      if(val3==0){
        if(val4==1){
          fHz = fHz + 0.01; 
          val4Flag=1;
        }
        else{
          fHz = fHz + 0.1;
        }
      }
      else{
          if(val4==1){
            fHz = fHz - 0.01;
            val4Flag=1;
          }
          else{
            fHz = fHz - 0.1;
          }
      }
      //Serial.println(fHz);
      Serial.println(fHz);
      prtHz();
      lastTm=millis();
      }
    old2=val2;
  }
  //streo-mono 切り替え
  if(old4!=val4){
    if(val4==1 && val4Flag==0){
      if(modeMONO==false){
        modeMONO=true;
        Serial.println("modeMONO=true"); 
        lcd.setCursor(11, 1);
        lcd.print("MONO");
      }
      else{
        modeMONO=false;
        Serial.println("modeMONO=false"); 
        lcd.setCursor(11, 1);
        lcd.print("ST  ");
      }
      radio.setMono(modeMONO);
    }
    if(val4==0){
      val4Flag = 0;
    }
    old4=val4;
  }
  long now = millis();
  if((now-lastTm)>1000){
    if(oldHz!=fHz){
//      Serial.println("NotEqual"); 
//      Serial.println(fHz); 
//      Serial.println(oldHz); 
//      Serial.println(now); 
//      Serial.println(lastTm); 
      Serial.print("set:");
      Serial.print(fHz);
      Serial.println("MHz");
      radio.setMute(true);
      //radio.init();
      radio.setBandFrequency(FIX_BAND, fHz*100);
      //radio.setVolume(FIX_VOLUME);
      //radio.setMono(false);
      radio.setMute(false);

      save_EEPROM(fHz*100);

//      char s[12];
//      radio.formatFrequency(s, sizeof(s));
//      Serial.print("Station:"); 
//      Serial.println(s);
//      
//      Serial.print("Radio:"); 
//      radio.debugRadioInfo();
//      
//      Serial.print("Audio:"); 
//      radio.debugAudioInfo();
      
      oldHz = fHz;
    }
  }
}


JUGEMテーマ:電子工作


照度センサーTSL2572をESP32のmicropythonで使う
 
秋月から照度センサーTSL2572が届いたので、ESP32に繋いで測定してみた。
 
秋月のページにサンプルとして掲載されている
プログラムにラズパイ用が有ったのでこれをベースにESP32のmicropythonで使えるようにしました。
 
■回路図
 

 
 

 
■ソース

 

ほぼそのままですが、ESP32のmicropythonに合わせて書き換えています。

 

#

#  ESP32 micro python system
#
# 接続(秋月の商品No=K-15536の場合)
#  TSL2572----------ESP32
#   VIN          3V3
#   3V3          3V3
#   GND          GND
#   SDA          21
#   SCL          22
#
# 仕様
#  
#  光の強さをルクス(LUX)単位で取得して表示する
#


import time
from machine import Pin, I2C
import sys

time.sleep(3.5)
print("TSL25721-get-LUX Build0.2")

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

addr_tsl25721=0x39
print(i2c.scan())

#TSL2572 Register Set
TSL2572_ADR      = 0x39
TSL2572_COMMAND  = 0x80
TSL2572_TYPE_REP = 0x00
TSL2572_TYPE_INC = 0x20
TSL2572_ALSIFC   = 0x66

TSL2572_SAI   = 0x40
TSL2572_AIEN  = 0x10
TSL2572_WEN   = 0x80
TSL2572_AEN   = 0x02
TSL2572_PON   = 0x01

TSL2572_ENABLE   = 0x00
TSL2572_ATIME    = 0x01
TSL2572_WTIME    = 0x03
TSL2572_AILTL    = 0x04
TSL2572_AILTH    = 0x05
TSL2572_AIHTL    = 0x06
TSL2572_AIHTH    = 0x07
TSL2572_PRES     = 0x0C
TSL2572_CONFIG   = 0x0D
TSL2572_CONTROL  = 0x0F
TSL2572_ID       = 0x12
TSL2572_STATUS   = 0x13
TSL2572_C0DATA   = 0x14
TSL2572_C0DATAH  = 0x15
TSL2572_C1DATA   = 0x16
TSL2572_C1DATAH  = 0x17

#TSL2572 setings
atime = 0xC0
gain = 1.0
buf = bytearray(1)

def initTSL2572() :
  if (getTSL2572reg(TSL2572_ID)!=0x34) :
    #check TSL2572 ID
    return -1
  setTSL2572reg(TSL2572_COMMAND | TSL2572_TYPE_INC | TSL2572_CONTROL, 0x00)
  setTSL2572reg(TSL2572_COMMAND | TSL2572_TYPE_INC | TSL2572_CONFIG,  0x00)
  setTSL2572reg(TSL2572_COMMAND | TSL2572_TYPE_INC | TSL2572_ATIME,   atime)
  setTSL2572reg(TSL2572_COMMAND | TSL2572_TYPE_INC | TSL2572_ENABLE,  TSL2572_AEN | TSL2572_PON)
  return 0


def getTSL2572reg(reg) :
  #dat = i2c.read_i2c_block_data(TSL2572_ADR,TSL2572_COMMAND | TSL2572_TYPE_INC | reg,1)
  dat = i2c.readfrom_mem(addr_tsl25721, TSL2572_COMMAND | TSL2572_TYPE_INC | reg, 1)
  
  print("dat="+str(dat[0]))
  return dat[0]


def setTSL2572reg(reg, dat) :
  #i2c.write_byte_data(TSL2572_ADR,reg,dat)
  buf[0]=dat
  i2c.writeto_mem(TSL2572_ADR, reg, buf)


def getTSL2572adc() :
  #dat = i2c.read_i2c_block_data(TSL2572_ADR,TSL2572_COMMAND | TSL2572_TYPE_INC | TSL2572_C0DATA,4)
  dat = i2c.readfrom_mem(addr_tsl25721, TSL2572_COMMAND | TSL2572_TYPE_INC | TSL2572_C0DATA, 4)
  adc0 = (dat[1] << 8) | dat[0]
  adc1 = (dat[3] << 8) | dat[2]
  return[adc0,adc1]


#main
print("init....")
if (initTSL2572()!=0) :
  print("Failed. Check connection!!")
  sys.exit()

while 1:
  adc = getTSL2572adc()

  cpl = 0.0
  lux1 = 0.0
  lux2 = 0.0
  cpl = (2.73 * (256 - atime) * gain)/(60.0)
  lux1 = ((adc[0] * 1.00) - (adc[1] * 1.87)) / cpl
  lux2 = ((adc[0] * 0.63) - (adc[1] * 1.00)) / cpl
  if ((lux1 <= 0) and (lux2 <= 0)) :
    print("0 Lx")
  elif (lux1 > lux2) :
    print("{:.1f} Lx".format(lux1))
  elif (lux1 < lux2) :
    print("{:.1f} Lx".format(lux2))
  time.sleep(1.0)


JUGEMテーマ:電子工作


オペアンプ+コンパレーターの活用
 
先週の記事で
 https://ameblo.jp/fc2miha/entry-12833773060.html

各種センサーからの入力が扱えるように
汎用的なオペアンプ+コンパレーター回路を組みました。
その中で焦電系のセンサーとかの微細な入力も扱える予定でしたので、
本当に使えるか、テストしてみましたな記事です。
 
■赤外線センサー RE-210 人感センサー

 
 
■ECM(エレクトレットコンデンサーマイク) C9767 音声

 
 
■ダイナミックマイク スピーカー 音声

 

■プログラム

 

import machine
import time

print("Button Version 0.1")

p15 = machine.Pin(15, machine.Pin.IN)

count = 0

old=0
while True:
  value =p15.value()
  if old != value :
    count = count + 1
    print(str(count)+", value="+str(value))
    old = value
  time.sleep(0.1);
 

■考察

 

3種試してみましたが、
どのパターンでも今一つ増幅率が足りない感じでしたがいちおう、
全部正常に検出してESP32へ正しい信号を送ることが出来ました。

RE-210においては、3.3Vでは電圧が足りないせいか、近くでしか反応しなかったりしましたが、
その辺りは実際の応用機器を作る場合に参考になる情報が取れたので良かったと思います。
RE-210の信号出力であるソースが抵抗を介してGNDへ接地しないとうまく電圧が出てくれなかったので
それに気づくまで少し時間がかかりましたが上の回路の通りでうまく検出できるようです。

 

下の二つは音に反応するタイプです。

昔々売ってた、音に反応して人形が躍るようなやつはこんな仕掛けで動いていると思います。


JUGEMテーマ:電子工作


赤外線リモコン(ESP32のRMT制御)
 
手持ちパーツで黒くて丸いやつ。

 
これってハードオフに
ケーブル探しに行ったときに3.5のオーディオプラグがくっついていて、
必要なのはオーディオプラグだけだったんで切り離して
こっちの丸くて黒いやつはそのまま取っておいたんだけど。
この度、もしやこれは、赤外線リモコンの受信部分じゃねーの?
と思い、いろいろ試した結果、
予想通り動きましたのでこれとESP32で赤外線リモコンの実験してみようかなと思います。


 
 
■赤外線リモコンの規格
 
赤外線は人の目に見えない光です。
目に見えるのは800nm~400nmの範囲になります。


 
引用
 https://www.toho-u.ac.jp/sci/biomol/glossary/chem/visible_light.html

リモコンで使っているのが940nmとの事なので、
周波数が低い方に少しずれたところの光を使っています。

 
ちなみに、https://keisan.casio.jp/exec/system/1240368538によると、
940nmの波長は周波数で言うと318.9THzとの事です。
携帯の5Gでやっと、30GHzですからね、人類はまだまだそこまで及ばないですね。
上記の赤外線を33KHz~40Khzの搬送波使って点滅させることで太陽光などの自然な光からの誤動作を防ぎつつ通信を行う。
ってもののようです。

 
参考ページ。
 http://elm-chan.org/docs/ir_format.html
上の参考ページによると
NECフォーマット、家製協フォーマット、SONYフォーマットに分かれており、
搬送波にONとOFFの信号が乗っかってくる。

そのONとOFFの信号を解析すると、メーカーコードとかデータが入ってくるんだぜ。
という事になっている。

 
となっているんですが、データの中身はそんなに興味はなくて、
市販のリモコンからデータを取り込んでおいて、
同じデータを送信できるとオリジナルリモコンとして、
マイコンと連動したり、ネットを経由して家電を制御できるよなーって思っております。

 
■回路
 

 
■データ受信
 フォトトランジスターで出来るのかなーと思っていたんですが、
 それだと搬送波の処理からやらきゃならないんですが、
 上の黒くて丸いやつとか、秋月のOSRB38C9AAでやると、搬送波の処理は
 すでに終わっている状態でONとOFFが取り出せるので、
 これの時間を記録していきます。
 一定時間記録したら、pythonの配列の形式で画面表示します。

 
■データ送信
 PWMでも出来そうなものですが、ESP32にはより正確な
 RMT制御ってのが有るそうでして、
 これを使うと、より簡単にリモコン信号を作ることができます。
 赤外線LEDは秋月のOSI5FU5111C-40を使います。
 中心波長は940nmです。

 

■プログラム使い方解説

 

受信プログラム実行例
 ex...
 IRread Version 0.1
 [8976, 4488, 561, 561, 561, 561, 561, 561, 561, 1683, 561, 1683, 561, 1683, 561, 561, 561, 1683, 561, 561, 561,  561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, 1683, 561, 561, 561, 1683, 561, 1683, 561,  1683, 561, 561, 561, 561, 561, 1683, 561, 561, 561, 1683, 561, 561, 561, 561, 561, 561, 561, 1683, 561, 1683,  561, 561, 561, 44880, 8976, 2244, 561]
------ここまで-----


IRread Version 0.1と出たらリモコンデータの入力待ちになるので、
お目当てのリモコンボタンを一回押します。
その下に表示されているカッコと数字とカンマをコピーして
送信プログラムの「↓①↓↓↓↓」の所の配列を書き換えてください。
それで、実行するとリモコンと同じ信号で赤外線
LEDが光るので家電の制御が出来るようになります。

 

■送信プログラム
#

#  ESP32 micro python system
#
# 接続
#  IR----------ESP32
#   +          23(トランジスターを間に入れて赤外線LEDを制御)
#
# 仕様
#  
#  赤外線リモコンの38KHzの搬送波に乗せて
#  パルス送信 Kenwood ミニコンポの電源ON/OFF
#  esp32のRMT機能を使用する
#

import machine
from machine import Pin
import time
import esp32

#
#↓①↓↓↓↓
signal_list=[8928, 4464, 558, 558, 558, 558, 558, 558, 558, 1674, 558, 1674, 558, 1674, 558, 558, 558, 1674, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 558, 1674, 558, 558, 558, 1674, 558, 1674, 558, 1674, 558, 558, 558, 558, 558, 1674, 558, 558, 558, 1674, 558, 558, 558, 558, 558, 558, 558, 1674, 558, 1674, 558, 558, 558, 44640, 8928, 2232, 558]

time.sleep(3.5)
print("start")

print("IRsend Version 0.4")

#ピンの準備
tx_pin = Pin(23, Pin.OUT)

#RMTの準備
ch = 0
freq=38000
rmt = esp32.RMT(ch, pin=tx_pin, clock_div=80, tx_carrier=(freq, 30, 1), idle_level=False)

#送信
rmt.write_pulses(signal_list, 1)
rmt.wait_done(timeout=2000)        #終わるまで待つ
print("end")


■受信プログラム
#

#  ESP32 micro python system
#
# 接続
#  PL-IRM0101----------ESP32
#   VOUT             15
#
# 仕様
#  
#  赤外線リモコンの37.9KHzの搬送波から
#  パルス受信
#


import machine
from machine import Pin
import time

print("IRread Version 0.1")

pin = machine.Pin(15,Pin.IN)

rec_time = []

first = 1
HiLo = 1
while True :
  if first == 1 :
    if pin.value()==0 :
      first = 0
      HiLo=0
      timeStamp = time.ticks_us()
      #print("point 100")
  else :
    if HiLo == 0 :
      if pin.value()==1 :
        #print("point 200")
        HiLo = 1
        newTimeStamp = time.ticks_us()
        sa = newTimeStamp - timeStamp
        rec_time.append(sa)
        timeStamp = newTimeStamp
    if HiLo == 1 :
      if pin.value()==0 :
        #print("point 300")
        HiLo = 0
        newTimeStamp = time.ticks_us()
        sa = newTimeStamp - timeStamp
        rec_time.append(sa)
        timeStamp = newTimeStamp
    
    #1秒経過でループ脱出
    newTimeStamp = time.ticks_us()
    sa = newTimeStamp - timeStamp
    if sa > 1000000 :
      #print("point 400")
      break

#
#誤差を修正して表示
#  先頭32の最小をmin_intervalとして
#  並びでmin_intervalの1.4倍よりも小さいものがあったらその二つの平均を求めて
#  basic_timeにして、rec_timeの中身をbasic_timeの倍数にして取り出す
#
first = []
#
for i in range(min(len(rec_time), 32)):
    first.append(rec_time[i])
#
min_interval = min(first)
#
for i in range(32):
    if first[i] < min_interval*1.4 and first[i+1] < min_interval*1.4:
        basic_time = (first[i]+first[i+1]) // 2
        break
#time_list = [round(rec_time[i]/basic_time)*basic_time for i in range(len(rec_time))]
for i in range(len(rec_time)) :
  rec_time[i] = round(rec_time[i]/basic_time)*basic_time

#表示
out_str="["
for i in range(len(rec_time)) :
  out_str=out_str+str(rec_time[i])
  if i<len(rec_time)-1 :
    out_str=out_str+", "
out_str=out_str+"]"
print(out_str)
 

 


JUGEMテーマ:電子工作


電力センサーのIoT化(P-08960&ESP32)
 
5月の記事でESP32で電力センサーを動作させる記事
 https://ameblo.jp/fc2miha/entry-12833773042.html

を書いていたんですが、ESP32なんだから、
WIFI接続しないともったいないですよね。
 
と、言うわけで・・・・・
 
サーバーから電力が見えるようにしてみました。
 
■完成図
 

 
■回路

 
■サーバー側スクリーンショット

 

■電力取得部分ソース

import utime
import machine

pin36=machine.Pin(36, machine.Pin.IN)
adc0 = machine.ADC(pin36)
adc0.atten(machine.ADC.ATTN_11DB)

def keisan(p_pp) :
  t_pp  =[0.0, 1.0, 2.0, 3.0, 4.0 , 5.0, 11.2 ,  22.45, 54.0 , 104.8, 148.5, 200.0, 200000.0]
  t_kake=[0.0, 8.0, 8.5, 9.0, 9.25, 9.8, 10.63,  10.78, 10.61, 10.35, 10.15, 10.0 , 10.0]
  for i in range(13):
    if p_pp < t_pp[i] :
      ret = t_kake[i-1] * p_pp
      #print("in="+str(p_pp)+" t_pp="+str(t_pp[i])+" t_kake="+str(t_kake[i-1])+" ret="+str(ret))
      return ret
  return 0

#debug
#for i in range(2000):
#  keisan(i)
#
#exit()

while True :
        val = 0
        min = 4096
        max = 0
        for i in range(50):
          total = 0
          count = 0
          for i in range(240):
                val = adc0.read()
                total = total + val
                count = count + 1
          try :
            ave = total / count
            if( min > ave) :
                min = ave
            if( max < ave) :
                max = ave
          except:
            print("dev-err")
        pp = max - min
        if pp<1.2 :
          pp=0.0
        w = pp*1.0
        print(str(min)+" - "+str(max)+" - pp="+str(pp)+" - "+str(keisan(pp))+"W")
 

■方式的に電線の中を通過する電力が発生させる磁気をコイルでキャッチして、

微電力に変換してそれの値を計測する方式なので、磁石とか、ほかのノイズに弱いです。

なんで、プログラムの中でppの値が小さかったらノイズと判断しています。

安物の同様のテスター(クランプ式)の場合に50W以下を検出できなかったのはこういった理由からなんですかね。

実際の運用では、アパートの電力の大元に付いている、ブレーカーのケーブルにクランプ挟もうと思っているので、

常時冷蔵庫とか、その他の待機電力を使っているので、上で登場したクランプ式テスターで計測すると、

最低でも100W程度は消費しているようなので問題ないと判断しています。

 

■そんなこんなであれですが、実際にecoワット的測定器と比較しながらテーブルを作成して

 取れた値とのグラフがこんな感じなので

 

 

 

プログラムでは取れた値と、比較して係数をかけている感じになります。

PPが200以上は係数10固定としていますが、これは、うちのecoワットちゃん1500Wまでしか測れないし、

普通のコンセントちゃんは1500Wが上限なので測定をあきらめました。

このへんはTEPCOと値を見ながら調整ですかね。

 


JUGEMテーマ:電子工作


静かで小型な12Vファン扇風機の開発とLM350Tの使い方
 
Novonest 120mm PCケースファン 静音タイプ 25mm厚 3ピン 1200rpm 3本1セット【12BK3-3】
これ、12センチのファンが3個入って、1000円。安いですよね。
 

 
コネクタが12Vでパソコン用のコネクタがついてきますが、
このままでは、使いにくいなーと思いまして、
DCプラグで動くようにしたいなーと思いまして。
付け替えました。
 
あと、手持ちのACアダプターが20Vのしかなくて、
このファンが12Vなので、直接つないだ場合に壊れそうなので、
丁度いい3端子レギュレーターがないかと探したんですが、
無くて、でも、可変型のLM350Tが見つかりましたので、
こちらで作成することにします。
 

 

 
LM350TはR1とR2を調整することで任意の電圧を出力することができる3端子レギュレーターです。
最大3Aの電流を取り出すことが出来るので、電子工作でこれを使って困ることはあまり無さそうです。
入力側は出力電圧+3V~最大35Vまで大丈夫みたいですね。
 
■電圧の計算
 
上のサンプルの回路のR1とR2で好きな電圧を出力することが可能です。
計算式
 VOUT=1.25*(1+R2/R1)
 で、12Vにするには・・・・いろいろ当てはめて計算したところ、
 R1=230Ω、R2=2000Ω

 これで計算すると12.11Vとなる。
 しかし、実際には230Ωという抵抗が普通には無いので、
 220Ωと10Ωを直列に繋いで作り出しました。
 実際には抵抗には誤差があって、
 R1=1984Ω、R2の合成が219.2Ωとなり、
 計算値では12.07Ωとなるので、これで作成。
 実際に組みあがって電圧を測定すると、12.08Ωなので、ほぼ計算通りという所です。
 

 

後日談

 これの応用で3.6Vを作ろうとして気づいたんですが、

 LM350Tって個体差があり、このチップだけ差し替えても若干電圧が変わります。

 ちなみに、3.6Vの場合はR2=2000、R1=1100とした場合、計算上は3.52になるはずですが、

 個体1では3.52、個体2は3.6が出力されました。

 

 


JUGEMテーマ:電子工作

LM386アンプ

 

簡単に音に出して聞きたいときにスピーカー付きの
アンプがあると良いなーなんて考えておりましたが、
 前の記事で
  http://miha.jugem.cc/?eid=309
オペアンプの汎用回路作ったので、ついでに作ってみました。の記事です。

 

■LM386


■回路

 

後ろの段のコンデンサーと抵抗は省略しちゃった。でも動く。

 →駄目です。ノイズ入るので10Ωと0.1μF後日追加。


■写真

左下の黒いのは昔のノートPCから取り出したスピーカーです。

入力大きめにするとすぐに音が割れますけど、それなりに聞こえるので

実験用としては実用的と思います。


JUGEMテーマ:電子工作


モーションセンサー的なIPM165とESP32実験用基板の汎用化
 
前の記事

 
記事をアップしてから思ったのですが、
LM358にはオペアンプが2ch入っており。
2ch目をコンパレーターにすれば
IC一個で済むよね。



 
それと、前の記事で少し触れた
「焦電系のAKE-1とかも同じ回路で動く気がする」の部分が気になっていたので、
基板1枚で汎用的に動けるようなオペアンプとコンパレーターをセットにした物を
実験用として作成しておくことにしました。
 
・特徴
 増幅率が調整可能。(固定抵抗の入れ替えによる)
 閾値の電圧を調整可能。(可変抵抗による)
 前段のオペアンプと後段のコンパレーター部を別々に使用することが可能
  (前段と後段の配線(白)が取り外し可能)
 
■回路
 
 

■写真