2

I'll start telling that the reference on the function serialEvent is not very well documented for Arduino. https://www.arduino.cc/en/Reference/SerialEvent

Due to the lack of information I've misunderstood how this function works. As I have the Arduino Mega 2560 it comes with 4 Serial inputs/outputs, and they have their own serialEventX function (where X = {'',1,2,3}).

I've successfully communicated with a ESP8266 module, which sends and receives information once a client is connected to it.

Using the serialEvent1 (1 because it's connected to RX1 and TX1) I want serialEvent1 to be called only when data is incoming, but actually is called also whenever I use Serial1.write(msg), so this means when a message is being sent.

#define DEBUG_ESP8622 1
#include <esp8622.h>
#include <string.h>
#include "common.h"
#include <stdlib.h>
Wifi esp = Wifi(); //Here Serial1.begin(115200) happens
void setup() {
  Serial.begin(9600); //First of all SERIAL for debugging
  Serial.println("Starting");

  while(!esp.sReachable());   //Works
  Serial.println("ESP found");

  while(!esp.sSetMode(1));    //Works
  Serial.println("Mode set to Client");

  while(!esp.sConnect(WIFISSID,WIFIPASSWORD));  //Works
  Serial.println("Connected");
  Serial.print("IP:");
  Serial.println(esp.getIP());

  while(!esp.sStartServer(80));  //Works
  Serial.println("Server started");
}
void loop() {
    if(Serial.available()>0){
            int inByte=Serial.read();
            /*HERE whenever I call Serial1.write(inByte)
              serialEvent1 will be called at the end of the loop
              but actually I don't want it to
            */
            Serial1.write(inByte);
    }

}
void serialEvent(){
    return;
}
void serialEvent1(){
   Serial.println("Write or Read event?");
   while(Serial1.available()>0){
      int inByte=Serial1.read();
      //Serial.write(inByte);
   }
   //esp.onSerialEvent(); //Stores message and parses it, not relevant
   return;
}

So now, knowing that the Arduino libraries are based on the AVR libc libraries, I suppose that the RX1 and TX1 interrupts inside the microcontroller are binded both to serialEvent1 through Arduino libraries.

Is it possible to unbind only TX1 from serialEvent1 using the library and still be using Arduino libraries (Serial1.write()/read())?

I use the easiest way to upload code to the Mega using a Makefile. Opted to use arduino from command line because it suited my needs so far, I know avrdude and avr-gcc is a more complete or better way to compile/upload from command line, correct me if I'm wrong.

CC=arduino
upload: terminal.ino
    $(CC) terminal.ino --upload

verify: terminal.ino
    $(CC) terminal.ino --verify

Should I start learning how to use avrdude and avr-gcc instead if I start using ? (or maybe it has nothing to do with the fact of using AVR libraries)

And last, I'm using the above Makefile with an USB cable, If i use avrdude and avr-gcc is it through ICSP or can be still used through USB cable? will this erese the bootloader?

Many thanks

Ruso_x
  • 347
  • 1
  • 3
  • 14
  • When `serialEvent1()` is called, is there data `Serial1.available()`? - You may want to change `serialEvent1()` to do `while(Serial1.available()>0){` instead of `if(...`. – JimmyB Jan 27 '16 at 14:02
  • 1
    Plus, you also may want to check if the ESP8266 is configured to `echo` back your commands to you (`ATE0`/`ATE1`). – JimmyB Jan 27 '16 at 14:04
  • @HannoBinder, thanks for the pointing that out, changed it. About the ESP8266 echoing back, it doesn't, already checked it with the code mentioned here: https://www.arduino.cc/en/Tutorial/MultiSerialMega – Ruso_x Jan 27 '16 at 15:08
  • @HannoBinder actually you are right, I was reading the NeoHWSerial code posted below and actually TX pin doesn't call serialEvent, my bad for not double checking about the ESP8266 echoing back, did it right this time and ATE0 solved the problem. Please post a reference to the AT commands, I was using this set [link](http://www.pridopia.co.uk/pi-doc/ESP8266ATCommandsSet.pdf) – Ruso_x Jan 30 '16 at 10:53
  • @HannoBinder, please post the set of AT commands reference you use for the ESP8266, – Ruso_x Feb 01 '16 at 14:01

1 Answers1

0

Yes, the SerialEvent functions are silly. They are no different from polling them in loop. You can still lose data if you do something time-consuming and don't return to loop quickly enough. The solution is to attach to the RX interrupt, but that isn't supported by the built-in class, HardwareSerial.

I have posted modified versions of HardwareSerial that allow you to attach to the RX interrupt. It is called NeoHWSerial.

Because it is a replacement, you must use only the NeoSerial[#] variables. You can't use Serial and NeoSerial1 in the same sketch. Just use NeoSerial instead of Serial, even though you don't call NeoSerial.attachInterrupt:

void setup()
{
  NeoSerial.begin( 9600 );            // replaces `Serial.begin(9600)`
  NeoSerial.println( F("Started.") ); // ... and all your prints, too

  NeoSerial1.attachInterrupt( myRxFunction );
  NeoSerial1.begin( 9600 );

Remember that myRxFunction is called during the interrupt. You must be quick about handling each character, and don't call things that depend on not being in an interrupt, like print or even millis(). Bad juju!

And be sure the files in the matching IDE version subdirectory (e.g., 1.6.5r2) are copied to your libraries/NeoHWSerial subdirectory. Do not put them in libraries/1.0.5 or libraries/1.6.5r2

slash-dev
  • 1,569
  • 2
  • 9
  • 9
  • In fact, the standard HW serial is interrupt-driven too. Received data is put into an RX buffer by the ISR to be retrieved in SerialEvent later. This buffering gives you more time to react because you won't lose data even if your loop takes e.g. 5 RX byte times before SerialEvent can run. Hence, if you don't need to react fast/asynchronously on an incoming byte, you're probably better off using the Arduino version. – JimmyB Jan 30 '16 at 15:45
  • I didn't say the standard `HardwareSerial` isn't interrupt driven. I said that `SerialEvent` is a polled function. `SerialEvent` is not called from the interrupt; it is called after you return from `loop`, and does not provide any benefit over just polling `Serial` from inside `loop`. Its name and usage implies that it is called asynchronously, but it really isn't. This is a source of confusion for many, as he stated. BTW, reaction time isn't the only criterion: other libraries' blocking time can cause the input buffer to overflow, losing data. Handling chars in the ISR might be the answer. – slash-dev Jan 30 '16 at 20:28
  • OTOH, in SerialEvent you can do more complex tasks, like parsing longer received messages, which may become awkward in an ISR. Depends on personal preference, I guess, but I favor the asynchronous approach, where processing of the data is not synchronous to reception. - I did however misunderstand your statement re polling, thinking you meant polling the serial port for single bytes instead of polling the *rx buffer*. – JimmyB Jan 30 '16 at 21:08