Skip to content

Commit

Permalink
Introducing hardware dimmer using analogWrite()
Browse files Browse the repository at this point in the history
  • Loading branch information
prampec committed Jan 6, 2020
1 parent 30a6c6e commit 1d8ed5b
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/Dimmer.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
* Author: Balazs Kelemen
* Contact: prampec+arduino@gmail.com
* Copyright: 2012 Balazs Kelemen
* Copyright: 2020 Balazs Kelemen
* Copying permission statement:
This file is part of SoftTimer.
Expand Down Expand Up @@ -42,7 +42,7 @@ class Dimmer : public Task
/**
* We use the SoftPwmTask for dimming.
* pwm - The predefined SoftPwm task.
* frequencyMs - Milliseconds will be passed in the OFF->ON->OFF cicle.
* frequencyMs - Milliseconds will be passed in the OFF->ON->OFF cycle.
* stepCount - Steps should be perform between a full ON-OFF state.
*/
Dimmer(SoftPwmTask* pwm, int frequencyMs, byte stepCount = DEFAULT_STEP_COUNT);
Expand Down Expand Up @@ -82,7 +82,7 @@ class Dimmer : public Task
void revertDirection();

/**
* Milliseconds will be passed in the OFF->ON->OFF cicle.
* Milliseconds will be passed in the OFF->ON->OFF cycle.
*/
void setFrequency(int frequencyMs);

Expand Down
108 changes: 108 additions & 0 deletions src/HardDimmer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* File: HardDimmer.cpp
* Description:
* SoftTimer library is a lightweight but effective event based timeshare solution for Arduino.
*
* Author: Balazs Kelemen
* Contact: prampec+arduino@gmail.com
* Copyright: 2012 Balazs Kelemen
* Copying permission statement:
This file is part of SoftTimer.
SoftTimer 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 option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "SoftTimer.h"
#include "HardDimmer.h"

HardDimmer::HardDimmer(int pwmPin, int frequencyMs) : Task(10, &(HardDimmer::step))
{
this->_pwmPin = pwmPin;
this->direction = DIMMER_DIRECTION_HIGH;
this->value = 0;
pinMode(this->_pwmPin, OUTPUT);
this->stepCount = DEFAULT_STEP_COUNT;

this->setFrequency(frequencyMs);
}


void HardDimmer::startPulsate() {
this->stopOnLimit = false;
analogWrite(this->_pwmPin, (int)this->value);
SoftTimer.add(this);
}

void HardDimmer::hold() {
SoftTimer.remove(this);
}

void HardDimmer::off() {
this->hold();
digitalWrite(this->_pwmPin, LOW);
SoftTimer.remove(this);
}

void HardDimmer::revertDirection() {
this->direction *= -1;
}

void HardDimmer::setFrequency(int frequencyMs) {
this->_stepLevel = (float)(this->_topLevel - this->_bottomLevel) / (float)this->stepCount;
this->periodMicros = (float)frequencyMs * 500.0 / (float)this->stepCount;
/*
Serial.print("Dimmer");
Serial.print(this->_pwmPin);
Serial.print(": stepLevel= ");
Serial.print(this->_stepLevel);
Serial.print(", periodMicros= ");
Serial.println(this->periodMicros);
*/
}

byte HardDimmer::getUpperLimit() {
return 255;
}


void HardDimmer::step(Task* task)
{
HardDimmer* dimmer = (HardDimmer*)task;

boolean isOnLimit = false;

dimmer->value += dimmer->direction * dimmer->_stepLevel;
if((dimmer->direction < 0) && (dimmer->value < dimmer->_bottomLevel)) {
dimmer->value = dimmer->_bottomLevel;
dimmer->direction *= -1; // -- next time go in the other direction
isOnLimit = true;
} else if((dimmer->direction > 0) && (dimmer->value > dimmer->_topLevel)) {
dimmer->value = dimmer->_topLevel;
dimmer->direction *= -1; // -- next time go in the other direction
isOnLimit = true;
}

// Serial.print("Dimmer");
// Serial.print(dimmer->_pwmPin);
// Serial.print(" = ");
// Serial.println((int)dimmer->value);
analogWrite(dimmer->_pwmPin, (int)dimmer->value);

if(isOnLimit && dimmer->stopOnLimit) {
SoftTimer.remove(dimmer);
}

}

121 changes: 121 additions & 0 deletions src/HardDimmer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/**
* File: HardDimmer.h
* Description:
* SoftTimer library is a lightweight but effective event based timeshare solution for Arduino.
*
* Author: Balazs Kelemen
* Contact: prampec+arduino@gmail.com
* Copyright: 2020 Balazs Kelemen
* Copying permission statement:
This file is part of SoftTimer.
SoftTimer 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 option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef HARDDIMMER_H
#define HARDDIMMER_H

#include "Task.h"
#include "SoftPwmTask.h"
#include "Arduino.h"

#define DIMMER_DIRECTION_HIGH 1
#define DIMMER_DIRECTION_LOW -1

#define DEFAULT_STEP_COUNT 8

/**
* HardDimmer should be a drop in replacement for Dimmer,
* expect for the constructor.
*/
class HardDimmer : public Task
{
public:
/**
* We use the SoftPwmTask for dimming.
* pwm - The predefined SoftPwm task.
* frequencyMs - Milliseconds will be passed in the OFF->ON->OFF cycle.
*/
HardDimmer(int pwmPin, int frequencyMs);

/**
* Start an unlimited pulsation from the current value on, in the current direction.
*/
void startPulsate();

/**
* Hold current PWM value on the output.
*/
void hold();

/**
* Stop PWM, and set output to LOW.
*/
void off();

/**
* Make the dimming to change direction.
*/
void revertDirection();

/**
* Milliseconds will be passed in the OFF->ON->OFF cycle.
*/
void setFrequency(int frequencyMs);

/**
* Get the upper level of the pwm.
*/
byte getUpperLimit();

void setBottomLevel(byte value = 0)
{
this->_bottomLevel = value;
}
void setTopLevel(byte value = 255)
{
this->_topLevel = value;
}

/**
* Current dim level PWM value. Note that the value should be between bottomLevel and topLevel.
*/
float value;

/**
* Stop if zero, or pwm->upperLimit is reached.
*/
boolean stopOnLimit;

/**
* Can be one of DIMMER_DIRECTION_HIGH or DIMMER_DIRECTION_LOW.
*/
char direction;

/**
* Level-arranging steps should be performed within each full OFF->ON change. Will be applied if setFrequency() is called.
*/
byte stepCount;

private:
int _pwmPin;
float _stepLevel;
static void step(Task* me);
float _topLevel = 255;
float _bottomLevel = 0;
};

#endif

0 comments on commit 1d8ed5b

Please sign in to comment.