Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

Thread: A Steering wheel, hall effect, and LEDs....please help me interrupt

  1. #1
    Junior Member
    Join Date
    Feb 2015
    Posts
    18

    A Steering wheel, hall effect, and LEDs....please help me interrupt

    I have a project where I am using a steering wheel that triggers a hall effect sensor as it rotates. The idea is that as you rotate the wheel, LEDs will chase up the strand. If you stop rotating, or go to slow, the LEDs will begin to extinguish. It randomly picks a color each time it goes through the cycle to chase up the strip. I would like to incorporate a "show" of sorts like a rainbow effect on the strip if the wheel has not been turned in say 1 minute or so. Then, if the wheel is turned again, the rainbow effect will extinguish, clearing the strip, and the LEDs will again chase up the strip as the wheel is turned. This is where I am stumped. I can't clear the rainbow to begin chasing the LEDS again.

    This is my first attempt at using an interrupt and I honestly don't know if I am going about this the right way with what I have done so far. The attached code works as I have described above with the exception of the rainbow "show". I know that it does not work as written. The LEDs chase up and down the strip as they should and the code works fine without the rainbow part added in. I threw in the rainbow function in the loop of the attached code so it's execution can be seen because I feel that this is part of the problem (it seems to be all about the timing). I have tried it many different ways, too many to describe in detail. I would greatly appreciate any guidance I can get in regards to getting this to work.

    Do I need to start over and rewrite what the interrupt is doing? Would it be better to poll the sensor and try and get it to work that way?

    Code:
    const int hallPin = 8;     // the number of the hall effect sensor pin
    #include <Adafruit_NeoPixel.h> // Neopixel Library
    #define Strip 11 // LED strip on pin 11
    Adafruit_NeoPixel strip = Adafruit_NeoPixel(93, Strip, NEO_GRB + NEO_KHZ800); 
    
    uint32_t color = strip.Color(0,0,0); 
    uint32_t Red = strip.Color(0,255, 0);
    uint32_t Green = strip.Color(255,0, 0);
    uint32_t ColorOff = strip.Color(0, 0, 0);
    uint32_t White = strip.Color(255,255,255);
    uint32_t Yellow = strip.Color(255,255, 0);
    uint32_t Blue = strip.Color(0, 0, 255);
    uint32_t Pink = strip.Color(51, 255, 255);
    uint32_t LtBlue = strip.Color(76, 0, 153);
    
    int j = 0;
    long randomNumber;
    unsigned long startMillis;
    unsigned long currentMillis;
    const unsigned long period =170;  //time between rotations before LEDs start turning off
    
    
    
    
    void setup() {
      
        randomSeed(analogRead(A1));
        startMillis = millis();  //initial start time
        strip.begin(); //enable LEDS
        strip.show();  //turn all LEDs off
      
        
      // initialize the hall effect sensor pin as an input:
      pinMode(hallPin, INPUT);     
       attachInterrupt(digitalPinToInterrupt(hallPin), toggle, CHANGE);
    }
    
    
    
    void loop(){
     
     
          currentMillis = millis();  //
          
          if (currentMillis - startMillis >= period){  //test whether the period has elapsed {
    
        
        // turn LED off:
         if ((j<93) && (j >-1)) { 
            strip.setPixelColor(j,ColorOff);
            strip.show();// turns LED #j off
            j=j-1;
         }
         
           startMillis = currentMillis;  
        
       }
    
      rainbow(30);  //XXX  this is where my problem lies  XXXX how to incorporate this so that after a period of time if the hall effect is not triggered,
                    // this rainbow show will display but once the hall effect is triggered again, the LED strip extinguishes and the hall effect controls the LEDS
                    //chasing up the strip
    }
    
    
    
    void toggle() {
      randomNumber = random(1,8);
      
     if (j <= 0) {
      switch (randomNumber) {// picks random color for chasing LEDs
    
        case 1:                  
          color = White;   
          break;
          
        case 2:                  
          color = Red;      
          break;
          
        case 3:                  
          color = Green;
          break;
          
        case 4:                  
          color = Yellow;
          break;
          
        case 5:                  
          color = Blue;
          break;
    
          case 6:                  
          color = LtBlue;
          break;
    
          case 7:                  
          color = Pink;
          break;
      }
    }  
     
        // turn LEDs on one at a time as wheel is turned  
         if (j < 92) {
           strip.setPixelColor(j, color); //  Sets the LED #j to color
           strip.show(); //lights the LED #j to color
           j=j+1;  //increments j to the next LED in line 
         
        }
    }
     
    
    
    
    void rainbow(uint8_t wait) {
      uint16_t i, j;
    
      for(j=0; j<256; j++) {
        for(i=0; i<strip.numPixels(); i++) {
          strip.setPixelColor(i, Wheel((i+j) & 255));
        }
        strip.show();
        delay(wait);
      }
    }
    
    
    
    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos) {
      WheelPos = 255 - WheelPos;
      if(WheelPos < 85) {
        return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
      }
      if(WheelPos < 170) {
        WheelPos -= 85;
        return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
      }
      WheelPos -= 170;
      return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
    }
    
    
    
    
    
     void colorWipe(uint32_t c) {
       for (uint16_t i = 0; i < strip.numPixels(); i++) {
          strip.setPixelColor(i, c);
          strip.show();
        }
      }

  2. #2
    Senior Member
    Join Date
    May 2017
    Posts
    180
    Try

    Code:
       if( j == -1 ) rainbow(30);

    In function rainbow, a loop of 256 times 30ms means you will be in this function for over 7 seconds, so you need a way to break out. Your local variable is also called j, so change that to k and again test the value of j to break out of the loop.

    Code:
    void rainbow(uint8_t wait) {
      uint16_t i, k;
    
      for(k=0; k<256; k++) {
        for(i=0; i<strip.numPixels(); i++) {
          strip.setPixelColor(i, Wheel((i+k) & 255));
        }
        strip.show();
        if( j > -1 ) break;
        delay(wait);
      }
    }
    Edit to add, your variable j should be declared volatile. volatile int j;

  3. #3
    Senior Member+ MichaelMeissner's Avatar
    Join Date
    Nov 2012
    Location
    Ayer Massachussetts
    Posts
    2,916
    You probably need to ban the use of the delay function (except in very specific cases), and learn to use the 'Blink without delay' programming style:


    Here is the library I wrote for this:

    Meissner_config.h:

    Code:
    // -*- arduino -*-
    // Meissner delay library
    // based on http://www.gammon.com.au/blink
    //
    // Copyright (C) 2014-2019, Michael Meissner (arduino@the-meissners.org)
    //
    // Permission is hereby granted, free of charge, to any person obtaining a copy
    // of this software and associated documentation files (the "Software"), to deal
    // in the Software without restriction, including without limitation the rights
    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    // copies of the Software, and to permit persons to whom the Software is
    // furnished to do so, subject to the following conditions:
    //
    // The above copyright notice and this permission notice shall be included in
    // all copies or substantial portions of the Software.
    //
    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    // THE SOFTWARE.
    
    #ifndef MEISSNER_DELAY_H
    #define MEISSNER_DELAY_H	1
    
    #include <stddef.h>
    #include <stdlib.h>
    #include <inttypes.h>
    
    #if defined(ARDUINO) && ARDUINO >= 100
    #include "Arduino.h"
    
    #else
    #include "WProgram.h"
    #include "WConstants.h"
    #endif
    
    class Delay {
     private:
      unsigned long	init_time;			// time when begin was called
      unsigned long	interval;			// interval in milliseconds to return true
      bool		repeat;				// whether to repeat the timer
      bool		immediate;			// immediate return true on the next call
    
     public:
      // constructor, destructor
      Delay (void) : init_time (0UL), interval (0UL), repeat (false), immediate (false) {}
      ~Delay (void) {}
    
      // register that delay_done will return true in the future
      void
      begin (unsigned long amount, bool r = false, bool imm = false)
      {
        init_time = millis ();
        interval  = amount;
        repeat    = r;
        immediate = imm;
      }
    
      // clear any potential delay
      void
      clear (void)
      {
        init_time = 0UL;
        interval  = 0UL;
        repeat    = false;
        immediate = false;
      }
    
      // Mark that the next call to delay_done will return true
      // If we are passed true, do not reset the timers.
      void
      run_immediate (bool no_reset = false)
      {
        if (!no_reset)
          {
    	init_time = 0UL;
    	interval  = 0UL;
    	repeat    = false;
          }
    
        immediate = true;
      }
    
      // register a time in the future
      void
      run_delay (unsigned long amount)
      {
        init_time = millis ();
        interval  = amount;
        repeat    = false;
        immediate = false;
      }
    
      // register a time in the future with repeat
      void
      run_delay_repeat (unsigned long amount)
      {
        init_time = millis ();
        interval  = amount;
        repeat    = true;
        immediate = false;
      }
    
      // Return true if the delay is done
      bool delay_done (void);
    };
    #endif	/* MEISSNER_DELAY_H */
    
    
    // HISTORY
    // $Log: Meissner_Delay.h,v $
    // Revision 1.10  2019/01/14 02:16:10  michaelmeissner
    // Update copyright.
    //
    // Revision 1.9  2018/03/18 21:48:03  michaelmeissner
    // Add optional argument to run_immedate to suppress reseting init_time, interval, or repeat.
    //
    // Revision 1.8  2016/04/03 22:43:31  michaelmeissner
    // Make (C) in copyright be upper case.
    //
    // Revision 1.7  2016/03/21 13:58:56  michaelmeissner
    // Update copyright year.
    //
    // Revision 1.6  2015/01/12 02:15:13  michaelmeissner
    // Move delay_done code from .h file to .cpp file.
    //
    // Revision 1.5  2015/01/11 14:46:48  michaelmeissner
    // Add run_immediate, run_delay, and run_delay_repeat.
    //
    // Revision 1.4  2015/01/10 03:13:13  michaelmeissner
    // Relicense under the MIT copyright so that we can link in neopixel patterns written by others.
    //
    // Revision 1.3  2015/01/01 23:35:08  michaelmeissner
    // Add ability to run immediately.
    //
    // Revision 1.2  2015/01/01 19:15:32  michaelmeissner
    // Update copyright year
    //
    // Revision 1.1  2014/12/31 13:54:50  michaelmeissner
    // Initial version.
    //
    Meissner_Delay.cpp:

    Code:
    // -*- arduino -*-
    // Meissner delay library
    // based on http://www.gammon.com.au/blink
    //
    // Copyright (C) 2014-2019, Michael Meissner (arduino@the-meissners.org)
    //
    // Permission is hereby granted, free of charge, to any person obtaining a copy
    // of this software and associated documentation files (the "Software"), to deal
    // in the Software without restriction, including without limitation the rights
    // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    // copies of the Software, and to permit persons to whom the Software is
    // furnished to do so, subject to the following conditions:
    //
    // The above copyright notice and this permission notice shall be included in
    // all copies or substantial portions of the Software.
    //
    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    // THE SOFTWARE.
    
    #include <stddef.h>
    #include <stdlib.h>
    #include <inttypes.h>
    
    #if defined(ARDUINO) && ARDUINO >= 100
    #include "Arduino.h"
    
    #else
    #include "WProgram.h"
    #include "WConstants.h"
    #endif
    
    #include <Meissner_Delay.h>
    
    
    
    // Return true if the delay is done
    
    bool
    Delay::delay_done (void)
    {
      bool ret = false;
    
      if (immediate)
        {
          immediate = false;
          ret = true;
        }
    
      else if (init_time != 0UL)
        {
          if ((millis () - init_time) >= interval)
    	ret = true;
        }
    
      if (ret)
        init_time = (repeat) ? millis () : 0UL;
    
      return ret;
    }
    
    
    // HISTORY
    // $Log: Meissner_Delay.cpp,v $
    // Revision 1.6  2019/01/14 02:16:25  michaelmeissner
    // Update copyright.
    //
    // Revision 1.5  2016/03/21 13:59:10  michaelmeissner
    // Update copyright year.
    //
    // Revision 1.4  2015/01/12 02:14:38  michaelmeissner
    // Move delay_done code from .h file to .cpp file.
    //
    // Revision 1.3  2015/01/10 03:13:41  michaelmeissner
    // Relicense under the MIT copyright so that we can link in neopixel patterns written by others.
    //
    // Revision 1.2  2015/01/01 19:15:50  michaelmeissner
    // Update copyright year
    //
    // Revision 1.1  2014/12/31 13:55:33  michaelmeissner
    // Initial version.
    //
    Usage would be something like:

    Code:
    const unsigned long ELAPSED_TIME_DELAY	= 1000UL;                 // once a second
    Delay timer;
    
    // ...
    
    void setup ()
    {
      // ...
      // track every second, repeating the delay, but don't fire immediately
      timer.begin (ELAPSED_TIME_DELAY, true, false);
    }
    
    // ...
    
    void loop ()
    {
      // ...
      if (timer.delay_done ()) {
        // ...
      }
    }
    Last edited by MichaelMeissner; 03-04-2019 at 03:01 PM.

  4. #4
    Junior Member
    Join Date
    Feb 2015
    Posts
    18
    rcarr,

    Thanks for your response! Your suggestions did the trick as far as getting the rainbow function to stop and allow the LED chasing to begin. It immediately made sense to me as soon as I saw it, I was at a point I probably should have stepped away and came back at it later.

    I've got more to figure out such as clearing the strip after the rainbow exits before the LED chase begins. And also putting in the idle time after the chase, prior to the rainbow. I'm going to work on those issues but just wanted to drop in and say thank you. I appreciate your time and help.

    Could I ask if you would have approached this project differently? I guess in regards to the interrupt, I feel like I have a lot of stuff going on in that routine, but with my lack of experience that is the only way I could get it to run the way I wanted. Trying to get better and would greatly appreciate any insight.

    Thanks again! I'm going to get to work on these other issues.

  5. #5
    Junior Member
    Join Date
    Feb 2015
    Posts
    18
    Mr. Meissner, thanks for your reply. I am going to look at the information you provided and by the looks of it , may be back with some questions. I consider myself a novice but am taking all opportunities I can to improve my coding. Thank you for taking the time to try and help out, it is much appreciated.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •