亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

XBee 对讲机

组件和用品

金发姑娘类比
目前仍为原型,但可以使用 MCP4822 DAC、麦克风放大器和耳机放大器重新创建功能,与 Arduino Uno 一起。
× 1
MAX9744
× 1
MAX9814
× 1
MCP4921 DAC
× 1
Arduino UNO
× 1
Arduino 无线扩展板 (Xbee)
× 1

关于这个项目

我正在构建一个基于 AVR ATmega1284p MCU 的高级 Arduino 克隆,具有一些特殊功能,包括 12 位 DAC MCP4822、耳机放大器、2x SPI 存储器(SRAM、EEPROM)和 SD 卡。模拟输出有许多实际应用,但由于 Arduino 平台没有集成 DAC 功能,因此很少有已发布的模拟信号应用。对讲机是将数字和模拟结合起来制作一个简单但非常有用的项目的一个例子。

Goldilocks Analogue - Prototype 3

实际的对讲机功能实际上只有几行代码,但它建立在模拟输入(采样)、SPI 总线上到 MCP4822 DAC 的模拟输出、采样定时例程和 XBee 数字无线电平台的基础上。让我们从顶部开始,然后逐层向下挖掘。

XBee 电台

我正在使用 XBee Pro S2B 无线电,配置为点对点通信。对于 XBee Pro,需要将一个无线电配置为协调器,另一个配置为路由器。网上有配置指南。

我已将无线电配置为在发送数据包之前等待最大字符间时间,这意味着只有在数据包已满(84 字节)时才会设置数据包。这使无线电吞吐量最大化。原始吞吐量为 250 kbit/s,但实际用户数据速率限于约 32 kbit/s。这会影响采样率,从而影响可传输的语音质量。

使用 8 位样本,我发现大约 3 kHz 的采样产生的数据量与不压缩传输的数据量差不多。我要为另一个项目进行压缩。

XBee 无线电配置为 AT 模式,作为两个端点之间的透明串行管道。这是通过数字无线电连接两个设备的最简单方法。它让我可以使用电线进行简单的测试,然后再担心无线电平台是否正常工作。

查看逻辑分析仪的跟踪,我们可以看到 XBee 数据包到达串行端口的(紫色)Rx 线。接收到的数据包数据存储在环形缓冲区中,并以恒定速率播放。我在接收环形缓冲区中允许最多 255 个字节,这已经足够了,因为 XBee 数据包大小为 84 个字节。

要传输到另一个设备的样本在(蓝色)Tx 线上传输,或多或少在每个采样周期中传输,即使它们在传输之前已被缓冲。 XBee 无线电将这些字节缓冲最多 0xFF 符号间周期(配置),并且仅在有完整数据包时才将数据包传输到另一个端点。

采样率

查看传输链路的比特预算,我们需要计算可以传输多少数据而不会使 XBee 无线电平台过载,并不会导致样本丢失。由于我们没有公开压缩语音样本,我们有 8 位样本乘以 3,000 Hz 采样或 24 kbit/s 进行传输。这似乎工作得很好。我尝试过 4 kHz 采样,但这太接近理论最大值了,而且效果不太好。

查看逻辑分析器,我们可以看到从 0x7E 和 0x7C 开始的字节数据包到达 Rx 线路。麦克风放大器和 DAC 输出都偏置在 0x7F(FF) 附近,因此我们可以看出这里捕获和传输的信号电平非常低。显示的采样率为 3,000 Hz。

样品处理

我在一个输出上放了一个“ping”,以便在处理采样中断时进行捕获(黄色)。我们可以看到,相对于可用的总时间,此应用程序在中断处理上花费的时间非常少。可能可以实现某种数据压缩。

在采样中断期间,有两个主要活动,生成音频输出,通过将样本放置到 DAC,然后读取 ADC 以捕获音频样本并将其传输到 USART 缓冲区。

这是由audioCodec_dsp函数完成的,该函数是从定时器中断中的代码调用的。

我正在使用 AVR 8 位 Timer0 通过触发中断来生成常规采样间隔。通过使用标准音频的二进制倍数的 MCU FCPU 频率,我们可以仅使用 8 位定时器和 64 的时钟预分频器来生成准确的再现采样率。要生成奇音频,如 44,100 Hz,16位 Timer1 可用于获得足够的精度,而无需时钟预分频器。

ATmega1284p ADC 设置为自由运行模式,并按比例缩小至 192 kHz。虽然这接近为 ATmega ADC 记录的最大采集速度,但仍符合 8 位样本的规范。

这个中断需要 14 us 才能完成,相对于我们每个采样周期的 333 us 来说非常短。这让我们有充足的时间进行其他处理,例如运行用户界面或进一步的音频处理。

SPI 交易

在最后的细节级别,我们可以看到实际的 SPI 事务,以将传入的样本输出到 MCP4822 DAC。

由于我在使用标准 SPI 总线的 Goldilocks Analogue Prototype 2 上构建了这个应用程序,所以事务是正常的。我后来的原型是在 ATmega1284p 的 USART 1 上使用主 SPI 模式,它通过双缓冲稍微加速 SPI 事务,并释放正常的 SPI 总线以同时读取或写入 SD 卡或 SPI 内存,用于音频流。在对讲机应用程序中,不需要捕获音频,因此使用旧原型和普通 SPI 总线没有任何缺点。

总结

使用一些预先存在的工具和几行代码,就可以快速构建一个数字加密的对讲机,能够传达(可理解,但不是高质量的)语音。而且,未来不会有 CB 卡车司机会倾听家人的谈话。

这是将基于 MAX9814 的麦克风输入添加到 Goldilocks Analogue 的测试。我将修改 Prototype 3 并添加麦克风放大电路以支持需要音频输入的应用,例如这个对讲机示例、变声器或声控音乐合成器。

两个带有 XBee 收音机和麦克风放大器的 Goldilocks 模拟原型。

我还在以 24.576 MHz 的增加频率运行 ATmega1284p 设备,超过 20 MHz 的标准速率。这个特定频率允许非常精确地再现从 48 kHz 到 4 kHz(甚至低到 1,500 Hz)的音频样本。在生成合成音乐时,每个采样周期的额外 MCU 时钟周期非常受欢迎。

像往常一样在 Sourceforge AVR freeRTOS 上编写代码 另外,在 SeeedStudio 中呼唤 Shuyang,他的 OPL 很棒,并且是许多组件和 PCB 的来源。


代码

  • 代码
  • 代码
  • 代码
代码C/C++
void audioCodec_dsp(uint16_t * ch_A, uint16_t * ch_B){ int16_t xn; uint8_t cn; /*----- Audio Rx -----*/ /* 从环形缓冲区中获取下一个字符。 */ if( ringBuffer_IsEmpty( (ringBuffer_t*) &(xSerialPort.xRxedChars) ) ) { cn =0x80 ^ 0x55; // 将 A 律归零信号放在输出上。 } else if (ringBuffer_GetCount( &(xSerialPort.xRxedChars) )> (portSERIAL_BUFFER_RX>>1) ) // 如果缓冲区超过一半。 { cn =ringBuffer_Pop( (ringBuffer_t*) &(xSerialPort.xRxedChars) ); // 弹出两个样本以赶上,丢弃第一个。 cn =ringBuffer_Pop((ringBuffer_t*) &(xSerialPort.xRxedChars)); } else { cn =ringBuffer_Pop( (ringBuffer_t*) &(xSerialPort.xRxedChars) ); // 弹出一个样本 } alaw_expand1(&cn, &xn); // 展开 A 律压缩 *ch_A =*ch_B =(uint16_t)(xn + 0x7fff); // 将信号移动到正值,在 A 和 B 通道上输出信号。 /*----- 音频传输 -----*/ AudioCodec_ADC( &mod7_value.u16 ); // 样本左对齐 10 位。 xn =mod7_value.u16 - 0x7fe0; // 通过减去 1/2 10 位范围将样本居中到 0。 IIRFilter( &tx_filter, &xn); // 过滤传输的样本序列 alaw_compress1(&xn, &cn); // 使用 A-Law 压缩 xSerialPutChar( &xSerialPort, cn); // 传输样本}
代码C/C++
ISR(TIMER0_COMPA_vect) __attribute__ ((hot, flatten));ISR(TIMER0_COMPA_vect){#if defined(DEBUG_PING) // 开始标记 - 检查中断的开始 - 仅用于调试(黄色跟踪) PORTD |=_BV( PORTD7); // Ping IO line.#endif // MCP4822 数据传输例程 // 将数据移动到 MCP4822 - 首先完成以保持规律性(减少抖动)。 DAC_out (ch_A_ptr, ch_B_ptr); // 音频处理例程 - 对输入进行任何需要的处理 - 为下一个样本准备输出。 // 触发作为回调函数的全局音频处理程序(如果已设置)。 if (audioHandler!=NULL) audioHandler(ch_A_ptr, ch_B_ptr);#if defined(DEBUG_PING) // 结束标记 - 检查中断结束 - 仅用于调试(黄色跟踪) PORTD &=~_BV(PORTD7);#endif} 
代码C/C++
void DAC_out(const uint16_t * ch_A, const uint16_t * ch_B){ DAC_command_t write; if (ch_A !=NULL) { write.value.u16 =(*ch_A)>> 4; write.value.u8[1] |=CH_A_OUT; } else // ch_A 为NULL 所以我们关闭DAC { write.value.u8[1] =CH_A_OFF; } SPI_PORT_SS_DAC &=~SPI_BIT_SS_DAC; // 将 SS 拉低以选择 Goldilocks 模拟 DAC。 SPDR =write.value.u8[1]; // 开始传输 ch_A。而 (!(SPSR &_BV(SPIF))); SPDR =write.value.u8[0]; // 继续传输ch_A。 if (ch_B !=NULL) // 在我们进行 ch_A 传输时开始处理 ch_B { write.value.u16 =(*ch_B)>> 4; write.value.u8[1] |=CH_B_OUT; } else // ch_B 为 NULL 所以我们关闭 DAC { write.value.u8[1] =CH_B_OFF; } while (!(SPSR &_BV(SPIF))); // 检查我们已经完成了 ch_A。 SPI_PORT_SS_DAC |=SPI_BIT_SS_DAC; // 将 SS 拉高以取消选择 Goldilocks 模拟 DAC,并将值锁存到 DAC。 SPI_PORT_SS_DAC &=~SPI_BIT_SS_DAC; // 将 SS 拉低以选择 Goldilocks 模拟 DAC。 SPDR =write.value.u8[1]; // 开始传输 ch_B。而 (!(SPSR &_BV(SPIF))); SPDR =write.value.u8[0]; // 继续传输ch_B。而 (!(SPSR &_BV(SPIF))); // 检查我们已经完成了 ch_B。 SPI_PORT_SS_DAC |=SPI_BIT_SS_DAC; // 将 SS 拉高以取消选择 Goldilocks 模拟 DAC,并将值锁存到 DAC。}
Sourceforge 上的 AVRfreeRTOS
freeRTOS 的 AVR 移植库,包括本项目使用的 DAC.h 和 Analogue 测试文件。请不要使用链接的 github 库。去 sourceforge 获取最新代码。https://sourceforge.net/projects/avrfreertos /https://github.com/feilipu/avrfreertos

示意图

这不是绝对正确的,因为它使用的是 MCP4725 DAC (I2C) 而不是 MCP4822 DAC (SPI),但 Fritzing 没有合适的 Adafruit 分线板。

此外,它仅在一个方向上绘制......(除了相互连接的 Rx 和 Tx)。
XBee 板只是替换了连接 Rx 和 Tx 的两根电线。任何可以携带足够数据的无线电设备都可以工作。 DAC 输出和耳机放大器的原理图。
话筒输入放大器将在原型 4 上添加。

制造工艺

  1. 什么是 VMC 加工?
  2. 高产量瑞士加工的注意事项
  3. CNC 原型制作指南
  4. 了解轴制造过程
  5. 什么是不锈钢钝化?
  6. 使用一个 GPIO 引脚读取模拟传感器
  7. 使用 MCP3008 的 Raspberry Pi 上的模拟传感器
  8. 如何使用 DAC 和定制 PCB 生成高精度波形
  9. 带有湿度传感器的 Win10 IOT 灌溉控制器
  10. 模拟测量的价值
  11. 在示波器上画任何东西
  12. 信号电路用屏蔽电缆(第 2 部分)