2

I want generate many 40khz square wave on GPIO pin by simulink but when I try generate more than 10khz is oscillascope not display accurately. I must fix this problem how ? I think supported language on simulink not appropriate with rasp or sample time ...but I not know solve.

I pursuring a project about acoustic levitation, using many ultrasonic sensor to lift the object in the specific medium. I must generate phase array to create a focal point that where can lift object. Ultrasound I using is MA40S4S murata, to it operate I must generate a 40khz square wave. Beside that, to create a phased array is that I must caculate delay time from each ultrasound to focal point. And my main task now, I must generate 25 of 40khz square wave with each wave have a delay time differently as the figure following. Because of caculatation of time delay very complex so I choose matlab to do it and I use matlab with raspberry pi to generate waves, but I only generated 20khz. Finally, I tried using python to programming. but I not sure whether your library can support 25 pin GPIO to I can generate 25 of 40 khz square wave. please help me, my english not good, sympathy for me. enter image description here

3
  • An interesting problem. Have a look at abyz.co.uk/rpi/pigpio/examples.html#Python_wave_PWM_py which shows how to generate PWM of the same frequency but different dutycycles on multiple GPIO. Of course they are all in phase which makes the solution much easier to code. I have a feeling that what you want to do is achievable within the limits of pigpio. Those limits are you can only shift phase in 1µs increments. Yes, I am fairly sure that would work as long as a 1µs phase interval resolution is acceptable. However I'm not sure how many updates per second would be achievable.
    – joan
    Aug 18, 2016 at 12:49
  • Interesting. I was just reading about a reclocker board here: cnx-software.com/2016/09/03/…
    – PaulF8080
    Sep 4, 2016 at 15:05
  • I prefer use Arduino instead to generate signals like this with 100% gurantee. Raspbian is event OS and if something slows the CPU down your PWN may suffer with delays.
    – WillyWonka
    Nov 9, 2016 at 7:58

4 Answers 4

1

I don't know anything about Simulink.

However, my pigpio library will allow you to generate accurate square waves in several ways.

I give Python examples, the same can be done from C or the command line.

  1. hardware clock GPIO
  2. hardware PWM GPIO
  3. Waves for arbitrary GPIO
6
  • Thanks joan vey much. But I want sure rasp can generate a lot of 40khz square wave at the same time accuratly? Maybe language in matlab not compatible with rasp when operate at high frequency
    – Xúc Cảm
    Aug 15, 2016 at 13:48
  • Your pigpio library have be limit about support number GPIO pin (number of output pin) ? I would generate about 25 pulse 40khz.
    – Xúc Cảm
    Aug 16, 2016 at 13:11
  • @XúcCảm You need to edit your question and define what you are trying to achieve with full details. The answer I gave you allows for 25 GPIO.
    – joan
    Aug 16, 2016 at 13:15
  • I be error a indentationerror: unexpected indent with this code: import time import pigpio pi = pigpio.pi() # Connect to local Pi. pi.hardware_clock(4, 40000) # 40 kHz square wave on gpio#4 (clock 0) time.sleep(60) # Wait for 60 seconds. pi.hardware_clock(4, 0) # Clock 0 off. pi.stop() # Disconnect from local Pi.
    – Xúc Cảm
    Aug 17, 2016 at 4:46
  • I fixed all the problem. and code run. But I want generate 40khz pulse to about 20 GPIO pin on raspberry pi 2 mode B. Can your library do it? so i read is that your library only can generate for 4 GPIO pin type B
    – Xúc Cảm
    Aug 17, 2016 at 6:40
0

I want sure rasp can generate a lot of 40khz square wave at the same time accurately

It's not clear what you mean by "a lot" here: As in, the number of consecutive waves, or the pins that can generate waves simultaneously?

If the latter, basic PWM generation on the Pi only has two independent channels, which can be accessed via 4 pins; GPIOs 12 and 18 for channel 0, 13 and 19 for channel 1.

I believe pigpio has a number of other ways of generating pulses by making use of some of the other clocks on the Pi and joan's links should lead you to examples of that. With regard to the basic hardware mentioned in the last paragraph, here's a simple C program using libbcm2835 to generate a 40 khz pulse. This should work on all models.1 Part of my point is whatever implementation simulink uses, it probably only makes use of these two basic channels.

Note most of the code is actually OS signal handling so you can start it, let it run in the foreground, then stop it with ctrl-c and have the pin reset as an input. Actually turning on the wave in hardware only take a few lines and the process then just sleeps indefinitely as it does not have to do anything except wait for SIGTERM.

#include <bcm2835.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// Compile --std=gnu99 for sigaction.

// 19200000 / 10 / 48 = 40000 Hz
#define CLOCK_DIVISOR 10
#define PWM_RANGE 48
#define PWM_PIN 18
// For pins 13 or 19, use channel 1.
#define PWM_CHANNEL 0
// For pins 12 or 13, use ALT0.
#define PWM_ALT BCM2835_GPIO_FSEL_ALT5


void sigHandler (int sig)
{
    fprintf(stderr, "Stopped by signal %d.\n", sig);
    bcm2835_pwm_set_mode(PWM_CHANNEL, 0, 0);
    bcm2835_gpio_clr(PWM_PIN);
    bcm2835_gpio_fsel(PWM_PIN, BCM2835_GPIO_FSEL_INPT);
    bcm2835_close();
    exit(0);
}


void setSigHandler ()
{
    int sigs[] = { SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGABRT },
        num_sigs = sizeof(sigs) / sizeof(int);

    struct sigaction sigact;
    memset(&sigact, 0, sizeof(sigact));
    sigact.sa_handler = sigHandler;
    for (int i = 0; i < num_sigs; i++) {
        if (sigaction(sigs[i], &sigact, NULL) == -1) {
            fprintf(stderr, "sigaction(%d) fail:\n", sigs[i]);
            perror(NULL);
        }
    }
}


int main (void)
{
    if (!bcm2835_init()) {
        fprintf(stderr, "Failed to initialize.\n");
        return 1;
    }

    setSigHandler();

    bcm2835_pwm_set_clock(CLOCK_DIVISOR);
    bcm2835_pwm_set_mode(PWM_CHANNEL, 1, 1);
    bcm2835_pwm_set_range(PWM_CHANNEL, PWM_RANGE);
    bcm2835_gpio_fsel(PWM_PIN, PWM_ALT);
    bcm2835_pwm_set_data(PWM_CHANNEL, PWM_RANGE / 2);

    while (1) sleep (60);

    return 0;
}

So to compile that:

gcc --std=gnu99 square_wave.c -lbcm2835

Here's 1 ms of output sampled with a logic analyzer working at 12 Mhz:

-

Looks like a perfect 40 kHz square wave. However, again, you can only generate 2 of these independently using the basic hardware, which you can access via 4 pins on the 40-pin models (there's only 1 explicit PWM pin on the older 26-pin models).


1. When I first posted this I said it did not work on the Pi 3, although that might have been been my fritzy logic analyzer; I've since had no problems generating servo style pulses on all four pins with libbcm2835 on the Pi 3, which are only 50 Hz but rely on microsecond scale differences in width (I use a divisor of 8 and a range of 48000 for that).

4
  • I using raspberry pi 2 mode B. If I use this library, I only generate 40khz pulse for 4 GPIO pin. All right?
    – Xúc Cảm
    Aug 17, 2016 at 6:36
  • Yeah, but only two of those pulses can be independently timed, and the channels are tied to specific pins as per the second paragraph. I'm not recommending this library over anything else, and any pi-specific library which implements PWM should offer at least this, because those are the basic constraints of the hardware; libbcm2835 is minimal in the sense that's all it offers. I believe one thing pigpio can do is make use of at least one more hardware clock (the PCM one, meaning you would lose audio), and possibly it can associate the pulses with more pins as well.
    – goldilocks
    Aug 17, 2016 at 12:53
  • You'd have to look through joan's links to find out more about that. But I don't believe you can reliably create a 40 kHz pulse purely in software on a multitasking OS, so one way or another, the number of independent pulses you can generate is limited to the access to timing via hardware and there aren't independent per pin pathways for that. Further, if you wanted to, e.g., have two waves offset by exactly 5 µs, or inverted, etc., arranging that may or (more likely, but it is just a guess) may not be possible.
    – goldilocks
    Aug 17, 2016 at 12:54
  • Note that if you want to generate umpteen 40 kHz waves that are perfectly synchronized you don't need more than one pin -- then just attach that to a breadboard and you can break it out effectively to probably at least a dozen inputs (again, just a guess, presuming they sink <= 1 mA, I don't know much about that topic). As joan says you should really be clearer about exactly what you need to do rather than forcing people to play guessing games with you, etc.
    – goldilocks
    Aug 17, 2016 at 13:02
0

You should use DMA to access the GPIO. Then you'll be able to map them all, and with hardware write your 1 and 0. It won't be CPU intensive and you'll be able to make it almost as fast as you'd like it.

Here you might find some really interesting hints : https://github.com/richardghirst/PiBits/tree/master/ServoBlaster

YCN-

-1

https://www.instructables.com/id/Ultrasonic-Array/ This one uses an Ardunio Mega, you can get the board for 8$. It also provides a driver to amplify the signals and software to focus and perform other operations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.