Motion controlled light - arduino

I'm trying to create an motion controlled light that doesn't turn on unless it's dark.
I want the light to turn on and off slowly with pwm when motion is detected. Right now my code works and does almost everything I want it to.
The problem is that I'm using the delay function to keep the light on after it reaches full brightness. And because of this if motion is detected while the light is on it doesn't reset the timer. Once the delay timer runs out and motion is detected the brightness will go down and then back up.
I would like to have the motion detector reset the timer that keeps the led on but haven't been able to get it working.
I have looked at these:
http://playground.arduino.cc/Code/AvoidDelay
https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
But because of my somewhat limited understanding of arduino code I haven't been able to get it working. I would really appreciate any help.
SOLVED
The working code below:
const byte MotionPin = 4; // Motionsensor
int LightSensorPin = 2; // Lightsensor
const byte LedPin = 11; // LED
unsigned long MotionDetectedMillis; // When motion was detected
unsigned long ledTurnedOnAt; // when led was turned on
unsigned long turnOnDelay = 50; // wait to turn on LED
unsigned long turnOffDelay = 5000; // turn off LED after this time
bool ledReady = false; // Has motion been detected
bool ledState = false; // Led on or off
int LightSensorState = 0;
int fadeAmount = 5; // How much to fade in a loop
byte brightness = 0;
void setup() {
pinMode(MotionPin, INPUT);
pinMode(LightSensorPin, INPUT);
pinMode(LedPin, OUTPUT);
digitalWrite(LedPin, LOW);
}
void loop() {
// get the time at the start of this loop()
unsigned long currentMillis = millis();
if (digitalRead(MotionPin) == HIGH && digitalRead(LightSensorPin)== HIGH)
{
MotionDetectedMillis = millis();
ledReady = true;
}
if (ledReady)
{
if ((unsigned long)(currentMillis - MotionDetectedMillis) >= turnOnDelay)
{
while (brightness < 255)
{
brightness = brightness + fadeAmount;
analogWrite(LedPin, brightness);
delay(30);
}
// setup our next "state"
ledState = true;
// save when the LED turned on
ledTurnedOnAt = currentMillis;
ledReady = false;
}
}
// see if we are watching for the time to turn off LED
if (ledState)
{
if ((unsigned long)(currentMillis - ledTurnedOnAt) >= turnOffDelay)
{
while (brightness >0)
{
brightness = brightness - fadeAmount;
analogWrite(LedPin, brightness);
delay(30);
}
ledState = false;
}
}
}

what you want is a state machine; you have to keep track in the loop of which state you currently are and what is the condition to trigger next state; because your loop will execute an action only if something happen to trigger a new state, instead of using delay() you will use a 'waiting for timeout' state (remember to keep a way to know what is the next state).
If this confuses you, imagine each state as step in the instruction manual;
turn on led 1, wait x, turn on led 1 a bit more, wait y, etc..
And because you have no more delay, before or after manage the "normal flow" of the state, you can add some special case like "if input 2 is high and current state is X or Y then set current state to Z".

So, what you want could be easily archived with an interrupt, but with a simple project like this one, you can get the same result just by removing the delay(OnTime) function.
If you want more on the interrupts of the atmega328 which is the one the Arduino UNO uses, go here

Related

Changing blinking duration of LED by using 2 pushbuttons and arduino

I'm trying to make an arduino UNO circuit that allows me to set the blinking duration of an LED with two pushbuttons, but I'm having trouble with the program. First of all, the default blinking duration is 0,5 s. And I want to program the first pushbutton to be able to extend the blinking duration by 0,1 seconds, whereas the second one is for speeding up the duration by 0,1 seconds.
So in my current code, I use if statements to check whether the two buttons are pressed or not. If the inc button is pressed, the program should increase the duration by 100 ms, whereas when dec button is pressed, the program should decrease the duration by 100 ms.
However when I run it on the arduino circuit, the duration is stuck in 600 and 500. So in every loop, the program adds 100 ms to the duration time and then decreases it again by 100, even when I do nothing to the buttons.
Here's my code so far:
const int led = 7;
const int buttonUp = 6;
const int buttonDown = 5;
int duration = 500;
void setup(){
pinMode(led, OUTPUT);
pinMode(buttonUp, INPUT);
pinMode(buttonDown, INPUT);
Serial.begin(9600);
}
void loop(){
int inc = digitalRead(buttonUp);
int dec = digitalRead(buttonDown);
if(inc == HIGH){
duration += 100;
Serial.println(duration);
}
if(dec == HIGH){
duration -= 100;
if(duration < 0){
duration = 100;
}
Serial.println(duration);
}
digitalWrite(led, HIGH);
delay(duration);
digitalWrite(led, LOW);
delay(duration);
}
the code and circuit
serial monitor
Will be extremely grateful if anyone can point out any mistakes!! Thank you!
duration is 500ms. So you basically poll your button states once every second. The time window where you can detect a button click is very short compared to the time you cannot detect it. So chances that you register a click are very little. You need to push the button for at least a second to capture the signal every time.
If you push both buttons you add and subtract 100. That's a total change of 0. What do you expect?
This can be avoided by checking your button state more frequently or by using interrupts.
Find out how to use non-blocking delays and interrupts. The internet is full of tutorials.
bool blink(unsigned int duration) {
// demo code only
// (usable only once per sketch, due to static variables)
static unsigned long last;
static bool state;
if (millis() - last >= duration) {
last = millis();
state = ! state;
}
return state;
}
This is the BlinkWithoutDelay pattern. Usage:
digitalWrite(led,blink(duration));
Button handling is trickier than a beginner thinks: often you want to detect a state change between pressed and released, and you want to ignore the bouncing of a mechanical switch happening during a state change. Or you want to repeat some action, when the button is pressed for a long time.
Easiest you do a little delay(10); after detecting a state change to pass the bouncing time. Or look for libraries doing all that button handling.
Or do such a lazy delay anyway, to slow down your fast microcontroller below button bouncing speed.
const int led = 7;
const int buttonUp = 6;
const int buttonDown = 5;
void setup(){
pinMode(led, OUTPUT);
pinMode(buttonUp, INPUT);
pinMode(buttonDown, INPUT);
Serial.begin(9600);
}
unsigned int duration = 500;
int lastbutton = 0; // 0 / -100 / +100 to detect button changes
void loop(){
bool inc = digitalRead(buttonUp);
bool dec = digitalRead(buttonDown);
delay(5); // debounce
if( (inc || dec) && lastbutton == 0){
lastbutton = (inc - dec) * 100;
duration += lastbutton;
if (duration == 0) duration = 100; // Minimum
Serial.println(duration);
}
if (lastbutton != 0 && !inc && !dec) lastbutton = 0;
digitalWrite(led, blink(duration) );
}

Arduino Interrupt won't ignore falling edge

I'm having some trouble completely debouncing a button attached to to an interrupt. The goal is to have the statement in the void loop() run exactly once when the button is pressed/released.
What usually ends up happening is one of two things
The ISR flag is set once when the button is pressed. Releasing the button does nothing, as intended.
The ISR flag is set once when the button is pressed, and once more when the button is released.
Here is the exact code I have:
#define interruptPin 2
#define DBOUNCE 100
volatile byte state = LOW; //ISR flag, triggers code in main loop
volatile unsigned long difference;
void setup() {
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), ISR_0, CHANGE);
Serial.begin(115200);
}
void loop() {
if(state){ //If we have a valid interrupt
Serial.println(difference); //Print the time since the last ISR call
state = LOW; //Reset the flag
}
}
void ISR_0() {
static unsigned long last_interrupt = 0;
if(millis()-last_interrupt > DBOUNCE && digitalRead(interruptPin)){
difference=millis()-last_interrupt;
state = HIGH;
}
last_interrupt = millis(); //note the last time the ISR was called
}
This seems to be a popular way to debounce an interrupt, but for whatever reason it isn't working for me.
I was hoping on the first falling edge of the button release that digitalRead(interruptPin) would read low, so the state flag would not be set.
Since the ISR updates the last_interrupt time, the successive bounces after the first falling edge still seem to be successfully ignored. This leads me to believe the debouncing is not the issue, but the digitalRead(interruptPin) is.
The debouncing seems to take care of all but one state. When the button is released, the code still occasionally sets the state flag to HIGH.
Here's some sample output:
3643 (after waiting ~3.6 seconds from boot, I press the button, releasing it ~1 second later)
In the same scenario as above, the output occasionally looks like this:
3643
1018
This shows me pressing the button, but also releasing the button.
I'm using an UNO R3 and a momentary tactile push button with a 1k pull-down resistor.
I'm not sure what's going wrong at this point. I hope this is simple enough that anyone can easily test this on their arduino if they feel so inclined.
You can always do debouncing in the hardware
I've encountered bounce several times with buttons and encoders, and doing debouncing in the software can get messy and lead to unreadable code or logic errors.
The easiest thing you can do is add a 0.1 uF capacitor, as illustrated:
The Arduino has hysteresis inputs, and if you use 10K as your pullup then this works for bounce that is under 1ms. This is my favorite approach.
If you wanna get more serious, a wonderful pdf exists on the internet with lots of examples and explanations: A Guide to Debouncing
You use the internal pullup resistor of the Uno, but also a pulldown resistor on the button itself. That's not correct, you can only use one of of them.
Inside the if, you want the input to be high, so use the pulldown resistor and change INPUT_PULLUP into INPUT.
(to make things clear: the resistor is connected between input pin and ground, the button between input pin and +5V)
[edit]
I think when the ISR is called, the status of interruptPin might be changed again.
Due to the slowness of digitalRead, compared to the (possible) spike.
I'm not sure if this is what you want, but the example below is working.
(I've enabled the LED for testing purposes).
One thing: keep the button pressed at least the debounce time (100msec), otherwise it won't work.
Not ideal, but that's the price you have to pay if you want instantly response on a switch.
#define interruptPin 2
#define DBOUNCE 100
volatile byte state = LOW; //ISR flag, triggers code in main loop
volatile unsigned long difference;
bool hasPrinted = false;
void setup() {
pinMode(interruptPin, INPUT);
pinMode (13, OUTPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), ISR_0, CHANGE);
Serial.begin(115200);
}
void loop() {
digitalWrite(13, state);
if (!hasPrinted) {
Serial.println(difference);
hasPrinted = true;
}
}
void ISR_0() {
static unsigned long last_interrupt = 0;
if(millis()-last_interrupt > DBOUNCE){
state = !state;
hasPrinted = false;
difference = millis()-last_interrupt;
}
last_interrupt = millis(); //note the last time the ISR was called
}
Debouncing buttons/switches in interrupts is a hassle.
I faced a (sort of) similar situation with limit switches.
The moment a limit switch is hit, something has to occur - so interrupt.
However the interrupt would fire when the limit switch was released as well which was a problem. I had my interrupt set to fire on a FALLING edge.
Anyhow, I wound up debouncing outside of the interrupt, using flags.
The code explains it but:
Switch is hit, ISR runs (does what it needs to) and sets an ISR flag.
The ISR flag stops the ISR from actually doing anything until it's cleared.
In the main loop, call a debounce function if the ISR flag is set.
the debounce function will wait until a pin/switch is stable at the required state (HIGH/LOW) for a predefined time, then clear ISR flag, allowing the ISR to do something again.
#define interruptPin 2
#define DEBOUNCE_TIME 100L
volatile bool ISR_ACTIVATED = false;
volatile bool display_int_time = false;
bool debounce_started = false;
unsigned long Isr_debounce_pin_timer;
volatile unsigned long difference;
void setup() {
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), ISR_0, CHANGE);
Serial.begin(112500);
}
void loop() {
if (display_int_time) {
Serial.println(difference); //Print the time since the last ISR call
// Right, done with interrupt stuff. clear the interrupt flag
display_int_time = false;
}
// Call debounce ISR routine in main loop
if (ISR_ACTIVATED)
ISR_ACTIVATED = !debounce(interruptPin, HIGH, Isr_debounce_pin_timer);
}
bool debounce(int debounce_pin, bool state, unsigned long &state_latch_start) {
// debounce_pin - what pin are we debouncing?
// state - should the stable state be HIGH or LOW
// state_latch_start - when we 'latched' on to a (possibly) stable state
static bool current_state;
// Read the required pin
current_state = digitalRead(debounce_pin);
// Is the pin at the required state, and we have not yet 'latched' it?
if ((!debounce_started) && (current_state == state)) {
// 'latch' this state (ie take note of when the pin went to the required level)
state_latch_start = millis();
debounce_started = true;
}
// Have we 'latched', but the pin has bounced
if (debounce_started && (current_state != state))
// unlatch
debounce_started = false;
// Have we latched, the pin is at the required level and enough time has passed (ie pin is stable)
if (debounce_started && (current_state == state) && (((unsigned long)(millis() - state_latch_start)) >= DEBOUNCE_TIME)) {
// cool. unlatch
debounce_started = false;
// report back that all is goood.
return(true);
}
// Blast. Either the pin is at the wrong level, or is still bouncing. Tell the boss to try again later!
return(false);
}
void ISR_0() {
static unsigned long last_interrupt = 0;
if((millis()-last_interrupt > DEBOUNCE_TIME) && digitalRead(interruptPin) && !ISR_ACTIVATED){
difference=millis()-last_interrupt;
//state = HIGH;
ISR_ACTIVATED = true;
display_int_time = true;
}
last_interrupt = millis(); //note the last time the ISR was called
}
*** Just a note, edited my code to incorporate the debounce time in your original ISR to ensure that the interrupt is valid. I had not read the comment regarding your noisy environment
I suppose the main issue, as was said in the comments, is because you have no actual debounce.
So, after the button is released, it continues to bounce, causing logic level on the input pin to change. If at the moment, when the pin state is latched for the digitalRead(), the state was read as high, then the whole condition will be met and state = HIGH; will be performed.
I'm not an artist, but I did my best to draw this timing diagram:
So, to avoid this, you can utilize any simple approach to debounce. Most simple one is to read again the pin state after a little timeout, greater than the maximal expected bounce time.
For example, if you're waiting for the button to be pressed and got high logical level (or low if the button is connected to GND), just wait about 5ms and read the level again. Process the button press only if the level still high (low).
And as was said in the other answers, hardware debounce also will help. You can use a higher resistor (actually you need not use external resistor: connect the button to GND and enable the internal pull-up, which is about 35kOhm). And add a capacitor about 1nF, parallel to the button.
My final solution, thanks to #darrob
#define interruptPin 2
#define DEBOUNCE_TIME 50L
//ISR Flags
volatile bool ISR_DEACTIVATED = false;
volatile bool display_int_time = false;
bool debounce_started = false;
unsigned long Isr_debounce_pin_timer;
int x = 0;
void setup() {
pinMode(interruptPin, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), ISR_0, CHANGE);
Serial.begin(112500);
}
void loop() {
//This runs every time we press the button
if (display_int_time) {
Serial.print("X "); //Print the time since the last ISR call
x++;
(x%10==0)?Serial.println(x):Serial.println();
display_int_time = false; //Done with interrupt stuff. Clear the interrupt flag
}
//Debounce for the ISR routine in main loop
if (ISR_DEACTIVATED)
//Wait until the pin settles LOW to reactivate the ISR
ISR_DEACTIVATED = !debounce(interruptPin, LOW, Isr_debounce_pin_timer);
}
//Returns TRUE if pin is stable at desired state, FALSE if bouncing or other state
bool debounce(const int debounce_pin, const bool state, unsigned long &state_latch_start) {
// debounce_pin - what pin are we debouncing?
// state - should the stable state be HIGH or LOW
// state_latch_start - when we 'latched' on to a (possibly) stable state
//If you are calling this routine to debounce multiple pins in the same loop,
// this needs to be defined outside of the function, and passed in as a separate
// parameter for each debounce item (like unsigned long &state_latch_start)
static bool current_state;
// Read the required pin
current_state = digitalRead(debounce_pin);
// Is the pin at the required state, and we have not yet 'latched' it?
if ((!debounce_started) && (current_state == state)) {
// 'latch' this state (ie take note of when the pin went to the required level)
state_latch_start = millis();
debounce_started = true;
}
// Have we 'latched', but the pin has bounced
if (debounce_started && (current_state != state))
// unlatch
debounce_started = false;
// Have we latched, the pin is at the required level and enough time has passed (ie pin is stable)
if (debounce_started && (current_state == state) && (((unsigned long)(millis() - state_latch_start)) >= DEBOUNCE_TIME)) {
// cool. unlatch
debounce_started = false;
// report back that all is goood.
return(true);
}
//Either the pin is at the wrong level, or is still bouncing. Try again later!
return(false);
}
void ISR_0() {
if(!ISR_DEACTIVATED){
ISR_DEACTIVATED = true;
display_int_time = true;
}
}

Arduino Button with LED

I have put together an Arduino circuit that turns the led's off when the button is pressed. How do I code it so when I press it once it comes on and stays on and will only turn off once its pressed again? Any help would be appreciated
My Current code is:
int ledred = 12;
int ledgreen = 8;
int BUTTON = 4;
int speakerPin = 1;
void setup() {
// initialize the digital pin as an output.
Serial.begin(9600);
pinMode(ledgreen, OUTPUT);
pinMode(ledred, OUTPUT);
pinMode(BUTTON,INPUT);
}
void loop() {
if(digitalRead(BUTTON) == HIGH){
digitalWrite(ledred,HIGH);
digitalWrite(ledgreen,HIGH);
}else
{
digitalWrite(ledred,LOW);
digitalWrite(ledgreen,LOW);
}
}
If all you want is do this, you can use one of the interrupt pins and watch for the RISING (or FALLING) event.
Something similar to this example:
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
}
void loop() {
digitalWrite(ledPin, state);
}
void blink() {
state = !state;
}
Mind that you may still need some debouncing strategy.
Also, you don't need to use an interrupt for that, but then you'd need some edge-detection algorithm. These are quite well explained in the debouncing article above. I personally prefer these, since interrupt pins in the UNO board are precious enough not to be used with humble button pressings... :o)
/*
Debounce
Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's a
minimum delay between toggles to debounce the circuit (i.e. to ignore noise).
The circuit:
- LED attached from pin 13 to ground
- pushbutton attached from pin 2 to +5V
- 10 kilohm resistor attached from pin 2 to ground
- Note: On most Arduino boards, there is already an LED on the board connected
to pin 13, so you don't need any extra components for this example.
created 21 Nov 2006
by David A. Mellis
modified 30 Aug 2011
by Limor Fried
modified 28 Dec 2012
by Mike Walters
modified 30 Aug 2016
by Arturo Guadalupi
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Debounce
*/
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// Variables will change:
int ledState = HIGH; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
// set initial LED state
digitalWrite(ledPin, ledState);
}
void loop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited long enough
// since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer than the debounce
// delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
ledState = !ledState;
}
}
}
// set the LED:
digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}

Arduino LCD Digital Input Counter

I currently have an arduino LCD and one SPDT switch connected to my board. The the common pin of the SPDT is grounded and the outer pins are each connected to a digital input. My program should increment and decrement the counter being printed to the LCD screen. I have one input working that increments the counter I do not know how to implement code for the input to decrement the counter. Code posted below.
Thank you
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5,4,3,2);
const byte buttonPin = 8;
int counter = 0; // set your counter to zero to begin with
byte buttonState; // the current reading from the input pin
byte lastButtonState = HIGH; // the previous reading from the input pin
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
void setup()
{
Serial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
lcd.begin(16, 2); // for 2x16 lcd display
}
void loop() {
// read the state of the switch into a local variable:
byte reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from HIGH to LOW), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) >= debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
buttonState = reading;
if (buttonState == LOW) {
counter ++;
Serial.println(counter);
lcd.setCursor(0, 1);
lcd.print(counter);
}
}
}
lastButtonState = reading;
}
You cannot simply connect one pole of a switch to an input pin an other to the ground. This will detect LOW but when when you are suppose to detect HIGH on the pin, it will be floating. Connect a pull-up resistor to your input pins.
Or you can use pinMode(InPin, INPUT_PULLUP);
This will pull your input pin to high internally and then you can detect the swithces and implememnt the code.

Light flashes more times than it's asked to

I am trying to get my LED to flash when the hypotenuse enters certain range. But it seems like it's passing that value of hypotenuse range more times than it should. LED Flashes for about good 30 -40 times before it goes back to being normal. Not sure how to fix this problem.
This is my processing code:
import processing.serial.*;
float r_height; // rise of the slope
float r_width; // run of the slope
float hypotnuse; // hypotenuse of the right angle
int d = 20; // diameter of the chocolate
float x ; // x of the chocolate destination
float y ; // y of the chocolate destination
int ledGlow; // how much the LED will glow
Serial myPort; // serial port object
void setup () {
size (510, 510); // size of the canvas
String portName = Serial.list()[8]; // my arduino port
myPort = new Serial(this, portName, 9600);
background (0); // color of the background
fill(204); // fill of the ellipse
ellipseMode (CORNER); //Ellipse mode
x = 0; //The placement on initial X for chocolate
y = 0; // the placement on initial Y for chocolate
ellipse (x, y, d, d); // ellipse
frameRate (30);
}
void draw () {
r_height = mouseY - y; // rise
r_width = mouseX - x; //run
hypotnuse = sqrt (( (sq(r_height)) + (sq (r_width)))); //A^2 +B^2 = C^2
ledGlow = 255 - (round (hypotnuse/2.84)); // flipping the values
myPort.write(ledGlow); // The value being sent to the Arduino
println (ledGlow);
}
This is the arduino code:
float val; // Data received from the serial port
int ledPin = 9;
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
// long steps2move = val.toInt();
}
if (val > 230) {
analogWrite (ledPin, 255) ; // I have already tried digitalWrite
delay (100);
analogWrite (ledPin, 1) ;
delay (100);
}
else if (val < 230) {
analogWrite(ledPin, val);
}
}
UPDATED ARDUINO:
float val; // Data received from the serial port
int ledPin = 9; // Set the pin to digital I/O 13
unsigned long currentTime = 0;
unsigned long pastTime = 0;
int currentState = 0;
int wait = 0;
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
// long steps2move = val.toInt();
}
if (val > 230) {
pastTime = currentTime;
currentTime = millis();
unsigned long timePassed = currentTime - pastTime;
if(timePassed >= wait)
{
switch(currentState )
{
case 0:
digitalWrite(9, HIGH);
wait = 500;
currentState = 1;
break;
case 1:
digitalWrite(9, LOW);
wait = 500;
currentState = 0;
break;
}
}
}
else if (val < 230) {
analogWrite(ledPin, val/2);
}
}
The processing code is presumably writing out to serial constantly. However, when the hypotenuse enters the range you've set, the Arduino has those delay() calls. I think that will be causing it to lag behind, so it keeps flashing while it clears the backlog of serial data that came in during the delays.
I think a better approach is to avoid using delay() at all, so the Arduino can handle the serial data as fast as possible. On each loop, it should first grab the latest serial data (if there is any). Based on that, it should figure out and store what the LED should currently be doing (i.e. whether it should be flashing, or else what brightness it should be).
After that (regardless of whether any serial data was actually received), the LED can be updated from the stored state. Remember not to use delay() for the flashing though. Instead, you could keep track of the last time it flashed on, and figure out if 100 ms has passed since then (using millis()). If so, switch it off. If another 100 ms has passed, switch it back on.
This approach decouples the flash timing from the serial data, so hopefully it should work better.

Resources