HardwareSerial break detect then read bytes
Posted: Mon Aug 19, 2019 1:13 pm
Putting this here since it's about hardware serial.
I am attempting to read a series of bytes that follow a break in the serial input. (For reference, this is reading DMX input. DMX begins transmission with an 88us low, 8us high, then is followed by 512 bytes. The baud rate is 250000.)
I have looked at similar code and studied their implementation. Some are write only, one apparently only reads the first specified number of bytes once. I was also never able to get any of them to read correct values.
The code below does see the 88us start of packet (I can see the toggle of the enable pin on my scope.) But, it does not read the correct values for the bytes. The bit stream presented to the rxPin does decode correctly with my Saleae logic analyser though.
Questions:
- Is it legit to simply do a .begin in the interrupt routine? (I gleaned this from other examples, but, it seems to me that the pin is still connected to the interrupt routine, after the .begin is executed. )
- Is it likely the 8us is not enough time for .begin get established?
- Am I missing something obvious? (which is my typical condition... )
```
#include <Arduino.h>
#include <HardwareSerial.h>
#define DMXSPEED 250000
#define DMXFORMAT SERIAL_8N2
#define dmxMaxChannel 513
#define defaultMax 32
int enablePin = 21; //dafault on ESP32
int rxPin = 16;
int txPin = 17;
uint32_t _lastTimeStamp = 0;
HardwareSerial DMXSerial(2);
uint8_t dmxData[dmxMaxChannel] = {};
int chanSize = defaultMax;
int currentChannel = 0;
void IRAM_ATTR startCode() {
if ((micros() - _lastTimeStamp) >= 87)
{
digitalWrite(enablePin, HIGH);
digitalWrite(enablePin, LOW);
detachInterrupt(digitalPinToInterrupt(rxPin));
currentChannel = 0;
DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);
}
_lastTimeStamp = micros();
}
void setup() {
Serial.begin(115200);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW);
pinMode(rxPin, INPUT);
_lastTimeStamp = micros();
attachInterrupt(digitalPinToInterrupt(rxPin), startCode, CHANGE);
}
void loop() {
Serial.println("In loop");
while (DMXSerial.available())
{
Serial.println("Data Avail");
if (currentChannel == 0)
{
DMXSerial.read();
}
dmxData[currentChannel++] = DMXSerial.read();
Serial.println(dmxData[currentChannel]);
}
if (currentChannel > chanSize) //Set the channel counter back to 0 if we reach the known end size of our packet
{
currentChannel = 0;
}
}
```
I am attempting to read a series of bytes that follow a break in the serial input. (For reference, this is reading DMX input. DMX begins transmission with an 88us low, 8us high, then is followed by 512 bytes. The baud rate is 250000.)
I have looked at similar code and studied their implementation. Some are write only, one apparently only reads the first specified number of bytes once. I was also never able to get any of them to read correct values.
The code below does see the 88us start of packet (I can see the toggle of the enable pin on my scope.) But, it does not read the correct values for the bytes. The bit stream presented to the rxPin does decode correctly with my Saleae logic analyser though.
Questions:
- Is it legit to simply do a .begin in the interrupt routine? (I gleaned this from other examples, but, it seems to me that the pin is still connected to the interrupt routine, after the .begin is executed. )
- Is it likely the 8us is not enough time for .begin get established?
- Am I missing something obvious? (which is my typical condition... )
```
#include <Arduino.h>
#include <HardwareSerial.h>
#define DMXSPEED 250000
#define DMXFORMAT SERIAL_8N2
#define dmxMaxChannel 513
#define defaultMax 32
int enablePin = 21; //dafault on ESP32
int rxPin = 16;
int txPin = 17;
uint32_t _lastTimeStamp = 0;
HardwareSerial DMXSerial(2);
uint8_t dmxData[dmxMaxChannel] = {};
int chanSize = defaultMax;
int currentChannel = 0;
void IRAM_ATTR startCode() {
if ((micros() - _lastTimeStamp) >= 87)
{
digitalWrite(enablePin, HIGH);
digitalWrite(enablePin, LOW);
detachInterrupt(digitalPinToInterrupt(rxPin));
currentChannel = 0;
DMXSerial.begin(DMXSPEED, DMXFORMAT, rxPin, txPin);
}
_lastTimeStamp = micros();
}
void setup() {
Serial.begin(115200);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, LOW);
pinMode(rxPin, INPUT);
_lastTimeStamp = micros();
attachInterrupt(digitalPinToInterrupt(rxPin), startCode, CHANGE);
}
void loop() {
Serial.println("In loop");
while (DMXSerial.available())
{
Serial.println("Data Avail");
if (currentChannel == 0)
{
DMXSerial.read();
}
dmxData[currentChannel++] = DMXSerial.read();
Serial.println(dmxData[currentChannel]);
}
if (currentChannel > chanSize) //Set the channel counter back to 0 if we reach the known end size of our packet
{
currentChannel = 0;
}
}
```