RPi GPIO как высокоскоростной прямоугольный генератор

Я пытаюсь заставить RPi генерировать высокоскоростную квадратную волну через свой вывод GPIO.

Мой код, управляющий выходом GPIO, основан на этой статье

Существенной частью моего кода является следующее:

speed = 1000000; // 1 MHz, or 0.5 MHz anyway (just notice the order of MHz)
s2us = 1000000; // second to microsecond
while(1){
    GPIO_SET = 1<<7; // set GPIO 07 HIGH
    usleep(1/speed * s2us); // sleep for 1 us
    GPIO_CLR = 1<<7; // set GPIO 07  LOW
    usleep(1/speed * s2us); // sleep for 1 us
}

Когда я запускаю свой код, он показывает квадратную волну с периодом 4,2 мс, что означает около 240 Гц. Это не допустимая ошибка с порядка сотен Гц и МГц.

Я искал эту проблему и нашел, что usleep, nanosleep не может работать должным образом, если время сна слишком короткое, так как какое-то планирование системы Linux. Но я не имею идеи решить эту проблему. Некоторые предлагают использовать delay вместо sleep но я не уверен, что это сработает или нет.

Я использую RPi модель B rev 2.0 и Raspbina wheezy 2014. Свежие установки и носки установлены.

4 голоса | спросил Jeon 30 J0000006Europe/Moscow 2014, 08:54:42

4 ответа


8

Моя библиотека pigpio позволит вам генерировать повторяющиеся формы сигналов с разрешением микросекунд. Если вам нужно меньше микросекунд, вам нужно найти другое решение.

Python

 #!/usr/bin/env python

import time

import pigpio

GPIO=4

square = []

#                          ON       OFF    MICROS
square.append(pigpio.pulse(1<<GPIO, 0,       4))
square.append(pigpio.pulse(0,       1<<GPIO, 4))

pi = pigpio.pi() # connect to local Pi

pi.set_mode(GPIO, pigpio.OUTPUT)

pi.wave_add_generic(square)

wid = pi.wave_create()

if wid >= 0:
   pi.wave_send_repeat(wid)
   time.sleep(60)
   pi.wave_tx_stop()
   pi.wave_delete(wid)

pi.stop()

С

 #include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>

#include <pigpio.h>

#define GPIO 4
#define ON   10
#define OFF  10

static int gpio = GPIO;
static int on   = ON;
static int off  = OFF;

gpioPulse_t pulse[2];

void fatal(char *fmt, ...)
{
   char buf[256];
   va_list ap;

   va_start(ap, fmt);
   vsnprintf(buf, sizeof(buf), fmt, ap);
   va_end(ap);

   fprintf(stderr, "%s\n", buf);

   exit(EXIT_FAILURE);
}

void usage()
{
   fprintf(stderr, "\n" \
      "Usage: sudo ./square [OPTION] ...\n" \
      "   -f value, off micros, 1- (%d)\n" \
      "   -g value, gpio, 0-31     (%d)\n" \
      "   -n value, on micros, 1-  (%d)\n" \
      "EXAMPLE\n" \
      "sudo ./square -g 23\n" \
      "  Generate square wave on gpio 23.\n" \
   "\n", OFF, GPIO, ON);
}

static void initOpts(int argc, char *argv[])
{
   int i, opt;

   while ((opt = getopt(argc, argv, "f:g:n:")) != -1)
   {
      i = -1;

      switch (opt)
      {
         case 'f':
            i = atoi(optarg);
            if (i >= 1) off = i;
            else fatal("invalid -f option (%d)", i);
            break;

         case 'g':
            i = atoi(optarg);
            if ((i >= 1) && (i <= 31)) gpio = i;
            else fatal("invalid -g option (%d)", i);
            break;

         case 'n':
            i = atoi(optarg);
            if (i >= 1) on = i;
            else fatal("invalid -n option (%d)", i);
            break;

         default: /* '?' */
            usage();
            exit(EXIT_FAILURE);
        }
    }
}

int main(int argc, char *argv[])
{
   int wid;

   initOpts(argc, argv);

   printf("gpio #%d, on %dus, off %dus\n", gpio, on, off);

   if (gpioInitialise()<0) return -1;

   gpioSetMode(gpio, PI_OUTPUT);

   pulse[0].gpioOn = (1<<gpio);
   pulse[0].gpioOff = 0;
   pulse[0].usDelay = on;

   pulse[1].gpioOn = 0;
   pulse[1].gpioOff = (1<<gpio);
   pulse[1].usDelay = off;

   gpioWaveClear();

   gpioWaveAddGeneric(2, pulse);

   wid = gpioWaveCreate();

   if (wid >= 0)
   {
      gpioWaveTxSend(wid, PI_WAVE_MODE_REPEAT);

      while (1) sleep(1);
   }

   gpioTerminate();
}
ответил joan 30 J0000006Europe/Moscow 2014, 10:01:06
1

Мне удалось создать выходной сигнал квадратной волны 1us на выводах GPIO, используя операционную систему ChibiOS в реальном времени ( http://chibios.sourceforge.net/html/index.html ). Вот статья, которая ссылается на драйверы BCM2835 http://www.stevebate.net/chibios -rpi /GettingStarted.html

Следуйте инструкциям по установке ОС, затем проверьте папку для управления GPIO.

ответил Hunter Akins 14 AM00000030000000031 2017, 03:30:00
0

То, что вы пытаетесь сделать, невозможно использовать в Linux, потому что это не операционная ОС.
Это не просто проблема с процедурами задержки.

Попробуйте свой код, опустив вызовы usleep, которые могут дать вам представление о максимальной частоте, но даже здесь вы найдете довольно длинные и непредсказуемые задержки из-за обработки прерываний.

Невозможно установить аппаратное обеспечение Pi для создания прямоугольной волны, но для этого требуется совершенно другой подход.

ответил Milliways 30 J0000006Europe/Moscow 2014, 09:47:58
0

Linux не является оперативной системой реального времени, поэтому вы не можете ожидать, что время ожидания будет точным. Это будет неточно, из-за чего вы НЕ получите устойчивую мелодию, вместо этого мелодия будет колебаться по частоте. Если вы попытаетесь сделать то же самое в микроконтроллере (например, arduino), частота не будет колебаться. Вы можете использовать этот фрагмент, чтобы получить звуковой сигнал, отрегулировав параметры синхронизации. Но вы не можете делать красивые мелодии: (.

Чтобы создать прямоугольную волну на выводе GPIO,

def beep(repeat):
   for i in range(0, repeat):
      for pulse in range(60):  # square wave loop
         GPIO.output(7, True)
         time.sleep(0.001)     # high for .001 sec
         GPIO.output(7, False)      
         time.sleep(0.001)     # low for .001 sec
      time.sleep(0.02)         # add a pause between each cycle
beep(4)
ответил Anum Sheraz 9 Mayam18 2018, 00:35:08

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132