// start of macros dbg and dbgi
#define dbg(myFixedText, variableName) \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope
#define dbgi(myFixedText, variableName,timeInterval) \
do { \
static unsigned long intervalStartTime; \
if ( millis() - intervalStartTime >= timeInterval ){ \
intervalStartTime = millis(); \
Serial.print( F(#myFixedText " " #variableName"=") ); \
Serial.println(variableName); \
} \
} while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a
// Serial.print is executed
// end of macros dbg and dbgi
#include "Arduino.h"
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__));
Serial.print( F(" compiled ") );
Serial.print(F(__DATE__));
Serial.print( F(" ") );
Serial.println(F(__TIME__));
}
boolean TimePeriodIsOver (unsigned long &periodStartTime, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - periodStartTime >= TimePeriod )
{
periodStartTime = currentMillis; // set new expireTime
return true; // more time than TimePeriod) has elapsed since last time if-condition was true
}
else return false; // not expired
}
unsigned long MyTestTimer = 0; // variables MUST be of type unsigned long
const byte OnBoard_LED = 13;
unsigned long buttonReleaseTimer;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
#include "NewEncoder.h"
const byte EncChA_Pin = 2;
const byte EncChB_Pin = 3;
const int minVal = -20;
const int maxVal = 20;
const int startVal = 2;
// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US¤cycode=USD
NewEncoder myEncoderObject(EncChA_Pin, EncChB_Pin, minVal, maxVal, startVal, FULL_PULSE);
// myEncState is a variable of type EncoderState
// EncoderState is a structured variable that has two "simple" variables
// .currentValue which is type int16_t
// (16 bit signed integer valuerange -36767 to 36767)
// currentValue counts up / down with each pulse created through rotating the encoder
// and
// .currentClick which is of type "EncoderClick"
// the variable type "EncoderClick" can have just 3 values
// NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
NewEncoder::EncoderState myEncState;
//NewEncoder::EncoderState myDummyState;
int16_t currentValue;
int16_t prevEncoderValue;
int16_t tempMin = 10;
int16_t tempMax = 30;
int16_t actualTemperature;
int16_t storedTemperature;
int16_t rpmMin = 40;
int16_t rpmMax = 50;
int16_t actualRpm;
int16_t storedRpm;
const byte EncBtnPin = 4;
const byte TEMPERATURE_MODE = 0;
const byte RPM_MODE = 1;
byte myMode = TEMPERATURE_MODE;
byte myLastMode = myMode;
void setup() {
pinMode(EncBtnPin, INPUT_PULLUP);
Serial.begin(115200);
PrintFileNameDateTime();
Serial.println("Starting");
if (!myEncoderObject.begin()) {
Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
while (1) {
yield();
}
} else {
// store values of currentValue and EncoderClick into variable myEncState
myEncoderObject.getState(myEncState);
Serial.print("Encoder Successfully Started at value = ");
prevEncoderValue = myEncState.currentValue;
Serial.println(prevEncoderValue);
}
}
void pushBtnTogglesMode(byte p_IO_Pin, byte &p_mode) {
static int buttonState; // the current reading from the input pin
static 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.
static unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
// read the state of the switch into a local variable:
int reading = digitalRead(p_IO_Pin);
// 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) {
if (p_mode == 1) {
p_mode = 0;
}
else {
p_mode = 1;
}
}
}
}
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}
void CheckForModeChange() {
if (myMode != myLastMode) {
myLastMode = myMode;
Serial.print("mode changed new mode ");
if (myMode == TEMPERATURE_MODE) {
Serial.println("Temperature");
}
if (myMode == RPM_MODE) {
Serial.println("rpm");
}
if (myMode == RPM_MODE) {
storedTemperature = actualTemperature; // store actual temperature for later RE-storing
myEncoderObject.newSettings(rpmMin, rpmMax, 22, myEncState); // setup encoder for rpm-mode
//myEncoderObject.getAndSet(storedRpm,myDummyState,myEncState);
actualRpm = myEncState.currentValue;
dbg("RPM-Mode active", actualRpm);
Serial.println();
}
if (myMode == TEMPERATURE_MODE) {
storedRpm = actualRpm; // store actual RPM for later RE-storing
actualTemperature = storedTemperature; // restore temperature as we are changing to temperature-mode
myEncoderObject.newSettings(tempMin, tempMax, actualTemperature, myEncState); // setup encoder for temperature-mode
//myEncoderObject.getAndSet(storedTemperature,myDummyState,myEncState);
actualTemperature = myEncState.currentValue;
dbg("TemperatureMode active", actualTemperature);
Serial.println();
}
}
}
void PrintEncoderValue() {
// very important ! this stores actual values into variable myEncState
if (myEncoderObject.getState(myEncState)) { //<<<== very important
Serial.print("Encoder: ");
if (myMode == TEMPERATURE_MODE) {
Serial.print("Temperature=");
}
if (myMode == RPM_MODE) {
Serial.print("rpm=");
}
currentValue = myEncState.currentValue;
// if currentValue has REALLY changed print new currentValue
if (currentValue != prevEncoderValue) {
Serial.println(currentValue);
prevEncoderValue = currentValue;
// if currentValue stayed the same because the number is at upper/lower limit
// check if encoder was rotated by using the UpClick / DownClick-values
} else
switch (myEncState.currentClick) {
case NewEncoder::UpClick:
Serial.println("at upper limit.");
break;
case NewEncoder::DownClick:
Serial.println("at lower limit.");
break;
default:
break;
}
}
}
void loop() {
pushBtnTogglesMode(EncBtnPin, myMode); // check if button was pressed if Yes change value of variable myMode
CheckForModeChange();
PrintEncoderValue();
// update value according to active mode
if (myMode == TEMPERATURE_MODE) {
actualTemperature = myEncState.currentValue;
}
else {
actualRpm = myEncState.currentValue;
}
}