My friend (seriously it’s not me I’ve got my own project) is trying to make a wireless mic using a pair of zigbees and pair of arduinos. Right now he is reading the builtin ADC sending that via serial to the zigbee to pass to the other zigbee then to the arduino which is using an SPI connection to write to a digital pot (the same model from the example code in the arduino IDE) which will output to a speaker. After spending way too much time helping him with code, and learning to count in binary, the system is still only able to transmit taps on the mic at best. I’m sure there are better ways to do a wireless mic, but that’s beside the point.
Without chaging the hardware, what are some code based improvements that can be made to improve the performance of the system? Already my thought is to increase the baud rate on the serial comm but how high? I’ve also told him about doing some basic DSP in the arduino (simple amplifier 1x in 2x out) but that was a very single sided conversation.
The data bandwidth of XBees are rather low. you could get away with up to 115.2 kBaud if not sent continuously, 57.6 kBaud should work with a continuous data flow.
XBees also packetize the data so the data is sent bursts over the RF link. So this may require the code in the receiving arduino to buffer and re-time the data out to the the DAC.
Are you doing 8bit ADC sampling? If so then at 57.6 kBaud, 7200 bytes can be sent in one second.
If you are having problems then break the project into parts and find the solution for each part, then join the parts together. I see this project as four parts:
1- output audio data to a DAC. Create data on your PC and send it to the arduino through the serial port to the DAC.
2- Input audio to the ADC. This time send the audio data from the arduino to the PC. The data can be graphed in Excel to check that it represents the audio input as seen on an O’scope.
3- The communication link between the arduinos. Get the data communication working without the XBees first. Connect the UART lines of the two arduinos together and get the ADC to DAC working.
4- The RF link. Once the about 3 parts work at a reasonable Buad rate then connect in the XBees.
Trying to do all four at once just increases the difficulty as there could (usually is) be more than one problem to solve.
I just completed this similar project but using an MSP430.
I used an ADPCM encoding sampling at 8 kHz. The ADC is 12-bit and the ADPCM allows the compression down to 4-bit.
Therefore, I managed to cramped 2 samples into 1 byte. So, we need to send 4000 bytes in 1 second.
It was working if I used serial connection without the XBee ( I get voice quality).
I was running at 115200 bps on the serial.
Moving on to XBee it fails as I think the XBee has an internal buffer that is quite small (~128 bytes). I even use CTS flow control in this case, but it couldn’t work.
115.2kBaud can be a problem with XBees for two reasons:
1- They can not maintain a continuous data flow at this rate over the RF link due to overhead and ACKs.
2- The base clock frequency can not be accurately divided to 115.2kBaud therefore there is a bit time error. One way around this problem is sending data to the XBee with 2 STOP bits. This allows the UART time to re-sync to the next START bit.
Probably you play audio on reception and that’s wrong. First of all if there is a way in xbee to send packets directly without serialization and acknowledgement - use it.
Then, depending on packet size choose you timeframe. In voip usually something like 30ms or 20ms used. So you send audio in 20ms frames, that’s 160 bytes of 8-bit 8khz audio.
Remember about sending raw packets? If your packet is lost you don’t want it to be retransmitted, if you scrap 20ms of audio it won’t hurt anybody.
Ok, so sending side spits 160 bytes each 20ms.
Now, receiving side. Make 20ms interval timer. And send 160 bytes of audio to speakers each 20ms.
Probably buffering single packet will be enough. This means that when you have no data to play, wait for next packet AND DO NOT PLAY it. Yep store it and wait for next one and only start playing audio again when you got it. This way you always will have something to play if clocks of both devices running approximately with same speed.
Sometimes it will get short of data anyway and this will cause short pause but that’s not a problem. Some systems replay previous packet when they have nothing to play, some just go with silence. If you get short of data often or you get excess packets and just dropping them is noticeable increase buffer size.