暫くほったらかしにしていた2017/11月のトラ技のオマケ基板。お安い中華製の完成品もいくつか購入しているので、無理して組み立てる必要はないのだが、他の完成品にはないSDスロットやブザーが付いてるのでなんとなく何か実験するには良いかもということで組み立ててみた。
予想通り、老眼の私の目には少々辛い作業...途中、2箇所ほど部品を付け間違えたりして発狂寸前まで行きかけたがなんとか無事に完成。おきまりのLチカで動作確認を済ませるが頑張って作ったのにLチカだけというのはなんだか寂しい。そこで、IOの少ないチープなMCUを使うといつも悩んでしまうデバッグ用表示器でも作ってみようかなと思い立つが...でも、全てのIOを使い果たしてる場合もあるし...って、さすがにそれはどうしょうもない...と、諦めるのは普通の人。私は普通じゃない人(笑)なので諦めずにない知恵絞って考えつづけること数日...そういえば動作確認用のLEDって普通付いてるじゃん?
ということで、最初に試したのは点滅回数で数値を表現するもので下記の順序で点滅していく仕様。
1)マイナス記号…2回の超短い点滅
2)数字の10の位…長い点滅
3)数字の1の位…短い点滅
これはこれで簡易的なデバッグには使えそうな感じ。
でも、もうちょっとなにか別の方法ないのかなと、ふと、思いついてしまったのがモールス信号。そういえば、昔昔、アマ無線取得したとき一生懸命覚えた記憶があるなと少し懐かしさを感じながら、その規格を調べるためにググってみたら今どきは様々な規格がありすぎて何が正しいのかさっぱりわからない。なので、とりあえず、欧文と記号を除く和文の一部に対応してみた。(欧文、和文の切り替え規格には未対応)
【ブザーとLEDで遭難信号を出力するプログラム】
一家にひとつ、このプログラム(※1)さえあればもう安心。
さぁ、皆さんも一緒にSOSしましょう!!(笑)
※1)ESP-WROOM-32を使う必要性は全くないですがツッコミ禁止ということで。(笑)
ちなみにモールス信号の速度を変えるには、ESP32_sos.ino内の
MorseCode<> morse;
の山括弧に下記のように短い符号の長さ(ms)を設定。
MorseCode<60> morse;
省略時は80ms(一級レベルの速度より少し遅い程度?)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
#define GPIO_BOARD_LED 2 #define GPIO_BUZZER 12 #include "MorseCode.h" MorseCode<> morse; bool output = false; void setup() { pinMode(GPIO_BOARD_LED, OUTPUT); ledcAttachPin(GPIO_BUZZER, 1); ledcSetup(1, 4000, 8); // 4 kHz PWM, 8-bit resolution } void loop() { if (morse.next()) morse.printStr("SOS"); if (morse.handle() != output) { if (output = !output) { ledcWrite(1, 128); digitalWrite(GPIO_BOARD_LED, HIGH); } else { ledcWrite(1, 0); digitalWrite(GPIO_BOARD_LED, LOW); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 |
#ifndef _MORSECODE_H #define _MORSECODE_H #include <string.h> #ifdef __AVR_ARCH__ #include <avr/pgmspace.h> #else #define PROGMEM #define pgm_read_byte_near(p) *((uint8_t *)(p)) #endif static const uint8_t PROGMEM ASCII6[] = { B10000110, B11110010, B00000000, B10001100, B00000001, B00000000, B00000000, B10000000 }; static const uint8_t PROGMEM ASCII[] = { B00000000, B10101100, B01001000, B00000000, B00010010, B00000000, B01000101, B01111000, // 20-27 .!".$.&' B10110101, B10110100, B00000000, B01010101, B11001100, B10000100, B01010100, B10010000, // 28-2F ().+,-./ B11111101, B01111101, B00111101, B00011101, B00001101, B00000101, B10000101, B11000101, // 30-37 01234567 B11100101, B11110101, B11100000, B10101000, B00000000, B10001101, B00000000, B00110000, // 38-3F 89:;.=.? B01101000, B01000010, B10000100, B10100100, B10000011, B00000001, B00100100, B11000011, // 40-47 @ABCDEFG B00000100, B00000010, B01110100, B10100011, B01000100, B11000010, B10000010, B11100011, // 48-4F HIJKLMNO B01100100, B11010100, B01000011, B00000011, B10000001, B10000011, B00010100, B01100011, // 50-57 PQRSTUVW B10010100, B10110100, B11000100, B00000000, B00000000, B00000000, B00000000, B00110100 // 58-5F XYZ...._ }; static const uint8_t PROGMEM KANA6[] = { B00010010, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000, B00000000 }; static const uint8_t PROGMEM KANA[] = { B00000000, B01010000, B00000000, B00000000, B01010100, B00000000, B01110100, B00000000, // A0-A7 ・。・・、・ヲ・ B01001101, B00000000, B01100101, B00000000, B00000000, B00000000, B00000000, B00000000, // A8-AF ヰ・ヱ・・・・・ B00000000, B11011101, B01000010, B00100011, B01000101, B10111101, B01000100, B10100101, // B0-B7 ・アイウエオカキ B00010100, B10110100, B11110100, B10101101, B11010101, B11101101, B01110101, B11100100, // B8-BF クケコサシスセソ B10000010, B00100100, B01100100, B01011101, B00100101, B01000011, B10100100, B00000100, // C0-C7 タチツテトナニヌ B11010100, B00110100, B10000100, B11001101, B11000100, B00000001, B10000011, B10010100, // C8-CF ネノハヒフヘホマ B00101101, B10000001, B10001101, B10010101, B01100011, B10011101, B11000010, B00000011, // D0-D7 ミムメモヤユヨラ B11000011, B10110101, B11100011, B01010100, B10100011, B01010101, B00000010, B00110101, // D8-DF リルレロワン゛゜ }; template <uint16_t DOT = 80, uint8_t SIZE = 16> class MorseCode { private: uint16_t _start; uint16_t _nspan; uint16_t _elaps; bool _ncall; bool _output; uint8_t _mclen; uint8_t _mcbit; uint8_t _index; uint8_t _count; uint8_t _buffer[SIZE]; protected: bool ismorsechar(uint8_t c) { if ((c >= 0x61) && (c <= 0x7a)) c -= 0x20; if ((c >= 0x20) && (c <= 0x5F)) { c -= 0x20; _mcbit = pgm_read_byte_near(ASCII + c); if (c == ('$' - 0x20)) _mclen = 7; else if (pgm_read_byte_near(ASCII6 + (c >> 3)) & (1 << (c & 0x07))) _mclen = 6; else _mclen = _mcbit & 0x07; return _mclen != 0; } else if ((c >= 0xA0) && (c <= 0xDF)) { c -= 0xA0; _mcbit = pgm_read_byte_near(KANA + c); if (pgm_read_byte_near(KANA6 + (c >> 3)) & (1 << (c & 0x07))) _mclen = 6; else _mclen = _mcbit & 0x07; return _mclen != 0; } return false; } uint8_t code(bool space) { bool brk = false; while (_index < _count) { uint8_t c = _buffer[_index++]; if (c == ' ') brk = space; else if (ismorsechar(c)) { if (brk) { --_index; _mclen = 0; return 2; } return 1; } } return _index = _count = 0; } void signal() { _output = true; _nspan = (_mcbit & 0x80 ? DOT * 3 : DOT); _mcbit <<= 1; _mclen--; } public: MorseCode() { _nspan = 0; start(); } void printStr(char *str) { if (_index == 0) { if ((_count = strlen(str)) > SIZE) _count = SIZE; memcpy(_buffer, str, _count); } } template <typename T> void printInt(T value) { if (_index == 0) { uint8_t i = (value < 0); uint8_t j = 0; if (i) { value = -value; _buffer[j++] = '-'; } do _buffer[j++] = (uint8_t)((value % 10) | '0'); while (value /= 10); _count = j--; while (i < j) { uint8_t x = _buffer[i]; _buffer[i++] = _buffer[j]; _buffer[j--] = x; } } } void start() { _ncall = false; _output = false; _mclen = 0; _index = 0; _count = 0; } void stop() { if (_index != (uint8_t)-1) { if (_index) _nspan = DOT * 7; _index = (uint8_t)-1; _output = false; } } bool next() { uint16_t now = (uint16_t)millis(); _ncall = true; if ((_elaps = now - _start) >= _nspan) { if (_nspan) _start += _nspan; else _start = now; return _index == 0; } return false; } bool handle() { if (!_ncall) next(); _ncall = false; if (_elaps >= _nspan) { if (!_output) { _nspan = 0; if (_index != (uint8_t)-1) { if (_mclen) signal(); else if (code(false)) signal(); } } else { _output = false; if (_mclen) _nspan = DOT; // continue else if (code(true) == 1) _nspan = DOT * 3; // next code else _nspan = DOT * 7; // end of word } } return _output; } }; #endif // _MORSECODE_H |