Выжимаем максимум. USB осциллограф на Arduino

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015
Прошу вашему вниманию самый простой осциллограф на Aduino.
Удалось достичь максимальной частоты которую позволяет АЦП контроллера.
20kHz выглядят так:
 
 
Программа: https://yadi.sk/d/ww1kQopXm8LA2
 
 
Схема:
 
Прошивка:
 
//Осциллограф  ©RasyakRoman

#include <CyberLib.h>

unsigned long currentTime;
unsigned long loopTime;

byte N = 0;
byte Rb = 255;
uint8_t MyBuff[255];

void setup()
{
  UART_Init(256000);
  ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (0 << ADIF) | (1 << ADIE) | (0 << ADPS2) | (1 << ADPS1) | (0 << ADPS0);
  ADMUX =  (0 << REFS1) | (0 << REFS0) | (1 << ADLAR)  | (0 << MUX3) | (0 << MUX2)  | (0 << MUX1)  | (0 << MUX0) ;
}

void loop()
{

  currentTime = millis();
  if (currentTime >= (loopTime +100))  // сравниваем текущий таймер с переменной loopTime + 1 секунда
  {
    ADCSRA &= ~(1 << ADIE); //Выключить
    UART_SendByte(15); UART_SendByte(0); UART_SendByte(15);
    UART_SendArray(MyBuff, 255);
    UART_SendByte(OCR1A); //Не используются
    UART_SendByte(OCR1B); //Не используются  
    UART_SendByte(N);  //Начальная точка
    UART_SendByte(1); UART_SendByte(15);UART_SendByte(1);
    ADCSRA |= (1 << ADIE); // Включить прерывание
    loopTime = currentTime;
  } 
  if   (UART_ReadByte(Rb))     {
    ADCSRA = (ADCSRA >> 3) << 3 | Rb ;
  };

}

ISR(ADC_vect)
{
  MyBuff[N] =  ADCH;
  N++;
}

 

 

jack0023
Offline
Зарегистрирован: 11.07.2015

На UNO будет работать?

а то этот http://compcar.ru/forum/showthread.php?t=4457 только на NANO работает и то только с чипом FTDI

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Работает с обычным китайским NANO и не вижу причин не работать на UNO.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

jack0023 пишет:

На UNO будет работать?

Без разницы - на UNO и NANO одинаковые микроконтроллеры стоят. 

jack0023 пишет:

а то этот http://compcar.ru/forum/showthread.php?t=4457 только на NANO работает и то только с чипом FTDI

Не может такого быть. Опять же - одинаковые микроконтроллеры. И с любым USB-UART чипом должен работать (если он исправный конечно).

Maverik
Offline
Зарегистрирован: 12.09.2012

просто на carduino барыги админят, поэтому та тема начинается со ссылки на их магазин, где наны по 1 тыс. рублей за штуку.  ну и естественно всё у них работает "только на таких ардуинах и больше ни на каких".

на самом деле китайские ардуины совместимы с самыми супер-пупер брендовыми с вероятностью 99.99% и тип уарта ни на что не влияет.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Забыл на схеме добавить один проводок.

В строке:

if (currentTime >= (loopTime +100))

Можно изменить частоту выборок. В представленом варианте производится 10 выборок в секунду. Можно поставить больше.

Обяснение по интерфейсу:

"Open" - открывает порт.

"Старт" - включает/останавливает отрисовку.

"Стабілізація"  -  пытается стабилизировать график сдвигая его на десятые доли выборок вправо или влево.

"AVG проходи"  -  усредняет значение отрисовки с предварительніми выборками. Число означает количество усреднений. 1 - рисует живой график.

"Дільник" -  делитель прерываний АЦП. Онже частота выборок.

"Калибровка"  -  Я этот пункт оставил для ручных настроек. Количество настроек можно добавлять войдя в вкладку "Режими". После правок можно сохранитьнастройки. Я не делал калибровочных замеров (лень). Буду благодарен за предоставленную информацию для каждого из режимов делителя.

Принцип работы:

Ацп отталкивается от стабилизированного выхода 3,2В и считает его максимумом. Входная шкала составляет 8 бит, тоесть 0 - 254.

Примитивный делитель делит 3,2/2=1,6В на два плеча. Такую схему нельзя использовать если масса ПК и измеряемой модели соединены. Идеальный вариант, как делал я, использовать ноутбук. 

Итого 1,6В на входе А0 будет равно 127 - вход это первый столбец параметров "Калибровка". После вход масштабируется в соответствии с вторым столбцом "Калибровка".

Ячейка, что размещена отдельно в параметрах "Калибровка" отвечает за горизонтальную шкалу.

Исходный код предоставлять не вижу смысла, ибо использовалисть платные библиотеки EhLib (честно купленные). С энтузиастами могу поделится в личке.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Есть вопрос.

Подскажите не дорогой и доступный АЦП преобразователь с параметрами около 3 000 000 выборок в секунду. С выходом 8-10 ног / бит.

Также интересуют простые схемы смещения сигнала на дешовых ОУ с пропускной частотой 5-10 mHz.

Цель проекта создать модульный осциллограф который можно модернизировать за малые деньги.

Верхняя планка стоимости проекта 100грн/300руб/4$.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Может будет интересен и такой вариант: http://tomeko.net/miniscope_v2e/ но это STM32 M0. Камень, например, stm32f042f4p6 в ЧипИДип 300р., в Терраэлектронике 225р.

 

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Кое-как откалибровал шкалы делителей.

Данные для калибровки:

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Пробовали больше 20КГц выжать?

20 должно быть при 10битном АЦП в режиме непрерывной работы.

А вы используете всего восемь бит, можно взять больше 20-ти.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Вот это больше похоже на максимум.

Подавал меандр 30КГц.

В роли осциллографа UNO но, долго не мог понять почему результат не сходится с моими расчетами, пока не доглядел китайцы поставили на мой клон кварц 12МГц вместо 16-ти(((  Если бы не эта затея так бы и не узнал.

Выкладываю результат, но с более быстрым кварцом будет лучше.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

У меня калибратор/генератор только до 20кГц.

Я уверен, что можно больше. Этот оссцилограф делает приблизительно до 300 000 выборок в секунду, хватает для просмотра до 30 кГц.

Разрядность АЦП на захватываемую частоту не влияет. Разрядность АЦП разворачивается по оси Y, а по оси Х (частота выборок) влияет только быстродействие АЦП. Тут можно попробовать поднять частоту кварца, но тогда не знаю как Arduino будет подключатся к ПК.

Также заметил сглаживание прямоугольных импульсов, тоесть наростание фронта не прямое.

 

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Кто подскажет быстрый (2-3 мГц), дешевый и доступный АЦП.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Порылся нашел у себя Pro Mini 16MHz.

Особой разницы не увидел с 12-тью, возможно если поднять до 20МГц кварц будет шустрее.

вот скрины.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Okmor пишет:

...

Разрядность АЦП на захватываемую частоту не влияет. Разрядность АЦП разворачивается по оси Y, а по оси Х (частота выборок) влияет только быстродействие АЦП. ..

Я наверное не четко донес мысль, вы понизили разрядность и это дает возможность АЦП корректно работать  свыше 200КГц чеще делать выборки.

С разрядностью от 50 до 200 возбожен 10-битный режим, если выше то там бред.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Частота работы АЦП не зависит от разрядности и всегда преобразуется в 10 бит. В микроконтроллере нет установки разрядности АЦП. Если уменьшать делитель частоты выборки, приближая ее к максимуму, то отбирать 2 верхних бита нет надобности - там будет мусор.

Я действительно забираю только 8 бит. При чем они делятся еще на два плеча - 4 бита на положительный и 4 на отрицательный сигнал. Для осциллографа такая точность не критична и потребность 10 битах редко возникает. 

Отбирание только  8 бит также поднимает частоту выборок, ибо в память нужно переносить только один бит.

Например использование в прерывании оператора IF {} приводит к уменьшению частоты выборок.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Okmor пишет:

....

Например использование в прерывании оператора IF {} приводит к уменьшению частоты выборок.

Согласен.

Пробовал добавлять запись в массив отсчета микросекунд сразу скорость АЦП падала до 250 000 выборок.

Нужен дешевый и быстрый АЦП!

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Okmor пишет:

Я уверен, что можно больше. Этот оссцилограф делает приблизительно до 300 000 выборок в секунду, хватает для просмотра до 30 кГц.

Вы про осцилл на ардуине? 300 000 выборок в секунду это теоретический максимум АЦП меги с делителем  на /2, но нужно учесть что разрядность уже не будет 10-битной. По-моему атмел не документировал чётко эту зависимость, но о ней везде написано. И у мк будет возможность  выполнить в прерывании, или между ними максимум пару команд, иначе они банально не успеют выполниться, прерывания будут выстраиваться в очередь, и пропускаться. Если же работать на рекомендуемых частотах, (делитель на 128 при 16Мгц) то это порядка 9000 выборок в секунду.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Через прерывания не успевает так быстро!

Я настроил с делителем на /4

И сам забираю в цикле сразу в массив и флаг сам сбрасываю.

Если в этот массив добавить хоть еще пару строк скорость выборок сразу падает.

Во время выборок контроллер только ими и занят.

void Zamer(){
          for(byte i=0;i<84;i++){ 
          while ((ADCSRA & 0x10)==0);
          ADCSRA|=0x10;
          mass[i]=ADCH;
                }
}

 

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

В Atmega328 нету делителя 1/2. -Сразу начинается с 1/4. В моей програмуле я его оставил для эксперимента. Я заметил, что при внутреннем опорном напряжении АЦП не отдает данные при делителе 1/2, кукието данные есть. Причем все работает как 1/4 только проскакивают помехи.

Относительно очереди прерываний.

Моя программа использует два потока. Первый поток имеет 100% приоритет и отбирает показания у АЦП и загоняет в буфер. Буфер постоянно перезаписывается по циклу. 

Второй поток с периодичностью 1/10 сек. останавливает прерывания АЦП и сбрасывает буфер на ПК. В данном варианте есть большие потери данных. Частоту сбрасывания можно менять здесь: (loopTime +100) на работу программы не должно отразится.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Какую частоту выборок показал ваш вариант ?

void Zamer(){
2           for(byte i=0;i<84;i++){
3           while ((ADCSRA & 0x10)==0);
4           ADCSRA|=0x10;
5           mass[i]=ADCH;
6                 }
7 }

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

Okmor пишет:

В Atmega328 нету делителя 1/2. -Сразу начинается с 1/4.

То есть нету?  В даташите есть, страница 250.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

84 выборки делает за 276 микросекунды

соостветственно 304 878 выборки в секунду.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

В даташите есть, а по факту нету. :-) От внутреннего опорного он вообще не работает, а от внешнего работает как 1/4 и то с помехами, то есть с периодичным проскакиванием FF.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

dimax пишет:

То есть нету?  В даташите есть, страница 250.

В даташите есть, и вот таблица-но выставляя по ней меньше /4 у меня не рабоатет АЦП.

Поэтому согласен с Okmor.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Привет! Okmor

Можно смотреть просто постоянку от 0 до 5В просто подавая на порт А0 или А1?

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Разобрался, туплю))

ADCSRA = 0b11100010;

sivanko
Offline
Зарегистрирован: 25.02.2016

Добрый день. Какой диапазон входного напряжения? Какой делитель использовать для просмотра синусоиды около 250 вольт в звуковом диапазоне?

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Тут встает вопрос. Нужно измерять только положительное плечо, или отрицательное тоже.

Пример подключения только плоложительного плеча сигнала амплитудой 220В.

Вход А0 измеряет напряжение от 0 до 3,3В считая его максимумом.

Дальнейшую калибровку необходимо производить в программе.

Также!!! При измерении отключите ноутбук от сети!!!

sivanko
Offline
Зарегистрирован: 25.02.2016

Нужно видеть полнную синусоиду...

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Ноутбук в розетку не включать!!!!

sivanko
Offline
Зарегистрирован: 25.02.2016

Спасибо. Я так и думал. Плохо что ноут нельзя включать в сеть, он без акумулятора. Эту проблему нельзя победить?

bwn
Offline
Зарегистрирован: 25.08.2014

sivanko пишет:

Спасибо. Я так и думал. Плохо что ноут нельзя включать в сеть, он без акумулятора. Эту проблему нельзя победить?

Самое надежное, трансформаторный блок питания. Для стандартных ноутовых 3А, 60Вт выходит, тяжеленький и габаритный сундучок.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Okmor Привет!

Если можно постучись на почту есть пару вопросов по твоему будущему прибору!

srukamiua  собака gmail.com

 

nkk
nkk аватар
Offline
Зарегистрирован: 18.03.2016

Привет. Спасибо за труд. Ще й Рiдною мовою! Лучше Осцилографа еще не находил, пробовал на аудиокарте со стабилитронами на щупах, но то не то, да и прога у Вас лучше.

Хочу собрать даный девайс. Для Ардуино ProMini на 5В нужно что-то переделывать? Питание - через повышающий модуль от аккумулятора 18650. Т.к. у меня ноутбука нет, а стационарник (или планшет на андроиде), решил использовать такой блютуз модуль но там нет возможности поставить чатоту как у Вас в коде - 256000, - близкие значения такие:
9 - 230400,
A - 460800,
B - 921600,
C - 1382400,
какую лучше поставить?

Есть ли какие-то ограничения, куда нельзя совать щупы Вашего осцелографа? Заранее спасибо.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Через блутуз ничего не выйдет.

ProMini не подойдет. У него нету USB. 

Вот схема для измерения исключительно положительного сигнала и не более 5В.

nkk
nkk аватар
Offline
Зарегистрирован: 18.03.2016

Не понятно. Вы только с Nano "работали"?

Или это не Ваш проект?

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Да.

Но разницы нет. Можно и с другими. Только у Микро нет порта и тогда нужен адаптер.

Там скетч из двух строк и адаптации не нужно под другие контроллеры.

nkk
nkk аватар
Offline
Зарегистрирован: 18.03.2016

Спасибо. Печаль.

Rossi25
Offline
Зарегистрирован: 08.02.2016

Здравствуйте!

Не могу понять, как задается аналоговый пин (analog reag).

Можно сделать осциллограф двухканальным?

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Rossi25 пишет:

Здравствуйте!

Не могу понять, как задается аналоговый пин (analog reag).

Можно сделать осциллограф двухканальным?

Регистр ADMUX задаёт входной контакт порта A для подключения АЦП

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

dimax, а можете пояснить как получается что 300тыс - это предел?

16Мгц с делитель 1/2, частота ADC = 8Мгц. В Том же даташите (и на Мега2560) написано что на 1 замер требуется 13.5 периодов частоты ADC + 3 такта ЦПУ на выход на обработчик прерывания. (это 1.5 такта ADC если делить 1/2). Итого имеем в теории 15 периодов ADC на 1 замер. 8/15 = 533кГц. Что я посчитал не так?

При этом на 16Мгц имеем ограничение на обработчик прерывания: 16 / 0.533 = 30 тактов. То есть обработчик не может занимать больше чем это количество тактов с учетом входа И возврата из него. Желательно и ещё меньше.

При 10 точках замера на период теоретически должны уметь оцифровывать до 50кГц - вполне уверенно.

Arhat109-2
Offline
Зарегистрирован: 24.09.2015

Я вижу примерно такой расклад для осцилографа на Атмел:

1. АЦП в потоковом режиме делает оцифровку в 8 бит и складывает результат в кольцевой буфер, скажем в 1кб (50% SRAM). Обработчик имеет регистровый счетчик (глобально занимаем регистры, скажем X), что его значительно упрощает: автоинремент при записи, не требуется сохранение/восстановление и вполне можно уложится в 15 тактов или около того.

2. Таймер времени тоже урезаем до миниума и ведем учет в 16 битовом и тоже глобальном регистре, скажем пара r2,r3. В этом случае, его обработчик точно также можно упихать в 12-15тактов.

3. Практически все писать на ассемблере с ручным контролем распределения регистров, дабы не пропали "глобальные счетчики" .. по идее, 32-х регистров должно хватить на все. Размер буфера АЦП можно подобрать так, чтобы его можно было успеть передать в комп раньше чем АЦП "догонит" слепок. Или делать двойную буферизацию с "пропуском" части данных.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Вот так:

16 000 000/ 13(число тактов оцифровки)/4(минимальный делитель)=307692

У меня все пишется в циклический буфер размером 254 байта. Буфер зациклен по переполнению счетчика. 

Если увеличить буфер, то нужно использовать оператор сравнения IF и тогда уходит время для его обработки. - Это максимальная скорось.

Ассамблер здесь нафиг не нужен. Компилятор на таком простом участке очень хорошо справляется.

У меня приблизительно столько и получилось. Несколько тиков уходит на инкремент счетчика и запись значения.

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Был вопрос про два канала.

К сожалению два канала без 4х кратной потери производительности реализовать не выйдет.

Я слышал, что Atmega8 может работать с делителем АЦП 1/2, но попробовать нет возможность изза отсутствия таковой. Если это правда, то можно достичь 600 000 выборок в секунду.

bodriy2014
bodriy2014 аватар
Offline
Зарегистрирован: 12.05.2015

Okmor пишет:

Был вопрос про два канала.

К сожалению два канала без 4х кратной потери производительности реализовать не выйдет.

Я слышал, что Atmega8 может работать с делителем АЦП 1/2, но попробовать нет возможность изза отсутствия таковой. Если это правда, то можно достичь 600 000 выборок в секунду.

Привет!

Я понял ты с УА напиши мне на мыло,

вышлю парочку на истязание укрпочтой.

Rossi25
Offline
Зарегистрирован: 08.02.2016

Да меня такая произодительность бы устроила... Если бы добавили такую опцию..

Витенька
Offline
Зарегистрирован: 03.04.2016

Здравствуйте Okmor! Почему данная программа не хочет работать на Mega 2560?

Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Возможно проблема в инициации АЦП и его прерываниях.

//Запуск АЦП  
 ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADATE) | (0 << ADIF) | (1 << ADIE) | (0 << ADPS2) | (1 << ADPS1) | (0 << ADPS0);
 ADMUX = (0 << REFS1) | (0 << REFS0) | (1 << ADLAR)  | (0 << MUX3) | (0 << MUX2)  | (0 << MUX1)  | (0 << MUX0) ;   // Включити переривання

Эту часть надо переписать.

 
 
  
Витенька
Offline
Зарегистрирован: 03.04.2016

Ну да, именно туда и тычит, еще бы знать что и как там переписать.

http://imglink.ru/show-image.php?id=14aa1b1f722b735887baad5e8722143d

Arduino: 1.6.8 (Windows 8.1), Плата:"Arduino/Genuino Mega or Mega 2560, ATmega2560 (Mega 2560)"
 
C:\Users\Администратор\Documents\Arduino\sketch_may26a\sketch_may26a.ino: In function 'void setup()':
 
sketch_may26a:14: error: 'UART_Init' was not declared in this scope
 
C:\Users\Администратор\Documents\Arduino\sketch_may26a\sketch_may26a.ino: In function 'void loop()':
 
sketch_may26a:25: error: 'UART_SendByte' was not declared in this scope
 
sketch_may26a:26: error: 'UART_SendArray' was not declared in this scope
 
sketch_may26a:34: error: 'UART_ReadByte' was not declared in this scope
 
exit status 1
'UART_Init' was not declared in this scope
 
Этот отчёт будет иметь больше информации с
включенной опцией Файл -> Настройки ->
"Показать подробный вывод во время компиляции"
 
Okmor
Okmor аватар
Offline
Зарегистрирован: 16.10.2015

Для исправления ошибки UART_SendByte нужно закачать библиотеку http://cyber-place.ru/showthread.php?t=550

Но она, помоему, заточено под Atmega328.

Переделать под Mega 2560 не могу в связи с ее отсутствием.

Вот выкладываю новую версию программы.

Исправлено:

1. Глюк, если на компе больше одного СОМ порта.

2. Теперь не нужно качать файл Mem.dfm и класть в ту же папку, он создается автоматически.

3. Сам скетч засунул в новую вкладку программы. Теперь не нужно каждый раз проверять версию и он не потеряется.