Tilt switch not working in processing

Hi! I'm currently doing a project, which I've already asked for some help for, but it seems that another problem has arisen. The project includes the tilt switch which comes with the starter kit. I have to control some type of visuals in Processing with this tilt switch, and have decided on a very simple switch between two different ellipses; a smaller, yellow one and a larger, green one. When I open the Arduino serial monitor, I can clearly see the switch working; turning on and off as I tilt it. However, when I try to see this on/off in Processing, it doesn't seem to be picking it up at all.

Here's my Arduino code (which I borrowed from here: The Terrific Tilt Switch (with Processing) - Make: Basic Arduino Projects - 26 Experiments with Microcontrollers and Electronics (2014)):

// variables for input pin and control LED
int digitalInput = 8;
int LEDpin = 13;

// variable to store the value
int value = 0;

void setup() {
  // declaration pin modes
  pinMode(digitalInput, INPUT);
  pinMode(LEDpin, OUTPUT);

  // begin sending over serial port
  Serial.begin(9600);
}

void loop() {
  // read the value on digital input
  value = digitalRead(digitalInput);

  // write this value to the control LED pin
  digitalWrite(LEDpin, value);

  // if value is high then send the letter 'H'; otherwise, send 'L' for low
  if (value) Serial.println('H');

  else
    Serial.println('L');
  // wait a bit to not overload the port
  delay(250);
}

And here's my Processing code:

import processing.serial.*;
Serial port;

int val;
int padding = 100;
float m;

void setup() {
  size(400, 400);
  noStroke();
  background(200);
  port = new Serial(this, "COM3", 9600);
  port.bufferUntil('\n');
}
void draw() {
  if (port.available()>0) {
    val=port.read();
  }
  if (val==-1) {
    ellipse(200, 200, 100, 100);
    fill(#FFDE14);
    println(port.read());
  } else {
    ellipse(200, 200, 150, 150);
    fill(#10e047);
    println(port.read());
  }
}

The values I'm getting in Processing only consist of -1, no matter how many times I tilt the switch...

Which COM port is the Arduino using ?

COM3, I only have that one available (or activated, I don't know if that makes sense?) when I look at tools and then ports.

if you have the Serial monitor open in the IDE, your Processing program won't be able to connect and read will fail, returning -1
the other thing is that you'll be receiving the \r and \n so you have to deal with that in your drawing

your protocol is simple enough to deal with 1 byte reads so on the arduino side do

if (value) Serial.write('H'); 
else Serial.write('L');

and just receive the incoming byte stream on the processing side, you won't have to worry about line termination etc

Hm, I tried closing the Arduino IDE entirely, and something did happen. Now, I'm getting values like 72, 10 and 13 in between the -1's, but quite rarely. My guess is, that these are ASCII characters, since I have been having that problem with another part of the project too. Do you think this is the case, it being ASCII characters?

Also, I'm not quite sure what the \r and \n are, as I've borrowed this code from elsewhere. When you say deal with them, I'm guessing I have to convert them somehow? But into what? And what are they even to begin with?? I'm so confused :laughing:

I changed the println() to write(), but am still not seeing any difference on the Processing side; I'm guessing it's because of the things I asked about above...

those are the ASCII codes you are sending, 10 is line feed (the '\n' code) and 13 is carriage return (the '\r' code)

if you changed for the write, you need to change the Processing code to not buffer -> get rid of

port.bufferUntil('\n');

the -1 you are seeing are likely timeout

If you use that setting, you should not mess around with single character reads.
Use the asynchronously called function serialEvent() for that.

https://www.processing.org/reference/libraries/serial/serialEvent_.html

Okay, so I did this to my sketch, trying to follow the example:

import processing.serial.*;
Serial port;

int val;
int padding = 100;
float m;
String inString;

void setup() {
  size(400, 400);
  noStroke();
  background(200);
  printArray(Serial.list());
  port = new Serial(this, "COM3", 9600);
  port.bufferUntil('\n');
}
void draw() {
  if (port.available()>0) {
    val=port.read();
  }
  if (val==-1) {
    ellipse(200, 200, 50, 50);
    fill(#FFDE14);
    println(port.read());
  } else {
    ellipse(200, 200, 150, 150);
    fill(#FFDE14);
    println(port.read());
  }
}
void serialEvent(Serial p) {
  inString = p.readString();
}

But it's still just -1's... I must've really messed up the logic somewhere, huh?

Hm, I tried turning off the buffer, still just -1's. I dunno, I feel like I've totally messed up the code, 'cause all of you guys are trying so hard to help me, but nothing works haha

What is so hard to understand in: "not mess around with single character reads"?

Do not use
port.available()
or
port.read()

Print your inString, if you want to see what is received.

I wasn't aware those were single character reads; I'm still quite a beginner, I apologize. When I delete those lines, I'm still getting -1's. However, I think I'll just give up trying to get it to work and explain in my report what I think went wrong, since the due date is tomorrow morning.

You did not post your try, and I am too lazy to guess.

The documentation I linked to, has a working example, did you try it?

Ah, I see!! This is my code now, and it's printing H for on and L for off in the serial monitor!!! :smiley:

import processing.serial.*;
Serial port;

int val;
int padding = 100;
float m;
String inString;

void setup() {
  size(400, 400);
  noStroke();
  background(200);
  printArray(Serial.list());
  port = new Serial(this, "COM3", 9600);
  port.bufferUntil('\n');
}
void draw() {
  print(inString);
  if (val==-1) {
    ellipse(200, 200, 50, 50);
    fill(#FFDE14);
    println(port.read());
  } else {
    ellipse(200, 200, 150, 150);
    fill(#FFDE14);
    println(port.read());
  }
}
void serialEvent(Serial p) {
  inString = p.readString();
}

I had forgotten to print the string, and got really frustrated that nothing happened :laughing:

Now, I just need to connect those values being printed in the serial monitor, with the if statement; so I would want the small ellipse to pop up if the value being printed is L, meaning the switch is off and the big ellipse popping up, whenever the tilt switch is connected, so when there's H's in the serial monitor. After looking at another forum, I tried doing what they suggested, using the equals function. So my code now looks like this:

import processing.serial.*;
Serial port;

int val;
int padding = 100;
float m;
String inString;


void setup() {
  size(400, 400);
  noStroke();
  background(200);
  printArray(Serial.list());
  port = new Serial(this, "COM3", 9600);
  port.bufferUntil('\n');
}
void draw() {
  print(inString);
  if (inString.equals("L")) {
    ellipse(200, 200, 50, 50);
    fill(#FFDE14);
    println(port.read());
   } else if (inString.equals("H")) {
    ellipse(200, 200, 150, 150);
    fill(#FFDE14);
    println(port.read());
  }
}
void serialEvent(Serial p) {
  inString = p.readString();
}

But when I try to run it, it's highlighting the first if statement and I'm getting an error code like this:

[0] "COM3"
nullNullPointerException

Seems your Arduino is not active on COM3 anymore.

Maybe you have to trim() the received string, IIRC some CR or LF are still appended to the string.

https://processing.org/reference/trim_.html

I went back to the Arduino IDE and it's definitely active now, but it didn't solve the problem. I've been trying the trim() technique and actually got it working for a second, but apparently I decided to change it and now I can't get it back to working :sweat_smile:
I've tried putting the trim() function in several places (off course deactivating others, as I'm testing, hence why some of the ones below are listed as comments), but am still getting the same error.

import processing.serial.*;
Serial port;

int val;
int padding = 100;
float m;
String inString;
String inString2 = trim(inString); // am very uncertain about this, they did it on the example, but I don't really see what for - I tried adding the "String[] a2 = trim(a1); printArray(a2);", right below the print(inString); in void draw(), but I'm getting error code: Type mismatch, "java.lang.String" does not match with "java.lang.String[]" 

void setup() {
  size(400, 400);
  noStroke();
  background(200);
  printArray(Serial.list());
  port = new Serial(this, "COM3", 9600);
  port.bufferUntil('\n');
}
void draw() {
  print(inString);
  //trim(inString);
  if (inString.equals("L")) {
    trim(inString);
    ellipse(200, 200, 50, 50);
    fill(#FFDE14);
    println(port.read());
  } else if (inString.equals("H")) {
  //  trim(inString);
    ellipse(200, 200, 150, 150);
    fill(#FFDE14);
    println(port.read());
  }
}
void serialEvent(Serial p) {
  inString = p.readString();
}

Programming is different from jigsaw puzzles.

You should try to understand what you are doing.
The most simple place for the trim() would be in the event function.
inString = trim(p.readString()); could work.

Yeah, I really messed myself over by not participating too actively in online lessons; it must be frustrating trying to teach someone, who's not even sure of the basics, I really do apologize for that. I tried your suggestion but am still getting the same error. I also tried moving the event to earlier on in the program, thinking it was because the trimming was happening too late; but still to no avail.

import processing.serial.*;
Serial port;

int val;
int padding = 100;
float m;
String inString;

void setup() {
  size(400, 400);
  noStroke();
  background(200);
  printArray(Serial.list());
  port = new Serial(this, "COM3", 9600);
  port.bufferUntil('\n');
}
void draw() {
  print(inString);
  if (inString.equals("L")) {
    ellipse(200, 200, 50, 50);
    fill(#FFDE14);
    println(port.read());
  } else if (inString.equals("H")) {
    ellipse(200, 200, 150, 150);
    fill(#FFDE14);
    println(port.read());
  }
}
void serialEvent(Serial p) {
  inString = trim(p.readString());
  inString = p.readString();
}

Edit: Since I'm still new to this website, I can't write anymore replies before 5 hours have passed, but I got a bunch of stuff to try, so thank you very, very much to both of you @Whandall and @J-M-L !! :smiley:

you were not far, try something like this:

arduino

// variables for input pin and control LED
const byte tiltSwitchPin = 8;  // wiring: D8 --- tilt Switch -- GND
const byte LEDpin = 13;
int previousState;

void setup() {
  pinMode(tiltSwitchPin, INPUT_PULLUP);
  pinMode(LEDpin, OUTPUT);
  Serial.begin(115200);
  Serial.println(F("Hello from Arduino"));
  previousState = digitalRead(tiltSwitchPin);
}

void loop() {
  int currentState = digitalRead(tiltSwitchPin);        // read the value on digital input. HIGH == not active

  // did the state change?
  if (currentState != previousState) {

    // write this value to the control LED pin
    digitalWrite(LEDpin, currentState == LOW ? HIGH : LOW);

    // if value is high then send the letter 'H'; otherwise, send 'L' for low
    if (currentState == HIGH) Serial.write('H');
    else Serial.write('L');

    // remember the new current state
    previousState = currentState;

    delay(30); // just in case the sensor is bouncing
  }
}

Processing

import processing.serial.*;
Serial arduino;

void setup() {
  size(400, 400);
  // display the known Serial ports
  printArray(Serial.list());
  noStroke();
  arduino = new Serial(this, Serial.list()[1], 115200); // pick the right entry for your arduino
}
void draw() {
  if (arduino.available() > 0) {
    int val = arduino.read();
    if (val=='H') {
      background(200);
      ellipse(200, 200, 100, 100);
      fill(#FFDE14);
    } else 
    if (val == 'L') {
      background(200);
      ellipse(200, 200, 150, 150);
      fill(#10e047);
    }
  }
}

On the processing side you'll have too look in the console to see at which index you arduino is and change the array index ([1] for my case) in this line
arduino = new Serial(this, Serial.list()[1], 115200); // pick the right entry for your arduino

note that I changed the baud rate to 115200 as there is no reason to go slow
I also changed the tilt switch to be INPUT_PULLUP, so the wiring is pin D8 -- switch -- GND and readings will be inverted (LOW means it's active)

1 Like

You try to access inString before it has any value.

Try ìnString = "nothing"; in setup.

void serialEvent(Serial p) {
  inString = trim(p.readString());
  inString = p.readString();
}

drop the dumb second read.

1 Like