Delay not working, please help!

Hi there,

I have some code i am working on for the Atmega328 and for some reason i just cannot get the delay to work at a certain point, i dont know if one of my libraries are conflicting with delay or if there is something silly i am missing? Here is the full code:

#include <SimpleFOC.h>
#include <Adafruit_NeoPixel.h>

const int statusLED = 4; // Define the pin for the LED

// NeoPixel settings
#define NUM_PIXELS 7  // Number of NeoPixels
#define NEOPIXEL_PIN A3 // Pin connected to the NeoPixels
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIXELS, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);

// Rotary encoder pins
const int encoderPinA = A1; // Output A
const int encoderPinB = A2; // Output B

// Rotary encoder click pin
const int encoderClickPin = A0;

// Sensor input pin
const int sensorPin = 2; // Replace with the actual pin number

// LED colors
uint32_t blueColor = strip.Color(0, 0, 255); // Blue color
uint32_t redColor = strip.Color(255, 0, 0); // Red color
int neoPixelBrightness = 50; // Adjust brightness (0 to 255)

// Variables to control the number of LEDs lit up
int blueNumLedsLit = 7; // Number of LEDs lit up for the blue page
int redNumLedsLit = 7;  // Number of LEDs lit up for the red page

int encoderState = LOW; // Initialize encoder state

// Variables to track the current page
int currentPage = 0; // 0 for blue, 1 for red

// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(7);
BLDCDriver6PWM driver = BLDCDriver6PWM(5, 6, 9, 10, 3, 11);

// Target variable
float target_velocity = 6;

// Sensor state
bool sensorTriggered = false;

void setup() {
  // Set the LED pin as an output and turn it on
  pinMode(statusLED, OUTPUT);
  digitalWrite(statusLED, HIGH);

  // NeoPixel initialization
  strip.begin();
  strip.show();  // Initialize all pixels to 'off'
  strip.setBrightness(neoPixelBrightness); // Set the NeoPixel brightness

  // Initialize to the blue page
  setNumLedsLit(blueNumLedsLit, blueColor);

  // Driver config
  driver.voltage_power_supply = 5;
  driver.voltage_limit = 5;
  driver.pwm_frequency = 32000;

  driver.init();
  motor.linkDriver(&driver);

  // Limiting motor movements
  motor.voltage_limit = 3;

  // Open loop control config
  motor.controller = MotionControlType::velocity_openloop;

  // Init motor hardware
  motor.init();

  // Add target command T
  Serial.begin(115200);
  Serial.println("Set color page");
}

void setNumLedsLit(int numLeds, uint32_t color) {
  for (int i = NUM_PIXELS - 1; i >= 0; i--) { // Reverse loop order
    if (i >= NUM_PIXELS - numLeds) {
      strip.setPixelColor(i, color);
    } else {
      strip.setPixelColor(i, strip.Color(0, 0, 0)); // Turn off the remaining pixels
    }
  }
  strip.show();
}

void swapPage() {
  // Store the current value based on the current page
  if (currentPage == 0) {
    blueNumLedsLit = blueNumLedsLit;
  } else {
    redNumLedsLit = redNumLedsLit;
  }

  // Toggle the page
  currentPage = 1 - currentPage;

  // Set the number of LEDs based on the new page
  if (currentPage == 0) {
    setNumLedsLit(blueNumLedsLit, blueColor);
  } else {
    setNumLedsLit(redNumLedsLit, redColor);
  }
}

void loop() {
  // Read the rotary encoder state
  int newEncoderState = digitalRead(encoderPinA);

  // Detect rotary encoder rotation
  if (newEncoderState != encoderState) {
if (digitalRead(encoderPinB) != newEncoderState) {
  // Clockwise rotation detected, increase the number of LEDs lit
  if (currentPage == 0) {
    blueNumLedsLit = min(NUM_PIXELS, blueNumLedsLit + 1);
    setNumLedsLit(blueNumLedsLit, blueColor);
  } else {
    redNumLedsLit = min(NUM_PIXELS, redNumLedsLit + 1);
    setNumLedsLit(redNumLedsLit, redColor);
  }
} else {
  // Counter-clockwise rotation detected, decrease the number of LEDs lit
  if (currentPage == 0) {
    blueNumLedsLit = max(0, blueNumLedsLit - 1);
    setNumLedsLit(blueNumLedsLit, blueColor);
  } else {
    redNumLedsLit = max(0, redNumLedsLit - 1);
    setNumLedsLit(redNumLedsLit, redColor);
  }
}

  }

  // Handle the encoder click button to swap pages
  int buttonState = digitalRead(encoderClickPin);
  static int lastButtonState = LOW;
  
  if (buttonState != lastButtonState) {
    if (buttonState == HIGH) {
      swapPage();
    }
    delay(50); // Debounce delay
  }

  // Read the sensor state
  sensorTriggered = digitalRead(sensorPin) == LOW;

  // Save the current button state and encoder state
  lastButtonState = buttonState;
  encoderState = newEncoderState;

  // Control the motor speed based on the blue and red LED maps respectively
  float mappedVelocity = map(blueNumLedsLit, 0, NUM_PIXELS, 0, 20); // Adjust the range as needed
  if (mappedVelocity < 1) {
    mappedVelocity = 0;
  }
  float redMappedVelocity = map(redNumLedsLit, 0, NUM_PIXELS, 0, 1000); // Adjust the range as needed
if (redMappedVelocity < 1) {
  redMappedVelocity = 0;
}
  if (sensorTriggered) {
    // Handle sensor logic (pause motor when sensor is triggered) and turn pixels red
    motor.move(0);
    setNumLedsLit(NUM_PIXELS, redColor);
  } else {
            // Add delay based on Red LEDS
    motor.move(0);       
    delay(redMappedVelocity);
    motor.move(mappedVelocity);
    // If the sensor is not triggered, set the pixels based on the current page
    if (currentPage == 0) {
      setNumLedsLit(blueNumLedsLit, blueColor);
    } else {
      setNumLedsLit(redNumLedsLit, redColor);
      // You can add code here for the red page functionality (e.g., adjusting the delay)
    }
  }
}

The part i am struggling with is here:

  if (sensorTriggered) {
    // Handle sensor logic (pause motor when sensor is triggered) and turn pixels red
    motor.move(0);
    setNumLedsLit(NUM_PIXELS, redColor);
  } else {
            // Add delay based on Red LEDS
    motor.move(0);       
    delay(redMappedVelocity);
    motor.move(mappedVelocity);
    // If the sensor is not triggered, set the pixels based on the current page
    if (currentPage == 0) {
      setNumLedsLit(blueNumLedsLit, blueColor);
    } else {
      setNumLedsLit(redNumLedsLit, redColor);
      // You can add code here for the red page functionality (e.g., adjusting the delay)
    }
  }

When the sensor is triggered the motor should stop and the lights go red, when the sensor is not triggered i need a delay before the motor starts again at the mapped speed. The delay is based on the map for the red LEDs.

I have also tried just having a number in there, or even using the other map as the delay and to no avail.

Please let me know if you need any more info and i will provide it. (Also fresh install of IDE this morning to make sure it wasnt that).

Any help is greatly appreciated!

-pobajobs

What do you see if you print sensorTriggered before testing its value ?

Does the code ever enter the else clause ?

Hey, thanks for getting back so quick!

I couldnt get serial working (i am uploading programs via programmer on the ICSP, maybe thats why) so cant check via serial if we are going into the else clause, but the motor does indeed go back to the mapped speeds and the leds go back to the correct colour so i am assuming we are entering the else clause.

I suppose i could try getting it to do something else also in case this is not working. I will try that now!

OK So i modified the code so the statusLED is off by default and make it go HIGH in the else clause and that is working fine, so i think it can only be something with the delay function?

Does the delay work if you use a fixed value instead of the variable?

Hi David,

No it does not, i have tried delay(1000); instead (as thats the upper limit of my map) and also tried a 5 second delay to no avail.

Which arduino are you using, or is this a bare atmega328? Are you using the arduino boards package?

Its a custom built PCB using an Atmega328P QFP, but as part of my testing i uploaded a blink sketch to check all was working, using statusLED as the LED (which worked as expected).

Its worth noting that all other functionality is also working on the board, just this delay that isnt.

Can use blink the status led at the end of setup using a few delays, to see if it works at that point? If not, try doing that before the begin() for the motor driver.

Interestingly, that delay works at the start of setup, but not at the end. I will try it at each bit of setup, that should let me know what is stopping it i guess?

Looks like the SimpleFOC library does some things with the timers, that might be the problem. I know the adafruit neopixel library does not affect the delay() function, although it does cause the millis() timer to lose count.

I think you are right, it has to go before here to work:

  driver.init();
  motor.linkDriver(&driver);

I guess i will have to do some research to see how to use a delay with simpleFOC or use another library. Thank you for all your help!

That library is definitely doing something with the timer, millis() is running about 32 times too fast. For the moment, you can try using this function to get the delay:


void myDelay(unsigned long ms){
  unsigned long startTime = millis();
  ms = ms * 32;
  while ((millis() - startTime) < ms) {};
}

great i will give that a try, thanks again!

Hi Again,

Sorry i am struggling a bit with your example.

How do i add this to the code, am i calling myDelay in the else function? If so how do i do that, replace delay(redMappedVelocity); with myDelay(); ?

Replace delay(redMappedVelocity) with myDelay(redMappedVelocity). You may need to change redMappedVelocity to an unsigned int instead of a float.

Thanks for the help, unfortunately this slows down the whole loop and so increments every second, i will mess around with this a bit longer and see if i can find another workaround, cheers again!

David, you are a genius! Your code here is working now:

void myDelay(unsigned long ms){
  unsigned long startTime = millis();
  ms = ms * 32;
  while ((millis() - startTime) < ms) {};
}

I realised i had the myDelay() in the wrong spot for how your code worked, so i moved it here:

  if (sensorTriggered) {
    // Handle sensor logic (pause motor when sensor is triggered) and turn pixels red
    motor.move(0);
    setNumLedsLit(NUM_PIXELS, redColor);
                // Add delay based on Red LEDS     
    myDelay(redMappedVelocity);
  }

Now it works as intended! Thanks for your help and for guiding me through!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.