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

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

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

под неё есть готовая библиотека и даже  не одна.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

библиотека это хорошо, но ты сможешь написать код с использованием либы?

 

dtvims
Offline
Зарегистрирован: 26.11.2012

А это и есть оптовый отдел, если зайти ножками в магаз, то цена может превысить данную раз в 5.

Согласен с jeka_tm.

dtvims
Offline
Зарегистрирован: 26.11.2012

Maverik пишет:

кстати, оставь плиз какой-нибудь контакт - аську, скайп чего-нибудь..

Мой скайп точно соответствует нику.

Logik
Offline
Зарегистрирован: 05.08.2014

Внешнее ОЗУ - плохо для осцилографа. Оно медленей в десятки раз. Вам нужен осцилограф для очччень медленнных процессов?! Забавно что ответ на вопрос, как освободить 86 байт содержится в стартовом сообщении. В первом скетче, строка 23. Найдите в ней неизвестное Вам, примените его к Вашему скетчу и память освободится ;)  

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

dtvims пишет:

Еще можно избавиться от загрузчика arduino, воспользоваться AVRStudio и залить прошивку как на чистый МК - еще и место останется. Правда придется переписать чуток саму прошивку - избавиться от функций библиотек arduino. 

Разве загрузчик работает с библиотеками ардуино?  Помоему у него одна функция - принять прошивку (скетч) по serial и разместить её в памяти, после чего передать ей управление. С библиотеками ардуино работает только компилятор. После того как код скомпилирован в двоичный - он должен работать в МК Atmega независимо от наличия в нём загрузчика.

P.S. Залить скетч без загрузчика через программатор можно также из родной Arduino IDE. Необязательно ставить ради этого AVRStudio.

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

Цитата:
Внешнее ОЗУ - плохо для осцилографа. Оно медленей в десятки раз. Вам нужен осцилограф для очччень медленнных процессов?!

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

Цитата:
В первом скетче, строка 23. Найдите в ней неизвестное Вам, примените его к Вашему скетчу и память освободится ;)
первый скетч меня не интересует, он под совершенно другой, маленький экран, поэтому там всё получается. а в 23й строке там по всей видимости логотип Adafruit, которого в нормальном коде (из сообщения номер 50, стр.2) уже нет.

Цитата:
Разве загрузчик работает с библиотеками ардуино?

естественно нет. optiboot например занимает 512 байт. куда ему еще с какими-то библиотеками работать при таком размере ????
Цитата:
P.S. Залить скетч без загрузчика через программатор можно также из родной Arduino IDE.

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

dtvims
Offline
Зарегистрирован: 26.11.2012

Jeka_M пишет:

Разве загрузчик работает с библиотеками ардуино?  

Загрузчик сам по себе, библиотеки Arduino сами по себе. AVRStudio или другая среда соответствующего уровня необходима, прежде всего для удобства программирования и настройки компилятора. AVRStudio хороша именно, что сделана специально для AVR. Arduino среда по любому потащит за собой все библиотеки, что негативно скажется на размере прошивки. А если такая жесткая нелюбовь к студии, то можно обойтись notepad++ и ручным компилированием gcc.

Logik
Offline
Зарегистрирован: 05.08.2014

Maverik пишет:
а откуда дровишки, что эта микросхема такая уж медленная ? она вроде на 20 кГц расчитана, мини про столько не может.
Все познается в сравнении. Основное ОЗУ в МГц меряем. 

Цитата:
Цитата:

В первом скетче, строка 23. Найдите в ней неизвестное Вам, примените его к Вашему скетчу и память освободится ;)

первый скетч меня не интересует, он под совершенно другой, маленький экран, поэтому там всё получается. а в 23й строке там по всей видимости логотип Adafruit, которого в нормальном коде (из сообщения номер 50, стр.2) уже нет.  
 оно  конечно, убрать логотип -  дело не хитрое. Как бы намекну ещё раз;) Слово progmem не вызвало вопросов?

dtvims
Offline
Зарегистрирован: 26.11.2012

Maverik пишет:
спасибо за совет, так и сделал, скетч загрузился но только в белый экран, видимо чего-то я лишнего стёр )) ладно, на выходных поищу.

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

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

dtvims пишет:

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

ааа, вон оно чо... фьюзы то я и не заметил...

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

придется ставить авр студио, разбираться.

dtvims
Offline
Зарегистрирован: 26.11.2012

Я пользую для записи на чип прогу SinaProg, там есть удобный редактор фьюзов. Должна быть опция вроде BOOTSZ0 

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

Logik пишет:

Слово progmem не вызвало вопросов?

я так понимаю, что в флеш имеет смысл сбрасывать только то, что, не будет особо крутиться в RAM.

иначе смысл просто пропадает. а там такого особо и нет, всё что было строковое для общения через уарт я просто стёр.

MickeySL
Offline
Зарегистрирован: 22.07.2014

Всем спасибо за эту полезную тему.

Срочно понадобился осциллограф. Под рукой оказались: arduino nano и дисплей 12864.

Пришлось доработать код в двух местах:

1) доработка раз:

const byte theAnalogPin = A0;             // Data read pin
 
//const byte lcdLED = 6;                   // LED Backlight
//const byte lcdA0 = 7;                    // Data and command selections. L: command  H : data
//const byte lcdRESET = 8;                 // Low reset
//const byte lcdCS = 9;                    // SPI Chip Select (internally pulled up), active low
//const byte lcdMOSI = 11;                 // SPI Data transmission
//const byte lcdSCK = 13;                  // SPI Serial Clock

 
// SW SPI:
//U8GLIB_MINI12864 u8g(lcdSCK, lcdMOSI, lcdCS, lcdA0, lcdRESET);
// HW SPI:
//U8GLIB_MINI12864 u8g(lcdSCK, lcdMOSI, lcdCS, lcdA0, lcdRESET);
U8GLIB_ST7920_128X64_1X u8g(8, 9, 10, 11, 4, 5, 6, 7, 18, 17, 16);   // 8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, di=17,rw=16

2) доработка два:

  // Turn on LED backlight
  //analogWrite(lcdLED, ledBacklight);

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

Ну и задняя часть дисплея, с описанием выводов:

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

хм, с ILI9340 всё оказалось еще проще - не заработали даже стандартные примеры из библиотек TFTLCD,  Adafruit_TFTLCD.

разбираться было влом, т.к. стандартные примеры работали из библиотеки Adafruit_ILI9340, ее и взял за основу, заточил скетч под нее, всё заработало с полпинка, программа использует  1 кб озу, отлично!  

а микросхемы памяти где-то всё еще едут... ну, пригодятся для чего-нибудь ))

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

Maverik пишет:

хм, с ILI9340 всё оказалось еще проще - не заработали даже стандартные примеры из библиотек TFTLCD,  Adafruit_TFTLCD.

разбираться было влом, т.к. стандартные примеры работали из библиотеки Adafruit_ILI9340, ее и взял за основу, заточил скетч под нее, всё заработало с полпинка, программа использует  1 кб озу, отлично!  

а микросхемы памяти где-то всё еще едут... ну, пригодятся для чего-нибудь ))

Исходник будете публиковать?

Петро
Offline
Зарегистрирован: 03.02.2015

Можете выложить схему подключения этого дисплея? Уже неделю над ним бьюсь...

sandr4
sandr4 аватар
Offline
Зарегистрирован: 11.02.2015

Вот здесь , то-ли итальянец то-ли француз, забульбенил замечательную штуку на друине и LCD Nokia 5110. Скачал, залил в Mega mini pro - всё работает. Только у меня джойстика для управления нет, и не разобрался пока куда что цеплять. 

ggeevv-ss
Offline
Зарегистрирован: 05.03.2015

Доброго времени суток! Можете помочь с распиновкой WD-X0908V. Просьба в Google не отсылайте, пожалуйста, так как там только лишь похожие вопросы на форумах на разных языках, но ответа ни одного не найти. Может оно бы и проще выкинуть этот экран, но во-первых в проекте нужен дисплей "чем меньше - тем лучше", так как это будет носимый на руке гаджет, а покупать другой пока финансы не позволяют, ибо студент...

Вот фото этого малыша:

Как запасной вариант рассматривался дисплей от SonyEricsson J110i, но это тоже "популярный" по запросам и, увы, "безответный" WD-X0906XQ...

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

http://vrtp.ru/index.php?s=337472604dab8bb72ee7489b90a4d5b8&showtopic=11...

тут подскажут.хз откуда они все это берут по дисплеям

dtvims
Offline
Зарегистрирован: 26.11.2012

Надо искать отталкиваясь от модели мобильного телефона.

Вот что удалось найти: http://kazus.ru/forums/showthread.php?p=146144

Вот тут собрал небольшую подборку схем: http://www.rukodelie-ds.ru/platy/motorola_v3.zip - там везде используется вторым данный дисплей, но на схемах найти его как-то тяжко, но думаю можно.

Удачи! Только если получится подключить, Вы выложите для потомков :)

ggeevv-ss
Offline
Зарегистрирован: 05.03.2015

jeka_tm, dtvims Спасибо!

dtvims пишет:

Вот что удалось найти: http://kazus.ru/forums/showthread.php?p=146144

Вот тут собрал небольшую подборку схем: http://www.rukodelie-ds.ru/platy/motorola_v3.zip - там везде используется вторым данный дисплей, но на схемах найти его как-то тяжко, но думаю можно.

Вот на kazus-e написали как раз: "Протокола обмена, ненайдёшь наверное. Вообщем геморой с ним возиться, нет смысла.". Советуют от нокии всё-таки... За подборку огромное СПАСИБО! (И где Вы её только накопали? Не поделитесь источником?:) ) Конечно попробую подключить его, не впервой гемороиться... Но видно, придется-таки заказывать от нокии, ну "про всякий случай" хотя бы, применение всё-равно найдётся, были бы детали.

dtvims пишет:

Только если получится подключить, Вы выложите для потомков :)

dtvims, Обязательно! )

ggeevv-ss
Offline
Зарегистрирован: 05.03.2015

dtvims пишет:

Удачи! 

Ещё раз спасибо!

dtvims
Offline
Зарегистрирован: 26.11.2012

Брал схемы тут: http://monitor.net.ru/forum/

Предварительно, нашел совместимость этого монитора по моделям телефонов.

Тупо было интересно смогу ли что найти... Понял только то, что можно попытаться поискать что-то аналогичное (другие дисплеи от моторолы похожего типа) и попытаться по аналогии подключиться к Вашему дисплею. Скорее всего там одинаковые контроллеры дисплея или их все-равно немного. Схема подключения вроде есть, значит осталось угадать протокол, а он от контроллера зависит. Как-то так, наверное...

ng0d
Offline
Зарегистрирован: 04.05.2013

Валяется дисплей от Nokia 5800. Может кто подключал такой?

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

Я тут осцилограф слегка допилил до 2-х канального. И пересадил на Adafruit_ST7735. Оставлю тут для истории.

 

Без общения с Serial получается

Sketch uses 14,466 bytes (47%) of program storage space. Maximum is 30,720 bytes.

Global variables use 881 bytes (43%) of dynamic memory, leaving 1,167 bytes for local variables. Maximum is 2,048 bytes.
 
Из минусов - он (возможно) медленнее. Но точнее. Раньше скриптик частоту сети 52 герца показывал.
Ну и с Serial слегка глючит
#include <SPI.h>
#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library

#define DOUBLESAMPLES

#ifdef DOUBLESAMPLES
#define NEW_TIMING
#define SERIAL_ENABLED
#else
#define NEW_TIMING
#define SERIAL_ENABLED
#endif

// For the breakout, you can use any 2 or 3 pins
// These pins will also work for the 1.8" TFT shield
#define TFT_CS     10
#define TFT_RST    0  // you can also connect this to the Arduino reset
// in which case, set this #define pin to 0!
#define TFT_DC     9

// Option 1 (recommended): must use the hardware SPI pins
// (for UNO thats sclk = 13 and sid = 11) and pin 10 must be
// an output. This is much faster - also required if you want
// to use the microSD card (see the image drawing example)
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS,  TFT_DC, TFT_RST);

// Option 2: use any pins but a little slower!
#define TFT_SCLK 13   // set these to be whatever pins you like!
#define TFT_MOSI 11   // set these to be whatever pins you like!
//Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);

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

// Variables you might want to play with
byte useThreshold = 1;                  // 0 = Off, 1 = Rising, 2 = Falling
byte theThreshold = 50;                // 0-255, Multiplied by voltageConst
unsigned int timePeriod = 250;          // 0-65535, us or ms per measurement (max 0.065s or 65.535s)
byte voltageRange = 0;                  // 1 = 0-3.3V, 2 = 0-1.65V, 3 = 0-0.825V
byte ledBacklight = 100;

boolean autoHScale = false;             // Automatic horizontal (time) scaling
boolean linesNotDots = false;            // Draw lines between data points

// Variables that can probably be left alone
const byte vTextShift = 44;              // Vertical text shift (to vertically align info)
const byte numOfSamples = 160;          // Leave at 100 for 128x64 pixel display
unsigned int HQadcReading1;
#ifdef NEW_TIMING
unsigned int HQadcReading2;
#else
unsigned int HQadcReadings1[numOfSamples];
#endif    
byte adcReadings1[numOfSamples];
byte adcOldReadings1[numOfSamples];

#ifdef DOUBLESAMPLES
byte adcReadings2[numOfSamples];
byte adcOldReadings2[numOfSamples];
#endif
byte thresLocation = 0;                 // Threshold bar location
float voltageConst = 0.079365;          // Scaling factor for converting 0-63 to V
float avgV = 0.0;
float maxV = 0.0;
float minV = 0.0;
float ptopV = 0.0;
float theFreq = 50;

byte OlduseThreshold = 1;
byte OldtheThreshold = 128;
unsigned int OldtimePeriod = 200;
float OldavgV = 0.0;
float OldmaxV = 0.0;
float OldminV = 0.0;
float OldptopV = 0.0;
float OldtheFreq = 0;

const byte theAnalogPin1 = 7;             // Data read pin
#ifdef DOUBLESAMPLES
const byte theAnalogPin2 =5;             // Data read pin
#endif



// High speed ADC code
// From: <a href="<a href="http://forum.arduino.cc/index.php?PHPSESSID=e21f9a71b887039092c91a516f9b0f36&topic=6549.15" rel="nofollow">http://forum.arduino.cc/index.php?PHPSESSID=e21f9a71b887039092c91a516f9b0f36&topic=6549.15</a>" title="<a href="http://forum.arduino.cc/index.php?PHPSESSID=e21f9a71b887039092c91a516f9b0f36&topic=6549.15" rel="nofollow">http://forum.arduino.cc/index.php?PHPSESSID=e21f9a71b887039092c91a516f9b0f36&topic=6549.15</a>" rel="nofollow"><a href="http://forum.arduino.cc/index.php?PHPSESSID=e21f9a71b887039092c91a516f9b..." rel="nofollow">http://forum.arduino.cc/index.php?PHPSESSID=e21f9a71b887039092c91a516f9b...</a></a>
#define FASTADC 0
#define MIN_TIMEPERIOD 100
// defines for setting and clearing register bits
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

void collectData(void) {
  unsigned int tempThres = 0;
  unsigned int i = 0;

  if (autoHScale == true) {
    // With automatic horizontal (time) scaling enabled,
    // scale quickly if the threshold location is far, then slow down
    if (thresLocation > 5 * numOfSamples / 8) {
      timePeriod = timePeriod + 10;
    } else if (thresLocation < 3 * numOfSamples / 8) {
      timePeriod = timePeriod - 10;
    } else if (thresLocation > numOfSamples / 2 + 1) {
      timePeriod = timePeriod + 2;
    } else if (thresLocation < numOfSamples / 2 - 1) {
      timePeriod = timePeriod - 2;
    }
  }
  // Enforce minimum time periods
  if (timePeriod < MIN_TIMEPERIOD) {
    timePeriod = MIN_TIMEPERIOD;
  }

  // Adjust voltage contstant to fit the voltage range
  if (voltageRange == 0) {
    //voltageConst = 0.0793650; // 0-5V
    voltageConst = 4.53/63; // 0-5V
  } else if (voltageRange == 1) {
    voltageConst = 0.0523810; // 0-3.30V
  } else if (voltageRange == 2) {
    voltageConst = 0.0261905; // 0-1.65V
  } else if (voltageRange == 3) {
    voltageConst = 0.0130952; //0-0.825V
  }

  // If using threshold, wait until it has been reached
  if (voltageRange == 0) tempThres = theThreshold << 2;  
  else if (voltageRange == 1) tempThres = theThreshold << 2;  
  else if (voltageRange == 2) tempThres = theThreshold << 1;
  else if (voltageRange == 3) tempThres = theThreshold;
  if (useThreshold == 1) {
    i = 0; while ((analogRead(theAnalogPin1) > tempThres) && (i < 32768)) i++;
    i = 0; while ((analogRead(theAnalogPin1) < tempThres) && (i < 32768)) i++;
  }
  else if (useThreshold == 2) {
    i = 0; while ((analogRead(theAnalogPin1) < tempThres) && (i < 32768)) i++;
    i = 0; while ((analogRead(theAnalogPin1) > tempThres) && (i < 32768)) i++;
  }

  // Collect ADC readings
  for (i = 0; i < numOfSamples; i++) {
#ifdef NEW_TIMING
    unsigned long startTime = micros();
#endif
    // Takes MIN_TIMEPERIOD us with high speed ADC setting
    HQadcReading1 = analogRead(theAnalogPin1);
#ifdef DOUBLESAMPLES
//    HQadcReading2 = analogRead(theAnalogPin2);        
    HQadcReading2 = analogRead(theAnalogPin2);
#endif
#ifndef NEW_TIMING
    HQadcReadings1[i] = HQadcReading1;
#endif    


#ifdef NEW_TIMING
#else
    if (timePeriod > MIN_TIMEPERIOD)
      delayMicroseconds(timePeriod - MIN_TIMEPERIOD);

  }
  for (i = 0; i < numOfSamples; i++) {
    
#endif          
#ifndef NEW_TIMING
    HQadcReading1 = HQadcReadings1[i];
#endif    

       
    // Scale the readings to 0-63 and clip to 63 if they are out of range.
    if (voltageRange == 0) {
      if (HQadcReading1 >> 4 < 0b111111) adcReadings1[i] = HQadcReading1 >> 4 & 0b111111;
      else adcReadings1[i] = 0b111111;
    } else if (voltageRange == 1) {
      if (HQadcReading1 >> 4 < 0b111111) adcReadings1[i] = HQadcReading1 >> 4 & 0b111111;
      else adcReadings1[i] = 0b111111;
    } else if (voltageRange == 2) {
      if (HQadcReading1 >> 3 < 0b111111) adcReadings1[i] = HQadcReading1 >> 3 & 0b111111;
      else adcReadings1[i] = 0b111111;
    } else if (voltageRange == 3) {
      if (HQadcReading1 >> 2 < 0b111111) adcReadings1[i] = HQadcReading1 >> 2 & 0b111111;
      else adcReadings1[i] = 0b111111;
    }
    // Invert for display
    adcReadings1[i] = 63 - adcReadings1[i];
#ifdef DOUBLESAMPLES
    // Scale the readings to 0-63 and clip to 63 if they are out of range.
    if (voltageRange == 0) {
      if (HQadcReading2 >> 4 < 0b111111) adcReadings2[i] = HQadcReading2 >> 4 & 0b111111;
      else adcReadings2[i] = 0b111111;
    } else if (voltageRange == 1) {
      if (HQadcReading2 >> 4 < 0b111111) adcReadings2[i] = HQadcReading2 >> 4 & 0b111111;
      else adcReadings2[i] = 0b111111;
    } else if (voltageRange == 2) {
      if (HQadcReading2 >> 3 < 0b111111) adcReadings2[i] = HQadcReading2 >> 3 & 0b111111;
      else adcReadings2[i] = 0b111111;
    } else if (voltageRange == 3) {
      if (HQadcReading2 >> 2 < 0b111111) adcReadings2[i] = HQadcReading2 >> 2 & 0b111111;
      else adcReadings2[i] = 0b111111;
    }
    // Invert for display
    adcReadings2[i] = 63 - adcReadings2[i];

#endif    
#ifdef NEW_TIMING
    unsigned long endTime = micros();
    if (endTime < startTime)
    {
      delayMicroseconds(timePeriod);
    } 
    else if (timePeriod > MIN_TIMEPERIOD*2)
    {
      delayMicroseconds(timePeriod - (endTime-startTime));
    }
#endif    
  }

  // Calculate and display frequency of signal using zero crossing
  if (useThreshold != 0) {
    if (useThreshold == 1) {
      thresLocation = 1;
      while ((adcReadings1[thresLocation] < (63 - (theThreshold >> 2))) && (thresLocation < numOfSamples - 1)) (thresLocation++);
      thresLocation++;
      while ((adcReadings1[thresLocation] > (63 - (theThreshold >> 2))) && (thresLocation < numOfSamples - 1)) (thresLocation++);
    }
    else if (useThreshold == 2) {
      thresLocation = 1;
      while ((adcReadings1[thresLocation] > (63 - (theThreshold >> 2))) && (thresLocation < numOfSamples - 1)) (thresLocation++);
      thresLocation++;
      while ((adcReadings1[thresLocation] < (63 - (theThreshold >> 2))) && (thresLocation < numOfSamples - 1)) (thresLocation++);
    }

    theFreq = (float) 1000 / (thresLocation * timePeriod) * 1000;
//    unsigned long startTime1 = micros();
//    digitalWrite(5, LOW);
//      while (analogRead(theAnalogPin1) >50) {}
//    theFreq = micros() - startTime1;
  }

  // Average Voltage
  avgV = 0;
  for (i = 0; i < numOfSamples; i++)
    avgV = avgV + adcReadings1[i];
  avgV = (63 - (avgV / numOfSamples)) * voltageConst;

  // Maximum Voltage
  maxV = 63;
  for (i = 0; i < numOfSamples; i++)
    if (adcReadings1[i] < maxV) maxV = adcReadings1[i];
  maxV = (63 - maxV) * voltageConst;

  // Minimum Voltage
  minV = 0;
  for (i = 0; i < numOfSamples; i++)
    if (adcReadings1[i] > minV) minV = adcReadings1[i];
  minV = (63 - minV) * voltageConst;

  // Peak-to-Peak Voltage
  ptopV = maxV - minV;
}

void handleSerial(void) {
#ifdef SERIAL_ENABLED
  char inByte;
  char dataByte;
  boolean exitLoop = false;
  do {
    // Clear out buffer
    do {
      inByte = Serial.read();
    } while (Serial.available() > 0);

    Serial.print("\nArduino LCD Oscilloscope\n");
    Serial.print(" 1 - Change threshold usage (currently: ");
    if (useThreshold == 0) Serial.print("Off)\n");
    else if (useThreshold == 1) Serial.print("Rise)\n");
    else if (useThreshold == 2) Serial.print("Fall)\n");
    Serial.print(" 2 - Change threshold value (currently: ");
    Serial.print(theThreshold, DEC); Serial.print(")\n");
    Serial.print(" 3 - Change sampling period (currently: ");
    Serial.print(timePeriod, DEC); Serial.print(")\n");
    Serial.print(" 4 - Change voltage range (currently: ");
    if (voltageRange == 0) Serial.print("0-5V)\n");
    else if (voltageRange == 1) Serial.print("0-3.3V)\n");
    else if (voltageRange == 2) Serial.print("0-1.65V)\n");
    else if (voltageRange == 3) Serial.print("0-0.825V)\n");
    Serial.print(" 5 - Toggle auto horizontal (time) scaling (currently: ");
    if (autoHScale == true) Serial.print("On)\n");
    else if (autoHScale == false) Serial.print("Off)\n");
    Serial.print(" 8 - Exit\n");

    // Wait for input/response, refresh display while in menu
    do {
      collectData();
      draw1();
    } while (Serial.available() == 0);
    inByte = Serial.read();

    if (inByte == '1') {
      Serial.print("Change threshold usage\n");
      Serial.print(" 0 - Off\n");
      Serial.print(" 1 - Rise\n");
      Serial.print(" 2 - Fall\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') useThreshold = 0;
      else if (dataByte == '1') useThreshold = 1;
      else if (dataByte == '2') useThreshold = 2;
    } else if (inByte == '2') {
      Serial.print("Change threshold value (thresholds for 0-3.3V,0-1.65V,0-0.825V ranges)\n");
      Serial.print(" 0 - 32 (0.41V, 0.21V, 0.10V)\n");
      Serial.print(" 1 - 80 (1.04V, 0.52V, 0.26V)\n");
      Serial.print(" 2 - 128 (1.66V, 0.83V, 0.41V)\n");
      Serial.print(" 3 - 176 (2.28V, 1.14V, 0.57V)\n");
      Serial.print(" 4 - 224 (2.90V, 1.45V, 0.72V)\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') theThreshold = 32;
      else if (dataByte == '1') theThreshold = 80;
      else if (dataByte == '2') theThreshold = 128;
      else if (dataByte == '3') theThreshold = 176;
      else if (dataByte == '4') theThreshold = 224;
    } else if (inByte == '3') {
      Serial.print("Change sampling frequency\n");
      Serial.print(" 0 - 28 kHz (35 us/sample)\n");
      Serial.print(" 1 - 20 kHz (50 us/sample)\n");
      Serial.print(" 2 - 10 kHz (100 us/sample)\n");
      Serial.print(" 3 - 5 kHz (200 us/sample)\n");
      Serial.print(" 4 - 2.5 kHz (400 us/sample)\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') timePeriod = 35;
      else if (dataByte == '1') timePeriod = 50;
      else if (dataByte == '2') timePeriod = 100;
      else if (dataByte == '3') timePeriod = 200;
      else if (dataByte == '4') timePeriod = 400;
    } else if (inByte == '4') {
      Serial.print("Change voltage range\n");
      Serial.print(" 1 - 0-5V\n");      
      Serial.print(" 1 - 0-3.3V\n");
      Serial.print(" 2 - 0-1.65V\n");
      Serial.print(" 3 - 0-0.825V\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') voltageRange = 0;      
      if (dataByte == '1') voltageRange = 1;
      else if (dataByte == '2') voltageRange = 2;
      else if (dataByte == '3') voltageRange = 3;
    } else if (inByte == '5') {
      Serial.print("Toggle auto horizontal (time) scaling\n");
      Serial.print(" 0 - Off\n");
      Serial.print(" 1 - On\n");
      do { } while (Serial.available() == 0);
      dataByte = Serial.read();
      if (dataByte == '0') autoHScale = false;
      else if (dataByte == '1') autoHScale = true;
    } else if (inByte == '8') {
      Serial.print("Bye!\n");
      exitLoop = true;
    }
    draw();
  } while (exitLoop == false);
#endif    
}

void drawD(void) {
  char buffer[16];
  if (avgV != OldavgV) {
    tft.setTextColor(BLACK);
    dtostrf(OldavgV, 3, 2, buffer);
    tft.setCursor(15, 5 + vTextShift);
    tft.print(buffer);
    tft.setTextColor(RED);
    dtostrf(avgV, 3, 2, buffer);
    tft.setCursor(15, 5 + vTextShift);
    tft.print(buffer);
    OldavgV = avgV;
  }
  if (maxV != OldmaxV) {
    tft.setTextColor(BLACK);
    dtostrf(OldmaxV, 3, 2, buffer);
    tft.setCursor(15, 2 + 11 + vTextShift);
    tft.print(buffer);
    tft.setTextColor(RED);
    dtostrf(maxV, 3, 2, buffer);
    tft.setCursor(15, 2 + 11 + vTextShift);
    tft.print(buffer);
    OldmaxV = maxV;
  }
  if (minV != OldminV) {
    tft.setTextColor(BLACK);
    dtostrf(OldminV, 3, 2, buffer);
    tft.setCursor(15, 4 + 17 + vTextShift);
    tft.print(buffer);
    tft.setTextColor(RED);
    dtostrf(minV, 3, 2, buffer);
    tft.setCursor(15, 4 + 17 + vTextShift);
    tft.print(buffer);
    OldminV = minV;
  }
  if (ptopV != OldptopV) {
    tft.setTextColor(BLACK);
    dtostrf(OldptopV, 3, 2, buffer);
    tft.setCursor(15, 6 + 23 + vTextShift);
    tft.print(buffer);
    tft.setTextColor(RED);
    dtostrf(ptopV, 3, 2, buffer);
    tft.setCursor(15, 6 + 23 + vTextShift);
    tft.print(buffer);
    OldptopV = ptopV;
  }
  if (theFreq != OldtheFreq) {
    tft.setTextColor(BLACK);
    dtostrf(OldtheFreq, 5, 0, buffer);
    tft.setCursor(0, 16 + 53 + vTextShift);
    tft.print(buffer);
    tft.setTextColor(RED, BLACK);
    dtostrf(theFreq, 5, 2, buffer);
    tft.setCursor(0, 16 + 53 + vTextShift);
    tft.print(buffer);
    OldtheFreq = theFreq;
  }
  /*if (useThreshold == 0) {
    tft.setCursor(15, 8+29+vTextShift);
    tft.print("Off");
  } else if (useThreshold == 1) {
    tft.setCursor(15, 8+29+vTextShift);
    tft.print("Rise");
    dtostrf((float) (theThreshold>>2) * voltageConst, 3, 2, buffer);
  } else if (useThreshold == 2) {
    tft.setCursor(15, 8+29+vTextShift);
    tft.print("Fall");
    dtostrf((float) (theThreshold>>2) * voltageConst, 3, 2, buffer);
  }
  tft.setCursor(11, 10+35+vTextShift);
  tft.print(buffer);*/
  // Correctly format the text so that there are always 4 characters
  if (timePeriod != OldtimePeriod) {
    tft.setTextColor(BLACK);
    if (OldtimePeriod < 400) {
      dtostrf((float) OldtimePeriod / 1000 * 25, 3, 2, buffer);
    } else if (OldtimePeriod < 4000) {
      dtostrf((float) OldtimePeriod / 1000 * 25, 3, 1, buffer);
    } else if (OldtimePeriod < 40000) {
      dtostrf((float) OldtimePeriod / 1000 * 25, 3, 0, buffer);
    } else { // Out of range
      dtostrf((float) 0.00, 3, 2, buffer);
    }
    tft.setCursor(15, 12 + 41 + vTextShift);
    tft.print(buffer);

    tft.setTextColor(RED);
    if (timePeriod < 400) {
      dtostrf((float) timePeriod / 1000 * 25, 3, 2, buffer);
    } else if (timePeriod < 4000) {
      dtostrf((float) timePeriod / 1000 * 25, 3, 1, buffer);
    } else if (timePeriod < 40000) {
      dtostrf((float) timePeriod / 1000 * 25, 3, 0, buffer);
    } else { // Out of range
      dtostrf((float) 0.00, 3, 2, buffer);
    }
    tft.setCursor(15, 12 + 41 + vTextShift);
    tft.print(buffer);
    OldtimePeriod = timePeriod;
  }
  /*if (voltageRange == 1) {
    tft.setCursor(7, 18+59+vTextShift);
    tft.print("0-3.30");
  } else if (voltageRange == 2) {
    tft.setCursor(7, 18+59+vTextShift);
    tft.print("0-1.65");
  } else if (voltageRange == 3) {
    tft.setCursor(7, 18+59+vTextShift);
    tft.print("0-0.83");
  } */
}
void drawT(void) {
  char buffer[16];
  tft.fillRect(0, vTextShift + 5, 45, 150, BLACK);
  tft.setTextColor(RED);
  tft.setTextSize(1);
  tft.setCursor(0, 5 + vTextShift);
  tft.print("Av");
  tft.setCursor(0, 2 + 11 + vTextShift);
  tft.print("Mx");
  tft.setCursor(0, 4 + 17 + vTextShift);
  tft.print("Mn");
  tft.setCursor(0, 6 + 23 + vTextShift);
  tft.print("PP");
  tft.setCursor(0, 8 + 29 + vTextShift);
  tft.print("Th");
  tft.setCursor(0, 10 + 35 + vTextShift);
  tft.print("V");
  tft.setCursor(0, 12 + 41 + vTextShift);
  tft.print("Tm");
  tft.setCursor(4, 14 + 47 + vTextShift);
  tft.print("ms/div");
  tft.setCursor(31, 16 + 53 + vTextShift);
  tft.print("Hz");
  tft.setCursor(0, 18 + 59 + vTextShift);
  tft.print("R");

  // Draw dynamic text
  if (autoHScale == true) {
    tft.setCursor(120, 2);
    tft.print("A");
  }
  dtostrf(avgV, 3, 2, buffer);
  tft.setCursor(15, 5 + vTextShift);
  tft.print(buffer);

  dtostrf(maxV, 3, 2, buffer);
  tft.setCursor(15, 2 + 11 + vTextShift);
  tft.print(buffer);

  dtostrf(minV, 3, 2, buffer);
  tft.setCursor(15, 4 + 17 + vTextShift);
  tft.print(buffer);

  dtostrf(ptopV, 3, 2, buffer);
  tft.setCursor(15, 6 + 23 + vTextShift);
  tft.print(buffer);

  dtostrf(theFreq, 5, 0, buffer);
  tft.setCursor(0, 16 + 53 + vTextShift);
  tft.print(buffer);

  if (useThreshold == 0) {
    tft.setCursor(15, 8 + 29 + vTextShift);
    tft.print("Off");
  } else if (useThreshold == 1) {
    tft.setCursor(15, 8 + 29 + vTextShift);
    tft.print("Rise");
    dtostrf((float) (theThreshold >> 2) * voltageConst, 3, 2, buffer);
  } else if (useThreshold == 2) {
    tft.setCursor(15, 8 + 29 + vTextShift);
    tft.print("Fall");
    dtostrf((float) (theThreshold >> 2) * voltageConst, 3, 2, buffer);
  }
  tft.setCursor(11, 10 + 35 + vTextShift);
  tft.print(buffer);
  // Correctly format the text so that there are always 4 characters
  if (timePeriod < 400) {
    dtostrf((float) timePeriod / 1000 * 25, 3, 2, buffer);
  } else if (timePeriod < 4000) {
    dtostrf((float) timePeriod / 1000 * 25, 3, 1, buffer);
  } else if (timePeriod < 40000) {
    dtostrf((float) timePeriod / 1000 * 25, 3, 0, buffer);
  } else { // Out of range
    dtostrf((float) 0.00, 3, 2, buffer);
  }
  tft.setCursor(15, 12 + 41 + vTextShift);
  tft.print(buffer);
  if (voltageRange == 0) {
    tft.setCursor(7, 18 + 59 + vTextShift);
    tft.print("0-5.00");
  } else if (voltageRange == 1) {
    tft.setCursor(7, 18 + 59 + vTextShift);
    tft.print("0-3.30");
  } else if (voltageRange == 2) {
    tft.setCursor(7, 18 + 59 + vTextShift);
    tft.print("0-1.65");
  } else if (voltageRange == 3) {
    tft.setCursor(7, 18 + 59 + vTextShift);
    tft.print("0-0.83");
  }
  OlduseThreshold = useThreshold;
  OldtheThreshold = theThreshold;
  OldtimePeriod = timePeriod;
  OldavgV = avgV;
  OldmaxV = maxV;
  OldminV = minV;
  OldptopV = ptopV;
  OldtheFreq = theFreq;
}

void draw(void) {
  tft.fillScreen(BLACK);
  drawT();
  draw1();
}

void draw1(void) {
  int i, j;
  //  tft.drawFastVLine((128-numOfSamples), 0, 63, ST7735_YELLOW);
  if (useThreshold != 0)
    for (i = 0; i < numOfSamples; i += 3) {
      tft.drawPixel(i, 63 - (theThreshold >> 2), YELLOW);
      tft.drawPixel(i, 63, YELLOW);
    }
  j = numOfSamples / 4;
  for (i = 0; i < 63; i += 5) {
    tft.drawPixel(0, i, YELLOW);
    tft.drawPixel(j, i, YELLOW);
    tft.drawPixel(j + j, i, YELLOW);
    tft.drawPixel(j + j + j, i, YELLOW);
    tft.drawPixel(numOfSamples - 1, i, YELLOW);
  }
  tft.drawLine(0, adcOldReadings1[0], 1, adcOldReadings1[1], BLACK);
#ifdef DOUBLESAMPLES
  tft.drawLine(0, adcOldReadings2[0], 1, adcOldReadings2[1], BLACK);
#endif
  for (i = 1; i < numOfSamples - 1; i++) { // Draw using lines
#ifdef DOUBLESAMPLES
    tft.drawLine(i, adcOldReadings2[i], i + 1, adcOldReadings2[i + 1], BLACK);
#endif
    tft.drawLine(i, adcOldReadings1[i], i + 1, adcOldReadings1[i + 1], BLACK);
    tft.drawLine(i - 1, adcReadings1[i - 1], i, adcReadings1[i], CYAN);
    adcOldReadings1[i - 1] = adcReadings1[i - 1];
#ifdef DOUBLESAMPLES
    tft.drawLine(i - 1, adcReadings2[i - 1], i, adcReadings2[i], GREEN);
    adcOldReadings2[i - 1] = adcReadings2[i - 1];
#endif
    
  }
  tft.drawLine(numOfSamples - 2, adcReadings1[numOfSamples - 2], i, adcReadings1[numOfSamples - 1], CYAN);
  adcOldReadings1[numOfSamples - 2] = adcReadings1[numOfSamples - 2];
  adcOldReadings1[numOfSamples - 1] = adcReadings1[numOfSamples - 1];
#ifdef DOUBLESAMPLES
  tft.drawLine(numOfSamples - 2, adcReadings2[numOfSamples - 2], i, adcReadings2[numOfSamples - 1], GREEN);
  adcOldReadings2[numOfSamples - 2] = adcReadings2[numOfSamples - 2];
  adcOldReadings2[numOfSamples - 1] = adcReadings2[numOfSamples - 1];
#endif
  
}

void setup() {
#ifdef SERIAL_ENABLED
  Serial.begin(115200);
#endif    
//  pinMode(theAnalogPin2, INPUT_PULLUP);
//  digitalWrite(theAnalogPin2, LOW);
  tft.initR(INITR_BLACKTAB);
  tft.setRotation(1);
  tft.fillScreen(BLACK);
  // Turn on LED backlight
  //analogWrite(3, ledBacklight);
  
  pinMode(2,INPUT_PULLUP);
  pinMode(5,OUTPUT);  

#if FASTADC
  // set prescale to 16
  sbi(ADCSRA, ADPS2) ;
  cbi(ADCSRA, ADPS1) ;
  cbi(ADCSRA, ADPS0) ;
#endif
  delay(100);
  draw();
}

int j = 8;

void loop() {
  if (digitalRead(2) == LOW) 
    theThreshold = ((maxV - minV)/voltageConst);
  
  collectData();
  draw1();
  drawD();
  if (j == 100) {
    drawT();
    j = 0;
  }
  j++;
  
#ifdef SERIAL_ENABLED
  // If user sends any serial data, show menu
  if (Serial.available() > 0) {
    handleSerial();
  }
#endif  

  // rebuild the picture after some delay
  digitalWrite(5, HIGH);          
  delay(100);
}

 

SergAG
Offline
Зарегистрирован: 22.12.2012

А можно, коль скоро для истории, весь проект выложить? На каком все-таки экране запустили, 5110? Сама схема отсутствует, тем более 2-канальная. Ну чтобы повторить можно было.

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

SergAG пишет:
А можно, коль скоро для истории, весь проект выложить? На каком все-таки экране запустили, 5110? Сама схема отсутствует, тем более 2-канальная. Ну чтобы повторить можно было.

Присоединяюсь.!!!

Удалось запустить на дисплее 5110 только вариант без шкалы и значений.

Как допилить, чтоб шкала и значения были?

dtvims
Offline
Зарегистрирован: 26.11.2012

Почитайте внимательно тему. Исходники выложены для всех получившихся вариантов.

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

Я вроде написал, что пересадил на Adafruit_ST7735. Экранчик, соответственно, ST7735. 

Пины в исходниках подписаны. 

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

Перечитал всю тему и целого решения как на 5110 уместить вариант с шкалой не нашел!(

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

Удалось собрать только простой без шкали.

Пожалуйста подправьте пример со шкалой под 5110!!!

dtvims пишет:

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

dtvims
Offline
Зарегистрирован: 26.11.2012

Самый первый пост имеет ссылку на оригинальную программу, где используется 5110. Да и в цитате ответ, что надо изменить...

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

Что каксается первого поста.

Выкладываю архив в котором скеч+библиотека+схема и инструкция чтоб не забыть может кому-то пригодится.(вариант без шкалы!!)

Все собранно мной вчера и работает. http://my-files.ru/e7szc0

Остальное с экраном 5110 не работает и в постах нет рабочего примера, есть только указания что можно подправить авось заработает.

Ни рабочего скетча ни библиотек именно к этому примеру нет!

Я понимаю те кто знает спецы крутые и влом такими пустяками заморачиваться чтоб подправить строки скетча прикрепить библиотеку и выложить, надеюсь и для вас кому-то влом будет что-то делать.

Очень дружественный форум к новичкам.

 

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

ну да. все тебе должны через 5 секунд как только ты захотел. или еще до того как захотел

если ты новичек тебе какие то привилегии должны быть? даже интересно

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

jeka_tm пишет:

ну да. все тебе должны через 5 секунд как только ты захотел. или еще до того как захотел

если ты новичек тебе какие то привилегии должны быть? даже интересно

Я не писал что кто-то мне должен, и о пяти секундах вы это тоже зря, потратил на изыскания и освоение пол суток.

А то что никто не подправил скетч это факт.

Разберусь в теме, точно буду подправлять и выкладывать результат вместо того чтоб писать как это просто.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

писать или не писать, выкладывать или нет личное дело каждого

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

jeka_tm я с уважением отношусь к вашему труду, и к тому что это все делается бесплатно и спасибо могут никогда не сказать.!

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

С уважением Игорь.

jeka_tm
jeka_tm аватар
Offline
Зарегистрирован: 19.05.2013

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

а какой мой труд? я в основном игрушки радиоуправляемые делаю)))

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

ты сам то знаешь что хочешь увидеть на дисплее?

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

Сегодня получил бредборд и соединители такая, удобная вещь!

Толи я все залуживал спаивал, потом распаивал, теперь освоение пойдет быстрей!

Раньше на пример простой уходило часа два с пайкой.)

Разберусь с дисплеями сам, и еще 3310 заказал в нем символов больше больше влезет.

Всем спасибо.!

dtvims
Offline
Зарегистрирован: 26.11.2012

Чтобы допилить под конкретный дисплей, нужно иметь этот дисплей. Вся тема переполнена попытками перейти на тот дисплей, что есть в наличии.

P.s. все скетчи вполне рабочие и заточены под то что есть у авторов.

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

Привет всем. Вопрос к тем, кто собирал этот осциллограф, который под дисплей 128х64. Я собрал, есть несколько проблем:

1) При тесте прибора, графики обрезаются на половину (нижнюю). Это у всех так или только у меня? Пришла мысль, что в схеме не хватает усилителя для смещения напряжения. Кто-то его делал? Можете привести схему?

2) При подведении руки к аналоговому вводу ардуины, отвечающему за прием сигнала, осциллограф бодро показывает синусоиду 50-52Hz (полную, без обрезания). Показания на экране обновляются несколько раз в секунду. Если подаю какую-нибудь форму сигнала, осциллограф начинает сильно тормозить (показания и график может зависать на несколько секунд, вплоть до 7-10 секунд). После меняется картинка, опять висит. Если при этом отключить генератор, и поднести опять руку, то в 50% случаев, скокрость отображения информации возвращаеся. Кто-то сталкивался с такой проблемой? Можете подсказать ее решение?

Буду благодарен как конкретным решениям, так и дельным советам!

dtvims
Offline
Зарегистрирован: 26.11.2012

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

По усилителю ничего не скажу. Сам поигрался с данным осциллографом и решил повернуться в сторону китайской копии USBee AX Pro, о чем ничуть не жалею. Уже несколько раз офигенно выручал.

Наводки он ловит прекрасно, а собственно и должен ловить, ведь вход ни к чему не подтянут и представляет собой простую антену, на которую и ловит 50Гц. Сам подключал ему на вход шим, добавлял конденсаторы, ну и так по мелочи, но никаких, описаных Вами подтормаживаний не наблюдал. Разве что При сигнале высокой частоты, дисплей (зависит от скорости общения с ним) очень долго может отрисовывать вертикальные линии. Чем больше линий, тем дольше отрисовывает.

Upd. Из-за долгой отрисовки, я себе переписывал функции отрисовки линий, для увеличения быстродействия на отрисовке вертикальных линий - видимо по этому более тормозов и не наблюдал :)

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

dtvims, изображение не обрезается, оно четко помещается на экране. Обрезается сам сигнал. Я его отрисовку приподнял, видно, что что-то с сигналом, а не с выводом на экран. Сам гравик (если смотреть без поднятия) прижат к низу экрана, а не по центру.

Также перевел некоторые пункты меню на кнопки, которые подключены через резисторы 10к на землю. Может загвоздка в них?

Из-за долгой отрисовки, я себе переписывал функции отрисовки линий, для увеличения быстродействия на отрисовке вертикальных линий

Можете про переписывание функции рассказать поподробнее? Или привести кусок кода.

dtvims
Offline
Зарегистрирован: 26.11.2012

Если сдвиг графика, так может так и должно быть: импульс слабый? Там же на вход можно подавать только 0-5В, где 5В - напряжение питания.

Если у Вас в одном случае идет быстро, а вдругом медленно, то опрос кнопок, скорее всего, тут непричем.

Пример кода отрисовки искать надо. Может я уже его где-то тут выкладывал... В общем, я полез в бибилиотеку и там нашел функции отрисовки прямых линий (назывались, что-то вроде "Быстрая линия") только по X или Y сразу блоками (отрисовка прямоугольника по кординатам двух углов - это если дисплей такое поддерживает), по моему это было в adafruit, а может и нет :(. И, основываясь на этих функциях сделал свою функцию отрисовки линий: Расчитывал на какие по длине отрезки можно разбить линию, если отрезки более 3-х пикселей (только в этом случае есть смысл оптимизации), то, с учетом направления отрезка (по Х или Y), выбирал или одну быструю отрисовку или другую. У меня так же было ограничение, что моя функция отрисовывала линии только слева направо - в этом оптимизация по величине кода.

Upd. Вспомнил, что еще менял весь подход отрисовки оригинального кода. Старый график удалял не стиранием всего дисплея, а только стиранием старых линий (отрисовка цветом фона).

dtvims
Offline
Зарегистрирован: 26.11.2012

Оригинальный код нашел, а свою переделку нет :(

void Adafruit_ST7735::drawFastVLine(int16_t x, int16_t y, int16_t h,
 uint16_t color) {

  // Rudimentary clipping
  if((x >= _width) || (y >= _height)) return;
  if((y+h-1) >= _height) h = _height-y;
  setAddrWindow(x, y, x, y+h-1);

  if (tabcolor == INITR_BLACKTAB)   color = swapcolor(color);

  uint8_t hi = color >> 8, lo = color;
  *rsport |=  rspinmask;
  *csport &= ~cspinmask;
  while (h--) {
    spiwrite(hi);
    spiwrite(lo);
  }
  *csport |= cspinmask;
}


void Adafruit_ST7735::drawFastHLine(int16_t x, int16_t y, int16_t w,
  uint16_t color) {

  // Rudimentary clipping
  if((x >= _width) || (y >= _height)) return;
  if((x+w-1) >= _width)  w = _width-x;
  setAddrWindow(x, y, x+w-1, y);

  if (tabcolor == INITR_BLACKTAB)   color = swapcolor(color);

  uint8_t hi = color >> 8, lo = color;
  *rsport |=  rspinmask;
  *csport &= ~cspinmask;
  while (w--) {
    spiwrite(hi);
    spiwrite(lo);
  }
  *csport |= cspinmask;
}

Очевидно, что это работает только для дисплея ST7735

Upd. Еще можн увеличить скорость SPI, если есть куда...

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

Jtest пишет:

Привет всем. Вопрос к тем, кто собирал этот осциллограф, который под дисплей 128х64. Я собрал, есть несколько проблем:

1) При тесте прибора, графики обрезаются на половину (нижнюю). Это у всех так или только у меня? Пришла мысль, что в схеме не хватает усилителя для смещения напряжения. Кто-то его делал? Можете привести схему?

2) При подведении руки к аналоговому вводу ардуины, отвечающему за прием сигнала, осциллограф бодро показывает синусоиду 50-52Hz (полную, без обрезания). Показания на экране обновляются несколько раз в секунду. Если подаю какую-нибудь форму сигнала, осциллограф начинает сильно тормозить (показания и график может зависать на несколько секунд, вплоть до 7-10 секунд). После меняется картинка, опять висит. Если при этом отключить генератор, и поднести опять руку, то в 50% случаев, скокрость отображения информации возвращаеся. Кто-то сталкивался с такой проблемой? Можете подсказать ее решение?

Буду благодарен как конкретным решениям, так и дельным советам!

Вчера перед сном слепил из того что было. Сначала наткнулся в ютубе на ролик с осцилоскопом, потом подумал, что у меня все есть, взял и как смог слепил. Чувак из ролика ни че не объяснил, схемы нет. Видно такой же "спец" как и я.

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

Вот чего получилось

Кто-нибудь делал такое, кто-то может подсказать?

dtvims
Offline
Зарегистрирован: 26.11.2012

А оригинальный ролик и скетч можно?

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

dtvims, Я с кнопками предполагаю проблему сдвига сигнала и его обрезку, а не быстро/медлено. Хотя завтра отпаяю кнопки, проверю, что-либо изменится или нет.

Joiner, у Вас вообще другой проект, насколько я понимаю. Мы сейчас обсуждаем вот этот проект: http://www.semifluid.com/2013/05/28/arduino-fio-lcd-oscilloscope/ Можете привести ссылку или скеч?  Может чего полезного из него извлеку. А какие характеристики этого осциллографа?

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

Даю ссылку на ролик. По ссылкам автора ролика нашел 2 скетча для разных мониторов. Больше ни чего не понял

http://www.youtube.com/watch?v=XHDNXXhg3Hg

Скетч

/*
This is set up to use a 128x64 I2C screen, as available
here: http://www.banggood.com/buy/0-96-oled.html
For wiring details see http://youtu.be/XHDNXXhg3Hg
*/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

/********************************************/

#define CHARWIDTH           5
#define CHARHEIGHT          8
#define AXISWIDTH           (2 + 1)                   // axis will show two-pixel wide graph ticks, then an empty column
#define VISIBLEVALUEPIXELS  (128 - AXISWIDTH)         // the number of samples visible on screen
#define NUMVALUES           (2 * VISIBLEVALUEPIXELS)  // the total number of samples (take twice as many as visible, to help find trigger point

#define TRIGGER_ENABLE_PIN       2  // set this pin high to enable trigger
#define SCREEN_UPDATE_ENABLE_PIN 3  // set this pin high to freeze screen

byte values[NUMVALUES];           // stores read analog values mapped to 0-63
int pos = 0;                      // the next position in the value array to read
int count = 0;                    // the total number of times through the loop
unsigned long readStartTime = 0;  // time when the current sampling started
int sampleRate = 1;              // A value of 1 will sample every time through the loop, 5 will sample every fifth time etc.

/********************************************/

// Draws a printf style string at the current cursor position
void displayln(const char* format, ...)
{
  char buffer[32];
  
  va_list args;
  va_start(args, format);
  vsprintf(buffer, format, args);
  va_end(args);
  
  int len = strlen(buffer);
  for (uint8_t i = 0; i < len; i++) {
    display.write(buffer[i]);
  }
}

// Draws the graph ticks for the vertical axis
void drawAxis()
{  
  // graph ticks
  for (int x = 0; x < 2; x++) {
    display.drawPixel(x,  0, WHITE);
    display.drawPixel(x, 13, WHITE);
    display.drawPixel(x, 26, WHITE);
    display.drawPixel(x, 38, WHITE);
    display.drawPixel(x, 50, WHITE);
    display.drawPixel(x, 63, WHITE);  
  }
}

// Draws the sampled values
void drawValues()
{
  int start = 0;
  
  if ( digitalRead(TRIGGER_ENABLE_PIN) ) {
    // Find the first occurence of zero
    for (int i = 0; i < NUMVALUES; i++) {
      if ( values[i] == 0 ) {
        // Now find the next value that is not zero
        for (; i < NUMVALUES; i++) {
          if ( values[i] != 0 ) {
            start = i;
            break;
          }
        }
        break;
      }
    }    
    // If the trigger point is not within half of our values, we will 
    // not have enough sample points to show the wave correctly
    if ( start >= VISIBLEVALUEPIXELS )
      return;
  }
  
  for (int i = 0; i < VISIBLEVALUEPIXELS; i++) {
    display.drawPixel(i + AXISWIDTH, 63 - (values[i + start]), WHITE);
  }
}

// Shows the time taken to sample the values shown on screen
void drawFrameTime(unsigned long us)
{
  display.setCursor(9 * CHARWIDTH, 7 * CHARHEIGHT - 2); // almost at bottom, approximately centered
  displayln("%ld us", us);
}

/********************************************/

void setup() {

  // Set up the display
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Initialize with the I2C addr 0x3D (for the 128x64)
  display.setTextColor(WHITE);

  pinMode(TRIGGER_ENABLE_PIN, INPUT);
  pinMode(SCREEN_UPDATE_ENABLE_PIN, INPUT);
}

/********************************************/

void loop() {
  
  // If a sampling run is about to start, record the start time
  if ( pos == 0 )
    readStartTime = micros();
  
  // If this iteration is one we want a sample for, take the sample
  if ( (++count) % sampleRate == 0 )
    values[pos++] = analogRead(0) >> 4; // shifting right by 4 efficiently maps 0-1023 range to 0-63

  // If we have filled the sample buffer, display the results on screen
  if ( pos >= NUMVALUES ) {
    // Measure how long the run took
    unsigned long totalSampleTime = (micros() - readStartTime) / 2;     // Divide by 2 because we are taking twice as many samples as are shown on the screen
 
    if ( !digitalRead(SCREEN_UPDATE_ENABLE_PIN) ) {
      // Display the data on screen   
      display.clearDisplay();
      drawAxis();
      drawValues();
      drawFrameTime(totalSampleTime);
      display.display();
    }
       
    // Reset values for the next sampling run
    pos = 0;
    count = 0;
  }
}

И еще скетч

#include <SPI.h>
#include <Adafruit_GFX.h>
#include "Adafruit_ILI9340.h"

#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 10
#define _dc 9
#define _rst 8

Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);

/********************************************/

#define SCREENWIDTH         320
#define SCREENHEIGHT        240
#define CHARWIDTH           5
#define CHARHEIGHT          7
#define AXISWIDTH           (2 + 1)                   // axis will show two-pixel wide graph ticks, then an empty column
#define VISIBLEVALUEPIXELS  (SCREENWIDTH - AXISWIDTH) // the number of samples visible on screen
#define NUMVALUES           (2 * VISIBLEVALUEPIXELS)  // the total number of samples (take twice as many as visible, to help find trigger point

#define TRIGGER_ENABLE_PIN       2  // set this pin high to enable trigger
#define SCREEN_UPDATE_ENABLE_PIN 3  // set this pin high to freeze screen

byte values[NUMVALUES];           // stores read analog values mapped to 0-127 (can't store 0-1024 in one byte)
byte values2[NUMVALUES];          // stores read analog values mapped to 0-127 (can't store 0-1024 in one byte)
byte* frontBuffer = values;
byte* backBuffer = values2;
int pos = 0;                      // the next position in the value array to read
int count = 0;                    // the total number of times through the loop
unsigned long readStartTime = 0;  // time when the current sampling started
int lastStart = 0;                // the sample at which drawing started last time (need to know this to clear the old line properly)

// Used by vsprintf.
char buffer[32];

/********************************************/

// Draws a printf style string at the current cursor position.
// Note that existing contents of buffer are used to overwrite
// the previous display with black to clear it first - a shameful
// hack indeed
void displayln(int x, int y, const char* format, ...)
{ 
  // Erase previous text 
  tft.setTextColor(ILI9340_BLACK);
  tft.setCursor(x, y);
  tft.println(buffer);
  
  va_list args;
  va_start(args, format);
  vsprintf(buffer, format, args);
  va_end(args);
    
  tft.setTextColor(ILI9340_YELLOW);
  tft.setCursor(x, y);
  tft.println(buffer);
}

// Draws the graph ticks for the vertical axis
void drawAxis()
{  
  byte div = SCREENHEIGHT / 5;
  for (int x = 0; x < 2; x++) {
    for (int y = 0; y < 6; y++) {
      tft.drawPixel(x, y * div, ILI9340_WHITE);  
    }
  }
}

// Draws the sampled values
void drawValues()
{
  int start = 0;
  float mag = SCREENHEIGHT / 128.0; // 128 because sample values are 0-127
 
  if ( true || digitalRead(TRIGGER_ENABLE_PIN) ) {
    // Find the first occurence of zero
    for (int i = 0; i < NUMVALUES; i++) {
      if ( backBuffer[i] != 0 ) {
        // Now find the next value that is not zero
        for (; i < NUMVALUES; i++) {
          if ( backBuffer[i] == 0 ) {
            start = i;
            break;
          }
        }
        break;
      }
    }    
    // If the trigger point is not within half of our values, we will 
    // not have enough sample points to show the wave correctly. In this
    // case, just draw the same line in white to let the user know that
    // the values are old (also prevents the screen from scrolling sideways,
    // and takes less time)
    if ( start >= VISIBLEVALUEPIXELS ) {
      for (int i = 0; i < VISIBLEVALUEPIXELS; i++) {
        tft.drawPixel(i + AXISWIDTH, SCREENHEIGHT - 1 - (frontBuffer[i + lastStart] * mag), ILI9340_WHITE);
      }
      return;
    }
  }

  // clear the old line and draw the new
  for (int i = 0; i < VISIBLEVALUEPIXELS; i++) {
    tft.drawPixel(i + AXISWIDTH, SCREENHEIGHT - 1 - (frontBuffer[i + lastStart] * mag), ILI9340_BLACK);
    tft.drawPixel(i + AXISWIDTH, SCREENHEIGHT - 1 - (backBuffer[i + start] * mag), ILI9340_GREEN);
  }
  
  // swap sample buffers
  byte* tmp = backBuffer;
  backBuffer = frontBuffer;
  frontBuffer = tmp;
  
  lastStart = start;

}

// Shows the time taken to sample the values shown on screen
void drawFrameTime(unsigned long us)
{
  displayln(SCREENWIDTH/2 - 4*CHARWIDTH, SCREENHEIGHT - 1.5*CHARHEIGHT, "%ld us", us);
}

/********************************************/

void setup() {
  
  // Set up the display
  tft.begin();
  tft.setRotation(1);
  tft.setTextSize(1);
  tft.fillScreen(ILI9340_BLACK);
  drawAxis();
  
  buffer[0] = 0;
  
  pinMode(TRIGGER_ENABLE_PIN, INPUT);
  pinMode(SCREEN_UPDATE_ENABLE_PIN, INPUT);
  
}

/********************************************/

// http://extremeelectronics.co.in/avr-tutorials/using-the-analog-to-digita...
void sampleValues() {
  // set the analog reference (high two bits of ADMUX) and select the
  // channel (low 4 bits).  this also sets ADLAR (left-adjust result)
  // to 0 (the default).
  ADMUX = (DEFAULT << 6) | (0 & 0x07);
  
  ADCSRA &= ~(ADPS0 | ADPS1 | ADPS2);

  boolean digi = false; // set this to true if you are only interested in digital signals, to get MUCH more speed
  
  if ( digi ) {
    for (int i = 0; i < NUMVALUES; i++) {
      backBuffer[i] = PINC;
      delayMicroseconds(5); // change this as necessary to alter the duration of the sampling pass
    }
    for (int i = 0; i < NUMVALUES; i++) {
      backBuffer[i] = backBuffer[i] > 0 ? 64 : 0; // a value of 64 is half-way in the 0-127 range we are using
    }
  }
  else {
    for (int i = 0; i < NUMVALUES; i++) {
      
      //start conversion  
      _SFR_BYTE(ADCSRA) |= _BV(ADSC);
          
      // ADSC is cleared when the conversion finishes
      while (bit_is_set(ADCSRA, ADSC));
    
      // we have to read ADCL first; doing so locks both ADCL
      // and ADCH until ADCH is read.  reading ADCL second would
      // cause the results of each conversion to be discarded,
      // as ADCL and ADCH would be locked when it completed.
      uint8_t low  = ADCL;
      uint8_t high = ADCH;
    
      // Combine the two bytes, shifting so that the result is in 0-127 range.
      // You could also do 0-255 range - I can't rememember why I didn't do that, 
      // but I think it had something to do with my screen being only 240 pixels 
      // high... looking at it now though, I don't see why that would have mattered.
      backBuffer[i] = (high << 5) | (low >> 3);
      
      delayMicroseconds(60); // change this as necessary to alter the duration of the sampling pass
    }
  }
  
}

/********************************************/

void loop() {
  
  if ( !digitalRead(SCREEN_UPDATE_ENABLE_PIN) ) {
    
    readStartTime = micros();
    
    sampleValues();
    
    unsigned long totalSampleTime = (micros() - readStartTime) / 2; // Divide by 2 because we are taking twice as many samples as are shown on the screen
 
    // Display the data on screen   
    drawValues();
    drawFrameTime(totalSampleTime);
    
  }
}

Оба скетча компилируются. У меня работает первый. Второй скетч для другого экрана, для какого не понял.