You can, the sequence repeats every 6ms, during which time signals 1 and 2 have completed 20 cycles, and signal 3 has completed 3 cycles.
I had to adjust the 'hold off time' to get a stable oscilloscope trace.
You can, the sequence repeats every 6ms, during which time signals 1 and 2 have completed 20 cycles, and signal 3 has completed 3 cycles.
Thank you so much @horace for your kind response, as mention in the post 19 with slight modification the mentioned wave forms are generated in the attachement
#define S1pin 2
#define S2pin 3
#define S3pin 4
// Setup pulse patterns - each slot is 50 µs
// Signal 1: 100 µs HIGH, 200 µs LOW
byte signal1[] = { 1, 1, 0, 0, 0, 0 };
int s1index = 0;
// Signal 2: 150 µs LOW, 100 µs HIGH, 50 µs LOW
byte signal2[] = { 0, 0, 0, 1, 1, 0 };
int s2index = 0;
// Signal 3: 650 µs LOW, 1000 µs HIGH, 150 µs LOW
byte signal3[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 650 µs LOW
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1000 µs HIGH
1, 1, 1, 1, 1, 1, 1, 1, // (20 × 50 µs)
0, 0, 0 }; // 150 µs LOW
int s3index = 0;
// Timer ISR (Interrupt Service Routine)
void TC3_Handler() {
// Clear the interrupt flag
TC_GetStatus(TC1, 0);
// Output next 50 µs level
digitalWrite(S1pin, signal1[s1index++]);
digitalWrite(S2pin, signal2[s2index++]);
digitalWrite(S3pin, signal3[s3index++]);
// Reset indices when reaching the end of arrays
if (s1index == sizeof(signal1)) s1index = 0;
if (s2index == sizeof(signal2)) s2index = 0;
if (s3index == sizeof(signal3)) s3index = 0;
}
void setup() {
// Initialize pins as outputs
pinMode(S1pin, OUTPUT);
pinMode(S2pin, OUTPUT);
pinMode(S3pin, OUTPUT);
// Configure Timer3 for 50 µs interval
pmc_set_writeprotect(false); // Disable write protection for PMC
pmc_enable_periph_clk(TC3_IRQn); // Enable Timer3 peripheral clock
Tc *tc = TC1; // Timer1 block
uint32_t channel = 0; // Channel 0 for TC3
uint32_t freq = 20000; // Timer frequency (1/50 µs = 20,000 Hz)
TC_Configure(tc, channel,
TC_CMR_TCCLKS_TIMER_CLOCK1 | // Select Timer clock (MCK/2)
TC_CMR_WAVE | // Waveform mode
TC_CMR_WAVSEL_UP_RC); // Count up to RC
uint32_t rc = VARIANT_MCK / 2 / freq; // Set RC for 50 µs
TC_SetRA(tc, channel, rc / 2); // Set RA for duty cycle (50%)
TC_SetRC(tc, channel, rc); // Set RC for 50 µs period
TC_Start(tc, channel); // Start Timer
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPCS; // Enable RC compare interrupt
tc->TC_CHANNEL[channel].TC_IDR = ~TC_IER_CPCS;
NVIC_EnableIRQ(TC3_IRQn); // Enable interrupt in NVIC
}
void loop() {
// Main loop does nothing - timing is handled by the Timer ISR
}
`
good news!
edit your post 22 to use code tags </> - make code much more readable
as @JohnLincoln mentions in post 20 you can synch a signal of 2000uSec period with signals of 300uSec period over 6mSec
e.g. timing
// setup pulse patterns - each slot is 50uSec
// signal 1 100uSec high 200uSec low
byte signal1[] = { 1, 1, 0, 0, 0, 0 };
int s1index = 0;
// signal 2 150uSec low 100uSec High 50uSec low
byte signal2[] = { 0, 0, 0, 1, 1, 0 };
int s2index = 0;
// signal 3 650uSec low 1000uSec high 150uSec low
byte signal3[]={0,0,0,0,0,0,0,0,0,0,0,0,0, // 650uSec low
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 1000uSec high
0, 0, 0, 0, 0, 0, 0}; // 350uSec low
int s3index = 0;
scope display using a hold off of 4.1mSec
I still prefer to use the ESP32S3 RMT to generate complex pulse sequences
set it going and you can forget about it - no ISRs etc
Hello, @horace @JohnLincoln could you help where am going wrong with the code which i used to generate for 6 signals. why the frequency of the signals are degrading ?
#define S1pin 2
#define S2pin 3
#define S3pin 4
#define S4pin 5
#define S5pin 6
#define S6pin 7
// Signal patterns (predefined based on required frequencies)
// Signal 1-4: 12.5 kHz (80 µs period, 8 steps)
byte signal1[] = {0, 0, 0, 1, 0, 0, 0, 0};
byte signal2[] = {0, 0, 0, 0, 0, 1, 0, 0};
byte signal3[] = {0, 0, 0, 0, 0, 0, 0, 1};
byte signal4[] = {0, 1, 0, 0, 0, 0, 0, 0};
// Signal 5: 2 kHz (500 µs period, 50 steps)
byte signal5[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
// Signal 6: 1 kHz (1 ms period, 100 steps)
byte signal6[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// Indices for signal tracking
volatile int s1index = 0, s2index = 0, s3index = 0, s4index = 0;
volatile int s5index = 0, s6index = 0;
// Timer Interrupt Service Routine (ISR)
void TC3_Handler() {
TC_GetStatus(TC1, 0); // Clear the interrupt flag
// Atomic signal update
digitalWrite(S1pin, signal1[s1index]);
digitalWrite(S2pin, signal2[s2index]);
digitalWrite(S3pin, signal3[s3index]);
digitalWrite(S4pin, signal4[s4index]);
digitalWrite(S5pin, signal5[s5index]);
digitalWrite(S6pin, signal6[s6index]);
// Increment and reset indices
s1index = (s1index + 1) % sizeof(signal1);
s2index = (s2index + 1) % sizeof(signal2);
s3index = (s3index + 1) % sizeof(signal3);
s4index = (s4index + 1) % sizeof(signal4);
s5index = (s5index + 1) % sizeof(signal5);
s6index = (s6index + 1) % sizeof(signal6);
}
void setup() {
// Configure pins as outputs
pinMode(S1pin, OUTPUT);
pinMode(S2pin, OUTPUT);
pinMode(S3pin, OUTPUT);
pinMode(S4pin, OUTPUT);
pinMode(S5pin, OUTPUT);
pinMode(S6pin, OUTPUT);
// Configure Timer 3
pmc_set_writeprotect(false); // Disable write protection
pmc_enable_periph_clk(TC3_IRQn); // Enable peripheral clock for Timer3
Tc *tc = TC1; // Use Timer1 block
uint32_t channel = 0; // Channel 0 (TC3)
uint32_t freq = 125000; // Timer frequency: 8 µs (125,000 Hz)
TC_Configure(tc, channel,
TC_CMR_TCCLKS_TIMER_CLOCK1 | // Clock source: MCK/2
TC_CMR_WAVE | // Enable waveform mode
TC_CMR_WAVSEL_UP_RC); // Count up to RC
uint32_t rc = VARIANT_MCK / 2 / freq; // Calculate RC for 8 µs period
TC_SetRA(tc, channel, rc / 2); // 50% duty cycle
TC_SetRC(tc, channel, rc); // Set RC for 8 µs
TC_Start(tc, channel); // Start Timer
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPCS; // Enable RC compare interrupt
tc->TC_CHANNEL[channel].TC_IDR = ~TC_IER_CPCS;
NVIC_EnableIRQ(TC3_IRQn); // Enable interrupt in NVIC
}
void loop() {
// Main loop left empty as timing is handled by the ISR
}
could be the Due is not fast enough
will experiment
signals 1 to 6 using digitalWriteFast()
// DUE six pulse test using timer interrupts
// // Signal 1-4: 12.5 kHz (80 µs period, 8 steps)
#include <DueTimer.h>
#define S1pin 2
#define S2pin 3
#define S3pin 4
#define S4pin 5
#define S5pin 6
#define S6pin 7
// setup pulse patterns - each slot is 10uSec
// Signal 1-4: 12.5 kHz (80 µs period, 8 steps)
byte signal1[] = { 0, 0, 0, 1, 0, 0, 0, 0 };
byte signal2[] = { 0, 0, 0, 0, 0, 1, 0, 0 };
byte signal3[] = { 0, 0, 0, 0, 0, 0, 0, 1 };
byte signal4[] = { 0, 1, 0, 0, 0, 0, 0, 0 };
// Signal 5: 2 kHz (500 µs period, 50 steps)
byte signal5[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
// Signal 6: 1 kHz (1 ms period, 100 steps)
byte signal6[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int s1index = 0;
int s2index = 0;
int s3index = 0;
int s4index = 0;
int s5index = 0;
int s6index = 0;
// digitalWriteFast from
// https://forum.arduino.cc/t/arduino-due-digitalwrite-vs-direct-port-manipulation-speed/666404/31
boolean NonConstantUsed(void) __attribute__((error("")));
#define digitalWriteFast(pin, val) \
if (__builtin_constant_p(pin)) { \
_dwfast(pin, val); \
} else { \
NonConstantUsed(); \
}
static inline __attribute__((always_inline)) void _dwfast(int pin, int val) {
if (val) {
digitalPinToPort(pin)->PIO_SODR = digitalPinToBitMask(pin);
} else {
digitalPinToPort(pin)->PIO_CODR = digitalPinToBitMask(pin);
}
}
// on timer interrupt output next 50uSec level
void timerISR(void) {
digitalWriteFast(S1pin, signal1[s1index++]); // signal 1
digitalWriteFast(S2pin, signal2[s2index++]);
digitalWriteFast(S3pin, signal3[s3index++]);
digitalWriteFast(S4pin, signal4[s4index++]);
digitalWriteFast(S5pin, signal5[s5index++]);
digitalWriteFast(S6pin, signal6[s6index++]);
if (s1index == sizeof(signal1)) s1index = 0; // increment array index if at end
if (s2index == sizeof(signal2)) s2index = 0;
if (s3index == sizeof(signal3)) s3index = 0;
if (s4index == sizeof(signal4)) s4index = 0;
if (s5index == sizeof(signal5)) s5index = 0;
if (s6index == sizeof(signal6)) s6index = 0;
}
void setup() {
pinMode(S1pin, OUTPUT); // initialise outputs
pinMode(S2pin, OUTPUT);
pinMode(S3pin, OUTPUT);
pinMode(S4pin, OUTPUT);
pinMode(S5pin, OUTPUT);
pinMode(S6pin, OUTPUT);
Timer3.attachInterrupt(timerISR); // attached interrupt ISR
Timer3.start(10); // interval is in microseconds.
}
void loop() {}
signals 1 to 4
signal 1, 2, 5, 6