Skip to content

Commit

Permalink
Changed SetFade() to SetFadeRate()
Browse files Browse the repository at this point in the history
Changed function from boolean to accepting a fade rate in 1/2
milliseconds. Each value equates to 500 microseconds delay.
  • Loading branch information
Arnd authored and Arnd committed Dec 18, 2016
1 parent 9637f37 commit e939263
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 17 deletions.
43 changes: 29 additions & 14 deletions RotaryEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@ EncoderClass::EncoderClass(const uint8_t LeftPin, const uint8_t RightPin, //
attachInterrupt(digitalPinToInterrupt(LeftPin),RotateISR,CHANGE); // Attach static internal function //
attachInterrupt(digitalPinToInterrupt(RightPin),RotateISR,CHANGE); // Attach static internal function //
attachInterrupt(digitalPinToInterrupt(PushbuttonPin),PushButtonISR,RISING); // Attach static internal function //
if (RedPin==255&&GreenPin==255&&BluePin==255) SetFade(false); // If no LEDs, turn off fader //
else SetFade(true); // turn on fader and interrupt //
if (RedPin==255&&GreenPin==255&&BluePin==255) SetFadeRate(0); // If no LEDs, turn off fader //
else SetFadeRate(1); // turn on fader to max speed //
} // of class constructor // //
/*******************************************************************************************************************
** Define the 5 ISR (Interrupt Service Routines). These definitions are done as static functions which can be set **
** directly as part of the Arduino IDE inside a class definition. They, in turn, redirect the interrupt to a class**
** member function where the actual interrupt is handled **
*******************************************************************************************************************/
ISR(TIMER0_COMPA_vect) {EncoderClass::TimerISR();} // Call the ISR every millisecond //
ISR(TIMER0_COMPB_vect) {EncoderClass::TimerISR();} // Call the ISR every millisecond //
static void EncoderClass::PushButtonISR(){ClassPtr->PushButtonHandler();} // Redirect to real handler function//
static void EncoderClass::RotateISR() {ClassPtr->RotateHandler();} // Redirect to real handler function//
static void EncoderClass::TimerISR() {ClassPtr->TimerHandler();} // Redirect to real handler function//
Expand All @@ -42,7 +48,7 @@ static void EncoderClass::TimerISR() {ClassPtr->TimerHandler();} //
** RGB LEDs of the device. It is also the only place where the actual PWM values for RGB are set. **
*******************************************************************************************************************/
void EncoderClass::TimerHandler() { // //
if (_LEDChanged||!(_RedActual==255&&_GreenActual==255&&_BlueActual==255)){ // only check if we need to //
if (_LEDChanged || !(_RedActual==255&&_GreenActual==255&&_BlueActual==255)){// Only check if LEDs aren't off //
_LEDChanged = false; // Reset the value //
if (_RedActual!=_RedTarget) { // adjust accordingly //
if(_RedActual<_RedTarget) _RedActual++; else _RedActual--; // //
Expand All @@ -53,7 +59,7 @@ void EncoderClass::TimerHandler() { //
if (_BlueActual!=_BlueTarget) { // //
if(_BlueTarget<_BlueTarget) _BlueActual++; else _BlueActual--; // //
} // of if-then actual and target don't match // //
if (_Fade) { // If we are fading colors, then //
if (_FadeMillis!=0 && millis()%_FadeMillis==0 ) { // If we are fading colors, then //
if (_RedTarget !=255&&_RedActual==_RedTarget) _RedTarget++; // Fade Red if max has been reached //
if (_GreenTarget!=255&&_GreenActual==_GreenTarget) _GreenTarget++; // Fade Green " " //
if (_BlueTarget !=255&&_BlueActual==_BlueTarget) _BlueTarget++; // Fade Blue " " //
Expand Down Expand Up @@ -173,22 +179,31 @@ void EncoderClass::SetEncoderValue(const int16_t NewValue = 0) { //
_EncoderValue = NewValue; // Set the new value //
} // of method SetEncoderValue() // //
/*******************************************************************************************************************
** function SetFade() is called to turn the fade functionality on or off. The fade is done by turning on the **
** Timer0 interrupt. Timer 0 is used by the millis() function and is an 8-bit register with a clock divisor of 64 **
** which triggers it to overflow at 976.5625Hz. The millis() function uses the TIMER0_OVF_vect so we can't use **
** that, so we set the TIMER0_COMPA_vect set to 0x01 which trigger when the value is equal to 1. This gives us a **
** pretty quick trigger rate which suffices to light and fade the LED lights **
** function SetFadeRate() is called to turn the fade functionality on or off and adjust the rate at which the fade**
** occurs. The fade is done by accessing the Timer0 interrupt, which is used by the millis() function and is an **
** 8-bit register with a clock divisor of 64 which triggers it to overflow at a rate of 976.5625Hz, or roughly **
** every millisecond. We set the TIMER0_COMPA_vect to 0x01 which triggers when the value is equal to 64. This **
** then gives us an identical trigger speed but different trigger point to the millis() function which triggers **
** when the Timer0 overflows. The same setup is done for the TIMER0_COMPB_vect but that is set to trigger halfway **
** along the full range of 255 at 192, thus giving an interrupt rate of 2 times per milli second. The FadeSpeed **
** equates to how many milliseconds ther are between incremental fades, the fastest is 1 which is every 1/2 milli-**
** second, 2 is every millisecond, etc. Each time the trigger is reached all of the LED values which are not "off"**
** are dimmed by 1/255 of the total value. A setting of 10 would fade the LEDs from full on to OFF 1/255 of their **
** brightness in 1.28 seconds **
*******************************************************************************************************************/
void EncoderClass::SetFade(const bool FadeState) { // //
_Fade = FadeState; // Set the private variable to value//
if (FadeState) { // If turning on, set the ISR //
void EncoderClass::SetFadeRate(const uint8_t FadeSpeed) { // //
_FadeMillis = FadeSpeed; // Set the private variable to value//
if (FadeSpeed) { // If turning on, set the ISR //
cli(); // Disable interrupts //
OCR0A = 0x01; // Comparison register setup to 1 //
OCR0A = 0x40; // Comparison register A to 64 //
OCR0B = 0xC0; // Comparison register B to 192 //
TIMSK0 |= _BV(OCIE0A); // TIMER0_COMPA trigger on 0x01 //
TIMSK0 |= _BV(OCIE0B); // TIMER0_COMPB trigger on 0x80 //
sei(); // Enable interrupts //
} else { // If turning off, unset the ISR //
cli(); // Disable interrupts //
TIMSK0 &= ~_BV(OCIE0A); // TIMER0_COMPA trigger off //
TIMSK0 &= ~_BV(OCIE0B); // TIMER0_COMPB trigger off //
sei(); // Enable interrupts //
} // of if-then-else we need to turn fading on or off // //
} // of method SetColor // //
} // of method SetFadeRate // //
16 changes: 13 additions & 3 deletions RotaryEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,16 @@
** voltage for the red is 2.0V and the green/blue LEDs have 3.3V and with a 25mA current that equates to resistors**
** at 120 and 68 Ohms respectively. **
** **
** The pushbutton has a pull-down resistor of 4.7KOhm to reduce bounce **
** The pushbutton should have a pull-down resistor of 4.7KOhm to reduce bounce. The sample breadboard schematic **
** used for the examples for this library can be located at in Github at the following address: **
** https://github.com/SV-Zanshin/RotaryEncoder/blob/master/Images/RotaryEncoder.png **
** **
** Although programming for the Arduino and in c/c++ is new to me, I'm a professional programmer and have learned,**
** over the years, that it is much easier to ignore superfluous comments than it is to decipher non-existent ones;**
** so both my comments and variable names tend to be verbose. The code is written to fit in the first 80 spaces **
** and the comments start after that and go to column 117 - allowing the code to be printed in A4 landscape mode. **
** There are several parts of code which can be somewhat optimized, but in order to make the c++ code more under- **
** standable by non-programmers some performance has been sacrificed for legibility and maintainability. **
** **
** This program is free software: you can redistribute it and/or modify it under the terms of the GNU General **
** Public License as published by the Free Software Foundation, either version 3 of the License, or (at your **
Expand All @@ -37,6 +46,7 @@
** **
** Vers. Date Developer Comments **
** ====== ========== =================== ======================================================================== **
** 1.0.2 2016-12-18 [email protected] Changed SetFade() to SetFadeRate() function to alter the fade speed **
** 1.0.1 2016-12-14 [email protected] Fixed error on condition to turn off LED lights. **
** 1.0.0 2016-12-14 [email protected] Allowed defaults for LEDs on class constructer **
** 1.0.b3 2016-12-13 [email protected] Made fading start only after the maximum setting was reached **
Expand All @@ -57,7 +67,7 @@
static void TimerISR(); // Interim ISR calls real handler //
void SetEncoderValue(const int16_t NewValue = 0); // Set the encoder value //
void SetLEDState(const bool Status); // Turns encoder LEDs on or off //
void SetFade(const bool FadeState); // Sets the fader state //
void SetFadeRate(uint8_t FadeMillis); // Sets the fader state and speed //
void SetColor(const uint8_t R, const uint8_t G, const uint8_t B);// Sets the LED colors //
void SetPushButtonColor(const uint8_t R, const uint8_t G, // Sets the RGB values displayed //
const uint8_t B); // when the pushbutton is pressed //
Expand All @@ -78,7 +88,7 @@
uint8_t _RedPin; // //
uint8_t _GreenPin; // //
uint8_t _BluePin; // //
bool _Fade = true; // Default to fade to dark //
uint8_t _FadeMillis = 1; // 1=fast, 0=Off //
bool _LEDOn = true; // Default to display LED lights //
volatile bool _LEDChanged = true; // Set when rotate or click changes //
volatile uint8_t _ButtonPresses = 0; // The current number of pushes //
Expand Down

0 comments on commit e939263

Please sign in to comment.