Attempting to clear tx-rx buffer throws errors about "NonCopyable resource"s

I’m trying to make stepper wheels spin but the longer I hold the move key, the longer the wheel moves, but I want the wheel to stop moving as soon as I stop pressing the move key. I think the problem is tx-rx buffering inputs so I’m trying to clear the buffered inputs but when i try to empty the tx-rx line I get the following errors:

Invalid copy construction of a NonCopyable resource: mbed::NonCopyable<T>::NonCopyable(const mbed::NonCopyable<T>&) [with T = mbed::SerialBase]
Invalid copy construction of a NonCopyable resource: mbed::NonCopyable<T>::NonCopyable(const mbed::NonCopyable<T>&) [with T = mbed::FileHandle]
Invalid copy construction of a NonCopyable resource: mbed::NonCopyable<T>::NonCopyable(const mbed::NonCopyable<T>&) [with T = mbed::FileBase]
Invalid copy construction of a NonCopyable resource: mbed::NonCopyable<T>::NonCopyable(const mbed::NonCopyable<T>&) [with T = mbed::FileLike]
Invalid copy construction of a NonCopyable resource: mbed::NonCopyable<T>::NonCopyable(const mbed::NonCopyable<T>&) [with T = mbed::Stream]
Invalid copy construction of a NonCopyable resource: mbed::NonCopyable<T>::NonCopyable(const mbed::NonCopyable<T>&) [with T = mbed::Serial]
Invalid copy construction of a NonCopyable resource: mbed::NonCopyable<T>::NonCopyable(const mbed::NonCopyable<T>&) [with T = PlatformMutex]

Code im using:

int main() {

//Wheels are on unless excplictly set off with EN = 0
xEN = 1;
yEN = 1;

//Command to make connection from pi(picocom --baud 9600 /dev/ttyS0)

int i = 0;
pc.printf("This is the wheel drive program. Press 'w' to go forwards, 's' to go back, and 'q' to stop\n");
while(1) {
        char dirKey = pc.getc();

        //debug to see if inputs are being detected
        //pc.putc(pc.getc());
        if(dirKey == 'w') {
            //Allows wheels to move
            xEN = 0;
            yEN = 0;

            //Sets direciton to hopefully forward
            xDIR = 0;
            yDIR = 0;
            for(int i = 0; i < 100; i++){
                xSTP = 1;
                ySTP = 1;
                wait(0.001);
                xSTP = 0;
                ySTP = 0;
                wait(0.001);
            }
            //Should hopefully flush tx-rx command buffer so wheel commands only execute when pressing w key
            fflush(pc);
            
        }
    }
}

is using fflush(pc); not the right command or is it something else?

Hello Ryan,

How do you define the pc object? The Serial class is not available in Mbed OS 6 anymore. You should use the BufferedSerial or UnbufferedSerial instead. The fflush(FILE* file) function expects a pointer to a FILE as its argument. Unfortunately, neither of those classes has a FILE type member available. Hence, fflush cannot be used anymore :frowning: I would suggest to try the UnfufferedSerial.

Best regards, Zoltan

im using platformio so I only have access to mbed 5 OS. Is there a way to clear buffer in mbed 5?

Unless there is a HAL function that clears the FIFO buffer, I think you need to keep reading until it’s empty.

Maybe you read the buffer and update a command character in an ISR? Once the motor control routine ends, you can nullify the command char. This way, the motor stops as soon as you release the key.

volatile char command;

void fwd() { /* */ }
void bwd() { /* */ }

void onKeyPress() {
    command = pc.getc();
}

int main() {

    pc.attach(&onKeyPress, Serial::RxIrq);

    while (1) {
    	switch (command) {
		case 'w':
			fwd();
			command = '\0';
			break;
		case 's':
			bwd();
			command = '\0';
			break;
		default: 
			break;
	    }
    }
}
1 Like

The pc variable doesn’t seem to be a pointer but fflush expects a pointer to FILE type argument. So try:

fflush(&pc);

Ah, your solution works perfectly! I modified it slightly to remove input bouncing, but now it works as it should! Why does replacing command with ‘\0’; clear the buffer though?

#include "mbed.h"
#include <iostream> 
#include <algorithm> 

using namespace std; 

    volatile char command;

    Serial pc(P0_2, P0_3, 9600);


    void fwd() { 
        //Allows wheels to move
        xEN = 0;
        yEN = 0;

        //Sets direciton to hopefully forward
        xDIR = 0;
        yDIR = 0;

        for(int i = 0; i < 100; i++){
                    xSTP = 1;
                    ySTP = 1;
                    wait(0.001);
                    xSTP = 0;
                    ySTP = 0;
                    wait(0.001);
                }
    }


    void onKeyPress() {
        command = pc.getc();
    }

    void commandManager(char c[]){
        switch(c[0]){
            case 'w':
                fwd();
                //pc.putc(c[0]);
                command = '\0';
                break;
            default:
                break;
        }
    }

    int main() {

    //Wheels are on unless excplictly set off with EN = 0
    xEN = 1;
    yEN = 1;

    //Command to make connection from pi(picocom --baud 9600 /dev/ttyS0)

    pc.attach(&onKeyPress, Serial::RxIrq);

    int debounceTimeAveragingLength = 100;

    //Make array of 100 char commands to store, 1 milisecond each, which ever one has the highest average gets executed. This is to stop button bouncing.
    char test [debounceTimeAveragingLength];




    //pc.printf("This is the wheel drive program. Press 'w' to go forwards, 's' to go back, and 'q' to stop\n");
    while(1) {
        for(int i = 0; i < debounceTimeAveragingLength; i ++){
            test[i] = command;
            wait(0.001);
            }
            commandManager(std::max_element(test, test + debounceTimeAveragingLength - 1));
        }        



}

Writing '\0' doesn’t clear the buffer. The variable command is the last char you read from the RX buffer. Since you now read in the ISR, command gets updated as soon as RX sees new data.

At the end of the motor control routine, you want to set command to whatever char that is not a valid command ('w', 's', 'q'). It could be 'a', 'b', etc. I used '\0' because I wanted to be explicit about my intention.

Hello Kentaro,

I don’t use Mbed OS 5 anymore so I’m not able to verify it. I could be mistaken, but for the sake of completeness:

Since you now read in the ISR, command gets updated as soon as RX sees new data.

I think that works when the UART FIFO is empty. However, if some bytes were retained in FIFO from the previous key press event then:

  • If the same key is pressed then still everything should be OK because pc.getc() gets the last character from the FIFO and that matches the first one which has been just received and added to the front end of the FIFO.

  • However when a different key is pressed then because the new character is added to the front end of the FIFO and pc.getc() gets the last character from the FIFO’s tail (retained there from the previous key press event) the command will not match the pressed key.