Search code examples
arduinointerruptavravr-gccavrdude

Disabling interrupts on TX pin on Arduino Mega 2560


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


Solution

  • 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