莫尔斯电码收发器
组件和用品
| × | 2 | ||||
| × | 2 | ||||
| × | 1 | ||||
| × | 1 |
关于这个项目
我今天正在教授一门关于通信系统的课程,并希望我的学生通过可视化和体验来学习。我们做了一些实验,从石器时代开始,了解交流的必要性以及语言和语法的含义,什么是可靠的交流、信号、消息等。
在讨论所有这些东西的同时,我们达到了要定义我们自己的视觉交流语言的地步,于是我们设计了摩尔斯电码!
很明显,学习摩尔斯电码对我们每个人来说都是一项乏味的任务,因此我们需要一台机器。因此,我们决定编写一个小程序,可以将给定的字符串编码为等效的莫尔斯电码,以及另一个可以为给定的莫尔斯电码流返回字符串的解码器。
为了找到一个字符的摩尔斯电码,我参考了下表 –
要将莫尔斯电码转换为等效字符,可以将其组织成如下所示的二叉树。每个“点”移动到左子树,“破折号”移动到右子树。
这使我能够快速将字符串编码为相应的莫尔斯电码,反之亦然。
我用 C# 写了一个程序作为 PoC
图>
输出
Hello World..... .-.. .-.. --- .-- --- .-. .-.. -..
但是,由于必须在两方之间进行通信,因此我想将此编码的莫尔斯电码传输到另一台设备并在那里对其进行解码。
我用两块 Arduino 板搭建了一个发射器和一个接收器。
在发射器板上,我连接了一个激光二极管 来自凯斯。容易获得和便宜的设备。对于我工作的距离,3v输入已经绰绰有余了,但是在5v的情况下,我可以看到激光至少达到200m。
我的发射器连接到带有串行接口的计算机(通过 USB)。它逐个字符读取串行端口上的任何数据。找到字符的等效莫尔斯电码并生成“点”和“破折号”光流。
我创建了一个 50 毫秒的脉冲,其中每个“点”是 50 毫秒的光束,而“破折号”是 150 毫秒的光束。每个“点”和“破折号”都被 50 毫秒的静音隔开。每个字符之后是另外 100 毫秒的静音。
发射器代码
const char* MorseTable[] ={ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 空格, !, ", #, $, %, &, ' NULL, "-. -.--", ".-..-.", NULL, NULL, NULL, NULL, ".----.", // ( ) * + , - . / “-.--.”, “-。 - 。-“, 空值, ”。-。-。”, ” - .. - ”, ”-....-”, ”。-。-。-”, ”-.. -.", // 0 1 2 3 4 5 6 7 "-----", ".----", "..---", "...--", "... .-", ".....", "-....", "--...", // 8 9 :; <=> ? "---..", "--- -.", "---...", "-.-.-.", NULL, "-...-", NULL, "..--..", //@ABCDEFG ".- -.-.", ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", // HIJKLMNO “....”、“..”、“.---”、“-.-”、“.-..”、“--”、“-.”、“---”、 / / PQRSTUVW “.--.”、“--.-”、“.-.”、“...”、“-”、“..-”、“...-”、“.--” , // XYZ [ \ ] ^ _ “-..-”、“-.--”、“-- .. “NULL,NULL,NULL,NULL,” .. - .-” //“ABCDEFG NULL, ”.-“, ”-...“, ”-.-“,“ - .. ", ".", "..-.", "--.", // hijklmno “....”, “..”, “.---”, “-.-”, “.- ..", "--", "-.", "---", // pqrstuvw ".--.", "--.-", ".-.", "...", " -", "..-", "...-", ".--", // xyz { | } ~ DEL "-..-", "-.--", "--..", NULL, NULL, NULL, NULL, NULL, };int dotLength =50;int dashLength =dotLength*3;void setup () { // 把你的设置代码放在这里,运行一次:pinMode(13, OUTPUT); Serial.begin(9600);}void loop() { char ch; if(Serial.available()){ ch =Serial.read(); flashDashDot(MorseTable[ch]);延迟(点长*2); }}void flashDashDot(const char * morseCode){ int i =0; while(morseCode[i] !=0) { if(morseCode[i] =='.'){ dot(); } else if (morseCode[i] =='-'){ dash(); i++; }}void dot(){digitalWrite(13, HIGH);延迟(点长度);数字写入(13,低);延迟(点长度);}空破折号(){ 数字写入(13,高);延迟(dashLength);数字写入(13,低);延迟(点长度);}
在接收器 Arduino 板上,我连接了一个 LDR , 压电蜂鸣器 和一个 LED . LED 和蜂鸣器是多余的,只是它们提供音频和视频反馈,看到一切正常的感觉真好😉
我的接收器还连接到计算机以读取生成的字符串字符。
在设备上,在一个循环中,我读取任何光线照射到连接到模拟端口 4 的 LDR。我用长管封装它以使其免受任何环境光的影响。当来自我的激光二极管的光照射到这个 LDR 时,结果值变高,我打开扬声器并打开。当它下降时,我打开扬声器并关闭。
我正在计算光束的长度以确定它是“点”还是“破折号”。考虑到所有延迟,我的 16MHz Atmel 处理器上的脉冲达到了大约 400 个周期。
接收者代码
//摩尔斯电码二叉树// 2n+1 处的左孩子// 2n+2 处的右孩子// <.|->// .E -T// .I -A .N - M//const char MorseTree[] ={'\0','E', 'T', 'I', 'A', 'N', 'M', 'S', 'U', 'R' , 'W', 'D', 'K', 'G', 'O', 'H', 'V', 'F', 'U', 'L', 'A', 'P', ' J', 'B', ' '3'、'\0'、'\0'、'\0'、'2'、'\0'、 '\0'、'+'、'\0'、'\0'、'\0 ','\0','1','6', '=', '/', '\0','\0','\0','(', '\0','7' , '\0','\0','\0','8','\0','9','0','\0', ','\'\0 0','\0','\0','\0','\0','\0', '\0','\0','\0','?','_' , '\0','\0','\0', '\0','"','\0','\0','.','\0','\0',' \0', '\0','@','\0','\0','\0','\0','\0','\0', ' ','\0','\0','\0','\0','\0','\0', '\0',';', '!', '\0',')', '\0','\0','\0', '\0','\0',',' , '\0','\0','\0','\0',':', '\0','\0','\0','\0','\0', '\0','\0' };int val =0; // 用于存储 LDRint ctrHigh =0;int ctrLow =0;int codePtr =0;int dotLen =400;void setup(){ Serial.begin(9600);// 开始串行连接 Serial 的变量.print(codePtr);}void loop(){ val =analogRead(4); if (val>=10) { ctrHigh++; ctrLow =0;数字写入(13,高);音调(9, 1000); } else { ctrLow++; if ((ctrHigh>=dotLen) &&(ctrHigh =dotLen * 2) { Serial.print("-"); codePtr =(2*codePtr) + 2; } else { if(ctrLow ==dotLen*2){ Serial.print(MorseTree[codePtr]);代码点 =0; } } ctrHigh =0;数字写入(13,低);无音(9); }}
接收器输出....HE-..L.-..L---O.--W---O.-.R.-..L-..D-。 -.--!
代码
- 发射器
- 接收器
发射器Arduino
发送器代码const char* MorseTable[] ={ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 空格, !, ", #, $, %, &, ' NULL, "-.- .--", ".-..-.", NULL, NULL, NULL, NULL, ".----.", // ( ) * + , - . / "-.--.", " -。 - 。-“, 空值, ”。-。-。”, ” - .. - ”, ”-....-”, ”。-。-。-”, ”-..- .", // 0 1 2 3 4 5 6 7 "-----", ".----", "..---", "...--", ".... -", ".....", "-....", "--...", // 8 9 :; <=> ? "---..", "---- .", "---...", "-.-.-.", NULL, "-...-", NULL, "..--..", //@ABCDEFG ".-- .-.", ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", // HIJKLMNO "..", "..", ".---", "-.-", ".-..", "--", "-.", "---", // PQRSTUVW ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", // XYZ [ \ ] ^ _ "-..-", "-.--", "--..", NULL, NULL, NULL, NULL, "..--.-", // ' abcdefg NULL, ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", // hijklmn o "..", "..", ".---", "-.-", ".-..", "--", "-.", "---", / / pqrstuvw ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--" , // xyz { | } ~ DEL "-..-", "-.--", "--..", NULL, NULL, NULL, NULL, NULL, };int dotLength =50;int dashLength =dotLength*3;void setup () { // 把你的设置代码放在这里,运行一次:pinMode(13, OUTPUT); Serial.begin(9600);}void loop() { char ch; if(Serial.available()){ ch =Serial.read(); flashDashDot(MorseTable[ch]);延迟(点长*2); }}void flashDashDot(const char * morseCode){ int i =0; while(morseCode[i] !=0) { if(morseCode[i] =='.'){ dot(); } else if (morseCode[i] =='-'){ dash();我++; }}void dot(){ digitalWrite(13, HIGH);延迟(点长度);数字写入(13,低);延迟(dotLength);}无效破折号(){digitalWrite(13,高);延迟(dashLength);数字写入(13,低);延迟(点长度);}
接收器Arduino
接收器代码//摩尔斯电码二叉树// 2n+1处的左孩子// 2n+2处的右孩子// <.|->// .E -T// .I -A .N -M //const char MorseTree[] ={'\0','E', 'T', 'I', 'A', 'N', 'M', 'S', 'U', 'R', “W”、“D”、“K”、“G”、“O”、“H”、“V”、“F”、“U”、“L”、“A”、“P”、“J” ', 'B', 'X', 'C', 'Y', 'Z', 'Q', '\0','\0','5', '4', '\0',' 3'、'\0'、'\0'、'\0'、'2'、'\0'、'\0'、'+'、'\0'、'\0'、'\0' ,'\0','1','6','=','/','\0','\0','\0','(','\0','7', '\0','\0','\0','8','\0','9','0','\0','\0','\0','\0 ','\0','\0','\0','\0','\0','\0','\0','\0','?','_', '\0','\0','\0','\0','"','\0','\0','.','\0','\0','\ 0'、'\0'、'@'、'\0'、'\0'、'\0'、'\0'、'\0'、'\0'、'-'、'\0' ,'\0','\0','\0','\0','\0','\0','\0',';','!','\0',' )', '\0','\0','\0','\0','\0',',','\0','\0','\0','\0 ',':', '\0','\0','\0','\0','\0','\0','\0' };int val =0; // A用于存储 LDRint ctrHigh =0;int ctrLow =0;int codePtr =0;int dotLen =400;void setup(){ Serial.begin(9600);// 开始串行连接 Serial.print(代码指针); }void loop(){ val =analogRead(4);如果 (val>=10) { ctrHigh++; ctrLow =0;数字写入(13,高);音调(9, 1000); } else { ctrLow++; if ((ctrHigh>=dotLen) &&(ctrHigh=dotLen * 2) { Serial.print("-"); codePtr =(2*codePtr) + 2; } else { if(ctrLow ==dotLen*2){ Serial.print(MorseTree[codePtr]);代码点 =0; } } ctrHigh =0;数字写入(13,低);无音(9); }}
示意图
莫尔斯电码接收器电路 morsereceiver_1JpG6jZ6yv.fzz摩斯电码发送器电路 morsetransmitter_sOKvrIbOv3.fzz制造工艺