Issues interfacing Arduino sensor MPU6050 and Processing - arduino

I have an MPU6050 gyroscope and accelerometer connected with Arduino through the I2C protocol. These sensor send a continuos stream of data into the Serial port with these instructions (in the arduino IDE):
Serial.print(euler[0] * 180/M_PI);
Serial.print(":");
Serial.print(euler[1] * 180/M_PI);
Serial.print(":");
Serial.println(euler[2] * 180/M_PI);
This come from an example sketch included in the library of the sensor and it just sends the value of yaw / pitch / roll to the serial port, separated by the colon.
Now there is the interesting part. I've always been fascinated about visualizing data, and so i want to build a sort of graph of these data coming from serial in Processing(this is part of a larger project that include a ultrasonic sensor, like a sort of radar).
So I wrote a short sketch on processing to catch that data in order to analyze and visualize it. This is the sketch:
import processing.serial.*;
Serial myPort;
String data; //Angle values
String[] splitted; //Array containing splitted data
float yaw, pitch , roll;
void setup()
{
myPort = new Serial (this, Serial.list()[0], 115200);
}
void draw()
{
while (myPort.available() > 0) //data arrived fromm serial
{
data = myPort.readStringUntil('\n');
//Data Parsing
splitted = data.split(":");
yaw = float(splitted[0]);
pitch = float(splitted[1]);
roll = float(splitted[2]);
println(yaw + " " + pitch + " " + roll);
}
}
This code doesn't work. There are 2 errors that alternate. One of them is:
ArrayIndexOutOfBondsException
And the other one:
NullPointerException
That points to the "splitted" array.
I think i got the problem. In a previous version of the Processing sketch i was using the:
readString() function
I think that, since data are sent to the Serial port in the Arduino sketch one at a time, the processing sketch sometimes catch only one, or two of the yaw, pitch, roll values, causing the array index to crash or to a nullPointerexception when no value is added to the array. I then changed the '''readString''' to the '''readStringUntil('\n')''', because, maybe the first packet will be lost but the other one coming next will always be cathed without breaking them (i catch the entire line). But there are the same errors, so I think my small experience can't help solving the problem anymore. I need your help.
Excuse me for my bad English, and thanks for any help.

You are on the right track. Here are a few pointers:
you can use a try/catch block so the sketch doesn't simply crash on an error
you can use bufferUntil() to tell the serial library to buffer bytes for you until a new line is encountered: it works well in tandem with serialEvent() which gets called automatically (so you don't need to use a while loop that would block rendering/the rest of the sketch)
you can check (and should) anything that could go wrong with the data (null string, empty string, not enough values within the string, etc.)
Here's a modified version of your sketch:
import processing.serial.*;
Serial myPort;
float yaw, pitch , roll;
void setup()
{
String[] portNames = Serial.list();
// skipp serial setup if there are no ports
if(portNames.length == 0){
println("no serial ports found");
return;
}
// try to open serial port, handle error
try
{
myPort = new Serial (this, portNames[0], 115200);
// buffer bytes(characters) until new line is hit
myPort.bufferUntil('\n');
}
catch(Exception e)
{
println("error opening port: " + portNames[0]);
println("double check the port is present and not used by other applications (e.g. SerialMonitor)");
e.printStackTrace();
}
}
void draw()
{
background(0);
text(String.format("yaw: %.2f \npitch: %.2f \nroll: %.2f", yaw, pitch, roll), 5, 15);
}
// serialEvent gets called when there's new data: no need an explicit blocking while loop
void serialEvent(Serial port){
try
{
// read string from serial
String rawSerialString = port.readString();
// exit on null string
if(rawSerialString == null)
{
println("received null string, skipping this serial message");
return;
}
// exit on empty string
if(rawSerialString.length() == 0)
{
println("received empty string, skipping this serial message");
return;
}
// trim white space (\r, \n, etc.)
rawSerialString = rawSerialString.trim();
// split and convert to float
float[] rotations = float(rawSerialString.split(":"));
// exit if message got jumbled up and values are missing
if(rotations.length < 3)
{
println("received less than 3 values, skipping this serial message");
return;
}
// finally extract values
yaw = rotations[0];
pitch = rotations[1];
roll = rotations[2];
println(yaw + " " + pitch + " " + roll);
}
catch(Exception e)
{
println("error reading/parsing serial data");
e.printStackTrace();
}
}

Obviously you receive lines with less than two colons.
Hard to tell from here what you should do then, but checking the length of the splitted array were the first step anyway. Either via if or as an Exception.

Related

Receive Arduino commands from Bluetooth module

First off this is my first Arduino project but I have coded basic c++ before. Anyway I am struggling to get the Arduino to acknowledge when save data to a variable. I know it's receiving the data but its not getting appended to my data variable. Here's the code and if I could get a basic explanation of what I did wrong I would appreciate it.
#include <SoftwareSerial.h>
SoftwareSerial BTserial(0, 1);
//declair pins
void setup() {
Serial.begin(9600);
//setup pins
}
void loop() {
String data;
bool run = false;
data = "";
while (Serial.available()) {
char inChar = (char)Serial.read();
Serial.print(inChar); //I know it is getting the sent data because prints here
if (inChar == '\n') {
Serial.print("Received Command: ");
if (data == "")
Serial.print("Data is NULL"); //this always prints too
Serial.print(data);
Serial.print('\n');
run = true;
break;
} else {
data += inChar;
}
}
if(run) {
//do stuff
}
}
I know there are plenty of websites I could copy paste from but I want to make my own and understand what I did wrong. I did read them though.
For example if I send command from my phone the output would be
command
Received Command: Data is NULL
The following segment will always appear null here on the first loop unless you receive characters other than newline when your serial begins listening because the program executes from top to bottom and you haven't given data a value yet here.
if (data == "") {
Serial.print("Data is NULL"); //this always prints too
}
P.S. This expression
String data;
data = "";
can be simplified to
String data ="";
More efficient.
I'll try to provide more information if I can figure out the issue once I get some sample data.

How to control multiple servos with a PS4 Controller using Processing Game Control Plus

I passed the last 3 days trying to figure this out with my basic programming knowledge and this is what I achieved: Collect data from PS4 controller with a Processing program and send it to Arduino through Serial port being able to control one servo using serial and Game Control Plus libraries.
Okay, then I shouldn't have more problems? Right? No.
I don't have any idea of how I'm going to pass the other 3 analogical axes of the PS4 control and make Arduino get them and split into variables to control the other servos.
I'm going to share my 2 codes:
//Processing Code
import processing.serial.*;
import org.gamecontrolplus.gui.*;
import org.gamecontrolplus.*;
import net.java.games.input.*;
Serial myPort;
ControlIO control;
ControlDevice stick;
float px, py, pz, pw;
int[] lista;
public void setup() {
lista = new int[4];
String portName = Serial.list()[2];
myPort = new Serial(this, portName, 9600);
surface.setTitle("GCP Joystick example");
control = ControlIO.getInstance(this);
stick = control.filter(GCP.STICK).getMatchedDevice("joystick");
if (stick == null) {
println("No suitable device configured");
System.exit(-1);
}
}
public void getUserInput() {
px = map(stick.getSlider("X").getValue(), -1, 1, 0, width);
py = map(stick.getSlider("Y").getValue(), -1, 1, 0, height);
pz = map(stick.getSlider("Z").getValue(), -1, 1, 0, width);
pw = map(stick.getSlider("W").getValue(), -1, 1, 0, height);
}
// Event handler for the SHADOW button
public void draw() {
getUserInput(); // Polling the input device
background(255, 255, 240);
fill(0, 0, 255, 32);
noStroke();
println(int(px));
myPort.write(int(px));
// I tried to pass this way, but I still don't know how make Arduino recognize and split them
/** lista[0] = int(px);
lista[1] = int(py);
lista[2] = int(pz);
lista[3] = int(pw);
for (int i = 0; i < 4) {
println(lista[i]);
myPort.write(lista[i]);
if (myPort.readStringUntil('\n') == "k"){
i += 1
}
else{}
println("---------");
*/
}
Now, the Arduino code:
#include <Servo.h>
char val;
Servo servo1;
int x_pos;
int servo1_pin = 9;
int initial_position = 90;
int x_pos_pas = 50;
void setup() {
Serial.begin(9600);
servo1.attach(servo1_pin);
servo1.write (initial_position);
}
void loop() {
if (Serial.available())
{
val = Serial.read();
x_pos = int(int(val) * 1.8);
}
if(x_pos != x_pos_pas){
servo1.write(x_pos);
}
else{}
x_pos_pas = x_pos;
delay(10);
}
It's a bit confusing what you're trying to do, but from what I can gather the confusion is around serial communication.
here's how I understand how the communication works with your current code and a few issues with that:
1. Truncation
You're writing px which is mapped to the sketch dimensions (which I can't see anywhere, so guessing it's the default 100x100 ?).
If the dimensions are bigger than 255 this may be a problem.
Even through Processing Serial write(int) takes an int, behind the scenes it's using jssc.Serial.writeInt() which takes a value from 0 to 255.
(Essentially it writes a single byte, but within 0-255 range, where as the byte type in Processing java is from -127 to 128).
If you want to send values greater than 255 you would need to split them into individual bytes. (see the ARGB value split example using bit shifting and AND masking and using OR to put the individual bytes together into a multiple byte integer)
2. Repetition
px is sent again in the for loop: myPort.write(lista[i]);
The code is commented anyway, but it's something to be mindful of.
Personally I make new simple test sketches solving individual simple problems instead of large unused blocks which make the code harder to read/navigate and ultimately debug.
I encourage you to split the bigger problem into multiple simpler single problems, and solving one at a time.
3. Data termination
The commented code attempts to send 4 integers, but there is no way for Arduino to know in which order the data arrives. If anything goes wrong it will be very hard to tell what's the order.
There are multiple ways to do this. Ideally you would write a communication protocol.
(and there are many resources on this topic.)
It sounds like a fun project to learn about working with bits/bytes/byte arrays and putting together a communication protocol from scratch with some form of data verification (checksum / CRC / etc.)
If you're tight on time and you simply want to drive a servo without worrying too much about reliably sending multiple (potentially) large values over serial I recommend trying Firmata Processing
You would need to flash the Firmata firmware to your Arduino then use the Firmata Processing library to connect to the serial port (with the correct baud rate) and call arduino.servoWrite() as required. See the library's arduino_servo example as well.
Based on your comment on mapped values between 0 -> 100, you could use repurpose the SerialEvent example using any other character > 100 to differentiate data from the string terminator char. Bare in mind you wil be loosing precision:
getValue() returns a float which has 32bit precision
You could in theory use the same technique with 0-254 (using 255 as the terminator character). 0-100 range uses 6 bits
Here is a rough example of what might look like in code, taking into account the code has not been tested with actual devices:
Processing:
import processing.serial.*;
import org.gamecontrolplus.gui.*;
import org.gamecontrolplus.*;
import net.java.games.input.*;
Serial myPort;
ControlIO control;
ControlDevice stick;
float px, py, pz, pw;
// px,py,pz,pw remapped to 0-100 range
int[] lista = new int[4];
// px,py,pz as bytes + terminator character (255)
byte[] toArduino = {0,0,0,0,(byte)255};
public void setup() {
size(100,100);
lista = new int[4];
String portName = Serial.list()[2];
try{
myPort = new Serial(this, portName, 9600);
}catch(Exception e){
println("error connecting to serial port: " + portName);
e.printStackTrace();
}
surface.setTitle("GCP Joystick example");
control = ControlIO.getInstance(this);
try{
stick = control.filter(GCP.STICK).getMatchedDevice("joystick");
}catch(Exception e){
e.printStackTrace();
}
if (stick == null) {
println("No suitable device configured");
}
}
public void getUserInput() {
if(stick == null){
return;
}
// map values
px = map(stick.getSlider("X").getValue(), -1, 1, 0, width);
py = map(stick.getSlider("Y").getValue(), -1, 1, 0, height);
pz = map(stick.getSlider("Z").getValue(), -1, 1, 0, width);
pw = map(stick.getSlider("W").getValue(), -1, 1, 0, height);
// cast to int
lista[0] = (int)px;
lista[1] = (int)py;
lista[2] = (int)pz;
lista[3] = (int)pw;
// update bytearray
toArduino[0] = (byte)lista[0];
toArduino[1] = (byte)lista[1];
toArduino[2] = (byte)lista[2];
toArduino[3] = (byte)lista[3];
}
// Event handler for the SHADOW button
public void draw() {
getUserInput(); // Polling the input device
background(255, 255, 240);
fill(0, 0, 255, 32);
noStroke();
text("px: " + px
+"\npy: " + py
+"\npz: " + pz
+"\npw: " + pw
,5,15);
if(myPort != null){
myPort.write(toArduino);
}
}
Arduino:
/*
Serial Event example
When new serial data arrives, this sketch adds it to a String.
When a newline is received, the loop prints the string and clears it.
A good test for this is to try it with a GPS receiver that sends out
NMEA 0183 sentences.
NOTE: The serialEvent() feature is not available on the Leonardo, Micro, or
other ATmega32U4 based boards.
created 9 May 2011
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/SerialEvent
*/
String inputString = ""; // a String to hold incoming data
bool stringComplete = false; // whether the string is complete
const char TERMINATOR = (char)255;
void setup() {
// initialize serial:
Serial.begin(9600);
// reserve 200 bytes for the inputString:
inputString.reserve(200);
}
void loop() {
// in case serialEvent() isn't called automatically
serialEvent();
// print the string when a newline arrives:
if (stringComplete) {
// process string
uint8_t px = inputString.charAt(0);
uint8_t py = inputString.charAt(1);
uint8_t pz = inputString.charAt(2);
uint8_t pw = inputString.charAt(3);
// TODO: pass this to servos
// debug print
Serial.print("px:");
Serial.print(px);
Serial.print("\tpy:");
Serial.print(py);
Serial.print("\tpz:");
Serial.print(pz);
Serial.print("\tpw:");
Serial.println(pw);
// clear the string:
inputString = "";
stringComplete = false;
}
}
/*
SerialEvent occurs whenever a new data comes in the hardware serial RX. This
routine is run between each time loop() runs, so using delay inside loop can
delay response. Multiple bytes of data may be available.
*/
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag so the main loop can
// do something about it:
if (inChar == TERMINATOR) {
stringComplete = true;
}
}
}

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!

Arduino Values arriving differently in Processing and Arduino Serial Monitor

I have an Arduino Mega2560 which reads analog values from a sensor (Grove Loudness Sensor) and sends them to a Raspberry Pie 3b+ via USB. The values arrive perfectly and without delay in the serial monitor of the Arduino IDE. But when I try to receive them in Processing I get mostly Zeros no matter how much noise I make, with random peaks here and there.
My first guess was that my Processing code garbles the received data, so I changed the Arduino sketch to send an incrementing Integer instead of the sensor value - and those test values show correctly in Processing! Next I tried padding the sensor value in some String like "MICRO("+theSensorValue+");". The serial monitor shows the whole String and the correct sensor value, Processing shows the whole String but the value inside is still garbage..
This doesn't make any sense to me. Processing can receive any value from the Arduino correctly, except when it's the sensor value...
Arduino:
void setup() {
Serial.begin(9600);
}
void loop() {
int micLevel = analogRead(A0);
Serial.println(micLevel,DEC);
}
Processing:
Serial port;
void setup() {
port = new Serial(this, "/dev/ttyACM0", 9600);
}
void draw() {
String s = "";
if(port.available() > 0) {
s = port.readStringUntil(10);
println(s);
}
}
In Serial.println(micLevel,DEC); why are you casting the value as decimal?
Try to just Serial.println(micLevel); or convert to String if you want to send text with it Serial.println("Value is: " + String(micLevel));

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.

Resources