That is a very demanding and egoistic request:
almost zero work from you 99.9% work for others
If you don't want to pay money. You will have to "pay" some time.
That is a very demanding and egoistic request:
almost zero work from you 99.9% work for others
If you don't want to pay money. You will have to "pay" some time.
Okay guys, I’m very interested to hear your opinions and thank you very much for some software calculations. My goal is to create a three-phase driver based on a simple Arduino module to control a powerful thyristor three-phase bridge. This is not for controlling motors but for emergency powering three-phase existing circuits commercial industrial and residential arias. Idea to create affordable reliable device
Decimal places are out. And micros() granularity is 4µs chunks.
using a ESP32 Timer0 interrupts to generate 666uSec pulses (period 1332uSec)
// ESP32 666uSec interrupt - generate pulse
// from original code
/****************************************************************************************************************************
TimerInterruptTest.ino
For ESP32, ESP32_S2, ESP32_S3, ESP32_C3 boards with ESP32 core v2.0.2+
Written by Khoi Hoang
Built by Khoi Hoang https://github.com/khoih-prog/ESP32TimerInterrupt
Licensed under MIT license
*/
#include "ESP32TimerInterrupt.h"
#define PIN_D19 19 // Pin D19 mapped to pin GPIO19 of ESP32
// Timer0 interrupt handler - invert pin GPIO19 and increment counter
volatile int counter = 0;
bool IRAM_ATTR TimerHandler0(void* timerNo) {
static bool toggle0 = false;
digitalWrite(PIN_D19, toggle0);
toggle0 = !toggle0;
counter++;
return true;
}
// Init ESP32 timer 0
ESP32Timer ITimer0(0);
void setup() {
pinMode(PIN_D19, OUTPUT);
Serial.begin(115200);
while (!Serial && millis() < 5000)
;
delay(500);
Serial.print(F("\nStarting TimerInterruptTest on "));
Serial.println(ARDUINO_BOARD);
Serial.println(ESP32_TIMER_INTERRUPT_VERSION);
Serial.print(F("CPU Frequency = "));
Serial.print(F_CPU / 1000000);
Serial.println(F(" MHz"));
// Interval in microsecs
if (ITimer0.attachInterruptInterval(666, TimerHandler0)) {
Serial.print(F("Starting ITimer0 OK "));
} else
Serial.println(F("Can't set ITimer0. Select another freq. or timer"));
Serial.flush();
}
// display counter every second
void loop() {
static long timer = millis();
if (millis() - timer >= 1000) {
timer = millis();
Serial.println(counter);
counter = 0;
}
}
serial monitor output
Starting TimerInterruptTest on ESP32_DEV
ESP32TimerInterrupt v2.3.0
CPU Frequency = 240 MHz
Starting ITimer0 OK 1516
1501
1502
1501
1502
1501
1502
1501
1502
1501
1502
1501
oscilloscope plot
a Tensey 4 may be able to get closer to 666.6uSec otherwise build some hardware
Well that's the wrong order of updates and the initial state needs defining, I think this might be closer to the OP's timing diagram:
const byte Pins[] = {9,10,11};
void setup()
{
for (byte i = 0 ; i < 3 ; i++). // set modes to OUTPUT
pinMode(Pins[i], OUTPUT);
digitalWrite(Pins[0], HIGH); // initial state
digitalWrite(Pins[1], LOW);
digitalWrite(Pins[2], HIGH);
}
void loop()
{
for (int i = 2; i >= 0; i--) // order of update to match diagram
{
digitalWrite(Pin[i], ! digitalRead(Pin[i])); // toggle pin
delayMicroseconds(333);
}
}
possibly a state machine may work, e.g. ESP32
// ESP32 333.3uSec interrupt - generate 3 phase pulses
// from ESP32 Sine Wave Example https://deepbluembedded.com/esp32-dac-audio-arduino-examples/
/* original from
* LAB Name: ESP32 Sine Wave Generation Example
* Author: Khaled Magdy
* DeepBlueMbedded 2023
* For More Info Visit: www.DeepBlueMbedded.com
*/
#include <driver/dac.h>
#include <driver/adc.h>
#define PIN_D19 19 // phase 1, 2 and 3
#define PIN_D18 18
#define PIN_D5 5
// Timer0 Configuration Pointer (Handle)
hw_timer_t *Timer0_Cfg = NULL;
// Timer0 interrupt handler - output 3 phase pulses and increment counter
volatile int counter = 0;
void IRAM_ATTR Timer0_ISR() {
static int state = 0; // state machine
switch (state) {
case 0:
digitalWrite(PIN_D19, 1); // phase 1 HIGH
break;
case 1:
digitalWrite(PIN_D5, 0); // phase 3 LOW
break;
case 2:
digitalWrite(PIN_D18, 1); // phase 2 HIGH
break;
case 3:
digitalWrite(PIN_D19, 0); // phase 1 LOW
break;
case 4:
digitalWrite(PIN_D5, 1); // phase 3 HIGH
break;
case 5:
digitalWrite(PIN_D18, 0); // phase 2 LOW
break;
}
if(++state > 5) state=0; // increment state or reset to 0
counter++;
}
void setup() {
Serial.begin(115200);
pinMode(PIN_D19, OUTPUT);
pinMode(PIN_D18, OUTPUT);
pinMode(PIN_D5, OUTPUT);
Serial.println("\nESP32 3 phase pulses");
// Configure Timer0 Interrupt 666.6uSec
Timer0_Cfg = timerBegin(0, 8, true);
timerAttachInterrupt(Timer0_Cfg, &Timer0_ISR, true);
timerAlarmWrite(Timer0_Cfg, 3333, true);
timerAlarmEnable(Timer0_Cfg);
}
// display counter every second
void loop() {
static long timer = millis();
if (millis() - timer >= 1000) {
timer = millis();
Serial.println(counter);
counter = 0;
}
}
gives (phase 1 yellow, phase 2 cyan phase 3 purple)
and
Did you do a search for three phase square wave? It’s been solved lots of times:
https://forum.arduino.cc/search?q=three%20phase%20square%20wave
I know I tried it once:
And here's one with Bresenham-like timing. It does have some jitter due to the granularity micros() and the execution time in software, but the average frequency is phase-locked with the to the match the accuracy of the processor clock:
You're right. Getting the pin order and initial conditions with round-robin toggle scheme is a bit tricky.
Managing the transitions or swapping pins with a state machine per @horace could be more straightforward.
UNO generate 3 phase pulses using state machine
// UNO 333uSec interrupt - generate 3 phase pulses
#include <TimerOne.h>
const byte pinA = 7;
const byte pinB = 8;
const byte pinC = 9;
// 3 phase state sequence
enum states{P1_HIGH, P3_LOW, P2_HIGH, P1_LOW, P3_HIGH, P2_LOW};
// Timer0 interrupt handler - output 3 phase pulses and increment counter
volatile int counter = 0;
void Timer1_ISR() {
static int state = P1_HIGH; // state machine
switch (state) {
case P1_HIGH:
digitalWrite(pinA, 1); // phase 1 HIGH
break;
case P3_LOW:
digitalWrite(pinC, 0); // phase 3 LOW
break;
case P2_HIGH:
digitalWrite(pinB, 1); // phase 2 HIGH
break;
case P1_LOW:
digitalWrite(pinA, 0); // phase 1 LOW
break;
case P3_HIGH:
digitalWrite(pinC, 1); // phase 3 HIGH
break;
case P2_LOW:
digitalWrite(pinB, 0); // phase 2 LOW
break;
}
if(++state > 5) state=P1_HIGH; // increment state or reset to P1_HIGH
counter++;
}
void setup() {
Serial.begin(115200);
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
pinMode(pinC, OUTPUT);
Serial.println("\nUNO 3 phase pulses");
Timer1.initialize(333); //Initialize timer with .1 mSec second period
Timer1.attachInterrupt(Timer1_ISR);
}
// display counter every second
void loop() {
static long timer = millis();
if (millis() - timer >= 1000) {
timer = millis();
Serial.println(counter);
counter = 0;
}
}
serial monitor output
UNO 3 phase pulses
3012
3013
3010
3013
3010
3013
3010
3013
3012
3010
3013
3009
3013
3010
scope displays (phase 1 yellow, phase 2 cyan phase 3 purple)
If you tweak the Timer1.setPeriod() to also toggle between 333us and 334us, you can get the average right on target (as accurate as the processor clock)
#include <TimerOne.h>
const byte pinA = 7;
const byte pinB = 8;
const byte pinC = 9;
// 3 phase state sequence
enum states{P1_HIGH, P3_LOW, P2_HIGH, P1_LOW, P3_HIGH, P2_LOW};
// Timer0 interrupt handler - output 3 phase pulses and increment counter
volatile int counter = 0;
void Timer1_ISR() {
static int state = P1_HIGH; // state machine
switch (state) {
case P1_HIGH:
digitalWrite(pinA, 1); // phase 1 HIGH
break;
case P3_LOW:
digitalWrite(pinC, 0); // phase 3 LOW
break;
case P2_HIGH:
digitalWrite(pinB, 1); // phase 2 HIGH
break;
case P1_LOW:
digitalWrite(pinA, 0); // phase 1 LOW
Timer1.setPeriod(334);
break;
case P3_HIGH:
digitalWrite(pinC, 1); // phase 3 HIGH
break;
case P2_LOW:
digitalWrite(pinB, 0); // phase 2 LOW
Timer1.setPeriod(333);
break;
}
if(++state > 5) state=P1_HIGH; // increment state or reset to P1_HIGH
counter++;
}
void setup() {
Serial.begin(115200);
pinMode(pinA, OUTPUT);
pinMode(pinB, OUTPUT);
pinMode(pinC, OUTPUT);
Serial.println("\nUNO 3 phase pulses");
Timer1.initialize(333); //Initialize timer with .1 mSec second period
Timer1.attachInterrupt(Timer1_ISR);
}
// display counter every second
void loop() {
static long timer = millis();
if (millis() - timer >= 1000) {
timer +=1000;
Serial.println(counter);
counter = 0;
}
}
I also tweaked the printing so it won't lose synchronization in time or count:
// display counter every second
void loop() {
static long timer = millis();
if (millis() - timer >= 1000) {
timer +=1000;
Serial.println(counter);
counter -= 3000;
}
}
Guys, in my opinion it’s a simple task, but I couldn't come up with anything. There are two outputs (pinMode, 13); and (pinMode, 12); if one is high then the other is low like a flip flop. ?? What code for those
Opinion doesn't code. Clarity is important. I can't reconcile post#1 with post#32. One has 3 outputs, the latter states two. I give up.
Okay/ When pin 13 ON then pin 7 OFF
pin 12 ON then pin 4 OFF
pin 8 ON then pin 2 OFF
So at least for you it is a difficult task
For others it is a difficult task you you do not specify the details on the functional level.
You are still collecting
by too short postings
how many users do you want to
That seems like 6 outputs.
possibly a 6-phase system?
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.