I'm trying to send a number value over serial to an Arduino to control an Individually Addressable LEDstrip. Using the Arduino IDE "Serial Monitor" I'm able to send a number to the light strip with no issue. However when i try to do it externally by reading from a text file in processing it doesn't go through.
After some debugging I can see that Processing has the number right and its stored in the variable. However the lightstip will only ever light up on led, instead of the number given.
Processing Code:
import processing.serial.*;
import java.io.*;
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);
}
void draw()
{
while(true) {
// Read data from the file
{
String[] lines = loadStrings("Lifenumber.txt");
int number = Integer.parseInt(lines[0]);
println(number);
myPort.write(number);
delay(5000);
}
}
}
Arduino Code:
if ( Serial.available()) // Check to see if at least one character is available
{
char ch = Serial.read();
if(index < 3 && ch >= '0' && ch <= '9'){
strValue[index++] = ch;
}
else
{
Lnum = atoi(strValue);
Serial.println(Lnum);
for(i = 0; i < 144; i++)
{
leds[i] = CRGB::Black;
FastLED.show();
delay(1);
}
re = 1;
index = 0;
strValue[index] = 0;
strValue[index+1] = 0;
strValue[index+2] = 0;
}
}
What I want the program to do is read a number from a text file and light up that number of LEDs on the 144led lightstrip.
Here are a couple of comments on your code that should help make improvements in the future. It's important to form good coding habits early on: it will make your life so much easier (I'm speaking a mostly self taught programmer that started with flash so I know what messy and hacky is ;) )
import processing.serial.*;
//import java.io.*; // don't include unused imports
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
// handle error initialising Serial
try{
myPort = new Serial(this, portName, 9600);
}catch(Exception e){
println("Error initializing Serial port " + portName);
e.printStackTrace();
}
}
void draw()
{
// don't use blocking while, draw() already gets called continuously
//while(true) {
// Read data from the file
//{
// don't load the file over and over again
String[] lines = loadStrings("Lifenumber.txt");
int number = Integer.parseInt(lines[0]);// int(lines[0]) works in Processing, but the Java approach is ok too
println("parsed number: " + number);
if(myPort != null){
myPort.write(number);
}
// don't use blocking delays, ideally not even in Arduino
//delay(5000);
//}
//}
}
Here's a version of the Processing code that loads the text file, parses the integer then sends it to serial only once (if everything is ok, otherwise basic error checking should reveal debug friendly information):
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
// handle error initialising Serial
try{
myPort = new Serial(this, portName, 9600);
}catch(Exception e){
println("Error initializing Serial port " + portName);
e.printStackTrace();
}
// Read data from the file
try{
String[] lines = loadStrings("Lifenumber.txt");
int number = Integer.parseInt(lines[0]);
println("parsed number: " + number);
// validate the data, just in case something went wrong
if(number < 0 && number > 255){
println("invalid number: " + number + ", expecting 0-255 byte sized values only");
return;
}
if(myPort != null){
myPort.write(number);
}
}catch(Exception e){
println("Error loading text file");
e.printStackTrace();
}
}
void draw()
{
// display the latest value if you want
}
// add a keyboard shortcut to reload if you need to
Your strip has 144 leds (less than 255) which fits nicely in a single byte which is what the Processing sketch sends
On the Arduino side there's nothing too crazy going on, so as long as you validate the data coming in should be fine:
#include "FastLED.h"
#define NUM_LEDS 64
#define DATA_PIN 7
#define CLOCK_PIN 13
// Define the array of leds
CRGB leds[NUM_LEDS];
int numLEDsLit = 0;
void setup() {
Serial.begin(9600);
Serial.println("resetting");
LEDS.addLeds<WS2812,DATA_PIN,RGB>(leds,NUM_LEDS);
LEDS.setBrightness(84);
}
void loop() {
updateSerial();
updateLEDs();
}
void updateSerial(){
// if there's at least one byte to read
if( Serial.available() > 0 )
{
// read it and assign it to the number of LEDs to light up
numLEDsLit = Serial.read();
// constrain to a valid range (just in case something goes funny and we get a -1, etc.)
numLEDsLit = constrain(numLEDsLit,0,NUM_LEDS);
}
}
// uses blacking delay
void updateLEDs(){
// for each LED
for(int i = 0; i < 144; i++)
{
// light up only the number of LEDs received via Serial, turn the LEDs off otherwise
if(i < numLEDsLit){
leds[i] = CRGB::White;
}else{
leds[i] = CRGB::Black;
}
FastLED.show();
delay(1);
}
}
Adjust the pins/LED chipsets/etc. based on your actual physical setup.
Related
I have 2 different LED Rings. (one has 16 LEDs and the other 24)
I want to make an interface from processing IDE where I can select a color and send this color to the selected ring. Here is the arduino code:
#include <FastLED.h>
#define LED_PIN1 3
#define LED_PIN2 12
#define NUM_LEDS1 16
#define NUM_LEDS2 24
CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
int r,g,b;
boolean state = false;
void setup() {
FastLED.addLeds<WS2812, LED_PIN1, GRB>(leds1, NUM_LEDS1);
FastLED.addLeds<WS2812, LED_PIN2, GRB>(leds2, NUM_LEDS2);
Serial.begin(9600);
}
void loop() {
String returnedInput = rgbInput();
String red = returnedInput.substring(0,3); //get 3 values like 255
String green = returnedInput.substring(4,7);
String blue = returnedInput.substring(8,11);
Serial.println(red);
Serial.println(green);
Serial.println(blue);
int r = red.toInt();
int g = green.toInt();
int b = blue.toInt();
if (Serial.available()){
char val = Serial.read();
if(val == '2') { //selects the second LED ring
if(state == false) {
state = true;
for(int i = 0 ; i < 24 ; i++ ){
leds2[i] = CRGB(r, g, b); //turn on all the LEDs on the ring to the selected color
FastLED.show();
FastLED.clear();
FastLED.show();
}}}
}}
String rgbInput() {
//prompt for input
Serial.println("ready");
while(!Serial.available()) {
//if 0, it keeps waiting for the user to enter sth.
}
String userInput = Serial.readStringUntil("\n");
return userInput;
}
I wrote this for the second LED, if I can manage this one, I will do the same for the other one but it's not working.
And here is the Processing codes:
import controlP5.*; //import ControlP5 library
import processing.serial.*;
Serial port;
ControlP5 cp5; //create ControlP5 object
PFont font;
PFont font2;
color col;
Serial serialMonitor;
String prompt;
ColorPicker cp;
void setup(){ //Same as setup in arduino
size(900, 900); //Window size, (width, height)
port = new Serial(this, "COM4", 9600); //Change this to your port
cp5 = new ControlP5(this);
font = createFont ("Georgia Bold", 20);
font2 = createFont ("Georgia Bold",15);
cp = cp5.addColorPicker("PICKER")
.setPosition(500,100)
.setColorValue(color(255,128,0,128))
;
Group configGroup = cp5.addGroup("CONFIGURATION")
.setPosition(90,100)
.setWidth(150)
.setHeight(30)
.setFont(font2)
.setBackgroundColor(color(0,0))
;
cp5.addButton("PICK_ALL") // The button
.setPosition(10, 10) // x and y relative to the group
.setSize(160, 150) // (width, height)
.setFont(font)
.setGroup(configGroup) // add it to the group
;
cp5.addButton("PICK_ONE") // The button
.setPosition(10, 200) // x and y relative to the group
.setSize(160, 150) // (width, height)
.setFont(font)
.setGroup(configGroup) // add it to the group
;
}
void draw(){ //Same as loop in arduino
background(150, 0 , 150); //Background colour of window (r, g, b) or (0 to 255)
}
public void controlEvent(ControlEvent c){
if(c.isFrom(cp)){
int r = int(c.getArrayValue(0));
int g = int(c.getArrayValue(1));
int b = int(c.getArrayValue(2));
int a = int(c.getArrayValue(3));
col = color(r,g,b,a);
}
}
void keyPressed(){
while(serialMonitor.available() > 0)
{
prompt = serialMonitor.readStringUntil (10);
}
println(keyCode);
String sendColor = nf(int(red(col)),3) + "," + nf(int(green(col)),3) + "," + nf(int(blue(col)),3);
println(sendColor);
serialMonitor.write(sendColor);
}
void PICKER(){
port.write('2');
}
void PICK_ALL(){
port.write('t');
}
void PICK_ONE(){
port.write('l');
}
I don't exactly know how to get the RGB values and use them in CRGB function. It is much easier when using a single RGB LED that uses 3 pins. But I couldn't implement it to an LED Ring that uses only 1 pin.
Here is the processing interface for color picking. I can select the colors but nothing is changing in the LED Ring on Arduino.
Reliable serial communication is not trivial. Ideally you would make you own binary communication protocol setting up a packet of bytes with a header that describes how many following bytes actually have data and perhaps even a checksum.
Strings will do to get started and it's great you're using nf() to make data easier to parse.
One potential gotcha could be the switch between putting a string together (rgbInput()) and reading one char at a time (char val = Serial.read();).
I would recommend breaking the problem down into smaller simpler parts, testing/debugging each part, then putting the parts back together one at a time to avoid integration bugs.
For example, the main challenge seems to be serial communication so I'd write a Processing and Arduino sketch to ensure that works reliably before adding in LED control.
Let's go for the option of \n terminated strings, even though it's sending a redundant extra character(e.g. port.write("2\n");) it would make buffering simpler:
always buffer until a newline
trim() the string for newline
if the trimmed string has length 1 it's a command (like '2', 'l', 't'), otherwise it's a colour triplet
Here's a basic Arduino sketch that uses the ideas above (and a bit of your code ;) ):
void setup() {
Serial.begin(9600);
}
void loop() {
// check if there are at least two characters to receive
if(Serial.available() > 1){
// buffer the full string until a new line character
String returnedInput = Serial.readStringUntil('\n');
// remove white space (new line char)
returnedInput.trim();
// if it's a single command
if(returnedInput.length() == 1){
char state = returnedInput.charAt(0);
switch(state){
case '2':
Serial.println("parsed 2 command");
break;
case 't':
Serial.println("parsed t command");
break;
case 'l':
Serial.println("parsed l command");
break;
default:
Serial.print("unknown state:");
Serial.println(state);
break;
}
}
// if it's a RGB triplet
else if(returnedInput.length() == 11){
String redString = returnedInput.substring(0, 3); //get 3 values like 255
String greenString = returnedInput.substring(4, 7);
String blueString = returnedInput.substring(8, 11);
int r = redString.toInt();
int g = greenString.toInt();
int b = blueString.toInt();
// constrain values to bytes
r = constrain(r, 0, 255);
g = constrain(g, 0, 255);
b = constrain(b, 0, 255);
// do something with the values (e.g. store globally, etc.)
Serial.print("parsed RGB: #");
Serial.print(r, HEX);
Serial.print(g, HEX);
Serial.print(b, HEX);
Serial.println();
}
// otherwise error message ?
else{
Serial.print("Uknown command: ");
Serial.println(returnedInput);
}
}
}
This should handle string messages with a new line terminator and based on the trimmed length parse either a single char command a 11 char RRR,GGG,BBB string.
You can test directly with Arduino's Serial Monitor.
In your Processing sketch it's unclear why there are two Serial ports (port and serialMonitor).
Here's a slightly modified version of your Processing sketch that sends either a couple of single char commands or the colour string:
import controlP5.*; //import ControlP5 library
import processing.serial.*;
PFont font;
PFont font2;
// Arduino serial port
Serial port;
// colour picker values to send to Arduino
int r;
int g;
int b;
// GUI variables
ControlP5 cp5; //create ControlP5 object
ColorPicker cp;
void setup() { //Same as setup in arduino
size(900, 900); //Window size, (width, height)
try {
port = new Serial(this, "/dev/tty.usbserial-A104WS3R", 9600); //Change this to your port
// buffer until new line: this plugs in nicely with serialEvent()
port.bufferUntil('\n');
}catch(Exception e) {
println("error opening serial");
e.printStackTrace();
}
cp5 = new ControlP5(this);
font = createFont ("Georgia Bold", 20);
font2 = createFont ("Georgia Bold", 15);
cp = cp5.addColorPicker("PICKER")
.setPosition(500, 100)
.setColorValue(color(255, 128, 0, 128))
;
Group configGroup = cp5.addGroup("CONFIGURATION")
.setPosition(90, 100)
.setWidth(150)
.setHeight(30)
.setFont(font2)
.setBackgroundColor(color(0, 0))
;
cp5.addButton("PICK_ALL") // The button
.setPosition(10, 10) // x and y relative to the group
.setSize(160, 150) // (width, height)
.setFont(font)
.setGroup(configGroup) // add it to the group
;
cp5.addButton("PICK_ONE") // The button
.setPosition(10, 200) // x and y relative to the group
.setSize(160, 150) // (width, height)
.setFont(font)
.setGroup(configGroup) // add it to the group
;
}
void draw() { //Same as loop in arduino
background(150, 0, 150); //Background colour of window (r, g, b) or (0 to 255)
}
public void controlEvent(ControlEvent c) {
if (c.isFrom(cp)) {
r = int(c.getArrayValue(0));
g = int(c.getArrayValue(1));
b = int(c.getArrayValue(2));
}
}
void keyPressed() {
if(port == null){
println("no serial, ignoring");
return;
}
String sendColor = nf(r, 3) + "," + nf(g, 3) + "," + nf(b, 3) + '\n';
println("sending to Arduino:", sendColor);
port.write(sendColor);
}
void PICKER() {
println("PICKER");
if (port != null) port.write("2\n");
}
void PICK_ALL() {
println("PICK_ALL");
if (port != null) port.write("t\n");
}
void PICK_ONE() {
println("PICK_ONE");
if (port != null) port.write("l\n");
}
void serialEvent(Serial s){
println("from Arduino:", s.readString());
}
Overall notice bits of error checking: always a good idea when working with Serial :)
Once this works as expected you can combine the FastLED control.
Here's a suggestion:
#include <FastLED.h>
#define LED_PIN1 3
#define LED_PIN2 12
#define NUM_LEDS1 16
#define NUM_LEDS2 24
CRGB leds1[NUM_LEDS1];
CRGB leds2[NUM_LEDS2];
// ring 1 color
int r1,g1,b1;
// ring 2 color
int r2,g2,b2;
// toggle wether to update r1,g1,b1 or r2,g2,b2 when a new colour arrives
boolean updateRing1 = true;
void setup() {
// setup serial
Serial.begin(9600);
// setup LEDs
FastLED.addLeds<WS2812, LED_PIN1, GRB>(leds1, NUM_LEDS1);
FastLED.addLeds<WS2812, LED_PIN2, GRB>(leds2, NUM_LEDS2);
}
void loop() {
handleSerial();
driveLEDRings();
}
void handleSerial(){
// check if there are at least two characters to receive
if(Serial.available() > 1){
// buffer the full string until a new line character
String returnedInput = Serial.readStringUntil('\n');
// remove white space (new line char)
returnedInput.trim();
// if it's a single command
if(returnedInput.length() == 1){
char state = returnedInput.charAt(0);
switch(state){
case '2':
Serial.println(F("parsed 2 command"));
break;
case 't':
Serial.println(F("parsed t command: switching to ring #1"));
updateRing1 = true;
break;
case 'l':
Serial.println(F("parsed l command: switching to ring #2"));
updateRing1 = false;
break;
default:
Serial.print(F("unknown state:"));
Serial.println(state);
break;
}
}
// if it's a RGB triplet
else if(returnedInput.length() == 11){
String redString = returnedInput.substring(0, 3); //get 3 values like 255
String greenString = returnedInput.substring(4, 7);
String blueString = returnedInput.substring(8, 11);
int r = redString.toInt();
int g = greenString.toInt();
int b = blueString.toInt();
// constrain values to bytes
r = constrain(r, 0, 255);
g = constrain(g, 0, 255);
b = constrain(b, 0, 255);
// do something with the values (e.g. store globally, etc.)
Serial.print(F("parsed RGB: #"));
Serial.print(r, HEX);
Serial.print(g, HEX);
Serial.print(b, HEX);
Serial.println();
// handle ring colour update
if(updateRing1){
r1 = r;
g1 = g;
b1 = b;
}else{
r2 = r;
g2 = g;
b2 = b;
}
}
// otherwise error message ?
else{
Serial.print("Uknown command: ");
Serial.println(returnedInput);
}
}
}
void driveLEDRings(){
//update ring 1
for(int i = 0 ; i < NUM_LEDS1; i++){
leds1[i] = CRGB(r1, g1, b1);
}
//update ring 2
for(int i = 0 ; i < NUM_LEDS2; i++){
leds2[i] = CRGB(r2, g2, b2);
}
// display
FastLED.show();
}
Note: the above code isn't tested with wired RGB LEDs so it might not work but hopefully it illustrates the idea. (You should double check the baud rate, pins, RGB colour channels, etc.)
If the above works as expected using Serial Monitor you can get back to testing the Processing interface sketch.
Additionally bare in mind 9600 is quite a low baud rate.
You should test with higher baud rates (e.g. 115200, 57600) and if it's stable use those to avoid delays driving LEDs while buffering serial data.
In general avoid / minimise blocking (while) loops where you can.
Overall, the idea is to delete/remove anything you don't need in your code to drill down to the problem: work it out in isolation. Once that's debugged and working reliably add new code one bit a time, testing after each addition (otherwise you risk introducing more bugs instead of one which is harder to spot / fix).
Using a LDR sensor for Arduino, I want to switch between two gif backgrounds in Processing depending on the intensity of light that the LDR senses. My Arduino set-up works and I can see a range of numbers in the Serial Monitor depending on the amount of light shined on the sensor - however I'm having trouble in Processing with making the switch between backgrounds. This is my first project combining Arduino with Processing so please forgive me if I've made any super obvious mistakes.
Arduino Code
int sensorPin = A0; // select the input pin for LDR
int sensorValue = 0; // variable to store the value coming from the sensor
void setup() {
Serial.begin(9600); //sets serial port for communication
}
void loop() {
sensorValue = analogRead(sensorPin); // read the value from the sensor
Serial.println(sensorValue); //prints the values coming from the sensor on the screen
delay(100);
}
Processing Code
//loads gif library for background
import gifAnimation.*;
Gif batmanGotham;
Gif batmanLair;
//loads Arduino
import processing.serial.*;
Serial myPort;
int sensorValue = 0;
void setup() {
size(1067, 800); //size of canvas
batmanGotham = new Gif(this, "background.gif"); //set gif
batmanGotham.play();
batmanLair = new Gif(this, "batman_lab.gif"); //set second gif
batmanLair.play();
String portName = "/dev/cu.usbmodem14201";
myPort = new Serial(this, portName, 9600);
myPort.bufferUntil('\n');
}
void draw() {
}
void serialEvent (Serial myPort) {
if (sensorValue > 300) {
image(batmanLair, 0, 0); //lays down gif background
} else {
image(batmanGotham, 0, 0); //lays down gif background
}
}
You forgot to read data from the serial port, try adding the following line on your serialEvent() routine:
byte[] buffer = new byte[2];
sensorValue = myPort.readBytes(buffer);
at the very beginning.
As you see you have to recover data from the buffer yourself. The event is triggered automatically whenever there is something to read but you have to take is yourself from there and store it or process it.
You should be reading two bytes at a time to account for the size of the int you are sending from your Arduino.
Marcos is right, through you will be sending more than two bytes.
Let's assume you're sending 1023, that is actually 4 characters (bytes) + another new line (from println).
You can draw continuously and simply update the image based on the data read, ideally with some error checking:
//loads gif library for background
import gifAnimation.*;
Gif batmanGotham;
Gif batmanLair;
//loads Arduino
import processing.serial.*;
Serial myPort;
int sensorValue = 0;
void setup() {
size(1067, 800); //size of canvas
batmanGotham = new Gif(this, "background.gif"); //set gif
batmanGotham.play();
batmanLair = new Gif(this, "batman_lab.gif"); //set second gif
batmanLair.play();
String portName = "/dev/cu.usbmodem14201";
try{
myPort = new Serial(this, portName, 9600);
myPort.bufferUntil('\n');
}catch(Exception e){
println("error opening serial port: double check the cable is connected, the portName is right and SerialMonitor anything else trying to access the port is closed");
e.printStackTrace();
}
}
void draw() {
if (sensorValue > 300) {
image(batmanLair, 0, 0); //lays down gif background
} else {
image(batmanGotham, 0, 0); //lays down gif background
}
}
void serialEvent (Serial myPort) {
try{
String rawString = myPort.readString();
if(rawString != null && rawString.length() > 0){
// remove newline
rawString = rawString.trim();
// parse value
sensorValue = int(rawString);
}
}catch(Exception e){
println("error parsing serial data");
e.printStackTrace();
}
}
If you want to keep the Processing Serial part simpler, you can do the threshold logic on arduino and simply send a single byte to Processing, like 1 or 0 depending on which image you want to display:
int sensorPin = A0; // select the input pin for LDR
int sensorValue = 0; // variable to store the value coming from the sensor
void setup() {
Serial.begin(9600); //sets serial port for communication
}
void loop() {
sensorValue = analogRead(sensorPin); // read the value from the sensor
if(sensorValue > 0){
Serial.print('1');
}else{
Serial.print('0');
}
delay(100);
}
Then in Processing:
//loads gif library for background
import gifAnimation.*;
Gif batmanGotham;
Gif batmanLair;
//loads Arduino
import processing.serial.*;
Serial myPort;
boolean showLair;
void setup() {
size(1067, 800); //size of canvas
batmanGotham = new Gif(this, "background.gif"); //set gif
batmanGotham.play();
batmanLair = new Gif(this, "batman_lab.gif"); //set second gif
batmanLair.play();
String portName = "/dev/cu.usbmodem14201";
try{
myPort = new Serial(this, portName, 9600);
}catch(Exception e){
println("error opening serial port: double check the cable is connected, the portName is right and SerialMonitor anything else trying to access the port is closed");
e.printStackTrace();
}
}
void draw() {
// read 1 char
if(myPort != null && myPort.available() > 0){
char fromArduino = myPort.read();
showLair = (fromArduino == '1');
}
// update content
if (showLair) {
image(batmanLair, 0, 0); //lays down gif background
} else {
image(batmanGotham, 0, 0); //lays down gif background
}
}
I successfully managed to send a single integer from processing to Arduino but now I want to send an array of three integers and I can't get it working. I want to create a buzzer feedback with Arduino which processing will control which buzzer to activate. For example, the data send from processing should be [1,0,1] meaning sensor 1 and 3 should start working. The buzzers should be able to be activated simultaneously in case that [1,1,1] goes through.
This is the code I have so far:
I am trying to understand what data is being sent back to Arduino to know how to use it and I keep getting either a null value or a random integer.
I'm trying to learn how to do this so apologies if the code is bad.
Arduino
void setup(){
Serial.begin(9600); // Start serial communication at 9600 bps
}
void loop(){
if (Serial.available()){
const char data = Serial.read();
char noteBuzzer[] = {data};
for (int i = 0 ; i < sizeof(noteBuzzer); i++) {
}
Serial.print(noteBuzzer[1]);
}
}
Processing
import processing.serial.*;
String notes[];
String tempo[];
Serial myPort;
String val;
void setup(){
size(200,200);
String portName = Serial.list()[0];
myPort = new Serial(this, portName, 9600);
notes = loadStrings("data/notes.txt");
tempo = loadStrings("data/tempo.txt");
}
void draw() {
if (keyPressed == true)
{
if (key == '1') {
println("Start");
readNotes();
}
}
}
void readNotes(){
for (int i = 0 ; i < notes.length; i++) {
println(notes[i]);
//println(tempo[i]);
myPort.write(notes[i]);
delay(int(tempo[i])); //this will be the tempo?
if ( myPort.available() > 0)
{
val = myPort.readStringUntil('\n');
println("Arduino",val);
}
}
}
If you're data is an array that always has 3 items and each of those items are always either 1 or 0 (bits), you could store that whole data in a single byte (and still have 5 more bits to spare). Sending and receiving a byte is pretty simple with Arduino.
Here's a basic sketch that shows you how to flip 3 bits in a single byte:
// the state as a byte
byte buzzerState = 0B000;
void setup(){
textFont(createFont("Courier New",18),18);
}
void draw(){
background(0);
text("DEC: " + buzzerState +
"\nBIN:" + binary(buzzerState,3),10,40);
}
void keyPressed(){
if(key == '1'){
buzzerState = flipBit(buzzerState,0);
}
if(key == '2'){
buzzerState = flipBit(buzzerState,1);
}
if(key == '3'){
buzzerState = flipBit(buzzerState,2);
}
}
// flips a bit at a given index within a byte and returns updated byte
byte flipBit(byte state,int index){
int bit = getBitAt(state,index);
int bitFlipped = 1 - bit;
return setBitAt(state,index,bitFlipped);
}
// returns the integer value of a bit within a byte at the desired index
int getBitAt(byte b,int index){
index = constrain(index,0,7);
return b >> index & 1;
}
// sets an individual bit at a desired index on or off (value) and returns the updated byte
byte setBitAt(byte b,int index, int value){
index = constrain(index,0,7);
value = constrain(value,0,1);
if(value == 1) b |= (1 << (index));
else b &= ~(1 << (index));
return b;
}
Use keys '1','2' and '3' to flip the bits.
Note that in keypress we're always updating the same byte.
The text will display the decimal value first and the binary value bellow.
This is the most efficient way to send your data and the simplest in terms of serial communication. On the Arduino side you can simply use bitRead() on the byte you get from Serial.read(). For more on binary/bits/bytes be sure to read the BitMath Arduino tutorial. Binary may seem intimidating at first, but it's really not that bad once you practice a bit and it's totally worth knowing.
Here's an updated version of the code above that sends the byte to Arduino on the first available serial port (be sure to change Serial.list()[0] with what makes sense for your setup and press 's' to send an update to Arduino:
import processing.serial.*;
// the state as a byte
byte buzzerState = 0B000;
Serial port;
void setup(){
textFont(createFont("Courier New",18),18);
try{
port = new Serial(this,Serial.list()[0],9600);
}catch(Exception e){
e.printStackTrace();
}
}
void draw(){
background(0);
text("DEC: " + buzzerState +
"\nBIN:" + binary(buzzerState,3),10,40);
}
void keyPressed(){
if(key == '1'){
buzzerState = flipBit(buzzerState,0);
}
if(key == '2'){
buzzerState = flipBit(buzzerState,1);
}
if(key == '3'){
buzzerState = flipBit(buzzerState,2);
}
if(key == 's'){
if(port != null){
port.write(buzzerState);
}else{
println("serial port is not open: check port name and cable connection");
}
}
}
// flips a bit at a given index within a byte and returns updated byte
byte flipBit(byte state,int index){
int bit = getBitAt(state,index);
int bitFlipped = 1 - bit;
return setBitAt(state,index,bitFlipped);
}
// returns the integer value of a bit within a byte at the desired index
int getBitAt(byte b,int index){
index = constrain(index,0,7);
return b >> index & 1;
}
// sets an individual bit at a desired index on or off (value) and returns the updated byte
byte setBitAt(byte b,int index, int value){
index = constrain(index,0,7);
value = constrain(value,0,1);
if(value == 1) b |= (1 << (index));
else b &= ~(1 << (index));
return b;
}
And here's a super basic Arduino sketch:
byte buzzerState;
void setup() {
Serial.begin(9600);
//test LEDs setup
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
}
void loop() {
if(Serial.available() > 0){
buzzerState = Serial.read();
bool bit0 = bitRead(buzzerState,0);
bool bit1 = bitRead(buzzerState,1);
bool bit2 = bitRead(buzzerState,2);
//test LEDs update
digitalWrite(10,bit0);
digitalWrite(11,bit1);
digitalWrite(12,bit2);
}
}
If you connect 3 LEDs to pins 10,11,12 you should them toggle as you press keys '1','2','3' then 's' in Processing
One way around binary in Processing could be using a String representation of your data (e.g. "00000101" for [1,0,1]) and unbinary() to convert that String to an integer value you can write to serial, but it will be a bit annoying to getting and setting a character at an index (and potentially parsing that char to it's integer value and back)
When you need to send more than a byte things get a bit more complicated as you need to handle data corruption/interruptions, etc. In these situations it's best to setup/design a communication protocol based on your needs and this isn't easy if you're just getting started with Arduino, but not impossible either. Here's an example, there are many more online.
One quick and dirty thing you could try is sending that data as string terminated by a new line character (\n) which you could buffer until in Arduino then read 4 bytes at a time, discarding the \n when parsing:
e.g. sending "101\n" from Processing, representing [1,0,1] then on the Arduino side use Serial.readStringUntil('\n') and a combination of charAt() and toInt() to access each integer within that that string.
Here's an example Processing sketch:
import processing.serial.*;
// the state as a byte
String buzzerState = "010\n";
Serial port;
void setup(){
textFont(createFont("Courier New",18),18);
try{
port = new Serial(this,Serial.list()[0],9600);
}catch(Exception e){
e.printStackTrace();
}
}
void draw(){
background(0);
text(buzzerState,30,50);
}
void keyPressed(){
if(key == '1'){
buzzerState = flipBit(buzzerState,0);
}
if(key == '2'){
buzzerState = flipBit(buzzerState,1);
}
if(key == '3'){
buzzerState = flipBit(buzzerState,2);
}
if(key == 's'){
if(port != null){
port.write(buzzerState);
}else{
println("serial port is not open: check port name and cable connection");
}
}
}
String flipBit(String state,int index){
index = constrain(index,0,2);
// parse integer from string
int bitAtIndex = Integer.parseInt(state.substring(index,index+1));
// return new string concatenating the prefix (if any), the flipped bit (1 - bit) and the suffix
return state = (index > 0 ? state.substring(0,index) : "") + (1 - bitAtIndex) + state.substring(index+1);
}
And an Arduino one based on Arduino > File > Examples > 04.Communication > SerialEvent:
/*
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.
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
boolean stringComplete = false; // whether the string is complete
void setup() {
// initialize serial:
Serial.begin(9600);
// reserve 200 bytes for the inputString:
inputString.reserve(200);
// test LEDs setup
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
pinMode(12,OUTPUT);
}
void loop() {
// print the string when a newline arrives:
if (stringComplete) {
Serial.println(inputString);
// process string
bool bit0 = inputString.charAt(2) == '1';
bool bit1 = inputString.charAt(1) == '1';
bool bit2 = inputString.charAt(0) == '1';
//test LEDs update
digitalWrite(10,bit0);
digitalWrite(11,bit1);
digitalWrite(12,bit2);
// 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 == '\n') {
stringComplete = true;
}
}
}
Note this is more prone to error and used 4 times as much data as the the single byte option.
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 form a two player game which requires an audio reflex to a visual. by using littebits sound trigger for sound input and littbits arduino to connect it to the computer. But I am new to this and don't know how to connect arduino to processing and use the input from sound trigger to effect the score when a black square appears.
here is my code in processing and a sample arduino code I have taken from littlebits website and tried to modify a little.
thanks in advance!
float dice;
int playerOne = 0; //player 1 score (left paddle)
int playerTwo = 0; //player 2 score (right paddle)
boolean oneWins = false;
boolean twoWins = false;
void setup(){
size(500, 500);
smooth();
noStroke();
frameRate(2.5);
}
void draw() {
background(255);
showGUI();
dice = random(0, 3);
if (dice < 1.000001 && dice > 0.1){
fill ((0), (255), (0));
ellipse (250,250,100,100);
} else if (dice < 2.000001 && dice > 1.000001){
rectMode(RADIUS);
fill ((255), (0), (0));
rect (250,250,50,50);
} else if (dice < 3.000000 && dice > 1.000000){
rectMode(RADIUS);
fill ((0), (0), (255));
rect (250,250,50,50);
} else if (dice < 0.1){
rectMode(RADIUS);
fill(0);
rect(250,250,50,50);
}
}
----------arduino------
void setup() {
Serial.begin(9600); //Establish rate of Serial communication
establishContact(); //See function below
}
void loop() {
if (Serial.available() > 0) {
int inByte = Serial.read();
int leftTrigger = analogRead(A0);
Serial.print(leftTrigger, DEC);
Serial.print(",");
int rightTrigger = analogRead(A1);
Serial.println(rightTrigger, DEC);
}
}
void establishContact() {
while (Serial.available() <= 0) {
Serial.println("hello");
delay(300);
}
}
You need two pieces of code for this to work: one on the Arduino that sends commands, and one for Processing to receive and parse those commands.
I haven't used the littlebits modules, but here's a button example from this very detailed tutorial.
Arduino code:
int switchPin = 4; // switch connected to pin 4
void setup() {
pinMode(switchPin, INPUT); // set pin 0 as an input
Serial.begin(9600); // start serial communication at 9600bps
}
void loop() {
if (digitalRead(switchPin) == HIGH) { // if switch is ON,
Serial.print(1, BYTE); // send 1 to Processing
} else { // if the switch is not ON,
Serial.print(0, BYTE); // send 0 to Processing
}
delay(100); // wait 100 milliseconds
}
And the matching Processing code:
import processing.serial.*;
Serial port; // create object from Serial class
int val; // data received from the serial port
void setup() {
size(200, 200);
frameRate(10);
// open the port that the board is connected to
// and use the same speed (9600bps)
port = new Serial(this, 9600);
}
void draw() {
if (0 < port.available()) { // if data is available,
val = port.read(); // read it and store it in val
}
background(255); // set background to white
if (val == 0) { // if the serial value is 0,
fill(0); // set fill to black
} else { // if the serial value is not 0,
fill(204); // set fill to light gray
}
rect(50, 50, 100, 100);
}
Notice that the Arduino sends a value that Processing looks for and interprets. You can also look at the PhysicalPixel example from the Arduino IDE for an example on sending data from Processing to Arduino.