Мини осциллограф Arduino на LCD 5110

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

Joiner пишет:

Дисплей ILI9163C смотрится симпатичнее чем дисплей от Nokia. И разрешение побольше, да и цвет присутствует. Поэтому автору бодрому2014 рекомендовал (скорее просил) сделать осцилоскоп с таким дисплеем.

Нет такого дисплея под рукой. Но назрела потребность переделать пультоскоп или сделать новый.

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

cilentlekx пишет:

Доброго времени ! Подключил ваш PULTOSCOP к дисплею ILI9163C очень красиво смотрится! конечно сделал пока без обвязки входов,это поэтому дисплей и показания моргают?

https://yadi.sk/d/cI4Dp4dHm2mSt

вот ссылка на фото с дисплеем. Подскажите пожалуйста переменный резистор ,для чего он нужен? За ранее спасибо!

Переменник регулирует развертку. Без него не рассмотрите ничего в мельтешении на экране.

cilentlekx
Offline
Зарегистрирован: 14.12.2014

У меня почему то когда соединяю А5 с D5 для измерения частоты,то сразу показывает 50гц,причем провод рукой не трогаю. В чем может быть дело,кто то сталкивался с таким?

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

cilentlekx пишет:

У меня почему то когда соединяю А5 с D5 для измерения частоты,то сразу показывает 50гц,причем провод рукой не трогаю. В чем может быть дело,кто то сталкивался с таким?

В скетче на А5 потенциометр.

D5 с А4 соединять нужно.

Для проверки подайте на D5 землю если пропадет значит просто ловит наводку.

Jtest
Offline
Зарегистрирован: 02.06.2015
назрела потребность переделать пультоскоп или сделать новый

 

bodriy2014, какие работы планируются? Как скоро выйдет обновленный пультоскоп?

 

cilentlekx
Offline
Зарегистрирован: 14.12.2014

В скетче от автора есть функция дисплея display.display(); что она значит,подскажите? В моем дисплее ILI9163такая функция не компилируется! Поэтому я ее убрал,вопрос-может ли она сказатся на работе дисплея?

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

cilentlekx пишет:

.....! Поэтому я ее убрал,вопрос-может ли она сказатся на работе дисплея?

она нужна только для той библиотеки что у меня.

У вас другой дисплей и своя библиотека вам она не нужна.

cilentlekx
Offline
Зарегистрирован: 14.12.2014

Понял,спасибо за консультации! Еще вопрос,моргание дисплея как можно убрать? Ведь используется функция очистки дисплея 

//display.clearDisplay();
tft.clearScreen();   А у вас на видео этого моргания не видно ! регулируя потенциомметр,частота моргания меняется конечно,но нет как у вас.Чем можно убрать это мигание к минимуму?
Joiner
Offline
Зарегистрирован: 04.09.2014

bodriy2014 пишет:

Нет такого дисплея под рукой. Но назрела потребность переделать пультоскоп или сделать новый.

Спасибо. Будем ждать.

onegin
Offline
Зарегистрирован: 14.10.2015

Dm77 пишет:

pooller пишет:

А скетч с доработанными кнопками где? Я заливал себе скетч от Noriaki Mitsunaga" (как в 203 посте), но только практчески все аналоговые входы UNO заняты экраном, кроме "А5" а в скетче вовсе указаны входы "А6" и "А7", которых в Arduino UNO совсем нет. Я только один канал на  А5 задействовал а второй 5вольт показывал постоянно.

Сырой пока чтобы выкладывать. Нужно настроить на работу сначала.... сейчас думаю как щуп сделать

Если скорость развертки меняет-сгодится и сырой.  Скиньте код,  пожалуйста. 

nikolyalomaev
Offline
Зарегистрирован: 24.11.2015

Нашел решение проблеммы на своем примере пультоскопа от bodriy2014 от произвольного изменения контраста дисплея от нокии 5110 (был у меня такой вопросик) На плате с которой постовляется дисплей, присутствует керамический чип кондедсатор на 0,1мкф, который походу перенасыщяется из-за не установленых на spi входах огранечительных резисторов, решил пойти подругому, припаял паролельно ему резистор на 1мом, и контраст остается пока на своем установленом в скетче параметре

Barbosa75
Offline
Зарегистрирован: 10.11.2015

nikolyalomaev пишет:

Нашел решение проблеммы на своем примере пультоскопа от bodriy2014 от произвольного изменения контраста дисплея от нокии 5110 (был у меня такой вопросик) На плате с которой постовляется дисплей, присутствует керамический чип кондедсатор на 0,1мкф, который походу перенасыщяется из-за не установленых на spi входах огранечительных резисторов, решил пойти подругому, припаял паролельно ему резистор на 1мом, и контраст остается пока на своем установленом в скетче параметре

Гг, чтото новенькое, "насыщение конденсатора".

nikolyalomaev
Offline
Зарегистрирован: 24.11.2015

ну у меня только такое определение возникает

cilentlekx
Offline
Зарегистрирован: 14.12.2014

Доброго времени всем! Доработа скетч с работой на дисплее ILI9163C,все работает прекрасно! Убрал моргание экрана,добавил раскраски.

Этот проект по функционалу мне кажется даже лучше,чем предыдущий.Ничего лишнего,только необходимые параметры и форма сигнала.Рекомендую всем. Скетч 

001#include <Adafruit_GFX.h>
002// #include <Adafruit_PCD8544.h>
003#include <SPI.h>
004#include <FreqCount.h>
005 
006#include <TFT_ILI9163C.h>
007 
008// Color definitions
009#define  BLACK   0x0000
010#define BLUE    0x001F
011#define RED     0xF800
012#define GREEN   0x07E0
013#define CYAN    0x07FF
014#define MAGENTA 0xF81F
015#define YELLOW  0xFFE0
016#define WHITE   0xFFFF
017 
018#define __CS 10
019#define __DC 9
020 
021TFT_ILI9163C tft = TFT_ILI9163C(__CS, 8, __DC);
022#define DISPLAY_WIDTH 128
023#define DISPLAY_HEIGHT 128
024#define ARDUINO_PRECISION 1023.0
025// Adafruit_PCD8544 display = Adafruit_PCD8544(14, 13, 12, 11, 10);
026int channelAI = A4;      //вход сигнала А5, частоту меряем на 5!!!
027int PINakum = A6;      //вход замера аккумулдятора
028int delayAI = A5;       //делитель нп потенциометре
029int razv = 0;// константы и пины добавления развертки
030int oldRazv=0;
031#define DELAY_POTENTIMETER
032#ifdef DELAY_POTENTIMETER
033#endif
034 
035float delayVariable = 0;
036float scale = 0;
037int xCounter = 0;
038int yPosition = 0;
039int readings[DISPLAY_WIDTH + 1];
040int oldReadings[DISPLAY_WIDTH + 1];
041int counter = 0;
042unsigned long drawtime = 0;
043unsigned long lastdraw = 0;
044unsigned long count = 0;
045int frames = 0;
046float analog=0;
047unsigned long oldCount=0;
048void setup()
049{
050  FreqCount.begin(1000);
051  tft.begin(); 
052  tft.setRotation(3);
053  tft.fillScreen(BLACK);
054  tft.setCursor(25, 5);
055  tft.print("PULTOSCOPE");
056  tft.setCursor(15, 15);
057  tft.print("Mobile v1.1");
058  //#################тест аккумулятора
059  if ((analogRead(PINakum) / ARDUINO_PRECISION * 5.0) > 3.3) {
060    tft.setCursor(10, 30);
061    tft.print("Test Batt OK!");
062  }
063  if ((analogRead(PINakum) / ARDUINO_PRECISION * 5.0) < 3.3) {
064    tft.setCursor(10, 30);
065    tft.print("Test Batt NO!");
066  }
067  tft.setCursor(40, 45);
068  tft.print(analogRead(PINakum) / ARDUINO_PRECISION * 5.0);
069  tft.print("V");
070  //tft.display(0);
071  delay(3000);
072  tft.clearScreen();
073  //#######################
074}
075void loop()
076{
077#ifdef DELAY_POTENTIMETER
078  delayVariable = analogRead(delayAI);
079  delayVariable = (delayVariable / 100); //делитель регулирует выборку
080#endif
081  //scale = (float)(DISPLAY_HEIGHT-1)/ARDUINO_PRECISION;
082  scale = 127 / 1210.0; //ограничиваем диаграмму на один символ сверху
083  //##############################################разделение шкалы по сигналу
084  for (xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
085  {
086    oldReadings[xCounter] = readings[xCounter];
087  }
088  for (xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
089  {
090    yPosition = analogRead(channelAI);
091    readings[xCounter] = (yPosition * scale);
092#ifdef DELAY_POTENTIMETER
093    delay (delayVariable );
094#endif
095  }
096  //##############################################шкала напряжений
097  tft.drawLine( 10, 20, 10, DISPLAY_HEIGHT - 1, RED);
098  tft.drawLine( 5, (DISPLAY_HEIGHT - 1) - (.2 * ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT - 1) - (.2 * ARDUINO_PRECISION * scale), RED);
099  tft.drawLine( 5, (DISPLAY_HEIGHT - 1) - (.4 * ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT - 1) - (.4 * ARDUINO_PRECISION * scale), RED);
100  tft.drawLine( 5, (DISPLAY_HEIGHT - 1) - (.6 * ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT - 1) - (.6 * ARDUINO_PRECISION * scale), RED);
101  tft.drawLine( 5, (DISPLAY_HEIGHT - 1) - (.8 * ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT - 1) - (.8 * ARDUINO_PRECISION * scale), RED);
102  tft.setTextColor(MAGENTA);
103  tft.setCursor(0, ((DISPLAY_HEIGHT - 1) - (.2 * ARDUINO_PRECISION * scale)) - 3);
104  tft.print((int)(5.0 * 0.2));
105  tft.setCursor(0, ((DISPLAY_HEIGHT - 1) - (.4 * ARDUINO_PRECISION * scale)) - 3);
106  tft.print((int)(5.0 * 0.4));
107  tft.setCursor(0, ((DISPLAY_HEIGHT - 1) - (.6 * ARDUINO_PRECISION * scale)) - 3);
108  tft.print((int)(5.0 * 0.6));
109  tft.setCursor(0, ((DISPLAY_HEIGHT - 1) - (.8 * ARDUINO_PRECISION * scale)) - 3);
110  tft.print((int)(5.0 * 0.8));
111  //##############################################отрисовка сигнала
112 
113  for (xCounter = 14; xCounter <= DISPLAY_WIDTH; xCounter++)
114  {
115    tft.drawPixel(xCounter, (DISPLAY_HEIGHT - 1) - readings[xCounter], RED);
116    if (xCounter > 1) {
117      tft.drawLine(xCounter - 1, (DISPLAY_HEIGHT - 1) - oldReadings[xCounter - 1], xCounter, (DISPLAY_HEIGHT - 1) - oldReadings[xCounter], BLACK);
118      tft.drawLine(xCounter - 1, (DISPLAY_HEIGHT - 1) - readings[xCounter - 1], xCounter, (DISPLAY_HEIGHT - 1) - readings[xCounter], RED);
119    }
120  }
121    
122  tft.setTextColor(BLACK);
123  tft.setCursor(90, 5);
124  tft.print(oldRazv);
125  tft.setTextColor(WHITE);
126  tft.setCursor(90, 5);
127  tft.print(razv);
128  oldRazv=razv;
129 
130  //############################################вывод напряжения
131  tft.setTextColor(BLACK);
132  tft.setCursor(5, 5);
133  tft.print(analog);
134  tft.setTextColor(WHITE);
135  tft.setCursor(5, 5);
136  analog= analogRead(channelAI) / ARDUINO_PRECISION * 5.0;
137  tft.print(analog);
138  tft.print("V");
139   
140  if (count < 1000) {
141    tft.setTextColor(BLACK);
142    tft.setCursor(42, 5);
143    tft.print(count);
144    tft.print("Hz");
145  }
146  if (count > 1000) {
147    tft.setTextColor(BLACK);
148    tft.setCursor(42, 5);
149    tft.print((count) / 1000);
150    tft.print("KHz");
151  }
152  if (FreqCount.available()) {
153    count = FreqCount.read();
154  }
155  if (count < 1000) {
156    tft.setTextColor(MAGENTA);
157    tft.setCursor(42, 5);
158    tft.print(count);
159    tft.print("Hz");
160  }
161  if (count > 1000) {
162    tft.setTextColor(MAGENTA);
163    tft.setCursor(42, 5);
164    tft.print((count) / 1000);
165    tft.print("KHz");
166  }
167  if (digitalRead(2) == HIGH) // проверяем состояние кнопки
168  {
169    razv = razv + 5;
170  }
171  if (digitalRead(3) == HIGH) // проверяем состояние кнопки
172  {
173    razv = razv - 5;
174    if (razv < 0) // проверяем состояние кнопки
175    {
176      razv = 0;
177    }
178  }
179  delay(razv);//регулирует частоту выборки
180}

 

Barbosa75
Offline
Зарегистрирован: 10.11.2015

Отлично, фото дисплея в работе не скините?

cilentlekx
Offline
Зарегистрирован: 14.12.2014

фото есть выше

но повторю

 

https://yadi.sk/d/cI4Dp4dHm2mSt

 

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

Доработал pultoscop переписал весь код с ноля, прошлый был частично по кускам собран из чужих.

--Теперь частота выборки АЦП будет 300 000 циклов в секунду.

--доработал управление графиком теперь все можно рассмотреть и даже заморозить.

--убрал потенциометр все только кнопками.

--все настройки сохраняются в энергонещависимую память.

--счас занимаюсь печаткой и дорабатываю функцию "АВТО"

--еще пару плюшек есть но это когда выложу весь материал.

 

 

Joiner
Offline
Зарегистрирован: 04.09.2014

bodriy2014 пишет:

....................................

--еще пару плюшек есть но это когда выложу весь материал.

Ждем. Давно хочу повторить конструкцию. Значит не зря ждал :) Буду делать новую версию.

Jtest
Offline
Зарегистрирован: 02.06.2015

bodriy2014 пишет:

Доработал pultoscop переписал весь код с ноля,

Здорово! Хороший подарок всем на НГ)) Интересно что получилось. Базовые компоненты те же (Pro mini + дисплей 3310)?

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

Jtest пишет:

Здорово! Хороший подарок всем на НГ)) Интересно что получилось. Базовые компоненты те же (Pro mini + дисплей 3310)?

Привет.

Да подарок из разряда сделай сам))

Компоненты

--любой ардуино где стоит Atmega328/

--Дисплей 5110/3310.

У меня и побольше есть дисплеи от друхих мобилок и даже цветные с неплохим разрешением, но тогда повторяемось упадет, где другие такой брать будут.

Будут предложения по функционалу пишите, ветку читаю смогу-добавлю!

revlerik
Offline
Зарегистрирован: 26.12.2015

bodriy2014 пишет:

--любой ардуино где стоит Atmega328/

Здравствуйте,мне понравился ваш проэкт,хочу повторить,дисплей у меня есть,а вот ардуино нету,но есть мега 328 в TQFP корпусе,возможно ли собрать ваш осциллограф без ардуино?

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

revlerik пишет:

bodriy2014 пишет:

--любой ардуино где стоит Atmega328/

Здравствуйте,мне понравился ваш проэкт,хочу повторить,дисплей у меня есть,а вот ардуино нету,но есть мега 328 в TQFP корпусе,возможно ли собрать ваш осциллограф без ардуино?

Возможно собрать на любой Atmega328.

TQFP корпус требует только более мелкие дорожки.

Нужен еще будет кварц на 16МГц, несколько резисторов и конденсаторов, кнопок.

revlerik
Offline
Зарегистрирован: 26.12.2015

Спасибо!

А где можно схемку глянуть?

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

revlerik пишет:

Спасибо!

А где можно схемку глянуть?

пост 267

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

в последнем предложении ответ на последнюю версию.

cilentlekx
Offline
Зарегистрирован: 14.12.2014

bodriy2014! Здравстауйте! Подскажите пожалуйста, как будет выглядеть схема делителя 1|10? Подтягивал к минусу резистор 100ком. Никакие сигналы не проходят! Может конденсатор в этом случае нужно убрать? За ранее спасибо!

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

cilentlekx пишет:

bodriy2014! Здравстауйте! Подскажите пожалуйста, как будет выглядеть схема делителя 1|10? Подтягивал к минусу резистор 100ком. Никакие сигналы не проходят! Может конденсатор в этом случае нужно убрать? За ранее спасибо!

конденсатор не остановит переменный ток, можете убрать можете оставть.

Вот схема делителя.

 

cilentlekx
Offline
Зарегистрирован: 14.12.2014

Спасибо большое !Буду подключать и пробовать. Еще вопрос-Если берусь за минусовой провод рукой,то тоже показывает порядка 50гц! Это нормально или наводки? 

nikolyalomaev
Offline
Зарегистрирован: 24.11.2015

bodriy2014, Отличные новости! А переменный резистор вовсе из схемы выбрасывается? За место него доп кнопок не будет?

cilentlekx
Offline
Зарегистрирован: 14.12.2014

bodriy2014,здравствуйте! Вопрос, обратил внимание,что при тестировании с генератора сигналов,если сигнал меньше 2 вольт,то частоту не считывает,то есть показывает ноль,хотя форма сигнала правильная! Можете как то пояснить с чем это связано?

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

cilentlekx пишет:
bodriy2014,здравствуйте! Вопрос, обратил внимание,что при тестировании с генератора сигналов,если сигнал меньше 2 вольт,то частоту не считывает,то есть показывает ноль,хотя форма сигнала правильная! Можете как то пояснить с чем это связано?

Легко.

Частоту меряет апаратно с порта D5, и на цифровых портах все что ниже 1,8В считается нулем что выше еденица.(могу незначительно ошибиться смотрите даташит)

Он видит только нули.

cilentlekx
Offline
Зарегистрирован: 14.12.2014

То есть ничего не изменить,просто получается такая особенность осцилографа?

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

cilentlekx пишет:
То есть ничего не изменить,просто получается такая особенность осцилографа?

--Можно добавить на вход усилитель, например LM358 он до 20КГц сигнал не искажает.

--Можно считать частоту программно, мерять время и количество импульсов.

cilentlekx
Offline
Зарегистрирован: 14.12.2014

Да я также предположил,что на вход поставить операционный усилитель. А програмно измерять,то точность не изменится?

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

cilentlekx пишет:
Да я также предположил,что на вход поставить операционный усилитель. А програмно измерять,то точность не изменится?

Зависит от того как реализовать подсчет.(от кода)

Причин ему считать не точно не вижу.

cilentlekx
Offline
Зарегистрирован: 14.12.2014

bodriy2014 добрый вечер! Сигнал до 2 вольт он не так и важен! Но как сделать с делителем ,чтобы онс 2в.- до 50 вольт воспринимал сигнал? Или так не получится?За ранее спасибо!

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

cilentlekx пишет:

bodriy2014 добрый вечер! Сигнал до 2 вольт он не так и важен! Но как сделать с делителем ,чтобы онс 2в.- до 50 вольт воспринимал сигнал? Или так не получится?За ранее спасибо!

Да как сделать, руками я думаю)))

Без делителя он берет сигнал  до 5В.

Если хотите до 50В собирайте щуп с делителем 1 к 10 и подключайте, можно продумать переключатель чтоб делитель переключать.

 

cilentlekx
Offline
Зарегистрирован: 14.12.2014

Но если делитель 1\10 то при 20 в и меньше на входе мк будет кокрас 2в. и меньше,то есть от 20 в и меньше снова будет мертвая зона! Единственное пока что я вижу это делать делители 1\2 , 1\5, 1\10 и т.д тогда будет перекрыватся мертвая зона на верхних пределах меньших делителей? Как вы считаете?

fly245
fly245 аватар
Offline
Зарегистрирован: 25.08.2013

Не получается пререкроить под ST7781 (((

fly245
fly245 аватар
Offline
Зарегистрирован: 25.08.2013

Вот подшаманил такой код под ST7781

001#include "TFTLCD.h"
002 
003#define LCD_CS A3
004#define LCD_CD A2
005#define LCD_WR A1
006#define LCD_RD A0
007#define LCD_RESET A4
008 
009#define  BLACK           0x0000
010#define BLUE            0x001F
011#define RED             0xF800
012#define GREEN           0x07E0
013#define CYAN            0x07FF
014#define MAGENTA         0xF81F
015#define YELLOW          0xFFE0
016#define WHITE           0xFFFF
017 
018TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
019 
020 //#include <Arial14.h>  // font definitions
021 
022#define txtLINE0   0
023#define txtLINE1   16
024#define txtLINE2   30
025#define txtLINE3   46
026 
027const int LCD_WIDTH = 320;
028const int LCD_HEIGHT = 240;
029const int SAMPLES = 270;
030const int DOTS_DIV = 30;
031 
032 
033int sensorValue = 0;
034const int ad_sw = 3;                    // Analog 3 pin for switches
035const int ad_ch0 = 5;                   // Analog 6 pin for channel 0
036const int ad_ch1 = 7;                   // Analog 7 pin for channel 1
037const unsigned long VREF[] = {150, 300, 750, 1500, 3000}; // reference voltage 5.0V ->  150 :   1V/div range (100mV/dot)
038                                        // It means 5.0 * DOTS_DIV = 150. Use 4.9 if reference voltage is 4.9[V]
039                                        //                        -> 300 : 0.5V/div
040                                        //                        -> 750 : 0.2V/div
041                                        //                        ->1500 : 100mV/div
042                                        //                       -> 3000 :  50mV/div
043const int MILLIVOL_per_dot[] = {33, 17, 6, 3, 2}; // mV/dot
044const int MODE_ON = 0;
045const int MODE_INV = 1;
046const int MODE_OFF = 2;
047const char *Modes[] = {" NORM", " INV", " OFF"};
048const int TRIG_AUTO = 0;
049const int TRIG_NORM = 1;
050const int TRIG_SCAN = 2;
051const int TRIG_ONE  = 3;
052const char *TRIG_Modes[] = {" Auto", " Norm", " Scan", " One"};
053const int TRIG_E_UP = 0;
054const int TRIG_E_DN = 1;
055#define RATE_MIN 0
056#define RATE_MAX 13
057const char *Rates[] = {"F1-1", "F1-2 ", "F2  ", "5ms", "10ms", "20ms", "50ms", "0.1s", "0.2s", "0.5s", "1s", "2s", "5s", "10s"};
058#define RANGE_MIN 0
059#define RANGE_MAX 4
060const char *Ranges[] = {"1V ", "0.5V", "0.2V", "0.1V", "50mV"};
061unsigned long startMillis;
062byte data[4][SAMPLES];                   // keep twice of the number of channels to make it a double buffer
063byte sample=0;                           // index for double buffer
064 
065///////////////////////////////////////////////////////////////////////////////////////////////
066// Define colors here
067#define   BGCOLOR  BLACK
068#define   GRIDCOLOR WHITE
069#define CH1COLOR  BLUE
070#define CH2COLOR  GREEN
071 
072// Declare variables and set defaults here
073// Note: only ch1 is available with Aitendo's parallel 320x240 TFT LCD 
074byte range0 = RANGE_MIN, ch0_mode = MODE_ON;  // CH0
075short ch0_off = 204;
076byte range1 = RANGE_MIN, ch1_mode = MODE_ON;  // CH1
077short ch1_off = 204;
078byte rate = 3;                                // sampling rate
079byte trig_mode = TRIG_AUTO, trig_lv = 30, trig_edge = TRIG_E_UP, trig_ch = 1; // trigger settings
080byte Start = 1;  // Start sampling
081byte menu = 0;  // Default menu
082///////////////////////////////////////////////////////////////////////////////////////////////
083 
084void setup(){
085  tft.reset();
086  tft.initDisplay();
087  tft.setRotation(1);
088 
089  tft.fillScreen(BGCOLOR);
090 
091  tft.setTextColor(WHITE);
092  tft.setTextSize(2);
093  tft.setCursor(0, 0);
094  tft.print("Arduino Oscillo Scope");
095  tft.setCursor(25, 100);
096  tft.print("with Aitendo TFT LCD (320x240)");
097  tft.setCursor(75, 240);
098  tft.print("(c) 2009-2014 non");
099   
100  delay(2000);
101 
102  tft.fillScreen(BGCOLOR);
103    
104  Serial.begin(9600);
105  DrawGrid();
106  DrawText();
107}
108 
109void CheckSW() {
110  static unsigned long Millis = 0, oMillis = 0;
111  unsigned long ms;
112  unsigned short ain = analogRead(ad_sw);
113 //Serial.println(ain);
114  return;
115  ms = millis();
116  if ((ms - Millis)<5)
117  return;
118  Millis = ms;
119  oMillis = Millis;
120   //Serial.println(ain);
121  DrawText();
122}
123 
124void menu0_sw(int sw) { 
125  switch (sw) {
126   case 0:
127    // START/HOLD
128    if (Start)
129       Start = 0;
130     else
131       Start = 1;
132    break;
133   case 1:
134    // CH0 RANGE -
135    if (range0 < RANGE_MAX)
136      range0 ++;
137    break;
138   case 2:
139    // CH1 RANGE -
140    if (range1 < RANGE_MAX)
141      range1 ++;
142    break;
143   case 3:
144    // RATE FAST
145    if (rate > 0)
146      rate --;
147    break;
148   case 4:
149    // TRIG MODE
150    if (trig_mode < TRIG_ONE)
151      trig_mode ++;
152    else
153      trig_mode = 0;
154    break;
155   case 5:
156    // SEND
157    SendData();
158    break;
159   case 6:
160    // TRIG MODE
161    if (trig_mode > 0)
162      trig_mode --;
163    else
164      trig_mode = TRIG_ONE;
165    break;
166   case 7:
167    // RATE SLOW
168    if (rate < RATE_MAX)
169      rate ++;
170    break;
171   case 8:
172    // CH1 RANGE +
173    if (range1 > 0)
174      range1 --;
175    break;
176   case 9:
177    // CH0 RANGE +
178    if (range0 > 0)
179      range0 --;
180    break;
181   case 10:
182   default:
183    // MENU SW
184    menu ++;
185     break;
186  }
187}
188 
189 
190 
191void SendData() {
192  Serial.print(Rates[rate]);
193  Serial.println("/div (30 samples)");
194  for (int i=0; i<SAMPLES; i ++) {
195      Serial.print(data[sample + 0][i]*MILLIVOL_per_dot[range0]);
196      Serial.print(" ");
197      Serial.println(data[sample + 1][i]*MILLIVOL_per_dot[range1]);
198   }
199}
200 
201void DrawGrid() {
202    for (int x=0; x<=SAMPLES; x += 2) { // Horizontal Line
203      for (int y=0; y<=LCD_HEIGHT; y += DOTS_DIV) {
204        tft.drawPixel(x, y, GRIDCOLOR);
205        CheckSW();
206      }
207      if (LCD_HEIGHT == 240)
208        tft.drawPixel(x, LCD_HEIGHT-1, GRIDCOLOR);
209    }
210    for (int x=0; x<=SAMPLES; x += DOTS_DIV ) { // Vertical Line
211      for (int y=0; y<=LCD_HEIGHT; y += 2) {
212        tft.drawPixel(x, y, GRIDCOLOR);
213        CheckSW();
214      }
215    }
216}
217 
218void DrawText() {
219  tft.setTextColor(YELLOW);
220  tft.setTextSize(1);
221  tft.setCursor(SAMPLES+3, 5);
222  tft.print(Ranges[range1]);
223  tft.println("/DIV");
224  tft.setCursor(SAMPLES+3, 15);
225  tft.print(Rates[rate]);
226  tft.println("/DIV");
227  tft.setCursor(SAMPLES+3, 25);
228  tft.println(TRIG_Modes[trig_mode]);
229  tft.setCursor(SAMPLES+3, 35);
230  tft.println(trig_edge == TRIG_E_UP ? "UP" : "DN");
231  tft.setCursor(SAMPLES+3, 45);
232  tft.println(Modes[ch1_mode]);
233  tft.setCursor(SAMPLES+3, 60);
234  tft.setTextColor(RED);
235  tft.println(" 5 V");
236   tft.setCursor(SAMPLES+3, 90);
237  tft.println(" 4 V");
238  tft.println("");
239   tft.setCursor(SAMPLES+3, 120);
240  tft.println(" 3 V");
241  tft.println("");
242   tft.setCursor(SAMPLES+3, 150);
243  tft.println(" 2 V");
244  tft.println("");
245  tft.setCursor(SAMPLES+3, 180);
246  tft.println(" 1 V");
247  tft.println("");
248  tft.setCursor(SAMPLES+3, 210);
249  tft.println(" 0 V");
250//  tft.setCursor(SAMPLES, 70);
251//  tft.println(trig_ch == 0 ? "T:1" : "T:2");
252 
253}
254 
255void DrawGrid(int x) {
256    if ((x % 2) == 0)
257      for (int y=0; y<=LCD_HEIGHT; y += DOTS_DIV)
258        tft.drawPixel(x, y, GRIDCOLOR);
259    if ((x % DOTS_DIV) == 0)
260      for (int y=0; y<=LCD_HEIGHT; y += 2)
261        tft.drawPixel(x, y, GRIDCOLOR);
262}
263 
264void ClearAndDrawGraph() {
265  int clear = 0;
266   
267  if (sample == 0)
268    clear = 2;
269#if 0
270   for (int x=0; x<SAMPLES; x++) {
271     GLCD.SetDot(x, LCD_HEIGHT-data[clear+0][x], WHITE);
272     GLCD.SetDot(x, LCD_HEIGHT-data[clear+1][x], WHITE);
273     GLCD.SetDot(x, LCD_HEIGHT-data[sample+0][x], BLACK);
274     GLCD.SetDot(x, LCD_HEIGHT-data[sample+1][x], BLACK);
275  }
276#else
277   for (int x=0; x<(SAMPLES-1); x++) {
278     tft.drawLine(x, LCD_HEIGHT-data[clear+0][x], x+1, LCD_HEIGHT-data[clear+0][x+1], BGCOLOR);
279     tft.drawLine(x, LCD_HEIGHT-data[clear+1][x], x+1, LCD_HEIGHT-data[clear+1][x+1], BGCOLOR);
280     if (ch0_mode != MODE_OFF)
281       tft.drawLine(x, LCD_HEIGHT-data[sample+0][x], x+1, LCD_HEIGHT-data[sample+0][x+1], CH1COLOR);
282     if (ch1_mode != MODE_OFF)
283       tft.drawLine(x, LCD_HEIGHT-data[sample+1][x], x+1, LCD_HEIGHT-data[sample+1][x+1], CH2COLOR);
284     CheckSW();
285  
286#endif
287}
288 
289void ClearAndDrawDot(int i) {
290  int clear = 0;
291 
292  if (i <= 1)
293    return;
294  if (sample == 0)
295    clear = 2;
296#if 0
297   for (int x=0; x<SAMPLES; x++) {
298     GLCD.SetDot(x, LCD_HEIGHT-data[clear+0][x], WHITE);
299     GLCD.SetDot(x, LCD_HEIGHT-data[clear+1][x], WHITE);
300     GLCD.SetDot(x, LCD_HEIGHT-data[sample+0][x], BLACK);
301     GLCD.SetDot(x, LCD_HEIGHT-data[sample+1][x], BLACK);
302  }
303#else
304  tft.drawLine(i-1, LCD_HEIGHT-data[clear+0][i-1], i, LCD_HEIGHT-data[clear+0][i], BGCOLOR);
305  tft.drawLine(i-1, LCD_HEIGHT-data[clear+1][i-1], i, LCD_HEIGHT-data[clear+1][i], BGCOLOR);
306  if (ch0_mode != MODE_OFF)
307    tft.drawLine(i-1, LCD_HEIGHT-data[sample+0][i-1], i, LCD_HEIGHT-data[sample+0][i], CH1COLOR);
308  if (ch1_mode != MODE_OFF)
309    tft.drawLine(i-1, LCD_HEIGHT-data[sample+1][i-1], i, LCD_HEIGHT-data[sample+1][i], CH2COLOR);
310#endif
311  DrawGrid(i);
312}
313 
314void DrawGraph() {
315   for (int x=0; x<SAMPLES; x++) {
316     tft.drawPixel(x, LCD_HEIGHT-data[sample+0][x], CH1COLOR);
317     tft.drawPixel(x, LCD_HEIGHT-data[sample+1][x], CH2COLOR);
318  }
319}
320 
321void ClearGraph() {
322  int clear = 0;
323   
324  if (sample == 0)
325    clear = 2;
326  for (int x=0; x<SAMPLES; x++) {
327     tft.drawPixel(x, LCD_HEIGHT-data[clear+0][x], BGCOLOR);
328     tft.drawPixel(x, LCD_HEIGHT-data[clear+1][x], BGCOLOR);
329  }
330}
331 
332inline unsigned long adRead(byte ch, byte mode, int off)
333{
334  unsigned long a = analogRead(ch);
335  a = ((a+off)*VREF[ch == ad_ch0 ? range0 : range1]+512) >> 10;
336  a = a>=(LCD_HEIGHT+1) ? LCD_HEIGHT : a;
337  if (mode == MODE_INV)
338    return LCD_HEIGHT - a;
339  return a;
340}
341 
342void  loop() {
343     
344  
345  if (trig_mode != TRIG_SCAN) {
346      unsigned long st = millis();
347      byte oad;
348      if (trig_ch == 0)
349        oad = adRead(ad_ch0, ch0_mode, ch0_off);
350      else
351        oad = adRead(ad_ch1, ch1_mode, ch1_off);
352      for (;;) {
353        byte ad;
354        if (trig_ch == 0)
355          ad = adRead(ad_ch0, ch0_mode, ch0_off);
356        else
357          ad = adRead(ad_ch1, ch1_mode, ch1_off);
358 
359        if (trig_edge == TRIG_E_UP) {
360           if (ad >= trig_lv && ad > oad)
361            break;
362        } else {
363           if (ad <= trig_lv && ad < oad)
364            break;
365        }
366        oad = ad;
367        
368       
369        CheckSW();
370       
371        if (trig_mode == TRIG_SCAN)
372          break;
373        if (trig_mode == TRIG_AUTO && (millis() - st) > 100)
374          break;
375      }
376  }
377   
378  // sample and draw depending on the sampling rate
379    if (rate <= 5 && Start) {
380    // change the index for the double buffer
381    if (sample == 0)
382      sample = 2;
383    else
384      sample = 0;
385 
386    if (rate == 0) { // full speed, channel 0 only
387      unsigned long st = millis();
388      for (int i=0; i<SAMPLES; i ++) {
389        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
390      }
391      for (int i=0; i<SAMPLES; i ++)
392        data[sample+1][i] = 0;
393      // Serial.println(millis()-st);
394    } else if (rate == 1) { // full speed, channel 1 only
395      unsigned long st = millis();
396      for (int i=0; i<SAMPLES; i ++) {
397        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
398      }
399      for (int i=0; i<SAMPLES; i ++)
400        data[sample+0][i] = 0;
401      // Serial.println(millis()-st);
402    } else if (rate == 2) { // full speed, dual channel
403      unsigned long st = millis();
404      for (int i=0; i<SAMPLES; i ++) {
405        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
406        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
407      }
408      // Serial.println(millis()-st);
409    } else if (rate >= 3 && rate <= 5) { // .5ms, 1ms or 2ms sampling
410      const unsigned long r_[] = {5000/DOTS_DIV, 10000/DOTS_DIV, 20000/DOTS_DIV};
411      unsigned long st0 = millis();
412      unsigned long st = micros();
413      unsigned long r = r_[rate - 3];
414      for (int i=0; i<SAMPLES; i ++) {
415        while((st - micros())<r) ;
416        st += r;
417        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
418        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
419      }
420      // Serial.println(millis()-st0);
421    }
422    ClearAndDrawGraph();
423    CheckSW();
424    DrawGrid();
425    DrawText();
426  } else if (Start) { // 5ms - 500ms sampling
427  // copy currently showing data to another
428    if (sample == 0) {
429      for (int i=0; i<SAMPLES; i ++) {
430        data[2][i] = data[0][i];
431        data[3][i] = data[1][i];
432      }
433    } else {
434      for (int i=0; i<SAMPLES; i ++) {
435        data[0][i] = data[2][i];
436        data[1][i] = data[3][i];
437      }     
438    }
439 
440    const unsigned long r_[] = {50000/DOTS_DIV, 100000/DOTS_DIV, 200000/DOTS_DIV,
441                      500000/DOTS_DIV, 1000000/DOTS_DIV, 2000000/DOTS_DIV,
442                      5000000/DOTS_DIV, 10000000/DOTS_DIV};
443    unsigned long st0 = millis();
444    unsigned long st = micros();
445    for (int i=0; i<SAMPLES; i ++) {
446      while((st - micros())<r_[rate-6]) {
447        CheckSW();
448        if (rate<6)
449          break;
450      }
451      if (rate<6) { // sampling rate has been changed
452        tft.fillScreen(BGCOLOR);
453        break;
454      }
455      st += r_[rate-6];
456      if (st - micros()>r_[rate-6])
457          st = micros(); // sampling rate has been changed to shorter interval
458      if (!Start) {
459         i --;
460         continue;
461      }
462      data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
463      data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
464      ClearAndDrawDot(i);    
465    }
466    // Serial.println(millis()-st0);
467    DrawGrid();
468    DrawText();
469  } else {
470    CheckSW();
471  }
472  if (trig_mode == TRIG_ONE)
473    Start = 0;
474     
475}

Но надписи перед самой сеткой почему то в самом верху экрана и не видны 

areht
Offline
Зарегистрирован: 14.03.2015

-

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

Всем привет!

В свободное время доработал Пультоскоп! 

Было так- https://youtu.be/OuyTVQXz458

Это еще не финал, но уже видно что он подрос стал на голову быстрее и дружелюбнее.

 

Рендерится звук и заливается на ютуб.

Сегодня выложу видео.

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

Здорово получается. А как он справляется с изменяющимся сигналом имеющим несколько гармоник? В нём нет синхронизации, она будет реализована паузой, записью определённого количества выборок и её отображением на дисплей с возможностью сдвига в обе стороны для просмотра? Хотелось бы увидеть на видео изменяющийся сигнал с гармониками и на верхнем пределе возможности, тоесть увеличивать частоту отображаемого сигнала, растяжку его по времени. Вещь замечательная, для тех кто занимается чисто Ардуино или вообще низкочастотными цифровыми сигналами, как переносной логический проник.

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

Gres Привет!

Перед тем как отвечать скажу сразу, хорошие вопросы мне обычно подсказывают как и что улучшить!)

Теперь по рядку

--Для него самой тяжело отображаемый сигнал это меандр, все что имеет скругленные форму может отображаться на более высоких частотах.Гармоники покажу на следующем видео.

--Синхронизацию могу реализовать пока только програмно, запись данных в буфер и отображение буфера с учетом оной. Пауза будет только замораживать отображение без прокрутки, кнопками будем листать не буфер в зад и вперед, а заново его наполнять. Если будет работать неудобно изменю.

--Тест верхних пределов будет в следующем видео в разогнанном состоянии и в стоковом.

Пока доступна полоса пропускания в стоке 300К и в разгоне 600К. Очень хочется реализовать эфект стробоскопа чтоб увеличить полосу пропускания до 8МГц, пробовал по быстрому написать не получилось((

 

fly245
fly245 аватар
Offline
Зарегистрирован: 25.08.2013

Отличный прибор получается!Буду следить,обязательно за ходом разработки.Такой прибор очень нужен.Пока буду использовать на экране 5110.Автор-спасибо огромное за труды!!!!

Joiner
Offline
Зарегистрирован: 04.09.2014

Очень понравился приборчик! Ждем с нетерпением публикации.

Автору УВАЖУХА!!!

Jtest
Offline
Зарегистрирован: 02.06.2015

bodriy2014, привет! Отличный прибор получается. Четкие задачи, выполнение на высоком уровне! Скажи какие компоненты сейчас ипользуются, чтоб можно было потихоньку прикупать. То идти они могут очень долго. Arduino 5ти вольтовая? Питание сам делал или модуль? Экран любой определенного разрешения или конкретная модель? Какая? О чем еще нужно заранее позаботиться?

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

Jtest Привет.

--Ардуино 5В любая с микроконтроллером Atmega328(uno,nano,pro mini) и большим кварцем чтоб можно было выпаять.

--дисплей у меня TFT 2.4 дюйма 240*320 на контроллере spfd5408 купил у местного перекупа чтоб не ждать.

--буду делать доп. версию для дисплея 5110/3310 их у меня много и каждый сможет найти легко себе такой.

--хорошо прокоментирую код чтоб могли себе менять под любые дисплеи.

По питание каждый пусть себе сам выбирает модуль готовый или напрямую от USB, то что я впихнул покажу в видео.

Jtest
Offline
Зарегистрирован: 02.06.2015

bodriy2014, Да... планов настроенно!)) Удачи в их реализации! Я пока прикуплю ардуинку, может чего с дисплеем решу (есть в наличии китайские телефоны с дисплеями такого разрешения, нужно выяснить на каких контроллерах они работают).

onegin
Offline
Зарегистрирован: 14.10.2015

bodriy2014, приветствую Вас. Респект Вам за проделанную работу.  А новый экранчик у Вас вроде бы сенсорный, отчего же решили управление кнопочками делать?