Мини осциллограф 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,все работает прекрасно! Убрал моргание экрана,добавил раскраски.

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

#include <Adafruit_GFX.h>
// #include <Adafruit_PCD8544.h>
#include <SPI.h>
#include <FreqCount.h>

#include <TFT_ILI9163C.h>

// Color definitions
#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

#define __CS 10
#define __DC 9

TFT_ILI9163C tft = TFT_ILI9163C(__CS, 8, __DC);
#define DISPLAY_WIDTH 128
#define DISPLAY_HEIGHT 128
#define ARDUINO_PRECISION 1023.0
// Adafruit_PCD8544 display = Adafruit_PCD8544(14, 13, 12, 11, 10);
int channelAI = A4;      //вход сигнала А5, частоту меряем на 5!!!
int PINakum = A6;      //вход замера аккумулдятора
int delayAI = A5;       //делитель нп потенциометре
int razv = 0;// константы и пины добавления развертки
int oldRazv=0;
#define DELAY_POTENTIMETER
#ifdef DELAY_POTENTIMETER
#endif

float delayVariable = 0;
float scale = 0;
int xCounter = 0;
int yPosition = 0;
int readings[DISPLAY_WIDTH + 1];
int oldReadings[DISPLAY_WIDTH + 1];
int counter = 0;
unsigned long drawtime = 0;
unsigned long lastdraw = 0;
unsigned long count = 0;
int frames = 0;
float analog=0;
unsigned long oldCount=0;
void setup()
{
  FreqCount.begin(1000);
  tft.begin();  
  tft.setRotation(3);
  tft.fillScreen(BLACK);
  tft.setCursor(25, 5);
  tft.print("PULTOSCOPE");
  tft.setCursor(15, 15);
  tft.print("Mobile v1.1");
  //#################тест аккумулятора
  if ((analogRead(PINakum) / ARDUINO_PRECISION * 5.0) > 3.3) {
    tft.setCursor(10, 30);
    tft.print("Test Batt OK!");
  }
  if ((analogRead(PINakum) / ARDUINO_PRECISION * 5.0) < 3.3) {
    tft.setCursor(10, 30);
    tft.print("Test Batt NO!");
  }
  tft.setCursor(40, 45);
  tft.print(analogRead(PINakum) / ARDUINO_PRECISION * 5.0);
  tft.print("V");
  //tft.display(0);
  delay(3000);
  tft.clearScreen();
  //#######################
}
void loop()
{
#ifdef DELAY_POTENTIMETER
  delayVariable = analogRead(delayAI);
  delayVariable = (delayVariable / 100); //делитель регулирует выборку
#endif
  //scale = (float)(DISPLAY_HEIGHT-1)/ARDUINO_PRECISION;
  scale = 127 / 1210.0; //ограничиваем диаграмму на один символ сверху
  //##############################################разделение шкалы по сигналу
  for (xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    oldReadings[xCounter] = readings[xCounter];
  }
  for (xCounter = 0; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    yPosition = analogRead(channelAI);
    readings[xCounter] = (yPosition * scale);
#ifdef DELAY_POTENTIMETER
    delay (delayVariable );
#endif
  }
  //##############################################шкала напряжений
  tft.drawLine( 10, 20, 10, DISPLAY_HEIGHT - 1, RED);
  tft.drawLine( 5, (DISPLAY_HEIGHT - 1) - (.2 * ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT - 1) - (.2 * ARDUINO_PRECISION * scale), RED);
  tft.drawLine( 5, (DISPLAY_HEIGHT - 1) - (.4 * ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT - 1) - (.4 * ARDUINO_PRECISION * scale), RED);
  tft.drawLine( 5, (DISPLAY_HEIGHT - 1) - (.6 * ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT - 1) - (.6 * ARDUINO_PRECISION * scale), RED);
  tft.drawLine( 5, (DISPLAY_HEIGHT - 1) - (.8 * ARDUINO_PRECISION * scale), 10, (DISPLAY_HEIGHT - 1) - (.8 * ARDUINO_PRECISION * scale), RED);
  tft.setTextColor(MAGENTA);
  tft.setCursor(0, ((DISPLAY_HEIGHT - 1) - (.2 * ARDUINO_PRECISION * scale)) - 3);
  tft.print((int)(5.0 * 0.2));
  tft.setCursor(0, ((DISPLAY_HEIGHT - 1) - (.4 * ARDUINO_PRECISION * scale)) - 3);
  tft.print((int)(5.0 * 0.4));
  tft.setCursor(0, ((DISPLAY_HEIGHT - 1) - (.6 * ARDUINO_PRECISION * scale)) - 3);
  tft.print((int)(5.0 * 0.6));
  tft.setCursor(0, ((DISPLAY_HEIGHT - 1) - (.8 * ARDUINO_PRECISION * scale)) - 3);
  tft.print((int)(5.0 * 0.8));
  //##############################################отрисовка сигнала

  for (xCounter = 14; xCounter <= DISPLAY_WIDTH; xCounter++)
  {
    tft.drawPixel(xCounter, (DISPLAY_HEIGHT - 1) - readings[xCounter], RED);
    if (xCounter > 1) {
      tft.drawLine(xCounter - 1, (DISPLAY_HEIGHT - 1) - oldReadings[xCounter - 1], xCounter, (DISPLAY_HEIGHT - 1) - oldReadings[xCounter], BLACK);
      tft.drawLine(xCounter - 1, (DISPLAY_HEIGHT - 1) - readings[xCounter - 1], xCounter, (DISPLAY_HEIGHT - 1) - readings[xCounter], RED);
    }
  }
   
  tft.setTextColor(BLACK);
  tft.setCursor(90, 5);
  tft.print(oldRazv);
  tft.setTextColor(WHITE);
  tft.setCursor(90, 5);
  tft.print(razv);
  oldRazv=razv;

  //############################################вывод напряжения
  tft.setTextColor(BLACK);
  tft.setCursor(5, 5);
  tft.print(analog);
  tft.setTextColor(WHITE);
  tft.setCursor(5, 5);
  analog= analogRead(channelAI) / ARDUINO_PRECISION * 5.0;
  tft.print(analog);
  tft.print("V");
  
  if (count < 1000) {
    tft.setTextColor(BLACK);
    tft.setCursor(42, 5);
    tft.print(count);
    tft.print("Hz");
  }
  if (count > 1000) {
    tft.setTextColor(BLACK);
    tft.setCursor(42, 5);
    tft.print((count) / 1000);
    tft.print("KHz");
  }
  if (FreqCount.available()) {
    count = FreqCount.read();
  }
  if (count < 1000) {
    tft.setTextColor(MAGENTA);
    tft.setCursor(42, 5);
    tft.print(count);
    tft.print("Hz");
  }
  if (count > 1000) {
    tft.setTextColor(MAGENTA);
    tft.setCursor(42, 5);
    tft.print((count) / 1000);
    tft.print("KHz");
  }
  if (digitalRead(2) == HIGH) // проверяем состояние кнопки
  {
    razv = razv + 5;
  }
  if (digitalRead(3) == HIGH) // проверяем состояние кнопки
  {
    razv = razv - 5;
    if (razv < 0) // проверяем состояние кнопки
    {
      razv = 0;
    }
  }
  delay(razv);//регулирует частоту выборки
}

 

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

#include "TFTLCD.h"

#define LCD_CS A3
#define LCD_CD A2
#define LCD_WR A1
#define LCD_RD A0
#define LCD_RESET A4

#define  BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0 
#define WHITE           0xFFFF

TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);

 //#include <Arial14.h>  // font definitions 

#define txtLINE0   0
#define txtLINE1   16
#define txtLINE2   30
#define txtLINE3   46

const int LCD_WIDTH = 320;
const int LCD_HEIGHT = 240;
const int SAMPLES = 270;
const int DOTS_DIV = 30;


int sensorValue = 0; 
const int ad_sw = 3;                    // Analog 3 pin for switches
const int ad_ch0 = 5;                   // Analog 6 pin for channel 0
const int ad_ch1 = 7;                   // Analog 7 pin for channel 1
const unsigned long VREF[] = {150, 300, 750, 1500, 3000}; // reference voltage 5.0V ->  150 :   1V/div range (100mV/dot)
                                        // It means 5.0 * DOTS_DIV = 150. Use 4.9 if reference voltage is 4.9[V]
                                        //                        -> 300 : 0.5V/div
                                        //                        -> 750 : 0.2V/div
                                        //                        ->1500 : 100mV/div
                                        //                       -> 3000 :  50mV/div
const int MILLIVOL_per_dot[] = {33, 17, 6, 3, 2}; // mV/dot
const int MODE_ON = 0;
const int MODE_INV = 1;
const int MODE_OFF = 2;
const char *Modes[] = {" NORM", " INV", " OFF"};
const int TRIG_AUTO = 0;
const int TRIG_NORM = 1;
const int TRIG_SCAN = 2;
const int TRIG_ONE  = 3;
const char *TRIG_Modes[] = {" Auto", " Norm", " Scan", " One"};
const int TRIG_E_UP = 0;
const int TRIG_E_DN = 1;
#define RATE_MIN 0
#define RATE_MAX 13
const char *Rates[] = {"F1-1", "F1-2 ", "F2  ", "5ms", "10ms", "20ms", "50ms", "0.1s", "0.2s", "0.5s", "1s", "2s", "5s", "10s"};
#define RANGE_MIN 0
#define RANGE_MAX 4
const char *Ranges[] = {"1V ", "0.5V", "0.2V", "0.1V", "50mV"};
unsigned long startMillis;
byte data[4][SAMPLES];                   // keep twice of the number of channels to make it a double buffer
byte sample=0;                           // index for double buffer

///////////////////////////////////////////////////////////////////////////////////////////////
// Define colors here
#define   BGCOLOR  BLACK
#define   GRIDCOLOR WHITE
#define CH1COLOR  BLUE
#define CH2COLOR  GREEN

// Declare variables and set defaults here
// Note: only ch1 is available with Aitendo's parallel 320x240 TFT LCD  
byte range0 = RANGE_MIN, ch0_mode = MODE_ON;  // CH0
short ch0_off = 204;
byte range1 = RANGE_MIN, ch1_mode = MODE_ON;  // CH1
short ch1_off = 204;
byte rate = 3;                                // sampling rate
byte trig_mode = TRIG_AUTO, trig_lv = 30, trig_edge = TRIG_E_UP, trig_ch = 1; // trigger settings
byte Start = 1;  // Start sampling
byte menu = 0;  // Default menu
///////////////////////////////////////////////////////////////////////////////////////////////

void setup(){
  tft.reset();
  tft.initDisplay();
  tft.setRotation(1);

  tft.fillScreen(BGCOLOR);

  tft.setTextColor(WHITE);
  tft.setTextSize(2);
  tft.setCursor(0, 0);
  tft.print("Arduino Oscillo Scope");
  tft.setCursor(25, 100);
  tft.print("with Aitendo TFT LCD (320x240)");
  tft.setCursor(75, 240);
  tft.print("(c) 2009-2014 non");
  
  delay(2000);

  tft.fillScreen(BGCOLOR);
   
  Serial.begin(9600);
  DrawGrid();
  DrawText();
}

void CheckSW() {
  static unsigned long Millis = 0, oMillis = 0;
  unsigned long ms;
  unsigned short ain = analogRead(ad_sw); 
 //Serial.println(ain);
  return;
  ms = millis();
  if ((ms - Millis)<5)
  return;
  Millis = ms;
  oMillis = Millis;
   //Serial.println(ain);
  DrawText();
}

void menu0_sw(int sw) {  
  switch (sw) {
   case 0:
    // START/HOLD
    if (Start)
       Start = 0;
     else
       Start = 1;
    break;
   case 1:
    // CH0 RANGE -
    if (range0 < RANGE_MAX)
      range0 ++;
    break;
   case 2:
    // CH1 RANGE -
    if (range1 < RANGE_MAX)
      range1 ++;
    break;
   case 3:
    // RATE FAST
    if (rate > 0)
      rate --;
    break;
   case 4:
    // TRIG MODE
    if (trig_mode < TRIG_ONE)
      trig_mode ++;
    else
      trig_mode = 0;
    break;
   case 5:
    // SEND
    SendData();
    break;
   case 6:
    // TRIG MODE
    if (trig_mode > 0)
      trig_mode --;
    else
      trig_mode = TRIG_ONE;
    break;
   case 7:
    // RATE SLOW
    if (rate < RATE_MAX)
      rate ++;
    break;
   case 8:
    // CH1 RANGE +
    if (range1 > 0)
      range1 --;
    break;
   case 9:
    // CH0 RANGE +
    if (range0 > 0)
      range0 --;
    break;
   case 10:
   default:
    // MENU SW
    menu ++;
     break;
  }
}



void SendData() {
  Serial.print(Rates[rate]);
  Serial.println("/div (30 samples)");
  for (int i=0; i<SAMPLES; i ++) {
      Serial.print(data[sample + 0][i]*MILLIVOL_per_dot[range0]);
      Serial.print(" ");
      Serial.println(data[sample + 1][i]*MILLIVOL_per_dot[range1]);
   } 
}

void DrawGrid() {
    for (int x=0; x<=SAMPLES; x += 2) { // Horizontal Line
      for (int y=0; y<=LCD_HEIGHT; y += DOTS_DIV) {
        tft.drawPixel(x, y, GRIDCOLOR);
        CheckSW();
      }
      if (LCD_HEIGHT == 240)
        tft.drawPixel(x, LCD_HEIGHT-1, GRIDCOLOR);
    }
    for (int x=0; x<=SAMPLES; x += DOTS_DIV ) { // Vertical Line
      for (int y=0; y<=LCD_HEIGHT; y += 2) {
        tft.drawPixel(x, y, GRIDCOLOR);
        CheckSW();
      }
    }
}

void DrawText() {
  tft.setTextColor(YELLOW);
  tft.setTextSize(1);
  tft.setCursor(SAMPLES+3, 5);
  tft.print(Ranges[range1]);
  tft.println("/DIV");
  tft.setCursor(SAMPLES+3, 15);
  tft.print(Rates[rate]);
  tft.println("/DIV");
  tft.setCursor(SAMPLES+3, 25);
  tft.println(TRIG_Modes[trig_mode]);
  tft.setCursor(SAMPLES+3, 35);
  tft.println(trig_edge == TRIG_E_UP ? "UP" : "DN"); 
  tft.setCursor(SAMPLES+3, 45);
  tft.println(Modes[ch1_mode]);
  tft.setCursor(SAMPLES+3, 60);
  tft.setTextColor(RED);
  tft.println(" 5 V");
   tft.setCursor(SAMPLES+3, 90);
  tft.println(" 4 V");
  tft.println("");
   tft.setCursor(SAMPLES+3, 120);
  tft.println(" 3 V");
  tft.println("");
   tft.setCursor(SAMPLES+3, 150);
  tft.println(" 2 V");
  tft.println("");
  tft.setCursor(SAMPLES+3, 180);
  tft.println(" 1 V");
  tft.println("");
  tft.setCursor(SAMPLES+3, 210);
  tft.println(" 0 V");
//  tft.setCursor(SAMPLES, 70);
//  tft.println(trig_ch == 0 ? "T:1" : "T:2"); 

}

void DrawGrid(int x) {
    if ((x % 2) == 0)
      for (int y=0; y<=LCD_HEIGHT; y += DOTS_DIV)
        tft.drawPixel(x, y, GRIDCOLOR);
    if ((x % DOTS_DIV) == 0)
      for (int y=0; y<=LCD_HEIGHT; y += 2)
        tft.drawPixel(x, y, GRIDCOLOR);
}

void ClearAndDrawGraph() {
  int clear = 0;
  
  if (sample == 0)
    clear = 2;
#if 0
   for (int x=0; x<SAMPLES; x++) {
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+0][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+1][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+0][x], BLACK);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+1][x], BLACK);
  }
#else
   for (int x=0; x<(SAMPLES-1); x++) {
     tft.drawLine(x, LCD_HEIGHT-data[clear+0][x], x+1, LCD_HEIGHT-data[clear+0][x+1], BGCOLOR);
     tft.drawLine(x, LCD_HEIGHT-data[clear+1][x], x+1, LCD_HEIGHT-data[clear+1][x+1], BGCOLOR);
     if (ch0_mode != MODE_OFF)
       tft.drawLine(x, LCD_HEIGHT-data[sample+0][x], x+1, LCD_HEIGHT-data[sample+0][x+1], CH1COLOR);
     if (ch1_mode != MODE_OFF)
       tft.drawLine(x, LCD_HEIGHT-data[sample+1][x], x+1, LCD_HEIGHT-data[sample+1][x+1], CH2COLOR);
     CheckSW();
  }  
#endif
}

void ClearAndDrawDot(int i) {
  int clear = 0;

  if (i <= 1)
    return;
  if (sample == 0)
    clear = 2;
#if 0
   for (int x=0; x<SAMPLES; x++) {
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+0][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[clear+1][x], WHITE);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+0][x], BLACK);
     GLCD.SetDot(x, LCD_HEIGHT-data[sample+1][x], BLACK);
  }
#else
  tft.drawLine(i-1, LCD_HEIGHT-data[clear+0][i-1], i, LCD_HEIGHT-data[clear+0][i], BGCOLOR);
  tft.drawLine(i-1, LCD_HEIGHT-data[clear+1][i-1], i, LCD_HEIGHT-data[clear+1][i], BGCOLOR);
  if (ch0_mode != MODE_OFF)
    tft.drawLine(i-1, LCD_HEIGHT-data[sample+0][i-1], i, LCD_HEIGHT-data[sample+0][i], CH1COLOR);
  if (ch1_mode != MODE_OFF)
    tft.drawLine(i-1, LCD_HEIGHT-data[sample+1][i-1], i, LCD_HEIGHT-data[sample+1][i], CH2COLOR);
#endif
  DrawGrid(i);
}

void DrawGraph() {
   for (int x=0; x<SAMPLES; x++) {
     tft.drawPixel(x, LCD_HEIGHT-data[sample+0][x], CH1COLOR);
     tft.drawPixel(x, LCD_HEIGHT-data[sample+1][x], CH2COLOR);
  }
}

void ClearGraph() {
  int clear = 0;
  
  if (sample == 0)
    clear = 2;
  for (int x=0; x<SAMPLES; x++) {
     tft.drawPixel(x, LCD_HEIGHT-data[clear+0][x], BGCOLOR);
     tft.drawPixel(x, LCD_HEIGHT-data[clear+1][x], BGCOLOR);
  }
}

inline unsigned long adRead(byte ch, byte mode, int off)
{
  unsigned long a = analogRead(ch);
  a = ((a+off)*VREF[ch == ad_ch0 ? range0 : range1]+512) >> 10;
  a = a>=(LCD_HEIGHT+1) ? LCD_HEIGHT : a;
  if (mode == MODE_INV)
    return LCD_HEIGHT - a;
  return a;
}

void  loop() {
    
 
  if (trig_mode != TRIG_SCAN) {
      unsigned long st = millis();
      byte oad;
      if (trig_ch == 0)
        oad = adRead(ad_ch0, ch0_mode, ch0_off);
      else
        oad = adRead(ad_ch1, ch1_mode, ch1_off);
      for (;;) {
        byte ad;
        if (trig_ch == 0)
          ad = adRead(ad_ch0, ch0_mode, ch0_off);
        else
          ad = adRead(ad_ch1, ch1_mode, ch1_off);

        if (trig_edge == TRIG_E_UP) {
           if (ad >= trig_lv && ad > oad)
            break; 
        } else {
           if (ad <= trig_lv && ad < oad)
            break; 
        }
        oad = ad;
       
      
        CheckSW();
      
        if (trig_mode == TRIG_SCAN)
          break;
        if (trig_mode == TRIG_AUTO && (millis() - st) > 100)
          break; 
      }
  }
  
  // sample and draw depending on the sampling rate
    if (rate <= 5 && Start) {
    // change the index for the double buffer
    if (sample == 0)
      sample = 2;
    else
      sample = 0;

    if (rate == 0) { // full speed, channel 0 only
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
      }
      for (int i=0; i<SAMPLES; i ++)
        data[sample+1][i] = 0;
      // Serial.println(millis()-st);
    } else if (rate == 1) { // full speed, channel 1 only
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      for (int i=0; i<SAMPLES; i ++)
        data[sample+0][i] = 0;
      // Serial.println(millis()-st);
    } else if (rate == 2) { // full speed, dual channel
      unsigned long st = millis();
      for (int i=0; i<SAMPLES; i ++) {
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      // Serial.println(millis()-st);
    } else if (rate >= 3 && rate <= 5) { // .5ms, 1ms or 2ms sampling
      const unsigned long r_[] = {5000/DOTS_DIV, 10000/DOTS_DIV, 20000/DOTS_DIV};
      unsigned long st0 = millis();
      unsigned long st = micros();
      unsigned long r = r_[rate - 3];
      for (int i=0; i<SAMPLES; i ++) {
        while((st - micros())<r) ;
        st += r;
        data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
        data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      }
      // Serial.println(millis()-st0);
    }
    ClearAndDrawGraph();
    CheckSW();
    DrawGrid();
    DrawText();
  } else if (Start) { // 5ms - 500ms sampling
  // copy currently showing data to another
    if (sample == 0) {
      for (int i=0; i<SAMPLES; i ++) {
        data[2][i] = data[0][i];
        data[3][i] = data[1][i];
      }
    } else {
      for (int i=0; i<SAMPLES; i ++) {
        data[0][i] = data[2][i];
        data[1][i] = data[3][i];
      }      
    }

    const unsigned long r_[] = {50000/DOTS_DIV, 100000/DOTS_DIV, 200000/DOTS_DIV,
                      500000/DOTS_DIV, 1000000/DOTS_DIV, 2000000/DOTS_DIV, 
                      5000000/DOTS_DIV, 10000000/DOTS_DIV};
    unsigned long st0 = millis();
    unsigned long st = micros();
    for (int i=0; i<SAMPLES; i ++) {
      while((st - micros())<r_[rate-6]) {
        CheckSW();
        if (rate<6)
          break;
      }
      if (rate<6) { // sampling rate has been changed
        tft.fillScreen(BGCOLOR);
        break;
      }
      st += r_[rate-6];
      if (st - micros()>r_[rate-6])
          st = micros(); // sampling rate has been changed to shorter interval
      if (!Start) {
         i --;
         continue;
      }
      data[sample+0][i] = adRead(ad_ch0, ch0_mode, ch0_off);
      data[sample+1][i] = adRead(ad_ch1, ch1_mode, ch1_off);
      ClearAndDrawDot(i);     
    }
    // Serial.println(millis()-st0);
    DrawGrid();
    DrawText();
  } else {
    CheckSW();
  }
  if (trig_mode == TRIG_ONE)
    Start = 0;
    
}

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

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, приветствую Вас. Респект Вам за проделанную работу.  А новый экранчик у Вас вроде бы сенсорный, отчего же решили управление кнопочками делать?