#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