Serial Port Problem or Timer Problem

Hello All,
I was just fooling around and found this buggy thing with Arduino Micro anyway. If you use this code and monitor pin 11 with an oscilloscope, then connect to Arduino using Putty via comport, let a few lines get dumped to the terminal and then close Putty and wait for 5-10 minutes the period changes from 200mS to 8 seconds…Is it something I’m doing wrong in the code?

#include <MemoryFree.h> //not required after Debug
#include <EEPROM.h>
#include <Event.h>
#include <Timer.h>
#include <Time.h> 

time_t start_time; //instantiate the time_t object start_time
time_t elapsed = 1; //instantiate the time_t object elapsed //rev 1.4
Timer t; //instantiate the timer object t
int var = 0;	// for incoming serial data
int cnt;
int tickEvent         = 0;
const int Debug_IO11 = 11; //Debug IO13 pin 18
int tog = 0;
void setup() {
	Serial.begin(19200);	// opens serial port, sets data rate to 9600 bps
  tickEvent = t.every(1100, doPrintMe); //doFreeRun is controlled by timer 
}

void loop() {
cnt++;
rxSerial();
t.update(); //This seems to be the problem

digitalWrite(Debug_IO11, tog);
delay(100);
tog = 1 - tog;
}

byte rxSerial()
{
	// send data only when you receive data:
  if (Serial.available() > 0) {
		// read the incoming byte:
		var = Serial.read();


	}
}

void doPrintMe()
{
  
    var = rxSerial();
		Serial.print("I received:");
    Serial.write(var);
    Serial.print("\t");
    Serial.print(var);
    Serial.print("\t");
		Serial.print(var, DEC);
    Serial.print("\t");
    Serial.print(var, BIN);
    Serial.print("\t");    
    Serial.print(var, OCT); 
    Serial.print("\t");
    Serial.print(var, DEC); 
    Serial.print("\t");
    Serial.print(var, HEX);
       
    Serial.println("");
}
  tickEvent = t.every(1100, doPrintMe); //doFreeRun is controlled by timer

doPrintMe() is an interrupt service routine. Serial.print() relies on interrupts being enabled, which is not the case while your ISR is running.

rremm2000: I was just fooling around and found this buggy thing with Arduino Micro

Where did you find it ?

If it is buggy why not just throw it in the trash and find something else that works ?

...R

I’ll try to add and ISR and see what that does

Enabled Interrupts but still have the same problem, basically at some point the loop() fails due to update() not returning when it should.

void setup() {
      
    Serial.begin(19200);    // opens serial port, sets data rate to 9600 bps
  //attachInterrupt(1, doPrintMe, RISING  ); // syntax attachInterrupt(interrupt, ISR, mode)
  interrupts();
  tickEvent = t.every(1100, doPrintMe); //doFreeRun is controlled by timer 
}

Enabled Interrupts

Where they were already enabled. Do NOT try to do that in the actual interrupt service routine. Instead, STOP trying to print to the serial port in the ISR. Serial.print() simply buffers data. It works AS LONG AS there is room in the buffer. When the buffer gets full, Serial.print() blocks, waiting for there to be room in the buffer.

Room is made in the buffer by shifting bytes out. But, that requires timer interrupts, which don't happen while your ISR is running.

So, once the buffer gets full, your code blocks waiting for an event that can never happen.

basically at some point the loop() fails due to update() not returning when it should.

And, now, you know why.

Hello PaulS, thanks for you help so far

As you can see the attachInterrupt was commented out which means it's not being used, I then found the interrupts(); which I guess starts and re-starts the interrupts which was the only thing added and still displays the same symptom.

So, I'm not sure I understand your explanation.

Your explanation sounds like the interrupt has nothing to do with it, I think I'm clear on that hopefully...lol?

However, I'm not clear on why the update() does not return, the update function is updating / servicing the timer, serial print should continue to shift data out of it's buffer no matter if the putty is connected or not.

If serial print function is dependent on the terminal being present or not being present then there should be some function to stop serial print when the terminal is disconnected.

For instance, if you load the program and reset Arduino there is no TX LED, you can see the loop running at the proper speed. However, when I connect the terminal the TX LED starts but when I disconnect the terminal then the TX LED keeps going and as you stated fills up the buffer until it stalls the loop.

So, how do we prevent that buffer from over running, I didn't see a function that checked to see if the terminal was disconnected.

It seems to me the TX should dump the data regardless if the terminal is connected, or there should be a function to stop dumping if there is nothing there?

So the question is how do we go about properly terminating the TX of Serial Print when someone closes the terminal?

rremm2000: So the question is how do we go about properly terminating the TX of Serial Print when someone closes the terminal?

For me the question is "Why use such complicated code to do such a simple thing? "

...R

Because I'm testing, I'd like to write an app that takes the A/D voltages and dumps the values to the terminal when connected.

Basically, the A.Micro will be monitoring dc voltages from several sensors continuously and keep a running average to dump to a terminal when we connect to it. We'd be collecting Max/Min/Ave over the period of several weeks to several months but it does have to be done at specific time intervals, so if the loop() fails to run properly because update() doesn't return do to a buffer overrun because TX continues to run when we disconnect a terminal then it won't do.

The Micro and Leonardo are a little different from the other Arduinos. It could make a difference in this case but not until you fix the serial prints in the ISR.

Show us some code which doesn't attempt to do Serial inside an ISR and then perhaps we can debug any remaining problems.

Hello Morgan, Thanks for the advice, part of the idea was the doPrintMe was also going to read the sensors, do some math and then dump to the serial.

However, I think you are saying change the architecture so that the print.serial is only done when we connect with a terminal and not part of the ISR. I can reserve the sensor read for that part and only do the serial dump when if (Serial.available() > 0). But I was thinking that if (Serial.available() > 0) would only be true if something was sent, in which case I need a command to kick off the serial print?

Hopefully that makes sense and it's what you were alluding to?

This is a long ways from the development code, I am testing idea's so I don't start on an approach that paints me into a corner. So, this was a good lesson #1...lol

rremm2000: Because I'm testing, I'd like to write an app that takes the A/D voltages and dumps the values to the terminal when connected.

Why can't you do that with simple code

void loop() {
  myVolts = analogRead(voltPIn);
  Serial.println(myVolts);
  delay(1000); // crude way to prevent flooding the Serial connection
}

...R

Good idea Robin, thanks but once we get it going it will be doing a lot of other things but I'll try it that way too ;-) We may have timing concerns that will have to factor into it

rremm2000: We may have timing concerns that will have to factor into it

That's why I said the delay() was a crude method. I would never use it in a "real" program.

See how to use millis() to manage timing in several things at a time.

If you want to add "a lot of other things" then it is important to keep the code as simple as possible.

...R

Code for the Micro/Leonardo will often have while(!Serial){} at the top. This makes it wait until there's a terminal connected. The regular Arduinos can't tell if there is anyone listening.

However I am reasonably sure that once there has been a connection, this will always proceed as if the connection is still there. It doesn't reset. There must be a way to detect if the recipient is still connected but it's not supported by the Arduino core. Usually any serial data logger like this will just send data regardless of whether anyone is listening.