2024/12/29(日)Hogbeat ロ試作2版 仕様

E1D70653-DDB3-4BFE-9A7F-4E8AEC2B5AA2.jpeg

  • 電源
    • 電圧 2.0V ~ 3.6V
    • 電流 50μA (Max)
  • 入力
    • 信号周波数 1.5Hz ~ 3000Hz
    • 信号振幅 0V ~ 5.5V
  • 出力
    • 出力抵抗 780Ω
    • 信号振幅 0V ~ 3.8V
  • 分周比
    • 3:2 および 1:1
    • 回転式スイッチでキリカエル
  • 基板サイズ
    • 幅12mm × 奥行40.5mm × 高さ4.7mm

2024/11/04(月)Arduino mega : frequency counter/duty cycle meter を改良する

Original: https://www.electronicsblog.net/arduino-frequency-counterduty-cycle-meter/

Added feature: analog input, able to preset threshold level.
(and we fixed a bug at the auto range feature.)

Sketch:
//Arduino frequency counter/duty cycle meter (analog input)
//www.electronicsblog.net/
#include <LiquidCrystal.h>
#include <TimerThree.h>
#include <TimerFour.h>

//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int rs = 8, en = 9, d4 = 4, d5 = 5, d6 = 6, d7 = 7;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

// cycle meter input is pin 21
#define Button A1 // 52
#define ClkOut A7 // clock generator output
#define ClkLed 16 // to check generated clock
#define CmpSig A2 // analog comparator input
#define CmpOut 21 // analog comparator output
#define CmpLed 17 // to check signal detected

int divider[6] ={
  0,1,8,64,256,1024};

volatile int prescaler=5;

int b=0;

int screen =0;

volatile double count =0;
volatile double middle =0;
double usage =0;
bool x = false;

ISR(TIMER1_OVF_vect) {

  if (prescaler<4) {
    prescaler++;
  }

}
void interrupt()
{
  if (!x) {
    count=TCNT1;
    TCNT1=0x000;  
    TCCR1B=prescaler;
    attachInterrupt(2, interrupt, FALLING);

  }

  else {
    middle=TCNT1;
    attachInterrupt(2, interrupt, RISING);

  }

  x=!x; 
}

void timerClock() {
  // clock generator interrupt handler
  static int tcnt = 0;

  bool out = (tcnt % 4 == 0);
  ++tcnt;
  digitalWrite(ClkOut, out);
  digitalWrite(ClkLed, out); // high = led lit
}

void setup_clock_gen() {
  pinMode(ClkOut, OUTPUT);
  pinMode(ClkLed, OUTPUT);

  Timer3.initialize(120000); // in micro second
  Timer3.attachInterrupt(timerClock);
}

volatile int volt = 0;
void timerAnalog() {
  // analog read interrupt handler
  const int vth1 = 400;
  const int vth0 = 320;
  static int out = 0;

  int val = analogRead(CmpSig);
  if (val > vth1) {
    out = 1;
  }
  if (val < vth0) {
    out = 0;
  }
  volt = val;

  digitalWrite(CmpOut, out);
  digitalWrite(CmpLed, out); // high = led lit
}

void setup()   { 

  lcd.begin(16, 2);

  pinMode(Button, INPUT);
  digitalWrite(Button, HIGH); //pull up resistor

  pinMode(CmpSig, INPUT);
  pinMode(CmpOut, OUTPUT);
  pinMode(CmpLed, OUTPUT);

  TIMSK1=0x01; // enabled global and timer overflow interrupt;
  TCCR1A = 0x00; // normal operation page 148 (mode0);
  attachInterrupt(2, interrupt, RISING);

  //setup_clock_gen();

  analogReference(DEFAULT);
  ADCSRA = ADCSRA & 0xf8;   // 分周比を決めるビット(ADPS2:0)を000へ
  ADCSRA = ADCSRA | 0x04;   // 分周比を決めるビットに分周比16(100)をセット

  Timer4.initialize(100); // in micro second
  Timer4.attachInterrupt(timerAnalog);
}

void loop()
{
  usage=count/65536*100;

/// screen modes
  switch (screen) {

  case 0: 

    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print("Freq ");
    lcd.print(16000000.0/divider[prescaler]/count);
    lcd.print(" Hz");
    lcd.setCursor(0, 1); 
    lcd.print("Duty ");  
    lcd.print(middle/count*100); 
    lcd.print(" % ");
    lcd.print("    "); 
    break;

  case 1:
    lcd.setCursor(0, 0);
    lcd.print("Period: ");
    lcd.print(volt); 
    lcd.setCursor(0, 1);
    lcd.print(0.0000625*divider[prescaler]*count);
    lcd.print(" ms     ");
    break;   

  case 2:
    lcd.setCursor(0, 0);
    lcd.print("H ");
    lcd.print(0.0000625*divider[prescaler]*middle);
    lcd.print(" ms    ");
    lcd.setCursor(0, 1);
    lcd.print("L ");
    lcd.print(0.0000625*divider[prescaler]*(count-middle));
    lcd.print(" ms    ");
    break;   

  case 3:
    lcd.setCursor(0, 0);
    lcd.print("Prescaler /");
    lcd.print(divider[prescaler]);
    lcd.setCursor(0, 1);
    lcd.print("Count.use ");
    //usage=count/65536*100;
    lcd.print(usage);
    lcd.print("%  ");
    break; 

  }

  delay(250);

  if (prescaler>1) {

    if (usage<0.15) {
      prescaler--; 
      delay(200);
    } 

  }    

  ///button /////////

  if (!digitalRead(Button)&&!b) {

    screen++;
    if (screen==4) {
      screen=0 ;   
    }
    lcd.clear();

    b=3;

  }

  if (!b==0) b--;

}

2024/10/25(金)Hogbeat の機構設計メモ

適応製品

Gear_Devil 1PJK の試作機1版

TODO

  • 基板の厚みを調査する。
→1.0mmとする。大きなMLCCは基板の曲がりを考慮
  • 「ポッティング剤」をモノタロウで検索

回路のアイディア

プリスケーラー設計案:
0 8 9 A B C D E F
000
000
001
010
011
100
101
110
111
load(1000b) if !b3;
out = (!b0);  // ratio is 9:5, 1.80
0 C D E F
000
100
101
110
111
load(1100b) if !b3;
out = (!b0);  // ratio is 5:3, 1.66
0 E F
000
110
111
load(1110b) if !b3;
out = (!b0);  // ratio is 3:2, 1.50
おまけ
load(1010b) if !b3;
out = (!b0);  // ratio is 7:4, 1.75
実は本命❓
000
101
110
111
load(1101b) if !b3; // または !b2
out = (b2);  // ratio is 4:3, 1.33

機構のアイディア

基板にケーブルを接続して固定する方法。
切り込みでなくて1.2mm径の穴3つだと厳しいか。長穴3つなら有りか。
裏と表は逆にした方が良いか。テープの反対側に部品を置ける。付け根だけ4線で出して強化するのも良い。
防水のため自己癒着テープをパッキンを通る部分に薄く伸ばして巻く。

信号伝達コネクタピンに圧着して(さらに曲げて)からTHにはんだ付けする。

2024/10/24(木)Hogbeat Gear_Devilの予備調査をする

直射日光に晒される場所、高温や低温になる場所、結露・氷結の発生する場所、過度の衝撃や振動の発生する場所で使用しないでください。また高信頼性が必要な箇所には使用できません。 本モジュールは試作およびホビー用として設計されています。一般製品を意図した逆接続、逆挿入、過電圧等の検証は行われていません。誤った使用は破損、発煙、発火の原因となります。 本モジュールを使用して発生した直接的、間接的損害について開発元および販売元は一切の責務を負いません。

LFP機能 ロジック回路試作2版で実装

(LFP: Low Frequency Pass-through)
  • 入力パルスが10Hz以下のときは、分周比1:1のパス・スルー・モードに移行します。

分周率の切替え

案B ロジック回路試作2版で採用
パルス数[入力:出力] - 3:2 | 1:1
分周度 - 1.50 | 1.00
案C ロジック回路試作1版で採用
パルス数[入力:出力] - 3:2 | 5:3 | 9:5 | 1:1
分周度 - 1.50 | 1.66 | 1.80 | 1.00

試作機(中止)

パルス数[入力:出力] - 15:10
分周度 - 1.5

ロジック回路試作1版

  • フロントエンドをNJU77230 ×2で構成
  • ディバイダを74LV161 ×2で構成

ロジック回路試作2版

  • ディバイダを74LV161 ×1で構成
  • クロック生成とデコード用に74AUP1G57 ×4を配置

2021/06/04(金)LPC55xx I2S : Configuration register 1 and 2

参照: NXP LPC55S1x RM R1.4, 37.7.1~2項 *1

*1 : この記事は筆者が私的利用のためにReference Manualを抜粋、翻訳したものです。いかなる問題に対しても責任は負いません。

I2S : Register description

Configuration register 1

CFG1レジスタにはモード設定が含まれ、そのほとんどが1つのFlexcomm Interface内のすべてのI2Sチャネルペアに適用されます。いくつかの設定は最初のペア(プライマリ・チャネルペア)にのみ適用されます。

bit 0 MAINENABLE

このFlexcomm InterfaceのI2S機能のメインのイネーブル。

  • 0
    このFlexcommのすべてのI2Sチャネルペアがディセーブルされ、内部ステートマシン、カウンタ、フラグがリセットされます。他のチャネルペアは有効にできません。
  • 1
    最初のI2Sチャネルペアは有効です。このFlexcomm Interfaceの他のチャネルペアは、それぞれのPAIRENABLEビットで有効にすることができます。
bit 1 DATAPAUSE

データフローの一時停止。I2Sシリアライザ/デシリアライザとFIFO間のデータフローを一時停止することができます。これは、ストリームを変更する場合や、データのアンダーフローまたはオーバーフロー後の再起動時に行うことができます。一時停止中は、送受信中のデータを壊すことなく、FIFOの操作を行うことができます。

データの一時停止が要求されると、インターフェイスは、データの流れを中断する前に、進行中のデータの送信を完了する必要がある場合があります。ソフトウェアは、STATレジスタのDATAPAUSEDフラグを監視することにより、アクションを起こす前に一時停止が実際に有効であることを確認する必要があります。

DATAPAUSEがクリアされると、次のフレームの先頭でデータ転送が再開されます。

  • 0
    通常動作、またはI2Sがすでに一時停止している場合は次のフレームで通常動作を再開。
  • 1
    データフローの一時停止が要求されている。STATのDATAPAUSEDが1のときに有効です。
bit 3:2 PAIRCOUNT

これは0x3の読み取り専用フィールドで、このFlexcommインターフェイスで提供されているI2Sチャネルペアの数をあらわします。

  • 00 = 1つのI2Sチャネルペアがあります。
  • 01 = 2つのI2Sチャネルペアがあります。
  • 10 = 3つのI2Sチャネルペアがあります。
  • 11 = 4つのI2Sチャネルペアがあります。
bit 5:4 MSTSLVCFG

マスタ/スレーブ構成の選択で、このFlexcommのすべてのI2SチャネルペアでSCKとWSがどのように使用されるかを決定します。

  • 0x0
    通常のスレーブモード。SCKとWSをマスタから受信し、データの送受信に使用します。
  • 0x1
    WS同期マスタ構成。WSは他のマスタから受信され、Flexcommのファンクションクロックから分配された場合に、SCKの生成を同期させるために使用されます。
  • 0x2
    既存のSCKを使用するマスタ構成。SCKを受信し、WSの生成に直接使用するとともに、データの送受信を行います。
  • 0x3
    通常のマスタモード。SCKとWSが生成され、1つまたは複数のスレーブ機器に送ることができます。
bit 7:6 MODE

基本的なI2Sの動作モードを選択します。37.8.2項の「Formats and modes」を例として参照してください。

  • モード0(0x0)
    I2Sモード、通称「Classic」モード。WSのデューティサイクルは50%で、(有効なチャネルペアごとに)左チャネルのデータが第1フェーズに、右チャネルのデータが第2フェーズにそれぞれ1つずつ発生します。このモードでは、データ領域はフレームの先行するWSエッジの1クロック後に開始されます。
    備考: WSのデューティサイクルが50%の場合、FRAMELENはフレームのI2Sクロック数を偶数に定義する必要があります。FRAMELENが奇数クロックを定義している場合、余分なクロックは右サイドに発生します。
  • モード1(0x1)
    WSのデューティサイクルが50%になるDSPモード。モード0の備考を参照してください。
  • モード2(0x2)
    このDSPモードでは、WSは各データフレームの最初に1クロック分のパルスを出力します。
  • モード3(0x3)
    このDSPモードでは、WSは各データフレームの最初に1データスロット分の長さのパルスを出力します。
bit 8 RIGHTLOW

左右チャネルがどのようにFIFOデータ内に配置されるかを決定します。基本的には、FIFOとの間で転送される左右のチャネルデータが入れ替わります。

このビットは、データ幅が24ビット以上の場合やPDMDATA = 1の場合には使用されません。

なお、ONECHANNEL = 1の場合、使用される1つのチャネルは通常左チャネルとなります。POSITIONは、右チャネルデータが通常配置されるフレームにそのデータを配置することができます。

備考: すべての有効なチャネルペアがONECHANNEL = 1である場合、RIGHTLOW = 1は許可されません。
  • 0
    右チャネルはFIFOデータの上位部分から取得されます。例えば、データが16ビットの場合、FIFOのビット31:16が右チャネルに使用されます。
  • 1
    右チャネルはFIFOデータの下位部分から取得されます。例えば、データが16ビットの場合、FIFOのビット15:0が右チャネルに使用されます。
bit 9 LEFTJUST

データの左詰め。

  • 0
    データは、FIFOとI2Sシリアライザ/デシリアライザ間で右詰めで転送されます。つまり、ビット0から始まり、DATALENで定義された位置まで続きます。これは、データバスストリーム上の右詰めのデータに対応します。
  • 1
    FIFOとI2Sシリアライザ/デシリアライザの間でデータが左詰めで転送されます。つまり、FIFOエントリのMSBから始まり、DATALENで定義されたビット数だけ続きます。これは、データバスストリーム上の左詰めのデータに対応します。
bit 10 ONECHANNEL

シングルチャネルモード。送信と受信の両方に適用されます。このコンフィギュレーションビットは、最初のI2Sチャネルペアにのみ適用されます。他のチャネルペアは、それぞれのCFG1レジスタで独立してこのモードを選択できます。

  • 0
    このチャネルペアのI2Sデータは、左右のチャネルとして扱われます。
  • 1
    このチャネルペアのI2Sデータは、単一のチャネルとして扱われます。機能的にはこのペアの左チャネルとなります。
備考: I2Sモード0では、フレームの右半分はPOSITION = 0x100から始まります。これはモード0がフレームの左と右のサイドを明確に区別しているためです。ONECHANNEL = 1の場合、POSITIONを0x100 + 右サイド内のデータ位置に設定することで、シングルチャネルのデータを右側に配置することができます。例えば、0x108の場合、フレーム中央から8クロック目からデータを配置することになります。 その他のI2Sモードでは、POSITIONで定義されたクロックにシングルチャネルのデータが配置されます。
bit 12 SCK_POL

SCKの極性。

bit 13 WS_POL

WSの極性。

bit 20:16 DATALEN

データ長(マイナス1エンコード)は、このFlexcommのすべてのチャネルペアのI2Sデータのビット数を定義します。データはここで定義されたビット数だけSDAに駆動されたり、SDAから受信されたりすることに注意してください。

DATALENは、I2Sで以下のようにも使用されます。

  1. FIFOとI2Sシリアライザ/デシリアライザ間のデータ転送のサイズを決定する。37.8.4項 「FIFO buffer configurations and usage」を参照してください。
  2. モード1、2、3では、フレーム内の右データとそれに続く左データの位置を決定します。
  3. モード3では、WSパルスの持続時間を決定します。

値を示します。

  • 0x00~0x02 = サポートされていません。
  • 0x03 = データ長は4ビット
  • 0x04 = データ長は5ビット
  • 0x1F = データ長は32ビット

Configuration register 2

CFG2レジスタは、I2Sデータ構成の外観をコントロールするフィールドを含んでいます。

bit 10:0 FRAMELEN

フレーム長(マイナス1エンコード)は、フレームに含まれるデータビット数(クロック数)を定義します。37.8.2.1項の「Frame format」を参照してください。

  • 0x000~0x002 = サポートされていません。
  • 0x003 = フレームの長さは4ビット
  • 0x004 = フレームの長さは5ビット
    ...
  • 0x7FF = フレームの長さは合計で2048ビット
備考: I2Sモード0または1で奇数長のフレーム(例: 33クロック)を定義した場合、余分なクロックは右半分に出現します。
備考: I2Sモード3の場合、WSパルスを正しく生成するためには、FRAMELENはDATALENよりも大きくなければなりません。
bit 24:16 POSITION

データポジション。フレーム内でのこのチャネルペアのデータの位置を定義します。POSITION + DATALENはFRAMELENよりも小さくなければなりません。37.8.2.1項の「Frame format」を参照してください。

備考: I2Sモード0の場合、POSITIONはWSエッジの1クロック後から、左相と右相の両方でデータの位置を定義します。その他のモードでは、POSITIONはフレーム全体内のデータの位置を定義します。モード0でONECHANNEL = 1の場合は特殊なケースで、ONECHANNELの説明を参照してください。
備考: 全てのチャネルペアのDATALENとPOSITIONフィールドの組み合わせは、フレーム内でチャネルが重ならないようにする必要があります。
  • 0x000 = フレームまたはWSフェーズ内のビットポジション0(最初のビット位置)からデータが始まる。
  • 0x001 = フレームまたはWSフェーズ内のビットポジション1からデータが始まる。
  • 0x0FF = フレームまたはWSフェーズ内のビットポジション255からデータが始まる。
  • 0x100 = ONECHANNELの説明を参照。