@Nick & cattledog: dear guys, thanks to your precious information I've reached my goal. Following, there is the code, comprehensive of the digital encoder's ( KY-040 Rotary Encoder Module) control, to manage the signals I was looking for.
/*
* Electronic DPDT
* by Fabrizio Ricciarelli - 2016 A.D.
* (with the precious advises given by Nick Gammon, cattledog and dlloyd, from the offical Arduino Forum - http://forum.arduino.cc/)
*
WIRING INFORMATION
===================
POT A
Connect CLK to Pin 2 on Arduino Board (CLK is Data Output 1 of KY-040)
Connect DT to Pin 4 on Arduino Board (DT is Data Output 2 of KY-040)
Connect SW to Pin 5 on Arduino Board (Switch - goes LOW when pressed)
POT B
Connect CLK to Pin 3 on Arduino Board (CLK is Data Output 1 of KY-040)
Connect DT to Pin 6 on Arduino Board (DT is Data Output 2 of KY-040)
Connect SW to Pin 7 on Arduino Board (Switch - goes LOW when pressed)
BOTH POTS
Connect GND to ground
Connect + to +5V (this will pull up CLK and DT with 10 KiloOhm resistors)
----------------------------------------------------------------------------
Connect a 0,47µ capacitor from ground to CLK (debouncing) 1 uF it's working fine
Connect a 0,47µ capacitor from ground to DT (debouncing) 1 uF it's working fine
Connect a 0,47µ capacitor from ground to SW (debouncing) 1 uF it's working fine
Connect a 10 KOhm resistor from +5V to SW (no integrated pullup for SW !!)
----------------------------------------------------------------------------
It is better NOT to use internal pull-up resistors on the Arduino, instead
use the integrated pull-ups of KY-040 (this requires "+" to be connected to 5V).
You can check if your version of the KY-040 has pull-up resistors on the bottom
side of the printed circuit board.
If not, use internal pull-ups from Arduino or external pull-ups.
-----------------------------------------------------------------------------
In the stopping positions the KY-040 has always HIGH signals on both CLK and DT.
When you turn the encoder from one position to another, either CLK or DT goes LOW
before the other signal goes LOW as well.
The signal that goes LOW first determines if the encoder is turned left or right.
Once you reach the next stopping position both signals will be HIGH again.
If you press the push button, the current count will be reset to the startup values.
For faster response you might increase the speed of the serial connection.
(Make sure, that the Serial Monitor is also set to a higher speed,
otherwise you will get no output).
----------------------------------------------------------------------------------
*/
#define STARTING_PERIOD 900
#define DEAD_INTERVAL 5
#define MIN_PERIOD 100
#define MIN_DEADTIME 5
#define SERIAL_OUT 0 // Sends or not the pot's value to the serial port (1 = serial enabled, 0 = serial disabled)
#define PinCLK_A 2 // Used for generating interrupts using CLK signal (PIN 2 = Interrupt 0)
#define PinDT_A 4 // Used for reading DT signal
#define PinSW_A 5 // Used for the push button switch
#define PinCLK_B 3 // Used for generating interrupts using CLK signal (PIN 3 = Interrupt 1), no more interrupts on Arduino UNO !!!
#define PinDT_B 6 // Used for reading DT signal
#define PinSW_B 7 // Used for the push button switch
volatile boolean TurnDetected_A;
volatile boolean up_A;
volatile boolean CLK_A;
volatile boolean DT_A;
volatile boolean TurnDetected_B;
volatile boolean up_B;
volatile boolean CLK_B;
volatile boolean DT_B;
static long virtualPosition_A = 0; // without STATIC it does not count correctly!!!
static long virtualPosition_B = 0; // without STATIC it does not count correctly!!!
static byte multiplier_A = 10; // increments the period by 10 units per turn
static byte multiplier_B = 1; // reduces the duty cycle by 1 unit per turn
void isr_A() { // Interrupt service routine is executed when any CHANGE transition is detected on CLK or DT
CLK_A = digitalRead(PinCLK_A);
DT_A = digitalRead(PinDT_A);
up_A = ((CLK_A && DT_A) || (!CLK_A && !DT_A));
ICR1 = virtualPosition_A; // period
OCR1A = ICR1 / 2; // duty cycle (half of ICR1, so 50% fixed)
OCR1B = (ICR1 / 2) - virtualPosition_B; // duty cycle NARROWABLE by pot/encoder
TurnDetected_A = true;
}
void isr_B() { // Interrupt service routine is executed when any CHANGE transition is detected on CLK or DT
CLK_B = digitalRead(PinCLK_B);
DT_B = digitalRead(PinDT_B);
up_B = ((CLK_B && DT_B) || (!CLK_B && !DT_B));
ICR1 = virtualPosition_A; // period
OCR1A = ICR1 / 2; // duty cycle (half of ICR1, so 50% fixed)
OCR1B = (ICR1 / 2) - virtualPosition_B; // duty cycle NARROWABLE by pot/encoder
TurnDetected_B = true;
}
void setup() {
DDRB |= bit (DDB1) | bit (DDB2); // Defining PB1 and PB2 as outputs by setting PORTB1 and PORTB2, Setting DDB1 and DDB2
TCCR1A = 0; // stop timer 1
TCCR1B = 0; // stop timer 1
TCCR1A = bit (COM1B0) | bit (COM1B1) // Set OC1B on Compare Match, clear OC1B at BOTTOM (inverting mode)
| bit (COM1A1); // Clear OC1A on Compare Match, set OC1A at BOTTOM (non-inverting mode)
TCCR1B = bit (WGM13) // PWM, top at ICR1
| bit (CS10); // Start timer, prescaler of 1
ICR1 = STARTING_PERIOD; // period
OCR1A = ICR1 / 2; // duty cycle (half of ICR1, so 50% fixed)
OCR1B = (ICR1 / 2) - DEAD_INTERVAL; // duty cycle - deadtime
// Digital encoder A
pinMode(PinCLK_A, INPUT);
pinMode(PinDT_A, INPUT);
pinMode(PinSW_A, INPUT);
// Digital encoder B
pinMode(PinCLK_B, INPUT);
pinMode(PinDT_B, INPUT);
pinMode(PinSW_B, INPUT);
// Attach interrupts
attachInterrupt (0, isr_A, CHANGE); // interrupt 0 is always connected to pin 2 on Arduino UNO
attachInterrupt (1, isr_B, CHANGE); // interrupt 1 is always connected to pin 3 on Arduino UNO
// Startup values
virtualPosition_A = STARTING_PERIOD;
virtualPosition_B = DEAD_INTERVAL;
#if SERIAL_OUT == 1
Serial.begin (19200);
Serial.println("Start");
#endif
}
void loop() {
if (!digitalRead(PinSW_A)) { // check if pushbutton A is pressed
virtualPosition_A = STARTING_PERIOD; // if YES, then reset counter to startup value
#if SERIAL_OUT == 1
Serial.print ("Reset_A = ");
Serial.println (virtualPosition_A);
#endif
}
if (TurnDetected_A) { // do this only if rotation was detected
if (up_A) {
virtualPosition_A += multiplier_A;
}
else if (virtualPosition_A > MIN_PERIOD)
{
virtualPosition_A -= multiplier_A;
}
TurnDetected_A = false; // do NOT repeat IF loop until new rotation detected
#if SERIAL_OUT == 1
Serial.print ("Value_A = ");
Serial.println (virtualPosition_A);
#endif
}
if (!digitalRead(PinSW_B)) { // check if pushbutton B is pressed
virtualPosition_B = DEAD_INTERVAL; // if YES, then reset counter to startupvalue
#if SERIAL_OUT == 1
Serial.print ("Reset_B = ");
Serial.println (virtualPosition_B);
#endif
}
if (TurnDetected_B) { // do this only if rotation was detected
if (up_B) {
virtualPosition_B += multiplier_B;
}
else if (virtualPosition_B > MIN_DEAD_TIME)
{
virtualPosition_B -= multiplier_B;
}
TurnDetected_B = false; // do NOT repeat IF loop until new rotation detected
#if SERIAL_OUT == 1
Serial.print ("Value_B = ");
Serial.println (virtualPosition_B);
#endif
}
}
The two digital encoders have been used here as digital potentiometers, allowing to change the frequency and the dead time (narrowing/expanding one of the two signals).
The numeric values coming from the two encoders are managed by two ISRs (Interrupt Services Routines, which seems to do not conflict with the timers used to generate the two PWMs) and there used to feed the main timers.
As you can see on the attached images, the whole circuit is a bit rude, but it works as planned.
The discrete component's part still requires some tuning and there is still the need to implement a decent MOSFET's driver but this is another story and it's out of the scope of this thread.
If you see something inadequate in what I've written inside the code or if you think that I could meet some unexpected behavior, feel free to note it to me.
Many thanks to all of you!
Fabrizio