Why is the serial monitor only outputting a few lines?

Hello,

I'm have written some code for the Arduino, where it receives a value from a python script over serial. It's then supposed to compare this value to a running total of encoder pulses, when the encoder pulses exceed this value the motors should stop running. I'm yet to integrate them motor part, that's the next step. I'm having an issue where the Arduino reaches the comparison while loop, in this loop I have it printing some information to the serial monitor for debugging - the issue is it only prints 4 or 5 lines before the output stops and the information it outputs is strangely formatted.

I have no idea what I'm doing wrong.

#include <Arduino.h>
#include <math.h>

#define ENC_COUNT_REV 64
#define GEAR 60 //30:1 + 2:1 gear ratio
#define ENC_PIN_A 20
#define ENC_PIN_B 21
#define ARD_PI_PIN 18


// MOTOR WIRING DATA
// Red - pos
// Black - Neg
// Green - GND
// Blue - Vcc (3.3v-20v)
// Yellow - Output A
// White - Output B


// Encoder counters
volatile long enc_a_count = 0;
volatile long enc_b_count = 0;
volatile long encoderCount = 0;
volatile long count; 

unsigned long reqCounts = 0;
unsigned long copy_count = 0;

void setup() {
  Serial.begin(115200);
  Serial.setTimeout(1);

  pinMode(ENC_PIN_A, INPUT_PULLUP);
  pinMode(ENC_PIN_B, INPUT_PULLUP);

  //attachInterrupt(digitalPinToInterrupt(ARD_ABORT_PIN), abort, RISING);
  attachInterrupt(digitalPinToInterrupt(ENC_PIN_A), updateEncoderA, CHANGE);
  attachInterrupt(digitalPinToInterrupt(ENC_PIN_B), updateEncoderB, CHANGE);

}

void loop() {


  String data = "";
  
  while (true) {
    while (!Serial.available());
    data = Serial.readStringUntil('\n');
    if (data == "OK") {
      break;  // Break out of the loop if "OK" is received
    } else {
      reqCounts = strtoul(data.c_str(), NULL, 10);
      Serial.print(reqCounts);
      delay(5);
    }
  }

  // LOWER SENSOR CODE TO GO HERE


  while (true) {

    Serial.print(" Running Total pulses:");
    Serial.print(copy_count);
    Serial.print('\t');
    Serial.print(" Target pulses:");
    Serial.print(reqCounts);
    Serial.println();
    delay(5);

    noInterrupts();
    copy_count = count; 
    interrupts();

    if (copy_count <=0.5*reqCounts) {
    //Set PIN to High
    }
    if (copy_count >=0.5*reqCounts) {
    //Set PIN to Low
    }
    if (copy_count >= 0.9*reqCounts) {
    // Set PIN to High
    }
    if (copy_count >= reqCounts) {
      // Set PIN to Low (STOP MOTORS)
      reqCounts = 0;
      copy_count = 0;
      count = 0;
      break;
    }
  }

  // RAISE SENSOR CODE TO GO HERE

}


void updateEncoderA() {
  count++;
  enc_a_count++;
}

void updateEncoderB() {
  enc_b_count++;
  count++;
}

Heres an example of the serial monitor output (mind you it changes every time the codes run):

20:49:39.384 ->  Running R
20:49:39.384 ->  Runniotal pulses:0	 Target pulses:200
20:49:39.384 ->  Running Total pulses:0	 Target pulses:200
20:49:39.384 ->  Running Total pulses:0	 Target pulses:200
20:49:39.384 ->  Running Total pulses0	 T

Thanks for the help!

Do you think you should share that output?

1 Like

Oops, added to the OP.

Every time your loop() makes a loop, you will be loosing memory because a NEW string is created. Eventually you will run out of available memory.

1 Like

look this over, avoid while (true) loops and generates a print 2 seconds. also added means to test

#include <Arduino.h>
#include <math.h>

#define ENC_COUNT_REV 64
#define GEAR 60 //30:1 + 2:1 gear ratio
#define ENC_PIN_A 20
#define ENC_PIN_B 21
#define ARD_PI_PIN 18

// MOTOR WIRING DATA
// Red - pos
// Black - Neg
// Green - GND
// Blue - Vcc (3.3v-20v)
// Yellow - Output A
// White - Output B

// Encoder counters
volatile long enc_a_count = 0;
volatile long enc_b_count = 0;
volatile long encoderCount = 0;
volatile long count;

unsigned long reqCounts  = 0;
unsigned long copy_count = 0;

void setup () {
    Serial.begin (115200);
    Serial.setTimeout (1);

    pinMode (ENC_PIN_A, INPUT_PULLUP);
    pinMode (ENC_PIN_B, INPUT_PULLUP);

    //attachInterrupt (digitalPinToInterrupt (ARD_ABORT_PIN), abort, RISING);
    attachInterrupt (digitalPinToInterrupt (ENC_PIN_A), updateEncoderA, CHANGE);
    attachInterrupt (digitalPinToInterrupt (ENC_PIN_B), updateEncoderB, CHANGE);
}

String data;
unsigned long msec0;

void loop ()
{
     if (Serial.available ())  {
        char buf [90];
        int n  = Serial.readBytesUntil ('\n', buf, sizeof(buf)-1);
        buf [n] = '\0';

        if ('c' == buf [0])         // for testing
            count++;
        else {
            reqCounts = atol (buf);
            Serial.print   ("reqCounts ");
            Serial.println (reqCounts);
        }
    }

    // LOWER SENSOR CODE TO GO HERE

    unsigned long msec = millis ();

    if (msec - msec0 >= 2000)  {
        msec0 = msec;

        if (copy_count < reqCounts) {
            noInterrupts ();
            copy_count = count;
            interrupts ();

            Serial.print (" Running Total pulses:");
            Serial.print (copy_count);
            Serial.print ('\t');
            Serial.print (" Target pulses:");
            Serial.print (reqCounts);
            Serial.println ();
            delay (5);

            if (copy_count <=0.5*reqCounts) {
                //Set PIN to High
            }
            if (copy_count >=0.5*reqCounts) {
                //Set PIN to Low
            }
            if (copy_count >= 0.9*reqCounts) {
                // Set PIN to High
            }
        }
        else {
            reqCounts  = 0;
            copy_count = 0;
            count = 0;
        }
    }
}

void updateEncoderA () {
    count++;
    enc_a_count++;
}

void updateEncoderB () {
    enc_b_count++;
    count++;
}
1 Like

Thanks for the code appreciate it. Unfortunately still having the same issue, here's the serial monitor output when I run your code:

09:52:37.239 ->  Running Total pul0
09:52:37.239 ->  Running Total pulses:0	 Target pulses:200
09:52:37.239 ->  Running Total pulses:0	 Target pulses:200
09:52:37.239 -> 0
�

Please share with us,

  • what Arduino device - Nano, Uno, ESP32, ???
  • simple schematic; include power arrangements, what's generating the interrupt, how fast, etc., what motor control arrangement.

When you don't know what the problem is, don't assume "it isn't ..." and therefore limit what you share with us - because you don't know what you don't know. Yes, some sharing may result in 'critique' or 'helpful advice'. That's part of resolving the issue.

1 Like

Thanks for you response!

There really isn't much more too it. I'm using an arduino mega 2560, but have also attempted to run the script on a nano (no success).

I plan on using pololu 37d geared motors which have a built in encoder. I haven't bothered wiring them up yet, I can't see any point if the serial print can't even relay information from the encoder. So the wiring schematic is a serial connection with my laptop over USB-B. I will share the script I'm running on my laptop when Im home.

Hope this helps.

I ran your code with nothing attached to an UNO. I type 177 <return> followed by OK <return> and this printed, very rapidly and would have forever.

177 Running Total pulses:0	 Target pulses:177
 Running Total pulses:0	 Target pulses:177
 Running Total pulses:0	 Target pulses:177
 Running Total pulses:0	 Target pulses:177
 Running Total pulses:0	 Target pulses:177

So I have no clue why it is not the same over where you are at.

With a rotary attached encoder, either direction adds to a count that reaches for the Target at which point the hole mess seems to reset (wait for target number + OK entry).

a7

1 Like

That's what it's supposed to do! Thanks for testing it. I'll have to have another look later

Well, with the code tested successfully elsewhere, I'd focus on mechanical issues.

  • bad cable (likely, as an intermittent might behave when you download, but fail when you move the board around, or whatever)
  • board lying on conductive surface, intermittently causing crashes
  • damaged Arduino (not likely, can't think of a suitable case, but...)
    All I can come up with without a photo or other evidence to investigate
1 Like

I'll grab some photos when I'm home, but as I say I've tested it on an uno with the same results. I've got to be doing something stupid....

I have managed to recreate your results by sending to the serial monitor rather than from the python script. Seems to suggest its an issue with the python script right?

Here is the code I'm running on Python:

import serial 
import time


counts = 200
def serial_comm(count):
    ser = serial.Serial('COM3', 115200, timeout=1)
    time.sleep(5)
    ser.reset_input_buffer()

    ser.write(bytes(str(count) + '\n', 'utf-8'))
    time.sleep(1)
    received_data = ser.readline().decode('utf-8').strip()
    if received_data != str(count):
        print(f"Received data {received_data} does not match the expected count {count}. Retrying...")
        ser.close()
        serial_comm(count)  # Recursive call to send and verify again
    else:
        ser.write(bytes('OK\n', 'utf-8'))
        print("Data sent OK")
        ser.close()

    
serial_comm(counts)
1 Like

I've tried using a different cable, no success. The Arduino's in a plastic case and not near anything conductive, so I doubt that's an issue.

Photos:




OK, since you have Mega, I suggest using two UARTs.

Leave the one that dies the code uploading and downloading, and talks to the serial monitor to do that and only that.

Use another UART and a second port on your PC to do whatever it is that you want the Python script to do.

More cables, but easier to be sure that the results aren't because of the dual use of one UART.

a7

1 Like

How would you propose doing this? Using the UNO as an intermediary or is there a special USB cable you can buy which can be plugged directly into the I/O pins on the Arduino?

OK, sry, this is the kind of thing I eat for breakfast.

You can use a second UART on the Mega, then to hook it to your PC you would need a TTL serial to USB adapter, typically known as an FTDI device.

They come in a variety of product designs. Should be inexpensive and sooner or later you'll want to have one or more…

Or, you can use an UNO as an FTDI. I've not done that, so I cannot give you a step-by-step.

a7

1 Like

I've ordered one those cables, should arrive sometime next week.

Could you check if your Arduino is reset every time the function serial_comm(count) is called?

It closes and reopens the serial port which may force a reset.

You could try to open and close the com port outside of that function...

Good luck!
ec2021

1 Like

That's a good idea. I didn't make much of the Python code.

Another thing you could try is using a serial terminal program instead of Python, just for testing.

Leave the Arduino serial monitor window closed, and after you uplaod you code, hook up to the Arduino using the same port on your PC through either PuTTY or CoolTerm, both just terminal emulators.

a7

1 Like