58 posts / 0 new

## Pages

Author
Message

I am working on an ultrasound device. We want to generate a particular signal to drive the 1 MHz piezoelectric sensor at various resonance frequencies point.

The goal is to write a code using Atmega328p (Arduino Nano) to generate a signal with 8 fixed-width pulses with varying intervals as seen in the table below.

The sample of the signal we are looking for is below: the yellow signal

I succeeded to find a code to generate an 8 pulses signal at the unique frequency of 1MHz: The code and the results on the oscilloscope are found below:

#define NOP __asm__ __volatile__ ("nop\n\t")

void delayMilliseconds(int ms) {
for (int i = 0; i < ms; i++) {
delayMicroseconds(1000);
}
}

void stopTransducer()
{
cli();
TCCR1B = 0;
sei();
}

void startTransducer(float freq, float dutyCycle)
{
dutyCycle = dutyCycle * 10.0;
if (dutyCycle == 0) dutyCycle = 0.0;
else if (dutyCycle == 1.0) dutyCycle = 0.1;
else if (dutyCycle == 2.0) dutyCycle = 0.2;
else if (dutyCycle == 3.0) dutyCycle = 0.3;
else if (dutyCycle == 4.0) dutyCycle = 0.4;
else if (dutyCycle == 5.0) dutyCycle = 0.5;
else if (dutyCycle == 6.0) dutyCycle = 0.6;
else if (dutyCycle == 7.0) dutyCycle = 0.7;
else if (dutyCycle == 8.0) dutyCycle = 0.8;
else if (dutyCycle == 9.0) dutyCycle = 0.9;

cli();
TCCR1B = _BV(WGM13) | _BV(CS10) | _BV(ICNC1);
//f0 = fclk / (2 * N * Top)
long topv = (long) ((float) F_CPU / (freq * 2.0 * 1.0));
ICR1 = topv;

//OCR1A = 4;
OCR1A = (int) ((float) topv * dutyCycle);
//OCR1B = (int) ((float) topv * (1 - dutyCycle));
DDRB |= _BV(PORTB1) | _BV(PORTB2);
TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(COM1A0) | _BV(COM1B0) ;
sei();
}

void setup()
{
//Serial.begin(9600);

pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
//pinMode (3, OUTPUT);

DDRD |= B01000000;
}

byte a = 0;
unsigned long t_start = 0;
unsigned long t_peak = 0;
unsigned long t = 0;
byte v_peak = 0;
const float SPEED_OF_SOUND_20C = 0.0003432; //per micro-second
float d = 0;

void loop()
{

startTransducer(1000000.0, 0.5);
delayMicroseconds(8);
stopTransducer();

delayMicroseconds(10);
DDRD |= B00001000;
PORTD &= ~(1 << PD3); //set PD3 low

v_peak = 0;
t_start = micros();
t_peak = t_start;

for (int i = 0; i < 256; i++) {
t = micros();

if (a > v_peak) {
t_peak = t;
v_peak = a;
}
}

t = t_peak - t_start;
d = (float) t * SPEED_OF_SOUND_20C / 2.0;
//Serial.println(d , 2);

PORTD |= 1 << PD3;
DDRD &= B00000000;
delay(100);
}

This is the result of the code from the oscilloscope:

My Challenge

How to twist the code above to generate a signal as in figure 1 with Atmega328P (Arduino). I have a little knowledge about timers for AVR, I will appreciate any help from the community. Thank you.

I am learning AVR, help me!!

Last Edited: Tue. May 17, 2022 - 08:53 PM

Welcome.

I went too deep and wrote this. I used AVR delay loop calculator.

Try this code and report.

void sendSignal()
{
// Pin Low for 31 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 10	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 7 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
"    lpm	\n"
);

// Pin Low for 56 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 18	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    rjmp 1f	\n"
"1:	\n"
);

// Pin High for 14 cycles

PORTD |= (1 << PD3);

asm volatile (
"    ldi  r18, 4	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    nop	\n"
);

// Pin Low for 31 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 10	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 7 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
"    lpm	\n"
);

// Pin Low for 56 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 18	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    nop	\n"
);

// Pin High for 14 cycles

PORTD |= (1 << PD3);

asm volatile (
"    ldi  r18, 4	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    nop	\n"
);

// Pin Low for 23 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 7	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    nop	\n"
);

// Pin High for 6 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
"    rjmp 1f	\n"
"1:	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    rjmp 1f	\n"
"1:  rjmp 2f	\n"
"2:	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    rjmp 1f	\n"
"1:  rjmp 2f	\n"
"2:	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High

PORTD |= (1 << PD3);
}

void setup() {

DDRD |= (1 << PD3);
PORTD |= (1 << PD3);
}

void loop() {

sendSignal();
delay(100);
}

EDIT :- I have not tested this on oscilloscope.

“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?” - Brian W. Kernighan
“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” - Antoine de Saint-Exupery

Last Edited: Tue. May 17, 2022 - 05:07 PM

Hello @Heisen

I thank you for taking the time to look at this, I really appreciate it!

Actually, it looks like I have not been using good technical words to explain the challenge, I am facing!

Your code actually helps me to improve the voltage output of the transducer but I still have some ripple on the signal due to the difference of PERIOD for each pulse!

If you see the 1 first image with the oscilloscope (yellow and blue signal). You will notice that the pulsing arrow is the same, but it doesn't give this result with your code.

It might my fault because I am not using the right term to explain the challenge. The Pulse are having a different periods but the On-time is the same for each pulse!

You can check the result with your code:

I am learning AVR, help me!!

Last Edited: Tue. May 17, 2022 - 05:20 PM

Techno KG wrote:
The Pulse are having a different periods but the On-time is the same for each pulse!

Oh, I think I understand what you are saying. Let me look at this one more time. I'll try to post with correction.

“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?” - Brian W. Kernighan
“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” - Antoine de Saint-Exupery

Heisen wrote:

Techno KG wrote:
The Pulse are having a different periods but the On-time is the same for each pulse!

Oh, I think I understand what you are saying. Let me look at this one more time. I'll try to post with correction.

Thank you!

I am learning AVR, help me!!

The proper term looks like this, if I may add it:

Generate a signal with 8 fixed-width pulses with a varying interval

I am learning AVR, help me!!

Who told you to use the ATMEGA?? You are using the WRONG device for this, forget about the ATMEGA

You need to use a DDS chip or PLL chip.  Do not use the ATMEGA, it will not have the fine freq resolution needed for ultrasonics, especially at these high frequencies.

You will only later regret it when you need to tweak your frequency and can only take very large steps.  Usually you want to tune in a few Hz or 10's of Hz, maybe even 100Hz.  You will be very disappointed if you use the ATMEGA.

Do yourself a favor now and walk away, move on to a DDS or PLL.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Thank you for your contribution @avrcandies. I am fine with a resolution of 1000 Hz. If you can help us to tune or twist the code @Heisen suggested. Thank you!

I am learning AVR, help me!!

What  avrcandies suggested is probably the right way to go.

Anyway, I made the changes. It can be further fine tuned.

void sendSignal()
{
// Pin Low for 35 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 11	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    nop	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 67 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 22	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 35 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 11	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    nop	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 66 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 21	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    rjmp 1f	\n"
"1:	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 25 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 8	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High

PORTD |= (1 << PD3);

}

void setup() {

DDRD |= (1 << PD3);
PORTD |= (1 << PD3);
}

void loop() {

sendSignal();
delay(100);
}

“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?” - Brian W. Kernighan
“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” - Antoine de Saint-Exupery

avrcandies wrote:

Who told you to use the ATMEGA?? You are using the WRONG device for this, forget about the ATMEGA

You need to use a DDS chip or PLL chip.  Do not use the ATMEGA, it will not have the fine freq resolution needed for ultrasonics, especially at these high frequencies.

Not in this instance.

The OP looks to be cloning an existing system pulse stream where only a single pulse is given with varying delays.

Thus KISS of inline ASM with defined delays looks just fine - easy to adjust.

DDS chips are adder based so are good at generating square and sine outputs but they are not designed for single pulse bursts of variant interpulse delays.

If the OP finds they need finer resolution, a MCU with a faster-clocked PWM block, that reloads the PWM period every cycle could do that.  (some AVR's have 64MHz PWM clock ability)

Google finds some TI MSP430 parts that claim a 256MHz Timer_D

Some Megawin 8b MCUs have 100 & 144MHz PWMs

Last Edited: Tue. May 17, 2022 - 08:35 PM

Thank you for your contribution! Very helpful! I will try to continue from here!

Also, I will try to see with ESP32, do you think, it is worth the try?

I am learning AVR, help me!!

Heisen wrote:

What  avrcandies suggested is probably the right way to go.

Anyway, I made the changes. It can be further fine tuned.

void sendSignal()
{
// Pin Low for 35 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 11	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    nop	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 67 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 22	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 35 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 11	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    nop	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 66 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 21	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
"    rjmp 1f	\n"
"1:	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 25 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 8	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High for 4 cycles

PORTD |= (1 << PD3);

asm volatile (
"    lpm	\n"
);

// Pin Low for 16 cycles

PORTD &= ~(1 << PD3);

asm volatile (
"    ldi  r18, 5	\n"
"1:  dec  r18	\n"
"    brne 1b	\n"
);

// Pin High

PORTD |= (1 << PD3);

}

void setup() {

DDRD |= (1 << PD3);
PORTD |= (1 << PD3);
}

void loop() {

sendSignal();
delay(100);
}

Thank you for this @Heisen! Very helpful! I will try to continue the twisting!

Do you have any advice for ESP32?

I am learning AVR, help me!!

The OP looks to be cloning an existing system pulse stream where only a single pulse is given with varying delays.

Thus KISS of inline ASM with defined delays looks just fine - easy to adjust.

You need to rethink that.  At full 20MHz that is 50ns per tick, a HUGE amount near 1 MHz

say you want to gen 1000000 Hz, that's 20 AVR ticks for either freq or equiv delay between 2 pulses

say you want to gen 1000250 Hz that's 19.995 ticks for either freq or equiv delay between 2 pulses

You can see the resolution is extremely low & the AVR should be replaced by something else.

You need to use a DDS chip or PLL chip.  Do not use the ATMEGA, it will not have the fine freq resolution needed for ultrasonics, especially at these high frequencies.

You will only later regret it when you need to tweak your frequency and can only take very large steps.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Tue. May 17, 2022 - 09:23 PM

avrcandies wrote:

The OP looks to be cloning an existing system pulse stream where only a single pulse is given with varying delays.

Thus KISS of inline ASM with defined delays looks just fine - easy to adjust.

You need to rethink that.  At full 20MHz that is 50ns per tick, a HUGE amount near 1 MHz

say you want to gen 1000000 Hz, that's 20 AVR ticks for either freq or equiv delay between 2 pulses

say you want to gen 1000250 Hz that's 19.995 ticks for either freq or equiv delay between 2 pulses

You can see the resolution is extremely low & the AVR should be replaced by something else.

The OP has not stated they need 1000250Hz, they have given an example pulse-spaced stream.

A 64MHz PWM AVR can define the delays to a resolution of 0.3%, and the other MCUs I mentioned can improve that by a factor of 4.

There is a good chance the pulses the OP has captured, that they seek to clone, are already generated by a simple component, so they may just need to find a matching clock speed, to be very precise.

It's not clear what the OPs capture and measuring precision is, but a quick scan finds a solution like this

CLK = 59.400MHz - use any MCU with PWM > 60MHz

CLK/145 = 409655  - that's a deviation of 3.9ns

CLK/106 = 560377

CLK/75   = 792000

CLK/264 = 225000

Techno KG wrote:

Also, I will try to see with ESP32, do you think, it is worth the try?

Any MCU with a controllable PWM unit, can generate pulses of varying spacing, by reloading the PWM period setting every pulse as I mention in my posts.

Usually that is buffered in the silicon, so the next PWM is the one it applies to, and you pace the re-loads in SW to match the PWM period completion.

The ESP32 looks to support 80MHz PWM clock, tho it's less clear if it can set the PWM period to 1 pwm-clk granularity ?

Google finds some mention of 1-16b but also finds 'ESP32 uses 8, 10, 12, 15-bit resolution' ?

The OP has not stated they need 1000250Hz, they have given an example pulse-spaced stream.

The point is the resolution is low, even at a large step you cant resolve between 20 ticks and 19.995 ticks.   Again, it doesn't matter whether it is a repetitive frequency, or spaced pulse.

The space pulse is prob actually more constrained, since it can only use the 20 MHz instruction limit.

Either way, the resolution is rather poor.  We did a fair amount of ultrasonic driver work & typically used a step size of maybe 5-50 Hz.  That was for surgical scalpel applications & the resonance was very critical. Do not start off assuming you won't need good resolution, and find out you do after your system is completely built!

You can easily set up a DDS and get exactly what you need, so why mess around?  Some of the chips offer burst gen, so you can create a gated pulsing in various flavors.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Tue. May 17, 2022 - 10:30 PM

avrcandies wrote:

The OP has not stated they need 1000250Hz, they have given an example pulse-spaced stream.

The point is the resolution is low, even at a large step you cant resolve between 20 ticks and 19.995 ticks.   Again, it doesn't matter whether it is a repetitive frequency or spaced pulse.

The space pulse is prob actually worse, since it can only use the 20 MHz instruction limit.

Either way, the resolution is rather poor.  We did a fair amount of ultrasonic driver work & typically used a step size of maybe 5-50 Hz.  Do not start off assuming you won't need good resolution and find out you do after your system is completely built!

You can easily set up a DDS and get exactly what you need, so why mess around?  Some of the chips offer burst gen, so you can create a gated pulsing in various flavors.

The signal, I want to replicate is coming from a CC2540 Bluetooth IC. From the datasheet, the Clock Frequency is 32MHz. I believe we can do the same thing with ESP32.

I am learning AVR, help me!!

Is this to be your own design of some product?

what does it have to do with:

I am working on an ultrasound device. We want to generate a particular signal to drive the 1 MHz piezoelectric sensor at various resonance frequencies point.

Then why not use the CC2540 if it gives you what you need?

Are you trying to follow two paths at once?  AVR?  now ESP32? You seem to be all over the map and avoiding the solution that will work.  Take a look at some Analog Devices DDS chips.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Tue. May 17, 2022 - 10:36 PM

Techno KG wrote:

The signal, I want to replicate is coming from a CC2540 Bluetooth IC. From the datasheet, the Clock Frequency is 32MHz. I believe we can do the same thing with ESP32.

Yes, if you know what generated the signal, you should be able to carefully capture and measure the timing, to confirm it is 32MHz granular.

The numbers you have in #1 are not quite 32MHz granular, but that's likely measuring and rounding effects.

Then, you can replicate it using a similar PWM block.

avrcandies wrote:

Is this to be your own design of some product?

what does it have to do with:

I am working on an ultrasound device. We want to generate a particular signal to drive the 1 MHz piezoelectric sensor at various resonance frequencies point.

Then why not use the CC2540 if it gives you what you need?

Are you trying to follow two paths at once?  AVR?  now ESP32? You seem to be all over the map and avoiding the solution that will work.  Take a look at some Analog Devices DDS chips.

Sorry for the misunderstanding, the project is to measure the level of a liquid inside a given tank using ultrasound. I found a product that does the work with an Embedded cc2540 IC. This MCU drives the Piezoelectric transducer circuit. But in order to avoid learning a new MCU from scratch (IAR Workbench), I wanted to use another MCU to do the same job for our project. Using a dev board seems easy for me to achieve the goal since there is a community to help us. I am familiar with Arduino than ESP32 and CC2540. This is why, I am looking for help to produce this signal pattern.

I am learning AVR, help me!!

Who-me wrote:

Techno KG wrote:

The signal, I want to replicate is coming from a CC2540 Bluetooth IC. From the datasheet, the Clock Frequency is 32MHz. I believe we can do the same thing with ESP32.

Yes, if you know what generated the signal, you should be able to carefully capture and measure the timing, to confirm it is 32MHz granular.

The numbers you have in #1 are not quite 32MHz granular, but that's likely measuring and rounding effects.

Then, you can replicate it using a similar PWM block.

The device is damaged because of too much manipulation, I am just having various videos or screenshots during various data acquisitions with the oscilloscope.

I am learning AVR, help me!!

Who gave you the frequencies you need to produce?  Was it precisely documented?  You certainly can't use the scope picture, unless you are planning on generating completely bogus results.  How did you get precision measurements--certainly not with a cursor that has maybe 5-20 ticks per screen block applied to a warped looking wave.  At least look at a square wave from the drive source.  Your cursor as shown is almost a joke for any precise measurement---at least zoom in so you get a full screen of resolution (use dual [expanded] timebase/zoom mode).

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Techno KG wrote:

Who-me wrote:

Techno KG wrote:

The signal, I want to replicate is coming from a CC2540 Bluetooth IC. From the datasheet, the Clock Frequency is 32MHz. I believe we can do the same thing with ESP32.

Yes, if you know what generated the signal, you should be able to carefully capture and measure the timing, to confirm it is 32MHz granular.

The numbers you have in #1 are not quite 32MHz granular, but that's likely measuring and rounding effects.

Then, you can replicate it using a similar PWM block.

The device is damaged because of too much manipulation, I am just having various videos or screenshots during various data acquisitions with the oscilloscope.

Then you will need to apply 'best guess' to the data you have :)  Certainly zoom where you can, as suggested in #22.

I would work in the time domain, rather than frequency domain, as it is easier to see the 31.25ns granularity effects

1/226k - 1/(32M/(round(32M/226k)))  = -12.721ns

1/409k - 1/(32M/(round(32M/409k)))  = 7.487ns

1/560k - 1/(32M/(round(32M/560k)))  = 4.464ns

1/792k - 1/(32M/(round(32M/792k)))  = 12.626ns

but 3 of those are off by 1 from closer 32MHz candidates

1/227k - 1/(32M/(round(32M/227k)))  = -0.9ns
1/410k - 1/(32M/(round(32M/410k))) = 1.524ns

1/561k - 1/(32M/(round(32M/561k))) = 1.281ns

and maybe

1/780k - 1/(32M/(round(32M/780k)))  = 0.801ns

or
1/800k - 1/(32M/(round(32M/800k)))  = 0ns

You can get AVR with 64MHz/32MHz PWMs to reduce the learning curve.

Last Edited: Tue. May 17, 2022 - 11:22 PM

But in order to avoid learning a new MCU from scratch (IAR Workbench), I wanted to use another MCU to do the same job for our project.

Ok, things are starting to make more sense...you are NOT trying to find resonant frequencies, you are just hoping what was already done will be good enough for your own purpose.  And, in fact, you are making more of a simple "pinger", not driving a load via piezo as such. Why not just learn the new MCU?  In a high language, that seems staight forward, not like you are coding assembler (or are they).  They are prob just pinging and measuring time of response...

Why do you need to replicate their exact software at all?  There are many simple codes avail to measure fluid levels with transducers--have you looked for some?

I doubt you need to worry too much about what they did--they happened to use that wave, there are a million you can choose from.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Tue. May 17, 2022 - 11:29 PM

I think that many of the comments above are trying to understand what you are trying to do.... and to understand how well you understand the design requirements.

Sometimes one (we have all done it) optimise some aspect perfectly... only to learn that +/- 20% (100%?) might have been OK. Understanding the details of how and why a system works (or doesn't) lets us all make good design decisions as to what matters more and less.

Do you feel you have a good understanding of the operation and critical aspects of the system you are planning to duplicate?

regards
Greg

Last Edited: Wed. May 18, 2022 - 03:57 AM

avrcandies wrote:

Who gave you the frequencies you need to produce?  Was it precisely documented?  You certainly can't use the scope picture, unless you are planning on generating completely bogus results.  How did you get precision measurements--certainly not with a cursor that has maybe 5-20 ticks per screen block applied to a warped looking wave.  At least look at a square wave from the drive source.  Your cursor as shown is almost a joke for any precise measurement---at least zoom in so you get a full screen of resolution (use dual [expanded] timebase/zoom mode).

I used the oscilloscope to measure the time period for each pulse

I am learning AVR, help me!!

avrcandies wrote:

But in order to avoid learning a new MCU from scratch (IAR Workbench), I wanted to use another MCU to do the same job for our project.

Ok, things are starting to make more sense...you are NOT trying to find resonant frequencies, you are just hoping what was already done will be good enough for your own purpose.  And, in fact, you are making more of a simple "pinger", not driving a load via piezo as such. Why not just learn the new MCU?  In a high language, that seems staight forward, not like you are coding assembler (or are they).  They are prob just pinging and measuring time of response...

Why do you need to replicate their exact software at all?  There are many simple codes avail to measure fluid levels with transducers--have you looked for some?

I doubt you need to worry too much about what they did--they happened to use that wave, there are a million you can choose from.

Exactly! Do you have any suggestions for me, please?

I am learning AVR, help me!!

gregd99 wrote:

I think that many of the comments above are trying to understand what you are trying to do.... and to understand how well you understand the design requirements.

Sometimes one (we have all done it) optimise some aspect perfectly... only to learn that +/- 20% (100%?) might have been OK. Understanding the details of how and why a system works (or doesn't) lets us all make good design decisions as to what matters more and less.

Do you feel you have a good understanding of the operation and critical aspects of the system you are planning to duplicate?

I have a fair good understanding of the design! Actually, with the code submitted by @Heisen, I succeeded to move from a 9V Pk-Pk to 28V Pk-Pk voltage! I believe I couldn't receive any echo because of the low voltage applied to the transducer by the driving circuit (LC circuit). Today, I will try to connect the amplifier and the transducer and see if I can read the echo! Let me not focus too much on the pulse for now since I have the same voltage peak to peak as the device being studied. Just that the 8 Pulses are not well giving the peak voltage.

The frequency, I shared, are the frequencies I have also identified practically with the transducer that produced a maximum Pk-Pk voltage.

I am learning AVR, help me!!

Who-me wrote:

Techno KG wrote:

The signal, I want to replicate is coming from a CC2540 Bluetooth IC. From the datasheet, the Clock Frequency is 32MHz. I believe we can do the same thing with ESP32.

Yes, if you know what generated the signal, you should be able to carefully capture and measure the timing, to confirm it is 32MHz granular.

The numbers you have in #1 are not quite 32MHz granular, but that's likely measuring and rounding effects.

Then, you can replicate it using a similar PWM block.

What does 32 MHz Granular mean, please?

I am learning AVR, help me!!

Last Edited: Wed. May 18, 2022 - 07:41 AM

Techno KG wrote:

What does 32 MHz Granular mean, please?

If the pulses are generated from a 32MHz PWM, then they should all be integer multiples of 1/32MHz or 31.25ns steps.

That's why the time domain is a better way to define pulses, it is closest to how they are created.

From the code suggested by @Heisen

We can easily observe that we are close to the result we are looking for. But there is some ripple in the signal. The cause can be the longer OFF-Time as well as some noise on the signal, I don't know!

The end result looks for: You see that, the signal at the Output (Bleu Signal) is OFF when the Driving signal is OFF. What can we do to have such a result?

I am learning AVR, help me!!

Who-me wrote:

Techno KG wrote:

What does 32 MHz Granular mean, please?

If the pulses are generated from a 32MHz PWM, then they should all be integer multiples of 1/32MHz or 31.25ns steps.

That's why the time domain is a better way to define pulses, it is closest to how they are created.

I see, thank you! I have check the timer of CC2540, it is actually 32MHz frequency:

I am learning AVR, help me!!

If you want to recreate the signal that produced the scope shot in the opening post then stop thinking in terms of frequency and duty cycle and start thinking in terms of time. You need to load timer registers with the number clock pulses to be high and the number between pulses, so let's just work with integers numbers of clock pulses. The ATmega328P runs at 16MHz. That means one clock pulse is 1/(16MHz) = 1/16us. That's 1/16 of one horizontal division on the scope.

In the photo, ignore the text added showing frequencies and duty cycles; they're wrong. Proof is the fact that the longest period is marked 792KHz and the shortest 226KHz. Higher frequencies have shorter periods and vice versa, so let's just look at the photo and try to tell how many clock cycles long each feature is.

Ok, I already did the hard work. What I did was load the photo into a drawing program that shows the x and y coordinates of whatever pixel you point at. (I used Pinta, but MS Paint would probably work just as well.) I went across and recorded the horizontal position of each vertical division on the scope. I fit a straight line to those numbers and got an equation that returns a time in microseconds given a horizontal position in pixels. I then went across and recorded the position of each transition. I took every measurment along the horizontal division just below the peak in the pulses. That method should compensate for parallax in the photo.

The width of each pulse is about 0.25 us, or 4 clock cycles at 16MHz. There's 16 transitions on the scope with only 7 actual pulses. If we assume there's a pulse hidden at one end or the other of the stream, then we can find 8 periods as shown below. My measurement came up with 1.22 us period for the 5th one while the cursors on the scope show 1.26 us. Take that however you want.

The period in clock cycles is in the first column with the remaining columns showing the corresponding number of clock cycles for different clock frequencies. Notice that at 16MHz the shortest pulse is only about 13 cycles. If the pulse is high for 4 cycles then it's low for 9. I'm not sure when you would have time to change the values in the timer registers.

I included a column for 80MHz because that's how fast the peripheral clock runs in the ESP32. That's an interesting microcontroller because it has a cool peripheral intended to send signals to an IR LED for remote control (RMT.) The way it works is that you put values in an array that say how long (in clock cycles) you want the LED to be on and off for each pulse in the stream. When you tell it to go it spits out the signal. Exactly what you want.

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

Last Edited: Wed. May 18, 2022 - 09:09 AM

Techno KG wrote:

From the code suggested by @Heisen

We can easily observe that we are close to the result we are looking for. But there is some ripple in the signal. The cause can be the longer OFF-Time as well as some noise on the signal, I don't know!

The end result looks for: You see that, the signal at the Output (Bleu Signal) is OFF when the Driving signal is OFF. What can we do to have such a result?

At what point was that lower 'master' waveform driving signal captured ?

If it was the GATE of a FET, you can see it has softer edges than the waveform above, and it is common to soften MOSFET drive often with a series resistor, to reduce the abrupt edges which can cause more ripple.

Ripple can also be reduced with a series R-C damper on the load, at the cost of a litte more power loss.

I used the oscilloscope to measure the time period for each pulse

Hardly! Only in the very crudest sense...you had next to NO accuracy, at least in terms of any precision work.  Ok, you see half a division, maybe 3/4th division, or maybe 5/8ths or even 9/16th  NONE of that is very good.  ...it's simply not precision work.

One percent, which is still barely accurate, means you'd take a block and divide it into 100 slices (assuming 100% is approx one full block)---can you see the block sliced up that fine?

I already mentioned you need to zoom in, or use the dual timebase feature to measure time accurately.  Also this assumes straight edges, not curvy wiggly edges (more uncertainty).

Also if you are measuring all these times, why are you mentioning up frequency at all?   Makes no sense whatsoever & quite misleading.

Again, just because the pulses were generated with this particular time separation doesn't mean you can't use your own separation. It really seems like you are blindly trying to copy things. Who said you need 8 pulses?  How about 4 or 20? Why 8?

Try some of your own experiments--that is the real learning.   You made a rough start on your journey, now it is time to get to work.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Mr Candies, I get your point, but we really don't know what kind of precision is required.

The OP has told us that the signal is fed to a piezo sensor. A short series of irregularly spaced pulses isn't going to excite any resonances (Trust me, I used to design drivers for piezo motors that ran at resonance. I understand what it takes.) So the pulses must be used in some other way. It's measuring depth? Maybe it's measuring time between reflections. Who knows how precisely the signal on the scope needs to be reproduced. The OP will just have to experiment to see what works, but he needs to start somewhere. Hi scope photo might not be good enough, or it might be more than good enough. How could either of us know?

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

What I see is a waveform with 15 different width pulses: some high, some low. So I'd write code to generate that. At this stage I'd even think about doing it with strings of NOPs. Forget timers and other such complications, it all an overhead. At  this time we're in the research phase, we aren't even close to development. Or don't people do it this way any more?

Like that I could start at the beginning and tweak each one individually for resonance (or whatever it is the OP is looking for).

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

I get your point, but we really don't know what kind of precision is required.

The point you are completely missing is, you would zoom in to make nearly any sort of measurement unless you are only interested in crude 10% errors tolerance (that's looking at 1/10 of a block, since the time is nearly 1 block).  He states he measured 792 KHz ---HARDLY...that's roughly 1 part in 1000...it's doubtful he could see things that well defined. How would that look different than 793 or 795 KHz?   Now if he said he measured 0.8 MHz (one significant digit), then it would be a plausible result.

If you tell someone you measured 792 KHz, that implies you were off by no more than approx 1.6 ns

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Wed. May 18, 2022 - 02:32 PM

eugene the jeep wrote:
In the photo, ignore the text added showing frequencies and duty cycles; they're wrong. Proof is the fact that the longest period is marked 792KHz and the shortest 226KHz.

Well spotted !

eugene the jeep wrote:
I included a column for 80MHz because that's how fast the peripheral clock runs in the ESP32. That's an interesting microcontroller because it has a cool peripheral intended to send signals to an IR LED for remote control (RMT.) The way it works is that you put values in an array that say how long (in clock cycles) you want the LED to be on and off for each pulse in the stream. When you tell it to go it spits out the signal. Exactly what you want.

Sounds nifty, what clock speed can that RMT run at ?

These threads can be confusing sometimes. We never seem to know exactly what the OP wants to do, never mind if what they want to do is what they should do. We try to figure out what we have to start with, what we want in the end, and how to get from one to the other. Each of us 'helpers' tend to interpret what the 'asker' is saying differently. We might interpret the data differently. We see different cause and effect. And then we each have our own favorite solution to whatever we've decided the problem is. I'm sure that if we could all meet in a room with a white board, we could discuss the hell out of this and reach some level of consensus before long. But we haven't met, so we're left with varied understandings of the problem.

Here's what I see in this thread. Anyone (especially the OP) should say if they see things differently.

1. Previously, the OP had a system that generated some stimulus (a pulse stream) that resulted in a qualitatively good and useful response.
2. The system that generated the stimulus no longer functions. This means that ...
3. All we have to go on is some photos and videos of a scope screen when the stimulator did work. In those photos the stimulus is shown in yellow and the response is shown in blue.
4. The OP would like to put together something that will reproduce the response in those photos.
5. The OP has expressed that there are two measures of goodness of the response: the height of the peaks (higher = better) and the ringing between peaks (less = better).
6. The only way the OP can hope to achieve the goal of good response is by trying different stimulus to see what happens.
7. It seems to me that a good place to start experimenting is by reproducing the stimulus in the photos as accurately as reasonably possible, with full understanding that what we start out with will likely not be exactly what's in the photo, but we have no other choice but to do the best we can to start out.

To that end, I have attempted to measure the yellow trace in the photo as accurately as I can. Previously I used the photo in post #1, but I went back and performed the same exercise with the bottom photo in post #31 because it looks a little cleaner and is not obscured with the added red lines. Here's what I came up with:

The period is the time from falling edge to falling edge (the last falling edge is not there, so I guess where it might be.)

There are two columns for pulse width because it depends on how you measure. Wide means I took the width at the widest point. Narrow is measured somewhere in the middle. Given finite rise and fall times, we don't know exactly what pulse width we need to try to make to get a high quality response. I'm guessing we want to attempt to produce a pulse that is somewhere between 0.23 us and 0.40 us.

My guess is that the ringing between pulses has more to do with the pulse width than the period between pulses. Likewise, my guess is that peaks of the response has more to do with the period between pulses than the width of individual pulses. Experiment will tell.

In my next post I will offer a suggestion of how to generate the stimulus with a M328P running at 16 MHz and how to vary it to get the best quality response.

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

Who-me wrote:

Sounds nifty, what clock speed can that RMT run at ?

According to the reference manual, the default (and highest) frequency is 80 MHz. I have never used an ESP32, but I once considered try to use the RMT to measure the duty cycles of an incoming stream. I ended up going in a different direction....

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

the project is to measure the level of a liquid inside a given tank using ultrasound. I found a product that does the work with an Embedded cc2540 IC. This MCU drives the Piezoelectric transducer circuit.

he has many options, not really constrained as he thinks

To that end, I have attempted to measure the yellow trace in the photo as accurately as I can.

Let the OP measure...he has the actual waves and can do so much more accurately ...at least he should ballpark match your findings.

We never seem to know exactly what the OP wants to do, never mind if what they want to do is what they should do.

THAT is worth its weight in gold or even AVR chips

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

avrcandies wrote:

To that end, I have attempted to measure the yellow trace in the photo as accurately as I can.

Let the OP measure...he has the actual waves and can do so much more accurately ...at least he should ballpark match your findings.

I might be mistaken, but I don't think he does have the waves, only photos of a scope.

Anyway, I kind of enjoy the process of extracting accurate data from an image. It's fun. You don't want to take that away from me, do you?

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

the project is to measure the level of a liquid inside a given tank using ultrasound.

We want to generate a particular signal to drive the 1 MHz piezoelectric sensor

So, I assume you want to use the ultrasonic transducer that is already present.

I assume you want to use the ultrasonic driver that is already present.

Do they both work, what part of your system is broken?

Are you fixing one system, or trying to design a system to sell many of them?

The missing specification is what is the distance to the liquid you need to measure?

The maximum distance?

The minimum distance?

How accurately do you need to measure it?

To how many decimal places do you need to measure it, and in what units, (meters, mm, micrometers, etc.)?

Range finding is very different from resonance for a scalpel, or for ultrasonic cleaning.

Typically, (I think...), there are two approaches.

One approach is to apply a single, high voltage, impulse to the piezo.

That shocks the crystal and it generates the acoustic pressure wave.

The crystal will ring, but that typically doesn't matter.

The receiver is watching for the single returning impulse, (and the trailing rings).

The other technique is to apply a short burst of sine wave, (although a square wave can be used), at the crystal's resonant frequency.

In this case that would be 8 periods, ("pulses"), with a 1 MHz Sine, (or square), wave.

The first period generates a small amplitude (ultrasonic) pressure wave.

Because of resonance, the second period generates a slightly larger amplitude pressure wave.

The third generates an even larger pressure wave.

etc.

If, for example, the crystal is vibrating maximally on the 4th period, (impulse), then the last 4 or so acoustic pressure waves will be of roughly the same, maximal, amplitude.

So if one looked at the output pressure wave one would see 4 blips of increasing amplitude, then 4 more at the same, (plateaued), amplitude.

That burst of 8 acoustic pressure waves hits the target, (the water surface in this case), and reflects back to the receiver transducer.

That could be the same transducer as the one that generated the signal, or it could be a separate one.

Each approach has its pros and cons.

The receiver looks for the incoming signal.

In this case a 1 MHz signal.

(It was a 1 MHz transducer, and the pulses were at its resonant frequency of 1 MHz).

The narrow band pass filtered received signal then needs to be "detected".

There are, as usual, multiple approaches to doing this.

For a simple "ping", (time of flight), detector, one could use a simple threshold detector for the received signal.

Either the signal is present, or it isn't.

The first couple of blips, received 1 MHz periods, will be of very low amplitude.

At some point along the overall burst of 8 periods of 1 MHz, the transmitted, and received, signal is of sufficient amplitude to trigger the threshold detector.

One could:

Feed the incoming, (BPF'd), signal to the threshold detector

Feed the incoming, (BPF'd), signal through an amplitude detector, (AM demodulator), to get a "dc" signal, and feed that to the threshold detector

Feed the incoming signal to a (very fast) ADC and process the incoming signal in either the time domain or the frequency domain.

(Forget Shannon-Nyquist, one would sample at 20 times, (for example) the fundamental frequency, so sample at 20 MHz!, (ARM, not AVR processing territory!))

The resolution and accuracy of the time of flight measurement is dependent upon the ultrasonic transducer's operating, (resonant), frequency.

One can "miss" the first period of the 8 period burst, or miss the first 2 periods, or miss...

Until both the transmitted signal and the received signal are strong enough to be detected.

Obviously, the variability of detecting the 1st, 2nd, 3rd, 4th, ... period of the transmitted burst is MUCH less with a 1 MHz transducer than it is with a 40 KHz transducer.

With a 25 times shorter period, the 1 MHz transducer has sent its entire 8 period burst before the 40 KHz transducer has even send its first of 8 periods of the bust signal.

Why 8 impulses, periods of the 1 MHz signal?

Because it takes time for the piezo crystal to physically resonant and generate its (best) signal.

By 8 periods at its resonant frequency it should have "ramped up" and sent a few strong acoustic pressure waves.

Too few, and the crystal will never be in full resonance and the transmitted signal will be weaker than it could be.

This impacts the distance, S/N ratio of the received signal, etc.

Too many just overheats the crystal, and doesn't aid the receiver, (assuming it is reasonably well designed).

Ideally one would stimulate the crystal with a sine wave at its resonant frequency.

The square wave just applies energy over a wide (infinite) frequency spectrum, of which only the energy at the primary, resonant frequency contributes to the desired signal generation.

The other energy just generates heat.

It one is unlucky, one of the square wave harmonics could land on a minor resonant frequency, and hence, again, generate more undesired signal, and worsen the receiver's S/N ratio.

(But, a good narrow band pass filter eliminates that "problem").

Finally, since the last 4 pulses, (or so), of the burst are all at maximal amplitude, and easily detectable, one can, (in theory), extrapolate backwards to the start of the signal.

That is actually very clever, but not needed for most applications.

Unfortunately, Murphy rears his head, and the crystal will continue to ring after the last, (8th, in this case), impulse, (or period of a 1 MHz signal), is applied.

So the receiver actually sees a string of (rapidly) decreasing in amplitude pulses after the actual 8 pulses that were sent.

Now, back to the OP's issue.

"Ping" your transducer with 8 periods of 1 MHz sine (or square) wave, and move on with the interesting part of the project, which is the receiver (detector).

You can, (and should), apply a sweep frequency to the transducer to determine its actual resonance frequency.

Perhaps sweep it from 900 MHz to 1100 MHz, or even a wider range.

You can do this with a benchtop signal generator, or with your microcontroller feeding the actual driver.

How accurate you need to be with the driving frequency depends upon the overall needs of the system.

I'm not at home, or I'd post a few photos of some of the ramp up and detected signals, (40 or 60 KHz, not 1 MHz, system).

JC

Last Edited: Thu. May 19, 2022 - 03:23 AM

Adjust/tweak times as needed, don't even need the table-

https://godbolt.org/z/zn6qa6hd3

You will have to account for the pin set/clr instruction also. Start with pulse 1, adjust low/high times until you get what you want, then pulse 2, and so on. Eventually you will get as close as you are going to get with your cpu clock source (1 instruction resolution).

curtvm wrote:

Adjust/tweak times as needed, don't even need the table-

https://godbolt.org/z/zn6qa6hd3

You will have to account for the pin set/clr instruction also. Start with pulse 1, adjust low/high times until you get what you want, then pulse 2, and so on. Eventually you will get as close as you are going to get with your cpu clock source (1 instruction resolution).

I must say, very nice approach. 👍

“Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?” - Brian W. Kernighan
“Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.” - Antoine de Saint-Exupery

As promised, here's my code submission. The OPS's code is Arduino format, so mine takes the same form. I tested it on a Sparkfun Pro Micro with ATmega32U4 and found that it reproduces the known-to-be-good signals in post #31 pretty well.

Essentially this just unrolls the string of transitions. Each instruction to change PORTB takes 2 clock cycles. The remaining time is consumed with NOPs which (obviously) are 1 cycle each. At 16 MHz each clock cycle is 62.5 us.

I had to guess about the time that the pulses are high. From the photos it looks like they are high for somewhere between 4 and 6 cycles. It's difficult to tell because that pin is apparently capacitively loaded, perhaps by the piezo. This code has the high time set to 5 cycles (1 write to PORTB + 3 NOP.) That can be shortened by commenting out a NOP from each section where the pin is high and uncommenting one NOP from each section where the pin is low.

A cursory look at the OP's code suggested that TIMER1 is outputting on PB1. This code doesn't use any timers, but directly writes to PORTB.

I would like to see what kind of response is generated on the OP's system. (I.e.. what does the blue trace look like when fed this yellow trace.) It can be used as a ready to go Arduino sketch, or copy the SendPulses() function into your own code.

#define NOP __asm__ __volatile__ ("nop\n\t")

void SendPulses()
{
/* This routine generates a series of transitions on PB1.
*
* Each transition (PORTB = ...) takes two clock cycles.
*
* Remaining time is filled with NOP. Obviously, 1 clock cycle per NOP
*
* Each clock cycle is 1/16 = 62.5 us
*/
// start of pulse #1
PORTB &= ~_BV(PORTB1); //set PB1 low
NOP; //1
NOP; //2
NOP; //3
NOP; //4
NOP; //5
NOP; //6
NOP; //7
NOP; //8
NOP; //9
NOP; //10
NOP; //11
//NOP; //12
//NOP; //13

PORTB |= _BV(PORTB1); //set PB1 high
NOP; //1
NOP; //2
NOP; //3
//NOP; //4
//NOP; //5

// start of pulse #2
PORTB &= ~_BV(PORTB1); //set PB1 low
NOP; //1
NOP; //2
NOP; //3
NOP; //4
NOP; //5
NOP; //6
NOP; //7
//NOP; //8
//NOP; //9
//NOP; //10
//NOP; //11
//NOP; //12
//NOP; //13

PORTB |= _BV(PORTB1); //set PB1 high
NOP; //1
NOP; //2
NOP; //3
//NOP; //4
//NOP; //5

// start of pulse #3
PORTB &= ~_BV(PORTB1); //set PB1 low
NOP; //1
NOP; //2
NOP; //3
NOP; //4
NOP; //5
NOP; //6
NOP; //7
NOP; //8
NOP; //9
NOP; //10
NOP; //11
//NOP; //12
//NOP; //13

PORTB |= _BV(PORTB1); //set PB1 high
NOP; //1
NOP; //2
NOP; //3
//NOP; //4
//NOP; //5

// start of pulse #4
PORTB &= ~_BV(PORTB1); //set PB1 low
NOP; //1
NOP; //2
NOP; //3
NOP; //4
NOP; //5
NOP; //6
NOP; //7
//NOP; //8
//NOP; //9
//NOP; //10
//NOP; //11
//NOP; //12
//NOP; //13

PORTB |= _BV(PORTB1); //set PB1 high
NOP; //1
NOP; //2
NOP; //3
//NOP; //4
//NOP; //5

// start of pulse #5
PORTB &= ~_BV(PORTB1); //set PB1 low
NOP; //1
NOP; //2
NOP; //3
NOP; //4
NOP; //5
NOP; //6
NOP; //7
NOP; //8
NOP; //9
NOP; //10
NOP; //11
NOP; //12
NOP; //13

PORTB |= _BV(PORTB1); //set PB1 high
NOP; //1
NOP; //2
NOP; //3
//NOP; //4
//NOP; //5

// start of pulse #6
PORTB &= ~_BV(PORTB1); //set PB1 low
NOP; //1
NOP; //2
NOP; //3
NOP; //4
NOP; //5
NOP; //6
NOP; //7
NOP; //8
NOP; //9
NOP; //10
NOP; //11
//NOP; //12
//NOP; //13

PORTB |= _BV(PORTB1); //set PB1 high
NOP; //1
NOP; //2
NOP; //3
//NOP; //4
//NOP; //5

// start of pulse #7
PORTB &= ~_BV(PORTB1); //set PB1 low
NOP; //1
NOP; //2
NOP; //3
NOP; //4
NOP; //5
NOP; //6
NOP; //7
NOP; //8
NOP; //9
NOP; //10
NOP; //11
NOP; //12
//NOP; //13

PORTB |= _BV(PORTB1); //set PB1 high
NOP; //1
NOP; //2
NOP; //3
//NOP; //4
//NOP; //5

// start of pulse #8
PORTB &= ~_BV(PORTB1); //set PB1 low
NOP; //1
NOP; //2
NOP; //3
NOP; //4
NOP; //5
NOP; //6
//NOP; //7
//NOP; //8
//NOP; //9
//NOP; //10
//NOP; //11
//NOP; //12
//NOP; //13

PORTB |= _BV(PORTB1); //set PB1 high
}

void setup()
{
DDRB |= _BV(DDB1);    //set PB1 as output
PORTB |= _BV(PORTB1); //set PB1 high
}

void loop()
{
SendPulses();
delay(1000);
}

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

There is a good chance any general approximation will be fine.

Since, unlike the OP's initial statement, frequencies are not really desired (instead, timed pulses), there is probably a huge latitude in what is allowable; they are probably largely arbitrary (within the general boundaries of what DOCJC mentioned).   It is time for the OP to do some pinging experiments!

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

The Doc beat me to it, but for this app, the 8 pulses most likely all need to be the same period, that is near the resonance of the transducers.  Unless some type of modulation is being used, what for is unknown to me.

one could use the spi, or better the USART in SPI mode to send the pulses at 1MHz.  PWM could be used if modulation is needed, but that is out of the realm for an AVR at that freq.
As Doc said, the sending is the easy part, receiving, detecting and timing the echo is the fun part…

fly over Jim

FF = PI > S.E.T

The two of you both make good suppositions, but I'm trying to work with the evidence. Look at the two photos in post #31. The bottom one was  the input and response of the equipment as it came from the manufacturer. The pulses clearly do not have the same period. Why would the original manufacture do that?

Looking at the last part any scan, the part where the signal stays high, it's clear that the piezo has a first resonance of about 1 MHz. It's odd that the system seems to resonate freely as long as the signal is high, but becomes damped as soon as the signal goes low.

In any case, I think there's more going on here than simply banging at the right frequency to build up resonance.

I'd like to know more details about this device. In the absence of that, I'd like to be able to feed a few different pulse trains into it and see what happens.

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

Last Edited: Thu. May 19, 2022 - 08:45 PM

Looking more closely at all of the photos, it looks like the first resonance of the piezo is around 1MHz. Looking more closely, it's apparent that there's another resonance at around 2.5MHz. That's the one that seems to be excited by the pulses.

The other weird thing is that the pulses start and stop abruptly with the pulse. Looking at the photo from post #31 (old image from when the system worked correctly.) Comparing the input to the output, I can see that the output started at the rising edge of the pulse (but not at the very beginning of the pulse.) But then it ends abruptly some 200ns after the falling edge of the pulse. Makes me wonder.... Is there a MOSFET across the piezo that keeps it shorted when the pulse is high, but 'releases' it when the pulse is low? Is that little jaggie at the start of the pulse there because the pulse is connected to the gate of the MOSFET? Does the pulse not get damped immediately because it takes 200ns for the MOSFET to turn off? (Seems a long time.)

Meanwhile, later photos with the 'emulated' pulses show ringing while the pulses are low. Another observation: in the first photo the input signal is less than 1V, yet in the later photo, with the ringing, it's close to 5V and square edged. What's going on? Is there something else wrong with this equipment?

Not sure what to make of the fact that the pulses are inverted. When 'high' they're close to, or just below 0V. When 'low' they're more negative. Only about -1.5V in the old photos. Exactly where were you probing here?

Brian Fairchild wrote:

It's at this point that we really do need the OP to come back and engage with us. So many questions..........

Last Edited: Thu. May 19, 2022 - 09:52 PM