Привет всем.У меня почему то напряжение АКБ всегда показывает 5в. Питаю от аккумулятора 18650.Собрал на дисплее 5110 и арудино нано.Напряжение от АКБ подаю через 10ком на пин А5. Если убираю резистор величина начинает прыгать.Пробовал на другие пины ,то же самое. Ещё при питании от usb при замере 1,5 вольтовой батарейки показывает 1,7 вольт. Как мне его настроить?
Sergei H. - все просто, автор скетча рассчитывал на питание 5 вольт, и прописал в качестве опорного VCC, поэтому замер собственного питания всегда будет показывать 5 вольт.
При питании от USB от компьютера приходит 5 вольт, но часть напряжения теряется на встроенном стабилизаторе, соответственно опорное получается уже не 5 вольт, а 4,7...4,5 - соответственно при пересчете измерения АЦП получается завышение показаний.
Простого решения нет - купи плату повышайки и подайте на плату 7 вольт и будет вам счастье.
При питании от USB от компьютера приходит 5 вольт, но часть напряжения теряется на встроенном стабилизаторе, соответственно опорное получается уже не 5 вольт, а 4,7...4,5
с чего бы это юсб питанию идти через стабилизатор? оно идет через диод шоттки B2, на котором напряжение тоже немного проседает, 0,2-0,3В (китай nano. вчера как раз сжег его, случайно коротнув питание. поменял на красную стекляшку%) ). через стаб идет только VIN.
Sergei H. пишет:
Подключил резистор 10к от A5 на землю ,показывает на 5 вольт меньше,чем на батарее.
если от входа A5 кинуть пару резисторов 10 КОм - один от A5 на VIN, другой от A5 на землю, при VIN = 9В на А5 должно быть 4,5В. обычный делитель напряжения на 2, все должно работать, если скетч в порядке. сделай контроль мультиметром между GND и A5... и начинай изучать, как работают детальки с двумя, тремя и более выводами :D
При питании от USB от компьютера приходит 5 вольт, но часть напряжения теряется на встроенном стабилизаторе, соответственно опорное получается уже не 5 вольт, а 4,7...4,5
Где то я реализовывал функцию, которая возвращает напряжения питания ардуинки, чтоб ничего не мерять тестером и не вычислять.
А так да - на диоде подает часть напряжения питания (где то 0.3 вольта). Линейный стабилизатор при питании от USB не участвует. Он завязан на ногу VIN (RAW)....
А может кто знает, на какой странице моя какая нибудь версия под ssd1306?
А как на этом форуме картинки вставлять? А то пришли макетки (платки с дырками под пайку) - паял тут три дня (да, я долго паяю). Дисплеи теперь есть 5110 и 1306 в изобилии...
Хотел с Вами поделиться результатом.....
P.S. правда нашел тут какой то свой скетч - и диву даюсь, как я так мог написать "херово". датировано 17-ым годом....
P.S.2. Теперь не надо хоть "таскать" эти здоровенные макетки для втыкания проводов.... все умещается меньше чем в пачке сигарет....
А может кто знает, на какой странице моя какая нибудь версия под ssd1306?
А как на этом форуме картинки вставлять? А то пришли макетки (платки с дырками под пайку) - паял тут три дня (да, я долго паяю). Дисплеи теперь есть 5110 и 1306 в изобилии...
Хотел с Вами поделиться результатом.....
P.S. правда нашел тут какой то свой скетч - и диву даюсь, как я так мог написать "херово". датировано 17-ым годом....
P.S.2. Теперь не надо хоть "таскать" эти здоровенные макетки для втыкания проводов.... все умещается меньше чем в пачке сигарет....
нужно нажать на значек изображение, там предложит загрузить на сервер фото, и потом уже с сервера вы добавляете фото сюда
За то каким именно путем приходит питание при запитке от USB не особо вникал, но у меня оно ВСЕГДА было пониженным 4,5...4,7В если мерить на лапе конторолера.
Если замер напряжения батареи требуется только при старте можно задействовать внутренний ИОН(источник опорного напряжения), это стандартная функция http://arduino.ru/Reference/AnalogReference
Но тут есть два подводных камня:
1. Нужен делитель напряжения, для однобаночного литевого акума 10 кОм на + акума, второй вывод резистора на аналоговый вход, на тот же анналоговый вход резистор 2 кОм - второй вывод резистора на землю.
2. Внутренний ИОН микроконторолера допускает разброс по напряжению, если не ошибаюсь +/- 0,1 вольт, нужно будет в формулу пересчета загонять поправочный коэфициент.
Да тут по сути нахер ничего не надо, че тупим то. Читаем, считаем и вуаля!
Я приводил пример функции, где ардуинка меряет свое напряжение питания, оно же будет и опорное.
P.S. На этих дерь/шовых китайских дисплейчиках мою анимацию главного меню практически не видно..... На оригинальном от нокии 3310 все гараздо контрастнее и четче... Думаю может отказаться от этой анимации? Как считаете, уважаемые форумчане?
... Через месяц придут платы для пультоскопа от узкоглазых товарищей...
А можно поподробней? А то я тоже много ждал с китая..
Развёл плату. Заказал изготовление в JLC PCB. Два проекта (по 5 и по 10 плат) с доставкой обошлись в 22 у. е. Получу через пару недель, спаяю, выложу фото. Под дисплей 1202.
Electronik83 пишет:
Где то я реализовывал функцию, которая возвращает напряжения питания ардуинки, чтоб ничего не мерять тестером и не вычислять.
Всё равно нужно мерить, вычислять, и вводить поправочный коэффициент, причём зависящий от варианта запитки контроллера. Если показания правильны в диапазоне 3,4 ... 4,2 вольт (питание от литиевого аккумулятора без повышайки), то при том же коэффициенте и питании 5 вольт будет неслабо врать. И наоборот. Надеюсь, смог выразить мысль понятно.
Electronik83 пишет:
мою анимацию главного меню практически не видно... Думаю может отказаться от этой анимации? Как считаете, уважаемые форумчане?
Я отказался. Баловство это. Главное- удобство пользования. И ничего лишнего в интерфейсе. Над каждой буквой-цифрой думал.
кстати автоомасштабирование пытаюсь прикрутить и пока не успешно. надо поковырять чьи то исходники. по моему кто то автомасштаб делал
Писал где то такой код, только не найти его. Или искать долго - тут на форуме:) Много очень страниц.... И после автомасштаба дисплейчик 1306 накернился (был один).... И я плюнул на это все:(
Замер напряжения питания arduino без использования дополнительно обвязки и без доп ног. . . . . . . . . . . . .
В скетчах Электроника это давно реализовано. Но это возможно только при питании напрямую от батареи. Если применён преобразователь, то без использования аналогового входа напряжение батареи (а оно не равно напряжению питания контроллера) замерить невозможно.
Ищи "magnify" ( автоомасштабирование) только не авто. Есть авто опорное 5.0, 1.1, 0.2
Я чет наверное туплю, но откуда 0.2 взялось?
И еще - если пин 13 делать свободным (а я хочу, чтоб на нем светодиод висел отладочный), то не предоставляется возможности резвести кнопки и генераторы.... что думаете, товарищи?!?! аналоговые кнопки не хочу.....
А дисплеев этих 1202 - у меня, как оказалось, есть несколько в наличии... яж сотики чиню больше 15-ти лет...
P.S. И кстати в голую атмегу328 в DIP корпусе влезает больше прошивки, чем в Arduino Pro.... - разные bootloader`ы...
И еще - если пин 13 делать свободным (а я хочу, чтоб на нем светодиод висел отладочный), то не предоставляется возможности резвести кнопки и генераторы.... что думаете, товарищи?!?! аналоговые кнопки не хочу.....
Вам выводов не хватает? Озадачили... У меня (и, насколько помню, еще у нескольких товарищей) в одном приборе совмещен пультоскоп со всеми оригинальными допами (генераторы, терминал), транзистор-тестер и логический анализатор, на отдельном пине сидит измерение напряжения аккумулятора, и еще один пин остался свободный. Как у вас-то не влезает?
У меня (и, насколько помню, еще у нескольких товарищей) в одном приборе совмещен пультоскоп со всеми оригинальными допами (генераторы, терминал), транзистор-тестер и логический анализатор, на отдельном пине сидит измерение напряжения аккумулятора, и еще один пин остался свободный. Как у вас-то не влезает?
Просмотрел почти всю тему. Фотку твоего чуда видел, а вот кода не нашел. Поделись, пожалуйста, своей версией скетча, если, конечно, это возможно. diksen выложил свою "альфа" версию и больше на форуме я его не пока не видел. Он обещал свою типа "бета" , но пока увы... Его "альфа" у меня работает, но терминала нет, меню настроек тоже нет... А я в программировании "0" без палочки...
https://yadi.sk/d/8KPXSivG1JWY8w набросок на голой атмеге 328 c тфт 2.4. Да и кто-нибудь может выложить hex стандартной версии, а то у меня толи библиотек не хватает, в общем не компилируется, заранее спасибо!
Доброго времени суток! В общем сваял я пробный образец но постигла меня неудача, файлы hex и eep у меня откомпилировались ,прошились в контроллер по usbasp шил через синапрог ,но как говорится "белый экран" наблюдаю только подсветку.Ладно подожду ардуинки и по проторённой тропе! да кстати дисплей попался вот такой 2.4" TFT ILI9341 240X320. соответственно и скетч комипилировал под него.
..."белый экран" наблюдаю только подсветку. ... дисплей попался вот такой 2.4" TFT ILI9341 240X320.
попробуй в функции setup закоментить определение идентификатора дисплея и вписать ID принудительно. для ili9341 это 0x9341. у меня на таком дисплее не читался id
делай, чтоб вышло так:
void setup(){
// эта строка нам больше не нужна uint16_t identifier = tft.readID(); //Читаем ID экрана
uint16_t identifier = 0x9341; //тут хардово прописываем ID 0x9341
Привет progrik! Извини за назойливость ,но не мог бы показать свой рабочий скетч,а лучше hex-файл,может я криворукий, но мантра "би хеппи" не помогает!!!!
удалил
вопросик созрел по разгону AVR. а выше 27 мгц заводится Mega328?
после замены кварца не прошивается, потому-что загрузчик Arduino на 16 мгц кварц написан, и банально не совпадают битрейты в IDE и борде.
если найти исходники, а они есть, то можно и не дергать потом туда-сюда, перешив бутлоад на текущий кварц, я так понимаю.
kloker, заведётся, но на сложных задачах повиснет. http://arduino.ru/forum/apparatnye-voprosy/turbo-arduino-na-32-mgts В принципе Optiboot не трудно скомпилить на любую частоту.
А вот mega328pb разгоняется на 32МГц :)
понял, будем пробовать. спасибо за ссылку!))
на 25 и 32 мгц кварцы есть, на 27мгц нечто от радиостанции, но похоже это кварцевый фильтр без имени и фамилии))
seri0shka
В этом скетче Автоматическое автопределение делителя "5.0" "1.1" "0.2" + превышение максимума АЦП
Выбор развёртки "Авто" и "Ручной" (только не получилось буквы прописать, цифры вместо букв так как библа другая).
Доработайте пожалуйста остальное, Я просто внедрил то к чему привык.
#define BUFSIZE 700 #define history 50 volatile int cur_index = 0; //переменная для отсчета замеров volatile int StartIndex = 0; // номер замера с которого нужно выводить результат (считается так: (замер сработки триггера-предистория)) volatile byte prev_data; // предыдущее состояние шины volatile byte pattern_mask; // маска для события PATTERN volatile byte pattern_value; // ЗНАЧЕНИЕ состояния для события PATTERN volatile boolean trigger_event = false; //признак сработки триггера volatile int time_disc = 0; // время выборки 1-го значения unsigned long prevMillis, curMillis; enum triggerEvents {BURST, MASTER_RISE, MASTER_FALL, PATTERN}; //именнованный список триггеров-событий bool flag = 0; //#include <EEPROM.h> #define RES 3 #define CS 4 #define Data 6 #define Clock 7 #define swap(a, b) { int t = a; a = b; b = t; } #include <FreqCount.h> #include <PWM.h> // Настройки пользователя - можно менять #define OVERCLOCK 16 // частота на которой работает Ардуино float VCC = 5.0; // напряжение питания #define KEY_L 11 // кнопка ЛЕВО (можно любой пин) #define KEY_OK 12 // кнопка ОК (можно любой пин) #define KEY_R 13 // кнопка ПРАВО (можно любой пин) #define KEY_P 8 // кнопка PAUSE (можно любой пин) #define KEY_DELAY 200 #define LCDX 96 // Переменные, дефайны и прочяя хрень - менять со смыслом #define GEN_PIN 9 // 9 пин для генератора сигналов (не менять) #define DDS_PIN 10 // 10 пин для генератора dds (не менять) #include <avr/pgmspace.h> const char string_0[] PROGMEM = "Осциллограф"; // "String 0" и т.д. - это содержимое строк; если необходимо меняйте его const char string_1[] PROGMEM = "Генератор"; const char string_2[] PROGMEM = "DDSгенератор"; const char string_3[] PROGMEM = "Терминал"; const char string_4[] PROGMEM = "Анализатор"; const char string_5[] PROGMEM = " "; const char string_6[] PROGMEM = "V bat="; const char string_7[] PROGMEM = " PWM="; const char string_8[] PROGMEM = " Pause "; const char string_9[] PROGMEM = "Частота"; const char string_10[] PROGMEM = " Синус "; const char string_11[] PROGMEM = " Треугольник "; const char string_12[] PROGMEM = " Пила "; const char string_13[] PROGMEM = "Обратная пила"; const char string_14[] PROGMEM = "Скорость:"; // Теперь создаем таблицу с отсылками к этим строкам: const char* const string_table[] PROGMEM = {string_0, string_1, string_2, string_3, string_4, string_5, string_6, string_7, string_8, string_9, string_10, string_11, string_12, string_13, string_14}; char buffer[13]; // массив должен быть достаточно велик, чтобы вместить даже самую большую строку byte symbol1 = 0; byte symbol2 = 0; byte symbol3 = 0; byte mode = 0; // пункт главного меню byte menu = 0; // пункт меню byte adcBuf[BUFSIZE]; byte vSync = 30; // уровень синхронизации bool vRef = 1; // флаг опорного напряжения bool pause = 0; // флаг режима паузы bool avtorazv=1; // Автоматический выбор развертки byte TextColor = 1; byte razv = 3; byte trig = 0; int kdel=5; //bulat автопредел 1,1/0,2 вольта int grOffset = 0; // смещение графика в рабочем режиме byte vMax, vMin; // максимальное и минимальное напряжение сигнала // Переменные для генератора int PWM = 50; // стартовое значение ШИМ от 0 до 100 для генератора int temp = 0; // временная переменная*** unsigned long freq = 1000; // стартовое значение частоты в Гц для генератора unsigned long stepFreq = 0; unsigned long count = 1; byte LCD_RAM[96 * 9]; // 96 * 9 static const char font[] PROGMEM = { 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 я }; //******************************************************** void setup() { // pinMode(8, OUTPUT); // 7, 8- питание на дисплей // pinMode(7, OUTPUT); // digitalWrite(8, 1); // digitalWrite(7, 0); pinMode(KEY_OK, INPUT); pinMode(KEY_L, INPUT); pinMode(KEY_R, INPUT); pinMode(KEY_P, INPUT); // настраиваем кнопки на вход digitalWrite(KEY_OK, HIGH); digitalWrite(KEY_L, HIGH); digitalWrite(KEY_R, HIGH); digitalWrite(KEY_P, HIGH); // подтяжка к плюсу питания VCC = ReadVcc(); Inicialize(); //Инициализация дисплея Clear_LCD(); ukazatel();//fillTriangle(1, mode * 10); // указатель меню // drawChar(1, mode * 10, 1, ">"); //char Str2[8] = {'a', 'r', 'd', 'u', 'i', 'n', 'o'}; /* print(10, 0, 1, "Oscillograf"); print(10, 10, 1, "Generator"); print(10, 20, 1, "DDSgenerator"); print(10, 30, 1, "Terminal"); print(10, 40, 1, "Analizator");*/ for (byte i = 0; i < 7; i++) { strcpy_P(buffer, (char*)pgm_read_word(&(string_table[i]))); // необходимые функции и расшифровки, просто скопируйте print(10, i * 10, 1, (buffer)); //delay( 500 ); } /*print(10, 0, 1, "Осциллограф"); print(10, 10, 1, "Генератор"); print(10, 20, 1, "DDSгенератор"); print(10, 30, 1, "Терминал"); print(10, 40, 1, "Анализатор"); print(10, 60, 1, "V bat="); // *************/ float_print(48, 60, 1, VCC, 2); Update(); delay(KEY_DELAY); while (digitalRead(KEY_OK)) { // цикл, пока не нажали кнопку ОК // опрос кнопок if (!digitalRead(KEY_R)) { mode = mode + 1; if (mode > 5 ) {mode = 0;} ukazatel(); } if (!digitalRead(KEY_L)) { mode = mode - 1; if (mode < 0) {mode = 5;} ukazatel(); } Update(); } // цикл нажатия ОК // нажали кнопку ОК из меню, инициализируем и выходим из меню count = 0; //countX = 0; // восстанавливаем на всякий случай переменные if (mode == 0) FreqCount.begin(1000); if (mode == 1) { InitTimersSafe(); bool success = SetPinFrequencySafe(GEN_PIN, freq); pwmWrite(GEN_PIN, PWM * 2.55); } if (mode == 2) { InitTimersSafe(); bool success = SetPinFrequencySafe(GEN_PIN, 200000); } if (mode == 4 || mode == 5) DDRC = 0x00; PORTC = 0x00; Serial.begin(115200); // razv = 0;// весь порт С (это A0...A5) на вход и без подтяжки } // беcконечный цикл - по сути прыгаем в подпрограммы void loop() { switch (mode) { // Прыгаем в выбранный режим из главного меню case 0 : Oscil(); break; // "выпадаем" в осцилл case 1 : Generator(); break; // "выпадаем" в генератор case 2 : DdsGenerator(); break; // "выпадаем" в DDS генератор case 3 : Terminal(); break; // "выпадаем" в USART приемник case 4 : LogAnalyzer(); break; // "выпадаем" в Анализатор case 5 : LogAnalyzer(); break; // "выпадаем" в Анализатор } } // === Читаем с АЦП данные и помещаем их в буфер === // void ReadAdc() { if (razv % 10) { // (razv>0) // если развертка без задержек всяких (с 1 по 7) ADCSRA = 0b11100000 | (8 - (razv % 10)); // установили делитель (/2 - не работает, так что начинаем с /4) for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения while (!(ADCSRA & 0x10)); // ждем готовность АЦП ADCSRA |= 0x10; // запускаем следующее преобразование adcBuf[i] = ADCH; // записываем данные в массив } delay(0.3 * BUFSIZE); // компенсация задержки по сравнению с разверткой 0... } else { // развертка с задержками (delay) ADCSRA = 0b11100111; // делитель на /128 for (int i = 0; i < BUFSIZE; i++) { // цикл для чтения while (!(ADCSRA & 0x10)); // ждем готовность АЦП ADCSRA |= 0x10; // запускаем следующее преобразование delayMicroseconds(500); // делаем задержку adcBuf[i] = ADCH; // записываем данные в массив } } } // === Чтение цифровых данных со всего порта C (A0...A5) === // /*void ReadDig() { if (razv == 9) { for (int i = 0; i < BUFSIZE; i++) adcBuf[i] = PINC; // быстро читаем данные } else { for (int i = 0; i < BUFSIZE; i++) { adcBuf[i] = PINC; // читаем данные delayMicroseconds((9 - razv) * 100); } } }*/ // ==== функция вывода float ==== void float_print(byte x, byte y, boolean color, float num, byte zn) { // последняя переменная- кол знаков после запятой char c[20]; long d = num; byte m = 1; while (d > 9) { d = d / 10; m++; } print(x, y, color, dtostrf(num, m, zn, c)); } // ==== Считывание напряжения питания ардуинки (Vcc) ==== #define Vref11 1.098 // для точной подстройки результата измерений 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)); // результат преобразования в вольтах } /*int GetCountsOfDigits(int n) //найти количество цифр в числе <a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a> { return n < 10 ? 1 : n < 100 ? 2 : n < 1000 ? 3 : n < 10000 ? 4 : n < 100000 ? 5 : n < 1000000 ? 6 : n < 10000000 ? 7 : n < 100000000 ? 8 : n < 1000000000 ? 9 : 10; }*/ // ==== найти количество цифр в числе <a href="<a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a>" rel="nofollow"><a href="https://habr.com/ru/post/269237/" rel="nofollow">https://habr.com/ru/post/269237/</a></a> /*static int stringSize(long x) { long p = 10; for (int i = 1; i < 19; i++) { if (x < p) return i; p = 10 * p; } return 19; }*/ void vivod(byte x, byte y, byte n, byte k) { // //Печать цифры размером 24х48 пикселя (x, y, цифра, размер (1-24х48, 2-12х24)) if ((n != 1) && (n != 4)) { fillRect(x + 3 / k, y, 15 / k, 5 / k, 1 ); // сегмент A } if ((n != 5) && (n != 6)) { fillRect(x + 16 / k, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент B } if (n != 2) { fillRect(x + 16 / k, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент C } if ((n != 1) && (n != 4) && (n != 7)) { fillRect(x + 3 / k, y + 42 / k, 15 / k, 5 / k, 1 ); // сегмент D } if ((n == 0) || (n == 2) || (n == 6) || (n == 8)) { fillRect(x, y + 24 / k, 5 / k, 20 / k, 1 ); // сегмент E } if ((n != 1) && (n != 2) && (n != 3) && (n != 7)) { fillRect(x, y + 3 / k, 5 / k, 20 / k, 1 ); // сегмент F } if ((n != 0) && (n != 1) && (n != 7)) { fillRect(x + 3 / k, y + 21 / k, 15 / k, 5 / k, 1 ); // сегмент G } } //====================================================указатель меню void ukazatel() { fillRect(1, 1, 8, 60, 0); for (byte i = 0; i < 4; i++) { // указатель меню drawLine(1 + i, mode * 10 + i, 1 + i, mode * 10 + 6 - i, 1); } Update(); delay(KEY_DELAY); } //===================================================Инициализация дисплея void Inicialize() { pinMode(RES, OUTPUT); pinMode(CS, OUTPUT); pinMode(Data, OUTPUT); pinMode(Clock, OUTPUT); // Инициализация дисплея dWrite(RES, 1); dWrite(Clock, 0); dWrite(Data, 0); dWrite(CS, 0); delay(20); dWrite(CS, 1); SendByte(0, 0x2F); // Power control set(charge pump on/off) SendByte(0, 0xA4); SendByte(0, 0xAF); // экран вкл/выкл //Clear_LCD(); //Update(); } //=======================================================Управление пинами void dWrite(byte pin, byte val) { byte bit = digitalPinToBitMask(pin); volatile byte *out; out = portOutputRegister(digitalPinToPort(pin)); (val) ? *out |= bit : *out &= ~bit; } //=========================================================Отправка 9 байт void SendByte(byte mode, byte c) { dWrite(CS, 0); (mode) ? dWrite(Data, 1) : dWrite(Data, 0); dWrite(Clock, 1); for (byte i = 0; i < 8; i++) { dWrite(Clock, 0); (c & 0x80) ? dWrite(Data, 1) : dWrite(Data, 0); dWrite(Clock, 1); c <<= 1; } dWrite(Clock, 0); } //======================================================Очистка дисплея void Clear_LCD() { for (int index = 0; index < 864 ; index++) { LCD_RAM[index] = (0x00); } } //=====================================================Обновить дисплей void Update() { for (byte p = 0; p < 9; p++) { SendByte(0, 0xB0 | p); SendByte(0, 0x00); SendByte(0, 0x10); for (byte col = 0; col < 96; col++) { SendByte(1, LCD_RAM[(96 * p) + col]); } } } //===================================================Нарисовать пиксель void drawPixel (byte x, byte y, boolean color) { if ((x < 0) || (x >= 96) || (y < 0) || (y >= 68)) return; if (color) LCD_RAM[x + (y / 8) * 96] |= _BV(y % 8); else LCD_RAM[x + (y / 8) * 96] &= ~_BV(y % 8); } //=====================================================Нарисовать букву void drawChar(byte x, byte y, boolean color, unsigned char c) { if ((x >= 96) || (y >= 68) || ((x + 4) < 0) || ((y + 7) < 0)) return; if (c < 128) c = c - 32; if (c >= 144 && c <= 175) c = c - 48; if (c >= 128 && c <= 143) c = c + 16; if (c >= 176 && c <= 191) c = c - 48; if (c > 191) return; for (byte i = 0; i < 6; i++ ) { byte line; (i == 5) ? line = 0x0 : line = pgm_read_byte(font + (c * 5) + i); // line = EEPROM.read((c * 5) + i); for (byte j = 0; j < 8; j++) { (line & 0x1) ? drawPixel(x + i, y + j, color) : drawPixel(x + i, y + j, !color); line >>= 1; } } } //========================================================Вывод строки void print(byte x, byte y, boolean color, char *str) { unsigned char type = *str; if (type >= 128) x = x - 3; while (*str) { drawChar(x, y, color, *str++); unsigned char type = *str; (type >= 128) ? x = x + 3 : x = x + 6; } } //========================================================Вывод числовых значений void print(byte x, byte y, boolean color, long num) { char c[20]; print(x, y, color, ltoa(num, c, 10)); } //====================================================Рисование линии void drawLine(byte x0, byte y0, byte x1, byte y1, boolean color) { int steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { swap(x0, y0); swap(x1, y1); } if (x0 > x1) { swap(x0, x1); swap(y0, y1); } int dx, dy; dx = x1 - x0; dy = abs(y1 - y0); int err = dx / 2; int ystep; (y0 < y1) ? ystep = 1 : ystep = -1; for (; x0 <= x1; x0++) { (steep) ? drawPixel(y0, x0, color) : drawPixel(x0, y0, color); err -= dy; if (err < 0) { y0 += ystep; err += dx; } } } //========================================Рисование вертикальной линии void drawFastVLine(byte x, byte y, byte h, boolean color) { drawLine(x, y, x, y + h - 1, color); } //======================================Рисование горизонтальной линии void drawFastHLine(byte x, byte y, byte w, boolean color) { drawLine(x, y, x + w - 1, y, color); } //=====================================Рисование залитый прямоугольник void fillRect(byte x, byte y, byte w, byte h, boolean color) { for (byte i = x; i < x + w; i++) { drawFastVLine(i, y, h, color); } } //=====================================Рисование битового нолика void printnull(byte a, byte i) { drawPixel(29 + a - i * 4, 64, 1); drawFastVLine(28 + a - i * 4, 65, 2, 1); // и вывести биты на дисплей drawFastVLine(30 + a - i * 4, 65, 2, 1); drawPixel(29 + a - i * 4, 67, 1); } // === Осциллоскоп === // void Oscil() { // установка опорного напряжения АЦП и настройка входа АЦП ADMUX = vRef ? 0b01100011 : 0b11100011; label_ReadAdc: // === Обработка кнопок === // if (!digitalRead(KEY_L)) switch (menu) { // кнопка лево:) case 0 : vRef = !vRef; break; // меняем опорное напряжение case 1 : avtorazv=!avtorazv; case 2 : razv--; if (razv == 255) razv = 6; break; // меняем развертку case 3 : grOffset -= 20; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе } if (!digitalRead(KEY_R)) switch (menu) { // кнопка право:) case 0 : vRef = !vRef; break; // меняем опорное напряжение case 1 : avtorazv=!avtorazv; case 2 : razv++; if (razv == 7) razv = 0; break; // меняем развертку case 3 : grOffset += 20; if (grOffset > BUFSIZE - LCDX) grOffset = BUFSIZE - LCDX; break; // листаем график в паузе } if (!digitalRead(KEY_OK)) switch (++menu) { case 3: grOffset = 0;// pause = 1; break; // вход в паузу - антидребезг типа case 4: menu = 0; pause = 0; break; // перебор меню } if (!digitalRead(KEY_P)) { menu = 3; pause = 1; } ///////////////авто razv if (avtorazv) #define PER 1.3 if (count > 3823.3*PER) razv = 6; else if (count > 1934.5*PER) razv = 5; else if (count > 0969.3*PER) razv = 4; else if (count > 0486.8*PER) razv = 3; else if (count > 0245.8*PER) razv = 2; else if (count > 0120.1*PER) razv = 1; else razv = 0; //////////////// // === Ведём рассчеты === // if (!pause) { // если нет паузы ReadAdc(); // то снимаем осциллограмму // == Вычисляем максимальное и минимальное значение сигнала == // vMax = 0; vMin = 0xFF; for (int y = 1; y < 255; y++) { if (vMax < adcBuf[y]) vMax = adcBuf[y]; // пока 255, но надо экспериментировать if (vMin > adcBuf[y]) vMin = adcBuf[y]; } vSync = (vMax - vMin) / 2 + vMin; // уровень синхронизации по середине уровня сигнала // == Определение точки синхронизации == // bool flagZero = 0; grOffset = 0; // сброс флага и точки синхронизации // Ищем перепад от меньшего уровня к большему for (int y = 1; y < BUFSIZE - LCDX; y++) { // смотрим весь массив данных АЦП if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - ставим флаг if (flagZero && adcBuf[y] > vSync) { grOffset = y; // нашли больше, чем синхра (перепад сигнала в плюс) - запомнили и выходим из цикла break; } } // === Считаем частоту сигнала === // if (vRef && vMax * VCC / 255 > 2.7) { // если можем замерить аппаратно - меряем if (FreqCount.available()) count = FreqCount.read(); // вывод частоты по готовности счетчика частоты сигнала } else { // === Меряем частоту сигнала программно === // flagZero = 0; count = 0; // сброс флага и счетчика for (int y = grOffset; y < BUFSIZE - LCDX; y++) { // смотрим массив от точки синхронизации до конца if (adcBuf[y] < vSync) flagZero = 1; // нашли меньше, чем синхра (перепад сигнала в минус) - выставляем флаг if (flagZero && adcBuf[y] > vSync) { // нашли больше, чем синхра (перепад сигнала в плюс) - отловили полный период switch (razv) { // считем частоту периода case 6: count = 1000000 / ((y - grOffset - 1) * 3.25); break; // делитель 4 case 5: count = 1000000 / ((y - grOffset) * 3.25) / 2; break; // делитель 8 case 4: count = 1000000 / ((y - grOffset) * 3.25) / 4; break; // делитель 16 case 3: count = 1000000 / ((y - grOffset) * 3.25) / 8; break; // делитель 32 case 2: count = 1000000 / ((y - grOffset) * 3.25) / 16; break; // делитель 64 case 1: count = 1000000 / ((y - grOffset) * 3.25) / 32; break; // делитель 128 case 0: count = 1000000 / ((y - grOffset) * 510); break; // делитель 128 тоже } break; } } } count = count * OVERCLOCK / 16.0; // пересчет частоты на разные кварцы } // закончили вести рассчеты Clear_LCD(); // чистим экран... // === Отрисовка меню осцилла === if (menu == 0) TextColor = 0; else TextColor = 1; if (vRef) float_print(0, 0, TextColor, VCC, 1); else { if(kdel==5)print(0, 0, TextColor, "1.1"); else print(0, 0, TextColor, "0.2"); } if (menu == 1) TextColor = 0; else TextColor = 1; print(20, 0, TextColor, avtorazv?'A':'M'); if (menu == 2) TextColor = 0; else TextColor = 1; print(35, 0, TextColor, razv); if (menu == 3) { // тут задержка для компенсации с остальными задержками delay(200); //print(48, 0, 0, " Pause "); strcpy_P(buffer, (char*)pgm_read_word(&(string_table[8]))); // необходимые функции и расшифровки, просто скопируйте print(48, 0, 0, (buffer)); } else TextColor = 1; if (!pause) float_print (48, 0, 1, count / 1000000.0, 6); // вывод частоты else { // рисуем прокрутку в режиме паузы temp = grOffset / 8; drawFastHLine(temp, 10, 6, 1); drawFastHLine(temp, 9, 6, 1); } // шкала прокрутки if (vRef && vMax * VCC / 255 > 2.7) drawChar(42, 0, 1, 97); // если замер аппаратный - "a" else drawChar(42, 0, 1, 112); // иначе "p" float_print(78, 14, 1, vMax * (vRef ? VCC : 1.1) / 255, 1); // рисуем максимальное напряжение сигнала float_print(78, 54, 1, vMin * (vRef ? VCC : 1.1) / 255, 1); // рисуем минимальное напряжение сигнала if (vMax==0xFF) for(int y=10; y<68; y++) drawFastHLine( 0, y, 5, 5); // превышение максимума АЦП // == Отрисовка сетки == // for (byte i = 11; i < 68; i = i + 14) { drawFastHLine( 0, i, 2, 1); // черточки слева } for (byte i = 67; i > 10; i = i - 4) { drawPixel(24, i, 1); drawPixel(48, i, 1); drawPixel(72, i, 1); } for (byte i = 8; i < 96; i = i + 4) { drawPixel(i, 39, 1); } //bulat если зашкаливает включаем предел 5 в if (vMax==255){ if (vRef==0) { vRef=1; ADMUX = 0b01100011;// выбор внутреннего опорного 5.0 В goto label_ReadAdc; } } //bulat если 5 в и уровень менее 1,1 в то вкл предел 1,1 в if (vMax<=55){ if (vRef==1) { vRef=0; ADMUX = 0b11100011;// выбор внутреннего опорного 1,1В goto label_ReadAdc; } } //bulat здесь автопредел 1,1/0,22 в,программный kdel=5; if (vMax<=55){ if (vRef==0) { kdel=1; } } // == Отрисовка графика == // for (int y = 0; y < 92; y++) drawLine(y + 4, 67 - adcBuf[y + grOffset]/kdel / 0.9, y + 4, 67 - adcBuf[y + grOffset + 1]/kdel / 0.9, 1); Update(); } //********************************************************************************** void Generator() { // обработка кнопок и отрисовка одновременно Clear_LCD(); //print(0, 0, 1, "Частота"); strcpy_P(buffer, (char*)pgm_read_word(&(string_table[9]))); // необходимые функции и расшифровки, просто скопируйте print(0, 0, 1, (buffer)); if (!digitalRead(KEY_OK)) { if (menu++ == 7) menu = 0; // переходим по разрядам / меняем ШИМ delay(KEY_DELAY); } if (menu == 7) { // меняем ШИМ if (!digitalRead(KEY_L)) { PWM--; if (PWM < 0) PWM = 100; delay(KEY_DELAY); } if (!digitalRead(KEY_R)) { PWM++; if (PWM > 100) PWM = 0; delay(KEY_DELAY); } pwmWrite(GEN_PIN, PWM * 2.55); // задали ШИМ TextColor = 0; // если меняем шим, то рисуем его инверсным } else { // меняем частоту if (!digitalRead(KEY_L)) { if (freq > stepFreq) freq -= stepFreq; // не даем выйти за допустимый диаппазон SetPinFrequencySafe(GEN_PIN, freq / (OVERCLOCK / 16.0)); // задали частоту delay(KEY_DELAY); // задержка для кнопок } if (!digitalRead(KEY_R)) { if ((freq + stepFreq) < 10000000) freq += stepFreq; // не даем выйти за допустимый диаппазон SetPinFrequencySafe(GEN_PIN, freq / (OVERCLOCK / 16.0)); // задали частоту delay(KEY_DELAY); // задержка для кнопок } TextColor = 1; // если ШИМ не меняем, то выбираем обычный текст #define XFREQ 10 // ======== // и, выделяем декаду частоты полосочками stepFreq = pow(10, (byte)menu); if (menu > 1) stepFreq++; // устраняем глючность pow, почему 10 в степени 2 = 99? temp = 42 - menu * 6; if (temp < 10) temp = 0; drawFastHLine(temp, XFREQ + 10, 5, 1); // выделяем декаду частоты полосочками drawFastHLine(temp, XFREQ + 9, 5, 1); } // рисуем уровень ШИМ (инверсия текста задана ранее) drawFastHLine(15, 39 , 54, !TextColor); // сверху полоска для большей инверсности strcpy_P(buffer, (char*)pgm_read_word(&(string_table[7]))); // необходимые функции и расшифровки, просто скопируйте print(15, 40, TextColor, (buffer)); print(45, 40, TextColor, PWM); print(57, 40, TextColor, "% "); // выводим уровень ШИМ if (PWM < 10) { drawChar(45, 40, TextColor, 32); // " " print(51, 40, TextColor, PWM); } drawChar(63, 40, TextColor, 32); // " " if (PWM == 100) { print(45, 40, TextColor, 100); print(63, 40, TextColor, "%"); } TextColor = 1; // убираем инверсию при выводе частоты // print(42 - stringSize(freq) * 6, XFREQ, 1, freq); // вывод частоты float_print (0, XFREQ, 1, freq / 1000000.0, 6); // вывод частоты print(50, XFREQ, 1, "MHz"); // отрисовка графика PWM for (char x = 17; x < 67; ) { if (PWM != 0) drawFastHLine(x, 26, PWM / 4, 1); x += PWM / 4; // верх if (PWM != 0 && PWM != 100) drawFastVLine(x, 26, 10, 1); // спад if (PWM != 100) drawFastHLine(x, 36, 25 - PWM / 4, 1); x += 25 - PWM / 4; // низ if (PWM != 0 && PWM != 100 && x < 43) drawFastVLine( x, 26, 11, 1); // подъем } Update(); // вываливаем буфер на дисплей } //********************************************************************************** void DdsGenerator() { static const byte ddsWave[][32] PROGMEM = { 2, 10, 21, 37, 57, 79, 103, 127, 152, 176, 198, 218, 234, 245, 253, 255, 253, 245, 233, 218, 198, 176, 152, 128, 103, 79, 57, 37, 21, 10, 2, 0, // El83_sinNew 16, 32, 48, 64, 80, 96, 112, 128, 143, 159, 175, 191, 207, 223, 239, 255, 239, 223, 207, 191, 175, 159, 143, 128, 112, 96, 80, 64, 48, 32, 16, 0, // El83_treugNew 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173, 181, 189, 197, 206, 214, 222, 230, 239, 247, 255, 0, // El83_pilaNew 255, 247, 239, 230, 222, 214, 206, 197, 189, 181, 173, 165, 156, 148, 140, 132, 123, 115, 107, 99, 90, 82, 74, 66, 58, 49, 41, 33, 25, 16, 8, 0 // El83_pilaObrNew }; byte ddsCount = 0; // Рисуем DDS-генератор Clear_LCD(); // режим работы, заголовок for (byte i = 0; i < 96;) drawLine(i, 36 - pgm_read_byte(&ddsWave[menu][i % 32]) / 10, i, 36 - pgm_read_byte(&ddsWave[menu][(i++) % 32]) / 10, 1); strcpy_P(buffer, (char*)pgm_read_word(&(string_table[10 + menu]))); // необходимые функции и расшифровки, просто скопируйте print(5, 40, 1, (buffer)); /*switch (menu) { //.......... case 0: strcpy_P(buffer, (char*)pgm_read_word(&(string_table[10]))); // необходимые функции и расшифровки, просто скопируйте print(3, 40, 1, (buffer)); break; case 1: strcpy_P(buffer, (char*)pgm_read_word(&(string_table[11]))); // необходимые функции и расшифровки, просто скопируйте print(3, 40, 1, (buffer)); break; case 2: strcpy_P(buffer, (char*)pgm_read_word(&(string_table[12]))); // необходимые функции и расшифровки, просто скопируйте print(3, 40, 1, (buffer)); break; case 3: strcpy_P(buffer, (char*)pgm_read_word(&(string_table[13]))); // необходимые функции и расшифровки, просто скопируйте print(3, 40, 1, (buffer)); break; }*/ Update(); while (digitalRead(KEY_R) && digitalRead(KEY_L) && digitalRead(KEY_OK)) { // выводим выбранный сигнал, пока не нажали кнопку pwmWrite(DDS_PIN, pgm_read_byte(&ddsWave[menu][(ddsCount++) & 0x1F])); } if (++menu == 4) menu = 0; // нажали кнопку - переключаем режим delay(KEY_DELAY); // чтоб кнопки нормально нажимались } //********************************************************************************** void Terminal() { //const long speedUart[] = { 9600, 19200, 38400, 57600, 115200, 300, 600, 1200, 2400, 4800 }; const PROGMEM uint32_t speedUart[] = { 9600, 19200, 38400, 57600, 115200, 250000, 300, 600, 1200, 2400, 4800 }; // ------ Clear_LCD(); //print(10, 0, 1, "Скорость:"); strcpy_P(buffer, (char*)pgm_read_word(&(string_table[14]))); // необходимые функции и расшифровки, просто скопируйте print(10, 0, 1, (buffer)); print(10, 10, 1, speedUart[menu]); Update(); if (!digitalRead(KEY_L)) { menu--; if (menu == 255) menu = 10; // print(28, 10, 1, " "); print(10, 10, 1, speedUart[menu]); Update(); delay(KEY_DELAY); } if (!digitalRead(KEY_R)) { menu++; if (menu == 11) menu = 0; // print(28, 10, 1, " "); print(10, 10, 1, speedUart[menu]); Update(); delay(KEY_DELAY); } if (!digitalRead(KEY_OK)) { Clear_LCD(); if (!digitalRead(KEY_P)) pause = 1; // включаем флаг, что пауза была нажата для вкл дополн функции else drawFastHLine(10, 66 , 75, 1); Serial.begin(speedUart[menu] * (16 / OVERCLOCK)); drawChar(0, 0, 0, 62); Update(); delay(KEY_DELAY); Update(); byte x = 0; byte y = 0; while (1) { if (Serial.available()) { // Если в буфере есть данные if (x > 90) { // проверяем, не заполнен ли экран x = 0; y = y + 8; } byte symbol = (Serial.read()); if ((symbol == 10 || symbol == 13) && x != 0) { x = 0; y = y + 8; } if (y > 56) { y = 0; x = 0; } if (symbol != 10 && symbol != 13) { if (symbol == 127 || symbol == 8) { // Del if (x == 0) { x = 90; if (y != 0) { y = y - 8; } else y = 56; } else { x += -6; } drawChar(x, y, 1, 32); // " " } else { symbol3 = symbol2; symbol2 = symbol1; symbol1 = symbol; if (symbol > 191) { //русские буквы if (symbol > 239) { drawChar(x, y, 1, symbol - 112); // } else drawChar(x, y, 1, symbol - 48); // } else drawChar(x, y, 1, symbol); // печать байта в дисплей // print(x + 6, y, 1, " "); //for (byte i = 0; i < 7; i++) drawLine(x + 6, y + i, 95, y + i, 0); // очистить место //for (byte i = 0; i < 7; i++) drawFastHLine(x + 6, y + i, 90, 0);// не работает x = x + 6; } } for (byte i = 0; i < 7; i++) drawLine(x, y + i, 95, y + i, 0); // очистить место if (pause == 1) { // вывод бинарных кодов символов только если были нажаты ДВЕ кнопки /*char p[17]; // itoa (symbol, p, 16); // перевод в шестнадцатеричное print(0, 60, 1, p); // отображение шестнадцатеричного*/ drawFastHLine(0, 65, 96, 0); // очистить место drawFastHLine(0, 66, 96, 0); drawPixel(31, 67, 1); // разделение байтов drawPixel(63, 67, 1); for (byte i = 0; i < 8; i++) { // разложить код символа на биты if (bitRead(symbol3, i)) drawFastVLine(29 - i * 4, 64, 4, 1); // биты предпредпоследнего байта else printnull(0, i); if (bitRead(symbol2, i)) drawFastVLine(61 - i * 4, 64, 4, 1); // биты предпоследнего байта else printnull(32, i); if (bitRead(symbol1, i)) drawFastVLine(94 - i * 4, 64, 4, 1); // биты последнего байта смещены на пиксель вправо else printnull(65, i); // биты последнего байта смещены на пиксель вправо } /*for (byte i = 0; i < 8; i++) { // разложить код символа на биты if (bitRead(symbol2, i) == 1) drawFastVLine(29 + 32 - i * 4, 64, 4, 1); // drawChar(i * 6, 56, 1, 49); else {// drawChar(i * 6, 56, 1, 48); drawPixel(29 + 32 - i * 4, 64, 1); drawFastVLine(28 + 32 - i * 4, 65, 2, 1); // и вывести биты на дисплей drawFastVLine(30 + 32 - i * 4, 65, 2, 1); drawPixel(29 + 32 - i * 4, 67, 1); } } for (byte i = 0; i < 8; i++) { // разложить код символа на биты if (bitRead(symbol1, i) == 1) drawFastVLine(29 + 64 - i * 4, 64, 4, 1); // drawChar(i * 6, 56, 1, 49); else {// drawChar(i * 6, 56, 1, 48); drawPixel(29 + 64 - i * 4, 64, 1); drawFastVLine(28 + 64 - i * 4, 65, 2, 1); // и вывести биты на дисплей drawFastVLine(30 + 64 - i * 4, 65, 2, 1); drawPixel(29 + 64 - i * 4, 67, 1); } }*/ } Update(); } } } Update(); } //********************************************************************************* void LogAnalyzer() { // обрабатываем кнопки if (!digitalRead(KEY_L)) switch (menu) { case 0 : razv--; if (razv == 255) razv = 19; delay(KEY_DELAY); break; // меняем развертку case 1 : trig--; if (trig == 255) trig = 3; delay(KEY_DELAY); break; // меняем trigger case 2 : grOffset -= 10; if (grOffset < 0) grOffset = 0; break; // листаем график в паузе } if (!digitalRead(KEY_R)) switch (menu) { case 0 : razv++; if (razv == 20) razv = 0; delay(KEY_DELAY); break; // меняем развертку case 1 : trig++; if (trig == 4) trig = 0; delay(KEY_DELAY); break; // меняем trigger case 2 : grOffset += 5; if (grOffset >= BUFSIZE - 50) grOffset = BUFSIZE - 50; break; // листаем график в паузе } if (!digitalRead(KEY_OK)) switch (++menu) { //case 2 : grOffset = 0; pause = 1; break; // вход в паузу case 3 : menu = 0; pause = 0; break; // перебор меню delay(KEY_DELAY); } if (!digitalRead(KEY_P)) { menu = 2; grOffset = 0; pause = 1; flag = 0;// вход в паузу } //if (!pause) ReadDig(); // если нет паузы - читаем данные Clear_LCD(); // чистим дисплей if ( menu == 0 ) print(0, 0, 0, razv); // выводим развертку else print(0, 0, 1, razv); // выводим развертку if ( menu == 1 ) print(24, 0, 0, trig); // выводим trigger else print(24, 0, 1, trig); // выводим trigger if (pause) { if (flag == 0) { print(50, 0, 1, "Waiting"); Update(); switch (trig) { case 0 : scanLoadBus(BURST); flag = 1; menu = 2; break; case 1 : scanLoadBus(MASTER_RISE); flag = 1; menu = 2; break; case 2 : scanLoadBus(MASTER_FALL); flag = 1; menu = 2; break; case 3 : scanLoadBus(PATTERN); flag = 1; menu = 2; break; } } //print(8, 0, 1, " Pause "); strcpy_P(buffer, (char*)pgm_read_word(&(string_table[8]))); // необходимые функции и расшифровки, просто скопируйте print(50, 0, 1, (buffer)); // рисуем прокрутку в режиме паузы drawLine( grOffset / 8, 8, grOffset / 8 + 6, 8, 1); // шкала прокрутки drawLine( grOffset / 8, 9, grOffset / 8 + 6, 9, 1); // шкала прокрутки delay(200); } for (byte chan = 0; chan < 4; chan++) // последовательный перебор 4-х каналов { int show_index = StartIndex >> 1; int read_index; print(0, 10, 1, (show_index + grOffset)); drawLine(50, 10, 50, 15, 1); print(54, 10, 1, (grOffset + grOffset + 50)); for (int x = 0; x < 48; x++ ) { read_index = show_index + grOffset + x; if (read_index >= BUFSIZE) read_index = read_index - BUFSIZE; if ((x % 5) == 0) { drawLine(x + x, 60, x + x, 64, 1); // если номер отсчета кратен 10 - рисуем черточку if (((grOffset + x - 100) / 5 % 10) == 0) print (x + x - 2, 60, 1, (grOffset + x) / 50); } //Декомпресиия старшей части if ((adcBuf[read_index] >> 4) & (1 << chan)) // выделяем соответствующий бит текущего канала { drawLine(x + x, chan * 10 + 20, x + x, chan * 10 + 24, 1); //если высокий уровень } else { drawPixel(x + x, chan * 10 + 24, 1); // если низкий уровень } //Декомпресиия младшей части if (adcBuf[read_index] & (1 << chan)) // выделяем соответствующий бит текущего канала { drawLine(x + x + 1, chan * 10 + 20, x + x + 1, chan * 10 + 24, 1); //если высокий уровень } else { drawPixel(x + x + 1, chan * 10 + 24, 1); // если низкий уровень } } // end y loop } Update(); } //============================================ // Функция расчета номера замера с которого начинается вывод данных включая предисторию // иными словами, от замера сработки тригера отнимаем (с учетом перекрутки буффера) величину предистории //============================================ int calc_StartIndex() { //=========== расчет точки останова чтобы не затереть начало сработки триггера if (cur_index < history) //если значение тек. индекса меньше, чем размер истории { return ((BUFSIZE + BUFSIZE) + cur_index - history); //считаем таким образом } else { return (cur_index - history); // ну и если больше, то просто отнимаем }//=========== End расчет точки останова чтобы не затереть начало сработки триггера } //=========================================================== // Процедура записи данных данных в буфер // тут происходит запись сжатых данных и увеличение текущего индекса замера // запись будет происходить при нечетном значении индекса (т.е., считаны уже два значения) void rec_data(byte cur_data) { if ((cur_index & 1)) //если текущее значение индекса нечетное (нечетные числа в двоичном виде всегда заканчиваются на 1) { adcBuf[cur_index >> 1] = ((prev_data << 4) | cur_data); // пишим обьеденное число так сказать КОМПРЕССИЯ :) } prev_data = cur_data; //запоминаем текущее состояние шины cur_index++; //увеличиваем номер замера if (cur_index == (BUFSIZE + BUFSIZE)) cur_index = 0; //если достигли конца буфера - сброс и все сначала } //end rec_data //============================================ // Процедура сканирования шины и отлов сработки триггеров // При сканировании шины будем учитывать тип триггера: typeTriggerEvent // Чтобы считать значения младших четырех бит (PORTC0, PORTC1, PORTC2, PORTC3) // нужно делать так: my_var1 = PINC & b00001111; // такой операцией мы обнулим старшие 4 бит и получим ТОЛЬКО младшие 4-ре //============================================ void scan_bus(byte typeTriggerEvent) { while (!trigger_event) { // ПЕРВЫМ делом нужно считать данные с шины, а уже потом будем разбираться со всякими сверками и расчетами byte cur_data = (PINC & B00001111); //сразу же считываем состояние пинов порта // ниже отладочная пришлепка для примерной оценки скорости оцифровки // по частоте переключения пина будем судить о скорости // данные считаны, теперь проверяем есть ли условия сработки триггера и если ДА, запоминаем номер замера (0-1024) switch (typeTriggerEvent) //ветвимся в зависимости от режима триггера { // BURST Mode Любое изменение на любом канале case (BURST): if (cur_data != prev_data) { trigger_event = true; //ставим признак сработки триггера StartIndex = calc_StartIndex(); // расчет номера замера с которого будем делать вывод } break; //--------------------------------- // master channel RISE (переход из 0 в 1) case (MASTER_RISE): if (~prev_data & cur_data & 1) { trigger_event = true; //ставим признак сработки триггера StartIndex = calc_StartIndex(); // расчет номера замера с которого будем делать вывод } break; //--------------------------------- // master chanel FALL (переход из 1 в 0) case (MASTER_FALL): if (prev_data & ~cur_data & 1) { trigger_event = true; //ставим признак сработки триггера StartIndex = calc_StartIndex(); // расчет номера замера с которого будем делать вывод } break; //--------------------------------- // PATTERN (определенное состояние шины) case (PATTERN): //if ((cur_data & pattern_mask) == pattern_value) // если проверка на совпадение условий прошла if ((cur_data & 7) == 5) // если проверка на совпадение условий прошла { trigger_event = true; //ставим признак сработки триггера StartIndex = calc_StartIndex(); // расчет номера замера с которого будем делать вывод } break; } //End switch (typeTriggerEvent) rec_data(cur_data); //запись данных в буффер if ((cur_index == 0) && Serial.available()) break; //единственный способ прервать - при нулевом индексе что-то появилось в ком-порту delayMicroseconds(razv * 4); } //end while }// end load data //====== read_bus ============ // тупо пишем состояние каналов void read_bus() { prevMillis = millis(); //запоминаем время начала записи истории while (cur_index != StartIndex) { rec_data(PINC & B00001111); //запись данных в буффер delayMicroseconds(razv * 4); } //end while curMillis = millis(); //время конца записи истории } //================== // инициализация перед замерами //Обнуляем буффер, сбрасываем индексы и запоминаем состояние шины void init_logic() { for (int i = 0; i <= BUFSIZE; i++) //в цикле затиранием рабочий массив { adcBuf[i] = 0; } cur_index = 0; // сбрасываем счетчик замеров StartIndex = 0; // сбрасываем положение начала данных для вывода time_disc = 0; // сбрасываем значения интервала одной выборки trigger_event = false; //сбрасываем признак сработки триггера prev_data = (PINC & B00001111); //сформируем пред. замер состояние пинов порта } // end logic init //======================================================== // процедура отображения полезной (и не очень) информации void show_info(byte typeTriggerEvent) { // немного расчетов "для красоты": для считывания ((BUFSIZE+BUFSIZE)-history) количества замеров требуется // сколько-то милисекунд (или, если умножить на 1000 - микросекунд) посчитаем, сколько микросекунд уходит на одну выборку (естественно, ОЧЕНЬ-ОЧЕНЬ ПРИМЕРНО) time_disc = ((curMillis - prevMillis) * 1000) / (((BUFSIZE + BUFSIZE) - history)); //время выборки одного замера Serial.println(F("---------------------------------------------------------")); Serial.print(F("Record size=")); Serial.print((BUFSIZE + BUFSIZE) - history, DEC); Serial.print(F(" Pre-history size=")); Serial.println(history, DEC); Serial.print(F("Current Trigger: ")); switch (typeTriggerEvent) { case (MASTER_RISE): Serial.println(F("Master (Ch0) RISE (0->1)")); break; case (MASTER_FALL): Serial.println(F("Master (Ch0) FALL (1->0)")); break; case (BURST): Serial.println(F("Change on any channel")); break; case (PATTERN): Serial.print(F("Bus status")); Serial.print(F(" MASK / VALUE =")); Serial.print(pattern_mask, HEX); Serial.print(F(" / ")); Serial.println(pattern_value, HEX); break; } //end switch //Serial.print("Start/Stop =");Serial.print(prevMillis);Serial.print(" / "); Serial.print(curMillis); //Serial.print("[Ind Start = ");Serial.print(StartIndex);Serial.print("] "); Serial.print(F("Time: 1 div = ")); Serial.print(time_disc); Serial.println(F(" (uSec)")); Serial.println(F("******************************************")); } //============================== // Процедура орисовки результатов в виде псевдографика // процедура достаточно медленная, но буфер к этому моменту заполнен, так что скорость тут УЖЕ не важна //============================== void show_graph() { for (byte chan = 0; chan < 4; chan++) // последовательный перебор 4-х каналов { Serial.print(F("Ch N")); Serial.print(chan); int show_index = StartIndex >> 1; Serial.print(F("\t")); for (int y = 0; y < BUFSIZE; y++ ) { if (show_index == BUFSIZE) show_index = 0; //Декомпресиия старшей части if ((adcBuf[show_index] >> 4) & (1 << chan)) // выделяем соответствующий бит текущего канала { Serial.print(F("-")); //если высокий уровень } else { Serial.print(F("_")); // если низкий уровень } //Декомпресиия младшей части if (adcBuf[show_index] & (1 << chan)) // выделяем соответствующий бит текущего канала { Serial.print(F("-")); //если высокий уровень } else { Serial.print(F("_")); // если низкий уровень } show_index++; }// end y loop Serial.println(); } //end loop chan // =========================================== // для красоты - типа вывод шкалы разметки :) // =========================================== Serial.print(F("\t")); //код TAB для ровности вывода for (int x = 0; x < (BUFSIZE + BUFSIZE); x++) { if (x == history) Serial.print(F("^")); //обозначим начало отсчета if ((x % 10) == 0) Serial.print(F("|")); // если номер отсчета кратен 10 - рисуем черточку if ((x % 10 != 0) && (x != history)) Serial.print(F(".")); // иначе рисуем точку } Serial.println(F(".")); //завершающая точка и перевод строки // рисуем "типа" разметку Serial.print(F("\t"));//код TAB для ровности вывода for (int x = 0; x < (BUFSIZE + BUFSIZE); x++) { if ((x % 10) == 0) { Serial.print(x / 10); if (x < 100) Serial.print(F(" ")); //чтобы не плыли значения относительно шкалы, в зависимости от разрядности тек. замера else if ((x >= 100) && (x < 1000)) Serial.print(F(" ")); // для случая ЗАМЕР - два знака else if ((x >= 1000) && (x < 10000)) Serial.print(F(" ")); // для случая ЗАМЕР - три знака } } Serial.println(); }//end show_graph //=================================================== //фантик обертка сканирования шины (scan_bus+read_bus) //1 фаза - ждем триггер или отмену пользователем //2 фаза - заполнение буфера данными void scanLoadBus(byte typeTriggerEvent) { Serial.print(F("Waiting......")); //digitalWrite(TriggerPin, LOW); // светрдиод TRG выключаем init_logic(); //инициализируем буфер и переменные scan_bus(typeTriggerEvent); if (trigger_event) //если триггер сработал { read_bus(); // пишем историю в буфер //digitalWrite(TriggerPin,HIGH); // светoдиод TRG включаем Serial.println(F("Ok!")); show_info(typeTriggerEvent); //выводим информацию show_graph(); //и следом выводим график } else { Serial.println(F("User break")); //а если мы вернулись без признака сработки триггера - значит ожидание было прервано пользователем Serial.flush(); //очищаем буфер } } //end scanLoadBussmokok, у меня сейчас другие приоритеты. Через месяц придут платы для пультоскопа от узкоглазых товарищей, тогда займусь.
Привет всем.У меня почему то напряжение АКБ всегда показывает 5в. Питаю от аккумулятора 18650.Собрал на дисплее 5110 и арудино нано.Напряжение от АКБ подаю через 10ком на пин А5. Если убираю резистор величина начинает прыгать.Пробовал на другие пины ,то же самое. Ещё при питании от usb при замере 1,5 вольтовой батарейки показывает 1,7 вольт. Как мне его настроить?
Sergei H. - все просто, автор скетча рассчитывал на питание 5 вольт, и прописал в качестве опорного VCC, поэтому замер собственного питания всегда будет показывать 5 вольт.
При питании от USB от компьютера приходит 5 вольт, но часть напряжения теряется на встроенном стабилизаторе, соответственно опорное получается уже не 5 вольт, а 4,7...4,5 - соответственно при пересчете измерения АЦП получается завышение показаний.
Простого решения нет - купи плату повышайки и подайте на плату 7 вольт и будет вам счастье.
То есть,если я подаю питание на ардуино нано 9вольт на VIN. К VIN резистор 10ком и на A5. То всё равно будет показывать 5вольт.
А как изменить скетч ,чтобы реально напряжение батареи выводилось?
Ещё один резистор на 10к от А5 на землю.
Подключил резистор 10к от A5 на землю ,показывает на 5 вольт меньше,чем на батарее.
https://www.youtube.com/watch?v=UpJxn_kCZBo&list=PLlbB54obuHAlrw5DtCUZjFGeMNmLTG-JU&index=8
Здесь у автора напряжение измеряется.Как я понял литиевый аккумулятор. на видео 3,87 вольта.
float VCC=5.00; //напряжение питания, меряем мультиметром
smokok, у меня сейчас другие приоритеты. Через месяц придут платы для пультоскопа от узкоглазых товарищей, тогда займусь.
VIN-10К-A5-10К-GND
Где то я реализовывал функцию, которая возвращает напряжения питания ардуинки, чтоб ничего не мерять тестером и не вычислять.
А так да - на диоде подает часть напряжения питания (где то 0.3 вольта). Линейный стабилизатор при питании от USB не участвует. Он завязан на ногу VIN (RAW)....
а может кто знает как уводить в сон и выводить из сна дисплей на ssd 1306 с библиотекой adafruit?
Дак гасить все пиксели:)
А может кто знает, на какой странице моя какая нибудь версия под ssd1306?
А как на этом форуме картинки вставлять? А то пришли макетки (платки с дырками под пайку) - паял тут три дня (да, я долго паяю). Дисплеи теперь есть 5110 и 1306 в изобилии...
Хотел с Вами поделиться результатом.....
P.S. правда нашел тут какой то свой скетч - и диву даюсь, как я так мог написать "херово". датировано 17-ым годом....
P.S.2. Теперь не надо хоть "таскать" эти здоровенные макетки для втыкания проводов.... все умещается меньше чем в пачке сигарет....
Дак гасить все пиксели:)
А может кто знает, на какой странице моя какая нибудь версия под ssd1306?
А как на этом форуме картинки вставлять? А то пришли макетки (платки с дырками под пайку) - паял тут три дня (да, я долго паяю). Дисплеи теперь есть 5110 и 1306 в изобилии...
Хотел с Вами поделиться результатом.....
P.S. правда нашел тут какой то свой скетч - и диву даюсь, как я так мог написать "херово". датировано 17-ым годом....
P.S.2. Теперь не надо хоть "таскать" эти здоровенные макетки для втыкания проводов.... все умещается меньше чем в пачке сигарет....
нужно нажать на значек изображение, там предложит загрузить на сервер фото, и потом уже с сервера вы добавляете фото сюда
нужно нажать на значек изображение, там предложит загрузить на сервер фото, и потом уже с сервера вы добавляете фото сюда
Uploaded fail пишет. Или что то типо того...
За то каким именно путем приходит питание при запитке от USB не особо вникал, но у меня оно ВСЕГДА было пониженным 4,5...4,7В если мерить на лапе конторолера.
Если замер напряжения батареи требуется только при старте можно задействовать внутренний ИОН(источник опорного напряжения), это стандартная функция http://arduino.ru/Reference/AnalogReference
Но тут есть два подводных камня:
1. Нужен делитель напряжения, для однобаночного литевого акума 10 кОм на + акума, второй вывод резистора на аналоговый вход, на тот же анналоговый вход резистор 2 кОм - второй вывод резистора на землю.
2. Внутренний ИОН микроконторолера допускает разброс по напряжению, если не ошибаюсь +/- 0,1 вольт, нужно будет в формулу пересчета загонять поправочный коэфициент.
Да тут по сути нахер ничего не надо, че тупим то. Читаем, считаем и вуаля!
Я приводил пример функции, где ардуинка меряет свое напряжение питания, оно же будет и опорное.
P.S. На этих дерь/шовых китайских дисплейчиках мою анимацию главного меню практически не видно..... На оригинальном от нокии 3310 все гараздо контрастнее и четче... Думаю может отказаться от этой анимации? Как считаете, уважаемые форумчане?
гасить все пиксели то понятно. а есть команды отправляющие спать сам контроллер ssd1306
только как эти команды в функциях adafruit передавать дисплею.?
чейчас вот пытаюсь убрать тумблер по питанию. что бы кнопкой включался любой и выключался сам через 10 минут бездействия.
делаю для работы автопробник с режимом осциллографа.
кстати автоомасштабирование пытаюсь прикрутить и пока не успешно. надо поковырять чьи то исходники. по моему кто то автомасштаб делал
гасить все пиксели то понятно. а есть команды отправляющие спать сам контроллер ssd1306
только как эти команды в функциях adafruit передавать дисплею.?
чейчас вот пытаюсь убрать тумблер по питанию. что бы кнопкой включался любой и выключался сам через 10 минут бездействия.
делаю для работы автопробник с режимом осциллографа.
кстати автоомасштабирование пытаюсь прикрутить и пока не успешно. надо поковырять чьи то исходники. по моему кто то автомасштаб делал
... Через месяц придут платы для пультоскопа от узкоглазых товарищей...
Развёл плату. Заказал изготовление в JLC PCB. Два проекта (по 5 и по 10 плат) с доставкой обошлись в 22 у. е. Получу через пару недель, спаяю, выложу фото. Под дисплей 1202.
Где то я реализовывал функцию, которая возвращает напряжения питания ардуинки, чтоб ничего не мерять тестером и не вычислять.
Всё равно нужно мерить, вычислять, и вводить поправочный коэффициент, причём зависящий от варианта запитки контроллера. Если показания правильны в диапазоне 3,4 ... 4,2 вольт (питание от литиевого аккумулятора без повышайки), то при том же коэффициенте и питании 5 вольт будет неслабо врать. И наоборот. Надеюсь, смог выразить мысль понятно.
мою анимацию главного меню практически не видно... Думаю может отказаться от этой анимации? Как считаете, уважаемые форумчане?
Я отказался. Баловство это. Главное- удобство пользования. И ничего лишнего в интерфейсе. Над каждой буквой-цифрой думал.
кстати автоомасштабирование пытаюсь прикрутить и пока не успешно. надо поковырять чьи то исходники. по моему кто то автомасштаб делал
Писал где то такой код, только не найти его. Или искать долго - тут на форуме:) Много очень страниц.... И после автомасштаба дисплейчик 1306 накернился (был один).... И я плюнул на это все:(
Только у меня
#define Vref11 1.212, иначе врёт, о чём я писал выше.
По дисплеям: https://www.google.com/search?q=%D0%B4%D0%B8%D1%81%D0%BF%D0%BB%D0%B5%D0%B9+nokia+1202+%D0%BA%D1%83%D0%BF%D0%B8%D1%82%D1%8C&ie=utf-8&oe=utf-8&client=firefox-b-e
Только там нужно паять с шагом 0,6 мм.
Замер напряжения питания arduino без использования дополнительно обвязки и без доп ног.
http://arduino.ru/forum/apparatnye-voprosy/kak-izmerit-arduino-mini-napr...
Удалил дубль.....
Удалил
Замер напряжения питания arduino без использования дополнительно обвязки и без доп ног. . . . . . . . . . . . .
В скетчах Электроника это давно реализовано. Но это возможно только при питании напрямую от батареи. Если применён преобразователь, то без использования аналогового входа напряжение батареи (а оно не равно напряжению питания контроллера) замерить невозможно.
...удалил дубль....
Ищи "magnify" ( автоомасштабирование) только не авто. Есть авто опорное 5.0, 1.1, 0.2
Пост 3756 (клац)
Ищи "magnify" ( автоомасштабирование) только не авто. Есть авто опорное 5.0, 1.1, 0.2
Я чет наверное туплю, но откуда 0.2 взялось?
И еще - если пин 13 делать свободным (а я хочу, чтоб на нем светодиод висел отладочный), то не предоставляется возможности резвести кнопки и генераторы.... что думаете, товарищи?!?! аналоговые кнопки не хочу.....
А дисплеев этих 1202 - у меня, как оказалось, есть несколько в наличии... яж сотики чиню больше 15-ти лет...
P.S. И кстати в голую атмегу328 в DIP корпусе влезает больше прошивки, чем в Arduino Pro.... - разные bootloader`ы...
И еще - если пин 13 делать свободным (а я хочу, чтоб на нем светодиод висел отладочный), то не предоставляется возможности резвести кнопки и генераторы.... что думаете, товарищи?!?! аналоговые кнопки не хочу.....
Вам выводов не хватает? Озадачили... У меня (и, насколько помню, еще у нескольких товарищей) в одном приборе совмещен пультоскоп со всеми оригинальными допами (генераторы, терминал), транзистор-тестер и логический анализатор, на отдельном пине сидит измерение напряжения аккумулятора, и еще один пин остался свободный. Как у вас-то не влезает?
А можно пример кода со всем этим хозяйством???
Код я здесь выкладывал. Может, не самую последнюю версию, но распайка с тех пор у меня не менялась.
Просмотрел почти всю тему. Фотку твоего чуда видел, а вот кода не нашел. Поделись, пожалуйста, своей версией скетча, если, конечно, это возможно. diksen выложил свою "альфа" версию и больше на форуме я его не пока не видел. Он обещал свою типа "бета" , но пока увы... Его "альфа" у меня работает, но терминала нет, меню настроек тоже нет... А я в программировании "0" без палочки...
Компактный аппаратик.
Спасибо.
Спасибо.
Не разберусь как фото выложить...
Очень интересно посмотреть на готовый аппарат. Какая коробочка. Всегда проблема с корпусом.
Не пойму про фото.... У меня нет картинок
Аналогично
smokok,
а не подскажете как мне можно подсчитать период в микросекундаХ?
очень не хватает.
копаюсь в вашем коде под олед дисплей. есть вещи, которые я не догоняю совсем.
из всего богатства в прошивке мне нужен осцилл но с авторазверткой и автомасштабом.
если уберу генератор то почему то осцилл прерывается постоянно примерно раз в секунду.
и можно ли с вами как то связаться или телеграмм или вайбер или еще как?
удалил дубль
https://yadi.sk/d/8KPXSivG1JWY8w набросок на голой атмеге 328 c тфт 2.4. Да и кто-нибудь может выложить hex стандартной версии, а то у меня толи библиотек не хватает, в общем не компилируется, заранее спасибо!
Доброго времени суток! В общем сваял я пробный образец но постигла меня неудача, файлы hex и eep у меня откомпилировались ,прошились в контроллер по usbasp шил через синапрог ,но как говорится "белый экран" наблюдаю только подсветку.Ладно подожду ардуинки и по проторённой тропе! да кстати дисплей попался вот такой 2.4" TFT ILI9341 240X320. соответственно и скетч комипилировал под него.
Привет progrik! Извини за назойливость ,но не мог бы показать свой рабочий скетч,а лучше hex-файл,может я криворукий, но мантра "би хеппи" не помогает!!!!