I'm working on a project where I need to generate three square pulses with a 120-degree phase shift using the PWM outputs of an Arduino 2560. The frequency should vary between 0 and 1.5 kHz, depending on the ADC values or digital inputs received.
Additionally, I would like to generate three more similar signals on another three PWM outputs.
If you wanted to get adventerous you could generate the phases using a 4 bit counter ic and a couple of Not and And gates.
Then vary the counter clock signal to change the putput frequency of the phases
Edit
Even easier you could use a shit register. Initially load the shift register with 10000000.
Then take the 4th bit out to the in of the shift register.
Then pulse the clock pin at the frequency you want. And your first 3 bits out of the shift registers should cycle around, with 1 bit sequanitally being high, and the other 2 low
You can get a time budget if you do the math: At 1500Hz, three square waves need 6 transitions, so 1000000us/1500/6=111us per transition.
Seems like it might be feasible with plainly coded state machine. Here's two square waves with a 180° shift for 0-20kHz:
// Quadrature Generator
// https://wokwi.com/projects/403218793081155585
// Define the output pins
const int pinA = 2;
const int pinB = 3;
// Define the state machine states
enum State {STATE0, STATE1, STATE2, STATE3};
State currentState = STATE0;
// Timing variables
unsigned long previousMicros = 0;
unsigned long interval = 357; // 357 microseconds for each state
bool on = false;
void setup() {
// Initialize the output pins
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
// Initialize the pins to a known state
digitalWrite(pinA, LOW);
digitalWrite(pinB, LOW);
Serial.begin(115200);
}
void readPot(void) {
static int lastADC = -1;
int pot = analogRead(A0);
if (pot != lastADC) { // change detection on potentiometer
lastADC = pot;
long speed = map(pot, 0, 1023, 0, 200000);
if (speed == 0) {
on = false;
} else {
on = true;
interval = 10000000.0 / speed / 4;
previousMicros = micros();
}
Serial.print(pot);
Serial.print(", ");
Serial.print(speed/10.0);
Serial.print("Hz us:");
Serial.println(interval);
}
}
void loop() {
// Get the current time in microseconds
unsigned long currentMicros = micros();
static unsigned long lastScan;
if (millis() - lastScan > 128) {
lastScan += 128;
readPot();
}
// Check if the interval has passed
if (on && currentMicros - previousMicros >= interval) {
// Save the current time for the next interval
// previousMicros = currentMicros;
previousMicros += interval;
// Advance the state machine
switch (currentState) {
case STATE0:
digitalWrite(pinA, HIGH);
// digitalWrite(pinB, LOW);
currentState = STATE1;
break;
case STATE1:
//digitalWrite(pinA, HIGH);
digitalWrite(pinB, HIGH);
currentState = STATE2;
break;
case STATE2:
digitalWrite(pinA, LOW);
//digitalWrite(pinB, HIGH);
currentState = STATE3;
break;
case STATE3:
//digitalWrite(pinA, LOW);
digitalWrite(pinB, LOW);
currentState = STATE0;
break;
}
}
}