I'm attempting to create a data exchange between sensors on an Arduino (well, actually an ATmega328PU-based clone built on a breadboard, but I don't believe that that's the source of my problem) and a Processing script, and I'm getting some unexpected results.
I was following the method of serial communication detailed here, but I get stuck with what appears to be no data actually traveling over the serial connection.
The Arduino code:
int buttonPin = 9, photodiodePin = A0;
char dataToSend;
void setup() {
Serial.begin(9600);
pinMode(buttonPin, OUTPUT);
pinMode(photodiodePin, INPUT);
}
void loop() {
if (Serial.available() > 0)
{
dataToSend = Serial.read();
if (dataToSend == 'B')
{
Serial.println(digitalRead(buttonPin));
}
else if (dataToSend == 'L')
{
Serial.println(analogRead(photodiodePin));
}
}
}
And the relevant parts of the Processing code:
import processing.serial.*;
Serial myPort;
void setup()
{
size(1600, 900);
String portName = Serial.list()[1];
myPort = new Serial(this, portName, 9600);
}
void draw()
{
if(getButtonData() == 1)
{
// Do stuff
}
}
int getLightData()
{
myPort.write('L');
println("L");
while(!(myPort.available() > 0))
{
}
int lightValue = int(myPort.readStringUntil('\n'));
return lightValue;
}
int getButtonData()
{
myPort.write('B');
println("B");
while(!(myPort.available() > 0))
{
println("stuck in here");
delay(500);
}
int buttonValue = int(myPort.readStringUntil('\n'));
return buttonValue;
}
And in Processing I get an output of:
B
stuck in here
stuck in here
stuck in here
stuck in here
...
Note: I know I have the correct port selected from the list, so that is not the issue.
I've tried debugging the issue and searching the Internet for similar problems, both to no avail.
I would first check if simply sending a simple message from Arduino to Processing works. Try something like this in Arduino:
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("test");
delay(1000);
}
and this in Processing:
import processing.serial.*;
Serial arduino;
void setup(){
String portName = Serial.list()[1];
try{
arduino = new Serial(this, portName, 9600);
arduino.bufferUntil('\n');
}catch(Exception e){
System.err.println("Error initializing Serial port!\nPlease check connections and port settings");
e.printStackTrace();
}
}
void draw(){
}
void serialEvent(Serial s){
println("received arduino message: " + s.readString());
}
If this simple setup works, you should be fine to move on to the next step and have two way communication. If the above doesn't work then there's something else causing issues with serial communication (in which case please report what errors you're receiving, if any or what behaviour you're experiencing)
In case the above works, you can try two way communication. Notice I'm making use of serialEvent() and bufferUntil. It's best to avoid blocking while loops wherever possible.
Arduino code:
int buttonPin = 9, photodiodePin = A0;
char dataToSend;
void setup() {
Serial.begin(9600);
pinMode(buttonPin, OUTPUT);
pinMode(photodiodePin, INPUT);
}
void loop() {
}
void serialEvent(){
if(Serial.available() > 0){
char cmd = Serial.read();
if(cmd == 'B'){
Serial.println(digitalRead(buttonPin));
}
if(cmd == 'L'){
Serial.println(analogRead(photodiodePin));
}
}
}
Processing code:
import processing.serial.*;
Serial arduino;
int digitalValue;
int analogValue;
int lastCMD;
void setup(){
size(200,100);
String portName = Serial.list()[1];
try{
arduino = new Serial(this, portName, 9600);
arduino.bufferUntil('\n');
}catch(Exception e){
System.err.println("Error initializing Serial port!\nPlease check connections and port settings");
e.printStackTrace();
}
}
void draw(){
background(0);
text("Press 'B' to read digital pin\nPress 'L' to read analog pin\n\n"+
"digital pin: " + digitalValue + "\nanalog pin: " + analogValue,10,25);
}
void keyReleased(){
if(key == 'B' || key == 'L'){
lastCMD = key;
println("sending command" + lastCMD);
if(arduino != null){
arduino.write(lastCMD);
}else println("Arduino is not initializing, not writing to serial port");
}
}
void serialEvent(Serial s){
String rawString = s.readString();
println("received arduino message" + rawString);
try{
rawString = rawString.trim();//remove any white space characters (if present)
if(lastCMD == 'B') digitalValue = int(rawString);
if(lastCMD == 'L') analogValue = int(rawString);
}catch(Exception e){
println("Error parsing String from serial port:");
e.printStackTrace();
}
}
Related
I wanted to make my Arduino communicate with Processing.
On Arduino, I use the code taken from the Processing site (Example 1A):
int switchPin = 4; // Switch connected to pin 4
void setup()
{
pinMode(switchPin, INPUT); // Set pin 0 as an input
Serial.begin(9600); // Initialize serial communications at a 9600 baud rate
}
void loop()
{
if (digitalRead(switchPin) == HIGH) // If switch is ON,
// send 1 to Processing
{
Serial.write(1);
}
else
{ // If the switch is not ON,
Serial.write(0); // send 0 to Processing
}
delay(100);
}
While in Processing I use this code:
import processing.serial.*;
Serial myPort; // Create object from Serial class
String val = "0"; // Data received from the serial port
void setup()
{
size(200, 200);
frameRate(10);
String portName = Serial.list()[0]; // Change the 0 to a 1, 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
}
background(255);
if(val.equals("0"))
{
fill(0);
}
else
{
fill(204);
}
rect(50, 50, 100, 100);
}
The program gives me the error NullPointerException on line 22 in the Processing program.
How can I solve it?
There is a delay in the communication and it is possible that the first time when the draw function is called, the serial port doesn't send any data, and the value received is null. That might be the reason you get the NullPointerException.
Try this:
void draw()
{
while (myPort.available() > 0)
{
// If data is available,
val = myPort.readStringUntil('\n'); // Read it and store it in val
}
background(255);
if(val != null)
{
if(val.equals("0"))
{
fill(0);
}
else
{
fill(204);
}
}
rect(50, 50, 100, 100);
}
I'm trying to pass multiple variables (n number of strings and n number of ints) from processing to my Arduino. I found this tutorial online and managed to send a single value. Now I have two arrays that both need to be accessed by the Arduino filesTypes[] and filesSizes[]. filesTypes[] consists of a 3 char long strings while fileSizes[] is an array of different integers.
Here is my Processing code:
import processing.serial.*;
Serial myPort; // Create object from Serial class
String[] fileTypes;
int[] fileSizes;
String[][] lines;
void setup()
{
size(200,200); //make our canvas 200 x 200 pixels big
String portName = Serial.list()[1]; //change the 0 to a 1 or 2 etc. to
match your port
myPort = new Serial(this, portName, 9600);
launch( sketchPath("") + "/test.bat");
}
void draw() {
if (mousePressed == true)
{ //if we clicked in the window
txtToStrg();
myPort.write('1'); //send a 1
txtToStrg();
} else
{ //otherwise
myPort.write('0'); //send a 0
}
}
void txtToStrg(){
String[] lines = loadStrings("list.txt");
fileTypes = new String[lines.length];
fileSizes = new int[lines.length];
for (int i = 0 ; i < lines.length; i++) {
if(lines[i] != null) {
String[] splitLine = split(lines[i], ' ');
fileTypes[i] = splitLine[0];
fileSizes[i] = int(splitLine[1]);
println(fileTypes[i] + " = " + fileSizes[i]);
}
}
}
And here my Arduino code:
char val; // Data received from the serial port
int ledPin = 4 ; // 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() {
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
Serial.print(val);
}
delay(10); // Wait 10 milliseconds for next reading
}
If a pass anything but a char it stops working.
I am trying to use a button switch in Arduino to trigger a visual display in Processing. I used "HIGH" and "LOW" to identify whether the button is pressed.
However, my code is constantly giving null instead of giving "HIGH" or "LOW" depending on the button state. I think this is pretty basic but I'm just quite lost. Any helps or comments would be appreciated!
Below is my code for Arduino and Processing respectively.
const int buttonPin = 2;
const int LEDPin = 13;
int buttonState = 0;
void setup() {
pinMode(buttonPin, INPUT);
pinMode(LEDPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
int analogValue = analogRead(A0)/4;
Serial.write(analogValue);
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
Serial.write(HIGH);
digitalWrite(LEDPin, HIGH);
} else {
Serial.write(LOW);
digitalWrite(LEDPin, LOW);
}
delay(100);
}
Processing code:
import processing.serial.*;
Serial myPort;
String val;
void setup() {
size(400,400);
String portName = Serial.list()[1];
myPort = new Serial(this, portName, 9600);
}
void draw() {
if (myPort.available() > 0) {
val = myPort.readStringUntil('\n');
println(val);
if (val == "HIGH") {
background(127,0,0);
}
if (val == "LOW") {
background(144, 26, 251);
}
}
}
write()
Writes binary data to the serial port. This data is sent as a byte or series of bytes.
Serial.write(str)
str: a string to send as a series of bytes
So when you use write HIGH and LOW in Serial.write, it will be send as a series of bytes. Edit your processing part to handle the incoming bytes. Just as follows :
import processing.serial.*;
Serial myPort;
String val;
int len; //length of byte array
void setup() {
size(400,400);
String portName = Serial.list()[1];
myPort = new Serial(this, portName, 9600);
}
void draw() {
if ((len=myPort.available()) > 0) {
for(i=0;i<len;i++)
myByteArray=myPort.read();
String val = String(myByteArray);
println(val);
if (val == "HIGH") {
background(127,0,0);
}
if (val == "LOW") {
background(144, 26, 251);
}
}
}
just change your buttonState variable type from integer to boolean, and then use
if(buttonState) {
Serial.println("HIGH");
}
else {
Serial.println("LOW");
}
In Arduino, HIGH and LOW are defined as 1 and 0.
By executing Serial.write(HIGH); and Serial.write(LOW); you are just sending a single byte 1 or 0.
But according to your Processing code, you are expecting Serial.write(HIGH); to send 'H', 'I', 'G', 'H' and '\n' characters.
In your Arduino code, you need to replace Serial.write(HIGH); and Serial.write(LOW); with Serial.print("HIGH\n"); and Serial.print("LOW\n");.
I was given a Intel Edison, with an integrated WiFi board, to mess around with and read some tweets. So far, I've downloaded the Twitter4j core .jar (version 4.0.2, latest as of today), and set up the Arduino-Processing communication.
Every time I try to execute a query (search tweets by hashtags, for instance) it says Error: api.twitter.com. I have verified that I am connected to the network, and that the network has no proxy issues with Twitter.
It stops working right after println("pre query").
Any ideas?
My Arduino sketch is as follows:
#include <WiFi.h>
#include <WiFiUdp.h>
#include <Ethernet.h>
int ledPin=13;
char ssid[] = "OnePlus One"; // the name of your network
char pass[] = "hugomario"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status
void setup()
{
Serial.println("inside setup");
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
Serial.println("\nconnecting ...");
status = WiFi.begin(ssid, pass);
// if you're not connected, stop here:
if ( status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// if you are connected :
else {
Serial.print("Connected to the network");
}
}
void loop()
{
Serial.println("\ninside loop");
while(Serial.available()==0);
int val = Serial.read()- '0';
Serial.println(val);
if(val == 1)
{
Serial.println("LED IS ON");
digitalWrite(ledPin,HIGH);
delay(1000);
digitalWrite(ledPin,LOW);
}
else
{
Serial.println("LED IS OFF");
digitalWrite(ledPin,LOW);
}
}
My Processing sketch:
import processing.serial.*;
Serial port;
static String OAuthConsumerKey="kxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxO";
static String OAuthConsumerSecret="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
static String AccessToken= "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
static String AccessTokenSecret="Mxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx5";
String[] searchedTweets = new String[50];
ConfigurationBuilder cb = new ConfigurationBuilder();
Twitter twitter;
void setup() {
//Set the size of the stage, and the background to black.
size(200, 200);
background(0);
smooth();
port = new Serial (this, "COM5", 115200);
connectTwitter();
}
void connectTwitter() {
cb.setOAuthConsumerKey(" kxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxO ");
cb.setOAuthConsumerSecret(" kxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxO ");
cb.setOAuthAccessToken("124767053- kxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxO ");
cb.setOAuthAccessTokenSecret(" kxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxO ");
cb.setHttpConnectionTimeout(100000);
twitter = new TwitterFactory(cb.build()).getInstance();
println("is twitter null? ");
println(twitter==null);
getSearchTweets();
}
void getSearchTweets() {
String queryStr = "#yolo";
try {
println("inside try");
Query query = new Query(queryStr);
// query.setRpp(10); //10 out of 100 results
query.count(10);
println("pre query");
QueryResult result = twitter.search(query);
println("post query");
ArrayList tweets = (ArrayList) result.getTweets();
println("tweets size= "+tweets.size());
for (int i=0; i<tweets.size (); i++) {
/*
Tweet t = (Tweet) tweets.get(i);
String user = t.getFromUser();
String msg = t.getText();
Date d = t.getCreatedAt();
*/
Status t = (Status) tweets.get(i);
String user = t.getUser().getName();
String msg = t.getText();
port.write('1');
searchedTweets[i] = user +": "+msg;
println(searchedTweets[i]);
}
}
catch (TwitterException e) {
println("Error: " + e.getMessage());
port.write('0');
}
}
void delay(int delay){
int time = millis();
while(millis()-time <= delay);
}
I want 2 Arduinos Leonardo to communicate, send a string for instance, so I have to use Serial1 to communicate via RS232 on pins 0 (RX) and 1 (TX).
I need to write binary data in that pins, the problem is how can I send a String using Serial1.write. Serial1.print works without errors but I think it does not do what I want. Any suggestion?
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
while (!Serial); // while not open, do nothing. Needed for Leonardo only
}
void loop() {
String outMessage = ""; // String to hold input
while (Serial.available() > 0) { // check if at least one char is available
char inChar = Serial.read();
outMessage.concat(inChar); // add Chars to outMessage (concatenate)
}
if (outMessage != "") {
Serial.println("Sent: " + outMessage); // see in Serial Monitor
Serial1.write(outMessage); // Send to the other Arduino
}
}
this line Serial1.write(outMessage); is giving me the error
"no matching function for call to 'HardwareSerial::write(String&)'"
You're using the String object(Wiring/C++). The function is using C strings: Serial.write(char*). To turn it into a C string, you use the toCharArray() method.
char* cString = (char*) malloc(sizeof(char)*(outMessage.length() + 1);
outMessage.stoCharArray(cString, outMessage.length() + 1);
Serial1.write(cString);
If we do not allocate the memory for our C string with malloc, we will get a fault. The following code WILL crash.
void setup() {
Serial.begin(9600);
String myString = "This is some new text";
char* buf;
Serial.println("Using toCharArray");
myString.toCharArray(buf, myString.length()+1); // **CRASH** buf is not allocated!
Serial.println(buf);
}
void loop() {
// put your main code here, to run repeatedly:
}
In the Serial Monitor the only message we will get is: Using toCharArray. At that point execution stops. Now if we correct the problem and use malloc() to allocate memory for our buffer and also use free() when done....
void setup() {
Serial.begin(9600);
String myString = "This is some new text";
char* buf = (char*) malloc(sizeof(char)*myString.length()+1);
Serial.println("Using toCharArray");
myString.toCharArray(buf, myString.length()+1);
Serial.println(buf);
Serial.println("Freeing the memory");
free(buf);
Serial.println("No leaking!");
}
void loop() {
// put your main code here, to run repeatedly:
}
The output we see in the Serial Monitor is:
Using toCharArray
This is some new text
Freeing the memory
No leaking!
Use toCharArry(), write() uses char*, not string, here is what i mean:
void setup() {
Serial.begin(9600);
Serial1.begin(9600);
while (!Serial);
}
void loop() {
String outMessage = "";
while (Serial.available() > 0) {
char inChar = Serial.read();
outMessage.concat(inChar);
}
if (outMessage != "") {
Serial.println("Sent: " + outMessage);
char* CharString; //
outMessage.toCharArray(cString, outMessage.length()) // My Changes Are Here
Serial1.write(CharString); //
}
}