SparkFun Forums 

Where electronics enthusiasts find answers.

For the discussion of Arduino related topics.
#145746
Hi,
Scott here from Salem. My program goal. Press 1 on the key board and an led lights up on the arduino. Press 2 and it goes off. Press anything else and the command port prints out "invalid". I then want to clear the serial port to erase anything else, because if I press a bunch of numbers e.g. 3456, it prints out invalid several times. I would like it to print out invalid only once. I read that Serial.flush() no longer works. I have tried byte = discard Serial.read() but this does not work. Can someone help me with how to flush the serial port of the remaining data?

Here is the code;
Code: Select all
  int val = 0;
int led = 13;
void setup()
{
  Serial.begin(9600);
  pinMode(led,OUTPUT);
}

void loop()

{
  while(Serial.available()== 0);  //stays on this line until something's in the buffer
  val = Serial.read() - 48;  // gives me the correct ascii output character
  
  Serial.println(val);
  
  if(val == 1)
  {
    digitalWrite(led,HIGH);
    
  }
    else if (val == 2)
    {
      digitalWrite(led,LOW);
    } 
      else
      {
        Serial.println("invalid");
        
        for (int i = 0; i < 18; i++)  // This is where I want to flush any remaing data
        byte discard = Serial.read();
      }
      
}    

thank you,
Scott
#145752
Hi Philba,
Thanks for responding. I was trying to follow Jeremy Blum's tutorial on utube and he used serial.flush to erase the buffer. Perhaps I may need this on some future project. Since serial.flush is not longer used to erase the buffer. Is there another way to erase what's in the buffer?
Thanks,
Scott
#145796
Code: Select all
void serial_flush_buffer()
{
  while (Serial.read() >= 0)
   ; // do nothing
}
Note that this doesn't flush "characters in transit." If you send "3456" at 9600bps, the 5 will arrive avour 1ms after the 4, and won't get flushed if you call the function immediately after receiving the 4. (however, this is the way the old flush function worked as well.)
#162857
westfw wrote:
Code: Select all
void serial_flush_buffer()
{
  while (Serial.read() >= 0)
   ; // do nothing
}
Note that this doesn't flush "characters in transit." If you send "3456" at 9600bps, the 5 will arrive avour 1ms after the 4, and won't get flushed if you call the function immediately after receiving the 4. (however, this is the way the old flush function worked as well.)
What if your serial input is coming faster than you can read? Point being, you are going to waste precious processing time 'flushing' the serial buffer by performing a read for each piece of data in the buffer (when all you want to do is reset your buffer index to 0 so serial.available() returns 0). I just realized that they completely changed the serial.flush() function...which was probably a bad idea since 'flush' means to empty! Now flush 'waits' for transmitting data to complete.

I'm looking into the original flush() operation, will post a fix comparable to the original function (if I can come up with one)
#162858
For anyone curious about the serial.flush() code change...

New (Arduino 1.0+ Serial.Flush())
Code: Select all
void HardwareSerial::flush()
{
  while (_tx_buffer->head != _tx_buffer->tail)
    ;
}
Old (Arduino 23- Serial.Flush())
Code: Select all
void HardwareSerial::flush()
{
  _rx_buffer->head = _rx_buffer->tail;
}
What I did to return this function to my current Arduino version, was add a new function to HardwareSerial.h.
Code: Select all
virtual void flushRX(void);
Then, add the above (old) flush() function to HardwareSerial.cpp (but name it flushRX). Worked like a charm.
Code: Select all
void HardwareSerial::flushRX()
{
  _rx_buffer->head = _rx_buffer->tail;
}
I did not realize they changed the function, and have been debugging code that USED to work... and suddenly stopped working.

Good Luck!
#192292
I did as advised, but there was an error:

C:\Program Files\Arduino\hardware\arduino\avr\cores\arduino\HardwareSerial.cpp:192:35: error: request for member 'tail' in '*(unsigned char*)(&((HardwareSerial*)this)->HardwareSerial::_rx_buffer)', which is of non-class type 'unsigned char'

_rx_buffer->head = _rx_buffer->tail;

^

exit status 1

I added a line in HardwareSerial.cpp:

void HardwareSerial::flushRX()
{
_rx_buffer->head = _rx_buffer->tail;
}
void HardwareSerial::flush()
{
// If we have never written a byte, no need to flush. This special
// case is needed since there is no way to force the TXC (transmit
// complete) bit to 1 during initialization
if (!_written)
return;

while (bit_is_set(*_ucsrb, UDRIE0) || bit_is_clear(*_ucsra, TXC0)) {
if (bit_is_clear(SREG, SREG_I) && bit_is_set(*_ucsrb, UDRIE0))
// Interrupts are globally disabled, but the DR empty
// interrupt should be enabled, so poll the DR empty flag to
// prevent deadlock
if (bit_is_set(*_ucsra, UDRE0))
_tx_udr_empty_irq();
}

I added a line in HardwareSerial.h:
public:
inline HardwareSerial(
volatile uint8_t *ubrrh, volatile uint8_t *ubrrl,
volatile uint8_t *ucsra, volatile uint8_t *ucsrb,
volatile uint8_t *ucsrc, volatile uint8_t *udr);
void begin(unsigned long baud) { begin(baud, SERIAL_8N1); }
void begin(unsigned long, uint8_t);
void end();
void flushRX(void);
virtual int available(void);
virtual int peek(void);
virtual int read(void);
int availableForWrite(void);
virtual void flush(void);
virtual size_t write(uint8_t);
inline size_t write(unsigned long n) { return write((uint8_t)n); }
inline size_t write(long n) { return write((uint8_t)n); }
inline size_t write(unsigned int n) { return write((uint8_t)n); }
inline size_t write(int n) { return write((uint8_t)n); }
using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool() { return true; }

// Interrupt handlers - Not intended to be called externally
inline void _rx_complete_irq(void);
void _tx_udr_empty_irq(void);
};
Please help me to understand whats wrong?