День добрый. Чего-то у меня кнопка ОК буд-то сама нажимается. Схему проверил. А когда на неё нажмёшь и держишь, то всё нормально. Наоборот работает. Это происходит во всех режимах.
volodya198024, вы хоть бы намекнули о чём речь. Не все фломастеры одинаково сладкие...
Например, в PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION.ino, есть строка 80:
//если автодетект работает неверно (менюха скачет постоянно), то нужно расскомментировать одну из следующих строчек:
// flag_key = 0; // кнопки просто подключены к земле, резюков нету.
flag_key = 1; // кнопки подключены к питанию и резюки на землю
Прошу прощения за мою не компетентность. Да действительно. Попробуй угадай. В последней версии для 5110 в сообщение #4401 при подачи питания сразу включается осциллограф. Если зажать кнопку ОК и включить, то включится меню которое можно листать (при зажатой кнопке ОК). Включение выбранного режима при кратковременном отпускание кнопки. Например при включенном PWM-генераторе постоянное перемещение курсора. Я понимаю что произошла инверсия состояния кнопки или входа. Но где? Я без помощи не разберусь.
ну да, остальные кроме всех работают)) ОК жмакается сам, пункты в меню тоже. а какие тогда кнопки ведут себя "правильно"?)) RESET?)))
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
//Страница проэкта <a href="http://srukami.inf.ua/pultoscop_v25110.html" title="http://srukami.inf.ua/pultoscop_v25110.html" rel="nofollow">http://srukami.inf.ua/pultoscop_v25110.html</a>
// === От меня [Electronik83] === mailTo: <a href="mailto:gsmkillersevsk@mail.ru">gsmkillersevsk@mail.ru</a>
// 1. Оптимизировал, причесал код
// 2. Сделал красивей главное меню, добавил новый пункт
// 3. Отображение частатоы и напряжения в осцилле при 1Кгц и 2,5в (был баг автора)
// 4. Новый режим - медленный осцилл - доделал...
// 5. Оптимизация.....
// 6. Убрал програмную растяжку сигнала из осцилла (развертка 7 и 8)
// 7. Изменил отрисовку сигнала в осцилле (больше нету этих раздвоений сигнала)
// 8. Убрал нахрен кнопку питания, и все что с ней сязано - проще тумблер (переключатель) поставить...
// 9. Анимировал главное меню. Пофиксил мерцание.
//10. Вставил свое меню генератора, DDS-генератора, терминала.
//11. Добавил немного новой анимации.
//12. Провел эксперимент с DDS-генератором и регулировкой частоты - не сделать.
// === ver19 ==
//13. В осциле - Сделал автосинхронизацию по серединке амплитуды сигнала <= подумать над внешней синхрой !!!
//14. В осциле - показываем масимальное и минимальное значение амплитуды сигнала справа
//15. Оптимизация некоторых участков кода
//16. Атмега теперь сама меряет напряжение своего питания, не надо ничего мультиметром мерять
//17. В осцилле - сделал более удобный вывод верхней строки в осцилле, "устатичил" вывод частоты.
// - теперь нет этого дерганья из Гц в кГц (и обратно) - просто выводим в Мгц.
//18. Добавил цифровой анализатор (входы A1, A2, A3, A4, A5) - что то мне он не понравился (и мне тоже).
/////////////// smokok ///////////////
//19. Добавил Авто-опорное 5.0,1.1,0.2
//20. Добавил Меню экрана (регулировка контрастности и включение подсвеки экрана).
//21. Добавил температуру. Пин термистора (10к) в А0 и +5, доп резистор (10к) в А0 и -5
//22. Разогнал PULTOSCOPE благодаря progrik
//23. Пока только вырезал UART приемник
// В планах внедрить Коэффициент заполнения
Уже наверное надо схему рисовать ,ведь видоизменилась..
ну да, остальные кроме всех работают)) ОК жмакается сам, пункты в меню тоже. а какие тогда кнопки ведут себя "правильно"?)) RESET?)))
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
//Страница проэкта <a href="http://srukami.inf.ua/pultoscop_v25110.html" title="http://srukami.inf.ua/pultoscop_v25110.html" rel="nofollow">http://srukami.inf.ua/pultoscop_v25110.html</a>
// === От меня [Electronik83] === mailTo: <a href="mailto:gsmkillersevsk@mail.ru">gsmkillersevsk@mail.ru</a>
// 1. Оптимизировал, причесал код
// 2. Сделал красивей главное меню, добавил новый пункт
// 3. Отображение частатоы и напряжения в осцилле при 1Кгц и 2,5в (был баг автора)
// 4. Новый режим - медленный осцилл - доделал...
// 5. Оптимизация.....
// 6. Убрал програмную растяжку сигнала из осцилла (развертка 7 и 8)
// 7. Изменил отрисовку сигнала в осцилле (больше нету этих раздвоений сигнала)
// 8. Убрал нахрен кнопку питания, и все что с ней сязано - проще тумблер (переключатель) поставить...
// 9. Анимировал главное меню. Пофиксил мерцание.
//10. Вставил свое меню генератора, DDS-генератора, терминала.
//11. Добавил немного новой анимации.
//12. Провел эксперимент с DDS-генератором и регулировкой частоты - не сделать.
// === ver19 ==
//13. В осциле - Сделал автосинхронизацию по серединке амплитуды сигнала <= подумать над внешней синхрой !!!
//14. В осциле - показываем масимальное и минимальное значение амплитуды сигнала справа
//15. Оптимизация некоторых участков кода
//16. Атмега теперь сама меряет напряжение своего питания, не надо ничего мультиметром мерять
//17. В осцилле - сделал более удобный вывод верхней строки в осцилле, "устатичил" вывод частоты.
// - теперь нет этого дерганья из Гц в кГц (и обратно) - просто выводим в Мгц.
//18. Добавил цифровой анализатор (входы A1, A2, A3, A4, A5) - что то мне он не понравился (и мне тоже).
/////////////// smokok ///////////////
//19. Добавил Авто-опорное 5.0,1.1,0.2
//20. Добавил Меню экрана (регулировка контрастности и включение подсвеки экрана).
//21. Добавил температуру. Пин термистора (10к) в А0 и +5, доп резистор (10к) в А0 и -5
//22. Разогнал PULTOSCOPE благодаря progrik
//23. Пока только вырезал UART приемник
// В планах внедрить Коэффициент заполнения
Уже наверное надо схему рисовать ,ведь видоизменилась..
ну да, остальные кроме всех работают)) ОК жмакается сам, пункты в меню тоже. а какие тогда кнопки ведут себя "правильно"?)) RESET?)))
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
//Страница проэкта <a href="http://srukami.inf.ua/pultoscop_v25110.html" title="http://srukami.inf.ua/pultoscop_v25110.html" rel="nofollow">http://srukami.inf.ua/pultoscop_v25110.html</a>
// === От меня [Electronik83] === mailTo: <a href="mailto:gsmkillersevsk@mail.ru">gsmkillersevsk@mail.ru</a>
// 1. Оптимизировал, причесал код
// 2. Сделал красивей главное меню, добавил новый пункт
// 3. Отображение частатоы и напряжения в осцилле при 1Кгц и 2,5в (был баг автора)
// 4. Новый режим - медленный осцилл - доделал...
// 5. Оптимизация.....
// 6. Убрал програмную растяжку сигнала из осцилла (развертка 7 и 8)
// 7. Изменил отрисовку сигнала в осцилле (больше нету этих раздвоений сигнала)
// 8. Убрал нахрен кнопку питания, и все что с ней сязано - проще тумблер (переключатель) поставить...
// 9. Анимировал главное меню. Пофиксил мерцание.
//10. Вставил свое меню генератора, DDS-генератора, терминала.
//11. Добавил немного новой анимации.
//12. Провел эксперимент с DDS-генератором и регулировкой частоты - не сделать.
// === ver19 ==
//13. В осциле - Сделал автосинхронизацию по серединке амплитуды сигнала <= подумать над внешней синхрой !!!
//14. В осциле - показываем масимальное и минимальное значение амплитуды сигнала справа
//15. Оптимизация некоторых участков кода
//16. Атмега теперь сама меряет напряжение своего питания, не надо ничего мультиметром мерять
//17. В осцилле - сделал более удобный вывод верхней строки в осцилле, "устатичил" вывод частоты.
// - теперь нет этого дерганья из Гц в кГц (и обратно) - просто выводим в Мгц.
//18. Добавил цифровой анализатор (входы A1, A2, A3, A4, A5) - что то мне он не понравился (и мне тоже).
/////////////// smokok ///////////////
//19. Добавил Авто-опорное 5.0,1.1,0.2
//20. Добавил Меню экрана (регулировка контрастности и включение подсвеки экрана).
//21. Добавил температуру. Пин термистора (10к) в А0 и +5, доп резистор (10к) в А0 и -5
//22. Разогнал PULTOSCOPE благодаря progrik
//23. Пока только вырезал UART приемник
// В планах внедрить Коэффициент заполнения
Уже наверное надо схему рисовать ,ведь видоизменилась..
ну да, остальные кроме всех работают)) ОК жмакается сам, пункты в меню тоже. а какие тогда кнопки ведут себя "правильно"?)) RESET?)))
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
//Страница проэкта <a href="http://srukami.inf.ua/pultoscop_v25110.html" title="http://srukami.inf.ua/pultoscop_v25110.html" rel="nofollow">http://srukami.inf.ua/pultoscop_v25110.html</a>
// === От меня [Electronik83] === mailTo: <a href="mailto:gsmkillersevsk@mail.ru">gsmkillersevsk@mail.ru</a>
// 1. Оптимизировал, причесал код
// 2. Сделал красивей главное меню, добавил новый пункт
// 3. Отображение частатоы и напряжения в осцилле при 1Кгц и 2,5в (был баг автора)
// 4. Новый режим - медленный осцилл - доделал...
// 5. Оптимизация.....
// 6. Убрал програмную растяжку сигнала из осцилла (развертка 7 и 8)
// 7. Изменил отрисовку сигнала в осцилле (больше нету этих раздвоений сигнала)
// 8. Убрал нахрен кнопку питания, и все что с ней сязано - проще тумблер (переключатель) поставить...
// 9. Анимировал главное меню. Пофиксил мерцание.
//10. Вставил свое меню генератора, DDS-генератора, терминала.
//11. Добавил немного новой анимации.
//12. Провел эксперимент с DDS-генератором и регулировкой частоты - не сделать.
// === ver19 ==
//13. В осциле - Сделал автосинхронизацию по серединке амплитуды сигнала <= подумать над внешней синхрой !!!
//14. В осциле - показываем масимальное и минимальное значение амплитуды сигнала справа
//15. Оптимизация некоторых участков кода
//16. Атмега теперь сама меряет напряжение своего питания, не надо ничего мультиметром мерять
//17. В осцилле - сделал более удобный вывод верхней строки в осцилле, "устатичил" вывод частоты.
// - теперь нет этого дерганья из Гц в кГц (и обратно) - просто выводим в Мгц.
//18. Добавил цифровой анализатор (входы A1, A2, A3, A4, A5) - что то мне он не понравился (и мне тоже).
/////////////// smokok ///////////////
//19. Добавил Авто-опорное 5.0,1.1,0.2
//20. Добавил Меню экрана (регулировка контрастности и включение подсвеки экрана).
//21. Добавил температуру. Пин термистора (10к) в А0 и +5, доп резистор (10к) в А0 и -5
//22. Разогнал PULTOSCOPE благодаря progrik
//23. Пока только вырезал UART приемник
// В планах внедрить Коэффициент заполнения
Уже наверное надо схему рисовать ,ведь видоизменилась..
По просьбе progrik снова мне помог добавить в пультоскоп очередную фишку!!! Теперь при длительном нажатии "ОК" отключается АВТОРАЗВЁРТКА и переходит на ручной режим кнопок "лево - право". Включается так же удержанием. Присутствуют индикаторы состояния "а" и "р". При коротком нажатии режим "Пауза". Спасибо большое progrik за помощь! Скетчи залил с кодом #define KEY_PRESSED 0 //progrik: логическое состояние нажатой кнопки 0 или 1
В первую очередь, хотелось бы сказать большое спасибо автору этого проекта! И всем кто позднее присоединился к его развитию отдельное спасибо!!
Прочитал всю тему)) Читал как какой-то детектив)) было интересно чем же это всё закончится. Ну или может не закончится, а во что это всё выльется. Сам я совсем только начинающий "ардуинщик/электронщик" и поэтому многое было на "птичьем языке", но решимости заказать дисплей и собрать приборчик это не убавило. Дисплей правда пока всё не доедет... но всё остальное для сборки имеется. Сейчас ковыряюсь в коде, пытаюсь разобраться что к чему и подкорректировать под свои хотелки.
Хочется конечно персонально отметить людей, но боюсь кого-то перечислять, дабы никого не пропустить, потому что людей приложивших свою руку (скорее конечно голову) было много! Ещё раз, спасибо всем участникам!! Подобные простые проекты не отпугивают начинающего радиолюбителя обилием незнакомых понятий, а дают возможность приобщиться к этому замечательному делу и заглянуть немного глубже.
smokok можно к скетчу(п.4416 - 5110) пояснения к меню осцилографа: как перейти к ручной развертке, к ручному изменению ОН,
при длительном нажатии ОК перехода к ручной установке развертки (от progrik )я не увидел. (может не туда смотрел).
У меня есть дисплей от Нокии 3510(монохром) 96х65 как 1230, только там контроллер PCF8814 и он размером побольше, помогите, пожалуйста адаптировать скетч (п.4416 - 1230) под этот дисплей, на него есть библиотека от Адафруит.
В последствии хочу оставить осцилограф, терминал и ТТ тестер из (п.3853 от diksen) и энкодер, - не знаю влезет ли..., но это потом, - сначала нужно дисплей "прикрутить"...
Очередное обновление от progrik! Теперь кнопки работают на должном уровне!!! При одном нажатии переключение, чуть передержал - нет перескоков. Убран delay в меню пультоскопа который я добавил.
Ребята, Я не спец, мне также помогают как вам по мере возможности опытные люди, за что им огромное СПАСИБО!!! progrik реально ускорил наш диафильм на экране до хорошего кино при спящей теме пультоскопа. Эти обновления как свет в тёмном небе!
Хотел подключить дисплей Нокии3510(контроллер PCD8544, как в нокии1100 96х65), но "не заводится", - экранчик молчит, хотя с теми же библиотеками циферки - буковки в демо выводятся...
Есть одна просьба: "прикрутите", пожалуйста, энкодер, - с ним намного удобнее...
Раз пошла такая пьянка (по поводу ускорения отображения на дисплее), то вот ещё подсказки.
Насчёт аппаратного SPI, надеюсь, знают все. Никакой другой вариант быстрей не будет. Но есть одно интересное исключение. Это USART в режиме SPI. На картинке ниже привожу 6 скринов с анализатора, все сняты в разных режимах (внимание, масштаб везде разный, поэтому смотрите на временные параметры).
Плюсы USART в режиме SPI:
1. Скорость выше, чем у аппаратного SPI, процентов на 30, с учётом пауз между передачей байтов. Возможность передавать по 2 байта подряд совсем без паузы (то есть 16 подряд тактирующих импульсов).
2.Заняты, в отличие от аппаратного SPI, только 2 ноги контроллера (1-data, 4-clk). У аппаратного SPI всегда заняты ноги 11, 12, 13, даже если 12 ни к чему не подключена. Здесь же ногу №0 можно использовать в любых своих целях. Само собой, для общения с дисплеем нужны ещё как минимум 2 или 3 ноги (то есть всего 4 или 5 сигнальных плюс 2 питание).
Минусы USART в режиме SPI:
1. Не поддерживает 9-битную передачу, необходимую некоторым дисплеям, хотя USART в обычном режиме умеет. (Это не точно, может кто подскажет как.)
2. Привязка к конкретным ногам контроллера (1 и 4).
3. Выплывает из пункта 2 - невозможность использовать USART для общения (не переживайте, скетчи при этом заливаются нормально).
Обратите внимание, на четвёртой и шестой картинках видна передача 2 байт подряд- расчёска с 16 зубцами.
Вот фрагмент кода, должен подойти для 5110, хотя я проверял на совсем другом дисплее. Ещё раз напоминаю: нога 0 - data(SDA,DI и т.п.), нога 4 - clk(SCK и др.), остальные ножки к дисплею тоже прописываются в скетче...
void Update() { //=======================Обновить дисплей
for (byte p = 0; p < 8; p++) {
transfer(0xb0 + p, 0);
transfer(0x10, 0xe0);
bitWrite(PORTD, 0, 1);// высокий уровень на DC (Data/Comand), можно любую ногу контроллера, кроме 0 и 4
for (byte col = 0; col < LCD_X ; col = col + 2) {
//SendByte(LCD_D, LCD_RAM[(LCD_X * p) + col]); //===========так было
transfer((LCD_RAM[(LCD_X * p) + col]), (LCD_RAM[(LCD_X * p) + col + 1]));//=========так стало, отправляем по 2 байта подряд, чтоб быстрее
}
bitWrite(PORTD, 0, 0);// низкий уровень на DC (Data/Comand)
}
}
void transfer(byte sp) { //=====================подпрограмма отправки байта
UCSR0A = _BV (TXC0); // Сбросить флаг завершения передачи, все остальные биты должны быть записаны в 0.
UDR0 = sp; // Начать передачу первого байта.
while (! (UCSR0A & _BV (TXC0))); // Проверьте, что мы закончили, ожидая флага завершения передачи.
}
void transfer(byte sp1, byte sp2) { //=================подпрограмма отправки двух байт
UCSR0A = _BV (TXC0); // Сбросить флаг завершения передачи, все остальные биты должны быть записаны в 0.
UDR0 = sp1; // Начать передачу первого байта.
UDR0 = sp2; // Начать передачу второго байта.
while (! (UCSR0A & _BV (TXC0))); // Проверьте, что мы закончили, ожидая флага завершения передачи.
}
И напоследок: кто поможет мне это переписать под Atmega64 ? Зачем? А затем, что мне нужны одновременно SPI, UART для терминала, и SPI к дисплею. Да и цена меньше, чем Atmega328. Пока что эксперименты не увенчались успехом.
Всем здравствуйте. Я так понимаю что у меня, у одного в этом девайсе с кнопками проблемы. Или с контроллерами, сразу с двумя. Чего у меня кнопочки сами нажимаются? progrik меня научил что делать. Но всё таки интересно почему у всех работает, а у меня нет.
раз пошла такая пьянка.... я человек - проверка. у меня SPI работает на 4МГц, и это проверенно опытом. можно быстрее, проводочки плохие... заливанием дисплея.... точки на фпс.... ВСЁ. он работает ровно на своей скорости. это аппаратная фигня, оно работает такт в такт... и только две ноги, я не понимаю, зачем тебе 3-я....
год не пил.... протрезвею - гляну твой код. и выскажу благодарность, за новые знания. если получу их)) но что-то надо думать... не сейчас....
есть 2 способа подключать кнопки. прижимаешь через резистор к земле(минус, 0), или подтягиваешь к плюсу(+, 1) в коде поменяй 0 на 1 или наоборот. как-то так...
...у меня SPI работает на 4МГц, и это проверенно опытом...это аппаратная фигня, оно работает такт в такт...
USART в режиме SPI работает на 8МГц, и это проверенно опытом. SPI может работать на 8МГц, но у меня пока не получилось. Кстати, есть нюанс- не все дисплеи поддерживают такую скорость передачи данных.
progrik пишет:
... и только две ноги, я не понимаю, зачем тебе 3-я....
Мне третья не нужна, это дисплею нужны кроме CLK и DATA ещё D/C, SCE, RESET (последний не обязательно). Вопрос в другом: можешь ли ты использовать ногу 12 для каких-либо целей при подключении дисплея через аппаратный SPI?
Всеь привет!!! Ребята помогите уточнить, Пультоскоп какие значение показываеть на вольта,т. е . Пик-Пик(Vpp) или Пик(Vp) или среднеквадратичное(Vrms) напряжение? Нужно измерить ВЧ сигнал через диодный детектор.
Пока тут идет "баловство", некоторые уже продают это чудо :)
Уж больно картинка на экране похожа на ту, что у Electronik83.
Тихо сп***дил и ушёл, называется нашёл!!! Пускай покупают те кто паять не могают ))). за 15$ можно два на коленке собрать с удовольствием или дсо138 взять, один фиг там корпуса нет. Ну молодец что платы себе нарисовал.
Так если бы хоть за 15$. У меня показывает $43.95 (3 039,84 ₽ RUB)
Даже нет ссылки на первоисточник... "Мой проект..."
Сразу мысль мелькнула, что если бы кто-то, типа AlexGyver, сделал разводку подобной платы (там ведь просто Ардуинка перенесена на свою плату с прорезью под SSD1306) и подарил китайцам, то можно было бы его уже купить за 2-3... ну пусть 5$. У него там связи есть. Лампы его очень даже продаются. Думаю, покупали были бы...
Кто может ответить,помогите!!!!
Пультоскоп какие значение показываеть на вольта,т. е . Пик-Пик(Vpp) или Пик(Vp) или среднеквадратичное(Vrms) напряжение?
Нужно измерить ВЧ сигнал через диодный детектор.
Andry Smart, если собираетесь "плагиатить" у плагиатора, то вот ещё "его" программатор к "его" осциллоскопу, за 13$...
Покупаете на Али готовый мини переходник и припаиваете к нему, от туда же (с Али), пружинные контакты. Сэкономите около 10$, как минимум.
Можно, но я там кажысь void OscilSlow сломал))). Меню отличается от автора. Вот вам под 5110.
Спасибо, буду пробовать! :)
smokok, можно скетч под 1203 сюда, без Яндексдиска?
seri0shka, Да конечно! Пожалуйста, сюда КЛАЦ
День добрый. Чего-то у меня кнопка ОК буд-то сама нажимается. Схему проверил. А когда на неё нажмёшь и держишь, то всё нормально. Наоборот работает. Это происходит во всех режимах.
volodya198024, вы хоть бы намекнули о чём речь. Не все фломастеры одинаково сладкие...
Например, в PULTOSCOPE_SSD1306_final2_DDS_Z_EL83_EDITION.ino, есть строка 80:
Может, это вариант вашей проблемы?
Прошу прощения за мою не компетентность. Да действительно. Попробуй угадай. В последней версии для 5110 в сообщение #4401 при подачи питания сразу включается осциллограф. Если зажать кнопку ОК и включить, то включится меню которое можно листать (при зажатой кнопке ОК). Включение выбранного режима при кратковременном отпускание кнопки. Например при включенном PWM-генераторе постоянное перемещение курсора. Я понимаю что произошла инверсия состояния кнопки или входа. Но где? Я без помощи не разберусь.
Остальные кнопки ведут себя правильно.
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
но попробовать стоит))
Ура! Заработала. Все кнопки фунциклируют правильно. Я в восторге от вас.
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
Уже наверное надо схему рисовать ,ведь видоизменилась..
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
Уже наверное надо схему рисовать ,ведь видоизменилась..
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
Уже наверное надо схему рисовать ,ведь видоизменилась..
приклеил состояние нажатой кнопки, в коде #define KEY_PRESSED 1 //progrik: логическое состояние нажатой кнопки 0 или 1
..ну и в коде не if (!digitalRead(KEY_OK)) а if(digitalRead(KEY_OK) == KEY_PRESSED) везде везде где кнопки....
короче, инвертировал все кнопки. проверить не на чем, так что извольте сами) если я чего напутал - жаль))
Уже наверное надо схему рисовать ,ведь видоизменилась..
Виноват,сглючил инет,можно лишнее убрать
По просьбе progrik снова мне помог добавить в пультоскоп очередную фишку!!! Теперь при длительном нажатии "ОК" отключается АВТОРАЗВЁРТКА и переходит на ручной режим кнопок "лево - право". Включается так же удержанием. Присутствуют индикаторы состояния "а" и "р". При коротком нажатии режим "Пауза". Спасибо большое progrik за помощь! Скетчи залил с кодом #define KEY_PRESSED 0 //progrik: логическое состояние нажатой кнопки 0 или 1
ВИДЕО
Скетч 1230
#define BUFSIZE_SHORT 256 //progrik: буфер для рабочего режима, чем короче - тем быстрее отображение. чем длиннее - тем медленнее, но синхра сможет ловить более "растянутый" сигнал #define BUFSIZE_LONG 512 //progrik: буфер для паузы. старый буфер был 800 #define PAUSE_OFFSET 1 //progrik: смещение графика за один кадр в режиме паузы. если для паузы указан достаточно длинный буфер, то можно увеличить до 2-3-4.., чтоб быстрее мотало #define APP 2.7 // 2.7) это переход на аппаратный замер #define NAPR 255 // это напряжение сигнала // Пины экранчика #define RES 3 #define CS 4 #define Data 6 #define Clock 7 #define swap(a, b) { byte t = a; a = b; b = t; } //progrik: определяем макросы для действий с управляющими пинами #define CLOCK_HIGH bitWrite(PORTD,7,1) // pin7=PORTD,7 pin8=PORTB,0 pin9=PORTB,1 и так далее #define CLOCK_LOW bitWrite(PORTD,7,0) #define DATA_HIGH bitWrite(PORTD,6,1) // pin6=PORTD,6 #define DATA_LOW bitWrite(PORTD,6,0) #define RESET_HIGH bitWrite(PORTD,3,1) // pin3 #define RESET_LOW bitWrite(PORTD,3,0) #define CS_HIGH bitWrite(PORTD,4,1) // pin4 #define CS_LOW bitWrite(PORTD,4,0) #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 KEY_PRESSED 0 //progrik: логическое состояние нажатой кнопки 0 или 1 #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_LONG]; 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 osc=15; // авто вкл. режима осциллографа (секунды) int grOffset = 0; // смещение графика в рабочем режиме byte vMax, vMin; // максимальное и минимальное напряжение сигнала int temp = 0; // временная переменная*** bool flag = 0; unsigned long ok_last_time; //была ok_press_time unsigned long ok_start_time; bool ok_short_press = false; unsigned long count = 0; 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кОм Для подстройки правим. 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(); Initialize(); //Инициализация дисплея 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) != KEY_PRESSED) { // цикл, пока не нажали кнопку ОК Update(); // Если не нажата 10 сек кнопка ок вход в режим осцилоографа автоматом osc--; if (osc==0) break; ////////// Выводим показание ///////// 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( 300 ); } // цикл нажатия ОК // нажали кнопку ОК из меню, инициализируем и выходим из меню count = 0; //countX = 0; // восстанавливаем на всякий случай переменные if (mode == 0) FreqCount.begin(1000); if (mode == 1) { InitTimersSafe(); } // if (mode == 2) { // InitTimersSafe(); // } if (mode == 3 || mode == 4) DDRC = 0x00; PORTC = 0x00;// Serial.begin(115200); // razv = 0;// весь порт С (это A0...A5) на вход и без подтяжки for (char a=37; a>0; a-=2); ok_last_time = millis(); //progrik: запоминаем время последнего нажатия } // беcконечный цикл - по сути прыгаем в подпрограммы void loop() { switch (mode) { // Прыгаем в выбранный режим из главного меню case 0 : Oscil(); break; // "выпадаем" в осцилл } } // === Читаем с АЦП данные и помещаем их в буфер === // void ReadAdc() { uint16_t len; len = (pause) ? BUFSIZE_LONG : BUFSIZE_SHORT; if (razv % 10) { // (razv>0) // если развертка без задержек всяких (с 1 по 7) ADCSRA = 0b11100000 | (8 - (razv % 10)); // установили делитель (/2 - не работает, так что начинаем с /4) for (uint16_t i = 0; i < len; i++) { // цикл для чтения while (!(ADCSRA & 0x10)); // ждем готовность АЦП ADCSRA |= 0x10; // запускаем следующее преобразование adcBuf[i] = ADCH; // записываем данные в массив } // delay(0.3 * BUFSIZE_LONG); //progrik: не нужно тормозить то, что и так еле работает)) // компенсация задержки по сравнению с разверткой 0... } else { // развертка с задержками (delay) ADCSRA = 0b11100111; // делитель на /128 for (uint16_t i = 0; i < len; i++) { // цикл для чтения while (!(ADCSRA & 0x10)); // ждем готовность АЦП ADCSRA |= 0x10; // запускаем следующее преобразование delayMicroseconds(500); // делаем задержку adcBuf[i] = ADCH; // записываем данные в массив } } } // ==== функция вывода 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="<a href="<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>" rel="nofollow"><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></a>" rel="nofollow"><a href="<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>" rel="nofollow"><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></a></a>" rel="nofollow"><a href="<a href="<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>" rel="nofollow"><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></a>" rel="nofollow"><a href="<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>" rel="nofollow"><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></a></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="<a href="<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>" rel="nofollow"><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></a>" rel="nofollow"><a href="<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>" rel="nofollow"><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></a></a>" rel="nofollow"><a href="<a href="<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>" rel="nofollow"><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></a>" rel="nofollow"><a href="<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>" rel="nofollow"><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></a></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 Initialize() { pinMode(RES, OUTPUT); pinMode(CS, OUTPUT); pinMode(Data, OUTPUT); pinMode(Clock, OUTPUT); // Инициализация дисплея // dWrite(RES, 1); RESET_HIGH; // dWrite(Clock, 0); CLOCK_LOW; // dWrite(Data, 0); DATA_LOW; // dWrite(CS, 0); // CS_LOW; delay(20); // dWrite(CS, 1); CS_HIGH; SendByte(0, 0x2F); // Power control set(charge pump on/off) SendByte(0, 0xA4); SendByte(0, 0xAF); // экран вкл/выкл //Clear_LCD(); //Update(); // delay(500); //progrik: задержка после включения // CS_LOW; //progrik: вернул для тестов // delay(500); //progrik: задержка после включения } //=======================================================Управление пинами void dWrite(byte pin, byte val) { byte bit = digitalPinToBitMask(pin); volatile byte *out; out = portOutputRegister(digitalPinToPort(pin)); (val) ? *out |= bit : *out &= ~bit; } //=========================================================Отправка 9 байт //progrik: добалено определение inline. функция встраивается в код и не расходуется время на ее вызов. //progrik: вместо многократных вызовов функций дергаем ногами при помощи написанных вверху кода макросов inline __attribute__((always_inline)) void SendByte(byte mode, byte c) { //dWrite(CS, 0); //progrik: чип селект нужно включить один раз в конце инициализации дисплея, и больше не трогать. перенес в инициализацию CS_LOW; //progrik: вернул для тестов //(mode) ? dWrite(Data, 1) : dWrite(Data, 0); (mode) ? DATA_HIGH : DATA_LOW; //dWrite(Clock, 1); CLOCK_HIGH; for (byte i = 0; i < 8; i++) { //dWrite(Clock, 0); CLOCK_LOW; //(c & 0x80) ? dWrite(Data, 1) : dWrite(Data, 0); (c & 0x80) ? DATA_HIGH : DATA_LOW; //dWrite(Clock, 1); CLOCK_HIGH; c <<= 1; } //dWrite(Clock, 0); CLOCK_LOW; } //======================================================Очистка дисплея 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]); } } } //===================================================Нарисовать пиксель inline __attribute__((always_inline)) void drawPixel (byte x, byte y, boolean color) { // if ((x < 0) || (x >= 96) || (y < 0) || (y >= 68)) return; // NAN херня 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); if(line & 0x1) { drawPixel(x + i, y + j, color); } else { 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++) { if(steep) { drawPixel(y0, x0, color); } else { drawPixel(x0, y0, color); } err -= dy; if (err < 0) { y0 += ystep; err += dx; } } } /////////////////добавь где-то, например, под функцией DrawLine такую функцию://////////////////////////// void drawVLineUltraFast(byte x, byte y0, byte y1, boolean color) { if(y0 > y1) { swap(y0, y1); } do { drawPixel(x, y0, color); } while(++y0 <= y1); } //========================================Рисование вертикальной линии void drawFastVLine(byte x, byte y, byte h, boolean color) { //drawLine(x, y, x, y + h - 1, color); byte y1 = y + h - 1; do { drawPixel(x, y, color); } while(++y <= y1); } //======================================Рисование горизонтальной линии void drawFastHLine(byte x, byte y, byte w, boolean color) { //drawLine(x, y, x + w - 1, y, color); byte x1 = x + w - 1; do { drawPixel(x, y, color); } while(++x <= x1); } //=====================================Рисование залитый прямоугольник 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); } //progrik: для расчета напряжений --------------- void calc_val() { vMax = 0; vMin = 0xFF; uint16_t l = (pause) ? BUFSIZE_LONG : BUFSIZE_SHORT; for (uint16_t x = 0; x < l; x++) { if (vMax < adcBuf[x]) vMax = adcBuf[x]; // пока 255, но надо экспериментировать if (vMin > adcBuf[x]) vMin = adcBuf[x]; } } // === Осциллоскоп === // void Oscil() { // установка опорного напряжения АЦП и настройка входа АЦП ADMUX = vRef ? 0b01100011 : 0b11100011; label_ReadAdc: // === Обработка кнопок === // if (digitalRead(KEY_L) == KEY_PRESSED) switch (menu) { // кнопка лево:) case 0 : razv--; if (razv == NAPR) razv = 6; delay(200); break; // меняем развертку case 1 : grOffset -= PAUSE_OFFSET; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе } if (digitalRead(KEY_R) == KEY_PRESSED) switch (menu) { // кнопка право:) case 0 : razv++; if (razv == 7) razv = 0; delay(200); break; // меняем развертку case 1 : grOffset += PAUSE_OFFSET; if (grOffset > BUFSIZE_LONG - LCDX) grOffset = BUFSIZE_LONG - LCDX; break; // листаем график в паузе } if (digitalRead(KEY_OK) == KEY_PRESSED) { if(ok_short_press && (millis() - ok_start_time) > 600) //progrik: задержка для длинного нажатия { avtorazv = !avtorazv; //progrik: переключит авторазвертку после длительного нажатия ^^^ 600ms ok_short_press = false; } if((millis() - ok_last_time) > 200) //progrik: подавление дребезга - ждем 200 мс со времени последнего нажатия { ok_start_time = millis(); //progrik: запоминаем время первого нажатия кнопки OK ok_short_press = true; //progrik: отмечаем флаг короткого нажатия } ok_last_time = millis(); //progrik: запоминаем время последнего нажатия кнопки OK } else { if(ok_short_press) //progrik: если нужно отработать короткое нажатие (флаг установлен) { ok_short_press = false; //progrik: снимаем флаг короткого нажатия switch (++menu) { case 1: grOffset = 0; pause = 1; ReadAdc(); calc_val(); break; // вход в паузу - антидребезг типа case 2: menu = 0; pause = 0; break; // перебор меню } } } // === Ведём рассчеты === // if (!pause) { // если нет паузы ReadAdc(); // то снимаем осциллограмму calc_val(); // == Вычисляем максимальное и минимальное значение сигнала == // vSync = (vMax - vMin) / 2 + vMin; // уровень синхронизации по середине уровня сигнала // == Определение точки синхронизации == // bool flagZero=0; grOffset = 0; // сброс флага и точки синхронизации // Ищем перепад от меньшего уровня к большему for (uint8_t x=1; x < BUFSIZE_SHORT - LCDX; x++) { // смотрим весь массив данных АЦП if (adcBuf[x]<vSync) flagZero=1; // нашли меньше, чем синхра (перепад сигнала в минус) - ставим флаг if (flagZero && adcBuf[x]>vSync) { grOffset=x; break; } // нашли больше, чем синхра (перепад сигнала в плюс) - запомнили и выходим из цикла } // === Считаем частоту сигнала === // if (vRef && vMax * VCC / NAPR > APP) { // если можем замерить аппаратно - меряем. > 2.7) это переход на аппаратный замер if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала } else { // === Меряем частоту сигнала программно === // flagZero = 0; count = 0; // сброс флага и счетчика for(uint8_t x=grOffset; x < BUFSIZE_SHORT - LCDX; x++) { // смотрим массив от точки синхронизации до конца if (adcBuf[x] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг if (flagZero && adcBuf[x] > vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период switch (razv) { // считем частоту периода case 6: count = 1000000 / ((x - grOffset - 1) * 3.25); break; // делитель 4 case 5: count = 1000000 / ((x - grOffset) * 3.25) / 2; break; // делитель 8 case 4: count = 1000000 / ((x - grOffset) * 3.25) / 4; break; // делитель 16 case 3: count = 1000000 / ((x - grOffset) * 3.25) / 8; break; // делитель 32 case 2: count = 1000000 / ((x - grOffset) * 3.25) / 16; break; // делитель 64 case 1: count = 1000000 / ((x - grOffset) * 3.25) / 32; break; // делитель 128 case 0: count = 1000000 / ((x - grOffset) * 510); break; // делитель 128 тоже } break; } } } count = count * OVERCLOCK / 16.0; // пересчет частоты на разные кварцы } // закончили вести рассчеты Clear_LCD(); // чистим экран... // === Отрисовка меню осцилла === if (vRef) float_print(0, 0, 1, VCC, 1); else { if(kdel==5)print(0, 0, 1, "1.1"); else print(0, 0, 1, "*22"); // отображение опорного } if (menu == 0) TextColor = 0; else TextColor = 1; print(27, 0, 1, razv); // отображение развёртки if (vRef && vMax * VCC / NAPR > APP) drawChar(19, 0, 1, 'а'); // если замер - "А"ппаратный else drawChar(19, 0, 1, 'п'); // иначе "П"рограмный if (menu == 1) { // тут всё для паузы // delay(20); } else TextColor = 1; if (!pause) TextColor = 0; else { // рисуем прокрутку в режиме паузы strcpy_P(buffer, (char*)pgm_read_word(&(string_table[4]))); print(6, 12, 1, (buffer)); temp = grOffset / 4.7; // место остоновки чёрточки при прокрутке в паузе в конце экрана drawFastHLine(temp, 10, 7, 1); drawFastHLine(temp, 9, 7, 1); //чёрточка прокрутки в паузе } // шкала прокрутки закончилась (pause) ? float_print (48, 0, 0, count / 1000000.0, 6) : float_print (48, 0, 1, count / 1000000.0, 6); // вывод частоты float_print(73, 12, 1, vMax * (vRef ? VCC : 1.1) / NAPR, 2); // рисуем максимальное напряжение сигнала float_print(78, 58, 1, vMin * (vRef ? VCC : 1.1) / NAPR, 1); // рисуем минимальное напряжение сигнала if (vMax==0xFF) for(uint8_t x=10; x<68; x++) drawFastHLine( 0, x, 5, 5); // превышение максимума АЦП if (avtorazv) drawChar(34, 0, 1, 'а'); // указатель состояния авторазвёртки else drawChar(34, 0, 1, 'p'); // == Отрисовка сетки == // 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, 19, 1); // это сеточка # горизонтальные линии drawPixel(i, 39, 1); drawPixel(i, 59, 1); } ///////////////авто razv////////////// if (avtorazv) #define PER 1.3 if (count > 4323.3 * PER) razv = 6; else if (count > 2434.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==NAPR){ 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 (uint8_t x = 0; x < 92; x++) drawVLineUltraFast(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1); //progrik: drawVLineUltraFast вместо медленной drawLine Update(); }Скетч 5110
В первую очередь, хотелось бы сказать большое спасибо автору этого проекта! И всем кто позднее присоединился к его развитию отдельное спасибо!!
Прочитал всю тему)) Читал как какой-то детектив)) было интересно чем же это всё закончится. Ну или может не закончится, а во что это всё выльется. Сам я совсем только начинающий "ардуинщик/электронщик" и поэтому многое было на "птичьем языке", но решимости заказать дисплей и собрать приборчик это не убавило. Дисплей правда пока всё не доедет... но всё остальное для сборки имеется. Сейчас ковыряюсь в коде, пытаюсь разобраться что к чему и подкорректировать под свои хотелки.
Хочется конечно персонально отметить людей, но боюсь кого-то перечислять, дабы никого не пропустить, потому что людей приложивших свою руку (скорее конечно голову) было много! Ещё раз, спасибо всем участникам!! Подобные простые проекты не отпугивают начинающего радиолюбителя обилием незнакомых понятий, а дают возможность приобщиться к этому замечательному делу и заглянуть немного глубже.
smokok можно к скетчу(п.4416 - 5110) пояснения к меню осцилографа: как перейти к ручной развертке, к ручному изменению ОН,
при длительном нажатии ОК перехода к ручной установке развертки (от progrik )я не увидел. (может не туда смотрел).
У меня есть дисплей от Нокии 3510(монохром) 96х65 как 1230, только там контроллер PCF8814 и он размером побольше, помогите, пожалуйста адаптировать скетч (п.4416 - 1230) под этот дисплей, на него есть библиотека от Адафруит.
В последствии хочу оставить осцилограф, терминал и ТТ тестер из (п.3853 от diksen) и энкодер, - не знаю влезет ли..., но это потом, - сначала нужно дисплей "прикрутить"...
откомпилировал без ошибок "Скетч 5110", где бы ещё схемку найти)
void OscilSlow вылечили?
void OscilSlow вылечили?
Очередное обновление от progrik! Теперь кнопки работают на должном уровне!!! При одном нажатии переключение, чуть передержал - нет перескоков. Убран delay в меню пультоскопа который я добавил.
Ребята, Я не спец, мне также помогают как вам по мере возможности опытные люди, за что им огромное СПАСИБО!!! progrik реально ускорил наш диафильм на экране до хорошего кино при спящей теме пультоскопа. Эти обновления как свет в тёмном небе!
Схемка 5110 кто просил, ССЫЛКА
Под другой дисплей лично я, вам не адаптирую. При длительном нажатии ОК переход к ручной установке развертки отлично работает, это подтверждает видео.
void OscilSlow пока не вылечил. Может поможет Electronik83 или сам по мере возможности, если не выйдет, то надежда умирает последней))).
1230
#define BUFSIZE_SHORT 256 //progrik: буфер для рабочего режима, чем короче - тем быстрее отображение. чем длиннее - тем медленнее, но синхра сможет ловить более "растянутый" сигнал #define BUFSIZE_LONG 512 //progrik: буфер для паузы. старый буфер был 800 #define PAUSE_OFFSET 1 //progrik: смещение графика за один кадр в режиме паузы. если для паузы указан достаточно длинный буфер, то можно увеличить до 2-3-4.., чтоб быстрее мотало #define APP 2.7 // 2.7) это переход на аппаратный замер #define NAPR 255 // это напряжение сигнала // Пины экранчика #define RES 3 #define CS 4 #define Data 6 #define Clock 7 #define swap(a, b) { byte t = a; a = b; b = t; } //progrik: определяем макросы для действий с управляющими пинами #define CLOCK_HIGH bitWrite(PORTD,7,1) // pin7=PORTD,7 pin8=PORTB,0 pin9=PORTB,1 и так далее #define CLOCK_LOW bitWrite(PORTD,7,0) #define DATA_HIGH bitWrite(PORTD,6,1) // pin6=PORTD,6 #define DATA_LOW bitWrite(PORTD,6,0) #define RESET_HIGH bitWrite(PORTD,3,1) // pin3 #define RESET_LOW bitWrite(PORTD,3,0) #define CS_HIGH bitWrite(PORTD,4,1) // pin4 #define CS_LOW bitWrite(PORTD,4,0) #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 KEY_PRESSED 0 //progrik: логическое состояние нажатой кнопки 0 или 1 #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_LONG]; 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 osc=15; // авто вкл. режима осциллографа (секунды) int grOffset = 0; // смещение графика в рабочем режиме byte vMax, vMin; // максимальное и минимальное напряжение сигнала int temp = 0; // временная переменная*** bool flag = 0; unsigned long ok_last_time; //была ok_press_time unsigned long ok_start_time; bool ok_short_press = false; unsigned long count = 0; 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кОм Для подстройки правим. 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(); Initialize(); //Инициализация дисплея 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) != KEY_PRESSED) { // цикл, пока не нажали кнопку ОК Update(); // Если не нажата 10 сек кнопка ок вход в режим осцилоографа автоматом osc--; if (osc==0) break; ////////// Выводим показание ///////// 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( 300 ); } // цикл нажатия ОК // нажали кнопку ОК из меню, инициализируем и выходим из меню count = 0; //countX = 0; // восстанавливаем на всякий случай переменные if (mode == 0) FreqCount.begin(1000); if (mode == 1) { InitTimersSafe(); } // if (mode == 2) { // InitTimersSafe(); // } if (mode == 3 || mode == 4) DDRC = 0x00; PORTC = 0x00;// Serial.begin(115200); // razv = 0;// весь порт С (это A0...A5) на вход и без подтяжки for (char a=37; a>0; a-=2); ok_last_time = millis(); //progrik: запоминаем время последнего нажатия } // беcконечный цикл - по сути прыгаем в подпрограммы void loop() { switch (mode) { // Прыгаем в выбранный режим из главного меню case 0 : Oscil(); break; // "выпадаем" в осцилл } } // === Читаем с АЦП данные и помещаем их в буфер === // void ReadAdc() { uint16_t len; len = (pause) ? BUFSIZE_LONG : BUFSIZE_SHORT; if (razv % 10) { // (razv>0) // если развертка без задержек всяких (с 1 по 7) ADCSRA = 0b11100000 | (8 - (razv % 10)); // установили делитель (/2 - не работает, так что начинаем с /4) for (uint16_t i = 0; i < len; i++) { // цикл для чтения while (!(ADCSRA & 0x10)); // ждем готовность АЦП ADCSRA |= 0x10; // запускаем следующее преобразование adcBuf[i] = ADCH; // записываем данные в массив } // delay(0.3 * BUFSIZE_LONG); //progrik: не нужно тормозить то, что и так еле работает)) // компенсация задержки по сравнению с разверткой 0... } else { // развертка с задержками (delay) ADCSRA = 0b11100111; // делитель на /128 for (uint16_t i = 0; i < len; i++) { // цикл для чтения while (!(ADCSRA & 0x10)); // ждем готовность АЦП ADCSRA |= 0x10; // запускаем следующее преобразование delayMicroseconds(500); // делаем задержку adcBuf[i] = ADCH; // записываем данные в массив } } } // ==== функция вывода 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="<a href="<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>" rel="nofollow"><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></a>" rel="nofollow"><a href="<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>" rel="nofollow"><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></a></a>" rel="nofollow"><a href="<a href="<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>" rel="nofollow"><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></a>" rel="nofollow"><a href="<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>" rel="nofollow"><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></a></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="<a href="<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>" rel="nofollow"><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></a>" rel="nofollow"><a href="<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>" rel="nofollow"><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></a></a>" rel="nofollow"><a href="<a href="<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>" rel="nofollow"><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></a>" rel="nofollow"><a href="<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>" rel="nofollow"><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></a></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 Initialize() { pinMode(RES, OUTPUT); pinMode(CS, OUTPUT); pinMode(Data, OUTPUT); pinMode(Clock, OUTPUT); // Инициализация дисплея // dWrite(RES, 1); RESET_HIGH; // dWrite(Clock, 0); CLOCK_LOW; // dWrite(Data, 0); DATA_LOW; // dWrite(CS, 0); // CS_LOW; delay(20); // dWrite(CS, 1); CS_HIGH; SendByte(0, 0x2F); // Power control set(charge pump on/off) SendByte(0, 0xA4); SendByte(0, 0xAF); // экран вкл/выкл //Clear_LCD(); //Update(); // delay(500); //progrik: задержка после включения // CS_LOW; //progrik: вернул для тестов // delay(500); //progrik: задержка после включения } //=======================================================Управление пинами void dWrite(byte pin, byte val) { byte bit = digitalPinToBitMask(pin); volatile byte *out; out = portOutputRegister(digitalPinToPort(pin)); (val) ? *out |= bit : *out &= ~bit; } //=========================================================Отправка 9 байт //progrik: добалено определение inline. функция встраивается в код и не расходуется время на ее вызов. //progrik: вместо многократных вызовов функций дергаем ногами при помощи написанных вверху кода макросов inline __attribute__((always_inline)) void SendByte(byte mode, byte c) { //dWrite(CS, 0); //progrik: чип селект нужно включить один раз в конце инициализации дисплея, и больше не трогать. перенес в инициализацию CS_LOW; //progrik: вернул для тестов //(mode) ? dWrite(Data, 1) : dWrite(Data, 0); (mode) ? DATA_HIGH : DATA_LOW; //dWrite(Clock, 1); CLOCK_HIGH; for (byte i = 0; i < 8; i++) { //dWrite(Clock, 0); CLOCK_LOW; //(c & 0x80) ? dWrite(Data, 1) : dWrite(Data, 0); (c & 0x80) ? DATA_HIGH : DATA_LOW; //dWrite(Clock, 1); CLOCK_HIGH; c <<= 1; } //dWrite(Clock, 0); CLOCK_LOW; } //======================================================Очистка дисплея 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]); } } } //===================================================Нарисовать пиксель inline __attribute__((always_inline)) void drawPixel (byte x, byte y, boolean color) { // if ((x < 0) || (x >= 96) || (y < 0) || (y >= 68)) return; // NAN херня 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); if(line & 0x1) { drawPixel(x + i, y + j, color); } else { 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++) { if(steep) { drawPixel(y0, x0, color); } else { drawPixel(x0, y0, color); } err -= dy; if (err < 0) { y0 += ystep; err += dx; } } } /////////////////добавь где-то, например, под функцией DrawLine такую функцию://////////////////////////// void drawVLineUltraFast(byte x, byte y0, byte y1, boolean color) { if(y0 > y1) { swap(y0, y1); } do { drawPixel(x, y0, color); } while(++y0 <= y1); } //========================================Рисование вертикальной линии void drawFastVLine(byte x, byte y, byte h, boolean color) { //drawLine(x, y, x, y + h - 1, color); byte y1 = y + h - 1; do { drawPixel(x, y, color); } while(++y <= y1); } //======================================Рисование горизонтальной линии void drawFastHLine(byte x, byte y, byte w, boolean color) { //drawLine(x, y, x + w - 1, y, color); byte x1 = x + w - 1; do { drawPixel(x, y, color); } while(++x <= x1); } //=====================================Рисование залитый прямоугольник 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); } //progrik: для расчета напряжений --------------- void calc_val() { vMax = 0; vMin = 0xFF; uint16_t l = (pause) ? BUFSIZE_LONG : BUFSIZE_SHORT; for (uint16_t x = 0; x < l; x++) { if (vMax < adcBuf[x]) vMax = adcBuf[x]; // пока 255, но надо экспериментировать if (vMin > adcBuf[x]) vMin = adcBuf[x]; } } // === Осциллоскоп === // void Oscil() { // установка опорного напряжения АЦП и настройка входа АЦП ADMUX = vRef ? 0b01100011 : 0b11100011; label_ReadAdc: // === Обработка кнопок === // if(digitalRead(KEY_L) == KEY_PRESSED) // кнопка лево { switch (menu) { //progrik: подавление дребезга и предотвращение постоянного циклического переключения case 0 : if((millis() - ok_last_time) > 100) { razv--; if(razv == NAPR) razv = 6; } break; // меняем развертку case 1 : grOffset -= PAUSE_OFFSET; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе } ok_last_time = millis(); //progrik: запоминаем время последнего нажатия кнопки } if(digitalRead(KEY_R) == KEY_PRESSED) // кнопка направо { switch (menu) { //progrik: подавление дребезга и предотвращение постоянного циклического переключения case 0 : if((millis() - ok_last_time) > 100) { razv++; if (razv == 7) razv = 0; } break; // меняем развертку case 1 : grOffset += PAUSE_OFFSET; if (grOffset > BUFSIZE_LONG - LCDX) grOffset = BUFSIZE_LONG - LCDX; break; // листаем график в паузе } ok_last_time = millis(); //progrik: запоминаем время последнего нажатия кнопки } if (digitalRead(KEY_OK) == KEY_PRESSED) { if(ok_short_press && (millis() - ok_start_time) > 600) //progrik: задержка для длинного нажатия { avtorazv = !avtorazv; //progrik: переключит авторазвертку после длительного нажатия ^^^ 600ms ok_short_press = false; } if((millis() - ok_last_time) > 200) //progrik: подавление дребезга - ждем 200 мс со времени последнего нажатия { ok_start_time = millis(); //progrik: запоминаем время первого нажатия кнопки OK ok_short_press = true; //progrik: отмечаем флаг короткого нажатия } ok_last_time = millis(); //progrik: запоминаем время последнего нажатия кнопки OK } else { if(ok_short_press) //progrik: если нужно отработать короткое нажатие (флаг установлен) { ok_short_press = false; //progrik: снимаем флаг короткого нажатия switch (++menu) { case 1: grOffset = 0; pause = 1; ReadAdc(); calc_val(); break; // вход в паузу - антидребезг типа case 2: menu = 0; pause = 0; break; // перебор меню } } } // === Ведём рассчеты === // if (!pause) { // если нет паузы ReadAdc(); // то снимаем осциллограмму calc_val(); // == Вычисляем максимальное и минимальное значение сигнала == // vSync = (vMax - vMin) / 2 + vMin; // уровень синхронизации по середине уровня сигнала // == Определение точки синхронизации == // bool flagZero=0; grOffset = 0; // сброс флага и точки синхронизации // Ищем перепад от меньшего уровня к большему for (uint8_t x=1; x < BUFSIZE_SHORT - LCDX; x++) { // смотрим весь массив данных АЦП if (adcBuf[x]<vSync) flagZero=1; // нашли меньше, чем синхра (перепад сигнала в минус) - ставим флаг if (flagZero && adcBuf[x]>vSync) { grOffset=x; break; } // нашли больше, чем синхра (перепад сигнала в плюс) - запомнили и выходим из цикла } // === Считаем частоту сигнала === // if (vRef && vMax * VCC / NAPR > APP) { // если можем замерить аппаратно - меряем. > 2.7) это переход на аппаратный замер if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала } else { // === Меряем частоту сигнала программно === // flagZero = 0; count = 0; // сброс флага и счетчика for(uint8_t x=grOffset; x < BUFSIZE_SHORT - LCDX; x++) { // смотрим массив от точки синхронизации до конца if (adcBuf[x] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг if (flagZero && adcBuf[x] > vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период switch (razv) { // считем частоту периода case 6: count = 1000000 / ((x - grOffset - 1) * 3.25); break; // делитель 4 case 5: count = 1000000 / ((x - grOffset) * 3.25) / 2; break; // делитель 8 case 4: count = 1000000 / ((x - grOffset) * 3.25) / 4; break; // делитель 16 case 3: count = 1000000 / ((x - grOffset) * 3.25) / 8; break; // делитель 32 case 2: count = 1000000 / ((x - grOffset) * 3.25) / 16; break; // делитель 64 case 1: count = 1000000 / ((x - grOffset) * 3.25) / 32; break; // делитель 128 case 0: count = 1000000 / ((x - grOffset) * 510); break; // делитель 128 тоже } break; } } } count = count * OVERCLOCK / 16.0; // пересчет частоты на разные кварцы } // закончили вести рассчеты Clear_LCD(); // чистим экран... // === Отрисовка меню осцилла === if (vRef) float_print(0, 0, 1, VCC, 1); else { if(kdel==5)print(0, 0, 1, "1.1"); else print(0, 0, 1, "*22"); // отображение опорного } if (menu == 0) TextColor = 0; else TextColor = 1; print(27, 0, 1, razv); // отображение развёртки if (vRef && vMax * VCC / NAPR > APP) drawChar(19, 0, 1, 'а'); // если замер - "А"ппаратный else drawChar(19, 0, 1, 'п'); // иначе "П"рограмный if (menu == 1) { // тут всё для паузы // delay(20); } else TextColor = 1; if (!pause) TextColor = 0; else { // рисуем прокрутку в режиме паузы strcpy_P(buffer, (char*)pgm_read_word(&(string_table[4]))); print(6, 12, 1, (buffer)); temp = grOffset / 4.7; // место остоновки чёрточки при прокрутке в паузе в конце экрана drawFastHLine(temp, 10, 7, 1); drawFastHLine(temp, 9, 7, 1); //чёрточка прокрутки в паузе } // шкала прокрутки закончилась (pause) ? float_print (48, 0, 0, count / 1000000.0, 6) : float_print (48, 0, 1, count / 1000000.0, 6); // вывод частоты float_print(73, 12, 1, vMax * (vRef ? VCC : 1.1) / NAPR, 2); // рисуем максимальное напряжение сигнала float_print(78, 58, 1, vMin * (vRef ? VCC : 1.1) / NAPR, 1); // рисуем минимальное напряжение сигнала if (vMax==0xFF) for(uint8_t x=10; x<68; x++) drawFastHLine( 0, x, 5, 5); // превышение максимума АЦП if (avtorazv) drawChar(34, 0, 1, 'а'); // указатель состояния авторазвёртки else drawChar(34, 0, 1, 'p'); // == Отрисовка сетки == // 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, 19, 1); // это сеточка # горизонтальные линии drawPixel(i, 39, 1); drawPixel(i, 59, 1); } ///////////////авто razv////////////// if (avtorazv) #define PER 1.3 if (count > 4323.3 * PER) razv = 6; else if (count > 2434.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==NAPR){ 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 (uint8_t x = 0; x < 92; x++) drawVLineUltraFast(x + 4, 67 - adcBuf[x + grOffset]/kdel / 0.9, 67 - adcBuf[x + grOffset + 1]/kdel / 0.9, 1); //progrik: drawVLineUltraFast вместо медленной drawLine Update(); }5110
Понял! Спасибо за схему!
...
progrik, smokok Спасибо за код! Залил п.4422 все чудесно работает!
Вернул на родину терминал, причесал немного отображение его меню, поставил по умолчанию 9600...
Есть один ньюанс: частоту при входном меньше Вольта показывает вместо 10000 - 10250... т.е. на пределах ОН 1,1В и 0,22В, а на 5,1В показыывает 10009
// UART приемник void Terminal() { const long speedUart[] = { 9600,19200,38400,57600,115200,1200,2400,4800, }; display.clearDisplay(); ShowModeInv(0); display.setCursor(25,15); display.println("Speed:"); display.setTextColor(WHITE, BLACK); display.setCursor(13, 27); display.print("-"); display.setTextColor(BLACK); display.print(" "); display.print(speedUart[menu]); display.setTextColor(WHITE, BLACK); display.setCursor(66, 27); display.println("+"); display.setTextColor(BLACK); ...Хотел подключить дисплей Нокии3510(контроллер PCD8544, как в нокии1100 96х65), но "не заводится", - экранчик молчит, хотя с теми же библиотеками циферки - буковки в демо выводятся...
Есть одна просьба: "прикрутите", пожалуйста, энкодер, - с ним намного удобнее...
Спасибо!
Раз пошла такая пьянка (по поводу ускорения отображения на дисплее), то вот ещё подсказки.
Насчёт аппаратного SPI, надеюсь, знают все. Никакой другой вариант быстрей не будет. Но есть одно интересное исключение. Это USART в режиме SPI. На картинке ниже привожу 6 скринов с анализатора, все сняты в разных режимах (внимание, масштаб везде разный, поэтому смотрите на временные параметры).
Плюсы USART в режиме SPI:
1. Скорость выше, чем у аппаратного SPI, процентов на 30, с учётом пауз между передачей байтов. Возможность передавать по 2 байта подряд совсем без паузы (то есть 16 подряд тактирующих импульсов).
2.Заняты, в отличие от аппаратного SPI, только 2 ноги контроллера (1-data, 4-clk). У аппаратного SPI всегда заняты ноги 11, 12, 13, даже если 12 ни к чему не подключена. Здесь же ногу №0 можно использовать в любых своих целях. Само собой, для общения с дисплеем нужны ещё как минимум 2 или 3 ноги (то есть всего 4 или 5 сигнальных плюс 2 питание).
Минусы USART в режиме SPI:
1. Не поддерживает 9-битную передачу, необходимую некоторым дисплеям, хотя USART в обычном режиме умеет. (Это не точно, может кто подскажет как.)
2. Привязка к конкретным ногам контроллера (1 и 4).
3. Выплывает из пункта 2 - невозможность использовать USART для общения (не переживайте, скетчи при этом заливаются нормально).
Обратите внимание, на четвёртой и шестой картинках видна передача 2 байт подряд- расчёска с 16 зубцами.
Информация есть здесь //https://feilipu.me/2015/02/17/avr-atmega-usart-spi-mspim/
Вот фрагмент кода, должен подойти для 5110, хотя я проверял на совсем другом дисплее. Ещё раз напоминаю: нога 0 - data(SDA,DI и т.п.), нога 4 - clk(SCK и др.), остальные ножки к дисплею тоже прописываются в скетче...
void Update() { //=======================Обновить дисплей for (byte p = 0; p < 8; p++) { transfer(0xb0 + p, 0); transfer(0x10, 0xe0); bitWrite(PORTD, 0, 1);// высокий уровень на DC (Data/Comand), можно любую ногу контроллера, кроме 0 и 4 for (byte col = 0; col < LCD_X ; col = col + 2) { //SendByte(LCD_D, LCD_RAM[(LCD_X * p) + col]); //===========так было transfer((LCD_RAM[(LCD_X * p) + col]), (LCD_RAM[(LCD_X * p) + col + 1]));//=========так стало, отправляем по 2 байта подряд, чтоб быстрее } bitWrite(PORTD, 0, 0);// низкий уровень на DC (Data/Comand) } } void transfer(byte sp) { //=====================подпрограмма отправки байта UCSR0A = _BV (TXC0); // Сбросить флаг завершения передачи, все остальные биты должны быть записаны в 0. UDR0 = sp; // Начать передачу первого байта. while (! (UCSR0A & _BV (TXC0))); // Проверьте, что мы закончили, ожидая флага завершения передачи. } void transfer(byte sp1, byte sp2) { //=================подпрограмма отправки двух байт UCSR0A = _BV (TXC0); // Сбросить флаг завершения передачи, все остальные биты должны быть записаны в 0. UDR0 = sp1; // Начать передачу первого байта. UDR0 = sp2; // Начать передачу второго байта. while (! (UCSR0A & _BV (TXC0))); // Проверьте, что мы закончили, ожидая флага завершения передачи. }И напоследок: кто поможет мне это переписать под Atmega64 ? Зачем? А затем, что мне нужны одновременно SPI, UART для терминала, и SPI к дисплею. Да и цена меньше, чем Atmega328. Пока что эксперименты не увенчались успехом.
Всем здравствуйте. Я так понимаю что у меня, у одного в этом девайсе с кнопками проблемы. Или с контроллерами, сразу с двумя. Чего у меня кнопочки сами нажимаются? progrik меня научил что делать. Но всё таки интересно почему у всех работает, а у меня нет.
раз пошла такая пьянка.... я человек - проверка. у меня SPI работает на 4МГц, и это проверенно опытом. можно быстрее, проводочки плохие... заливанием дисплея.... точки на фпс.... ВСЁ. он работает ровно на своей скорости. это аппаратная фигня, оно работает такт в такт... и только две ноги, я не понимаю, зачем тебе 3-я....
год не пил.... протрезвею - гляну твой код. и выскажу благодарность, за новые знания. если получу их)) но что-то надо думать... не сейчас....
есть 2 способа подключать кнопки. прижимаешь через резистор к земле(минус, 0), или подтягиваешь к плюсу(+, 1) в коде поменяй 0 на 1 или наоборот. как-то так...
...
У меня входы контроллера стянуты на землю через 10 КОм и "+" подаётся через кнопки. Как на схеме. Буду стараться, изучать.
У меня входы контроллера стянуты на землю через 10 КОм и "+" подаётся через кнопки. Как на схеме. Буду стараться, изучать.
Так просто! И всё заработало. Спасибо.
...у меня SPI работает на 4МГц, и это проверенно опытом...это аппаратная фигня, оно работает такт в такт...
... и только две ноги, я не понимаю, зачем тебе 3-я....
...
а где раздобыть версию с рабочим медленным осциллографом?
Всеь привет!!! Ребята помогите уточнить, Пультоскоп какие значение показываеть на вольта,т. е . Пик-Пик(Vpp) или Пик(Vp) или среднеквадратичное(Vrms) напряжение? Нужно измерить ВЧ сигнал через диодный детектор.
Пока тут идет "баловство", некоторые уже продают это чудо :)


Уж больно картинка на экране похожа на ту, что у Electronik83.
Понравилось, как он вместо трёх кнопок колёсико применил, как на китайских Bluetooth-модулях...
http://www.tindie.com/products/phoenixcnc/olediscope-an-oscilloscope-for-your-pocket/
Пока тут идет "баловство", некоторые уже продают это чудо :)
Уж больно картинка на экране похожа на ту, что у Electronik83.
Тихо сп***дил и ушёл, называется нашёл!!! Пускай покупают те кто паять не могают ))). за 15$ можно два на коленке собрать с удовольствием или дсо138 взять, один фиг там корпуса нет. Ну молодец что платы себе нарисовал.
Del
Так если бы хоть за 15$. У меня показывает $43.95 (3 039,84 ₽ RUB)
Даже нет ссылки на первоисточник... "Мой проект..."
Сразу мысль мелькнула, что если бы кто-то, типа AlexGyver, сделал разводку подобной платы (там ведь просто Ардуинка перенесена на свою плату с прорезью под SSD1306) и подарил китайцам, то можно было бы его уже купить за 2-3... ну пусть 5$. У него там связи есть. Лампы его очень даже продаются. Думаю, покупали были бы...
Кто может ответить,помогите!!!!
Пультоскоп какие значение показываеть на вольта,т. е . Пик-Пик(Vpp) или Пик(Vp) или среднеквадратичное(Vrms) напряжение?
Нужно измерить ВЧ сигнал через диодный детектор.
ну поделитесь плиииз прошивкой в которой работает медленный осциллограф. можно на дисплее от нокия или олед.
блин а еще я хочу такой же трехпозиционный джойстик как у этого плагиатора
блин а еще я хочу такой же трехпозиционный джойстик как у этого плагиатора
А чем плох 4х позиционный джойстик от сотовых?Цена копейки и места занимает минимум места .https://aliexpress.ru/item/32969557581.html
Del
ну не плохая штука конечно но для моих целей нужен именно такой как у плагиатора. с боковым выходом.
или миниатюрный энкодкодер типа как на мышке (мышинный не очень удобен но на крайняк возможно попробую его)
Andry Smart, это то, что вам надо? (вариант подешевле). Есть такие же, но дороже.
https://a.aliexpress.com/_BORXXB

Вот еще дешевле, US $0.64 за 10 шт.
https://aliexpress.ru/item/4000697123862.html
Andry Smart, если собираетесь "плагиатить" у плагиатора, то вот ещё "его" программатор к "его" осциллоскопу, за 13$...

Покупаете на Али готовый мини переходник и припаиваете к нему, от туда же (с Али), пружинные контакты. Сэкономите около 10$, как минимум.