Skip to content

How can I make copy about UART_TX_FIFO in Arduino skatch? #1551

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Galilei11 opened this issue Feb 1, 2016 · 36 comments
Closed

How can I make copy about UART_TX_FIFO in Arduino skatch? #1551

Galilei11 opened this issue Feb 1, 2016 · 36 comments

Comments

@Galilei11
Copy link

I need to catch and store all of characters coming out UART0 tx pin, and send them to another direction.
It have to do inside ESP, with software, because no free pin on ESP already (read back tx pin).
I think, if I can get every characters when is written to UART_TX_FIFO it can solve this problem.
But I dont know how, any idea?

@Links2004
Copy link
Collaborator

is it needed to do it register level?
simple create a class with stream interface.

HardwareSerial mirror(&Serial);

class SerialMirror: public Stream {
        HardwareSerial * _serial;
        SerialMirror(Serial * s) {
            _serial = s;
        }

        size_t write(const uint8_t *data, size_t size) {
             /// add code for your mirror here
            return _serial->write(data, size);
        }

        size_t write(uint8_t data) {
             /// add code for your mirror here
            return _serial->write(data);
        }

        int available() {
            return _serial->available();
        }

        int read() {
            return _serial->read();;
        }

        int peek() {
            return _serial->peek();
        }

        void flush() {
            _serial->flush();
        }
}

usage:

mirror.println('test');

@Galilei11
Copy link
Author

thx, I will test it
but I am beginner yet, I started 2 month ago with ESP and Arduino, I try to understand and use it :)
how do you think: register level?

@me-no-dev
Copy link
Collaborator

@Links2004 I think he means that he wants to output at two locations at the same time.
For example: mirror.println(blah); to actually print to Serial and a Client (or some other destiantion)

@Links2004
Copy link
Collaborator

@me-no-dev yes think so, that is why I write `add code for your mirror here`` as comment in the code ;)

@tzapu
Copy link
Contributor

tzapu commented Feb 9, 2016

@Links2004 will this make it possible for instance to stream serial to websockets? got any sample of that somewhere? :)

@Links2004
Copy link
Collaborator

@tzapu yes you can write a class that can "print" to websocktes in the same way, or eaven combine them to print to Serial and WS.
for many small prints I recommend the usage of the Async mode for websocktes or it will be slow.

class SerialMirror: public Stream {
        WebSocketsServer* _ws;
        SerialMirror(WebSocketsServer * s) {            _ws = s;        }

        size_t write(const uint8_t *data, size_t size) {    _ws->broadcastTXT(data, size); return size;        }
        size_t write(uint8_t data) {            return _ws->broadcastTXT(data);    return 1;    }

        int available() { return 0;  }
        int read() {    return -1;    }
        int peek() {    return -1;    }
        void flush() {       }
}

@tzapu
Copy link
Contributor

tzapu commented Feb 10, 2016

hi, thank you very much for the hints, i assume i can combine the two above to proxy reading from serial to websockets... need to learn more :D

on second thought, do i need the stream interface if i m just reading and passing on to websockets? probably for simplicity it s better and i can just add the sending to the read method, maybe with some buffering ...

@Links2004
Copy link
Collaborator

yes for serial to websockets bridge you not need a stream interface for websockets .
simple buffering:

    Serial.setTimeout(200);
    String line = Serial.readStringUntil('\n');
    if(line.length() > 0) {
        // add back line ending
        line+='\n';
        ws->broadcastTXT(line);
    }

sends all 200ms (when data is there) or on every line ending.

@tzapu
Copy link
Contributor

tzapu commented Feb 10, 2016

how cool is that :D
thank you very much

@tzapu
Copy link
Contributor

tzapu commented Feb 17, 2016

@Links2004 this seems to be missing some strings at 115200, is there something i can do to make it more reliable?
p.s. i don t know yet, and i should check, if it is missing while reading or it s missing while sending over websockets... i ll check and be back

@tzapu
Copy link
Contributor

tzapu commented Feb 17, 2016

@Links2004 , double checked, it seems it s missing strings when reading from serial.
cand i make it more reliable somhow?
thanks for all your help

my loop looks like this currently


void loop() {
  Serial.setTimeout(200);
  String line = Serial.readStringUntil('\n');
  if (line.length() > 0) {
    // add back line ending
    line += '\n';
    webSocket.broadcastTXT(line);
    Serial.print(line);
  }
  webSocket.loop();
}

@Links2004
Copy link
Collaborator

so you not get echoed back all data?

you can try:

void setup() {
 ....
 Serial.setTimeout(200);
}

void loop() {
    webSocket.loop();
    if(Serial.available()) {
        String line = Serial.readStringUntil('\n');
        if(line.length() > 0) {
            // add back line ending
            line+='\n';
            ws->broadcastTXT(line);
        }
    }
}

@tzapu
Copy link
Contributor

tzapu commented Feb 17, 2016

nop, somhow it s eating characters.

tried with timeout in setup, still no go

connecting to 
emoncms.org
RequHTTP/1.1 200 OK
Date: Wed, 17 Feb 2016 17:29:59 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powentent-Length: 2
ok

that should have the full url there somewhere and headers, etc

@tzapu
Copy link
Contributor

tzapu commented Feb 17, 2016

i have also tried without timeout, larger timeout, still the same.
a 500ms timeout does seem to make it a bit better, but still misses some stuff

@tzapu
Copy link
Contributor

tzapu commented Feb 17, 2016

this seems to yield some better results on some fast tests, but i m not convinced it would hold as no timeouts, no buffering, etc

void serialEvent() {
  while (Serial.available()) {
    char inChar = (char)Serial.read();
    if (inChar == '\n') {
      stringComplete = true;
      return;
    } else {
      inputString += inChar;
    }
  }
}


void loop() {
  serialEvent();
  if (stringComplete) {

    String line = inputString;
       // clear the string:
    inputString = "";
    stringComplete = false;

    //line += '\n';
    webSocket.broadcastTXT(line);
    Serial.print(line);
  }
}

@tzapu
Copy link
Contributor

tzapu commented Feb 17, 2016

although i just realised in the latest example i forgot to add the websockets loop...
more testing tomorrow
thanks

@tzapu
Copy link
Contributor

tzapu commented Mar 2, 2016

hi @Links2004 , took longer than i expected to try this

it seems that indeed if i use the serialEvent loop like above, it does not miss characters....

weird

/edit

i was quick to post... still eating characters

Date: Wed, 02 Mar 2016 14:36:25 GMT
Server: Apache/2.2.22 (Ubuntu)
X-Powered-By: PHP/5.3.10-1ubuntu3.21
Content-Length: 2
ection: close
Content-Type: applicaok

no idea what i could do to it to make it better ... any suggestions welcome
also, this issue could be closed i guess, as it s rather off topic by now :P
thanks

@Links2004
Copy link
Collaborator

that you lost the empty lines make sens with your code.
if you find a \n you not add it and then you send a empty buffer to the browser.
may this is part of the problem.

you can try to:
reserve some space in the string too
check the return value of the broadcastTXT may simple the TCP buffer is full.

@tzapu
Copy link
Contributor

tzapu commented Mar 2, 2016

thanks for the hints, will play with it more
not loosing just new lines, in the example above Connection: close is truncated, application/html or whatever was there is also trucated
also, not just broadcast, i mirror it on serial as well before sending and it s truncated there as well
i am also doing this inputString.reserve(256); , it doesn t seem to be larger than that, seeing that it reads only one line at a time and also the ones truncated are quite short

@Links2004
Copy link
Collaborator

the internal serial hardware buffer is 128Byte with the code above I not see a reason why it can
have a overflow, you read fast form it.
have you tried a other Serial adapter in best case with other chip may yours is defektiv.

@tzapu
Copy link
Contributor

tzapu commented Mar 2, 2016

i m using a nodemcu as a serial reader of stuff spat out by an esp01
the project is this https://github.com/tzapu/WebSocketSerialMonitor
i will try to read from the esp01 directly with a usb to serial reader, see if that output comes out ok, and will try another things instad of the nodemcu i currently use as proxy

@tablatronix
Copy link
Contributor

Did you give up on serial tx mirror ? I am looking for the same, but not websockets, although that would be nice also.

@tzapu
Copy link
Contributor

tzapu commented Mar 5, 2016

well, my repo above does mirroring over websockets to a page, also on github pages
so far, it eats some characters up, still yet to find why, good enough to play and see what s happening with it

@tablatronix
Copy link
Contributor

hmm I thought Serial.read(); only reads RX buffer...
Is the magic somewhere else ?

@tablatronix
Copy link
Contributor

Oh you are using a hardware rx.

I am wanting what the op wanted.

Mirror all Serial tx to a server stream say telnet write or websockets whatever. Like overloading or interxepting Serial writes.

@tzapu
Copy link
Contributor

tzapu commented Mar 17, 2016

sorry for waking the dead with this one @Links2004 , i got around to plugging a real serial adapter into the GND/TX of the sending ESP, and unline the NodeMCU that was reading with the code above, this does not miss any characters.

It does seem that somehow serial rx is missing characters, and quite a bit of them

@Links2004
Copy link
Collaborator

you can try:
Links2004/arduinoWebSockets#61 (comment)

how high is you data rate, may you overload the Hardware serial RX buffer.

@tablatronix
Copy link
Contributor

looks nice, how big is the hardware buffer?

screen shot 2016-03-19 at 12 29 11 pm

@tzapu
Copy link
Contributor

tzapu commented Mar 19, 2016

hi, baud is set at 115200, data is rather little, should not go over buffer. longest line seems to be around 115 characters, and it seems to eat random parts of the buffer anyway, not always the same one.

i will try the sample you kindly provided. thank you. i ll also try slower baud rates

@tablatronix
Copy link
Contributor

Ah I reread, hardware buffer is 128 byte.

Do you have a reproduction test, I have two boards in my dev, i can try, or try a loopback. I am Assumig you do not have a problem generating data internally , but only when reading hardware serial?

@tablatronix
Copy link
Contributor

as an aside
@Links2004 serialmirror code above doesn't work and is confusing me ( which is easy in C++)
The errors make sense I think, HardwareSerial wants an int eg. UART0

And I am guessing Serial is not typedefed or something for the second error.

SerialMirror.h:1:30: error: invalid conversion from 'HardwareSerial*' to 'int' [-fpermissive]
 HardwareSerial mirror(&Serial);
                              ^
/SerialMirror.h:5:29: error: expected ')' before '*' token
         SerialMirror(Serial * s) {
                             ^

Nor do I get how mirror() is using the SerialMirror class , or was that all supposed to be handled via the &Serial reference ? Since there is no explicit instantiation of the class...
😕

I guess that could have been psuedocode..

@Links2004
Copy link
Collaborator

for #1551 (comment)
SerialMirror(Serial * s) { need to be SerialMirror(HardwareSerial* s) {
its never tested code, only to show the way.

for a Serial to WS bridge is currently use
Links2004/arduinoWebSockets#61 (comment)
without any problems, it has a more advanced buffering and can run without blocking in the loop.

@tablatronix
Copy link
Contributor

That bridge is what I am using above (screenshot), I was interested in having a stream to websockets/hardwareserial/telnet so i figured a serial mirror like that would be useful for easily pluggin into existing sketches and redirecting to wherever I wanted.

Thanks!

I guess I will have to read up on classes, since i already changed that, but was having a problem with other errors like non-class member private etc.

@Links2004
Copy link
Collaborator

for mirroring the "Serial out" to multible interfaces you need to create a class with the Stream interface like:

class SerialMirror: public Stream {
        size_t write(const uint8_t *data, size_t size) {   
              ws.broadcastTXT(data, size); 
              Serial.write(data, size);
              Serial1.write(data, size);
              return size;       
         }

        size_t write(uint8_t data) { 
             ws.broadcastTXT(data);    
             Serial.write(data);
             Serial1.write(data);
             return 1;
    }

        int available() { return 0;  }
        int read() {    return -1;    }
        int peek() {    return -1;    }
        void flush() {       }
}

SerialMirror SerialM;

SeriaM.println("print to all interfaces");

@tablatronix
Copy link
Contributor

Sounds easy enough, do i need to alias the print/ln stuff or is that done by the stream class?

@Links2004
Copy link
Collaborator

the Stream class will do this for you.
you only need the functions shown above.
the code will handle the sending / print / write stuff.

but the code may send byte by byte.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants