0

I am working on a small project with Processing and Arduino, in which, depending upon the value of a photoresistor, it displays whether it is day/night/evening.

I read the value from the photoresistor and write the value to the serial port. Then in Processing I read the value from the serial port and display depending on the value.

But I get a very flickery output, and there is always a -1 imprinted on the screen as shown in the video.

Please help me out.

link to the video

Code for Arduino:

int ldr1 = A0;
int x,y;

void setup() {
  pinMode(ldr1,INPUT);
  Serial.begin(9600);
}

void loop() {
  x = analogRead(ldr1);
  Serial.write(x);
  delay(100);
}

Code for Processing:

import processing.serial.*;
Serial port;
int x,y;

void setup() {
  size(640, 320);
  port = new Serial(this, "COM3", 9600);
}

void draw() {
  background(0);
  x = port.read();
  text(x,100,100);
  if(x < 400 && x > 200) {
    textSize(32);
    fill(0,0,255);
    text("it is evening",200,200);
  }
  if(x < 200 && x > 20) {
    textSize(32);
    fill(0,255,0);
    text("it is night",200,200);
  }
  if(x > 400 && x < 900) {
    textSize(32);
    fill(255,0,0);
    text("it is morning",200,200);
  }
}
  • Is the Arduino actually on COM3? If serial read returns -1, then you did not receive a byte. You should check for if read >= 0 before entering your "if x < ... " etc. – KyranF Mar 5 '17 at 20:05
1

If you read the documentation for Serial::read() at https://processing.org/reference/libraries/serial/Serial_read_.html

it says:
"Returns a number between 0 and 255 for the next byte that's waiting in the buffer. Returns -1 if there is no byte, although this should be avoided by first cheacking available() to see if data is available."

Either before calling "Draw" function, or inside "Draw", you should first check:

if(port.available()){
  //do your checking for X value and set text as you are doing before

}

IMPORTANT - you are only ever sending the lower byte (values 0-255) from Arduino when you do Serial.write(x). That is only 1 byte. The "int" return from an analogue read is 10 bits, and needs 2 bytes to store the information from 0-1023.

You should use the Arduino function Map() to scale it down from 0-1023 to 0-255. It looks like your application should be okay with this, in terms of resolution.

  int val = analogRead(ldr1);
  val = map(val, 0, 1023, 0, 255);
  Serial.write(val); //now you will not lose information

On the Processing side, you would then look at values from 0-255 to determine daylight/times of day.

| improve this answer | |
  • Map is great if you need to do a linear interpolation but in a situation like this it's complete overkill. Rather than using map you could just divide the value by 4 or shift it right by 2 bits using 'val = val >> 2'. Either of these options are both far smaller and faster. – Andrew May 5 '17 at 9:03
  • @Andrew you are correct, it's handy that it's a factor of 2 so shifting or division is fine. – KyranF May 5 '17 at 11:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.