ultrasonic phased array

Hello :slight_smile:
I have the following code for Arduino mega to output 40 kHz square waves at the analog pins. I need to apply specific phase delays for the signals at each pin though and am struggling to find out how to do this. Any help would be appreciated.
Thanks!

byte TP = 0b10101010; // Every other port receives the inverted signal

void setup() {

DDRF = 0b11111111; // Set all analog ports to be outputs
DDRK = 0b11111111; // Set all analog ports to be outputs
// Initialize Timer1

noInterrupts(); // Disable interrupts

TCCR1A = 0;

TCCR1B = 0;

TCNT1 = 0;

OCR1A = 200; // Set compare register (16MHz / 200 = 80kHz square wave -> 40kHz full wave)

TCCR1B |= (1 << WGM12); // CTC mode

TCCR1B |= (1 << CS10); // Set prescaler to 1 ==> no prescaling

TIMSK1 |= (1 << OCIE1A); // Enable compare timer interrupt

interrupts(); // Enable interrupts

}

ISR(TIMER1_COMPA_vect) {

PORTF = TP; // Send the value of TP to the outputs
PORTK = TP;
TP = ~TP; // Invert TP for the next run

}

void loop() {

// Nothing left to do here :)

}

Hello marionboynton,
Welcome to the forum.

When you read 'how to use this forum - please read', what did it say under item #7?

Please go back and modify your post accordingly, you are more likely to get helpful, friendly answers that way.

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html .
Then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Thanks.. Tom.. :slight_smile:

What's your specific problem?

Each timer can have a different phase, but each timer controls 2 or 3 analog pins typically, so certain pins have
to stay in phase (although they can be in antiphase on the same timer). Reading the hardware timers sections of the ATmega2560 will explain all this in detail.

What's the intended phase shift?

@marionboynton

OTHER POST DELETED

Do NOT cross post as it wastes peoples time and effort to help you.

Could you please READ THIS to get the best out of the forum before adding any further posts.

Bob.

Use the PINx registers to toggle outputs.

// These are the bit masks for each pair of pins in PORTF and PORTK
const uint16_t Channels[8] = {0xC000U, 0x3000U, 0x0C00U, 0x0300U, 0x00C0U, 0x0030U, 0x000CU, 0x0003U};


// In each of the 32 phases, OR together the channels that toggle at that phase offset.
// The actual phase offsets will depend on processor timing so I just put the 8 channels 
// in randomly.
const uint16_t Phases[32] =
{
  Channels[0] | Channels[4], 0, 0, Channels[1] | Channels[5], 0, 0, 0, 0,
  0, Channels[2], Channels[3], 0, 0, 0, 0, 0,
  0, 0, Channels[6] | Channels[7], 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0, 0
};

void setup()
{
  DDRF = 0b11111111; // Set all analog ports to be outputs
  DDRK = 0b11111111; // Set all analog ports to be outputs
  PORTF = 0b10101010;
  PORTK = 0b10101010;


  // Initialize Timer1


  noInterrupts(); // Disable interrupts


  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;


  OCR1A = 200; // Set compare register (16MHz / 200 = 80kHz square wave -> 40kHz full wave)


  TCCR1B |= (1 << WGM12); // CTC mode
  TCCR1B |= (1 << CS10); // Set prescaler to 1 ==> no prescaling
  TIMSK1 |= (1 << OCIE1A); // Enable compare timer interrupt


  interrupts(); // Enable interrupts
}


ISR(TIMER1_COMPA_vect)
{
  // Writing bits to the PINx register will toggle the output bits.


  // Unroll the loop so everything will be constants.  This should allow the compiler to 
  // optimize each line into a single instruction.  You can add NOP instructions between 
  // phase offsets to increase the offsets.  As long as the ISR doesn't take longer than a 
  // few microseconds it should be OK.


  PINF = Phases[0] >> 8;
  PINK = Phases[0];
  
  PINF = Phases[1] >> 8;
  PINK = Phases[1];
  
  PINF = Phases[2] >> 8;
  PINK = Phases[2];
  
  PINF = Phases[3] >> 8;
  PINK = Phases[3];
  
  PINF = Phases[4] >> 8;
  PINK = Phases[4];
  
  PINF = Phases[5] >> 8;
  PINK = Phases[5];
  
  PINF = Phases[6] >> 8;
  PINK = Phases[6];
  
  PINF = Phases[7] >> 8;
  PINK = Phases[7];
  
  PINF = Phases[8] >> 8;
  PINK = Phases[8];
  
  PINF = Phases[9] >> 8;
  PINK = Phases[9];
  
  PINF = Phases[10] >> 8;
  PINK = Phases[10];
  
  PINF = Phases[11] >> 8;
  PINK = Phases[11];
  
  PINF = Phases[12] >> 8;
  PINK = Phases[12];
  
  PINF = Phases[13] >> 8;
  PINK = Phases[13];
  
  PINF = Phases[14] >> 8;
  PINK = Phases[14];
  
  PINF = Phases[15] >> 8;
  PINK = Phases[15];
  
  PINF = Phases[16] >> 8;
  PINK = Phases[16];
  
  PINF = Phases[17] >> 8;
  PINK = Phases[17];
  
  PINF = Phases[18] >> 8;
  PINK = Phases[18];
  
  PINF = Phases[19] >> 8;
  PINK = Phases[19];
  
  PINF = Phases[20] >> 8;
  PINK = Phases[20];
  
  PINF = Phases[21] >> 8;
  PINK = Phases[21];
  
  PINF = Phases[22] >> 8;
  PINK = Phases[22];
  
  PINF = Phases[23] >> 8;
  PINK = Phases[23];
  
  PINF = Phases[24] >> 8;
  PINK = Phases[24];
  
  PINF = Phases[25] >> 8;
  PINK = Phases[25];
  
  PINF = Phases[26] >> 8;
  PINK = Phases[26];
  
  PINF = Phases[27] >> 8;
  PINK = Phases[27];
  
  PINF = Phases[28] >> 8;
  PINK = Phases[28];
  
  PINF = Phases[29] >> 8;
  PINK = Phases[29];
  
  PINF = Phases[30] >> 8;
  PINK = Phases[30];
  
  PINF = Phases[31] >> 8;
  PINK = Phases[31];
}


void loop()
{
  // Nothing left to do here :)
}

I need to apply specific phase delays for the signals at each pin

Please state the specific delays required and how many pins will be controlled.

There are only 400 processor clock cycles (at 16 MHz) in one cycle of 40 kHz, so the standard AVR-based Arduinos may not be a good choice.

Hi,
What is the application that you need to apply phase shifts?

Thanks.. Tom.. :slight_smile:

How long can zombies continue living? :wink:

hi Tom :slight_smile: the phase shifts are so that when emitting the square wave signals from several transducers I can focus the resulting beam in a region of constructive interference.

Hi,
Squarewaves won't produce an interference pattern, sinewaves will.

There will be many regions of constructive interference, are you trying to make an ultrasonic cannon?
What are you using as ultrasonic transmitters?
How much phase/time shift are you trying to get?

Tom.. :slight_smile:

the square waves are to power the ultrasonic transmitters which resultantly produce ultrasound (longitudinal sin) waves.

Wouldn't just arranging the transducers in a circle cause them to constructively interfere along the central axis? That would be much easier than a phased array if size is not an issue.

Consider which minor phase shifts are required for generating the intended focus, and which phase shifts can be provided by a 16MHz controller. I'd recommend a much faster controller for your project. But for now you can find out how to code the generation of multiple square waves with time shifts.

the phase shifts are so that when emitting the square wave signals from several transducers I can focus the resulting beam in a region of constructive interference.

Yes, that is the basic theory behind common practice, except of course, the transducers are assumed to emit sine waves.

If you can't provide quantitative answers to the questions we are asking, this project may be too difficult for you.

The important details of focusing by ultrasonic phased arrays are discussed in this excellent and comprehensive tutorial: Olympus Phased Array Tutorial, Learn About Ultrasonic Phased Array

Multiple (acoustic) waves can accumulate in certain places, and extinct each other to some degree somewhere else.

Likewise a single source can be recorded in a number of locations, so that the required phase shift for all transmitters in those locations can be determined. This should work for all waveforms, be sine or square or something distorted in between these, provided equal speed of sound.

after spending torturous hours trying to learn timers and interrupts I think I got it in a much simpler way! :smiley:

#include <util/delay.h>

void setup() {
DDRA = 0b11111111; //outputs
DDRB = 0b11111111;
DDRC = 0b11111111;
}

void loop() {
noInterrupts();

PORTA = 0b10101010; 
PORTC = 0b10101001;
_delay_us(2);
PORTC = 0b10101010; 
_delay_us(10.5);
PORTA = 0b01010101;
PORTC = 0b01010110; 
_delay_us(2);
PORTC = 0b01010101; 
_delay_us(10.5);
interrupts();

}
1 Like