ArduinoSerialInput

From arrizza.org wiki

Jump to navigation Jump to search
Previous ⇦ ArduinoSerialOutput Arduino ⇫ Up ArduinoSOS ⇨ Next

Overview

This sketch adds serial port input.

It gets a single character from the serial port and prints some information about it. If it's a 'b' then it also blinks the LED.

Git repository

https://bitbucket.org/arrizza/arduinoserialinput

git clone git@bitbucket.org:arrizza/arduinoserialinput.git

Setup

The setup function is roughly the same as that for ArduinoSerialOutput except the initial message is now "serial input" and the LED is internalized too, see ArduinoLedBlink

Main Loop

The main loop checks to see if a character is available on the serial port. If not, it exits the loop() function immediately. The loop() function is called continually, so this bit of code is run at maximum speed.

The .available() call returns the number of bytes waiting in the serial port buffer

if (Serial.available() <= 0)
    {
    return;
    }

If there is at least one byte waiting, it's read. The read() function simply returns the next byte from the serial port buffer. the "char ch" declares that byte to be a character and initially sets it to 0 (a "null character")

 char ch = 0;
 // ... other code ...
 ch = Serial.read();

Then the value of the byte is printed in hexadecimal (aka "hex" - base 16) and in decimal (our normal base 10). the character itself is also printed.

  Serial.print("recv: 0x");
  Serial.print(ch, HEX);
  Serial.print("=");
  Serial.print(ch, DEC);
  Serial.print("=");
  Serial.println(ch);

In the CLion Serial Monitor (see Arduino Setup#Install CLion), enter "abc" in the input text area and make sure the dropdown says "No line ending". Then press Send. You should see the character information for 'a', 'b' and 'c'.

recv: 0x61=97=a
recv: 0x62=98=b
blink
recv: 0x63=99=c

This output shows that the 'a' is hex 0x61 (the "0x" prefix is just a reminder that it is in hex). It is decimal 97. And it is displayed on the screen like so: "a". To see all of the character values, you can see [1] or type them in to the Serial Monitor.

When the code sees the character 'b', it prints :"blink" and blinks the LED 3 times

  if (ch == 'b')
    {
    // blink the LED
    Serial.println("blink");
    for(int i = 0; i < 3; ++i)
      {
      digitalWrite(13, HIGH);
      delay(200);
      digitalWrite(13, LOW);
      delay(200);
      }
    }


Notes

  • on the Mega, any serial port communication already blinks an LED. It is right next to LED attached to pin 13. The pin 13 LED blinks a little slower than the communication LED.
  • the Serial Monitor in CLion is ok when you want to send a string of characters down to the Arduino. You enter the characters and then press Send. But if you want it more interactive, use PuTTY. Set up putty as described here Arduino Setup#Setup putty and then open up a PuTTY session. As you type in characters one-by-one, they'll be sent to the Arduino and it will respond immediately.

Automate It!

Install Ruby

  • if you don't have ruby installed, install it now
  sudo apt-get install ruby
  ruby -v
      ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]  
      # your version may be slightly different
  • install the ruby serial port gem
sudo gem install serialport

gem list serialport

*** LOCAL GEMS ***
serialport (1.3.1)   
# your version may be slightly different

Run the ruby script

  • run auto_test.rb
$ ruby auto_test.rb 
recv: 0x48=72=H
recv: 0x65=101=e
recv: 0x6C=108=l
recv: 0x6C=108=l
recv: 0x6F=111=o
recv: 0x20=32= 
recv: 0x57=87=W
recv: 0x6F=111=o
recv: 0x72=114=r
recv: 0x6C=108=l
recv: 0x64=100=d
recv: 0x21=33=!

How does it work?

  • It sets up the serial port
@port = '/dev/ttyACM0'
parity = SerialPort::NONE
@mc    = SerialPort.new(@port, 115_200, 8, 1, parity)
  • it's unlikely, but there could be characters in the serial port from a previous session, so clean them out
@mc.read_timeout = -1
@mc.flush_input
@mc.flush_output

# read a couple of times to get rid of garbage
@mc.getbyte
@mc.getbyte

# reset the read_time to 1s
@mc.read_timeout = 1000
  • it takes a string "Hello World!" and sends it character by character to the Arduino

s = "Hello World!"
s.each_byte do |ch|
  @mc.putc(ch)
  read_response()
end
  • after each character it waits for the Arduino's response. The function read_response() does that work with a simple loop to read the input a character at a time until a linefeed. The linefeed has ASCII code 0x0A and is sent by the Arduino by the println() function (see above)

The .chr() ruby function converts a byte (an integer) into a character (a letter)

  loop do
    # get the next byte
    ch = @mc.getbyte

    # if we got nothing from the Arduino, 
    # it may have timed out, try again
    continue if ch.nil?
    
    # the response ends on a linefeed from the Arduino
    if ch == 0x0A
      puts
      return
    end

    # print the character as a character (not a byte) on your PC
    print(ch.chr)
  end
  • we're done with it, so close the serial port
@mc.close
Personal tools