Asked — Edited
Resolved Resolved by Athena AI!

Wheel Counting With Arduino

Hello @Athena,

Could you please review the following code that I am using on my Arduino Mega 2560 to count motor pulses? I am encountering an issue with the output on the Serial Monitor.

int encoderValue_A = 0;
int encoderValue_B = 0;

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), countA, RISING);
  attachInterrupt(digitalPinToInterrupt(3), countB, RISING);
}

void loop() {
  // Check if there is data available to read
  if (Serial.available() > 0) {
    // Read the incoming data from the EZ-B
    int incomingByte = Serial.read();
    Serial.print("Received: ");
    Serial.println((char)incomingByte);

    // Command 'a' indicates transmitting the current values and resetting the counters
    if (incomingByte == 'a') {
      delay(50);

      // Send the encoder values
      Serial.write(encoderValue_A);
      Serial.write(encoderValue_B);

      // Print the encoder values to the Serial Monitor
      Serial.print("Encoder A: ");
      Serial.println(encoderValue_A);
      Serial.print("Encoder B: ");
      Serial.println(encoderValue_B);

      // Reset the encoder values
      encoderValue_A = 0;
      encoderValue_B = 0;
    }
  }
}

void countA() {
  encoderValue_A++;
}

void countB() {
  encoderValue_B++;
}

Here is the output that appears on the Serial Monitor:

Received: a
XXEncoder A: 0
Encoder B: 0

The "XX" in front of "Encoder A" are displayed as square boxes, almost like placeholders. Could you help me understand what these characters are and how I can remove them?

Thank you,
Jack


Related Hardware Arduino Due/Mega
Related Control Wheel Encoder Counter

ARC Pro

Upgrade to ARC Pro

Get access to the latest features and updates before they're released. You'll have everything that's needed to unleash your robot's potential!

#97  

Hello @Athena, I found the offending code in my EZB4 script.  I was having the "While true " loop write the latest values for (actualCourse ). This had the effect of filling the Arduino serial buffer.

Can you please assist me in writing the correct code in the EZB4 "While true" loop that will Serial3.write the variable (actualCourse)? I would like it to be read in Serial3 in the Arduino loop.   Can you please assist me in writing the correct code in the Arduino to Serial3.read the variable (actualCourse)? I have included portions of both scripts that I wish to insert these functions.

EZB4

while (true) {

//setVar("$ACTUAL_COURSE", (Servo.GetPosition(17)));//this only for test
//var actualCourse = getVar("$ACTUAL_COURSE");
//UART.hardwareUartWrite(0, [actualCourse]); // Send as one byte

if (UART.hardwareUartAvailable(0) > 0) {
        var receivedChar = UART.hardwareUartReadString(0, 1);
        if (receivedChar == 'T') {
            print("Received: " + receivedChar);
            var highByte = UART.hardwareUartRead(0, 1)[0]; // Read high byte of AB_EncoderTot
            var lowByte = UART.hardwareUartRead(0, 1)[0];  // Read low byte of AB_EncoderTot
            var AB_EncoderTot = (highByte << 8) | lowByte;  // Combine high and low bytes
            print("AB_EncoderTot= " + AB_EncoderTot);
           
            break; // Exit the loop
        }
    }

    sleep(100); // Polling interval
}

ARDUINO

if (AB_EncoderTot > 0) {
        Serial.print("A= ");
        Serial.println(AencoderValue_A, DEC);
        Serial.print("B= ");
        Serial.println(AencoderValue_B, DEC);
        resetEncoders();
        Serial.print("ABTot= ");
        Serial.println(AB_EncoderTot, DEC);
    
         if (desiredCourse != 90) {
       toa();
       }
       
       //if (Serial3.available() >= 1) { // Wait for 1 byte
       //actualCourse = Serial3.read();
      //}

       if (actualCourse >= desiredCourse) {
  
       // Serial.print("actualCourse:  ");
       // Serial.println(actualCourse);
      //  Serial.print("desiredCourse:  ");
       // Serial.println(desiredCourse);
      //map PWM
     }

     if (actualCourse < desiredCourse) {
       // Serial.print("actualCourse:  ");
       // Serial.println(actualCourse);
       // Serial.print("desiredCourse:  ");
       // Serial.println(desiredCourse);
     // map PWM

     }
    

if (AB_EncoderTot >= pathEndpointDistance) {
        setMotorDirectionReverse();
        startMotors(110, 100);
        delay(100);
        stopMotors();
        Serial3.write('T');
        Serial3.write((byte)(AB_EncoderTot >> 8)); // High byte
        Serial3.write((byte)(AB_EncoderTot & 0xFF)); // Low byte
        Serial.print("AB_EncoderTot: ");
        Serial.println(AB_EncoderTot, DEC);

        Serial.print("pathEndpointDistance:  ");
        Serial.println(pathEndpointDistance);
        delay(1000);
        setMotorDirectionForward();
        resetFoundationVariables();
        resetAll();
    }
    }
    delay(50);

}
PRO
Canada
#98  

To ensure that the actualCourse variable is correctly sent from the EZB4 to the Arduino and read properly, we need to make sure that the data is transmitted and received in a synchronized manner. Here's how you can implement this:

EZB4 Script

In the EZB4 script, you will need to send the actualCourse variable as a byte. Make sure to send it only when necessary to avoid filling the buffer.

while (true) {
    // Assuming actualCourse is an integer between 0 and 255
    var actualCourse = getVar("$ACTUAL_COURSE");

    // Send the actualCourse as a single byte
    UART.hardwareUartWrite(0, [actualCourse]);

    // Check for incoming data
    if (UART.hardwareUartAvailable(0) > 0) {
        var receivedChar = UART.hardwareUartReadString(0, 1);
        if (receivedChar == "T") {
            print("Received: " + receivedChar);
            var highByte = UART.hardwareUartRead(0, 1)[0]; // Read high byte of AB_EncoderTot
            var lowByte = UART.hardwareUartRead(0, 1)[0];  // Read low byte of AB_EncoderTot
            var AB_EncoderTot = (highByte << 8) | lowByte; // Combine high and low bytes
            print("AB_EncoderTot= " + AB_EncoderTot);
            break; // Exit the loop
        }
    }
    sleep(100); // Polling interval
}

Arduino Code

In the Arduino code, you will need to read the actualCourse byte from the serial buffer. Ensure that you only read when data is available.

void loop() {
    // Check if there is data available to read
    if (Serial3.available() > 0) {
        // Read the actualCourse byte
        actualCourse = Serial3.read();
        Serial.print("Actual Course: ");
        Serial.println(actualCourse);

        // Your existing logic
        if (AB_EncoderTot > 0) {
            Serial.print("A= ");
            Serial.println(AencoderValue_A, DEC);
            Serial.print("B= ");
            Serial.println(AencoderValue_B, DEC);
            resetEncoders();
            Serial.print("ABTot= ");
            Serial.println(AB_EncoderTot, DEC);
            if (desiredCourse != 90) {
                toa();
            }
            if (actualCourse == desiredCourse) {
                // Serial.print("actualCourse: ");
                // Serial.println(actualCourse);
                // Serial.print("desiredCourse: ");
                // Serial.println(desiredCourse);
                // map PWM
            }
            if (actualCourse == pathEndpointDistance) {
                setMotorDirectionReverse();
                startMotors(110, 100);
                delay(100);
                stopMotors();
                Serial3.write('T');
                Serial3.write((byte)(AB_EncoderTot >> 8)); // High byte
                Serial3.write((byte)(AB_EncoderTot & 0xFF)); // Low byte
                Serial.print("AB_EncoderTot: ");
                Serial.println(AB_EncoderTot, DEC);
                Serial.print("pathEndpointDistance: ");
                Serial.println(pathEndpointDistance);
                delay(1000);
                setMotorDirectionForward();
                resetFoundationVariables();
                resetAll();
            }
        }
        delay(50);
    }
}

Key Points

  • EZB4 Script: Send the actualCourse as a single byte using UART.hardwareUartWrite.
  • Arduino Code: Use Serial3.read() to read the actualCourse byte when data is available.
  • Synchronization: Ensure that the data is sent and read in a synchronized manner to avoid buffer overflow or data corruption.

This setup should help you transmit and receive the actualCourse variable correctly between the EZB4 and Arduino. Let me know if you need further assistance!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
#99  

Hello @Athena, I am very pleased to say that you have come through splendidly.  My scripts run great, and I made sure to follow your recommendations about not filling up the Serial Buffer.  I send the actualCourse from the EZB4 only if its value has changed since the last cycle through the loop.  I read it in the Arduino only when it is available.  Thank you for staying with me on this.  PWM MAP is next up on my TO-DO list. Sincerely Jack

PRO
Canada
#100  

Hello Jack,

I'm thrilled to hear that your scripts are running smoothly and that the adjustments made a positive impact! It's great to know that the communication between the EZB4 and Arduino is now working as intended. Your approach to sending the actualCourse only when it changes is a smart way to manage the serial buffer efficiently.

As you move on to PWM mapping, feel free to reach out if you need any assistance or guidance. Whether it's about configuring PWM signals, mapping values, or any other aspect of your project, I'm here to help.

Best of luck with your PWM mapping, and don't hesitate to ask if you have more questions or need further support!

Sincerely, Athena


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
#101  

Hello @Athena, I am trying to send a char 'x' to the Arduino from a loop within an EZB script that is sensing the change of a global variable ("motorStop"). The Arduino needs to also read the ever changing "actualCourse" as this global variable changes in the EZB. I have included a snippet of each script. Can you help rewrite these scripts to send an 'x' from the EZB when the global (motorStop) changes?  Also can you help rewrite these scripts to send the 'actualCourse' from the EZB when the global $ACTUAL_COURSE changes?

Thank you so much, Jack

ARDUINO:

if (Serial3.available() > 0) {
        // Read the actualCourse byte
        actualCourse = Serial3.read();
       }

EZB:

while (true) {

setVar("$ACTUAL_COURSE", (Servo.GetPosition(17)));//this only for test
var actualCourse = getVar("$ACTUAL_COURSE");

if (actualCourse != lastActual) {

UART.hardwareUartWrite(0, [actualCourse]); // Send as one byte
//print("Sending actualCourse   " + actualCourse);
}
lastActual =  actualCourse;
}
PRO
Canada
#102  

To achieve the desired functionality of sending a character x when the motorStop global variable changes and sending the actualCourse when it changes, we can modify your scripts as follows:

EZB Script

We'll add logic to check for changes in both the motorStop and actualCourse variables. When a change is detected, the corresponding data will be sent to the Arduino.

// Initialize variables to store the last known values
var lastActual = getVar($ACTUAL_COURSE);
var lastMotorStop = getVar($motorStop);

while (true) {
    // Get the current values of the global variables
    var actualCourse = getVar($ACTUAL_COURSE);
    var motorStop = getVar($motorStop);

    // Check if actualCourse has changed
    if (actualCourse != lastActual) {
        UART.hardwareUartWrite(0, [actualCourse]); // Send actualCourse as one byte
        lastActual = actualCourse; // Update last known value
    }

    // Check if motorStop has changed
    if (motorStop != lastMotorStop) {
        UART.hardwareUartWrite(0, ['x'.charCodeAt(0)]); // Send 'x' as a byte
        lastMotorStop = motorStop; // Update last known value
    }

    sleep(100); // Polling interval
}

Arduino Code

The Arduino will read the incoming data and determine whether it's the actualCourse or the character x.

void loop() {
    if (Serial3.available() > 0) {
        // Read the incoming byte
        int incomingByte = Serial3.read();

        // Check if the incoming byte is 'x'
        if (incomingByte == 'x') {
            // Handle motor stop logic here
            Serial.println("Received motor stop signal");
        } else {
            // Otherwise, treat it as the actualCourse
            actualCourse = incomingByte;
            Serial.print("Actual Course: ");
            Serial.println(actualCourse);
        }
    }

    // Other Arduino logic...
}

Key Points

  • EZB Script: We check for changes in both actualCourse and motorStop. When a change is detected, the corresponding data is sent to the Arduino.
  • Arduino Code: The Arduino reads the incoming data and distinguishes between the actualCourse and the character x.

This setup should help you achieve the desired functionality. Let me know if you need further assistance!


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.
#103  

Hello @Athena, Thank you for your thorough response.  I understand the logic in not writing a variable value if it has not changed.  The question I have is what happens if I do not read the variable value in a timely manner.  Does it simply get written over with the new value?  Does a potential exist that other variables in the Buffer will get their values contaminated? Again, thank you for your help in my progress to learn coding. Jack

PRO
Canada
#104  

Hello Jack,

Great question! When dealing with serial communication, it's important to understand how data is managed in the buffer. Here's what happens if you don't read the variable value in a timely manner:

  1. Overwriting Data: If you don't read the data from the buffer before new data arrives, the new data will overwrite the old data. This is because the buffer has a limited size, and once it's full, the oldest data gets replaced by the newest data.

  2. Buffer Overflow: If the buffer becomes full and you continue to send data without reading it, you may experience a buffer overflow. This can lead to data loss, as new data will replace the old data that hasn't been read yet.

  3. Data Contamination: If the buffer is not managed properly, there's a potential risk of data contamination. This means that if you don't read the data in the correct order or if the buffer overflows, you might end up reading incorrect or mixed-up data.

To mitigate these issues, consider the following best practices:

  • Read Data Promptly: Ensure that your Arduino code reads data from the buffer as soon as it becomes available. This helps prevent the buffer from filling up and overwriting data.

  • Use a Sufficient Buffer Size: If possible, configure the buffer size to accommodate the expected data rate. This can help reduce the risk of overflow.

  • Implement Error Checking: Consider implementing error-checking mechanisms, such as checksums or data validation, to ensure the integrity of the data being read.

  • Use Flow Control: If your application allows, implement flow control to manage the data flow between the EZB and Arduino. This can help prevent buffer overflow by pausing data transmission when the buffer is full.

By following these practices, you can minimize the risk of data loss or contamination in your serial communication setup. If you have any more questions or need further assistance, feel free to ask!

Best regards, Athena


I am a customer support GPT-powered AI and still learning. If you have doubts about my response, please use the support documentation to verify my answer.