Это код Electronik83, Я просто повкидывал куски кода что собрал тут или вытянул из других скетчей. Лично сам я код не писал и не умею, так что боюсь что я вам ничем не смогу помочь. Тем более тот приборчик с олед дисплей ушёл в люди))).
Просто развёл плату в форме щупа,а экранчик пришел на синей плате и у него пины для подключения с одной стороны в отличии от экранчиков на красной плате, попал в засаду,всё работает но изображение вверх ногами.
Здравствуйте все. Я не много отстал от вас и не могу найти на какой странице последняя рабочая версия этого чудесного прибора. Или ссылка на скечь. Или сам скечь. У меня только один из первых. За ранее спасибо.
надо в проошивке указать частоту 27 и прошить ардуину пока она с кварцем на 16. а потом заменить кварц
Так и делал - скачут цифры, аж бегом.
В коде сменил/добавил count на countZ (в подсвеченных строках)
Добавил в начало скетча
long countZ=0;
было
// === Считаем частоту сигнала === //
if (vRef && vMax*VCC/255 > 2.7) { // если можем замерить аппаратно - меряем
if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала
} else { // === Меряем частоту сигнала программно === //
flagZero=0; count = 0;// сброс флага и счетчика
for(int y=grOffset; y<BUFSIZE-LCDX; y++) { // смотрим массив от точки синхронизации до конца
if (adcBuf[y]<vSync) flagZero=1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг
if (flagZero && adcBuf[y]>vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период
switch (razv) { // считем частоту периода
case 6: count=1000000/((y-grOffset-1)*3.25); break; // делитель 4
case 5: count=1000000/((y-grOffset) *3.25)/2; break; // делитель 8
case 4: count=1000000/((y-grOffset) *3.25)/4; break; // делитель 16
case 3: count=1000000/((y-grOffset) *3.25)/8; break; // делитель 32
case 2: count=1000000/((y-grOffset) *3.25)/16; break; // делитель 64
case 1: count=1000000/((y-grOffset) *3.25)/32; break; // делитель 128
case 0: count=1000000/((y-grOffset) *510); break; // делитель 128 тоже
}
break;
}
}
}
count=count*(OVERCLOCK/16.0); // пересчет частоты на разные кварцы
} // закончили вести рассчеты
display.clearDisplay(); // чистим экран...
// === Отрисовка меню осцилла ===
if (menu==0) display.setTextColor(WHITE, BLACK); else display.setTextColor(BLACK);
if (vRef) display.print(VCC,1); else display.print("1.1");
if (menu==1) display.setTextColor(WHITE, BLACK); else display.setTextColor(BLACK);
display.print(" "); display.print(razv);
if (menu==2) { display.print(" "); display.setTextColor(WHITE, BLACK); delay(200); display.print(" Pause "); } else display.setTextColor(BLACK); // тут задержка для компенсации с остальными задержками
display.setTextColor( BLACK);
display.print(" ");
if (!pause) display.print (count/1000000.0, 6); // вывод частоты
стало
// === Считаем частоту сигнала === //
if (vRef && vMax*VCC/255 > 2.7) { // если можем замерить аппаратно - меряем
if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала
} else { // === Меряем частоту сигнала программно === //
flagZero=0; count = 0; countZ = 0;// сброс флага и счетчика
for(int y=grOffset; y<BUFSIZE-LCDX; y++) { // смотрим массив от точки синхронизации до конца
if (adcBuf[y]<vSync) flagZero=1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг
if (flagZero && adcBuf[y]>vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период
switch (razv) { // считем частоту периода
case 6: count=1000000/((y-grOffset-1)*3.25); break; // делитель 4
case 5: count=1000000/((y-grOffset) *3.25)/2; break; // делитель 8
case 4: count=1000000/((y-grOffset) *3.25)/4; break; // делитель 16
case 3: count=1000000/((y-grOffset) *3.25)/8; break; // делитель 32
case 2: count=1000000/((y-grOffset) *3.25)/16; break; // делитель 64
case 1: count=1000000/((y-grOffset) *3.25)/32; break; // делитель 128
case 0: count=1000000/((y-grOffset) *510); break; // делитель 128 тоже
}
break;
}
}
}
countZ=count*(OVERCLOCK/16.0); // пересчет частоты на разные кварцы
} // закончили вести рассчеты
display.clearDisplay(); // чистим экран...
// === Отрисовка меню осцилла ===
if (menu==0) display.setTextColor(WHITE, BLACK); else display.setTextColor(BLACK);
if (vRef) display.print(VCC,1); else display.print("1.1");
if (menu==1) display.setTextColor(WHITE, BLACK); else display.setTextColor(BLACK);
display.print(" "); display.print(razv);
if (menu==2) { display.print(" "); display.setTextColor(WHITE, BLACK); delay(200); display.print(" Pause "); } else display.setTextColor(BLACK); // тут задержка для компенсации с остальными задержками
display.setTextColor( BLACK);
display.print(" ");
if (!pause) display.print (countZ/1000000.0, 6); // вывод частоты
Частота прыгать перестала. Вернее на 1000Гц показывает 1000-999.
==========
Но, через делитель 1/10, делал его по этой схеме, только у меня Arduino Pro Mini.
Все равно прыгала очень сильно.
Тогда сменил 2.7 на 0.1 в этой строке
if (vRef && vMax*VCC/255 > 2.7) { // если можем замерить аппаратно - меряем
сменил на
if (vRef && vMax*VCC/255 > 0.1) { // если можем замерить аппаратно - меряем
В итоге, 5v 1000Гц через делитель 1/10 при опорном 5, частоту не меряет.
5v 1000Гц через делитель 1/10 при опорном 1.1 - меряет но скачет, хоть и намного меньше - 980-1012
=====
Сама идея Пультоскопа понравилась, но я в этом слабо разбираюсь, накрутил чего то, а правильно ли это,хз.
Мой пультоскоп с дисплеем 1202. Пока много недоделано.
Выбор режима:
Режим терминала:
Режим логического анализатора:
Тот же сигнал параллельно отображается на компьютере:
Ещё один замер анализатором:
То же место на компе:
В режиме осциллографа:
В режиме генератора:
Самое сложное- пайка. Шаг 0,6 мм.
Пины Ардуино прописаны в скетче- 4 штуки к дисплею и 4 штуки к кнопкам (внутренняя подтяжка к плюсу, кнопки замыкаются на минус). Вход осциллографа А3 и D5 впараллель (как у автора), выходы генератора тоже как у автора- 9 и 10, для терминала D0 и D1. Входы анализатора А0, А1, А2, А3.
Поменять пины по вкусу в строках с 30 по 49. Убрать строки 258, 259, 260, 261.
привет seri0shka увидел Ваш прибор и захотелось повторить. Только у меня экран OLED 128x64 SPI. пытался сам что-то сделать но не получилось. ПРОШУ вас помочь.
Здраствуйте seri0shka. Большое спасибо что ответили мне. Мой экранчик 0.96 OLED 128x64 SPI. Фото прикреплено ниже, такой же как мой. Я в написании сложных скейчей не силен. но очень понравился ваш ПУЛЬТОСКОП, особенно логический анализатор. Хотелось бы повторить.
Здравствуйте! Подскажите, скетчи под 0.96 OLED 128x64 которые тут обсуждались ранее , они только под SSD1306 SPI IIC (как на фото выше) или есть и на SSD1306 I2C (четырёх-контактный)?
Если кто-то подключал этот дисплей по шине I2C, дайте скетч, пожалуйста (со схемой вообще - идеально). Сам найти не смог.
PS
Просьба отменяется, решил сам. Всё скомпилировалось в 1.8.12, загрузилось, работает. В двойне приятно, так как делаю это впервые (правки в коде). Раньше только заливал готовое.
Может кому будет интересно (на примере PULTOSCOPE_128x64_OLED_display.ino для SSD1306 SPI):
В начале кода, в первый блок, добавляем две строчки:
#include <SPI.h>
#include <Wire.h>
Далее, сразу за этим блоком:
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Ну и, комментируем часть кода, которая была для SPI и добавляем для I2C:
// Declaration for an SSD1306 display connected to SPI
//#define OLED_RESET 4
//Adafruit_SSD1306 display(OLED_RESET);
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
При компиляции получаем ошибку: :482:3: note: suggested alternative: 'ssd1306_sda'
ssd1306_refresh();
^~~~~~~~~~~~~~~
ssd1306_sda
exit status 1 'ssd1306_init' was not declared in this scope
Была эта мысль, по-этому брал и arduino-1.6.5-r5_портабл IDE. Было то же самое.
Даже перегружался в Windows 7 - она у меня Arduino впервые увидела (чтобы никаких накладок не было).
Скетч переименовывал!!! Содержимое не правил. Например, в PULTOSCOPE_final.
Всё сдвинулось с мёртвой точки, когда я не просто скетч взял, а скопировал всю папку PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION вместе с её содержимым: my_fonts.ino, my_i2c_for_ssd1306.ino, my_ssd1306.ino и PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION.ino. (есть зависимости?).
Только после этого, все отработало как надо: Скетч использует 12322 байт (40%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1942 байт (94%) динамической памяти, оставляя 106 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
Такие вот чудеса. Залилось и работает. Спасибо!
От версии IDE не зависит, как оказалось. Хоть 1.8.12, хоть 1.6.5.
У меня ProMini, 5V, 16MHz. "Недостаток памяти" - критично или норма?
как говорит Елена Малышева - "это нормально!" )) пока ты не надумаешь рей-трейсинг считать, или крипту майнить - все будет хорошо)) просто "мало" памяти для динамических переменных. думаю, что 106 байт на i да иксы-игрики в функциях памяти хватит) просто хорошенько затести на предмет багов/глюков/подвисаний все пункты и режимы во всех позах))
А можно ли Андроид подключить по USB или WIFI вместо местного экрана? И вот бы простенький осциллограф-индикатор добавить: форма сигнала, 5-10 кГц, 4-5 вольт)) Найти бы программное обеспечение на Arduino (IDE) Вот бы собрать бы на Wi-Fi модуле ESP8266 ESP-01)))
seri0shka, если "самое сложное - пайка. Шаг 0,6 мм", то китайцы об этом уже подумали.
Адаптер, вдруг будет интересно: https://aliexpress.ru/item/32677955690.html https://aliexpress.ru/item/1859102902.html
Любой шаг, под любой дисплей.
Шаг на верхней стороне: 0,5 мм, 0,7 мм, 0,9 мм, 1,1 мм
Шаг на нижней стороне: 0,6 мм, 0,8 мм, 1,0 мм, 1,2 мм
Размер платы (Д x Ш): прибл. 2,7x2,2 дюймов (68,58x50,8 мм)
Iskatel, пробовал я 0.96 OLED 128x64 SPI (пришлось перепаять свой 0.96 OLED 128x64 I2С), пока не особо успешно, так что в ближайшее время не получится. Может, попозже перепишу скетч под библиотеку для OLED 128x64. Пока нет времени и желания.
есть ли этот проект по 2,8 TFT touch. Может кто поделиться скетчем) Хоть без тача, кнопками сделаю
можно рашпилем пройтись по краям, сделать 2,4" - тогда тут полно кода под него со старта. но если вдруг у тебя разрешение 320*240 - можно попробовать без рашпиля)) РАЗМЕР не при чем. важен интерфейс, чип дисплея и разрешение. ты назвал самый бесполезный параметр.
для DDS генератора нужны 8 пинов, и дисплей у тебя на параллельном 8bit интерфейсе, жрет еще с десяток+ пинов. я так понимаю, поэтому тут не видно изделий на таких дисплеях с DDS (не помню таких, все ч/б и/или spi). в целом, можно попробовать сделать. для этого нужно 8 ног отобрать у дисплея, прямо на его шине и повесить DDS, только переписать код - поднимать CS(чип селект) дисплея, после чего он будет игнорить ноги, и фигачить тудой ддс, выходить по прерыванию. и суперфаст диоды ставить на ноги штоле, чтоб при работе дисплея у него меж ног не сквозило от резисторов цап)) простых путей тут нет. или нужен чип - клон атмеги со встроенным цап, или (не)много думать, кодить и паять. но я так понимаю, для тебя это темный лес(кодинг, даташЫтЫ)? нужно учиться кодить и понимать аппаратуру с которой работаешь - занимательно и полезно. и вкусно)
люди тут ленивые/занятые/незнайки, поэтому вместо тебя никто делать ничего не станет, что уже не сделано другими или для себя. так, подкрутить что-то... а у тебя вон целая проблема - повесить две функции(два устройства) на одни и те-же ноги. здесь это считается высшим пилотажем, как и обращение к порту и упаси Господи, регистру. тут живут-то всего 3-5-несколько программистов, еще меньше из которых раскрывали хоть один даташыт, а это не комп, где все "само" работает, тут кишки знать нужно...
я все глубже понимаю кодеров, которые ардуинщиков не считают программистами ваще...
аж ска грустно стало... пойду бухну...
апдейт: ты написал название микросхемы двунаправленного трансивера, это не чип дисплея. его не видно. его или знают, или кодом пытаются прочитать. или хардово прописывают, если не читается... короче, чую я повозишься ты, забросишь это дело, и айда к гайверу лампочками моргать)))
Всем здравствуйте. Многие хотят приклеить какие-то слишком модные дисплеи. Зачем? Этого вполне хватает . А чем вам не нравится дисплей от китайского ESR-метра. И ног не много и большой.
Electronik83, не подскажите, вы делали какие-либо существенные изменения в схеме для скетчей SSD1306_EL83_EDITION_avto и PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION?
Можно схему для final EDITION?
Дело в том, что если только подтягивающие резисторы к "кнопочным" выводам ардуинки ставить, то первый ("avto") у меня работает без проблем: адекватно реагирует на нажатия кнопок и живет так, как хочу я.
Но стоит в эту же ProMini, ничего не меняя в схеме, залить "final2" и прибор начинает жить своей жизнью: сначала самопроизвольное перелистывание пунктов меню при подаче питания, потом сам входит в пункт "Осциллоскоп", показывает наводку 50 Гц от сети и картинка замирает. На кнопки никакой реакции - ни до, ни после "замирания".
Что я делаю не так?
В общем оставил только "ОСЦИЛЛОГРАФ" так как другим не пользуюсь. Добавил коды автоматики: развёртка, Авто-опорное 5.0, 1.1, 0.22. Оставил только 3 кнопки. На кнопке "ок" вход и выход " Pause ". При удержании "лева-право" увидим "меньше-больше" развёртку + клацнем на "ок" такова же вида развёртка останется в " Pause ". От балды добавил в дежурное меню термометр и активный вольтметр батареи. Там ещё что то делал, но забыл))). Если интересно, то сделаю видео.
это беспощадный кодинг с кровью в глазах)) что я увидел за 10 сек: смотрим функцию drawLine
int steep = abs(y1 - y0) > abs(x1 - x0);
if (steep) {
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1) {
swap(x0, x1);
swap(y0, y1);
}
все, что тут намалёвано - библиотечный студенческий сблёв. у тебя Х всегда один, а тут проверка, вычитание, свап 4 раза, ненужные условия. int steep - я тоже люблю булевый тип переменных засунуть в чё нить пограндиознее. давай long double, чего уж там. если bool жмет.
в функции drawPixel - идет беспощадная проверка _каждого_пиксела_ и кодера на дебилизм. а не захочет ли он, падлюка тупая, нарисовать пиксель за пределами экрана?... ты же не дебил, рисовать мимо унитаза. выкинь нахер проверку - первая строка в функции. бл*ть!!byte проверять на <0... бл*ть!! скоруу мне!!! товарищи кодеры, так держать! я крепну в гневе...
короче, все в этом коде сделано без малейшего намека на мозг и понимание работы железа, скорость будет вот такая... какая есть. полтора фпс...
я как увидел в коде дравфастлайн, ну думаю, наконец то, избавились от библиотеки и переписали, ускорили... XYZ там был! просто чтоб байблу не подключать, хитро.
девиз ардуинщика: учиться долго программистом стать.. а к ардуино можно спизд*ть...
только оно так и будет работать, а что ты хотел...
хотя чё это я. тут же надо улучшать, а не ускорять. сейчас кто нибудь тебе меню с полосочками круглыми и квадратиками треугольными напишет. ну, чтоб лучше стало))
smokok - не принимай на личный счет. мое негодование вызвано не тобой)) ты честно написал - не шарю. ты не виноват)) просто удали первую строку из... вот твой новый drawPixel:
можно еще ускорить. потом. если захочешь)) просто, я лучше не сделаю, не хочу и не буду. а быстрее - можно)) но может и не нужно будет, с такой инертностью дисплея...
проверишь - отпиши. может глюки какие или не заработает... на моем интерпретаторе в голове вроде работает раза в три-пять быстрее))
Это не мой код, его замутил seri0shka: Я просто туда добавил автоматику от Electronik83:, так как это на много удобнее в пользовании.
С новым drawPixel: работает, А с кодом ниже ей не нравится 'print'. Пока не могу придти в себя после 9 мая, кстаки С Днём Победы! Если в реальную за "работает раза в три-пять быстрее))", то круто!!!
и строку (line & 0x1) ? drawPixel(x + i, y + j, color) : drawPixel(x + i, y + j, !color); замени на
if(line & 0x1)
{
drawPixel(x + i, y + j, color);
}
else
{
drawPixel(x + i, y + j, !color);
}
не все макросы можно пихать в конструкцию ?:, сделал тоже самое, только через if/else. проверяй. и прикинь получившийся фпс, оч интересно. а то у тебя был где-то 3 )) не знаешь как - снимай в 60-120 фпс и считай по кадрам)) на паузе перемотка должна показать хорошо...
а, да. с днем победы. отдыхай))
ЗЫ: seri0shka и все все причастные к коду. извините меня за грубости об этом коде и кодерах... на самом деле присутствует отсутствие обучающего материала) - в основном только модули китайские цепляют, никакого креатива. нет разъяснения кода. нет выхода за рамки библиотек. короче, чёт я погорячился поливать. сорри. вы же стараетесь)...я надеюсь)
progrik: Вроди бы шустрее стало))), только чего то при опорном 5в. стало писать "NAN". При опорном ниже 5в. всё норм. ХЗ.
я тут не при чем)) как бы мы вообще не трогали напяжения... ищи VCC = ReadVcc(); закомментируй эту строку (VCC уже определен раньше). или поменяй ее на VCC = 5.0; чтобы проверить. должно 5.0 опорное показывать. а оно покажет... потому, что 0.2 и 1.1 прям прописаны в коде, а 5.0 берется из переменной VCC, которую рожает функция ReadVcc. домашнее задание)) прописать что я написал и проверить. если прописанные вручную пять вольт "заработают", значит не работает функция ReadVcc. попробуй починить функцию)) ну или я позже гляну... функция ReadDig - не юзается вообще, вытирай. там конечно капец... давай починим VCC, ускорим, и на этом мои полномочия всё)) или оставь VCC=5.0; и не парься. еще одну функцию ReadVcc удалишь)) решай) все равно питание пять вольт. ну или обеспечь стабильные 5В.
еще в функции SendByte снова перед _каждой_отправкой_байта_ вызывается dWrite(CS, 0); что есть хорошо... НЕ ОЧЕНЬ)) это нужно сделать один раз в сетапе, после инициализации дисплея. и если ноги от дисплея не используются другими приблудами(не вижу таких), то не поднимать ногу вообще. опустил и забыл.
и еще кто-то решил, что программный SPI быстрее аппаратного... это грустно... на отрисовку одной точки вызывается три функции, некоторе по 4-5 раз - мне этого не понять. dWrite нужно дефайном или инлайн делать, все нужно делать.. да, в выводе хлама много. много=всё.
вообще крайне странно, что никак не связанная с изменениями функция ReadVcc перестала работать...
вообще крайне странно, что никак не связанная с изменениями функция ReadVcc перестала работать...
Старый код вернул (выше написал), ReadVcc стала работать. А по поводу SPI, dWrite и функции SendByte я нервно курю в стороне)))), не осилю!!! И так спасибо за домашку ;) .
нужно пробовать. и по хорошему все равно надо посмотреть что там за косяки в ReadVcc ... а у меня мало времени, я очень много отдыхаю))) пробуй заменить дравпиксель на новый с инлайн дизайном))) но я бы с прибором в 40 пикселей в высоту написал бы 5 вольт и не морочился, что там мерить?... запитал от более-менее хорошего стаба или DC-DC модуля и всё. ладно. давай чинить)) пробуй))
Всем спасибо за полезную информацию и проделанную работу по такому осциллографическому пробничку!По началу делал на дисплее Nokia 5110, но для данного дисплея видимо просто необходим преобразователь уровней (как здесь уже упоминалось). Т.к. работает нестабильно, либо вообще не включается. Поэтому решил повторить на OLED дисплее. Так компактнее получается и видно все, не смотря на миниатюризацию показаний. Фото изделия прилагаю...
удалил,у меня SPI...
Andry Smart,
Это код Electronik83, Я просто повкидывал куски кода что собрал тут или вытянул из других скетчей. Лично сам я код не писал и не умею, так что боюсь что я вам ничем не смогу помочь. Тем более тот приборчик с олед дисплей ушёл в люди))).
ОК спасибо за подсказку рою библиотеки!
Здравствуйте, столкнулся с проблемой. Все функции прибора работают нормально, кроме пультоскопа. Если зайти в него то дисплей сразу отключается.
Мы обратились к шаману чтобы он узнал какой скетч в вашем приборчике. А так всё ясно что дело тёмно))).
Я уже разобрался )
Привет всем кто на форуме! У меня вопрос - нужно перевернуть изображение на 5110 на 180 градусов как отобразить это в скетче?
Просто развёл плату в форме щупа,а экранчик пришел на синей плате и у него пины для подключения с одной стороны в отличии от экранчиков на красной плате, попал в засаду,всё работает но изображение вверх ногами.
в общем решил я свою проблему помогли соединительные провода и двусторонний скотч!
потер
Здравствуйте все. Я не много отстал от вас и не могу найти на какой странице последняя рабочая версия этого чудесного прибора. Или ссылка на скечь. Или сам скечь. У меня только один из первых. За ранее спасибо.
Здравствуйте. Посмотрите где то страниц 10 назад. Что нибудь выберете.
VicSan: Если кому нужно, то выложу то, что сделано.
Доброго времени всем.
Понимаю, что маловероятно, но все же спрошу, а вдруг кто будет мимо проходить)
На 19й прошивке PULTOSCOPE_LCD5110_EL83_19.1_OK от Electronik83, при разгоне на 27Мгц жутко скачут цифры частоты. в остальном все ОК.
Может кто правил прошивку под разгон - поделитесь пож-та, или посоветуйте чего.
а как вы разгон делали?
просто надо в проошивке указать частоту 27 и прошить ардуину пока она с кварцем на 16. а потом заменить кварц
а как вы разгон делали?
просто надо в проошивке указать частоту 27 и прошить ардуину пока она с кварцем на 16. а потом заменить кварц
надо в проошивке указать частоту 27 и прошить ардуину пока она с кварцем на 16. а потом заменить кварц
Так и делал - скачут цифры, аж бегом.
В коде сменил/добавил count на countZ (в подсвеченных строках)
Добавил в начало скетча
было
// === Считаем частоту сигнала === // if (vRef && vMax*VCC/255 > 2.7) { // если можем замерить аппаратно - меряем if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала } else { // === Меряем частоту сигнала программно === // flagZero=0; count = 0;// сброс флага и счетчика for(int y=grOffset; y<BUFSIZE-LCDX; y++) { // смотрим массив от точки синхронизации до конца if (adcBuf[y]<vSync) flagZero=1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг if (flagZero && adcBuf[y]>vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период switch (razv) { // считем частоту периода case 6: count=1000000/((y-grOffset-1)*3.25); break; // делитель 4 case 5: count=1000000/((y-grOffset) *3.25)/2; break; // делитель 8 case 4: count=1000000/((y-grOffset) *3.25)/4; break; // делитель 16 case 3: count=1000000/((y-grOffset) *3.25)/8; break; // делитель 32 case 2: count=1000000/((y-grOffset) *3.25)/16; break; // делитель 64 case 1: count=1000000/((y-grOffset) *3.25)/32; break; // делитель 128 case 0: count=1000000/((y-grOffset) *510); break; // делитель 128 тоже } break; } } } count=count*(OVERCLOCK/16.0); // пересчет частоты на разные кварцы } // закончили вести рассчеты display.clearDisplay(); // чистим экран... // === Отрисовка меню осцилла === if (menu==0) display.setTextColor(WHITE, BLACK); else display.setTextColor(BLACK); if (vRef) display.print(VCC,1); else display.print("1.1"); if (menu==1) display.setTextColor(WHITE, BLACK); else display.setTextColor(BLACK); display.print(" "); display.print(razv); if (menu==2) { display.print(" "); display.setTextColor(WHITE, BLACK); delay(200); display.print(" Pause "); } else display.setTextColor(BLACK); // тут задержка для компенсации с остальными задержками display.setTextColor( BLACK); display.print(" "); if (!pause) display.print (count/1000000.0, 6); // вывод частотыстало
// === Считаем частоту сигнала === // if (vRef && vMax*VCC/255 > 2.7) { // если можем замерить аппаратно - меряем if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала } else { // === Меряем частоту сигнала программно === // flagZero=0; count = 0; countZ = 0;// сброс флага и счетчика for(int y=grOffset; y<BUFSIZE-LCDX; y++) { // смотрим массив от точки синхронизации до конца if (adcBuf[y]<vSync) flagZero=1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг if (flagZero && adcBuf[y]>vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период switch (razv) { // считем частоту периода case 6: count=1000000/((y-grOffset-1)*3.25); break; // делитель 4 case 5: count=1000000/((y-grOffset) *3.25)/2; break; // делитель 8 case 4: count=1000000/((y-grOffset) *3.25)/4; break; // делитель 16 case 3: count=1000000/((y-grOffset) *3.25)/8; break; // делитель 32 case 2: count=1000000/((y-grOffset) *3.25)/16; break; // делитель 64 case 1: count=1000000/((y-grOffset) *3.25)/32; break; // делитель 128 case 0: count=1000000/((y-grOffset) *510); break; // делитель 128 тоже } break; } } } countZ=count*(OVERCLOCK/16.0); // пересчет частоты на разные кварцы } // закончили вести рассчеты display.clearDisplay(); // чистим экран... // === Отрисовка меню осцилла === if (menu==0) display.setTextColor(WHITE, BLACK); else display.setTextColor(BLACK); if (vRef) display.print(VCC,1); else display.print("1.1"); if (menu==1) display.setTextColor(WHITE, BLACK); else display.setTextColor(BLACK); display.print(" "); display.print(razv); if (menu==2) { display.print(" "); display.setTextColor(WHITE, BLACK); delay(200); display.print(" Pause "); } else display.setTextColor(BLACK); // тут задержка для компенсации с остальными задержками display.setTextColor( BLACK); display.print(" "); if (!pause) display.print (countZ/1000000.0, 6); // вывод частотыЧастота прыгать перестала. Вернее на 1000Гц показывает 1000-999.
==========
Но, через делитель 1/10, делал его по этой схеме, только у меня Arduino Pro Mini.
Все равно прыгала очень сильно.
Тогда сменил 2.7 на 0.1 в этой строке
if (vRef && vMax*VCC/255 > 2.7) { // если можем замерить аппаратно - меряем сменил на if (vRef && vMax*VCC/255 > 0.1) { // если можем замерить аппаратно - меряемВ итоге, 5v 1000Гц через делитель 1/10 при опорном 5, частоту не меряет.
5v 1000Гц через делитель 1/10 при опорном 1.1 - меряет но скачет, хоть и намного меньше - 980-1012
=====
Сама идея Пультоскопа понравилась, но я в этом слабо разбираюсь, накрутил чего то, а правильно ли это,хз.
вот и прошу помощи )
Был дубль -удалите пожалуйста
Подскажите-а под такую версию экрана http://srukami.inf.ua/st7735_128_128.html не переписывался скетч?
1
Мой пультоскоп с дисплеем 1202. Пока много недоделано.
Выбор режима:
Режим терминала:
Режим логического анализатора:
Тот же сигнал параллельно отображается на компьютере:
Ещё один замер анализатором:
То же место на компе:
В режиме осциллографа:
В режиме генератора:
Самое сложное- пайка. Шаг 0,6 мм.
Пины Ардуино прописаны в скетче- 4 штуки к дисплею и 4 штуки к кнопкам (внутренняя подтяжка к плюсу, кнопки замыкаются на минус). Вход осциллографа А3 и D5 впараллель (как у автора), выходы генератора тоже как у автора- 9 и 10, для терминала D0 и D1. Входы анализатора А0, А1, А2, А3.
Поменять пины по вкусу в строках с 30 по 49. Убрать строки 258, 259, 260, 261.
привет seri0shka увидел Ваш прибор и захотелось повторить. Только у меня экран OLED 128x64 SPI. пытался сам что-то сделать но не получилось. ПРОШУ вас помочь.
Только у меня экран OLED 128x64 SPI. пытался сам что-то сделать но не получилось. ПРОШУ вас помочь.
Помочь не так просто, тем более не имея дисплея под рукой. Но я попробую. Мне нужен тип дисплея (всё, что на нём написано, подробно).
ufo
Здраствуйте seri0shka. Большое спасибо что ответили мне. Мой экранчик 0.96 OLED 128x64 SPI. Фото прикреплено ниже, такой же как мой. Я в написании сложных скейчей не силен. но очень понравился ваш ПУЛЬТОСКОП, особенно логический анализатор. Хотелось бы повторить.
Здравствуйте! Подскажите, скетчи под 0.96 OLED 128x64 которые тут обсуждались ранее , они только под SSD1306 SPI IIC (как на фото выше) или есть и на SSD1306 I2C (четырёх-контактный)?
Если кто-то подключал этот дисплей по шине I2C, дайте скетч, пожалуйста (со схемой вообще - идеально). Сам найти не смог.
PS
Просьба отменяется, решил сам. Всё скомпилировалось в 1.8.12, загрузилось, работает. В двойне приятно, так как делаю это впервые (правки в коде). Раньше только заливал готовое.
Может кому будет интересно (на примере PULTOSCOPE_128x64_OLED_display.ino для SSD1306 SPI):
В начале кода, в первый блок, добавляем две строчки:
Далее, сразу за этим блоком:
Ну и, комментируем часть кода, которая была для SPI и добавляем для I2C:
А вот дальше таки помощь нужна.
В финальном коде от Electronik83 (PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION) есть строка:
При компиляции получаем ошибку:
:482:3: note: suggested alternative: 'ssd1306_sda'
ssd1306_refresh();
^~~~~~~~~~~~~~~
ssd1306_sda
exit status 1
'ssd1306_init' was not declared in this scope
От чего так может быть и как победить?
У Вас скорее всего стоит какая то библиотека на SSD1306 и в ней уже есть обьявление ssd1306_sda. Попробуйте скачать другой Arduino IDE.
Была эта мысль, по-этому брал и arduino-1.6.5-r5_портабл IDE. Было то же самое.
Даже перегружался в Windows 7 - она у меня Arduino впервые увидела (чтобы никаких накладок не было).
Скетч переименовывал!!! Содержимое не правил. Например, в PULTOSCOPE_final.
Всё сдвинулось с мёртвой точки, когда я не просто скетч взял, а скопировал всю папку PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION вместе с её содержимым: my_fonts.ino, my_i2c_for_ssd1306.ino, my_ssd1306.ino и PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION.ino. (есть зависимости?).
Только после этого, все отработало как надо:
Скетч использует 12322 байт (40%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 1942 байт (94%) динамической памяти, оставляя 106 байт для локальных переменных. Максимум: 2048 байт.
Недостаточно памяти, программа может работать нестабильно.
Такие вот чудеса. Залилось и работает. Спасибо!
От версии IDE не зависит, как оказалось. Хоть 1.8.12, хоть 1.6.5.
У меня ProMini, 5V, 16MHz. "Недостаток памяти" - критично или норма?
А можно ли Андроид подключить по USB или WIFI вместо местного экрана? И вот бы простенький осциллограф-индикатор добавить: форма сигнала, 5-10 кГц, 4-5 вольт)) Найти бы программное обеспечение на Arduino (IDE) Вот бы собрать бы на Wi-Fi модуле ESP8266 ESP-01)))
seri0shka, если "самое сложное - пайка. Шаг 0,6 мм", то китайцы об этом уже подумали.
Адаптер, вдруг будет интересно:
https://aliexpress.ru/item/32677955690.html
https://aliexpress.ru/item/1859102902.html
Любой шаг, под любой дисплей.
Шаг на верхней стороне: 0,5 мм, 0,7 мм, 0,9 мм, 1,1 мм
Шаг на нижней стороне: 0,6 мм, 0,8 мм, 1,0 мм, 1,2 мм
Размер платы (Д x Ш): прибл. 2,7x2,2 дюймов (68,58x50,8 мм)
Iskatel, пробовал я 0.96 OLED 128x64 SPI (пришлось перепаять свой 0.96 OLED 128x64 I2С), пока не особо успешно, так что в ближайшее время не получится. Может, попозже перепишу скетч под библиотеку для OLED 128x64. Пока нет времени и желания.
Добрые люди подскажите есть ли этот проект по 2,8 TFT touch. Может кто поделиться скетчем)
Хоть без тача, кнопками сделаю
seri0shka, что можно сделать, буду ждать. если найдете время и желание переделайте под этот дисплай.
Чип дисплея SUM74HC245T D1409AFP71
Помогите пожалуйста прикрутить, очень уж хочется собрать такой прибор, DDS генератор нужен в основном но и остальной функционал полезный.
Рашпиля нет у меня, он сломан когда я в зубах ковырялся.
для DDS генератора нужны 8 пинов, и дисплей у тебя на параллельном 8bit интерфейсе, жрет еще с десяток+ пинов. я так понимаю, поэтому тут не видно изделий на таких дисплеях с DDS (не помню таких, все ч/б и/или spi). в целом, можно попробовать сделать. для этого нужно 8 ног отобрать у дисплея, прямо на его шине и повесить DDS, только переписать код - поднимать CS(чип селект) дисплея, после чего он будет игнорить ноги, и фигачить тудой ддс, выходить по прерыванию. и суперфаст диоды ставить на ноги штоле, чтоб при работе дисплея у него меж ног не сквозило от резисторов цап)) простых путей тут нет. или нужен чип - клон атмеги со встроенным цап, или (не)много думать, кодить и паять. но я так понимаю, для тебя это темный лес(кодинг, даташЫтЫ)? нужно учиться кодить и понимать аппаратуру с которой работаешь - занимательно и полезно. и вкусно)
люди тут ленивые/занятые/незнайки, поэтому вместо тебя никто делать ничего не станет, что уже не сделано другими или для себя. так, подкрутить что-то... а у тебя вон целая проблема - повесить две функции(два устройства) на одни и те-же ноги. здесь это считается высшим пилотажем, как и обращение к порту и упаси Господи, регистру. тут живут-то всего 3-5-несколько программистов, еще меньше из которых раскрывали хоть один даташыт, а это не комп, где все "само" работает, тут кишки знать нужно...
я все глубже понимаю кодеров, которые ардуинщиков не считают программистами ваще...
аж ска грустно стало... пойду бухну...
апдейт: ты написал название микросхемы двунаправленного трансивера, это не чип дисплея. его не видно. его или знают, или кодом пытаются прочитать. или хардово прописывают, если не читается... короче, чую я повозишься ты, забросишь это дело, и айда к гайверу лампочками моргать)))
Спасибо за ответ! Все в точку особенно про мигание лампочками). Вывод для себя сделал благодаря ответу.
Так же пошел бухать. А завтра продолжу мигать лампочками и подбирать соответствующие комплектующие.
Спасибо!
Всем здравствуйте. Многие хотят приклеить какие-то слишком модные дисплеи. Зачем? Этого вполне хватает . А чем вам не нравится дисплей от китайского ESR-метра. И ног не много и большой.
Electronik83, не подскажите, вы делали какие-либо существенные изменения в схеме для скетчей SSD1306_EL83_EDITION_avto и PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION?
Можно схему для final EDITION?
Дело в том, что если только подтягивающие резисторы к "кнопочным" выводам ардуинки ставить, то первый ("avto") у меня работает без проблем: адекватно реагирует на нажатия кнопок и живет так, как хочу я.
Но стоит в эту же ProMini, ничего не меняя в схеме, залить "final2" и прибор начинает жить своей жизнью: сначала самопроизвольное перелистывание пунктов меню при подаче питания, потом сам входит в пункт "Осциллоскоп", показывает наводку 50 Гц от сети и картинка замирает. На кнопки никакой реакции - ни до, ни после "замирания".
Что я делаю не так?
seri0shka:
пультоскоп с дисплеем 1202.
В общем оставил только "ОСЦИЛЛОГРАФ" так как другим не пользуюсь. Добавил коды автоматики: развёртка, Авто-опорное 5.0, 1.1, 0.22. Оставил только 3 кнопки. На кнопке "ок" вход и выход " Pause ". При удержании "лева-право" увидим "меньше-больше" развёртку + клацнем на "ок" такова же вида развёртка останется в " Pause ". От балды добавил в дежурное меню термометр и активный вольтметр батареи. Там ещё что то делал, но забыл))). Если интересно, то сделаю видео.
Вот видео: ССЫЛКА
Я не спец, так что критика мне не поможет, а вот если сможете улучшить то это большой +
#define BUFSIZE 800 #define history 50 volatile int cur_index = 0; //переменная для отсчета замеров volatile int StartIndex = 0; // номер замера с которого нужно выводить результат (считается так: (замер сработки триггера-предистория)) volatile byte prev_data; // предыдущее состояние шины volatile byte pattern_mask; // маска для события PATTERN volatile byte pattern_value; // ЗНАЧЕНИЕ состояния для события PATTERN volatile boolean trigger_event = false; //признак сработки триггера volatile int time_disc = 0; // время выборки 1-го значения unsigned long prevMillis, curMillis; enum triggerEvents {BURST, MASTER_RISE, MASTER_FALL, PATTERN}; //именнованный список триггеров-событий bool flag = 0; // Пины экранчика #define RES 3 #define CS 4 #define Data 6 #define Clock 7 #define swap(a, b) { int t = a; a = b; b = t; } #include <FreqCount.h> #include <math.h> #include <PWM.h> // Настройки пользователя - можно менять #define OVERCLOCK 16 // частота на которой работает Ардуино float VCC = 5.0; // напряжение питания #define KEY_L 11 // кнопка ЛЕВО (можно любой пин) #define KEY_OK 12 // кнопка ОК (можно любой пин) #define KEY_R 13 // кнопка ПРАВО (можно любой пин) #define VBAT A1 // любой свободный аналоговый пин для измерения напряжения АКБ #define TempC A0 // любой свободный аналоговый пин для измерения температуры #define KEY_DELAY 200 #define LCDX 96 #include <avr/pgmspace.h> const char string_0[] PROGMEM = "ОСЦИЛЛОГРАФ"; // "String 0" и т.д. - это содержимое строк; если необходимо меняйте его const char string_1[] PROGMEM = " "; const char string_2[] PROGMEM = "VБат.= "; const char string_3[] PROGMEM = "Temп.= "; const char string_4[] PROGMEM = " Pause "; // Теперь создаем таблицу с отсылками к этим строкам: const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4}; char buffer[11]; // массив должен быть достаточно велик, чтобы вместить даже самую большую строку byte mode = 0; // пункт главного меню byte menu = 0; // пункт меню byte adcBuf[BUFSIZE]; byte vSync = 30; // уровень синхронизации bool vRef = 1; // флаг опорного напряжения bool pause = 0; // флаг режима паузы bool avtorazv=1; // Автоматический выбор развертки byte TextColor = 1; byte razv = 0; byte trig = 0; int kdel=5; //bulat автопредел 1,1/0,22 вольта int grOffset = 0; // смещение графика в рабочем режиме byte vMax, vMin; // максимальное и минимальное напряжение сигнала int temp = 0; // временная переменная*** unsigned long count = 1; byte LCD_RAM[96 * 9]; // 96 * 9 static const char font[] PROGMEM = { //HEX B DEC переводим 0x00, 0x00, 0x00, 0x00, 0x00 , // 0x20 space 0x00, 0x00, 0x5f, 0x00, 0x00 , // 0x21 ! 0x00, 0x07, 0x00, 0x07, 0x00 , // 0x22 " 0x14, 0x7f, 0x14, 0x7f, 0x14 , // 0x23 # 0x24, 0x2a, 0x7f, 0x2a, 0x12 , // 0x24 $ 0x23, 0x13, 0x08, 0x64, 0x62 , // 0x25 % 0x36, 0x49, 0x55, 0x22, 0x50 , // 0x26 & 0x00, 0x05, 0x03, 0x00, 0x00 , // 0x27 ' 0x00, 0x1c, 0x22, 0x41, 0x00 , // 0x28 ( 0x00, 0x41, 0x22, 0x1c, 0x00 , // 0x29 ) 0x14, 0x08, 0x3e, 0x08, 0x14 , // 0x2a * 0x08, 0x08, 0x3e, 0x08, 0x08 , // 0x2b + 0x00, 0x50, 0x30, 0x00, 0x00 , // 0x2c , 0x08, 0x08, 0x08, 0x08, 0x08 , // 0x2d - 0x00, 0x60, 0x60, 0x00, 0x00 , // 0x2e . 0x20, 0x10, 0x08, 0x04, 0x02 , // 0x2f / 0x3e, 0x51, 0x49, 0x45, 0x3e , // 0x30 0 0x00, 0x42, 0x7f, 0x40, 0x00 , // 0x31 1 0x42, 0x61, 0x51, 0x49, 0x46 , // 0x32 2 0x21, 0x41, 0x45, 0x4b, 0x31 , // 0x33 3 0x18, 0x14, 0x12, 0x7f, 0x10 , // 0x34 4 0x27, 0x45, 0x45, 0x45, 0x39 , // 0x35 5 0x3c, 0x4a, 0x49, 0x49, 0x30 , // 0x36 6 0x01, 0x71, 0x09, 0x05, 0x03 , // 0x37 7 0x36, 0x49, 0x49, 0x49, 0x36 , // 0x38 8 0x06, 0x49, 0x49, 0x29, 0x1e , // 0x39 9 0x00, 0x36, 0x36, 0x00, 0x00 , // 0x3a : 0x00, 0x56, 0x36, 0x00, 0x00 , // 0x3b ; 0x08, 0x14, 0x22, 0x41, 0x00 , // 0x3c < 0x14, 0x14, 0x14, 0x14, 0x14 , // 0x3d = 0x00, 0x41, 0x22, 0x14, 0x08 , // 0x3e > 0x02, 0x01, 0x51, 0x09, 0x06 , // 0x3f ? 0x32, 0x49, 0x79, 0x41, 0x3e , // 0x40 @ 0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x41 A 0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x42 B 0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x43 C 0x7f, 0x41, 0x41, 0x22, 0x1c , // 0x44 D 0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x45 E 0x7f, 0x09, 0x09, 0x09, 0x01 , // 0x46 F 0x3e, 0x41, 0x49, 0x49, 0x7a , // 0x47 G 0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x48 H 0x00, 0x41, 0x7f, 0x41, 0x00 , // 0x49 I 0x20, 0x40, 0x41, 0x3f, 0x01 , // 0x4a J 0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x4b K 0x7f, 0x40, 0x40, 0x40, 0x40 , // 0x4c L 0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x4d M 0x7f, 0x04, 0x08, 0x10, 0x7f , // 0x4e N 0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x4f O 0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x50 P 0x3e, 0x41, 0x51, 0x21, 0x5e , // 0x51 Q 0x7f, 0x09, 0x19, 0x29, 0x46 , // 0x52 R 0x46, 0x49, 0x49, 0x49, 0x31 , // 0x53 S 0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x54 T 0x3f, 0x40, 0x40, 0x40, 0x3f , // 0x55 U 0x1f, 0x20, 0x40, 0x20, 0x1f , // 0x56 V 0x3f, 0x40, 0x38, 0x40, 0x3f , // 0x57 W 0x63, 0x14, 0x08, 0x14, 0x63 , // 0x58 X 0x07, 0x08, 0x70, 0x08, 0x07 , // 0x59 Y 0x61, 0x51, 0x49, 0x45, 0x43 , // 0x5a Z 0x00, 0x7f, 0x41, 0x41, 0x00 , // 0x5b [ 0x02, 0x04, 0x08, 0x10, 0x20 , // 0x5c backslash 0x00, 0x41, 0x41, 0x7f, 0x00 , // 0x5d ] 0x04, 0x02, 0x01, 0x02, 0x04 , // 0x5e ^ 0x40, 0x40, 0x40, 0x40, 0x40 , // 0x5f _ 0x00, 0x01, 0x02, 0x04, 0x00 , // 0x60 ` 0x20, 0x54, 0x54, 0x54, 0x78 , // 0x61 a 0x7f, 0x48, 0x44, 0x44, 0x38 , // 0x62 b 0x38, 0x44, 0x44, 0x44, 0x20 , // 0x63 c 0x38, 0x44, 0x44, 0x48, 0x7f , // 0x64 d 0x38, 0x54, 0x54, 0x54, 0x18 , // 0x65 e 0x08, 0x7e, 0x09, 0x01, 0x02 , // 0x66 f 0x0c, 0x52, 0x52, 0x52, 0x3e , // 0x67 g 0x7f, 0x08, 0x04, 0x04, 0x78 , // 0x68 h 0x00, 0x44, 0x7d, 0x40, 0x00 , // 0x69 i 0x20, 0x40, 0x44, 0x3d, 0x00 , // 0x6a j 0x7f, 0x10, 0x28, 0x44, 0x00 , // 0x6b k 0x00, 0x41, 0x7f, 0x40, 0x00 , // 0x6c l 0x7c, 0x04, 0x18, 0x04, 0x78 , // 0x6d m 0x7c, 0x08, 0x04, 0x04, 0x78 , // 0x6e n 0x38, 0x44, 0x44, 0x44, 0x38 , // 0x6f o 0x7c, 0x14, 0x14, 0x14, 0x08 , // 0x70 p 0x08, 0x14, 0x14, 0x18, 0x7c , // 0x71 q 0x7c, 0x08, 0x04, 0x04, 0x08 , // 0x72 r 0x48, 0x54, 0x54, 0x54, 0x20 , // 0x73 s 0x04, 0x3f, 0x44, 0x40, 0x20 , // 0x74 t 0x3c, 0x40, 0x40, 0x20, 0x7c , // 0x75 u 0x1c, 0x20, 0x40, 0x20, 0x1c , // 0x76 v 0x3c, 0x40, 0x30, 0x40, 0x3c , // 0x77 w 0x44, 0x28, 0x10, 0x28, 0x44 , // 0x78 x 0x0c, 0x50, 0x50, 0x50, 0x3c , // 0x79 y 0x44, 0x64, 0x54, 0x4c, 0x44 , // 0x7a z 0x00, 0x08, 0x36, 0x41, 0x00 , // 0x7b { 0x00, 0x00, 0x7f, 0x00, 0x00 , // 0x7c | 0x00, 0x41, 0x36, 0x08, 0x00 , // 0x7d } 0x10, 0x08, 0x08, 0x10, 0x08 , // 0x7e ~ 0x00, 0x00, 0x00, 0x00, 0x00 , // 0x7f 0x7e, 0x11, 0x11, 0x11, 0x7e , // 0x80 A // Русские символы 0x7f, 0x49, 0x49, 0x49, 0x33 , // 0x81 Б 0x7f, 0x49, 0x49, 0x49, 0x36 , // 0x82 В 0x7f, 0x01, 0x01, 0x01, 0x03 , // 0x83 Г 0xe0, 0x51, 0x4f, 0x41, 0xff , // 0x84 Д 0x7f, 0x49, 0x49, 0x49, 0x41 , // 0x85 E 0x77, 0x08, 0x7f, 0x08, 0x77 , // 0x86 Ж 0x41, 0x49, 0x49, 0x49, 0x36 , // 0x87 З 0x7f, 0x10, 0x08, 0x04, 0x7f , // 0x88 И 0x7c, 0x21, 0x12, 0x09, 0x7c , // 0x89 Й 0x7f, 0x08, 0x14, 0x22, 0x41 , // 0x8A K 0x20, 0x41, 0x3f, 0x01, 0x7f , // 0x8B Л 0x7f, 0x02, 0x0c, 0x02, 0x7f , // 0x8C M 0x7f, 0x08, 0x08, 0x08, 0x7f , // 0x8D H 0x3e, 0x41, 0x41, 0x41, 0x3e , // 0x8E O 0x7f, 0x01, 0x01, 0x01, 0x7f , // 0x8F П 0x7f, 0x09, 0x09, 0x09, 0x06 , // 0x90 P 0x3e, 0x41, 0x41, 0x41, 0x22 , // 0x91 C 0x01, 0x01, 0x7f, 0x01, 0x01 , // 0x92 T 0x47, 0x28, 0x10, 0x08, 0x07 , // 0x93 У 0x1c, 0x22, 0x7f, 0x22, 0x1c , // 0x94 Ф 0x63, 0x14, 0x08, 0x14, 0x63 , // 0x95 X 0x7f, 0x40, 0x40, 0x40, 0xff , // 0x96 Ц 0x07, 0x08, 0x08, 0x08, 0x7f , // 0x97 Ч 0x7f, 0x40, 0x7f, 0x40, 0x7f , // 0x98 Ш 0x7f, 0x40, 0x7f, 0x40, 0xff , // 0x99 Щ 0x01, 0x7f, 0x48, 0x48, 0x30 , // 0x9A Ъ 0x7f, 0x48, 0x30, 0x00, 0x7f , // 0x9B Ы 0x00, 0x7f, 0x48, 0x48, 0x30 , // 0x9C Э 0x22, 0x41, 0x49, 0x49, 0x3e , // 0x9D Ь 0x7f, 0x08, 0x3e, 0x41, 0x3e , // 0x9E Ю 0x46, 0x29, 0x19, 0x09, 0x7f , // 0x9F Я 0x20, 0x54, 0x54, 0x54, 0x78 , // 0xA0 a 0x3c, 0x4a, 0x4a, 0x49, 0x31 , // 0xA1 б 0x7c, 0x54, 0x54, 0x54, 0x28 , // 0xA2 в 0x7c, 0x04, 0x04, 0x04, 0x0c , // 0xA3 г 0xe0, 0x54, 0x4c, 0x44, 0xfc , // 0xA4 д 0x38, 0x54, 0x54, 0x54, 0x18 , // 0xA5 e 0x6c, 0x10, 0x7c, 0x10, 0x6c , // 0xA6 ж 0x44, 0x44, 0x54, 0x54, 0x28 , // 0xA7 з 0x7c, 0x20, 0x10, 0x08, 0x7c , // 0xA8 и 0x7c, 0x41, 0x22, 0x11, 0x7c , // 0xA9 й 0x7c, 0x10, 0x10, 0x28, 0x44 , // 0xAA к 0x20, 0x44, 0x3c, 0x04, 0x7c , // 0xAB л 0x7c, 0x08, 0x10, 0x08, 0x7c , // 0xAC м 0x7c, 0x10, 0x10, 0x10, 0x7c , // 0xAD н 0x38, 0x44, 0x44, 0x44, 0x38 , // 0xAE o 0x7c, 0x04, 0x04, 0x04, 0x7c , // 0xAF п 0x7C, 0x14, 0x14, 0x14, 0x08 , // 0xB0 p 0x38, 0x44, 0x44, 0x44, 0x20 , // 0xB1 c 0x04, 0x04, 0x7c, 0x04, 0x04 , // 0xB2 т 0x0C, 0x50, 0x50, 0x50, 0x3C , // 0xB3 у 0x30, 0x48, 0xfc, 0x48, 0x30 , // 0xB4 ф 0x44, 0x28, 0x10, 0x28, 0x44 , // 0xB5 x 0x7c, 0x40, 0x40, 0x40, 0xfc , // 0xB6 ц 0x0c, 0x10, 0x10, 0x10, 0x7c , // 0xB7 ч 0x7c, 0x40, 0x7c, 0x40, 0x7c , // 0xB8 ш 0x7c, 0x40, 0x7c, 0x40, 0xfc , // 0xB9 щ 0x04, 0x7c, 0x50, 0x50, 0x20 , // 0xBA ъ 0x7c, 0x50, 0x50, 0x20, 0x7c , // 0xBB ы 0x7c, 0x50, 0x50, 0x20, 0x00 , // 0xBC ь 0x28, 0x44, 0x54, 0x54, 0x38 , // 0xBD э 0x7c, 0x10, 0x38, 0x44, 0x38 , // 0xBE ю 0x08, 0x54, 0x34, 0x14, 0x7c , // 0xBF я }; //******************************************************** // ==== Считывание напряжения питания ардуинки (Vcc) ==== #define Vref11 1.095 // для точной подстройки результата измерений float ReadVcc() { ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); // устанавливаем вход АЦП на VCC !!! delay(1); // задержка для устаканивания АЦП. Можно её избежать, если ADMUX как в строке выше (не менялся) ADCSRA |= _BV(ADSC); // запуск АЦП преобразования while (bit_is_set(ADCSRA, ADSC)); // ждем, пока АЦП отработает (выставит бит) return (Vref11 * 1023.0) / (ADCL | (ADCH << 8)); // результат преобразования в вольтах } /////// ==== Температура ==== //////// double Thermister(int RawADC) { double Temp; Temp = log(((10240000/RawADC) - 10000)); // 10000=10кОм Для подстройки правим 10000. Temp = 1 / (0.001129148 + (0.000234125 * Temp) + (0.0000000876741 * Temp * Temp * Temp)); Temp = Temp - 273.15; // Kelvin to Celcius return Temp; } void setup() { pinMode(KEY_OK, INPUT); pinMode(KEY_L, INPUT); pinMode(KEY_R, INPUT); // настраиваем кнопки на вход digitalWrite(KEY_OK, HIGH); digitalWrite(KEY_L, HIGH); digitalWrite(KEY_R, HIGH); // подтяжка к плюсу питания VCC = ReadVcc(); Inicialize(); //Инициализация дисплея Clear_LCD(); for (byte i = 0; i < 3; i++) { strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // необходимые функции и расшифровки, просто скопируйте print(10, i * 10, 1, (buffer)); //delay( 500 ); } Update(); delay(KEY_DELAY); while (digitalRead(KEY_OK)) { // цикл, пока не нажали кнопку ОК Update(); ////////// Выводим показание ///////// float_print(60, 20, 1, analogRead(VBAT)*VCC/1024,1); //Вольтаж батареи float_print(55, 40, 1, analogRead(TempC), 1); // выводим на экран показание Температуры strcpy_P(buffer, (char*)pgm_read_word(&(string_table[3]))); // пишем слово "Температура" print(10, 40, 1, (buffer)); delay( 200 ); } // цикл нажатия ОК // нажали кнопку ОК из меню, инициализируем и выходим из меню count = 0; //countX = 0; // восстанавливаем на всякий случай переменные if (mode == 0) FreqCount.begin(1000); if (mode == 1) { InitTimersSafe(); } if (mode == 2) { InitTimersSafe(); } if (mode == 4 || mode == 5) DDRC = 0x00; PORTC = 0x00;// Serial.begin(115200); // razv = 0;// весь порт С (это A0...A5) на вход и без подтяжки for (char a=37; a>0; a-=2); } // беcконечный цикл - по сути прыгаем в подпрограммы void loop() { switch (mode) { // Прыгаем в выбранный режим из главного меню case 0 : Oscil(); break; // "выпадаем" в осцилл } } // === Читаем с АЦП данные и помещаем их в буфер === // void ReadAdc() { if (razv % 10) { // (razv>0) // если развертка без задержек всяких (с 1 по 7) ADCSRA = 0b11100000 | (8 - (razv % 10)); // установили делитель (/2 - не работает, так что начинаем с /4) for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения while (!(ADCSRA & 0x10)); // ждем готовность АЦП ADCSRA |= 0x10; // запускаем следующее преобразование adcBuf[i] = ADCH; // записываем данные в массив } delay(0.3 * BUFSIZE); // компенсация задержки по сравнению с разверткой 0... } else { // развертка с задержками (delay) ADCSRA = 0b11100111; // делитель на /128 for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения while (!(ADCSRA & 0x10)); // ждем готовность АЦП ADCSRA |= 0x10; // запускаем следующее преобразование delayMicroseconds(500); // делаем задержку adcBuf[i] = ADCH; // записываем данные в массив } } } // === Чтение цифровых данных со всего порта C (A0...A5) === // void ReadDig() { if (razv == 9) { for (int i = 0; i < BUFSIZE; i++) adcBuf[i] = PINC; // быстро читаем данные } else { for (int i = 0; i < BUFSIZE; i++) { adcBuf[i] = PINC; // читаем данные delayMicroseconds((9 - razv) * 100); } } } // ==== функция вывода float ==== void float_print(byte x, byte y, boolean color, float num, byte zn) { // последняя переменная- кол знаков после запятой char c[20]; long d = num; byte m = 1; while (d > 9) { d = d / 10; m++; } print(x, y, color, dtostrf(num, m, zn, c)); } /*int GetCountsOfDigits(int n) //найти количество цифр в числе <a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a> { return n < 10 ? 1 : n < 100 ? 2 : n < 1000 ? 3 : n < 10000 ? 4 : n < 100000 ? 5 : n < 1000000 ? 6 : n < 10000000 ? 7 : n < 100000000 ? 8 : n < 1000000000 ? 9 : 10; }*/ // ==== найти количество цифр в числе <a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a> /*static int stringSize(long x) { long p = 10; for (int i = 1; i < 19; i++) { if (x < p) return i; p = 10 * p; } return 19; }*/ void vivod(byte x, byte y, byte n, byte k) { // //Печать цифры размером 24х48 пикселя (x, y, цифра, размер (1-24х48, 2-12х24)) if ((n != 1) && (n != 4)) { fillRect(x + 3 / k, y, 15 / k, 5 / k, 1 ); // сегмент A } if ((n != 5) && (n != 6)) { fillRect(x + 16 / k, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент B } if (n != 2) { fillRect(x + 16 / k, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент C } if ((n != 1) && (n != 4) && (n != 7)) { fillRect(x + 3 / k, y + 42 / k, 15 / k, 5 / k, 1 ); // сегмент D } if ((n == 0) || (n == 2) || (n == 6) || (n == 8)) { fillRect(x, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент E } if ((n != 1) && (n != 2) && (n != 3) && (n != 7)) { fillRect(x, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент F } if ((n != 0) && (n != 1) && (n != 7)) { fillRect(x + 3 / k, y + 21 / k, 15 / k, 5 / k, 1 ); // сегмент G } } //====================================================указатель меню /*void ukazatel() { fillRect(1, 1, 8, 60, 0); for (byte i = 0; i < 4; i++) { // указатель меню drawLine(1 + i, mode * 10 + i, 1 + i, mode * 10 + 6 - i, 1); } Update(); delay(KEY_DELAY); } */ //===================================================Инициализация дисплея void Inicialize() { pinMode(RES, OUTPUT); pinMode(CS, OUTPUT); pinMode(Data, OUTPUT); pinMode(Clock, OUTPUT); // Инициализация дисплея dWrite(RES, 1); dWrite(Clock, 0); dWrite(Data, 0); dWrite(CS, 0); delay(20); dWrite(CS, 1); SendByte(0, 0x2F); // Power control set(charge pump on/off) SendByte(0, 0xA4); SendByte(0, 0xAF); // экран вкл/выкл //Clear_LCD(); //Update(); } //=======================================================Управление пинами void dWrite(byte pin, byte val) { byte bit = digitalPinToBitMask(pin); volatile byte *out; out = portOutputRegister(digitalPinToPort(pin)); (val) ? *out |= bit : *out &= ~bit; } //=========================================================Отправка 9 байт void SendByte(byte mode, byte c) { dWrite(CS, 0); (mode) ? dWrite(Data, 1) : dWrite(Data, 0); dWrite(Clock, 1); for (byte i = 0; i < 8; i++) { dWrite(Clock, 0); (c & 0x80) ? dWrite(Data, 1) : dWrite(Data, 0); dWrite(Clock, 1); c <<= 1; } dWrite(Clock, 0); } //======================================================Очистка дисплея void Clear_LCD() { for (int index = 0; index < 864 ; index++) { LCD_RAM[index] = (0x00); } } //=====================================================Обновить дисплей void Update() { for (byte p = 0; p < 9; p++) { SendByte(0, 0xB0 | p); SendByte(0, 0x00); SendByte(0, 0x10); for (byte col = 0; col < 96; col++) { SendByte(1, LCD_RAM[(96 * p) + col]); } } } //===================================================Нарисовать пиксель void drawPixel (byte x, byte y, boolean color) { if ((x < 0) || (x >= 96) || (y < 0) || (y >= 68)) return; if (color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8); else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8); } //=====================================================Нарисовать букву void drawChar(byte x, byte y, boolean color, unsigned char c) { if ((x >= 96) || (y >= 68) || ((x + 4) < 0) || ((y + 7) < 0)) return; if (c < 128) c = c - 32; if (c >= 144 && c <= 175) c = c - 48; if (c >= 128 && c <= 143) c = c + 16; if (c >= 176 && c <= 191) c = c - 48; if (c > 191) return; for (byte i = 0; i < 6; i++ ) { byte line; (i == 5) ? line = 0x0 : line = pgm_read_byte(font + (c * 5) + i); // line = EEPROM.read((c * 5) + i); for (byte j = 0; j < 8; j++) { (line & 0x1) ? drawPixel(x + i, y + j, color) : drawPixel(x + i, y + j, !color); line >>= 1; } } } //========================================================Вывод строки void print(byte x, byte y, boolean color, char *str) { unsigned char type = *str; if (type >= 128) x = x - 3; while (*str) { drawChar(x, y, color, *str++); unsigned char type = *str; (type >= 128) ? x = x + 3 : x = x + 6; } } //========================================================Вывод числовых значений void print(byte x, byte y, boolean color, long num) { char c[20]; print(x, y, color, ltoa(num, c, 10)); } //====================================================Рисование линии void drawLine(byte x0, byte y0, byte x1, byte y1, boolean color) { int steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { swap(x0, y0); swap(x1, y1); } if (x0 > x1) { swap(x0, x1); swap(y0, y1); } int dx, dy; dx = x1 - x0; dy = abs(y1 - y0); int err = dx / 2; int ystep; (y0 < y1) ? ystep = 1 : ystep = -1; for (; x0 <= x1; x0++) { (steep) ? drawPixel(y0, x0, color) : drawPixel(x0, y0, color); err -= dy; if (err < 0) { y0 += ystep; err += dx; } } } //========================================Рисование вертикальной линии void drawFastVLine(byte x, byte y, byte h, boolean color) { drawLine(x, y, x, y + h - 1, color); } //======================================Рисование горизонтальной линии void drawFastHLine(byte x, byte y, byte w, boolean color) { drawLine(x, y, x + w - 1, y, color); } //=====================================Рисование залитый прямоугольник void fillRect(byte x, byte y, byte w, byte h, boolean color) { for (byte i = x; i < x + w; i++) { drawFastVLine(i, y, h, color); } } //=====================================Рисование битового нолика void printnull(byte a, byte i) { drawPixel(29 + a - i * 4, 64, 1); drawFastVLine(28 + a - i * 4, 65, 2, 1); // и вывести биты на дисплей drawFastVLine(30 + a - i * 4, 65, 2, 1); drawPixel(29 + a - i * 4, 67, 1); } // === Осциллоскоп === // void Oscil() { // установка опорного напряжения АЦП и настройка входа АЦП ADMUX = vRef ? 0b01100011 : 0b11100011; label_ReadAdc: // === Обработка кнопок === // if (!digitalRead(KEY_L)) switch (menu) { // кнопка лево:) case 0 : razv--; if (razv == 255) razv = 6; break; // меняем развертку case 1 : grOffset -= 20; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе } if (!digitalRead(KEY_R)) switch (menu) { // кнопка право:) case 0 : razv++; if (razv == 7) razv = 0; break; // меняем развертку case 1 : grOffset += 20; if (grOffset > BUFSIZE - LCDX) grOffset = BUFSIZE - LCDX; break; // листаем график в паузе } if (!digitalRead(KEY_OK)) switch (++menu) { case 1: grOffset = 0; pause = 1; break; // вход в паузу - антидребезг типа case 2: menu = 0; pause = 0; break; // перебор меню } //////////////// // === Ведём рассчеты === // if (!pause) { // если нет паузы ReadAdc(); // то снимаем осциллограмму // == Вычисляем максимальное и минимальное значение сигнала == // vMax = 0; vMin = 0xFF; for (int y = 1; y < 255; y++) { if (vMax < adcBuf[y]) vMax = adcBuf[y]; // пока 255, но надо экспериментировать if (vMin > adcBuf[y]) vMin = adcBuf[y]; } vSync = (vMax - vMin) / 2 + vMin; // уровень синхронизации по середине уровня сигнала // == Определение точки синхронизации == // bool flagZero = 0; grOffset = 0; // сброс флага и точки синхронизации // Ищем перепад от меньшего уровня к большему for (int y = 1; y < BUFSIZE - LCDX; y++) { // смотрим весь массив данных АЦП if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - ставим флаг if (flagZero && adcBuf[y] > vSync) { grOffset = y; // нашли больше, чем синхра (перепад сигнала в плюс) - запомнили и выходим из цикла break; } } // === Считаем частоту сигнала === // if (vRef && vMax * VCC / 255 > 2.7) { // если можем замерить аппаратно - меряем if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала } else { // === Меряем частоту сигнала программно === // flagZero = 0; count = 0; // сброс флага и счетчика for (int y = grOffset; y < BUFSIZE - LCDX; y++) { // смотрим массив от точки синхронизации до конца if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг if (flagZero && adcBuf[y] > vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период switch (razv) { // считем частоту периода case 6: count = 1000000 / ((y - grOffset - 1) * 3.25); break; // делитель 4 case 5: count = 1000000 / ((y - grOffset) * 3.25) / 2; break; // делитель 8 case 4: count = 1000000 / ((y - grOffset) * 3.25) / 4; break; // делитель 16 case 3: count = 1000000 / ((y - grOffset) * 3.25) / 8; break; // делитель 32 case 2: count = 1000000 / ((y - grOffset) * 3.25) / 16; break; // делитель 64 case 1: count = 1000000 / ((y - grOffset) * 3.25) / 32; break; // делитель 128 case 0: count = 1000000 / ((y - grOffset) * 510); break; // делитель 128 тоже } break; } } } count = count * OVERCLOCK / 16.0; // пересчет частоты на разные кварцы } // закончили вести рассчеты Clear_LCD(); // чистим экран... // === Отрисовка меню осцилла === if (vRef) TextColor = 0; else TextColor = 1; if (vRef) float_print(0, 0, 1, VCC, 1); else { if(kdel==5)print(0, 0, 1, "1.1"); else print(0, 0, 1, "0.2"); } if (menu == 0) TextColor = 0; else TextColor = 1; drawChar(21, 0, TextColor, 'р'); print(27, 0, TextColor, razv); if (menu == 1) { // тут задержка для компенсации с остальными задержками delay(200); // print(48, 0, 0, " Pause "); strcpy_P(buffer, (char*)pgm_read_word(&(string_table[4]))); // необходимые функции и расшифровки, просто скопируйте print(48, 0, 0, (buffer)); } else TextColor = 1; if (!pause) float_print (48, 0, 1, count / 1000000.0, 6); // вывод частоты else { // рисуем прокрутку в режиме паузы temp = grOffset / 8; drawFastHLine(temp, 10, 6, 1); drawFastHLine(temp, 9, 6, 1); } // шкала прокрутки if (vRef && vMax * VCC / 255 > 2.7) drawChar(38, 0, 1, '*'); // если замер - "а"ппаратный else drawChar(38, 0, 1, 'п'); // иначе "п"програмный float_print(73, 10, 1, vMax * (vRef ? VCC : 1.1) / 255, 2); // рисуем максимальное напряжение сигнала float_print(78, 54, 1, vMin * (vRef ? VCC : 1.1) / 255, 1); // рисуем минимальное напряжение сигнала if (vMax==0xFF) for(int y=10; y<68; y++) drawFastHLine( 0, y, 5, 5); // превышение максимума АЦП // == Отрисовка сетки == // for (byte i = 11; i < 68; i = i + 14) { drawFastHLine( 0, i, 2, 1); // черточки слева } for (byte i = 67; i > 10; i = i - 4) { drawPixel(24, i, 1); drawPixel(48, i, 1); drawPixel(72, i, 1); } for (byte i = 8; i < 96; i = i + 4) { drawPixel(i, 39, 1); } ///////////////авто razv////////////// if (avtorazv) #define PER 1.3 if (count > 3823.3*PER) razv = 6; else if (count > 1934.5*PER) razv = 5; else if (count > 0969.3*PER) razv = 4; else if (count > 0486.8*PER) razv = 3; else if (count > 0245.8*PER) razv = 2; else if (count > 0120.1*PER) razv = 1; else razv = 0; //bulat если зашкаливает включаем предел 5 в if (vMax==255){ if (vRef==0) { vRef=1; ADMUX = 0b01100011;// выбор внутреннего опорного 5.0 В goto label_ReadAdc; } } //bulat если 5 в и уровень менее 1,1 в то вкл предел 1,1 в if (vMax<=55){ if (vRef==1) { vRef=0; ADMUX = 0b11100011;// выбор внутреннего опорного 1,1В goto label_ReadAdc; } } //bulat здесь автопредел 1,1/0,22 в,программный kdel=5; if (vMax<=55){ if (vRef==0) { kdel=1; } } // == Отрисовка графика == // for (int y = 0; y < 92; y++) drawLine(y + 4, 67 - adcBuf[y + grOffset]/kdel / 0.9, y + 4, 67 - adcBuf[y + grOffset + 1]/kdel / 0.9, 1); Update(); }это беспощадный кодинг с кровью в глазах)) что я увидел за 10 сек: смотрим функцию drawLine
int steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { swap(x0, y0); swap(x1, y1); } if (x0 > x1) { swap(x0, x1); swap(y0, y1); }void drawPixel (byte x, byte y, boolean color) { if (color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8); else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8); }но еще лучше определить ее дефайном, ибо очень часто вызывается. функцию удали/закомментируй, где нить вверху к дефайнам прилепи это:
#define drawPixel(pix_x, pix_y, clr) { \ if(clr) LCD_RAM[(pix_x) + ((pix_y) / 8) * 96] |= _BV((pix_y) % 8); \ else LCD_RAM[(pix_x) + ((pix_y) / 8) * 96] &= ~_BV((pix_y) % 8); \ }можно еще ускорить. потом. если захочешь)) просто, я лучше не сделаю, не хочу и не буду. а быстрее - можно)) но может и не нужно будет, с такой инертностью дисплея...
проверишь - отпиши. может глюки какие или не заработает... на моем интерпретаторе в голове вроде работает раза в три-пять быстрее))
progrik:
Это не мой код, его замутил seri0shka: Я просто туда добавил автоматику от Electronik83:, так как это на много удобнее в пользовании.
С новым drawPixel: работает, А с кодом ниже ей не нравится 'print'. Пока не могу придти в себя после 9 мая, кстаки С Днём Победы! Если в реальную за "работает раза в три-пять быстрее))", то круто!!!
if(steep) { drawPixel(y0, x0, color); } else { drawPixel(x0, y0, color); }и строку (line & 0x1) ? drawPixel(x + i, y + j, color) : drawPixel(x + i, y + j, !color); замени на
if(line & 0x1) { drawPixel(x + i, y + j, color); } else { drawPixel(x + i, y + j, !color); }не все макросы можно пихать в конструкцию ?:, сделал тоже самое, только через if/else. проверяй. и прикинь получившийся фпс, оч интересно. а то у тебя был где-то 3 )) не знаешь как - снимай в 60-120 фпс и считай по кадрам)) на паузе перемотка должна показать хорошо...
а, да. с днем победы. отдыхай))
ЗЫ: seri0shka и все все причастные к коду. извините меня за грубости об этом коде и кодерах... на самом деле присутствует отсутствие обучающего материала) - в основном только модули китайские цепляют, никакого креатива. нет разъяснения кода. нет выхода за рамки библиотек. короче, чёт я погорячился поливать. сорри. вы же стараетесь)...я надеюсь)
progrik: Вроди бы шустрее стало))), только чего то при опорном 5в. стало писать "NAN". При опорном ниже 5в. всё норм. ХЗ.
void drawPixel (byte x, byte y, boolean color) { if (color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8); else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8); }Вернул на место и всё ОК.
еще в функции SendByte снова перед _каждой_отправкой_байта_ вызывается dWrite(CS, 0); что есть хорошо... НЕ ОЧЕНЬ)) это нужно сделать один раз в сетапе, после инициализации дисплея. и если ноги от дисплея не используются другими приблудами(не вижу таких), то не поднимать ногу вообще. опустил и забыл.
и еще кто-то решил, что программный SPI быстрее аппаратного... это грустно... на отрисовку одной точки вызывается три функции, некоторе по 4-5 раз - мне этого не понять. dWrite нужно дефайном или инлайн делать, все нужно делать.. да, в выводе хлама много. много=всё.
вообще крайне странно, что никак не связанная с изменениями функция ReadVcc перестала работать...
вообще крайне странно, что никак не связанная с изменениями функция ReadVcc перестала работать...
if (Косо-криво, лиж бы было); else print (шутка);
inline __attribute__((always_inline)) void drawPixel (byte x, byte y, boolean color) { if (color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8); else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8); }нужно пробовать. и по хорошему все равно надо посмотреть что там за косяки в ReadVcc ... а у меня мало времени, я очень много отдыхаю))) пробуй заменить дравпиксель на новый с инлайн дизайном))) но я бы с прибором в 40 пикселей в высоту написал бы 5 вольт и не морочился, что там мерить?... запитал от более-менее хорошего стаба или DC-DC модуля и всё. ладно. давай чинить)) пробуй))
Всем спасибо за полезную информацию и проделанную работу по такому осциллографическому пробничку!По началу делал на дисплее Nokia 5110, но для данного дисплея видимо просто необходим преобразователь уровней (как здесь уже упоминалось). Т.к. работает нестабильно, либо вообще не включается. Поэтому решил повторить на OLED дисплее. Так компактнее получается и видно все, не смотря на миниатюризацию показаний. Фото изделия прилагаю...