#include "AiEsp32RotaryEncoder.h"
#include "Arduino.h"
#include "LedController.hpp"
// Define the MAX7219 connection pins
#define DIN 15
#define CS 2
#define CLK 4
// Define the rotary encoder pins
#define ROTARY_ENCODER_A_PIN 19
#define ROTARY_ENCODER_B_PIN 18
#define ROTARY_ENCODER_BUTTON_PIN 5
#define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
#define ROTARY_ENCODER_STEPS 4
AiEsp32RotaryEncoder rotaryEncoder = AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, ROTARY_ENCODER_VCC_PIN, ROTARY_ENCODER_STEPS);
// Create a new LedController object
LedController<1, 1> lc;
unsigned long increaseTimer = 0;
unsigned long counter = 0;
// Define the frequency value (in kHz)
float frequency = 99.99;
int changeprecision=0;
void rotary_onButtonClick()
{
static unsigned long lastTimePressed = 0;
//ignore multiple press in that time milliseconds
if (millis() - lastTimePressed < 500)
{
changeprecision= changeprecision+1;
if (changeprecision>=4) changeprecision==0;
return;
}
lastTimePressed = millis();
Serial.print("button pressed ");
Serial.print(millis());
Serial.println(" milliseconds after restart");
}
void rotary_loop()
{
//dont print anything unless value changed
if (rotaryEncoder.encoderChanged())
{
if (changeprecision <=1 ){
frequency = rotaryEncoder.readEncoder();
} if ( changeprecision == 2){
frequency = frequency + ((rotaryEncoder.readEncoder()-frequency) / 10) ;
}
// Clamp the frequency value between 0 and 99.99
if (frequency > 99.99) {
//frequency = 0;
} else if (frequency < 0) {
frequency = 99.99;
}
Serial.print("Value: ");
Serial.println(rotaryEncoder.readEncoder());
}
if (rotaryEncoder.isEncoderButtonClicked())
{
rotary_onButtonClick();
}
}
void IRAM_ATTR readEncoderISR()
{
rotaryEncoder.readEncoder_ISR();
}
void setup()
{
Serial.begin(115200);
rotaryEncoder.begin();
rotaryEncoder.setup(readEncoderISR);
//set boundaries and if values should cycle or not
//in this example we will set possible values between 0 and 1000;
bool circleValues = false;
rotaryEncoder.setBoundaries(0, 1000, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
/*Rotary acceleration introduced 25.2.2021.
* in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
* without accelerateion you need long time to get to that number
* Using acceleration, faster you turn, faster will the value raise.
* For fine tuning slow down.
*/
//rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
rotaryEncoder.setAcceleration(100); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
lc=LedController<1,1>(DIN,CLK,CS);
// lc.shutdown(0, false); //Activate display
lc.setIntensity( 3); //low brightness
lc.clearMatrix(); //clear
for (int i = 0; i < 10; i++)
{
floatToDecimalNumber();
delay(3000);
}
}
const int DEBOUNCE_TIME = 50; // Debounce time in milliseconds
unsigned long lastDebounceTime = 0; // Last time the encoder was debounced
void loop(){
//in loop call your custom function which will process rotary encoder values
rotary_loop();
floatToDecimalNumber();
}
//float frequency = 0.00;
void floatToDecimalNumber()
{
//We need a floating point number
//Generate a random float with 2 digits
// frequency = random(99999) + (random(99) / 1000.0);
Serial.print("Random float: ");
Serial.println(frequency);
//Casting the float into long will cut off the decimal digits, we keep the integers (e.g.: 12587.74 becomes 12587)
long integerpart = (long) frequency;
Serial.print("Integer part: ");
Serial.println(integerpart);
//multiplying the float by 100, casting it to long, then taking the modulo 100 will give us 2 digits (10^2 = 100) after the decimal point
//long decimalpart = ((long)(frequency * 100.00) % 100);
long decimalpart = (long)(100 * (frequency - integerpart)); //e.g.: 100 * (12587.74-12587) = 100 * 0.74 = 74
//Possible improvement: Sometimes the decimals of the floating point number are slightly different
//For example, this is the floating point number: 87073.37, but the extracted decimal part is 36.
//This can happen because I do not round the number. So 87073.37 can be 87073.3650212125... which is 87073.37 when it is rounded
//But when I do the above operation, the two digits extracted are 3 and 6. For "more accuracy", float must be rounded first.
Serial.print("Decimal part: ");
Serial.println(decimalpart);
//At this point we know the following things:
//1.) we manually set the number of decimal digits to 2. it will be two digits whatever we do.
//2.) we know the value of the integer part, but we don't (yet) explicitly know the number of digits (number can be 1245.4 but also 1.29...etc.)
//Let's count the integer part digits
int integerDigits = 0; //number of digits in the integer part
long tmp_integerpart = integerpart; //temporary variable, copy of the original integer parts
long tmp2_integerpart = integerpart; //temporary variable 2, copy of the original integer parts
while (tmp_integerpart)
{
tmp_integerpart = tmp_integerpart / 10;
integerDigits++;
//What happens inside:
//Original float number: 16807.34, integer part: 16807 -(/10)-> 1680 -(/10)-> 168 -(/10)-> 16 -(/10)-> 1
}
int digitsPosition = integerDigits + 2; //+2 comes from the 2 decimal digits
Serial.print("Number of digits: "); //Total number of digits of the processed float
Serial.println(digitsPosition);
//now we know the total number of digits - keep in mind that the max integer digits allowed is 6!
//The next step is to fill up an array that stores all the digits.
//The array is filled up in a same was as the display: decimal numbers will be 0th and 1st elements, we do this first
long digits[digitsPosition]; //array with the needed size
int decimalDigits = 2; //manually created number of digits
long tmp_decimalpart = decimalpart; //copy the original decimal part value
//I do this part "manually"
digits[integerDigits + 1] = tmp_decimalpart % 10; //2nd decimal digit (e.g.: 634.23 -> 3)
tmp_decimalpart /= 10;
digits[integerDigits] = tmp_decimalpart % 10; //1st decimal digit (e.g.: 634.23 -> 2)
// [4 3 2 1 0]
//Example: 634.23 -> Int: 634, Dec: 23. Digits: 5. Int.Digits: 3. [3 2 4 3 6] <----- reading direction
Serial.print("Dec 0: ");
Serial.println(digits[integerDigits + 1]); //2nd decimal digit
Serial.print("Dec 1: ");
Serial.println(digits[integerDigits]); //1st decimal digit
//We got the decimals right, now we move on to the integer digits
Serial.print("Integer digits: "); //Number of integer digits
Serial.println(integerDigits);
while (integerDigits--)
{
digits[integerDigits] = tmp2_integerpart % 10;
tmp2_integerpart /= 10;
//Same exercise as above with the decimal part, but I put it in a loop because we have more digits
}
Serial.println("----------------------");
//This is just to check the contents of the array and if the number is stored properly
for (int i = 0; i < digitsPosition; i++)
{
Serial.print(i);
Serial.print(": ");
Serial.println(digits
);
}
//Finally, we print the digits on the display
lc.clearMatrix();
for (int j = 0; j < digitsPosition; j++)
{
if (j == 2)
{
lc.setDigit(0, j, digits[digitsPosition - j - 1], true); //we know that we have to put a decimal point here (last argument is "true")
//0: address, j: position, value, decimal point.
//Additional -1 is because we count the digits as first, second, third...etc, but the array starts from 0.
}
else
{
lc.setDigit(0, j, digits[digitsPosition - j - 1], false);
//Example: number is 634.23
//j = 0: digits[5-0-1] = digits[4] -> 0th element of the display gets the last element of the array which is the second decimal: 3 (hundreths)
//j = 1: digits[5-1-1] = digits[3] -> 1th element of the display gets the last-1 element of the array which is the first decimal: 2 (tenths)
//j = 2: digits[5-2-1] = digits[2] -> 2nd element of the display gets the last-2 element of the array which is the first integer: 4 (ones)
//j = 3: digits[5-3-1] = digits[1] -> 3rd element of the display gets the last-3 element of the array which is the second integer: 3 (tens)
//j = 4: digits[5-4-1] = digits[0] -> 4th element of the display gets the last-4 element of the array which is the third integer: 6 (hundreds)
}
}
}
void countUp()
{
int numberOfDigits = 0;
unsigned long tmp_countUpNumber = 0; //variable for the counter
unsigned long tmp2_countUpNumber = 0; //copy of the above
tmp_countUpNumber = counter * 10; //counter (+10 every ~10 ms)
tmp2_countUpNumber = tmp_countUpNumber; //copy of the above
while (tmp_countUpNumber) //counting the digits
{
tmp_countUpNumber /= 10;
numberOfDigits++;
//same exercise as in the float processing part
}
int tmp_numberOfDigits = 0; //copy of the numberOfDigits
int displayDigits[numberOfDigits]; //array to store the individual digits
tmp_numberOfDigits = numberOfDigits; //copy the number of digits
while (numberOfDigits--) //filling up the array
{
displayDigits[numberOfDigits] = tmp2_countUpNumber % 10;
tmp2_countUpNumber /= 10;
//same exercise as in the float processing part
}
lc.clearMatrix();
for (int i = 0; i < tmp_numberOfDigits; i++)
{
lc.setDigit(0, i, displayDigits[tmp_numberOfDigits - i - 1], false);
//same exercise as in the float processing part
}
}
now it works from 0 to 1000 with rotary encoder… it has acceleation in the encoder making it wonderfull for a good range… now implementing the increments for higher precision manual tuning
i thought of making it possible to change the parameters without wifi… just saving on epprom
the idea is to use one long 5s click to set the config mode than pressing the button change the function to change the param with the encoder
A phase
B band width
C center frequency
D Wave form
E Gate duty cycle
F Frequency manual change
G Gate Frequency
H
I current sensor
J magnetic field
K don’t display
L magnetic field
M and N don’t display well
O lambda display
P pressure limit
Q don’t display well I guess
R Rpm control or indication
S sweep frequency select
T Air time
U exhaust time
V = U and W and X = H don’t display well I guess
Y injector min time
Y2 injector max time
Z hydrogen /oxygen time
PA gas processor phase
Pb band
Pc center f
Pd wave f
Pe gate duty
Pf freq
Pg gate freq
Pi current sensor
Also the wave form can be selected… maybe also a quick start stop would be nice too…
This is how I live since 2006 where I started this
https://youtube.com/shorts/mDf5PrBoEug