Here is a problem I discovered with my (complex) Oscilloscope sketch.
http://www.mccauslandcenter.sc.edu/CRNL/tools/oscilloscope
but it is more easily demonstrated in this simple demo where the Teensy3 can send data to processing
http://www.mccauslandcenter.sc.edu/CRNL/sw/oscilloscope/bt_test.zip
In fact, you do not even need processing, as the Teensy freezes up (the light stops blinking) when you upload a sketch where
gSampleHz > 0 (interrupts running)
gBytesPerSample > 8 (large packets)
and "#define ENABLE_SERIAL1" UNcommented.
You do not even need a serial device connected to Serial1 to observe this problem. On my OSX computer, setting gSampleHz = 0 (e.g. no interrupts) I am able to transfer several thousand samples per second with either 8 or 10 bytes per sample, and with gSampleHz = 1000 and gBytesPerSample=8 I can send precisely 1kHz of 8 bit samples with either the wired or wireless. However, with gSampleHz = 100; and gBytesPerSample = 10; the system locks up. I can then comment "#define ENABLE_SERIAL1" to read "//#define ENABLE_SERIAL1"" and the Teensy will happily send 10 bytes per sample at 100 Hz (but only on the wired connection).
Since the program locks up with or without my JY_MCU attached, it seems to be independent of the serial device.
I know this is appears a pretty obscure bug, and in general the T3 is a terrific platform. However, this one has really puzzled me. I have tried changing the interrupt timer to 0,1,2 (wondering if the PIT is also used for Serial timing) to no avail.
Here is the sketch
--------------------
const int gSampleHz = 100; //set to 0 for as fast as possible, else sets samples per second, e.g. 1000 = 1kHz
const int gBytesPerSample = 8;
#define ENABLE_SERIAL1 //Teensy will freeze when gSampleHz>0, gBytesPerSample>8 and this line is UNCOMMENTED
/*
This simple sketch demonstrates that the Teensy3 locks up when trying to transmit more than 8 bytes via Serial1
To demonstrate, use PROCESSING script bt_RX_Processing to either connect to the wired Serial port, or to a Bluetooth module set up on Serial1
Serial ALWAYS Works
gSampleHz = 0; gBytesPerSample = 8; //transmits 8 bytes as fast as possible
gSampleHz = 1000; gBytesPerSample = 8; //transmits 8 bytes at 1kHz
gSampleHz = 0; gBytesPerSample = 10; //transmits 10 bytes as fast as possible
gSampleHz = 1000; gBytesPerSample = 10; //transmits 10 bytes at 1kHz
Serial FAILS when more than 8 bytes are sent with interrupts enabled
gSampleHz = 0; gBytesPerSample = 8; //transmits 8 bytes as fast as possible
gSampleHz = 1000; gBytesPerSample = 8; //transmits 8 bytes at 1kHz
gSampleHz = 0; gBytesPerSample = 10; //transmits 10 bytes as fast as possible
gSampleHz = 1000; gBytesPerSample = 10; //FAILS transmits 10 bytes at 1kHz
gSampleHz = 100; gBytesPerSample = 16; //FAILS even though 20% data transfer of 1000Hz * 8 bytes!!!!
*/
//************ no need to edit lines below here *******
const int kOutLEDpin = 13; //location of in-built light emitting diode - 11 for Teensy2, 13 for Arduino/Teensy3
#define BAUD_RATE 230400 // 230400 //921600 //460800//115200 is the max for the Uno - Teensy and Leonardo use direct for much higher speeds
byte gSerialBytes[gBytesPerSample];
void sendOsc(void) {
Serial.write(gSerialBytes, gBytesPerSample);
#ifdef ENABLE_SERIAL1
Serial1.write(gSerialBytes, gBytesPerSample);
#endif
}
//use periodic interrupt timer, PIT http://forum.pjrc.com/threads/14-Teensy-3-0-and-interrupts
// http://www.pjrc.com/teensy/datasheets.html
#define PIT_LDVAL (PIT_LDVAL##n)
#define PIT_TCTRL (PIT_TCTRL##n)
#define IRQ_PIT_CH (IRQ_PIT_CH##n)
#define PIT_TFLG (PIT_TFLG##n)
#define clearPIT {PIT_TFLG = 1;}
#define startPITFreq(n, freq) {cli(); PIT_LDVAL = (F_BUS / (freq))-1; PIT_TCTRL = 3; NVIC_ENABLE_IRQ(IRQ_PIT_CH); sei();}
#define stopPIT {cli(); NVIC_DISABLE_IRQ(IRQ_PIT_CH); PIT_TCTRL = 0; sei();}
void pit0_isr(void) { //ARM interrupt
clearPIT(0) ;
sendOsc();
}
void timer_setup() { //setup ARM interupts
startPITFreq(0,gSampleHz);
}
void timer_stop() {
stopPIT(0);
}
void setup()
{
pinMode(kOutLEDpin, OUTPUT); //turn analog status light on
for (int i = 0; i < gBytesPerSample; i++)
gSerialBytes = i;
Serial.begin(BAUD_RATE);
#ifdef ENABLE_SERIAL1
Serial1.begin(BAUD_RATE);
#endif
if (gSampleHz > 0) {
timer_setup();
}
} //setup()
void loop() {
if (gSampleHz < 1) {
sendOsc();
}
int modulo = millis() % 1000;
if (modulo == 1) digitalWrite(kOutLEDpin, HIGH);
if (modulo == 500) digitalWrite(kOutLEDpin, LOW);
} //loop()
http://www.mccauslandcenter.sc.edu/CRNL/tools/oscilloscope
but it is more easily demonstrated in this simple demo where the Teensy3 can send data to processing
http://www.mccauslandcenter.sc.edu/CRNL/sw/oscilloscope/bt_test.zip
In fact, you do not even need processing, as the Teensy freezes up (the light stops blinking) when you upload a sketch where
gSampleHz > 0 (interrupts running)
gBytesPerSample > 8 (large packets)
and "#define ENABLE_SERIAL1" UNcommented.
You do not even need a serial device connected to Serial1 to observe this problem. On my OSX computer, setting gSampleHz = 0 (e.g. no interrupts) I am able to transfer several thousand samples per second with either 8 or 10 bytes per sample, and with gSampleHz = 1000 and gBytesPerSample=8 I can send precisely 1kHz of 8 bit samples with either the wired or wireless. However, with gSampleHz = 100; and gBytesPerSample = 10; the system locks up. I can then comment "#define ENABLE_SERIAL1" to read "//#define ENABLE_SERIAL1"" and the Teensy will happily send 10 bytes per sample at 100 Hz (but only on the wired connection).
Since the program locks up with or without my JY_MCU attached, it seems to be independent of the serial device.
I know this is appears a pretty obscure bug, and in general the T3 is a terrific platform. However, this one has really puzzled me. I have tried changing the interrupt timer to 0,1,2 (wondering if the PIT is also used for Serial timing) to no avail.
Here is the sketch
--------------------
const int gSampleHz = 100; //set to 0 for as fast as possible, else sets samples per second, e.g. 1000 = 1kHz
const int gBytesPerSample = 8;
#define ENABLE_SERIAL1 //Teensy will freeze when gSampleHz>0, gBytesPerSample>8 and this line is UNCOMMENTED
/*
This simple sketch demonstrates that the Teensy3 locks up when trying to transmit more than 8 bytes via Serial1
To demonstrate, use PROCESSING script bt_RX_Processing to either connect to the wired Serial port, or to a Bluetooth module set up on Serial1
Serial ALWAYS Works
gSampleHz = 0; gBytesPerSample = 8; //transmits 8 bytes as fast as possible
gSampleHz = 1000; gBytesPerSample = 8; //transmits 8 bytes at 1kHz
gSampleHz = 0; gBytesPerSample = 10; //transmits 10 bytes as fast as possible
gSampleHz = 1000; gBytesPerSample = 10; //transmits 10 bytes at 1kHz
Serial FAILS when more than 8 bytes are sent with interrupts enabled
gSampleHz = 0; gBytesPerSample = 8; //transmits 8 bytes as fast as possible
gSampleHz = 1000; gBytesPerSample = 8; //transmits 8 bytes at 1kHz
gSampleHz = 0; gBytesPerSample = 10; //transmits 10 bytes as fast as possible
gSampleHz = 1000; gBytesPerSample = 10; //FAILS transmits 10 bytes at 1kHz
gSampleHz = 100; gBytesPerSample = 16; //FAILS even though 20% data transfer of 1000Hz * 8 bytes!!!!
*/
//************ no need to edit lines below here *******
const int kOutLEDpin = 13; //location of in-built light emitting diode - 11 for Teensy2, 13 for Arduino/Teensy3
#define BAUD_RATE 230400 // 230400 //921600 //460800//115200 is the max for the Uno - Teensy and Leonardo use direct for much higher speeds
byte gSerialBytes[gBytesPerSample];
void sendOsc(void) {
Serial.write(gSerialBytes, gBytesPerSample);
#ifdef ENABLE_SERIAL1
Serial1.write(gSerialBytes, gBytesPerSample);
#endif
}
//use periodic interrupt timer, PIT http://forum.pjrc.com/threads/14-Teensy-3-0-and-interrupts
// http://www.pjrc.com/teensy/datasheets.html
#define PIT_LDVAL (PIT_LDVAL##n)
#define PIT_TCTRL (PIT_TCTRL##n)
#define IRQ_PIT_CH (IRQ_PIT_CH##n)
#define PIT_TFLG (PIT_TFLG##n)
#define clearPIT {PIT_TFLG = 1;}
#define startPITFreq(n, freq) {cli(); PIT_LDVAL = (F_BUS / (freq))-1; PIT_TCTRL = 3; NVIC_ENABLE_IRQ(IRQ_PIT_CH); sei();}
#define stopPIT {cli(); NVIC_DISABLE_IRQ(IRQ_PIT_CH); PIT_TCTRL = 0; sei();}
void pit0_isr(void) { //ARM interrupt
clearPIT(0) ;
sendOsc();
}
void timer_setup() { //setup ARM interupts
startPITFreq(0,gSampleHz);
}
void timer_stop() {
stopPIT(0);
}
void setup()
{
pinMode(kOutLEDpin, OUTPUT); //turn analog status light on
for (int i = 0; i < gBytesPerSample; i++)
gSerialBytes = i;
Serial.begin(BAUD_RATE);
#ifdef ENABLE_SERIAL1
Serial1.begin(BAUD_RATE);
#endif
if (gSampleHz > 0) {
timer_setup();
}
} //setup()
void loop() {
if (gSampleHz < 1) {
sendOsc();
}
int modulo = millis() % 1000;
if (modulo == 1) digitalWrite(kOutLEDpin, HIGH);
if (modulo == 500) digitalWrite(kOutLEDpin, LOW);
} //loop()