Processing - missing serial data from Arduino, using readStringUntil() - arduino

I've been trying to create an oscilloscope for serial data from my Arduino. In the Arduino serial plotter I can get a good waveform up to suitable frequencies, but when I try send the data to Processing it doesn't receive all the data from the Arduino. Is there a way around this?
Arduino
const int analogIn = A6;
int integratorOutput = 0;
void setup() {
// put your setup code here, to run once:
pinMode(3, OUTPUT);
pinMode(2, OUTPUT);
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
integratorOutput = analogRead(analogIn);
Serial.println(integratorOutput);
}
Processing
void serialEvent (Serial port) {
// get the ASCII string:
String inString = port.readStringUntil('\n');
if (inString != null) {
inString = trim(inString); // trim off whitespaces.
inByte = float(inString); // convert to a number.
inByte = map(inByte, 0, 1023, 100, height-100); //map to the screen height.
println(inByte);
newData = true;
}
}
Thanks!

It's because readStringUntil is a non blocking function. Let's assume Arduino is printing a line: 12345\n The serial port at 115200 bits per seconds is relatively slow, so it's possible that the at some point the receiving buffer contains only a part of the message, for example: 1234. When the port.readStringUntil('\n') is executed it doesn't encounter a \n in the buffer so it fails and returns a NULL. You can solve this problem by using bufferUntil as in this example

Related

How to make serial reading asynchronously to main loop

I have arduino with code below. It has encoder, and prints something on encoder turn. But also it receive a lot of data, so if arduino is reading serial main loop stops and encoder loosing steps. How can I write code where encoders printing has always priority?
code:
#include <Encoder.h>
String receivedData = "";
Encoder encoder1(24, 25);
long position1 = -999;
long newPosition1;
void setup() {
Serial.begin(57600);
}
void loop() {
newPosition1 = encoder1.read();
if (newPosition1 != position1) {
Serial.print("PrintSomething");
}
position1 = newPosition1;
Serial.flush();
if(Serial.available() > 0) {
receivedData = Serial.readStringUntil(';');
if (receivedData == "?") {
Serial.print("3," + String(deviceId) + ",0,0,3;");
}
doSomethingImmediatly();
}
}
Important thing is in reality i have 6 encoders, so i can't use interrupts. And doSomethingImmediatly function should run as fast as possible.
Funny thing is if i use higher braud the problem is even more visible.
I would strongly suggest using SerialEvent instead of polling for serial data. This way, you build the serial string char by char and you can decide where to stop reading.
I would rather poll the encoders to avoid using clock cycles reading the status of every encoder sequentially. Otherwise, reconsider using a different library that might offer better performance (like RotaryEncoder from mathertel)
Based on the number of encoders that you are trying to read and the potential bottlenecks that you will encounter at 16 MHz (most common clock speed from Arduino - unless us Due or Mega-), I advise porting your application to a Teensy Microcontroller (> 3.2)
Keep in mind, there is no such thing as 'priorities' unless, as lurker mentioned, you use RTOS. You have to play with timings and efficient logic
For instance, a skimmed example code would look like the following (it shows only one polling routine):
unsigned long previousEncoderTime;
unsigned long pollPeriod = 200; // Poll every 200 ms
char serialString[] = " "; // Empty serial string variable
bool stringFinished = false; // Flag to indicate reception of a string after terminator is reached
void setup(){
previousEncoderTime = 0;
}
void loop(){
unsigned long now = millis();
if (now - previousEncoderTime >= pollPeriod){
previousEncoderTime = now;
// Encoder reading routine
}
if (stringFinished){ // When the serial Port has received a command
stringFinished = false;
// Implement your logic here
}
}
void serialEvent()
{
int idx = 0;
while (Serial.available())
{
char inChar = (char)Serial.read();
if (inChar == '\n') // The reading event stops at a new line character
{
serialTail = true;
serialString[idx] = inChar;
}
if (!serialTail)
{
serialString[idx] = inChar;
idx++;
}
if (serialTail)
{
stringFinished = true;
Serial.flush();
serialTail = false;
}
}
}

Sending strings from processing to arduino

I'm trying to set up communications between my PC, and my Arduino with the Processing environment, but the Arduino doesn't seem to be getting any of the messages I send. I doubled checked, and I know I can receive messages from the Arduino, but I can't send anything back. Does anyone know how to fix this?
Here's my test code for processing:
import processing.serial.*;
Serial myPort;
void setup(){
myPort = new Serial(this, Serial.list()[0], 9600);
}
void draw(){
myPort.write("test");
while (myPort.available() > 0) {
String inByte = myPort.readString();
println(inByte);
}
}
Here's my test code for the Arduino:
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
}
String data;
void loop() {
// put your main code here, to run repeatedly:
//Serial.println("is running");
if (Serial.available() > 0) {
// read the incoming byte:
data = Serial.readString();
// say what you got:
Serial.print("I received: ");
Serial.println(data);
}
}
I'd appreciate any help I can get! Thanks!
Okay, after looking into several different posts on the Arduino forum, I figured out what the problem is. The function processing uses to send data over serial does not automatically include a return character at the end of the string. This is important because the Arduino won't read from the serial buffer until it sees that return character. All I had to do was add "\r\n" to the end of each string I sent over serial, and that solved the problem!

Processing IDE data is not being sent to arduino properly

I want to send processing IDE data to arduino. But led is not working. It worked fine once. But not working now :( Serial port name is exactly same in arduino as it is found by processing.
Processing code:
import processing.serial.*;
Serial myPort; // Create object from Serial class
void setup()
{
size(200,200); //make our canvas 200 x 200 pixels big
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
}
//send a 1
void draw() {
if (mousePressed == true)
{ //if we clicked in the window
myPort.write('1'); //send a 1
println("1");
} else
{ //otherwise
myPort.write('0'); //send a 0
}
}
Arduino code:
char val='0'; // Data received from the serial port
int ledPin = 13; // Set the pin to digital I/O 13
void setup() {
pinMode(ledPin, OUTPUT); // Set pin as OUTPUT
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop() {
//digitalWrite(ledPin, HIGH); // turn the LED on
if (Serial.available())
{ // If data is available to read,
val = Serial.read(); // read it and store it in val
}
if (val == '1')
{ // If 1 was received
digitalWrite(ledPin, HIGH); // turn the LED on
} else {
digitalWrite(ledPin, LOW); // otherwise turn it off
}
delay(10); // Wait 10 milliseconds for next reading
}
Processing
You can simply say if(mousePressed)..., there is no need to say == true (it's implied)
Arduino
You're correct to check if(Serial.available()) before trying to overwrite val with whatever character you read from there. However, the rest of your code inside loop() is executing regardless of this check. There is no reason to repeatedly write a pin to LOW or HIGH if it is already there. In fact, you will be more responsive if you only delay on loops where you find a character available for reading.
I'd recommend you add some print statements to your Arduino code so you can get a look at what you're reading.
Also, could it be that your hardware is connected improperly or that your LED is simply burnt out?

Reading Arduino int array with Processing

I have an arduino-processing communication problem.
I have arduino code that gives me X-and/Y coordinates from a touchScreen
and it works well, no problem with that, I got my X- and Y coordinates.
BUT I need to visualize that, I am trying to write code in Processing 3.0, so that I will be able to see on my computer, where the touchFolie was being touched.
So I need to send the x-y from arduino to processing so that I will be able to draw.
Does anyone know how can I send an integer array[X,Y] from arduino to processing ??
It will be helpful to have a play with the Serial library in Processing and the SerialRead example (in Processing > File > Examples > Libraries > serial > SimpleRead)
Let's say you're starting from scratch.
To send data from Arduino you need to open a Serial connection.
At this stage the only important details is the baud rate: how fast is the data flowing.
Here's a minimal Arduino data out example:
void setup() {
//initialize the Serial library with baud rate 115200
Serial.begin(115200);
}
void loop() {
//write data to the serial port
Serial.println("test");
delay(1000);
}
If you open Serial Monitor in the Arduino software and set the baud rate to 115200 you should see test printed once a second.
To read the same data in Processing, aside from specifying the baud rate, you must also specify the serial port (what you have selected in Tools > Port and is also listed at the bottom right of your current Arduino sketch):
import processing.serial.*;
void setup() {
//update the serial port index based on your setup
println(Serial.list());
Serial arduino = new Serial(this, Serial.list()[0], 115200);
arduino.bufferUntil('\n');
}
void draw() {
}
void serialEvent(Serial p) {
//read the string from serial
String rawString = p.readString();
println(rawString);
}
Notice that we tell Processing to buffer until it reaches a '\n' character so we don't have to worry about waiting for every single character and append it manually to a String. Instead using bufferUntil(), serialEvent() and readString() most of the work is done for us.
Now that you can send a String from Arduino and read it in Processing, you can do some String manipulation, like splitting a string into multiple using a separator via the split() function:
String xyValues = "12,13";
printArray(xyValues.split(","));
The last part would be converting the split values from String to int:
String xyValues = "12,13";
String[] xy = xyValues.split(",");
printArray(xy);
int x = int(xy[0]);
int y = int(xy[1]);
println("integer values: " + x + " , " + y);
So, in theory, you should be able to do something like this on Arduino:
int x,y;
void setup() {
//initialize serial
Serial.begin(115200);
}
void loop() {
//simulating the x,y values from the touch screen,
//be sure to replace with the actual readings from
//NOTE! If the screen returns values above 255, scale them to be from 0 to 255
x = map(analogRead(A0),0,1024,0,255);
y = map(analogRead(A1),0,1024,0,255);
//write the data to serial
Serial.print(x);
Serial.print(",");
Serial.print(y);
Serial.print("\n");
}
then on the Arduino side:
import processing.serial.*;
float x,y;
void setup() {
size(400,400);
//update the serial port index based on your setup
Serial arduino = new Serial(this, Serial.list()[0], 115200);
arduino.bufferUntil('\n');
}
void draw() {
background(0);
ellipse(x,y,10,10);
}
void serialEvent(Serial p) {
//read the string from serial
String rawString = p.readString();
//trim any unwanted empty spaces
rawString = rawString.trim();
try{
//split the string into an array of 2 value (e.g. "0,127" will become ["0","127"]
String[] values = rawString.split(",");
//convert strings to int
int serialX = int(values[0]);
int serialY = int(values[1]);
//map serial values to sketch coordinates if needed
x = map(serialX,0,255,0,width);
y = map(serialY,0,255,0,height);
}catch(Exception e){
println("Error parsing string from Serial:");
e.printStackTrace();
}
}
Note The Arduino code above will probably not solve your problem as it is, you need to integrate your touch sensor code, but hopefully it provides some hints on how you can tackle this.
Sending a String, then parsing it is one approach, but not the most efficient. If you have your x,y values in a 0-255 range, you could send just 2 bytes (each coordinate as a single char) instead of up to 8 bytes, but for now it may be much easier to play with Strings rather than jump into bytes straight away.
This tutorial will help you.
5 minutes and you are able to connect each others!
EDIT:
First of all look the first part of the tutorial ("From Arduino..." "...To processing").
In arduino you have just to send your coordinates in your Serial.
Serial.println(coordX);
Serial.println(coordY);
In processing you receive this coordinates as Text but you are able to convert it in Float with parseFloat() function.
This is the code you need in Processing to receive your coordinates and store them in variables.
import processing.serial.*;
Serial myPort; // Create object from Serial class
String val; // Data received from the serial port
float x = 0;
float y = 0;
boolean first = true;
setup() {
String portName = Serial.list()[0]; //change the 0 to a 1 or 2 etc. to match your port
myPort = new Serial(this, portName, 9600);
}
void draw() {
if ( myPort.available() > 0) { // If data is available,
val = myPort.readStringUntil('\n'); // read it and store it in val
if (first) {
x = parseFloat(val);
first = false;
println("x= "+val); //print it out in the console
}
else {
y = parseFloat(val);
first = true;
println("y= "+val); //print it out in the console
}
}
I hope this will help you solve your problem.

Making arduino only write when signaled (serial)

I'm trying to communicate between a Raspberry Pi and Arduino with USB serial, but I only want the Arduino to write when the RPI sends a signal.
My arduino code is as follows:
int sensorPin = A0;
int sensorValue = 0;
void setup(){
Serial.begin(9600);
}
void loop(){
sensorValue = analogRead(sensorPin);
if (Serial.available() > 0) {
Serial.read();
Serial.println(sensorValue,DEC);
Serial.flush();
}
}
Once i do one call from the RPI of:
serial.write('hey')
The arduino writes repeatedly. I thought Serial.available would return 0 most of the time because the buffer is cleared by the read, but it seems like it never gets cleared. I thought flush() might do it but it doesn't really have any effect.
That's odd.. Serial.read() should remove the bytes from the buffer after reading them.
Note: Keep in mind that Serial.read() only reads one byte at a time, this could be your issue since you're sending 'hey' from the Raspberry Pi it'll take 3 iterations of the loop the completely empty the buffer.
If this is not the issue you could try the serialEvent() function wich is called each time something arrives trough serial.
Your code would be like this:
int sensorPin = A0;
int sensorValue = 0;
void setup(){
Serial.begin(9600);
}
void loop(){
//Any other logic here
}
void serialEvent() {
sensorValue = analogRead(sensorPin);
Serial.read();
Serial.println(sensorValue,DEC);
}
By using the serialEvent() event, your loop looks cleaner. That's always nice.

Resources