Using two different readStringUntil "characters"

I guess what you’re actually attempting there is to move the line()'s current coordinates w/ the values received from Serial, right? :thinking:

I see that at the Arduino’s side, you use map() in order to constrain the sent values within the range of [-10 to 10]. :world_map:

My bet is that those values mean how much farther to draw the next line()'s coordinates in relation to the previous 1.:horse_racing:

So I’ve made some changes to my previous Serial posted sketch. :man_mechanic:

Now, instead of vals[], we’re gonna have a PVector mov variable:

Variable mov is gonna store the values received from Serial::readString() using its method PVector::set():

void serialEvent(final Serial s) {
  mov.set(float(splitTokens(s.readString())));
  redraw = true;
}

We’re also gonna need a 2nd PVector named vec, which’s gonna store canvas’ current coordinates:
final PVector vec = new PVector(), mov = new PVector();

And we’re gonna initialize it w/ the canvas’ center coordinates:
vec.set(width>>1, height>>1);

Now, every time a new coordinate pair is received within serialEvent(), we’re gonna use PVector::add() method in order to move vec’s current coordinates to a new 1, passing mov as its argument:

line(vec.x, vec.y, vec.add(mov).x, vec.y);

Here’s the complete sketch “Serial TSV-Reading Line-Drawing”. Have fun: :smile_cat:

/**
 * Serial TSV-Reading Line-Drawing (v1.0)
 * GoToLoop (2019/May/02)
 *
 * https://Discourse.Processing.org/t/
 * using-two-different-readstringuntil-characters/10769/21
 */

import processing.serial.Serial;

static final String PORT = "COM12";
static final int BAUDS = 115200, INDEX = 1;

final PVector vec = new PVector(), mov = new PVector();

void setup() {
  size(1300, 700);
  noLoop();

  stroke(-1);
  clear();

  vec.set(width>>1, height>>1);

  final String[] ports = Serial.list();
  printArray(ports);

  new Serial(this, PORT, BAUDS).bufferUntil(ENTER);
  //new Serial(this, ports[INDEX], BAUDS).bufferUntil(ENTER);
}

void draw() {
  line(vec.x, vec.y, vec.add(mov).x, vec.y);

  if (outtaBounds(vec)) {
    vec.set(width>>1, height>>1);
    System.err.println("Coords reset back to center of canvas!");
  }

  println(vec, mov);
}

boolean outtaBounds(final PVector v) {
  return v.x < 0 | v.x >= width | v.y < 0 | v.y >= height;
}

void serialEvent(final Serial s) {
  mov.set(float(splitTokens(s.readString())));
  redraw = true;
}

Hmm I was actually prepping for a reply on the other thread I asked. It involved having potentiometer input from Arduino and feeding it to processing to draw lines

I have been a bit confused because it’s not behaving like ContinuousLines demo, rather it’s just really weird lines…

Yes!
Yes! It’s 10 and -10 to interact with the “coordinates” on screen
YES!!

So I’ll look into this and thank you very much for all the support and help! Thanks for being patient too

  • Now that it seems all’s been sorted out, how about some optimization?
  • The range [-10 to 10] is so small (5-bit) that it comfortably fits in a byte (8-bit).
  • So, rather than send those 2 small values as TSV, w/ lotsa extra separator characters, we can simply send 2 bytes only using Serial.write():
    https://www.Arduino.cc/reference/en/language/functions/communication/serial/write/
  • We just need to create a char array of length = 2: signed char xy[2];
#define BAUDS 115200
#define DELAY 10
#define BYTES 2

#define MIN 0
#define MAX 1023
#define MIN_RANGE -10
#define MAX_RANGE 10

signed char xy[BYTES];

void setup() {
  Serial.begin(BAUDS);
}

void loop() {
  xy[0] = map(analogRead(A1), MIN, MAX, MIN_RANGE, MAX_RANGE);
  xy[1] = map(analogRead(A0), MIN, MAX, MIN_RANGE, MAX_RANGE);

  Serial.write(xy);
  delay(DELAY);
}
/**
 * Serial readBytes() Line-Drawing (v1.0)
 * GoToLoop (2019/May/02)
 *
 * https://Discourse.Processing.org/t/
 * using-two-different-readstringuntil-characters/10769/23
 */

import processing.serial.Serial;

static final String PORT = "COM12";
static final float FPS = 100;
static final int BAUDS = 115200, INDEX = 1, BYTES = 2;
static final color STROKE = -1;

final byte[] xy = new byte[BYTES];
final PVector vec = new PVector(), mov = new PVector();

void setup() {
  size(1300, 700);
  noLoop();
  frameRate(FPS);

  stroke(STROKE);
  clear();

  vec.set(width>>1, height>>1);

  final String[] ports = Serial.list();
  printArray(ports);

  new Serial(this, PORT, BAUDS).buffer(BYTES);
  //new Serial(this, ports[INDEX], BAUDS).buffer(BYTES);
}

void draw() {
  line(vec.x, vec.y, vec.add(mov).x, vec.y);

  if (outtaBounds(vec)) {
    vec.set(width>>1, height>>1);
    System.err.println("Coords reset back to center of canvas!");
  }

  println(vec, mov);
}

boolean outtaBounds(final PVector v) {
  return v.x < 0 | v.x >= width | v.y < 0 | v.y >= height;
}

void serialEvent(final Serial s) {
  s.readBytes(xy);
  mov.set(xy[0], xy[1]);
  redraw = true;
}
1 Like

@GoToLoop ,

Your Arduino code from previous post above has errors.

Working (simplified) version:

//unsigned char xy[2];  //ok
//byte xy[2];  //ok
uint8_t xy[2]; //ok

//signed char xy[2];  // Error!

void setup() 
  {
  Serial.begin(9600);
  }

void loop() 
  {
  xy[0] = 255;
  xy[1] = 128;

  Serial.write(xy, 2);
  delay(1000);
  }

Reference:

:)

Well, I’m far of being knowledgeable in C/C++ so I dunno the details. :woozy_face:

However I guess in my original C code from 3 years ago the range [-10…+10] (MIN_RANGE & MAX_RANGE) used by map() is comfortably within a signed char datatype, isn’t it? :thinking:

Hello @GoToLoop,

Your Arduino code compiles with errors:

Errors

Arduino: 1.8.15 (Windows 10), Board: "Arduino Mega or Mega 2560, ATmega2560 (Mega 2560

D:\Users\GLV\Documents\Arduino\Serial_send_floats_1_0_0\Serial_send_floats_1_0_0.ino: In function ‘void loop()’:

Serial_send_floats_1_0_0:20:18: error: no matching function for call to ‘write(signed char [2])’

Serial.write(xy);

              ^

In file included from D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Arduino.h:233:0,

             from sketch\Serial_send_floats_1_0_0.ino.cpp:1:

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:129:20: note: candidate: virtual size_t HardwareSerial::write(uint8_t)

 virtual size_t write(uint8_t);

                ^~~~~

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:129:20: note: conversion of argument 1 would be ill-formed:

D:\Users\GLV\Documents\Arduino\Serial_send_floats_1_0_0\Serial_send_floats_1_0_0.ino:20:18: warning: invalid conversion from ‘signed char*’ to ‘uint8_t {aka unsigned char}’ [-fpermissive]

Serial.write(xy);

              ^

In file included from D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Arduino.h:233:0,

             from sketch\Serial_send_floats_1_0_0.ino.cpp:1:

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:130:19: note: candidate: size_t HardwareSerial::write(long unsigned int)

 inline size_t write(unsigned long n) { return write((uint8_t)n); }

               ^~~~~

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:130:19: note: conversion of argument 1 would be ill-formed:

D:\Users\GLV\Documents\Arduino\Serial_send_floats_1_0_0\Serial_send_floats_1_0_0.ino:20:18: warning: invalid conversion from ‘signed char*’ to ‘long unsigned int’ [-fpermissive]

Serial.write(xy);

              ^

In file included from D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Arduino.h:233:0,

             from sketch\Serial_send_floats_1_0_0.ino.cpp:1:

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:131:19: note: candidate: size_t HardwareSerial::write(long int)

 inline size_t write(long n) { return write((uint8_t)n); }

               ^~~~~

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:131:19: note: conversion of argument 1 would be ill-formed:

D:\Users\GLV\Documents\Arduino\Serial_send_floats_1_0_0\Serial_send_floats_1_0_0.ino:20:18: warning: invalid conversion from ‘signed char*’ to ‘long int’ [-fpermissive]

Serial.write(xy);

              ^

In file included from D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Arduino.h:233:0,

             from sketch\Serial_send_floats_1_0_0.ino.cpp:1:

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:132:19: note: candidate: size_t HardwareSerial::write(unsigned int)

 inline size_t write(unsigned int n) { return write((uint8_t)n); }

               ^~~~~

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:132:19: note: conversion of argument 1 would be ill-formed:

D:\Users\GLV\Documents\Arduino\Serial_send_floats_1_0_0\Serial_send_floats_1_0_0.ino:20:18: warning: invalid conversion from ‘signed char*’ to ‘unsigned int’ [-fpermissive]

Serial.write(xy);

              ^

In file included from D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Arduino.h:233:0,

             from sketch\Serial_send_floats_1_0_0.ino.cpp:1:

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:133:19: note: candidate: size_t HardwareSerial::write(int)

 inline size_t write(int n) { return write((uint8_t)n); }

               ^~~~~

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:133:19: note: conversion of argument 1 would be ill-formed:

D:\Users\GLV\Documents\Arduino\Serial_send_floats_1_0_0\Serial_send_floats_1_0_0.ino:20:18: warning: invalid conversion from ‘signed char*’ to ‘int’ [-fpermissive]

Serial.write(xy);

              ^

In file included from D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Stream.h:26:0,

             from D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/HardwareSerial.h:29,

             from D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Arduino.h:233,

             from sketch\Serial_send_floats_1_0_0.ino.cpp:1:

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Print.h:52:12: note: candidate: size_t Print::write(const char*)

 size_t write(const char *str) {

        ^~~~~

D:\Program Portable\arduino-1.8.15\hardware\arduino\avr\cores\arduino/Print.h:52:12: note: conversion of argument 1 would be ill-formed:

D:\Users\GLV\Documents\Arduino\Serial_send_floats_1_0_0\Serial_send_floats_1_0_0.ino:20:18: warning: invalid conversion from ‘signed char*’ to ‘const char*’ [-fpermissive]

Serial.write(xy);

              ^

exit status 1

no matching function for call to ‘write(signed char [2])’

This report would have more information with
“Show verbose output during compilation”
option enabled in File → Preferences.

It will compile error free with these changes:

//signed char xy[BYTES];
unsigned char xy[BYTES];

//Serial.write(xy);
Serial.write(xy, 2);

Serial.write(buf, len) works with buf as a:

  • unsigned char xy[2];
  • byte xy[2];
  • uint8_t xy[2];

:)

I’ve never had an Arduino and any blind code I post for it is just wishful thinking. :dark_sunglasses:

So I depend on Arduino users’ feedback to know if it’s actually working! :construction_worker_man:

After all these years you’ve given me that feedback, thx! :bowing_man:

However, based on the big log you’ve posted above, I still think that’s rather a warning than an actual error. :warning:

AFAIK, the C language is able to automatically fit in an unsigned char into a signed char b/c both are 8-bit datatypes. :eight:

The log also mentions [-fpermissive], which I believe is a command line flag parameter which would allow the C compiler to ignore all those related warnings when compiling my code. :smile_cat: