It turns out that SoftwareSerial is not only expectably slow, but also causes the board to freeze spontaneously for some reason.
Since there are 2 UART blocks available in the PIC, lets switch to HardwareSerial. The second UART on the DP32 chip (PIC32MX250F128B) is on the PPS pins for RB14 and RA1. So we only need to move one pin, HC05/RXD from 18/RA4 to 7/RB14:
The updated pin assignment is this:
Usage Pin (Arduino/PIC) Notes
------------------------------------------------------------------ REF 0/RB5 AM2303 1/RB7 BMP180 2/RB8 all I2C devices - not just BMP any more BMP180 3/RB9 all I2C devices - not just BMP any more USB+ 4/RB10 USB- 5/RB11 6/RB13 HC05/RXD 7/RB14 8/RB15 9/RA0 HC05/TXD 10/RA1 MEAS1 11/RB0 LED4 12/RB1 LED3 MEAS2 13/RB2 LED2 MEAS3 14/RB3 LED1 CLOCK 15/RA2 16/RA3 HC05/EN 17/RB4 18/RA4And then we need a software update.
Serial.println() is a blocking call and the hardware FIFO buffer is only 8 bytes deep, so if we send the whole data string at once we will wait until the transfer is complete instead of being able to handle the stream to the USB serial connection. The default rate of the HC05 is pretty slow, but regardless of its' speed, we don't want to block on the FIFO. The solution is as follows:
1. declare a buffer for the current data. If new data is available before this buffer has been transmitted, we skip the new sample
2. write a function that takes characters from the buffer and puts it into any available space in the FIFO, but does not block
3. Call that function frequently
For 1,
#include <CircularBuffer.h>[...]CircularBuffer<char> bluetoothBuffer(300); // make some space for hardware accelerated output[...]buffer[offset15-1]=0; // terminate message buffer Serial.println(buffer); if (0==bluetoothBuffer.available()) { for (int i=0;i<strlen(buffer);i++) bluetoothBuffer.write(buffer[i]); bluetoothBuffer.write('\r'); bluetoothBuffer.write('\n'); } // update queue if ((FIFO_SIZE-1)==tail) // check for wrap around tail = 0; // update tail location else tail = tail +1; // update tail location }[...]For 2,
void SendBluetoothData() { // direct to hardware FIFO if (bluetoothBuffer.available()) { if (U2STAbits.UTXBF == 0) { U2TXREG = bluetoothBuffer.read(); } } }this part was quite frustrating to get right. Thanks to Matt at UECIDE.org:
http://www.uecide.org/forum/viewtopic.php?f=13&t=685&sid=884bd83863c9acc2932434a61170895a
For 3,
void convertToAscii( INT64 value,int offset)// constant time version of string conversion. For speed, not all are considered// with 15 divisions by 10, and at 10 MHz that is about 30 years of continuous operation// 64 bits can be done with 19 divisions{ int i; SendBluetoothData(); // needs to be called periodically, so I am doing it in this frequently run routine if (value<0) { buffer[0+offset]='-'; value = -value; } else { buffer[0+offset]='+'; } for(i=numbersize-2; i>=1;i--) { buffer[i+offset] = (value % 10) +'0'; value = value / 10; } buffer[numbersize-1+offset]= ' '; SendBluetoothData(); // needs to be called periodically, so I am doing it in this frequently run routine}[...]void loop() { sensorCounter++; // cycle through the different sensors SendBluetoothData(); if (head != tail) // only send a new data packet if the queue is not empty; probably superfluous since serial.println blocks :/ {[...]That works quite well, but I should probably make the data transfer interrupt driven in the future....