SSブログ
前の10件 | -

久しぶりにISPで書き込みしてみると [Arduino]

ATTinyCoreのATtiny85にUSBaspを使って、書き込みしてみるとエラーが出る。

isp_error_1.png
Arduino:1.8.19 (Windows 10), ボード:"ATtiny25/45/85 (No bootloader), Enabled, CPU (CPU frequency), ATtiny85, 16.5 MHz (PLL, tweaked), EEPROM retained, B.O.D. Disabled (saves power), Enabled"

最大8192バイトのフラッシュメモリのうち、スケッチが1008バイト(12%)を使っています。
最大512バイトのRAMのうち、グローバル変数が37バイト(7%)を使っていて、ローカル変数で475バイト使うことができます。
スケッチの書き込み中にエラーが発生しました
avrdude: set SCK frequency to 187500 Hz
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: error: program enable: target doesn't answer. 0 
avrdude: initialization failed, rc=-1
         Double check connections and try again, or use -F to override
         this check.

・Arduino as ISP なら問題なくスケッチを書き込める。
・AVRDUDESS - A GUI for AVRDUDE ではATtiny85をちゃんと認識できる。
・USBaspのファームウェアを書き換えたりしてみたけどダメ。

ということで、Arduino の AVRDUDE が怪しい。

%USERPROFILE%\AppData\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino18\bin

(別の書き方だと、 %APPDATA%\..\Local\Arduino15\packages\arduino\tools\avrdude\6.3.0-arduino18\bin )

ここにある avrdude.exe を「AVRDUDESS-2.14-portable.zip (844 KB)」 の中に入っていた avrdude.exe に置き換えてみたらエラーが消えた。

(参照)
AVRDUDESS – A GUI for AVRDUDE - Zak’s Electronics Blog --
https://blog.zakkemble.net/avrdudess-a-gui-for-avrdude/

isp_error_2.png

問題解決、けっこう疲れた。
タグ:ISP AVRDUDE USBasp
nice!(0)  コメント(0) 

DigisparkでCharlieplexingするために、、 [Arduino]

DigisparkでCharlieplexingするために、、

Digisparkのいいところは、USB機能で、
 ・電源として
 ・書き込み手段として
 ・通信として(HIDデバイスなど)
使えるところですが、
 ・容量が減る
 ・3, 4番ピンが使いにくい
というデメリットがあります。
3, 4番ピンが使いにくいので、うまいことUSBとして使わないときだけ切ることができればいいと思ったのですが、どうもそれだけではなさそうで、USBの D- の1.5kΩの抵抗を挟んでのpull-upがされているとUSB接続されていることになり、PC側でエラーが出てしまいます。
pull-up、D-、D+の3回路をスイッチ操作で切り替えられるといいのですが、そもそもコンパクトな3回路2接点(3PDT?)のスイッチってなかなかない。

ということで、USB部分とマイコン部分をやむなく分離することにしました。
分離するにあたって、通販でよく見かけるマイコンなしのソケットタイプのdigispark互換機をUSB部分として使うことにしました。
ちなみにこれ、2x4=8ピンのスルーホールがありますが、6ピンISPコネクタの隣にUSBに使っている3,4番ピンがついており、全8ピンがマイコンの8ピンに対応しています。
ds-socket.png
マイコン部分には電源機能が欲しいので、USBコネクタを取り付けました。今つけるなら Type-Cということで、

USB Type-Cコネクタ 電源供給用 パーツ一般 秋月電子通商-電子部品・ネット通販
https://akizukidenshi.com/catalog/g/gC-16895/
C-16895-3.jpg
を使いました。
あとあとのことですが、type-Aからtype-Cへの変換ケーブルなら普通に給電できますが、CC1, CC2ピンがないので、Nintendo SwitchのACアダプタなどの賢いtype-C電源には使えませんでした。

以下、作成の経過です。
ds-half-1.jpg
エナメル線がはんだ付けされているように見えますが、繋がっていない部分がありました。
はんだが溶けてもさらに熱を加え続け、なんとなくプチっと音がしたくらいで(天ぷら?)やっと導通を確認できました。
ds-half-2.jpg
マイコンソケットは丸穴。丸穴のソケットだと隙間が多く、ソケットの下あたりにUSBコネクタ(レセプタクル)の足を通せるので。
ds-half-3.jpg
マイコン部分はこれで完成。
ATtiny85は、fuse設定やDigisparkのブートローダは書き込み済。
ds-half-4.jpg
裏もこんな感じ、一応チップタイプのパスコンも付けてみた。
ds-half-5.jpg
書き込み器。
上は6ピンISPとしても使えるようにした。
P0をpull-downできるスイッチもとりつけた。
ds-half-6.jpg
重ねたところ。
ds-half-7.jpg
0, 1, 2, 3番を使ったCharlieplexingでLEDはきちんと光っています。

作ってみて思ったのは、USBを書き込みでしか使わないのであれば、ISPプログラマでいいのでは、、Digisparkのメリット全部否定してるし。



nice!(0)  コメント(0) 

DigisparkにCharlieplexingは不向きかな。その2 [Arduino]

調べていたら、aitendoで12連LEDを発見したので購入。

12バーLEDアレイ - aitendo
https://www.aitendo.com/product/11443
LED-B12.png
ついでにこれも。

超極細エナメル線★φ0.1★10m巻き★ - aitendo
https://www.aitendo.com/product/4733
cp12-2.jpg

それで作ってみました。抵抗もチップ抵抗を使用。
cp12-1.jpg

で、こんな感じ。
cp12-3.jpg



nice!(0)  コメント(0) 

DigisparkにCharlieplexingは不向きかな。 [Arduino]

以前にもマトリックスLEDでCharlieplexingの応用で駆動するのをやりましたが、Digisparkのようなピン数の少ないものほどよい適応かなと思って作ってみました。

結論からいくと、Digisparkではやや動作がおかしいので、Arduino Nano互換機でやりました。


10ポイント青色バーLEDアレイOSX10201-B ディスプレイ・表示器 秋月電子通商-電子部品・ネット通販
https://akizukidenshi.com/catalog/g/gI-04294/

I-04294.jpg

これをCharlieplexingで光らせるには4ピンあればOKです。(4ピンあれば12個のLEDまでいける)
端切れ基盤にICソケットとピンヘッダと抵抗を載せてポリウレタン銅線で配線。
cp10-1.jpg
cp10-2.jpg

いざDigisparkでやってみると、なにかおかしい。
光っちゃいけないところがぼやっと光ったりする。
理由として考えられること:
・リセットピン(P5)をI/Oピンとして使うとドライブ能力が低い
・純粋なピンがはP0、P2しかなく、他はUSBやbuilt-in LEDとつながっている
という感じだと推測しています。
たとえば、A → B と電流が流れてLEDを光らせる場合、 A → C → B という経路にはほぼ流れないんだけど、ピンの条件が均一でないために A → C → B という経路でもそこそこ流れてしまうのかなって。

仕方ないので、Arduino Nanoの互換機で試してみました。
cp10-3.jpg

// Drive 10 LEDs with 4 pins
// 
//   A A A B B B C C C D     D  D
// +---------------------+   |  |
// | | | | | | | | | | | |   |  |
// | _ _ _ _ _ _ _ _ _ _ |   _  _ Cathode(K)
// | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |   ^  ^ Anode(A)
// | | | | | | | | | | | |   |  |
// +---------------------+   |  |
//   B C D A C D A B D A     B  C
//
const  uint8_t LEDsK[12] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3 };  // Cathode side (0:A, 1:B, 2:C, 3:D)
const  uint8_t LEDsA[12] = { 1, 2 ,3, 0, 2, 3, 0, 1, 3, 0, 1, 2 };  // Anode side
const  uint8_t LEDsPn[4] = { 2, 3, 4, 5 };                          // Arduino pin number (or DDRxn, PORTxn)
static uint8_t pos = 0, dir = true;                                 // Position and Direction(0:-, 1:+) of light

void setup() {
}

void loop() {
  lightUpD( dir ? pos++ : pos-- );
  delay(50);
  if(pos == 9 || pos == 0) dir = 1 ^ dir;
}

void lightUp(uint8_t n){                // Arduino form
  for(uint8_t i=0; i<4; i++) {
    if( LEDsA[n]==i || LEDsK[n]==i ) {          // If the pin is connected to the anode or cathode of the LED,
      pinMode( LEDsPn[i], OUTPUT );             //   set to output pin
      digitalWrite( LEDsPn[i], LEDsA[n]==i );   //   set cathode LOW, Set anode HIGH
    } else {
      pinMode( LEDsPn[i], INPUT  );             // Set to Hi-
    }
  }
}

void lightUpD(uint8_t n){               // port D version
  for(uint8_t i=0; i<4; i++) {
    bitWrite( DDRD , LEDsPn[i], LEDsA[n]==i || LEDsK[n]==i );
    bitWrite( PORTD, LEDsPn[i], LEDsA[n]==i                );
  }
}

nice!(0)  コメント(0) 

Digisparkで音楽演奏【PLL OC1A編】 [Arduino]

以前のスケッチを手直し。
ボードマネージャは、ATTinyCore でも Digistump AVR Boards でも行けるようにしてみた。
8MHzでもなんとか遅延はなさそうで、乾電池2本でも動作できるはず。

dsoutput.jpg
結局もう1つ改造Digispark作成。
壊れたイヤホンからケーブルをリユースして録音用パーツを作成。



以下、スケッチ。
//  Digispark version Score Replay Sketch
//    Clock : 16.5/16/8 MHz, PLL : 66/64 MHz
#include "notes2.h"                     // Definition data of notes ( pitch (scale & octave), and note value (length))
#include "Kewpie3min.h"                 // "The Parade of the Tin Soldiers" by Leon Jessel
#define MAX_TRACK   4                   // Maximum number of tracks

// Number of cycles that are the wavelength of the basic 12-note scale (from C0 to B0) (@ 8 MHz, with an interrupt every 256 clocks)
static const uint16_t CYC_SCALE[] = { 1911, 1804, 1703, 1607, 1517, 1432, 1351, 1276, 1204, 1136, 1073, 1012 };

void setup(){
  pinMode( 1, OUTPUT );                 // Audio output (PB1,OC1A)
  pinMode( 0, INPUT_PULLUP );           // Switch       (PB0)
  
  // *** Register Settings (Timer1, for DAC)  *** PLL 64MHz, No prescaling. 8bit=256clock to make PWM, so 250kHz. 
  TIMSK  &= ~_BV(TOIE1);        // TIMSK(T/C Interrupt Mask Register)      - TOIE1(T/C1 Overflow Interrupt Enable) CLEAR : Disable ISR(TIMER1_OVF_vect) (for Digistump AVR Boards)
  PLLCSR |=  _BV(PCKE);         // PLLCSR(PLL Control and Status Register) - PCKE(PCK Enable) SET : PCK clock(fast 64 MHz) is used as T/C1 clock source
  TCCR1   = B01100001;          // TCCR1(T/C1 Control Register) : PWM A Enable. OC1A cleared on compare match. OC1A not connected. No prescale
  OCR1A   = 0;                  // OCR1A(T/C1 Output Compare RegisterA) : Set output to 0
  OCR1C   = 255;                // OCR1C(T/C1 Output Compare RegisterC) : Set upper limit to 255
  // *** Register Settings (Timer0, for Data) *** Data processing interval 31.25kHz(256clk@8MHz or 512clk@16MHz)
  TIMSK  &= ~_BV(TOIE0);        // TIMSK(T/C Interrupt Mask Register)      - TOIE0(T/C0 Overflow Interrupt Enable) CLEAR : Disable ISR(TIMER0_OVF_vect) (for ATTinyCore)
  TCCR0A  = B00000011;          // TCCR0A(T/C0 Control Register A) :  OC0A/OC0B disconnected, Fast PWM
  TCCR0B  = B01001010;          // TCCR0B(T/C0 Control Register B) :  Fast PWM, TOP:OCR0A, clk/8 (From prescaler)
  OCR0A   = F_CPU / 250000;     // OCR0A (T/C0 Output Compare A Register) : TOP 8MHz:32, 16MHz:64, 16.5MHz:66
}

void loop(){
  while(  digitalRead(0) );             // Wait until the switch is pressed
  while( !digitalRead(0) );             // Wait until the switch is released
  playDsPLL( Kewpie3min );              // Playback
}

void playDsPLL(const uint16_t *d){      // Digispark PLL version (16.5/16/8 MHz support)
  uint8_t  Tracks;                      // Number of tracks
  const uint16_t *NoteP[MAX_TRACK];     // Pointer for each track of the score
  uint16_t NoteCycle, n;                // Number of interrupt cycles required for the length of the reference note (96th note) and its counter (n)
  uint16_t note;                        // Note (pitch + note value) information read from PROGMEM
  uint8_t  len[MAX_TRACK];              // Length of note (how many 96th notes) (subtraction counter)
  uint16_t cyc[MAX_TRACK], c[MAX_TRACK];// Number of interrupt cycles (cyc) required for one sound wavelength cycle and its counter (c)
  uint16_t env[MAX_TRACK];              // Sound amplitude (envelope)
  uint16_t out[MAX_TRACK];              // Output value
  uint8_t  lap = 20;                    // Sound transitional cycles(laptime) (for Attenuation calculator)

  // *** Preparing Scores ***
  NoteCycle = 8000000 / 256 *4*60 / pgm_read_word_near(d++) / MIN_NOTE; // Number of cycles required for reference note
  for( Tracks = 0; Tracks < MAX_TRACK; ) {              // Get the number of tracks and the start position of each track from the song data
    if( pgm_read_word_near(d++) != 0 ) continue;        // Skip until the break comes
    if( pgm_read_word_near(d)   == 0 ) break;           // If two zeros follow, end of data
    len[ Tracks ] = 1;                                  // Initialize the note length subtraction counter to the remaining 1
    NoteP[ Tracks++ ] = d;                              // Get location in memory, Count up the number of tracks
  }
  n = Tracks;                           // Initialize the score processing so that it can be performed immediately after the start of the do loop

  // *** Playback ***
  do {
    // * Processing Scores *
    if( --n < Tracks ) {                // Processing of score for each reference note length
      if( !--len[n] ) {
        note   = pgm_read_word_near( NoteP[n]++ );
        len[n] = (uint8_t) note;        // The lower 8 bits are the length of the note (how many times the length of a 96th note)
        cyc[n] = (note>>8) ? CYC_SCALE[ (note>>8) & 0xf ] >> (note>>12) : 0;    // Upper 4 bits are octave, next 4 bits are pitch class (0-11), 0 for rests
          c[n] = 0;                     // Initialize the counter for the number of cycles to create one square wave cycle
        env[n] = 0xffff;                // Initially, the maximum amplitude
      }
      if( !n ) n = NoteCycle;
    }
    // * Waveform Processing / Output *
    switch( Tracks ) {                  // Create output data, Square wave with duty ratio of 1:1
      case 4:   out[3] = ( ( c[3] = (++c[3]==cyc[3]) ? 0 : c[3] ) < (cyc[3]>>1) ) ? env[3] : 0;   [[fallthrough]];
      case 3:   out[2] = ( ( c[2] = (++c[2]==cyc[2]) ? 0 : c[2] ) < (cyc[2]>>1) ) ? env[2] : 0;   [[fallthrough]];
      case 2:   out[1] = ( ( c[1] = (++c[1]==cyc[1]) ? 0 : c[1] ) < (cyc[1]>>1) ) ? env[1] : 0;   [[fallthrough]];
      case 1:   out[0] = ( ( c[0] = (++c[0]==cyc[0]) ? 0 : c[0] ) < (cyc[0]>>1) ) ? env[0] : 0;
    }
    switch( Tracks ) {                  // OC1A(ATtiny85:PB1) Change output by number of tracks
      case 1:   OCR1A =   out[0] >>8;                                   break;
      case 2:   OCR1A = ((out[0]>>1) + (out[1]>>1)) >>8;                break;
      case 3:   OCR1A = ((out[0]>>1) + (out[1]>>2) + (out[2]>>2)) >>8;  break;
      case 4:   OCR1A = ((out[0]>>2) + (out[1]>>2) + (out[2]>>2) + (out[3]>>2)) >>8;
    }
    switch( --lap ) {                   // Amplitude attenuation (Distribute processing per loop)
      case 4:   env[3] -= (env[3]>>9);    break;
      case 3:   env[2] -= (env[2]>>9);    break;
      case 2:   env[1] -= (env[1]>>9);    break;
      case 1:   env[0] -= (env[0]>>9);    break;
      case 0:   lap = 20;               // every 640usec(32usec*20) @16MHz (Adjustable)
    }
    while( !(TIFR & _BV(TOV0)) );       // Waiting for Timer0 overflow (every 32usec)
    TIFR |= _BV(TOV0);                  // Clear T/C0 Overflow Flag
  //if( ! digitalRead(0) ) break;       // Ends when PB0 is pressed.
    if( !(PINB & _BV(0)) ) break;       // Ends when PB0 is pressed.
  } while( note );                      // Exit if note data is 0
  OCR1A = 0;                            // Set output to 0
}

次は、矩形波じゃないやつで。
タグ:Digispark 音楽 PLL
nice!(0)  コメント(0) 

Digisparkで音楽演奏【楽譜サンプル】 [Arduino]

あたらしい楽譜の記載法で入力はやや楽に。
kewpie3score2.jpg
「Kewpie3min.h」
イントロ部分を和音がきれいになるようにちょこっとアレンジしてみた。
static const uint16_t Kewpie3min[] PROGMEM = {  // "The Parade of the Tin Soldiers" by Leon Jessel
  168, 0 ,
  RSe , g5s , g5s , g5e , g5e , e5e , e5e , f5q , RSe , g5s , g5s , g5e , g5e , C5e , C5e , d5q , RSe , g5s , g5s , g5h , d5h , g4h , RSq , g5e , g5s , g5s ,
  e5e , RSe , g5e , RSe , g5e , RSe , RSe , g5s , g5s , f5e , RSe , g5e , RSe , g5e , RSe , RSe , g5s , g5s , e5e , RSe , g5e , RSe , b5e , RSe , a5e , RSe , g5e , F5e , f5e , e5e , d5e , RSe , RSe , g5s , g5s ,
  e5e , RSe , g5e , RSe , g5e , RSe , RSe , g5s , g5s , d5e , RSe , b5e , RSe , b5e , RSe , RSe , a5s , a5s , a5e , RSe , a5e , RSe , d6e , RSe , d6e , RSe , g5q , g5s , G5s , a5s , A5s , b5e , g5e , a5e , g5e ,
  e5e , RSe , g5e , RSe , e5e , g5e , RSe , g5e , f5e , RSe , g5e , RSe , f5e , g5e , RSe , g5e , e5e , RSe , g5e , RSe , b5e , RSe  ,a5e , RSe , g5e , F5e , f5e , e5e , d5e , RSe , RSe , g5s , g5s ,
  e5e , RSe , g5e , RSe , g5e , RSe , RSe , g5s , g5s , f5e , RSe , a5e , RSe , a5e , RSe , c6e , RSe , e6e , RSe , RSq , d6e , RSe , RSq ,
//c6e , RSe , g5e , RSe , c6e , RSe , RSq ,                     // OP
  c6e , g5s , G5s , a5s , A5s , b5e , c6e , RSe , c4q ,         // ED  
  0,
  RSq , RSq , C5e , C5e , d5q , RSq , RSq , A4e , A4e , b4q , RSq , RSe , F5h , c5h , RSe , g5h , RSq ,
  RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e ,
  RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , b3e , RSe , b3e , RSe , b3e , RSe , b3e , RSe , a3e , RSe , a3e , RSe , a3e , RSe , a3e , g3q , RSq , RSh ,
  RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e ,
  RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , a3e , RSe , a3e , RSe , a3e , RSe , a3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e ,
//RSe , g3e , RSe , g3e , g3e , RSe , RSq ,                     // OP
  g3e , RSe , RSq , c4e , RSe , c3q ,                           // ED
  0,
  RSq , RSw , RSw , RSe , RSe , f5h , b4h , RSq , g4h ,
  RSe , e3e , RSe , e3e , RSe , e3e , RSe , e3e , RSe , f3e , RSe , f3e , RSe , f3e , RSe , f3e , RSe , e3e , RSe , e3e , RSe , e3e , RSe , e3e , RSe , f3e , RSe , f3e , RSe , f3e , RSe , f3e ,
  RSe , e3e , RSe , e3e , RSe , e3e , RSe , e3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , g3e , RSe , F3e , RSe , F3e , RSe , F3e , RSe , F3e , RSw ,
  RSe , e3e , RSe , e3e , RSe , e3e , RSe , e3e , RSe , f3e , RSe , f3e , RSe , f3e , RSe , f3e , RSe , e3e , RSe , e3e , RSe , e3e , RSe , e3e , RSe , f3e , RSe , f3e , RSe , f3e , RSe , f3e ,
  RSe , e3e , RSe , e3e , RSe , e3e , RSe , e3e , RSe , f3e , RSe , f3e , RSe , f3e , RSe , f3e , RSe , e3e , RSe , d3e , RSe , f3e , RSe , f3e ,
//RSe , e3e , RSe , e3e , e3e , RSe , RSq ,                     // OP
  e3e , RSe , RSq , RSe , RSe , c2q ,                           // ED
  0,
  RSq , RSw , RSw , RSe , RSe , RSe , e5h , a4h , RSe , RSh ,
  c3q , g2q , c2q , g2q , d2q , g2q , d2q , g2q , c3q , g2q , c2q , g2q , d2q , g2q , d2q , g2q ,
  c3q , g2q , c2q , g2q , d2q , g2q , d2q , g2q , a2q , d2q , F2q , d2q , g2q , RSq , RSh ,
  c3q , g2q , c3q , c3q , g2q , d2q , g2q , g2q , c3q , g2q , c3q , c3q , g2q , d2q , g2q , g2q ,
  c3q , g2q , c3q , c3q , f2q , c2q , f2q , f2q , c3q , g2q , d2q , g2q ,
//c3q , g2q , c3q , RSq ,                                       // OP
  c3e , RSe , RSq , RSq , RSq ,                                 // ED
  0, 0 };

スケッチも手直ししてみたので次回。
タグ:楽譜 音楽
nice!(0)  コメント(0) 

Digisparkで音楽演奏【楽譜編】 [JavaScript]

kewpie3score.jpg
以前につくった notes.h ですが、やっぱり楽譜から入力しづらい。大文字が多いこととアンダーバー('_')が入力しにくさの原因ではないかと考えました。
もうちょっと楽譜から入力しやすいようにしました。
変更点としては、小文字メインで、半音上がるシャープ(♯)がつくのを大文字にするのと、長さを数字ではなく英語での頭文字の小文字としました。
以下、再度楽譜のマイルール。

【マイコンで処理しやすい楽譜・音符情報を作ります。】
  • 音の高さ(音高、ピッチ)は、周波数(Hz)等ではなく、音階とオクターブで表す
  • 音の長さ(音価)は基準の最小音符の何倍かで表す
  • 一音で2byte(16bit)使用する
    • 上位8bitが音の高さ(音高)
      • 0xooの時は休符
      • 上位4ビットがオクターブ
        • 0-9まで
      • 次の4ビットが音階・スケール(ド~シの12音階で0-11)
        • 音名は、英語でCDEFGAB
        • 入力簡便化のため小文字とし、半音上げる際は大文字を使用
          • 'c','C','d','D','e','f','F','g','G','a','A','b'
        • 半音下げるのは、一音下げてから半音あげる対応で   
      • MIDIノート番号でいうとNo.13(C#0)~127(G9)まで網羅
      • C0は休符用に使用, A9, A#9, B9はMIDI番号にもないため除く
      • 音階とオクターブを分けることで12個の基本音階情報からシフト演算を用いて容易に算出できる
    • 下位8ビットが音の長さ(音価)
      • 96分音符を最小単位の1とする
        • 1-255までに各種音符の長さを入れるとすると32分音符(3)から倍全音符(192)まで入れることができる
        • 3連符には対応できるよう通常の音符は3の倍数
      • 音符の長さの表記は、英語訳の頭文字
        • 32分音符 thirty-second note
        • 16分音符 sixteenth note
        • 8分音符 eighth note
        • 4分音符 quarter note
        • 2分音符 half note
        • 全音符 whole note (breve)
        • 倍全音符 double whole note (longa)
        • 4倍全音符 4x whole note (maxima)
      • 入力簡便化のため小文字を使用する
      • 付点音符はさらに'd' (dotted) を付ける
      • 3連符用に三分の一の長さ(one third)には't'を付ける
        • 本来は3連符は3等分する前の音符の半分の長さの音符で書かれる   
      • タイによる音符の結合は、休符(長さ情報のみでできている)を加算することで可能
  • 楽譜としては、音符となるunsigned int(2byte)の情報を配列に羅列する
    • 先頭は、テンポ(♩=1~65535)を入れて、次に0で区切る
    • 1トラック内に和音は置けないため、必要な和音の分だけトラックを使用する
    • 各トラック内の終わりは0とし、つづけて次のトラック情報に入る
    • すべてのトラック情報のあとにさらに0を入れて楽譜データ終了とする

【楽譜定義のヘッダーファイルを作るjavascript】

前回はエクセルでしこしこ作りましたが、今回は修正もしやすいようにjavascriptを使用。
以下を「note2.html」として保存してブラウザで開く。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>Musical notes 2</title>
<script>
// *** twelve-tone scale ***
//   capital letter : raise a semitone. (e.g. C means C#)
const twelveTone = ['c','C','d','D','e','f','F','g','G','a','A','b'];

// *** note value (sound length) ***
const noteValue  = [
  { note: 't' , value:   3 },   // thirty-second note
  { note: 's' , value:   6 },   // sixteenth note
  { note: 'e' , value:  12 },   // eighth note
  { note: 'q' , value:  24 },   // quarter note
  { note: 'h' , value:  48 },   // half note
  { note: 'w' , value:  96 },   // whole note (breve)
  { note: 'd' , value: 192 },   // double whole note (longa)

  { note: 'sd', value:   9 },   // dotted sixteenth note
  { note: 'ed', value:  18 },   // dotted eighth note
  { note: 'qd', value:  36 },   // dotted quarter note
  { note: 'hd', value:  72 },   // dotted half note
  { note: 'wd', value: 144 },   // dotted whole note (breve)

  { note: 'tt', value:   1 },   // 1/3 of a 32nd note
  { note: 'st', value:   2 },   // 1/3 of a 16th note
  { note: 'et', value:   4 },   // 1/3 of an eighth note
  { note: 'qt', value:   8 },   // 1/3 of a quarter note
  { note: 'ht', value:  16 },   // 1/3 of a half note
  { note: 'wt', value:  32 },   // 1/3 of a whole note (breve)
  { note: 'dt', value:  64 },   // 1/3 of a double whole note (longa)
  { note: 'mt', value: 128 },   // 1/3 of a 4x whole note (maxima)
 ];

$ = function(id) { return document.getElementById(id); }

function notes() {
    let  octave, scale;
    $('main').value  = $('explanation').value;
    $('main').value += '#define MIN_NOTE  96    // 96th note (reference note)\n';
    $('main').value += '\n// Rests of various lengths (rests are just Length, so it is also for connection by Tie)\n';
    for( let nv of noteValue ) $('main').value += '#define RS' + (nv.note + '   ').slice(0,2)  + "   "  + ('   ' + nv.value).slice(-3) + '\n';
    $('main').value += '\n// combination of pitch and length\n';
    for( octave = 0; octave < 10; octave++ ) {
        for( scale = 0; scale < 12; scale++ ) {
            if( octave == 0 && scale == 0) continue;
            if( octave == 9 && scale >  8) continue;
            for( let nv of noteValue ) {
                $('main').value += '#define ' + twelveTone[scale] + octave +  (nv.note + '  ').slice(0,2)
                                +  '   (0x' + octave + scale.toString(16) + '00 | ' +  ('   ' + nv.value).slice(-3) + ')\n';
            }
        }
    }
    $('main').style.display  = 'block';
    $('dlBtn').style.display = 'inline';
}

function downloadText(fileName) {
  const blob = new Blob([$('main').value], { type: 'text/plain' });
  const aTag = document.createElement('a');
  aTag.href = URL.createObjectURL(blob);
  aTag.target = '_blank';
  aTag.download = fileName;
  aTag.click();
  URL.revokeObjectURL(aTag.href);
}
</script>
</head>
<body>
<h1>Musical notes 2</h1>
<p>Creates musical score and note information that is easy to process with a microcomputer.
<p>
<button onClick="notes()">Create a note definition data</button>
<button onClick="downloadText('note2.h')" style="display:none;" id="dlBtn">Download the header file</button>
<p>
<textarea id="explanation" disabled style="display:none;">
// ****************************************************************
//  notes2.h
// ****************************************************************
//   upper 8 bits   : pitch of a sound (0x00 : rest)
//     upper 4 bits : octaves  [0-9]
//     next  4 bits : 12 tone scale (C,C#,D,D#,E,F,F#,G,G#,A,A#,B)
//                      ['c','C','d','D','e','f','F','g','G','a','A','b']
//   lower 8 bits   : length of the sound 
//                      Let the 96th note be 1
//                      't'  =   3   thirty-second note
//                      's'  =   6   sixteenth note
//                      'e'  =  12   eighth note
//                      'q'  =  24   quarter note
//                      'h'  =  48   half note
//                      'w'  =  96   whole note (breve)
//                      'd'  = 192   double whole note (longa)
//                      'sd' =   9   dotted sixteenth note
//                      'ed' =  18   dotted eighth note
//                      'qd' =  36   dotted quarter note
//                      'hd' =  72   dotted half note
//                      'wd' = 144   dotted whole note (breve)
//                      'tt' =   1   1/3 of a 32nd note
//                      'st' =   2   1/3 of a 16th note
//                      'et' =   4   1/3 of an eighth note
//                      'qt' =   8   1/3 of a quarter note
//                      'ht' =  16   1/3 of a half note
//                      'wt' =  32   1/3 of a whole note (breve)
//                      'dt' =  64   1/3 of a double whole note (longa)
//                      'mt' = 128   1/3 of a 4x whole note (maxima)
// ****************************************************************

</textarea>
<textarea id="main" style="display:none; width:90%; height: calc( 1.2em * 25 );  line-height: 1.2;"></textarea>
</body>
</html>

再生のスケッチは後日。
nice!(0)  コメント(0) 

DigisparkのPLLとlow-pass filterとアンプと [Arduino]

上位のArduino Uno(ATmega328)にはなくて、Digispark(ATtiny85)にはあるものとして、PLL(位相同期回路: phase locked loop)があります。

まず、使用するには、、
PLLCSR(PLL Control and Status Register)
 Bit 1 - PLLE: PLL Enable はシステムクロック元としPLLが選択されているので元々1。
 Bit 2 - PCKE: PCK Enable を1にすることで、タイマー/カウンタ1のクロック元をPLLにします。
 Bit 7 - LSM: Low Speed Mode(32MHz) ですが、そのまま 0 で高速モード(64MHz)。


・注意点

★システムクロック(16/8/1MHz)に関わらず64MHz(LSM: Low Speed Mode時は32MHz)
(ただしOSCCAL (Oscillator Calibration Register)をいじるとシステムクロックと一緒に微調整はできます)

★タイマー/カウンタ1だけ
(ただしDigisparkではボードマネージャでDigistump AVR Boardsの場合でISR(TIMER1_OVF_vect)が使用されてしまっている)


・使用用途

とりあえず、高速PWMによる疑似DACかな。
64MHz / 256(8bit) = 250kHz が、キャリア周波数ということでした。
まあ、Uno(16MHz)で9bitだと 16MHz / 512(9bit) = 31.25kHz だとノイズらしいノイズは分かりませんでしたが、半分の15.625kHzだとノイズが分かりました。
あと、外部出力の際には、low-pass filterがないとアンプが壊れるよっていうのが各所に書いてありました。
low-pass filterの具体的な値の計算式は理解できなかったので、以下のサイトのPLL音声出力時の回路図を参考とさせていただきました。
PB4(OC1B)から1kΩの抵抗と、そこからGNDとの間に0.1μFのコンデンサとなっていました。

waveformgenerator.png
Technoblogy - Waveform Generation using an ATtiny85
http://www.technoblogy.com/show?QVN

とか
Technoblogy - Four Sample Player
http://www.technoblogy.com/show?2XJD

また、次のページには、PB4(OC1B)から220μFの電解コンデンサを介してスピーカとつないでありました。

Technoblogy - Tiny Synth
http://www.technoblogy.com/show?Q7H

他では、100μFだったりするのもありました。

Technoblogy - Audio Pitch Shifter
http://www.technoblogy.com/show?1L02

できあいのアンプとつないでみました。
sp_amp.jpg
そのままアンプにつなぐと、音が大きすぎて音が割れるので、回路図のとおり10kΩの半固定抵抗をつけました。



nice!(0)  コメント(0) 

Digispark関連の追加のボードマネージャのURL [Arduino]

Digispark関連の追加のボードマネージャのURL (additonal Boards Manager URLs)
addboards.png

追加したものは、以下に保存されるっぽい。

%appdata%\..\local\Arduino15\packages\
具体的には、、
C:\Users\%USERNAME%\AppData\Local\Arduino15\packages\

追加の.jsonファイルはその一つ上位のフォルダに。


★Digispark関連と、そのほか興味はあるけどまだ試していないボードの追加のボードマネージャのURL★


■ ATTinyCore by Spence Konde
Dr. Azzy's Electronics (作者のページ)
http://drazzy.com/e/
GitHub - SpenceKonde/ATTinyCore: Arduino core for ATtiny 1634, 828, x313, x4, x41, x5, x61, x7 and x8
https://github.com/SpenceKonde/ATTinyCore
ATTinyCore/Installation.md at master · SpenceKonde/ATTinyCore · GitHub
https://github.com/SpenceKonde/ATTinyCore/blob/master/Installation.md
★additonal URL:
http://drazzy.com/package_drazzy.com_index.json

ATtinyで遊ぶときに欠かせない。
これにもDigisparkが含まれている。
デフォルトだと、時間関連に対して、Timer0を使っている。(Digistumpはtimer1を使用)
DigiKeyboard.h などは使えない。
他に megaTinyCore というので tinyAVR 0/1/2-series 用のも作ってみえます。



■ kosakalab
Arduino IDE で ATtiny 他の開発 Make kosakalab
https://make.kosakalab.com/make/electronic-work/arduino-ide-dev/
★additonal URLs:
Arduino IDE に ATtiny10/13 の開発環境を組み込む
https://kimio-kosaka.github.io/bitDuino13/package_bitDuino13_index.json
Arduino IDE に ATmaga88P/328P/644P 他の開発環境を組み込む
https://kimio-kosaka.github.io/ATMegaCore/package_ATMegaCore_index.json

ATTinyCoreで対応していないATtiny13とか、足多めのATmega644Pとか。



■ Digistump AVR Boards
digisparktutorialsconnecting [Digistump Wiki]
http://digistump.com/wiki/digispark/tutorials/connecting
★additonal URL:
http://digistump.com/package_digistump_index.json

Digistump公式のかな。
Timer1を時間関連で使用されている。
DigiKeyboard.h などで簡単にHID (Human Interface Device)を作れる。



■ Improved version of Digistump avr core for Arduino
GitHub - ArminJoDigistumpArduino Improved version of Digistump avr core for Arduino
https://github.com/ArminJo/DigistumpArduino
★additonal URL:
https://raw.githubusercontent.com/ArminJo/DigistumpArduino/master/package_digistump_index.json

Digistump AVR Boardsの代用で、いろいろ改良されているらしい。
今後触ってみたいと思っていた MH-ET LIVE Tiny88 というものも、Version 1.7.4までは対応していた。



■ MH-ET LIVE Boards
GitHub - MHEtLive/MHEtLiveArduino
https://github.com/MHEtLive/MHEtLiveArduino
★additonal URL:
https://raw.githubusercontent.com/MHEtLive/arduino-boards-index/master/package_mhetlive_index.json

MH-ET LIVE Tiny88 だけ、説明なさすぎ。



■ MightyCore
GitHub - MCUdude/MightyCore: Arduino hardware package for ATmega1284, ATmega644, ATmega324, ATmega324PB, ATmega164, ATmega32, ATmega16 and ATmega8535
https://github.com/MCUdude/MightyCore
★additonal URL:
https://mcudude.github.io/MightyCore/package_MCUdude_MightyCore_index.json

大きめ、足多めのATmega使いたいとき。



■ esp8266
GitHub - esp8266/Arduino: ESP8266 core for Arduino
https://github.com/esp8266/Arduino
★additonal URL:
http://arduino.esp8266.com/stable/package_esp8266com_index.json



■ esp32
GitHub - espressif/arduino-esp32: Arduino core for the ESP32
https://github.com/espressif/arduino-esp32
★additonal URL:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json



■ Seeeduino Xiao
https://wiki.seeedstudio.com/jp/Seeeduino-XIAO/
★additonal URL:
https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json



■ Raspberry Pi Pico/RP2040
GitHub - earlephilhower/arduino-pico: Raspberry Pi Pico Arduino core, for all RP2040 boards
https://github.com/earlephilhower/arduino-pico
★additonal URL:
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json

Raspberry Pi Picoは、Arduino公式版(ボードマネージャ追加不要)とearlephilhower/arduino pico版がある。これは後者。

タグ:Digispark
nice!(0)  コメント(0) 

Digispark 16.5MHzの謎に迫る [Arduino]

Digispark は V-USBのとき、16MHzではなく16.5MHzと気持ち(3%ほど)速めの設定になっています。
USBの処理のために3%ほど速くしてくれているのだと思います。(たぶん)

そもそもATtiny85は、外部クリスタルなしでは8MHzなのですが、そこからいろいろあって16MHzや16.5MHzを作りだしているようです。
そのあたりを調べてみました。

まずfuse。
ds_fuse.png
工場出荷時と異なるのは、、

・Fuse Extended Byte
 Self-programming enabledが、1→0で自己プログラミング機能が許可されています。
 USBから書き込めるということでこれは当然。

・Fuse Low Byte
 7ビット目のCKDIV8と、3~0ビット目のCKSEL3~CKSEL0が変更されています。
 CKDIV8 は、0→1となり、システムクロックの8分周はしないということでこれも当然。
 CKSEL3~CKSEL0 を CKSEL[3:0] 0001 に設定することで、
 Clock source setting を High Frequency PLL Clock として、divided by four として、16MHz にしているようです。

つづいてRegister。
クロックに関係しそうなのは、CLKPR, PLLCSR, OSCCALです。
手持ちのDigisparkに以下のスケッチを書き込み、LEDの点灯時間を目視で確認することでこれらのレジスタの値を調べました。
#define isBitSet(byte, bit) ((byte) & (1 << (bit)))

void setup() {
    pinMode( 0, INPUT_PULLUP );   // tactile switch
    pinMode( 1, OUTPUT );         // builtin LED
}

void loop() {
    uint8_t i;
    while( digitalRead(0) );
    delay(1000);
    //0x31 OSCCAL
    for(i=0; i<8; i++) {
      digitalWrite( 1, HIGH);
      delay( isBitSet( OSCCAL, 7-i) ? 500: 100 );
      digitalWrite( 1, LOW );
      delay(500);
    }
    delay(2000);
    // 0x27 PLLCSR
    for(i=0; i<8; i++) {
      digitalWrite( 1, HIGH);
      delay( isBitSet( PLLCSR, 7-i) ? 500: 100 );
      digitalWrite( 1, LOW );
      delay(500);      
    }
    delay(2000);
    // 0x26 CLKPR
    for(i=0; i<8; i++) {
      digitalWrite( 1, HIGH);
      delay( isBitSet( CLKPR, 7-i) ? 500: 100 );
      digitalWrite( 1, LOW );
      delay(500);
    }
}

ds_reg.png
・0x26 CLKPR (Clock Prescale Register)
 CLKPS[3:0] Clock Division Factor のところで16MHz, 16.5MHz時は、分周なし(1分周), 8MHz時は2分周, 1MHz時は16分周となっていました。

・0x27 PLLCSR (PLL Control and Status Register)
 Bit 7 – LSM: Low Speed Mode(32MHz) はそのまま 0 で高速モード(64MHz)。
 Bit 2 – PCKE: PCK Enable もそのまま 0で、はタイマ/カウンタ1のクロック元はシステムクロック。
 Bit 1 – PLLE: PLL Enable は1に変更されていますが、システムクロック元としてPLLが選択されているので当然。
 Bit 0 – PLOCK: PLL Lock Detector も1に変更で、PLLが基準クロックに固定化されている、と。

・0x31 OSCCAL (Oscillator Calibration Register)
 あらかじめ工場で設定された値が自動的に入るようにできているようです。
 手持ちのDigisparkでは、
  16/8/1MHz時は、0x91(10進で145) (おそらく工場での設定値のまま)
  16.5MHz時は、0x99(10進で153)
 となっていました。
 このレジスタで3%のclock upをしていたようです。
 
タグ:Digispark
nice!(0)  コメント(0) 
前の10件 | -