сдвиг сигнала по времени

nikmih
Offline
Зарегистрирован: 02.06.2014

аналоговый сигнал. от 0 до 2 вольт синусоидальной формы. как организовать задержку выходного сигнала относительно входного по времени?

ZagZag
Offline
Зарегистрирован: 08.05.2014

Как часто происходит опрос порта? И на какой период по времени нужно сдвигать?

Есть мысль использовать для этого буффер в оперативке, но ее не так много. Возможно придется использовать внешнюю RAM-память. Типа http://www.microchip.com/pagehandler/en-us/products/memory/serialSRAM/home.html

Или высчитывать период сигнала и генерировать новый на его основе. Лучше для этого использовать предварительно сгенерированную таблицу значений синуса.

nikmih
Offline
Зарегистрирован: 02.06.2014

хотелось бы непрерывный сигнал.

сдвиг до 3х секунд.

ZagZag
Offline
Зарегистрирован: 08.05.2014

Так о какой частоте идет речь? 50Гц или 16МГц (ардуинка на большее не способна)?

Для 50Гц нужно делать 50 выборок в секунду с задержкой 20мс. Размер буфера для 3х секунд 50 * 3 = 150 байт.

Размер буфера для непрерывной записи 16МГц даже считать боюсь :)

nikmih
Offline
Зарегистрирован: 02.06.2014

всё понял. тогда можно пример работы с буфером?

ZagZag
Offline
Зарегистрирован: 08.05.2014

Кода нет. Сейчас на работе.

Принцип такой:

int pos = 0; // Текущая позиция в буфере

bool full = false; // Флаг "буфер полон"

byte buf[150];

do_process() {

  buf[pos] = analogRead(...);

  if (full) analogWrite(..., buf[ ((pos == 0) ? sizeof(buf) : pos - 1) ])

  pos++;

  if (pos > sizeof(buf)) {

    pos = 0;

    full = true;

  }

  delay(20); // Какая-то задержка, придется поэкспериментировать

}

nikmih
Offline
Зарегистрирован: 02.06.2014

т.е. нужно организвать очередь и через определённые промежутки времени записывать и считывать из неё?

tmr
Offline
Зарегистрирован: 19.05.2014

nikmih, опишите задачу подробнее - что за сигнал на входе, его источник и хар-ки и что вы хотите реализовать. На всякий случай уточню, что на выходе вы не получите синусоиду никак, программно можно только ШИМом имитировать аналоговый сигнал.

nikmih
Offline
Зарегистрирован: 02.06.2014

есть аналоговый датчик. на выходе что то похожее на синусоиду, от 0 до 2 Вольт. хочу собрать программный преобразователь. сдиг по времени + сжатие/увеличение по амплитуде.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

nikmih пишет:

есть аналоговый датчик. на выходе что то похожее на синусоиду, от 0 до 2 Вольт. хочу собрать программный преобразователь. сдиг по времени + сжатие/увеличение по амплитуде.

Что-то похожее на синусоиду.... Амплитуду - уже знаем.... А период или частота ЭТОГО сигнала - какая ?!!!!!

1 - оцифровать сигнал

2 - с заданной задержкой выдать на ЦАП

Но чтобы оцифровать нормально - тов. Котельников хотел бы знать частоту ЭТОГО сигнала !!!!!!!!!!!!!!!!!

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

10 бит АЦП - достаточно для оцифровки по амплитуде.... А вот частота оцифровки должна быть >=  2 х F сигнала....

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

одно значение амплитуды с 10-АЦП = 4 байта

записать амплитуду каждые 0,01 секунды в течении 3-ёх секунд = 100 отсчётов

Буфер = 400 байт

 

одно значение амплитуды с 10-АЦП = 4 байта

записать амплитуду каждые 0,005 секунды в течении 3-ёх секунд = 200 отсчётов

Буфер = 800 байт

Играясь с  разрядностью АЦП и временем квантования - можно выбрать приемлемый размер буфера....

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

ой-ой-ой !!!!!! за ТРИ секунды - ВСЕ вычисления - в три раза больше !!!!!! :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

ZagZag пишет:

Так о какой частоте идет речь? 50Гц или 16МГц (ардуинка на большее не способна)?

Для 50Гц нужно делать 50 выборок в секунду с задержкой 20мс. Размер буфера для 3х секунд 50 * 3 = 150 байт.

Размер буфера для непрерывной записи 16МГц даже считать боюсь :)

Для 50Гц нужно делать 100 выборок в секунду с задержкой 10мс. Размер буфера для 3х секунд 100 * 3 = 300 байт. :) 

В области цифровой обработки сигналов, Теоре́ма Коте́льникова (в англоязычной литературе — теорема Найквиста — Шеннона, или теорема отсчётов) связываетаналоговые и дискретные сигналы и гласит, что, если аналоговый сигнал x(t)\; имеет конечный (ограниченный по ширине) спектр, то он может быть восстановлен однозначно и без потерь по своим отсчётам, взятым с частотой, большей или равной удвоенной верхней частоте f_c\;:

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

SU-27-16 пишет:

одно значение амплитуды с 10-АЦП = 4 байта

одно значение амплитуды с 10-АЦП = 2 -ДВА- байта !!!!!!!!!!!!!!!!!!!! блииииииииииииин....

nikmih
Offline
Зарегистрирован: 02.06.2014

сам же спрашивал - сам и отвечаю :)

вот что получилось:

int analogReadPin = A0;
int analogWritePin = A1;

const int maxCountValues = 300;
byte analogReadPinValue = 0;

byte values[maxCountValues];
int posWriteToPin = 0;
int posReadFromPin = 0;

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

void loop () {

  analogReadPinValue = map(analogRead(analogReadPin), 0, 1023, 0, 255);  
  values[posReadFromPin] = analogReadPinValue;

  Serial.print("Read ");
  Serial.print(posReadFromPin);
  Serial.print(" ");
  Serial.println(values[posReadFromPin]);  

  posReadFromPin++;

  if (posReadFromPin > maxCountValues-1) {
     posReadFromPin = 0;
  }
  
  
  
  if (millis()>300) {

    analogWrite(analogWritePin, values[posWriteToPin]);      
    
    Serial.print("Write ");
    Serial.print(posWriteToPin);
    Serial.print(" ");
    Serial.println(values[posWriteToPin]);  

    posWriteToPin++;
    
    if (posWriteToPin > maxCountValues-1) {
     posWriteToPin = 0;
    }
  
  }
    

  delay(50);


}

 

toly
Offline
Зарегистрирован: 17.05.2014

Все замечательно, но только проблема в том, что analogWrite на самом деле не дает настоящий аналоговый уровень на выходе, а только лишь ШИМ. Чтобы получить нормальный аналоговый сигнал, вам нужен внешний ЦАП.

ZagZag
Offline
Зарегистрирован: 08.05.2014

дроссель + конденсатор

nikmih
Offline
Зарегистрирован: 02.06.2014

поделитесь схемкой.

toly
Offline
Зарегистрирован: 17.05.2014

дроссель+конденсатор тоже вариант, но тут все будет зависеть от нужного частотного диаппазона и нужной точности...лучше ЦАП, так можно будет и все 10 разрядов сохранить

ZagZag
Offline
Зарегистрирован: 08.05.2014

Вообще, советуют RC-связку, а не дроссель. Она проще, но сглаживает не очень хорошо.

http://easyelectronics.ru/avr-uchebnyj-kurs-ispolzovanie-shim.html

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

Можно построить ЦАП на ногах Ардуино... 8 ног - на выход, 16 резисторов = 8-ми разрядный ЦАП.

Как сглаживать и чем - зависит от частоты оцифрованного сигнала, типа датчика ( что измеряем ).

А зачем задерживать сигнал ? Не лучше ли определить СОБЫТИЕ для входного сигнала и задержать ДЕЙСТВИЕ по нему ?

Задерживать сигнал и сравнивать его с оригиналом - СДЦ ( селекция движущихся целей в радиолокации ), эффект Допплера и др.

У Вас-то - какая задача ? Датчик ЧЕГО ? Задержанный сигнал как используется ?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

toly пишет:

дроссель+конденсатор тоже вариант, но тут все будет зависеть от нужного частотного диаппазона и нужной точности...лучше ЦАП, так можно будет и все 10 разрядов сохранить

дааааа :) после ЦАПа и сглаживать не надо будет, если частоту дискретизации выбрать максимальной ( по возможности )

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

сигнал - АЦП - задержка - ЦАП = проще чем

>>>>>>>

сигнал - АЦП - задержка - ШИМ - сглаживание

 

....есть ещё преобразование Фурье   :)-

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

"..........гласит, что, если аналоговый сигнал x(t)\; имеет конечный (ограниченный по ширине) спектр, то он может быть восстановлен однозначно и без потерь..........." - БЕЗ ПОТЕРЬ !!!

т.е. - не надо сглаживать !

nikmih
Offline
Зарегистрирован: 02.06.2014

небольшие исправления в коде:

 

int analogReadPin = A0;
int analogWritePin = 11;

void setup () {
pinMode(analogReadPin, INPUT);
pinMode(analogWritePin, OUTPUT);
}

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
int analogReadPin = A0;            // датчик
//int analogWritePin = A1;
const int maxCountValues = 300;          // количество отсчётов
//byte analogReadPinValue = 0;
byte analogReadPinValue;           // значение с датчика
byte values[ maxCountValues ];     // буфер значений с датчика
int N;                             // индекс буфера значений с датчика
boolean Out;
//************************************************************************************************************
void setup ( )
{
  pinMode( analogReadPin , INPUT );        // вход
  digitalWrite( analogReadPin , HIGH );    // подтяжка
  DDRB = DDRB | B00111111;                 // пины 8, 9, 10, 11, 12, 13 - выходы
  Out = false;
  N = 0;

}
//************************************************************************************************************
void loop( ) 
{
  if ( Out )
    {
      PORTB = values[ N ];               // вывод задержанного сигнала
    }
    
  analogReadPinValue = map( analogRead(analogReadPin), 0, 1023, 0, 63 );  // приведение сигнала к 6 битам
  values[ N ] = analogReadPinValue;                                       // запись в буфер
  if ( N > maxCountValues - 1 )          // если буфер заполнен
    {
      N = 0;                             // индекс в начало буфера
      Out = true;                        // разрешить вывод задержанного сигнала
    }
    
  N++;
    
  delay( 50 );       // вместе с maxCountValues определяет время задержки сигнала, примерно 50 х 300 = 15000 mS
}

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

логика

- запись в буфер трёхсот отсчётов

- разрешение формировать выходной сигнал

- вывод 0-го значения датчика, запись в буфер текущего значения

- вывод 1-го значения датчика, запись в буфер текущего значения

- вывод 2-го значения датчика, запись в буфер текущего значения

...

- вывод 299-го значения датчика, запись в буфер текущего значения

и т.д.

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

после строки 14 нужно добавить PORTB = 0; - чтобы на первые 1,5 секунды на выходе ЦАПа было = 0 V, потом напряжение на выходе ЦАПа будет изменяться в диапазоне 0....5 V.