HardwareSerial break detect then read bytes

drmacro
Posts: 26
Joined: Tue Dec 25, 2018 8:25 pm

HardwareSerial break detect then read bytes

Postby drmacro » 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;
}
}
```

melias
Posts: 2
Joined: Wed Jan 15, 2020 4:16 am

Re: HardwareSerial break detect then read bytes

Postby melias » Wed Jan 15, 2020 4:25 am

Did you get this working?

drmacro
Posts: 26
Joined: Tue Dec 25, 2018 8:25 pm

Re: HardwareSerial break detect then read bytes

Postby drmacro » Wed Jan 15, 2020 7:54 pm

No. But it turned out to be more complex than this post captures.

The UART driver can detect the break. And it will then return received data, but only data streams that fall on 120 byte boundaries.

It has been logged as an issue in github, where I describe in gory detail what I think is going on:
How to read UART bytes in queue after break? (IDFGH-2424) #4537

The issue has been assigned, but as far as I can tell no update has occurred.

The break detect works, but only transmissions that coincide with 120 byte boundaries can be read. So, it never gets a call back for the last 32 bytes of the 512(actually 513) bytes of the (DMX) transmission I'm trying to capture.

If, what I describe is happening, then anyone attempting to use the UART driver for received data that is not a multiple of 120 bytes will experience the same problem.

Who is online

Users browsing this forum: No registered users and 10 guests