制作の続きです。お古の元アンプのケースを加工します。
フロントは TONE と VOLUME 穴はそのまま再利用でき、BALANCE 穴は SPEED ボリュームに変更。電源スイッチは私の好きな自照式ロッカーSWにしました。リアは穴だらけで埋まりませんが、リアなので良しとします。
次に小物類をケースに付ける前に配線しておきます。その前に VR の軸を短くします。長いままだとツマミがパネルから浮いてしまってかっこ悪いのです。秋月で売っているVRですが、個人の制作で2重パネルにする人はあまりいないと思うので、最初から軸は短いものを売ってもらいたいです。糸鋸で切るのがちょっと面倒。
↓上のがカット後。
小物を配線。ピンヘッダを使うようになってから基板と別にできるので非常に楽です。
スピーカーもオークションで落札しました。非常に小型のものですが、CWのモニタなら十分です。
組み込み完了。ケースに余裕あり過ぎ。AC電源内蔵も考えましたが、手持ちのトランス(ACアダプタを分解したもの)を固定するのがちょっと難しくてやめました。トランスをきっちり固定できないと火事になる可能性もありますから、安全第一で。
パネル裏・表
裏側の大きい穴は Nano の USB コネクタ接続口です。USBコネクタ自体は小さくても、ケーブル側(オス)のモールドが大きいため、こんなサイズになってしまいます。でも、ケースを開けずに接続できて便利です。
これで屋根裏部屋で CW インベーダーをプレイできるようになりました。
今回も回路図は私の頭の中です。要望がありましたら紙に書きます。
スケッチは以下のとおりです。前回のメモリー付きエレキーのコードが残っていますが動作に問題はありません。
/*
wKeyerRev2-2: 2022/1/23
- Key 入力 (BTR_PIN, BTL_PIN) をプルダウンし、正論理で使うように設計したが、3.5mm ジャックの入力は GND になっているため、
負論理でないとダメなことが組み込み時に判明した。抵抗はプルアップにして、論理を逆に変更。
- 音程の VR(A1 ポート) 変更対応コード追加 toneValue
wKeyerRev2-1: 2022/1/17
- 3F で練習用に Nano を使用する版 wKeyer10 から派生
- tone() で音を出すようにした
- チャタリング防止回路なしでもそれほど問題無い
- メモリ再生ピンは GND してないと勝手に再生されてしまうので削除した
書き込みは Arduino NANO ATmega168 で行うこと。
ボード情報
* VID: 1A86
* PID: 7523
*/
//port to read
#define BT1_PIN 2 //M1 Button PD2
#define BT2_PIN 3 //M2 Button PD3
#define BT3_PIN 4 //M3 Button PD4
#define BT4_PIN 5 //M4 Button PD5
#define BTR_PIN 8 //key sw R PB0 =>PD6
#define BTL_PIN 9 //key sw L PB1 =>PD7
//port to write
#define KEY1_PIN 6 //Output1 PD6 =>PB0
#define KEY2_PIN 7 //Output2 PD7 =>PB1
#define KEY3_PIN 10 //tone() output ex. Output3 (via Photocuppler) PB2
#define LED_PIN LED_BUILTIN //PB5
#define VR_SPEED A0 //Analog VR
#define VR_TONE A1 //Analog VR
#define PWR_LED_PIN 11 //Power Led
unsigned long stime;
int speed=80;
int toneValue=530;
uint8_t u8state;
long cnt=0;
int btr_state,btl_state,bt1_state,bt2_state,bt3_state,bt4_state;
int vrValue,exVrValue;
int vrToneValue, exVrToneValue;
void setup() {
Serial.begin(9600);
pinMode(BTR_PIN, INPUT);
pinMode(BTL_PIN, INPUT);
/* pinMode(BT1_PIN, INPUT);
pinMode(BT2_PIN, INPUT);
pinMode(BT3_PIN, INPUT);
pinMode(BT4_PIN, INPUT);*/
pinMode(LED_PIN, OUTPUT);
pinMode(PWR_LED_PIN, OUTPUT);
pinMode(KEY1_PIN, OUTPUT);
pinMode(KEY2_PIN, OUTPUT);
//pinMode(KEY3_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
digitalWrite(PWR_LED_PIN, HIGH);
digitalWrite(KEY1_PIN, LOW);
digitalWrite(KEY2_PIN, LOW);
//digitalWrite(KEY3_PIN, LOW);
exVrValue=100; //初期値 0に近くない値
u8state=0;
Serial.println("Start 0117");
//setSpeed();
}
void dot() {
stime=millis();
//digitalWrite(KEY1_PIN, HIGH); digitalWrite(KEY2_PIN, HIGH); digitalWrite(KEY3_PIN, HIGH);
PORTD |= _BV(6)|_BV(7); //PORTB |= _BV(2);
tone(KEY3_PIN, toneValue);
while (millis() < speed+stime) {}
//digitalWrite(KEY1_PIN, LOW); digitalWrite(KEY2_PIN, LOW); digitalWrite(KEY3_PIN, LOW);
PORTD &= ~(_BV(6)|_BV(7)); //PORTB &= ~_BV(2);
noTone(KEY3_PIN);
}
void dash() {
stime=millis();
//digitalWrite(KEY1_PIN, HIGH); digitalWrite(KEY2_PIN, HIGH); digitalWrite(KEY3_PIN, HIGH);
PORTD |= _BV(6)|_BV(7);// PORTB |= _BV(2);
tone(KEY3_PIN, toneValue);
while (millis() < speed*3+stime) {}
//digitalWrite(KEY1_PIN, LOW); digitalWrite(KEY2_PIN, LOW); digitalWrite(KEY3_PIN, LOW);
PORTD &= ~(_BV(6)|_BV(7)); //PORTB &= ~_BV(2);
noTone(KEY3_PIN);
}
void space() {
stime=millis();
while (millis() < speed+stime) {}
}
void space3() {
stime=millis();
while (millis() < speed*3+stime) {}
}
void space4() {
stime=millis();
while (millis() < speed*4+stime) {}
}
void space5() {
stime=millis();
while (millis() < speed*5+stime) {}
}
void space7() {
stime=millis();
while (millis() < speed*7+stime) {}
}
void keyout(char ch) {
String code=cwCode[ch-'/'];
// Serial.println(ch-'/');
// Serial.println(code);
for (int i=0;i<code.length();i++) {
char ch=code.charAt(i);
if (ch=='.') dot();
if (ch=='-') dash();
if (ch==' ') space();
}
}
void invokeMem(String s) {
for (int i=0;i<s.length();i++) {
char c=s.charAt(i);
if (c==' ') {
space7();
} else {
keyout(c);
if (i != s.length()-1) space5(); //space3 is sounding short, so using space4
}
}
}
void setSpeed() {
//speed が 70 ± 20 の範囲となるようにする
vrValue = analogRead(VR_SPEED);
//Serial.println("setSpeed()");
if (abs(vrValue-exVrValue)>2) {
exVrValue=vrValue;
speed=40+vrValue/20;//25
Serial.print("speed=");Serial.print(speed);Serial.println();
}
}
void setTone() {
//tone が 200 ~ 1200 ぐらいの範囲となるようにする
vrToneValue = analogRead(VR_TONE);
//Serial.println("setSpeed()");
if (abs(vrToneValue-exVrToneValue)>2) {
exVrToneValue=vrToneValue;
toneValue=200+(1023-vrToneValue);
Serial.print("toneValue=");Serial.print(toneValue);Serial.println();
}
}
void loop() {
/* パドルが押され続けても、stime が更新されるまでは u8state は変わらないので出力状態も変わらない
* パドルが押されなくても u8state は保持されるので出力状態も変わらない
* L ->R の順で追加で押された場合、u8state=2 になるので R が勝つ
*/
cnt++;
switch( u8state ) {
case 0:
if (cnt>50000) {
setSpeed();
setTone();
cnt=0;
}
btr_state=digitalRead(BTR_PIN);
btl_state=digitalRead(BTL_PIN);
//bt1_state=digitalRead(BT1_PIN); bt2_state=digitalRead(BT2_PIN); bt3_state=digitalRead(BT3_PIN); bt4_state=digitalRead(BT4_PIN);
//u8state = PIND & (_BV(2)|_BV(3)|_BV(4)|_BV(5));
if (btr_state==LOW) u8state=64; //負論理
if (btl_state==LOW) u8state=128; //負論理
/*
if (bt1_state==HIGH) u8state=50;
if (bt2_state==HIGH) u8state=60;
if (bt3_state==HIGH) u8state=70;
if (bt4_state==HIGH) u8state=80;*/
stime=millis();
break;
case 64: //L button process (Dash)
//digitalWrite(KEY1_PIN, HIGH); digitalWrite(KEY2_PIN, HIGH); digitalWrite(KEY3_PIN, HIGH);digitalWrite(LED_PIN, HIGH);
PORTD |= _BV(6)|_BV(7); PORTB |= _BV(5);
tone(KEY3_PIN, toneValue);
u8state=65;
break;
case 65:
if (millis() > speed*3+stime) {
stime=millis();
u8state=200;
}
break;
case 128: //R button process (Dot)
//digitalWrite(KEY1_PIN, HIGH); digitalWrite(KEY2_PIN, HIGH); digitalWrite(KEY3_PIN, HIGH); digitalWrite(LED_PIN, HIGH);
PORTD |= _BV(6)|_BV(7); PORTB |= _BV(5);
tone(KEY3_PIN, toneValue);
u8state=129;
break;
case 129:
if (millis() > speed+stime) {
stime=millis();
u8state=200;
}
break;
case 200: //space process
//digitalWrite(KEY1_PIN, LOW); digitalWrite(KEY2_PIN, LOW); digitalWrite(KEY3_PIN, LOW); digitalWrite(LED_PIN, LOW);
PORTD &= ~(_BV(6)|_BV(7)); PORTB &= ~(_BV(5));
noTone(KEY3_PIN);
u8state=201;
break;
case 201:
if (millis() > speed+stime) {
u8state=0;
//setSpeed();
}
break;
case 4: //Memory 1
invokeMem(M1);
u8state=0;
break;
case 8: //Memory 2
invokeMem(M2);
u8state=0;
break;
case 16: //Memory 2
invokeMem(M3);
u8state=0;
break;
case 32: //Memory 3
invokeMem(M4);
u8state=0;
} //end switch()
}