I am trying to control an LED strip to fade on, stay on for "pictureTime" milliseconds, then fade off, using a MOSFET as a relay.
This action gets triggered by a sensor value. I am using an Adafruit Time of Flight sensor to read this value, and this portion of the function works perfectly. When the distance is close enough, the trigger starts as expected and the lights fade on. The fade-on to stay-on transition is smooth. BUT when the fade out section happens, there is a blip in the LEDs where they go off for just a "blink of an eye's" worth of time before continuing to fading out smoothly. I wish to get rid of this blip. Not sure why this behavior is happening, so this is why I am here.
my code is here, but please focus on the void loop() section // making the LEDs behave smoothly on the fade-out. The setup is mostly for the ToF sensor.
#include "Adafruit_VL53L1X.h"
#define IRQ_PIN 2
#define XSHUT_PIN 3
Adafruit_VL53L1X vl53 = Adafruit_VL53L1X(XSHUT_PIN, IRQ_PIN);
int pictureTime = 5000;
int brightness = 0;
int fadeAmount = 3;
int light = 7;
void setup() {
pinMode(light, OUTPUT);
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println(F("Adafruit VL53L1X sensor demo"));
Wire.begin();
if (! vl53.begin(0x29, &Wire)) {
Serial.print(F("Error on init of VL sensor: "));
Serial.println(vl53.vl_status);
while (1) delay(10);
}
Serial.println(F("VL53L1X sensor OK!"));
Serial.print(F("Sensor ID: 0x"));
Serial.println(vl53.sensorID(), HEX);
if (! vl53.startRanging()) {
Serial.print(F("Couldn't start ranging: "));
Serial.println(vl53.vl_status);
while (1) delay(10);
}
Serial.println(F("Ranging started"));
// Valid timing budgets: 15, 20, 33, 50, 100, 200 and 500ms!
vl53.setTimingBudget(50);
Serial.print(F("Timing budget (ms): "));
Serial.println(vl53.getTimingBudget());
}
void loop() {
int16_t distance;
analogWrite(light, brightness);
if (vl53.dataReady()) {
// new measurement for the taking!
distance = vl53.distance();
if (distance == -1) {
// something went wrong!
Serial.print(F("Couldn't get distance: "));
Serial.println(vl53.vl_status);
return;
}
if (distance < 500){ //TRIGGERED MOMENT
Serial.print(F("Distance: "));
Serial.print(distance);
Serial.print (" mm");
Serial.println(" IM IN!!");
brightness = 0;
while (brightness < 256) { ///FADE ON
delay(30);
brightness = brightness + fadeAmount;
analogWrite(light, brightness);
}
analogWrite(light, 255); //HOLD
delay(pictureTime);
while (brightness > 0){ ///FADE OFF
analogWrite(light, brightness);
brightness = brightness - (fadeAmount*.3);
delay(15);
}
}
brightness = 0;
Serial.print(F("Distance: "));
Serial.print(distance);
Serial.println(" mm");
// data is read out, time for another reading!
vl53.clearInterrupt();
}
}
At the end of this loop, brightness will be 258. Since the maximum value that analogWrite() allows is 255, it will treat 258 the same as (258-256) = 2. So for a very, very short time, less than the blink of an eye, the brightness will be very low. But this won't be noticeable because...
this code immediately sets the led to max brightness.
But then ...
this code will set it back to 2 again and then there is a short delay, so the effect does last for the blink of an eye.
Thanks @PaulRB ! This was the exact answer I was looking for. I see two solutions, one; change 255 to 258.
two; set brightness equal to 255 again right before entering the fade off loop.
I wouldn't choose either of them. They won't fix the fact that your code is "blocking code", code which uses delay() for timing. This prevents the Arduino from doing anything else at the "same time", such as checking for button presses or other events. You may not realise the importance of that yet.
@PaulRB this is all true, I actually did want my arduino to do nothing and not check for anything else while on delay(), but maybe this is clogging something? Also, I had to run some long wires between the sensor, arduino (mega) and mosfet in order to place things in my setup appropriately, and after a few successful runs, the lights do not turn on anymore and the serial monitor stops communicating. After testing, what I have discovered is that after a power cycle the system works as expected for a couple more iterations, then stops again. Sometimes I have to reset everything. Very inconsistent function. Why? And how do I fix this?
Use the watch dog timer with interrupt. Just set up the pre-scaler values and have it service the interrupt. You can use that to increment a counter then after so many counts increment or decrement the fade amount.
That way you can carry on and do other things or just leave it to do its stuff.
There was some guy on the forum only a couple of days ago saying he had a logic level MOSFET, but when he revealed the model number, guess what?
But if connecting the MOSFET gate to 5V causes no flickering or other problems then I guess you are right.
Those tests point back to a problem with the sketch, I think, not the PSU, MOSFET or wiring. What does serial monitor show just before the problems begin?
One thing I don't personally like about your code on post #11 is the use of return; in loop(). I think that's poor code structure that could lead to coding errors. For example:
That vl53.clearInterrupt(); never gets called because of the return; .
Double checked the mosfet, that seemed solid! Moving to shielded wire helped a lot, also that return removal helped a lot as well, seems to be running smoothly now! Thanks