using serial communication to vary the led brightness

Hi, I’m been working on this project tried to use serial communication to vary the led brightness(vary the duty cycle). Basically the program has 3 function ON, OFF , Brightness. I couldn’t get the brightness function to work. tried so many ways. I’ll inlcude the code for my latest attempt. any help will be greatly appreciated.

int ledPin = 9;
char val;

int brightness = 0;
int fadeamount = 5;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);

}

void loop() {

  ONOFF();
  bright();
  if (Serial.available()) {
    val = Serial.read();
  }

}
void ONOFF() {

  if (val == '1') {
    analogWrite(ledPin, HIGH);
  } else if ( val =='2') {
    digitalWrite(ledPin, LOW);

  }
}

void bright() {
  if ( val == '3' && brightness == 255) {
    analogWrite(ledPin, brightness);

    brightness = brightness - 5;
    delay(250);

  }else if(val == '3' && brightness == 0){
    brightness = brightness +5;
      delay(250);
    }



}

and here is the processing code, serial communication works fine.

import processing.serial.*;
Serial myPort;

void setup() {
  size(400, 400);
  background(255);
  textAlign(CENTER);
  rectMode(CENTER);

  String portName = Serial.list()[5];
  printArray(Serial.list());
  myPort = new Serial(this, portName, 9600);
}

void draw() {
  fill(0, 255, 0);
  rect(200, 100, 200, 80);
  fill(0);
  textSize(40);
  text("ON", 200, 110);

  fill(255, 0, 0);
  rect(200, 200, 200, 80);
  fill(0);
  textSize(40);
  text("OFF", 200, 210);

  fill(120);
  rect(200, 300, 200, 80);  
  fill(0);
  textSize(30);
  text("BRIGHTNESS", 200, 310);

  if (mousePressed&&(mouseY>60)&&(mouseY<140)&&(mouseX>150)&&(mouseX<250)) {
    myPort.write('1');
    println("1");
    fill(255, 255, 0);
    rect(200, 100, 200, 80);
  }
  if (mousePressed&&(mouseY>160)&&(mouseY<240)&&(mouseX>150)&&(mouseX<250)) {
   myPort.write('2'); 
    println("2");
    fill(255, 255, 0);
    rect(200, 200, 200, 80);
  }
  if (mousePressed&&(mouseY>260)&&(mouseY<340)&&(mouseX>150)&&(mouseX<250)) {
    myPort.write('3');
    println("3");
    fill(255, 255, 0);
    rect(200, 300, 200, 80);
  }else{
    //myPort.write('0');
  
  }
}
void loop() {

  ONOFF();
  bright();
  if (Serial.available()) {
    val = Serial.read();
  }
}

Turn the light on and off. Vary the brightness. Then, see what needs to be done.

Does that order make sense?

Forget Processing for the moment. Add Serial.print() statements, to print what you received, and when val contains in each of the functions. Print what brightness is, in appropriate places.

Only you can see what the code actually does. You need to tell us. "It doesn't work" is useless. If it worked, I'm pretty sure you wouldn't be asking what was wrong, so it is a safe assumption that, since you ARE asking, it doesn't work, and you don't need to tell us that.

Have a look at the examples in Serial Input Basics - simple reliable ways to receive data. There is also a parse example.

...R

void loop() {
 if (Serial.available()) {
    val = Serial.read();
  }
  ONOFF();
  bright();
 Serial.print(brightness);
 Serial.println(val);

}

OK so my loop looks like this now. What happens is when I send '1' the led glows very faint. When I send '2' it turns off. When I send '3' it doesn't really change the brightness I mean physically not noticeable, and the serial print does show the brightness to be 5. If I send '3' again it doesn't increment the brightness value. I should add when I send e.g '1' from the serial monitor it shows 1s and when I send another val it shows that val until another val is sent(keeps on looping, it starts with 0).

void loop() {
 if (Serial.available()) {
    val = Serial.read();
  }
  ONOFF();
  //bright();
 Serial.print(brightness);
 Serial.println(val);

}
void ONOFF() {

  if (val == '1') {
    digitalWrite(ledPin, HIGH);
  } else if ( val =='2') {
    digitalWrite(ledPin, LOW);

  }
}

Without the bright function and then changing the analogWrite to digitalWrite the on/off function works perfectly. The led turns on full brightness.

I'm also struggling to figure out how to carry out the function like if led is on then only you could vary the brightness. Like remember the last brightness value it had before it was turned off and when it turns back on again it remains at the same brightness.

It does not make sense, to me, to call ONOFF() is val is '3'. It does not make sense to call bright() if val is not '3'.

What I would have is

void loop()
{
   if(Serial.available() > 0)
      val = Serial.read();

   if(val == '1' || val == '2')
     ONOFF();
   else if(val == '3')
     bright();
}

Then, in bright(), you can get rid of all references to val.

That might let you see what the problem is in bright().

If not, pay particular attention to the conditions under which you actually call analogWrite(). I doubt that they are what you planned.

Thanks so much for the help. I have changed the code like so, and now get the result I want or rather almost.

int ledPin = 9;
char val;
int brightness = 0;

int fadeamount = 20;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);

}

void loop() {
  if (Serial.available()) {
    val = Serial.read();
  }
  if (val == '1' || val == '2') {
    ONOFF();
    
  } else if (val == '3') {
    bright();

  }else if (val == '4'){
    brightness = brightness;
    
    
    }
  Serial.print(brightness);
  Serial.println(val);

}
void ONOFF() {

  if (val == '1') {
    brightness = 255;
    analogWrite(ledPin,brightness);
   
  } else if ( val == '2') {
    brightness = 0;
   analogWrite(ledPin,brightness);

  }
}

void bright() {

  analogWrite(ledPin, brightness);

  // change the brightness for next time through the loop:
  brightness = brightness - fadeamount;

  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeamount = +fadeamount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(1000);
  
  
  }

The only problem now is that, when changing the brightness value it doesn’t matter if the led was already on or off. I would like to make work only if the led is in the ON.

I tried

} else if (val == '3') {
    if(brightness >0){
        bright();
      }

I also tried

} else if (val == '3'&& brightness > 0) {
    bright();


  }

And also I notice that brightness value sometime goes in to the negative values too.

Finally got to the point I’m happy :D. The code actually looks a bit dodgy(very amature), any comment on improvement would be really appreciated. Also could you please tell me on how I can turn on the light from its last brightness value, but the catch is when the program runs for the first time and when I turn on the led it should be at 255 :S. Here is the final code. Once again thanks for the help

int ledPin = 9;
char val;
int brightness = 0;
int current;
int dutycycle;

float fadeamount = 25.5;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);

//dutycycle = ((brightness/255)*100);
}

void loop() {
  if (Serial.available()) {
    val = Serial.read();
  }
  current = brightness;

  analogWrite(ledPin, brightness);

  if (val == '1' || val == '2') {
    ONOFF();

  } else if (val == '3') {
    bright();


  } else if (val == '4') {
    brightness = brightness;


  }
  dutycycle = (brightness*100)/255;
  Serial.print(brightness,0);
  Serial.println(dutycycle);

}
void ONOFF() {

  if (val == '1') {
    brightness = 255;
    //analogWrite(ledPin, brightness);

  } else if ( val == '2') {
    brightness = 0;
    //analogWrite(ledPin, brightness);

  }
}

void bright() {

  
  if (brightness > 0) {
    
    brightness = brightness - fadeamount;
    if (brightness < 0) {
      brightness = 255;
    }

    
    if (brightness <= 0 || brightness >= 255) {
      fadeamount = +fadeamount;
    }
  
    delay(1000);
  }

I do not understand diddling with brightness in loop(). I do not understand writing to the output pin in loop(). All such diddling and writing should happen in ONOFF() or bright().

else if (val == '4') {
    brightness = brightness;


  }

This is completely useless. I have to wonder "what were you thinking? Or were you?".

Your bright() function is weird. First, I'm willing to bet that you can't tell the difference in the LED brightness when using analogWrite(somePin, 250) and analogWrite(somePin, 255). So, if you want steps of 1/10th the range, just live with a range of 0 to 250, and quit farting around with floats.

Second, it seems pointless to test for brightness having a negative value, when you perform that test only when brightness started with a positive value and, if that became negative due to the decrement operation, you make it 255.

Third, assigning the value of fadeamount to fadeamount is completely useless. Assigning -fadeamount to fadeamount would make sense, if you want the LED to fade down once it reached full brightness.

Applying the + operator to a negative value, were fadeamount ever to become negative, does not make the negative value positive. Applying the negative operator to a negative amount will return a positive value.

else if (val == '4') {
    brightness = brightness;


  }

The reason I put this piece of code is when the brightness function is called it keeps on looping it doesn't stop. So I added a mouseReleased function in Processing which writes a '4', so it stops at the current brightness value.

With the 255 - I wanted to display the duty cycle of the PWM. You are right with the float, it kind of messes up the displaying of the duty cycle too. So rather than displaying 50% it displays 49%.